[
  {
    "path": ".gitignore",
    "content": "/build\n"
  },
  {
    "path": "AUTHORS",
    "content": "(c) Copyright 2017-2025  DirectFB2 Open Source Project (fork of DirectFB)\n(c) Copyright 2012-2016  DirectFB integrated media GmbH\n(c) Copyright 2001-2013  The world wide DirectFB Open Source Community (directfb.org)\n(c) Copyright 2000-2004  Convergence (integrated media) GmbH\n\nDirectFB was originally written by Denis Oliver Kropp,\n                                   Andreas Shimokawa,\n                                   Marek Pikarski,\n                                   Sven Neumann,\n                                   Ville Syrjala and\n                                   Claudio Ciccani.\n\nDirectFB2 is the work of Nicolas Caramelli whose goal is to preserve and maintain DirectFB.\n\nContributors are listed, but if you think you're missing out on this list, feel free to request to be added.\n\nDenis Oliver Kropp\nAndreas Shimokawa\nMarek Pikarski\nSven Neumann\nVille Syrjala\nClaudio Ciccani\nMichael Natterer\nHolger Waechtler\nJohannes Stezenbach\nJiri Svoboda\nHallvar Helleseth\nSebastian Klemke\nAndreas Kotes\nAntonino Daplas\nAndreas Oberritter\nMartin Mueller\nSebastian Ley\nMaurizio Monge\nAndreas Robinson\nMichael Hunold\nTom Bridgwater\nStefan Lucke\nMike Emmel\nIvan Daniluk\nMark Salter\nMarcel Siegert\nMarko Makela\nMark Adams\nDamian Kowalewski\nJakub Bogusz\nAndy Stewart\nNikita Egorov\nJeff Bailey\nBen Combee\nDaniel Laird\nGuillem Jover\nAttilio Fiandrotti\nVaclav Slavik\nPhil Endecott\nKamijo Takashi\nMike Crowe\nKieran Bingham\nNiels Roest\nMandy Wu\nKeith Mok\nGuillaume Gardet\nYoung Hoon\nTimothy Strelchun\nAndre Draszik\nSorin Otescu\nJacques Luder\nStanislav Bezzubtsev\nMike Frysinger\nIlyes Gouta\nTim Ross\nRussell Dawson\nHaithem Rahmani\nHolger Freyther\nRob McConnell\nDaniel Schaal\nBryce Poole\nMike Nelis\nTarik Sekmen\nKazunori Kobayashi\nChris Tomlinson\nTakanari Hayama\nKui Zheng\nDaniel Palmer\nShengwen Cheng\nStephen Bird\nNicolas Caramelli\n"
  },
  {
    "path": "COPYING",
    "content": "                  GNU LESSER GENERAL PUBLIC LICENSE\n                       Version 2.1, February 1999\n\n Copyright (C) 1991, 1999 Free Software Foundation, Inc.\n 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n[This is the first released version of the Lesser GPL.  It also counts\n as the successor of the GNU Library Public License, version 2, hence\n the version number 2.1.]\n\n                            Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicenses are intended to guarantee your freedom to share and change\nfree software--to make sure the software is free for all its users.\n\n  This license, the Lesser General Public License, applies to some\nspecially designated software packages--typically libraries--of the\nFree Software Foundation and other authors who decide to use it.  You\ncan use it too, but we suggest you first think carefully about whether\nthis license or the ordinary General Public License is the better\nstrategy to use in any particular case, based on the explanations below.\n\n  When we speak of free software, we are referring to freedom of use,\nnot price.  Our General Public Licenses are designed to make sure that\nyou have the freedom to distribute copies of free software (and charge\nfor this service if you wish); that you receive source code or can get\nit if you want it; that you can change the software and use pieces of\nit in new free programs; and that you are informed that you can do\nthese things.\n\n  To protect your rights, we need to make restrictions that forbid\ndistributors to deny you these rights or to ask you to surrender these\nrights.  These restrictions translate to certain responsibilities for\nyou if you distribute copies of the library or if you modify it.\n\n  For example, if you distribute copies of the library, whether gratis\nor for a fee, you must give the recipients all the rights that we gave\nyou.  You must make sure that they, too, receive or can get the source\ncode.  If you link other code with the library, you must provide\ncomplete object files to the recipients, so that they can relink them\nwith the library after making changes to the library and recompiling\nit.  And you must show them these terms so they know their rights.\n\n  We protect your rights with a two-step method: (1) we copyright the\nlibrary, and (2) we offer you this license, which gives you legal\npermission to copy, distribute and/or modify the library.\n\n  To protect each distributor, we want to make it very clear that\nthere is no warranty for the free library.  Also, if the library is\nmodified by someone else and passed on, the recipients should know\nthat what they have is not the original version, so that the original\nauthor's reputation will not be affected by problems that might be\nintroduced by others.\n\f\n  Finally, software patents pose a constant threat to the existence of\nany free program.  We wish to make sure that a company cannot\neffectively restrict the users of a free program by obtaining a\nrestrictive license from a patent holder.  Therefore, we insist that\nany patent license obtained for a version of the library must be\nconsistent with the full freedom of use specified in this license.\n\n  Most GNU software, including some libraries, is covered by the\nordinary GNU General Public License.  This license, the GNU Lesser\nGeneral Public License, applies to certain designated libraries, and\nis quite different from the ordinary General Public License.  We use\nthis license for certain libraries in order to permit linking those\nlibraries into non-free programs.\n\n  When a program is linked with a library, whether statically or using\na shared library, the combination of the two is legally speaking a\ncombined work, a derivative of the original library.  The ordinary\nGeneral Public License therefore permits such linking only if the\nentire combination fits its criteria of freedom.  The Lesser General\nPublic License permits more lax criteria for linking other code with\nthe library.\n\n  We call this license the \"Lesser\" General Public License because it\ndoes Less to protect the user's freedom than the ordinary General\nPublic License.  It also provides other free software developers Less\nof an advantage over competing non-free programs.  These disadvantages\nare the reason we use the ordinary General Public License for many\nlibraries.  However, the Lesser license provides advantages in certain\nspecial circumstances.\n\n  For example, on rare occasions, there may be a special need to\nencourage the widest possible use of a certain library, so that it becomes\na de-facto standard.  To achieve this, non-free programs must be\nallowed to use the library.  A more frequent case is that a free\nlibrary does the same job as widely used non-free libraries.  In this\ncase, there is little to gain by limiting the free library to free\nsoftware only, so we use the Lesser General Public License.\n\n  In other cases, permission to use a particular library in non-free\nprograms enables a greater number of people to use a large body of\nfree software.  For example, permission to use the GNU C Library in\nnon-free programs enables many more people to use the whole GNU\noperating system, as well as its variant, the GNU/Linux operating\nsystem.\n\n  Although the Lesser General Public License is Less protective of the\nusers' freedom, it does ensure that the user of a program that is\nlinked with the Library has the freedom and the wherewithal to run\nthat program using a modified version of the Library.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.  Pay close attention to the difference between a\n\"work based on the library\" and a \"work that uses the library\".  The\nformer contains code derived from the library, whereas the latter must\nbe combined with the library in order to run.\n\f\n                  GNU LESSER GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License Agreement applies to any software library or other\nprogram which contains a notice placed by the copyright holder or\nother authorized party saying it may be distributed under the terms of\nthis Lesser General Public License (also called \"this License\").\nEach licensee is addressed as \"you\".\n\n  A \"library\" means a collection of software functions and/or data\nprepared so as to be conveniently linked with application programs\n(which use some of those functions and data) to form executables.\n\n  The \"Library\", below, refers to any such software library or work\nwhich has been distributed under these terms.  A \"work based on the\nLibrary\" means either the Library or any derivative work under\ncopyright law: that is to say, a work containing the Library or a\nportion of it, either verbatim or with modifications and/or translated\nstraightforwardly into another language.  (Hereinafter, translation is\nincluded without limitation in the term \"modification\".)\n\n  \"Source code\" for a work means the preferred form of the work for\nmaking modifications to it.  For a library, complete source code means\nall the source code for all modules it contains, plus any associated\ninterface definition files, plus the scripts used to control compilation\nand installation of the library.\n\n  Activities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning a program using the Library is not restricted, and output from\nsuch a program is covered only if its contents constitute a work based\non the Library (independent of the use of the Library in a tool for\nwriting it).  Whether that is true depends on what the Library does\nand what the program that uses the Library does.\n\n  1. You may copy and distribute verbatim copies of the Library's\ncomplete source code as you receive it, in any medium, provided that\nyou conspicuously and appropriately publish on each copy an\nappropriate copyright notice and disclaimer of warranty; keep intact\nall the notices that refer to this License and to the absence of any\nwarranty; and distribute a copy of this License along with the\nLibrary.\n\n  You may charge a fee for the physical act of transferring a copy,\nand you may at your option offer warranty protection in exchange for a\nfee.\n\f\n  2. You may modify your copy or copies of the Library or any portion\nof it, thus forming a work based on the Library, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) The modified work must itself be a software library.\n\n    b) You must cause the files modified to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    c) You must cause the whole of the work to be licensed at no\n    charge to all third parties under the terms of this License.\n\n    d) If a facility in the modified Library refers to a function or a\n    table of data to be supplied by an application program that uses\n    the facility, other than as an argument passed when the facility\n    is invoked, then you must make a good faith effort to ensure that,\n    in the event an application does not supply such function or\n    table, the facility still operates, and performs whatever part of\n    its purpose remains meaningful.\n\n    (For example, a function in a library to compute square roots has\n    a purpose that is entirely well-defined independent of the\n    application.  Therefore, Subsection 2d requires that any\n    application-supplied function or table used by this function must\n    be optional: if the application does not supply it, the square\n    root function must still compute square roots.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Library,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Library, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote\nit.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Library.\n\nIn addition, mere aggregation of another work not based on the Library\nwith the Library (or with a work based on the Library) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may opt to apply the terms of the ordinary GNU General Public\nLicense instead of this License to a given copy of the Library.  To do\nthis, you must alter all the notices that refer to this License, so\nthat they refer to the ordinary GNU General Public License, version 2,\ninstead of to this License.  (If a newer version than version 2 of the\nordinary GNU General Public License has appeared, then you can specify\nthat version instead if you wish.)  Do not make any other change in\nthese notices.\n\f\n  Once this change is made in a given copy, it is irreversible for\nthat copy, so the ordinary GNU General Public License applies to all\nsubsequent copies and derivative works made from that copy.\n\n  This option is useful when you wish to copy part of the code of\nthe Library into a program that is not a library.\n\n  4. You may copy and distribute the Library (or a portion or\nderivative of it, under Section 2) in object code or executable form\nunder the terms of Sections 1 and 2 above provided that you accompany\nit with the complete corresponding machine-readable source code, which\nmust be distributed under the terms of Sections 1 and 2 above on a\nmedium customarily used for software interchange.\n\n  If distribution of object code is made by offering access to copy\nfrom a designated place, then offering equivalent access to copy the\nsource code from the same place satisfies the requirement to\ndistribute the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  5. A program that contains no derivative of any portion of the\nLibrary, but is designed to work with the Library by being compiled or\nlinked with it, is called a \"work that uses the Library\".  Such a\nwork, in isolation, is not a derivative work of the Library, and\ntherefore falls outside the scope of this License.\n\n  However, linking a \"work that uses the Library\" with the Library\ncreates an executable that is a derivative of the Library (because it\ncontains portions of the Library), rather than a \"work that uses the\nlibrary\".  The executable is therefore covered by this License.\nSection 6 states terms for distribution of such executables.\n\n  When a \"work that uses the Library\" uses material from a header file\nthat is part of the Library, the object code for the work may be a\nderivative work of the Library even though the source code is not.\nWhether this is true is especially significant if the work can be\nlinked without the Library, or if the work is itself a library.  The\nthreshold for this to be true is not precisely defined by law.\n\n  If such an object file uses only numerical parameters, data\nstructure layouts and accessors, and small macros and small inline\nfunctions (ten lines or less in length), then the use of the object\nfile is unrestricted, regardless of whether it is legally a derivative\nwork.  (Executables containing this object code plus portions of the\nLibrary will still fall under Section 6.)\n\n  Otherwise, if the work is a derivative of the Library, you may\ndistribute the object code for the work under the terms of Section 6.\nAny executables containing that work also fall under Section 6,\nwhether or not they are linked directly with the Library itself.\n\f\n  6. As an exception to the Sections above, you may also combine or\nlink a \"work that uses the Library\" with the Library to produce a\nwork containing portions of the Library, and distribute that work\nunder terms of your choice, provided that the terms permit\nmodification of the work for the customer's own use and reverse\nengineering for debugging such modifications.\n\n  You must give prominent notice with each copy of the work that the\nLibrary is used in it and that the Library and its use are covered by\nthis License.  You must supply a copy of this License.  If the work\nduring execution displays copyright notices, you must include the\ncopyright notice for the Library among them, as well as a reference\ndirecting the user to the copy of this License.  Also, you must do one\nof these things:\n\n    a) Accompany the work with the complete corresponding\n    machine-readable source code for the Library including whatever\n    changes were used in the work (which must be distributed under\n    Sections 1 and 2 above); and, if the work is an executable linked\n    with the Library, with the complete machine-readable \"work that\n    uses the Library\", as object code and/or source code, so that the\n    user can modify the Library and then relink to produce a modified\n    executable containing the modified Library.  (It is understood\n    that the user who changes the contents of definitions files in the\n    Library will not necessarily be able to recompile the application\n    to use the modified definitions.)\n\n    b) Use a suitable shared library mechanism for linking with the\n    Library.  A suitable mechanism is one that (1) uses at run time a\n    copy of the library already present on the user's computer system,\n    rather than copying library functions into the executable, and (2)\n    will operate properly with a modified version of the library, if\n    the user installs one, as long as the modified version is\n    interface-compatible with the version that the work was made with.\n\n    c) Accompany the work with a written offer, valid for at\n    least three years, to give the same user the materials\n    specified in Subsection 6a, above, for a charge no more\n    than the cost of performing this distribution.\n\n    d) If distribution of the work is made by offering access to copy\n    from a designated place, offer equivalent access to copy the above\n    specified materials from the same place.\n\n    e) Verify that the user has already received a copy of these\n    materials or that you have already sent this user a copy.\n\n  For an executable, the required form of the \"work that uses the\nLibrary\" must include any data and utility programs needed for\nreproducing the executable from it.  However, as a special exception,\nthe materials to be distributed need not include anything that is\nnormally distributed (in either source or binary form) with the major\ncomponents (compiler, kernel, and so on) of the operating system on\nwhich the executable runs, unless that component itself accompanies\nthe executable.\n\n  It may happen that this requirement contradicts the license\nrestrictions of other proprietary libraries that do not normally\naccompany the operating system.  Such a contradiction means you cannot\nuse both them and the Library together in an executable that you\ndistribute.\n\f\n  7. You may place library facilities that are a work based on the\nLibrary side-by-side in a single library together with other library\nfacilities not covered by this License, and distribute such a combined\nlibrary, provided that the separate distribution of the work based on\nthe Library and of the other library facilities is otherwise\npermitted, and provided that you do these two things:\n\n    a) Accompany the combined library with a copy of the same work\n    based on the Library, uncombined with any other library\n    facilities.  This must be distributed under the terms of the\n    Sections above.\n\n    b) Give prominent notice with the combined library of the fact\n    that part of it is a work based on the Library, and explaining\n    where to find the accompanying uncombined form of the same work.\n\n  8. You may not copy, modify, sublicense, link with, or distribute\nthe Library except as expressly provided under this License.  Any\nattempt otherwise to copy, modify, sublicense, link with, or\ndistribute the Library is void, and will automatically terminate your\nrights under this License.  However, parties who have received copies,\nor rights, from you under this License will not have their licenses\nterminated so long as such parties remain in full compliance.\n\n  9. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Library or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Library (or any work based on the\nLibrary), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Library or works based on it.\n\n  10. Each time you redistribute the Library (or any work based on the\nLibrary), the recipient automatically receives a license from the\noriginal licensor to copy, distribute, link with or modify the Library\nsubject to these terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties with\nthis License.\n\f\n  11. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Library at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Library by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Library.\n\nIf any portion of this section is held invalid or unenforceable under any\nparticular circumstance, the balance of the section is intended to apply,\nand the section as a whole is intended to apply in other circumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  12. If the distribution and/or use of the Library is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Library under this License may add\nan explicit geographical distribution limitation excluding those countries,\nso that distribution is permitted only in or among countries not thus\nexcluded.  In such case, this License incorporates the limitation as if\nwritten in the body of this License.\n\n  13. The Free Software Foundation may publish revised and/or new\nversions of the Lesser General Public License from time to time.\nSuch new versions will be similar in spirit to the present version,\nbut may differ in detail to address new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Library\nspecifies a version number of this License which applies to it and\n\"any later version\", you have the option of following the terms and\nconditions either of that version or of any later version published by\nthe Free Software Foundation.  If the Library does not specify a\nlicense version number, you may choose any version ever published by\nthe Free Software Foundation.\n\f\n  14. If you wish to incorporate parts of the Library into other free\nprograms whose distribution conditions are incompatible with these,\nwrite to the author to ask for permission.  For software which is\ncopyrighted by the Free Software Foundation, write to the Free\nSoftware Foundation; we sometimes make exceptions for this.  Our\ndecision will be guided by the two goals of preserving the free status\nof all derivatives of our free software and of promoting the sharing\nand reuse of software generally.\n\n                            NO WARRANTY\n\n  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO\nWARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.\nEXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR\nOTHER PARTIES PROVIDE THE LIBRARY \"AS IS\" WITHOUT WARRANTY OF ANY\nKIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE\nLIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME\nTHE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN\nWRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY\nAND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU\nFOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR\nCONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE\nLIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING\nRENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A\nFAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF\nSUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGES.\n\n                     END OF TERMS AND CONDITIONS\n\f\n           How to Apply These Terms to Your New Libraries\n\n  If you develop a new library, and you want it to be of the greatest\npossible use to the public, we recommend making it free software that\neveryone can redistribute and change.  You can do so by permitting\nredistribution under these terms (or, alternatively, under the terms of the\nordinary General Public License).\n\n  To apply these terms, attach the following notices to the library.  It is\nsafest to attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least the\n\"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the library's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n\nAlso add information on how to contact you by electronic and paper mail.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the library, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the\n  library `Frob' (a library for tweaking knobs) written by James Random Hacker.\n\n  <signature of Ty Coon>, 1 April 1990\n  Ty Coon, President of Vice\n\nThat's all there is to it!\n"
  },
  {
    "path": "ChangeLog",
    "content": "commit 3b6508281d8c23270dde6002f1142a3906fb2da0\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sun Jun 22 19:43:02 2025 +0200\n\n    Use unsigned int for accelerator ID selecting graphics driver\n\ncommit f321b9a48c657acea37b7f23fb2eb040cca49602\nMerge: 77c71dc 5c81466\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sat Mar 15 12:12:51 2025 +0100\n\n    Merge pull request #156 from caramelli/master\n    \n    Don't generate .pc files for static modules when building for shared type libraries\n\ncommit 5c81466de693cb180712a71b36e7ccbcc8ad43ef\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Mar 15 12:05:34 2025 +0100\n\n    Update ChangeLog\n\ncommit d83df032ec719b8d22d893e227e7d39f74e7b6f4\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Mar 15 12:04:19 2025 +0100\n\n    Don't generate .pc files for static modules when building for shared type libraries\n\ncommit 77c71dcf072a5c7d1944073793c3030c14af049e\nMerge: 4d6b7dd db0c8b9\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sat Mar 8 23:35:58 2025 +0100\n\n    Merge pull request #155 from stefan11111/master\n    \n    increase maximum number of input evdev devices\n\ncommit db0c8b938902b6a69772782c347b847c150a0ebc\nAuthor: stefan11111 <stefan11111@shitposting.expert>\nDate:   Sat Mar 8 20:30:54 2025 +0200\n\n    increase maximum number of input evdev devices\n\ncommit 4d6b7ddd8477b4b52aa78ec82a3add28ade0c965\nMerge: 51af532 7a9e58a\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed Oct 9 22:05:07 2024 +0200\n\n    Merge pull request #154 from shengwen-tw/master\n    \n    Check DRM plane type before attaching it as main plane\n\ncommit 7a9e58ac9d2c1f610c8cafe7d3c0c6a63b33c130\nAuthor: Shengwen Cheng <shengwen1997.tw@gmail.com>\nDate:   Wed Oct 9 00:18:36 2024 +0800\n\n    Check DRM plane type before attaching it as main plane\n    \n    Linux DRM allows using multiplane overlay (MPO) model for power-saving. The\n    plane types consist of PRIMARY, CURSOR, and OVERLAY, with only the PRIMARY\n    plane supporting operations like modesetting, flipping, etc.\n    \n    This commit introduces type checking for plane attachment, ensuring that\n    DirectFB2 does not misuse other plane types as the main plane.\n    \n    Reference:\n    [1] https://dri.freedesktop.org/docs/drm/gpu/amdgpu/display/mpo-overview.html\n\ncommit 51af532e5c1d6c0c742092d3bc3f93770475e626\nMerge: 2952d1d 97d74c9\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Sep 23 22:55:51 2024 +0200\n\n    Merge pull request #152 from kootrit/patch-1\n    \n    Change SA_NOMASK to SA_NODEFER in lib/fusion/lock.c\n\ncommit 97d74c98b9e133027a273fbea84bc5e64167bcd0\nAuthor: kootrit <humble.tyler@disroot.org>\nDate:   Sun Sep 22 13:15:04 2024 +0000\n\n    Change SA_NOMASK to SA_NODEFER in lib/fusion/lock.c\n    \n    This fixes compiling on musl.\n    SA_NOMASK is deprecated.\n\ncommit 2952d1d16b546be09e1cbb5da5e0c718d8f5ee32\nMerge: 9ea1879 699ec04\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Thu Jun 27 16:57:48 2024 +0200\n\n    Merge pull request #150 from shengwen-tw/master\n    \n    Alias __NR_futex with __NR_futex_time64 for RV32 platform\n\ncommit 699ec0471dec73639e1d18eb4426590440c28642\nAuthor: Shengwen Cheng <shengwen1997.tw@gmail.com>\nDate:   Thu Jun 27 21:20:10 2024 +0800\n\n    Alias __NR_futex with __NR_futex_time64 for RV32 platform\n    \n    Since version 5.1, Linux has dropped several RISC-V 32-bit syscalls by\n    removing __ARCH_WANT_TIME32_SYSCALLS macro, causing the compilation of\n    DirectFB2 to fail on RV32 platform with error of no definition of\n    __NR_futex is declared.\n    \n    To resolve the issue, this commit aliases __NR_futex with __NR_futex_time64\n    as a fallback solution.\n    \n    Reference:\n    [1] https://sourceware.org/legacy-ml/libc-alpha/2019-06/msg00557.html\n    [2] https://git.openembedded.org/openembedded-core/tree/meta/recipes-support/boost/boost/0001-fiber-libs-Define-SYS_futex-if-it-does-not-exist.patch?h=honister\n\ncommit 9ea1879446e1ccdb9a25e91e3b03d1980a0ec53e\nMerge: 38ad79a ed0ade2\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Tue Apr 2 22:58:16 2024 +0200\n\n    Merge pull request #146 from caramelli/master\n    \n    Disable shadow warnings\n\ncommit ed0ade2ef88686b4b50c46310de2aa2233ebeaeb\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Tue Apr 2 22:51:52 2024 +0200\n\n    Disable shadow warnings\n\ncommit 38ad79a4d63955fa7c3a8d307fc9d0c63de36a9b\nMerge: d1ed180 cf13a79\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Thu Mar 14 16:10:52 2024 +0100\n\n    Merge pull request #145 from caramelli/master\n    \n    Input/NuttX: Fix build on sim board\n\ncommit cf13a798e5258190109a4808bdaf93483ff2599e\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Mar 14 16:07:20 2024 +0100\n\n    Input/NuttX: Fix build on sim board\n\ncommit d1ed1801f0b8485f4ebc246fac2f280e47e11b44\nMerge: 65c2707 ef1f5d5\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Dec 18 22:24:36 2023 +0100\n\n    Merge pull request #140 from caramelli/master\n    \n    meson: Add fluxcomp option\n\ncommit ef1f5d505491c650b9d59b73f7e967a80c49e6b5\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Dec 18 16:16:34 2023 +0100\n\n    Update ChangeLog\n\ncommit d2af10462639dfb0fb9293e358a7cc03b3b8bda9\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Dec 18 16:15:17 2023 +0100\n\n    meson: Add fluxcomp option\n\ncommit 65c27072986793a646cb75cc2b0f5562227e1717\nMerge: 16b05d0 ed8084e\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Dec 11 22:45:02 2023 +0100\n\n    Merge pull request #139 from caramelli/master\n    \n    Python implementation of fluxcomp\n\ncommit ed8084e7fdd6054be7065e760f2607811ea7d3de\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Dec 11 22:41:44 2023 +0100\n\n    Python implementation of fluxcomp\n\ncommit 16b05d03e95032acca6aef3c527650ca94e048a5\nMerge: a7a176b 26daf3f\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Fri Oct 6 19:19:51 2023 +0200\n\n    Merge pull request #138 from caramelli/master\n    \n    IDirectFBGL: Add SwapBuffers()\n\ncommit 26daf3fc9ef84e0bbf88c09df2c075e2ac57b504\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Fri Oct 6 18:48:55 2023 +0200\n\n    Update ChangeLog\n\ncommit 5c5202a50e2f2ddb7d56738b290cfce5f70c42d9\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Fri Oct 6 18:48:50 2023 +0200\n\n    IDirectFBGL: Add SwapBuffers()\n\ncommit a7a176bb501c0730cd24bf06420ce35f53e85a15\nMerge: abf3795 d1b396f\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed Aug 16 08:06:57 2023 +0200\n\n    Merge pull request #137 from fifteenhex/fixdrmkms-on-mstar-20230816\n    \n    drmkms: Enumerate all planes when looking for the primary format\n\ncommit d1b396f67827e236d734f902874ff9568ca0256b\nAuthor: Daniel Palmer <daniel@0x0f.com>\nDate:   Tue Aug 15 20:18:17 2023 +0900\n\n    drmkms: Enumerate all planes when looking for the primary format\n\ncommit abf379572bdc2271ddedea42c78a442218963d3c\nMerge: e4921b7 30e4afd\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sat Aug 12 09:25:49 2023 +0200\n\n    Merge pull request #135 from miyoo-oss/feature/screen_rot_fixes\n    \n    Fix screen rotation to read the proper props values\n\ncommit 30e4afdd8be64cde0c73a6c9de69f64a3286e392\nAuthor: Stephen Bird <sebirdman@gmail.com>\nDate:   Fri Aug 11 15:35:14 2023 -0700\n\n    Fix screen rotation to read the proper props values\n    \n    This inner loop breaks screen rotation for devices that require it and is\n    unneccessary.\n\ncommit e4921b7349329e6c1e4720adf5dec5979a31f48f\nMerge: c85b06b a8a327e\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sun Aug 6 10:44:23 2023 +0200\n\n    Merge pull request #133 from caramelli/master\n    \n    STM32F429I-DISCO NuttX defconfig: Use PL_MPEG video provider\n\ncommit a8a327eb44cffa0f3111a05ba77e5b5f33aad534\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sun Aug 6 10:34:59 2023 +0200\n\n    STM32F429I-DISCO NuttX defconfig: Use PL_MPEG video provider\n\ncommit c85b06b8fe6abc3853cf3b1be3cfa815fa09b542\nMerge: 27dbab6 6077fca\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Jul 17 12:53:57 2023 +0200\n\n    Merge pull request #131 from caramelli/master\n    \n    Add support for DirectFBGL module initialization when constructor attribute is not used (MCU targets)\n\ncommit 6077fcae36d306b82f9060bd538a55b0ba38677a\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Jul 17 12:42:56 2023 +0200\n\n    Update ChangeLog\n\ncommit 22d42e25bc73daf61a612a88ff4e9c6d969aad00\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Jul 17 12:42:40 2023 +0200\n\n    Add support for DirectFBGL module initialization when constructor attribute is not used (MCU targets)\n\ncommit 27dbab6d58662cbe7dfbb54315dcfc0b459af98f\nMerge: b99f492 42d7daf\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Jul 3 10:55:24 2023 +0200\n\n    Merge pull request #130 from caramelli/master\n    \n    NuttX Input Driver: Translate raw X/Y touchscreen data into pixel coordinates\n\ncommit 42d7daf26d56704326abbe73c838f44f102046fb\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Jul 3 10:51:16 2023 +0200\n\n    NuttX Input Driver: Translate raw X/Y touchscreen data into pixel coordinates\n\ncommit b99f49243bab1c8ffccd6c2401d7085c2d66caab\nMerge: b60149a 69f0558\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Thu Jun 22 15:09:53 2023 +0200\n\n    Merge pull request #129 from caramelli/master\n    \n    NuttX defconfig: CONFIG_PTHREAD_CLEANUP => CONFIG_PTHREAD_CLEANUP_STACKSIZE\n\ncommit 69f05580ecde6eae418608623229bf8645d1ea38\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Jun 22 15:05:57 2023 +0200\n\n    NuttX defconfig: CONFIG_PTHREAD_CLEANUP => CONFIG_PTHREAD_CLEANUP_STACKSIZE\n\ncommit b60149ab11185167f03876448edb863247c8bc19\nMerge: 2276c80 26fdee5\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Thu Jun 22 08:25:07 2023 +0200\n\n    Merge pull request #128 from caramelli/master\n    \n    NuttX Input Driver: Add support for buttons and keyboard\n\ncommit 26fdee5e4811fd2592145ae75b51c35cae998ba4\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Jun 22 08:20:15 2023 +0200\n\n    NuttX Input Driver: Add support for buttons and keyboard\n\ncommit 2276c8096dd5effa235c0f672b212f50a5256f91\nMerge: 1c65e0c 6a64478\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sun Jun 18 11:34:06 2023 +0200\n\n    Merge pull request #127 from caramelli/master\n    \n    NuttX: Add defconfig for STM32F429I-DISCO board\n\ncommit 6a64478037c017cabadc64a4c7c7c719f37ce328\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sun Jun 18 11:28:29 2023 +0200\n\n    NuttX: Add defconfig for STM32F429I-DISCO board\n\ncommit 1c65e0c2c668b5d59705b0d0005b8976bddde8d2\nMerge: ab61370 ffe97c4\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Tue Jun 13 05:53:49 2023 +0200\n\n    Merge pull request #126 from caramelli/master\n    \n    drmkms: Fix plane layers registration with multi application core\n\ncommit ffe97c43f621af0946b32a40b30f4a8ae4258178\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Tue Jun 13 05:41:33 2023 +0200\n\n    drmkms: Fix plane layers registration with multi application core\n\ncommit ab613703de874a59be5847b5068d8791d69881d7\nMerge: 62fb8e2 c1e5099\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Fri Jun 2 08:17:17 2023 +0200\n\n    Merge pull request #125 from caramelli/master\n    \n    drmkms: Implement system_get_modes() / system_get_current_mode()\n\ncommit c1e5099fb3d40b55118f8cb32a0313d3f8634d57\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Fri Jun 2 08:03:57 2023 +0200\n\n    Update ChangeLog\n\ncommit d96c8c43ae375d28d58ccc71b40e3670830f4f9a\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Fri Jun 2 08:03:32 2023 +0200\n\n    drmkms: Implement system_get_modes() / system_get_current_mode()\n\ncommit 62fb8e283b2acff8afbb41cd365ee2c4ed3104e8\nMerge: 69975b9 fc38845\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sat May 27 08:27:54 2023 +0200\n\n    Merge pull request #124 from caramelli/master\n    \n    Add NuttX input driver module\n\ncommit fc38845b7878773fa7c12e4073cbf253f2ef183d\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat May 27 08:22:26 2023 +0200\n\n    Add NuttX input driver module\n\ncommit 69975b9a9e96f3f1253f5818e89b1c9e7c3e03e5\nMerge: 6a1e50d 5435e13\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Fri May 26 14:58:14 2023 +0200\n\n    Merge pull request #123 from caramelli/master\n    \n    Direct/Stream: Restore RTSP support\n\ncommit 5435e137d1a95674acaa656b6a7f064459b9ec09\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Fri May 26 14:42:52 2023 +0200\n\n    Direct/Stream: Restore RTSP support\n\ncommit 6a1e50d741ef552b36fcf73d30be2dd35cf93bc5\nMerge: 223ad60 648adcd\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed May 24 19:01:26 2023 +0200\n\n    Merge pull request #122 from caramelli/master\n    \n    Direct/Stream: Add D_STREAM_BYPASS environment variable\n\ncommit 648adcdab2a342a051608b48845ec6c267c38c0b\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed May 24 18:50:48 2023 +0200\n\n    Direct/Stream: Add D_STREAM_BYPASS environment variable\n\ncommit 223ad60872f6b95c1d01bacf6e3e85e2ab360b4e\nMerge: 0beca0f 5b6504f\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon May 22 15:50:48 2023 +0200\n\n    Merge pull request #121 from caramelli/master\n    \n    NuttX: Add NuttXFB System Module\n\ncommit 5b6504f4ca36b1fc303de4588ec094b308d16d11\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon May 22 15:23:36 2023 +0200\n\n    NuttX: Add NuttXFB System Module\n\ncommit 0beca0f2c47a57885fcd5d910188a5961ab87d12\nMerge: e3919ee 70c600a\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Thu May 18 08:18:00 2023 +0200\n\n    Merge pull request #120 from caramelli/master\n    \n    dfb_scale_linear_32(): Fix premultiplication when loading a scaled image\n\ncommit 70c600a530324d7cc36c82a35f22eff1dbe8fb8a\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu May 18 08:13:46 2023 +0200\n\n    dfb_scale_linear_32(): Fix premultiplication when loading a scaled image\n\ncommit e3919eee1bfca09d88b2280ca06ca7fa127a6d76\nMerge: 68666a6 42f6d22\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sun May 14 16:26:08 2023 +0200\n\n    Merge pull request #119 from caramelli/master\n    \n    Direct/Stream: Add RTSP URL stub\n\ncommit 42f6d220e2f33a875ec2d62605303764a2730e80\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sun May 14 16:09:08 2023 +0200\n\n    Direct/Stream: Add RTSP URL stub\n\ncommit 68666a61e47f6c386f08889fa781a6b1f14e61a1\nMerge: cb33e33 72698b2\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sat May 13 21:40:13 2023 +0200\n\n    Merge pull request #118 from caramelli/master\n    \n    Update to NuttX 12.1.0\n\ncommit 72698b25fef7de684374b50761c675eaaf1d5355\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat May 13 21:33:18 2023 +0200\n\n    Update to NuttX 12.1.0\n\ncommit cb33e33cd5ccfb0d084ed13153f71501110f7784\nMerge: 2692779 5879443\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed May 10 17:04:49 2023 +0200\n\n    Merge pull request #116 from caramelli/master\n    \n    IDirectFBFont: Fix loading from streamed data buffer\n\ncommit 58794434bc29f6e5706eece867d5a614cec9aa5f\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed May 10 16:54:39 2023 +0200\n\n    Update ChangeLog\n\ncommit 0f9d5265270031d4a8d03a892beef4481b6a97a4\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed May 10 16:53:42 2023 +0200\n\n    IDirectFBFont: Fix loading from streamed data buffer\n\ncommit 26927796d587aafccedceb9faf531670347448a1\nMerge: 84a3131 1c4cf69\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sat May 6 11:32:07 2023 +0200\n\n    Merge pull request #115 from caramelli/master\n    \n    Add build option for piped stream support\n\ncommit 1c4cf69ab193fc8e0b59062415f1c1022aa5c406\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat May 6 11:24:15 2023 +0200\n\n    Update ChangeLog\n\ncommit 8cb3a8a67eb51b3b5b6b5eed44082bd51f522568\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat May 6 11:24:07 2023 +0200\n\n    Add build option for piped stream support\n\ncommit 84a31310821fb4af12df7651376b3bd3debd3f65\nMerge: 6269d4a 646c725\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sat Apr 29 14:22:05 2023 +0200\n\n    Merge pull request #114 from caramelli/master\n    \n    DGIFF/DFIFF/DFVFF: Add support for input data located in memory or streamed\n\ncommit 646c7259d6f17f71fc5de4d60e3e5a9e429b99c8\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Apr 29 14:11:56 2023 +0200\n\n    DGIFF/DFIFF/DFVFF: Add support for input data located in memory or streamed\n\ncommit 6269d4a55d013737704997dadccdf32e07890dd4\nMerge: 632cba0 d06f9b3\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sun Apr 16 13:04:34 2023 +0200\n\n    Merge pull request #113 from caramelli/master\n    \n    drmkms: Only register planes with possible_crtcs compatible with primary CRTC\n\ncommit d06f9b3dc2ccfb08a1420c0c3ef30d6299325c5a\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sun Apr 16 12:57:31 2023 +0200\n\n    drmkms: Only register planes with possible_crtcs compatible with primary CRTC\n\ncommit 632cba05c265346cc2cd27c99b311f99526f1ce1\nMerge: f0d703b fb01984\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sat Apr 15 14:28:02 2023 +0200\n\n    Merge pull request #112 from caramelli/master\n    \n    Add definition for the SCHED_SPORADIC scheduling policy\n\ncommit fb0198449e57efd89d7e1b51416e5efa92088c08\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Apr 15 14:11:15 2023 +0200\n\n    Update ChangeLog\n\ncommit 820a2146f7eb83348ad22356fb915ad1bf04d8f0\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Apr 15 14:10:47 2023 +0200\n\n    Add definition for the SCHED_SPORADIC scheduling policy\n\ncommit f0d703b7a3aaf38b94815449cbf86e3420e20a2f\nMerge: 452b899 95d9fb3\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Thu Apr 13 18:41:10 2023 +0200\n\n    Merge pull request #111 from caramelli/master\n    \n    Input/Linux: Initialize device_info before calling get_device_info()\n\ncommit 95d9fb31694c6a5aeaedb9b6b27911b97fb92dba\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Apr 13 18:36:44 2023 +0200\n\n    Input/Linux: Initialize device_info before calling get_device_info()\n\ncommit 452b899a28fbc13710af16d6798a587bbfd51ae1\nMerge: d01c4df 9bddf65\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Apr 10 12:21:58 2023 +0200\n\n    Merge pull request #109 from caramelli/master\n    \n    If the AR24 format is not supported, look at all formats to find a fallback format (not just the first one)\n\ncommit 9bddf65c1f29b37fabf92eedd7836df96fd65391\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Apr 10 01:00:35 2023 +0200\n\n    If the AR24 format is not supported, look at all formats to find a fallback format (not just the first one)\n\ncommit d01c4dff74bb9be5f9b66bed410befd572e401de\nMerge: 2f872de d11102d\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Fri Apr 7 09:56:14 2023 +0200\n\n    Merge pull request #107 from caramelli/master\n    \n    Add NuttX support for running DirectFB apps on MCU devices\n\ncommit d11102daba0af1f75339d9a27b3b5c9eba242884\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Fri Apr 7 09:50:46 2023 +0200\n\n    Add NuttX support for running DirectFB apps on MCU devices\n\ncommit 2f872de307cc9db0749122fa33286268d4e1be49\nMerge: f0904fd 3d9375c\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed Apr 5 22:19:09 2023 +0200\n\n    Merge pull request #106 from caramelli/master\n    \n    Fix -Wshadow and -Woverflow warnings when using bare metal toolchain\n\ncommit 3d9375c67041849fcf37f674218b008cd08c04ce\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Apr 5 22:13:01 2023 +0200\n\n    Update ChangeLog\n\ncommit ff14133b16a0bffcc9e597cd33e8cb551f964703\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Apr 5 22:10:23 2023 +0200\n\n    Fix -Wshadow and -Woverflow warnings when using bare metal toolchain\n\ncommit f0904fdd06c972384bd526f440823a8e95393c19\nMerge: f904c12 b039561\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed Apr 5 12:37:43 2023 +0200\n\n    Merge pull request #105 from caramelli/master\n    \n    meson: Update INSTALL instructions\n\ncommit b0395614ea9213b86fde03b842132778233bf068\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Apr 5 13:35:05 2023 +0200\n\n    meson: Update INSTALL instructions\n\ncommit f904c1206e7b729024e91d9a20bc558a85bb9e30\nMerge: b4b351b 440784a\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Tue Apr 4 02:52:28 2023 +0200\n\n    Merge pull request #104 from caramelli/master\n    \n    Add os/signals.h\n\ncommit 440784ab747a2547cab4b72f0b134ad7f30e3a5e\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Tue Apr 4 03:53:30 2023 +0200\n\n    Add os/signals.h\n\ncommit b4b351b98f0933c509b7223afe27a9dcaa8650cd\nMerge: ac474a2 9af0ca5\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Apr 3 15:00:32 2023 +0200\n\n    Merge pull request #103 from caramelli/master\n    \n    Move signals.c to the os directory\n\ncommit 9af0ca58cbefee17e0200e9f2aca582e6641f88a\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Apr 3 16:00:19 2023 +0200\n\n    Move signals.c to the os directory\n\ncommit ac474a2e9d85a5bc5ec5639f04755963c82082eb\nMerge: 1d310d2 c71f508\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Apr 3 11:14:49 2023 +0200\n\n    Merge pull request #102 from caramelli/master\n    \n    Fix warning: function declaration isn't a prototype [-Wstrict-prototypes]\n\ncommit c71f508b3b58c101560a6726b94d9235cb17db98\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Apr 3 12:12:06 2023 +0200\n\n    Fix warning: function declaration isn't a prototype [-Wstrict-prototypes]\n\ncommit 1d310d2f9a08df42c17225289029a54f144b21f4\nMerge: 4a02a2b 7555132\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sun Apr 2 20:43:43 2023 +0200\n\n    Merge pull request #101 from caramelli/master\n    \n    Restore build option for network support\n\ncommit 75551320d921327a536d6f22d405d8752d26de1e\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sun Apr 2 20:32:14 2023 +0200\n\n    Restore build option for network support\n\ncommit 4a02a2b3c418daa84a3050ba0c71cfe71ca22918\nMerge: 1ac8ead 0daf53e\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sat Apr 1 09:59:32 2023 +0200\n\n    Merge pull request #100 from caramelli/master\n    \n    Add build option for constructor attribute\n\ncommit 0daf53ebc8c80d67b32540d1053730d60580b01c\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Apr 1 09:51:11 2023 +0200\n\n    Add build option for constructor attribute\n\ncommit 1ac8ead8f18870f3a42cd5aa159fe0e1741d9bdd\nMerge: db494a2 2d69fe6\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Fri Mar 31 22:27:39 2023 +0200\n\n    Merge pull request #99 from caramelli/master\n    \n    drmkms: alpha range is [0 - 65535]\n\ncommit 2d69fe606ae125b476508322683124567781c190\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Fri Mar 31 22:25:38 2023 +0200\n\n    drmkms: alpha range is [0 - 65535]\n\ncommit db494a279fdff50f4b1480783f766e058e611767\nMerge: 27037bc a83ef2c\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Tue Mar 28 17:41:07 2023 +0200\n\n    Merge pull request #97 from caramelli/master\n    \n    Fix type cast when calling direct_file_seek() in file_peek()\n\ncommit a83ef2c5640b93deb4a4cd0624877250933c3c27\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Tue Mar 28 17:41:43 2023 +0200\n\n    Fix type cast when calling direct_file_seek() in file_peek()\n\ncommit 27037bcf84dbb8f280637ba149c5f793f7231c15\nMerge: 1b87ca6 85cc655\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sun Mar 12 10:46:51 2023 +0100\n\n    Merge pull request #96 from caramelli/master\n    \n    VideoProvider/DFVFF: Add support for speed multiplier below and over 1.0\n\ncommit 85cc65592a45ce9bee035130f3559360b543ed92\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sun Mar 12 10:40:41 2023 +0100\n\n    Update ChangeLog\n\ncommit 318c33fbf2244b876b8067b2e3ac4f4aa62e5bfd\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sun Mar 12 10:40:29 2023 +0100\n\n    VideoProvider/DFVFF: Add support for speed multiplier below and over 1.0\n\ncommit 1b87ca61d16b46a06960c1fd29428316bc87a547\nMerge: ac4f10c bf501d7\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Fri Mar 10 16:31:56 2023 +0100\n\n    Merge pull request #18 from fifteenhex/gfx_neon_20220217\n    \n    Genefx: Add NEON assembly support\n\ncommit bf501d779dad8ecf038e6f8ffb7377e489bca318\nMerge: 2cea303 ac4f10c\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Fri Mar 10 16:31:14 2023 +0100\n\n    Merge branch 'master' into gfx_neon_20220217\n\ncommit 2cea3031d8078fc64ee6ea7b34c9fdc36488a8a2\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Fri Mar 10 16:10:53 2023 +0100\n\n    Merge ARM NEON optimization\n\ncommit ac4f10ca5dcb9fb8c848fcde26a19d88cc8afd25\nMerge: d1182ae f87bad2\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed Mar 1 03:55:09 2023 +0100\n\n    Merge pull request #92 from caramelli/master\n    \n    Restore global variables for DirectFB version\n\ncommit f87bad231f8c6239a9ce7eb8a9b9ea6897553c1c\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Mar 1 03:55:03 2023 +0100\n\n    Update ChangeLog\n\ncommit 185a5fce4aeb8b581c0b42fc040c83c5a1b6943a\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Mar 1 03:54:58 2023 +0100\n\n    Restore global variables for DirectFB version\n\ncommit d1182aeace2fbc3877266f52cf1b640235442390\nMerge: 8bea71e 70045be\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Feb 27 11:15:50 2023 +0100\n\n    Merge pull request #91 from caramelli/master\n    \n    dfb-update-pkgconfig: Add DESTDIR\n\ncommit 70045be30a4414c45c806dbf0c88a894023210cd\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Feb 27 10:58:34 2023 +0100\n\n    Update ChangeLog\n\ncommit 5731e6d121ec20c67aecbd2d4ededc93a2565404\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Feb 27 10:58:28 2023 +0100\n\n    dfb-update-pkgconfig: Add DESTDIR\n\ncommit 8bea71e1e5e0fe185a264b66a40bc83291fe5f06\nMerge: d33e3d4 e1a7adf\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed Feb 22 08:44:07 2023 +0100\n\n    Merge pull request #88 from caramelli/master\n    \n    Add pkg-config files per module (for static build)\n\ncommit e1a7adf6e1b0107f930cfa3a5e98647a556b8715\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Feb 22 08:37:07 2023 +0100\n\n    Update ChangeLog\n\ncommit 3e2638eb08d581d7f8bac4d34303a4859506990e\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Feb 22 08:36:47 2023 +0100\n\n    Add pkg-config files per module (for static build)\n\ncommit d33e3d40c20d3f50cb6e48882f670477068e3288\nMerge: be72f1f d244ae0\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sun Feb 19 07:07:13 2023 +0100\n\n    Merge pull request #86 from caramelli/master\n    \n    drmkms: Set default pixel format using drmModePlane formats array\n\ncommit d244ae07fd84d511a82066bf0b37a648534311e5\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sun Feb 19 07:06:13 2023 +0100\n\n    drmkms: Ask the kernel to expose all planes to userspace, thanks to Daniel Palmer!\n\ncommit c6db97e3ee85b81e7fd3ca778664b989d42db679\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Feb 18 09:59:05 2023 +0100\n\n    drmkms: Set default pixel format using drmModePlane formats array if AR24 is not supported\n\ncommit be72f1f0ca0fc5a6f0b42a0bb0164dad654d875e\nMerge: e510f61 3770869\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Thu Feb 2 20:33:51 2023 +0100\n\n    Merge pull request #84 from caramelli/master\n    \n    Use Libs.private in pkg-config files corresponding to modules\n\ncommit 3770869d315e1db1a4a85001f17e767863f78969\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Feb 2 20:29:45 2023 +0100\n\n    Use Libs.private in pkg-config files corresponding to modules\n\ncommit e510f613a422a88fd3b556dc2346a0f51c18e17f\nMerge: b859a6a d26374d\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Thu Feb 2 06:37:44 2023 +0100\n\n    Merge pull request #83 from caramelli/master\n    \n    DRMKMS/Screen: Get panel orientation on screen initialization\n\ncommit d26374df50878001ea591bdf72e3bfa7765e2d15\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Feb 2 06:31:18 2023 +0100\n\n    Update ChangeLog\n\ncommit 5e7d9f13ef93d974947391250b8edd747777f368\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Feb 2 06:30:58 2023 +0100\n\n    DRMKMS/Screen: Get panel orientation on screen initialization\n\ncommit b859a6a2f57c72432e57df198e57b3853c11891e\nMerge: c17a0d9 8396440\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Jan 30 11:03:13 2023 +0100\n\n    Merge pull request #82 from caramelli/master\n    \n    Merge dfb_types.h into directfb.h\n\ncommit 8396440cc5c77e06023d5d21f197e02a0c13d052\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Jan 30 11:03:26 2023 +0100\n\n    Update ChangeLog\n\ncommit 5670235d139e4395b5dba725a4cec75843c66b1e\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Jan 30 11:03:11 2023 +0100\n\n    Merge dfb_types.h into directfb.h\n\ncommit c17a0d9a67272420afe7677d8f03e15672839546\nMerge: ef867c1 3ebe7ea\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Fri Jan 27 18:47:57 2023 +0100\n\n    Merge pull request #81 from caramelli/master\n    \n    Add support for BGR24 format\n\ncommit 3ebe7ea437f3d38adad9d4d1ee3fd9b706da08dc\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Fri Jan 27 18:47:19 2023 +0100\n\n    Update ChangeLog\n\ncommit 0da4139930f6d644e4001c62ad7a25aa1b4f8378\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Fri Jan 27 18:47:05 2023 +0100\n\n    Add support for BGR24 format\n\ncommit ef867c10dc63f8f734d9aa8c7f17396e9dc1838a\nMerge: b80fbc8 d14c65f\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Jan 16 14:28:25 2023 +0100\n\n    Merge pull request #80 from caramelli/master\n    \n    Meson: Fix debug buildtype\n\ncommit d14c65fa1b4d7e79e1576dde682049730f316a4e\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Jan 16 14:21:04 2023 +0100\n\n    Meson: Fix debug buildtype\n\ncommit b80fbc8cdb98839108676ae9cc24fabdec3b34b5\nMerge: 68367a4 acae2dc\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sat Jan 14 03:16:33 2023 +0100\n\n    Merge pull request #79 from caramelli/master\n    \n    Add check for state->source in dfb_gfxcard_state_check_acquire()\n\ncommit acae2dc598e5f41397e0e69844758870ace7bd53\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Jan 14 03:15:44 2023 +0100\n\n    Core/GfxState: Add check for state->source in dfb_gfxcard_state_check_acquire()\n\ncommit 68367a48c745630e3180437405ec3e2975036c78\nMerge: cd4172c 5be9975\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sat Jan 7 08:18:47 2023 +0100\n\n    Merge pull request #78 from caramelli/master\n    \n    Core/Screen: Add screen_data argument for GetScreenRotation() function\n\ncommit 5be99757310e92e2922f10162f74ed2e51b9c789\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Jan 7 08:17:31 2023 +0100\n\n    Update ChangeLog\n\ncommit c3742ae6cae0efa30e4ecd53c70d1c3b52c0b676\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Jan 7 08:17:23 2023 +0100\n\n    Core/Screen: Add screen_data argument for GetScreenRotation() function\n\ncommit cd4172c5c38ccfd11caaa53cbc33acb7724b55b4\nMerge: bf85d08 47b5604\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Jan 2 10:47:38 2023 +0100\n\n    Merge pull request #76 from caramelli/master\n    \n    Meson: Use install_symlink() function instead of meson_symlink.sh script\n\ncommit 47b5604a830d1bab9abf2c881717aee6b0c8f552\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Jan 2 10:34:16 2023 +0100\n\n    Update ChangeLog\n\ncommit 9bdd8911aed12a5b6a293aded3d3c54c27ccc7cb\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Jan 2 10:33:47 2023 +0100\n\n    Meson: Use install_symlink() function instead of meson_symlink.sh script\n\ncommit bf85d083d07ffca28361235c6c10caf73961776e\nMerge: d942ae0 487211f\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Thu Dec 29 16:42:08 2022 +0100\n\n    Merge pull request #75 from caramelli/master\n    \n    Fix loop initial declarations (due to removal of -std=gnu99 option)\n\ncommit 487211ffd4b4a13bc59a1b5f658908835619da28\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Dec 29 16:42:29 2022 +0100\n\n    Fix loop initial declarations (due to removal of -std=gnu99 option)\n\ncommit d942ae051557c7aae03b65f4b1e14dd7ddde0223\nMerge: 1278837 36f78a5\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed Dec 28 19:55:37 2022 +0100\n\n    Merge pull request #73 from fifteenhex/drmkmsrotsupport-20221227\n    \n    WorkInProgress: Allow DRM/KMS orientation to configure the rotation\n\ncommit 36f78a5dca1ac9d48a341cf4b5a201a7e40a9a30\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Dec 28 19:55:51 2022 +0100\n\n    Allow DRM/KMS orientation to configure the rotation\n\ncommit 76ae5f3c50fd06b94c5ca56565769b4ca71b8eb7\nAuthor: Daniel Palmer <daniel@0x0f.com>\nDate:   Fri Nov 11 21:47:05 2022 +0900\n\n    system: drmkms: Probe for panel rotation\n    \n    On some embedded systems the LCD panel is mounted in the chassis\n    upside down. To render the image correctly it needs to be rotated\n    in userspace.\n    \n    The kernel part of DRM/KMS exposes the panel orientation via a\n    connector property. So grab the orientation for the panel from the\n    kernel and present that as the screen rotation so that the image\n    is flipped when blitted.\n\ncommit 16cc14cf28dc5cfc75cb29456f4e443495e7f2a3\nAuthor: Daniel Palmer <daniel@0x0f.com>\nDate:   Sun Feb 20 11:39:10 2022 +0900\n\n    core: layer: Get the physical rotation from the system\n    \n    For drmkms the physical orientation of the display can be\n    probed so it is possible to automatically correct for a\n    rotated display.\n    \n    If the user hasn't set the rotation in their config ask\n    the system what the rotation should be.\n\ncommit 5525df479e8ced0287e7c3b325bc3c4dc7b69c13\nAuthor: Daniel Palmer <daniel@0x0f.com>\nDate:   Sat Feb 19 11:02:57 2022 +0900\n\n    conf: Add flag for whether the rotation was configured or not.\n    \n    If the user specified a rotation the value could be 0,90,180 or 270.\n    If they didn't specify anything it will be 0. Currently it's not\n    possible to tell if they asked for 0 or it's just the default.\n    \n    If the value is 0 but the user didn't set it we should ask the\n    system what it thinks the rotation is (i.e. the panel orientation\n    from DRM/KMS). So a flag is needed to tell if the 0 came from the\n    user.\n    \n    Add a flag for whether the rotation was user set.\n\ncommit 1278837fafc6d85d3a4dd316d848b5bb7dd19ec6\nMerge: 0fdf5df 7da29a8\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Tue Dec 20 13:22:23 2022 +0100\n\n    Merge pull request #71 from caramelli/master\n    \n    fusion: Install shm/pool.h header file\n\ncommit 7da29a843e2a765f53c87874c7ffdc37a2312f51\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Tue Dec 20 13:19:21 2022 +0100\n\n    fusion: Install shm/pool.h header file\n\ncommit 0fdf5df3995bbcb4d2e06fd5d2b979651bc60f0c\nMerge: 7fd8c8e 5bd77be\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Dec 12 17:27:35 2022 +0100\n\n    Merge pull request #69 from caramelli/master\n    \n    Move shutdown-info parameter definition to fusion config\n\ncommit 5bd77be2daf48c36a22d6fccf1f8e6970705e1d1\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Dec 12 17:27:09 2022 +0100\n\n    Update ChangeLog\n\ncommit 1e4c97c588121b3c814b108a26a356d977a946a6\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Dec 12 17:26:49 2022 +0100\n\n    Move shutdown-info parameter definition to fusion config\n\ncommit 7fd8c8ef0492711667e668a73c2cc336636a97b4\nMerge: 96a680d 4388a63\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sat Dec 3 08:07:36 2022 +0100\n\n    Merge pull request #68 from caramelli/master\n    \n    Move tools to DirectFB2-tools repository (for static library support)\n\ncommit 4388a633a043f34f3b12fdb6aa329d4ea800c45a\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Dec 3 07:25:42 2022 +0100\n\n    Update ChangeLog\n\ncommit 5ff1a698b3d5607c089b50910fa73138f98e4ec9\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Dec 3 07:25:11 2022 +0100\n\n    Move tools to DirectFB2-tools repository (for static library support)\n\ncommit 96a680da988cf3466f5106b943bc9739b2199fa9\nMerge: 2519295 4db5565\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed Nov 30 17:59:49 2022 +0100\n\n    Merge pull request #67 from caramelli/master\n    \n    Add DIRECT_DEALLOCATE_INTERFACE() calls on error\n\ncommit 4db5565d6ec9e5c5c06fe528bf111209bf11a112\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Nov 30 17:52:13 2022 +0100\n\n    Add DIRECT_DEALLOCATE_INTERFACE() calls on error\n\ncommit 2519295bc91765c1fc036d6ee206f163f7509c37\nMerge: ab42607 896141d\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sat Nov 19 10:33:09 2022 +0100\n\n    Merge pull request #65 from caramelli/master\n    \n    IDirectFBSurface: Set flip_func to control the triggering of the actual Flip\n\ncommit 896141dcd2ccb610c6aedad904dc1602ba9289f4\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Nov 19 10:33:03 2022 +0100\n\n    Update ChangeLog\n\ncommit 64471d3ce80ff3f948e02d809c51247a50e058ca\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Nov 19 10:32:50 2022 +0100\n\n    IDirectFBSurface: Set flip_func to control the triggering of the actual Flip\n\ncommit ab426077fe6c9dbfa8b0dfe95b7789d15172a159\nMerge: 1989def ee6ffd6\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Nov 14 12:20:31 2022 +0100\n\n    Merge pull request #64 from caramelli/master\n    \n    drmkms: Unused PoolData\n\ncommit ee6ffd6e8ff0d09cd886e7abbcc2dc26a0c06873\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Nov 14 12:00:12 2022 +0100\n\n    drmkms: Unused PoolData\n\ncommit 1989def37e4768782f98f57ba60be5f4b9d53f69\nMerge: e2814bb 3310069\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Thu Nov 10 12:11:25 2022 +0100\n\n    Merge pull request #63 from caramelli/master\n    \n    tools: Add dfiffinfo\n\ncommit 331006993b9d711fe88e74a82013e1debbddcb90\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Nov 10 11:41:08 2022 +0100\n\n    Update ChangeLog\n\ncommit 27d02177ae28cec5f8ea1e9afff402298c83d9f7\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Nov 10 11:40:56 2022 +0100\n\n    tools: Add dfiffinfo\n\ncommit e2814bb5c8b21072896026c3d8c318e4697ac4db\nMerge: 634b1a2 b781bc9\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Nov 7 21:17:53 2022 +0100\n\n    Merge pull request #62 from caramelli/master\n    \n    IDirectFB: Add GetFontSurfaceFormat()\n\ncommit b781bc98cbf1587a1a14110416750c6cc39d99c9\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Nov 7 19:57:32 2022 +0100\n\n    Update ChangeLog\n\ncommit 76fa4a7639c60fbddaf295fdef0aa97079128fe7\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Nov 7 19:57:00 2022 +0100\n\n    IDirectFB: Add GetFontSurfaceFormat()\n\ncommit 634b1a25488bc8a64b7026416712ebf99f66b91f\nMerge: ae9393d 54efecd\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Thu Oct 27 03:46:51 2022 +0200\n\n    Merge pull request #60 from caramelli/master\n    \n    Core/Main: Call fusion_hash_set_autofree()\n\ncommit 54efecd8acae0e6828f75c7ea8b1e2f128e2919d\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Oct 27 03:38:15 2022 +0200\n\n    Update ChangeLog\n\ncommit fb7411f36a7bbc0af99089a9dc179fffe30b0c29\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Oct 27 03:38:00 2022 +0200\n\n    Core/Main: Call fusion_hash_set_autofree()\n\ncommit ae9393d2d756a7a6907da5ec481e2b3e4e91efb0\nMerge: 85ee588 0659ed2\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed Oct 26 10:33:49 2022 +0200\n\n    Merge pull request #59 from caramelli/master\n    \n    Fusion: Fix memory leak and destroy event_dispatcher_thread on exit\n\ncommit 0659ed23c1d3bd86e06b70cdc1680d1c1e8de88e\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Oct 26 09:51:13 2022 +0200\n\n    Fusion: Fix memory leak and destroy event_dispatcher_thread on exit\n\ncommit 85ee588f636d4836bdf7c1d0db47b74d4ec3827d\nMerge: 3e0a706 d2a158a\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Oct 24 18:50:13 2022 +0200\n\n    Merge pull request #58 from caramelli/master\n    \n    Add musl libc compatibility\n\ncommit d2a158a3a89910e99f50e6ff8f073a457dcfcea0\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Oct 24 18:46:49 2022 +0200\n\n    Add musl libc compatibility\n\ncommit 3e0a706978538a2e2050a2745edb6ad0c30ad39c\nMerge: 651ac43 cb3fb64\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sat Oct 22 15:59:59 2022 +0200\n\n    Merge pull request #56 from caramelli/master\n    \n    Input/Linux: Uninitialised value was created by a stack allocation\n\ncommit cb3fb6487b6b8e5b66a9c1cb7a08673d50d49cc4\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Oct 22 15:59:16 2022 +0200\n\n    Input/Linux: Uninitialised value was created by a stack allocation\n\ncommit 651ac43bbb8daf812b410a66736a0ce457b00498\nMerge: 3392959 857032f\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Oct 17 17:57:33 2022 +0200\n\n    Merge pull request #55 from caramelli/master\n    \n    Meson: Add the boolean check kwarg to the run_command() call\n\ncommit 857032f9a16800f352cead58a1958965231c5ff7\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Oct 17 17:47:12 2022 +0200\n\n    Meson: Add the boolean check kwarg to the run_command() call\n\ncommit 339295980e9a0eeda55641dd35691942512bc70b\nMerge: 9a2d1bf 00c3612\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sat Oct 8 02:45:31 2022 +0200\n\n    Merge pull request #54 from caramelli/master\n    \n    Add support for static libraries (MCU targets)\n\ncommit 00c361275f506b798f06ff0979b6fa0ec89e1a80\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Oct 8 02:45:07 2022 +0200\n\n    Update ChangeLog\n\ncommit 821cffd5f7102eaa5bf75da1190e0670293e50a9\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Oct 8 02:44:17 2022 +0200\n\n    Add support for static libraries (MCU targets)\n\ncommit 9a2d1bf1beb2c8d8c8bf1ca5154a19acffe2f4f8\nMerge: 1989eb1 c61ab74\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Thu Sep 29 17:49:11 2022 +0200\n\n    Merge pull request #53 from caramelli/master\n    \n    Add support for BT.2020 conversion\n\ncommit c61ab74f402dab12de791a69d40fe8cae2a399bc\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Sep 29 17:49:33 2022 +0200\n\n    Update ChangeLog\n\ncommit 9328df9ddd34e097606b47776a94b73c947fb417\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Sep 29 17:49:25 2022 +0200\n\n    Add support for BT.2020 conversion\n\ncommit 1989eb1c12b329cb618c3c7669d6bfc29f9480d9\nMerge: 4b49dda 0bd4a4f\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed Sep 28 21:38:41 2022 +0200\n\n    Merge pull request #52 from caramelli/master\n    \n    Direct/Interface: Ignore character case for 'default-interface-implementation' option\n\ncommit 0bd4a4f14ba57a27cfbd2767eaa1329405aaa574\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Sep 28 21:08:59 2022 +0200\n\n    Update ChangeLog\n\ncommit a31867801de215e6f92c0fbaf1f192d454784846\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Sep 28 21:08:37 2022 +0200\n\n    Direct/Interface: Ignore character case for 'default-interface-implementation' option\n\ncommit 4b49dda3e337774f04ff77773afadcb409610f94\nMerge: 4260493 e613839\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sat Sep 24 11:36:15 2022 +0200\n\n    Merge pull request #51 from caramelli/master\n    \n    Add dfb_colorspace_parse()\n\ncommit e613839786d0e9e48828f50bd1a3e06e887f4ac1\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Sep 24 11:24:38 2022 +0200\n\n    Update ChangeLog\n\ncommit 58b530ab60abe2fe5b7ba32a7f9fa9fc80d5efdb\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Sep 24 11:24:08 2022 +0200\n\n    Add dfb_colorspace_parse()\n\ncommit 4260493757d59f0fe750fa6ade2397247bcf1dce\nMerge: 002b6f3 9de9d06\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Fri Sep 16 08:57:22 2022 +0200\n\n    Merge pull request #50 from caramelli/master\n    \n    Direct/Stream: Add file_wait()\n\ncommit 9de9d06d1a7f58ab5eb468373cb10a3dba566f93\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Fri Sep 16 08:24:15 2022 +0200\n\n    Update ChangeLog\n\ncommit 1694795f34e698b7544f86d688fcec6613666ab4\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Fri Sep 16 08:24:03 2022 +0200\n\n    Direct/Stream: Add file_wait()\n\ncommit 002b6f331a2b202359d601fc4c3425b7e9307449\nMerge: ad438fc fc9ce01\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Thu Sep 15 10:11:30 2022 +0200\n\n    Merge pull request #49 from caramelli/master\n    \n    Add support for BT.709 conversion\n\ncommit fc9ce013b85b514843a6962140ab668a55d4af70\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Sep 15 10:11:17 2022 +0200\n\n    Update ChangeLog\n\ncommit 0d188b62f3519fcdd1ee100bc992414d60dfaff6\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Sep 15 10:11:04 2022 +0200\n\n    Add support for BT.709 conversion\n\ncommit ad438fce3601e86658e72e4f795bec187014ef4f\nMerge: 4bfa300 46ee720\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed Sep 7 12:55:18 2022 +0200\n\n    Merge pull request #48 from caramelli/master\n    \n    Add support for NV24 and NV42 video format\n\ncommit 46ee7207cf3678fea84f2ea96dbc58842069b5fc\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Sep 7 12:45:53 2022 +0200\n\n    Update ChangeLog\n\ncommit ccd58c3e9c96f964a01f9c4937381c6ce6cad54c\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Sep 7 12:45:35 2022 +0200\n\n    Add support for NV24 and NV42 video format\n\ncommit 4bfa300a8f25334d29815cca44d594382b7b2c2e\nMerge: 0c0a38c 16623ff\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Sep 5 11:21:07 2022 +0200\n\n    Merge pull request #47 from caramelli/master\n    \n    Font/DGIFF: return DFB_INVARG if height not set in font description\n\ncommit 16623ff93089d404505d9279d3247c27a0611a0c\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Sep 5 11:16:18 2022 +0200\n\n    Update ChangeLog\n\ncommit 80f94b0867308ce373a1c4ffd2dbc33d300adf34\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Sep 5 11:16:03 2022 +0200\n\n    Font/DGIFF: return DFB_INVARG if height not set in font description\n\ncommit 0c0a38cd0dc67a8fb254b1ca7ff4913222d038b8\nMerge: 0b9984b 396d28e\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Thu Sep 1 09:00:50 2022 +0200\n\n    Merge pull request #46 from caramelli/master\n    \n    Add support for YVU 4:4:4 planar format\n\ncommit 396d28e145e0f205718861e4d4ee5376319d80dc\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Sep 1 08:58:36 2022 +0200\n\n    Update ChangeLog\n\ncommit badf1d0b52ea7e6d39070dcd68c968dd0ed9f5fa\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Sep 1 08:58:29 2022 +0200\n\n    Add support for YVU 4:4:4 planar format\n\ncommit 0b9984b5d680d48422badff6f36f3439c806d3f4\nMerge: eb7ab25 dea029a\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed Aug 24 13:38:14 2022 +0200\n\n    Merge pull request #45 from caramelli/master\n    \n    Add support for YUV 4:2:2 planar format\n\ncommit dea029adcb4daf103956aa73ebd32c57db400596\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Aug 24 13:08:55 2022 +0200\n\n    Update ChangeLog\n\ncommit a7bcf7475493700e166f44ed5307105eabc0676e\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Aug 24 13:04:37 2022 +0200\n\n    Add support for YUV 4:2:2 planar format\n\ncommit eb7ab25c193f90743553e6e09724756723348038\nMerge: c750bb9 1d99b8a\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sun Aug 21 11:09:20 2022 +0200\n\n    Merge pull request #44 from caramelli/master\n    \n    drmkms: Remove libkms dependency\n\ncommit 1d99b8a946dfbb4ed6011380448738a78fb49272\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sun Aug 21 10:56:22 2022 +0200\n\n    Update ChangeLog\n\ncommit 958aab760292281eff4ca41d3de11a8581fa45ef\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sun Aug 21 10:08:11 2022 +0200\n\n    drmkms: Remove libkms dependency\n\ncommit c750bb98c76191e8149e501db3d408175983d30a\nMerge: 33c7613 2690e4b\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sun Aug 14 09:11:37 2022 +0200\n\n    Merge pull request #43 from caramelli/master\n    \n    Core_Resource_AddIdentity(): if (call_owner != fusion_id), return DFB_FAILURE\n\ncommit 2690e4bfcca798b6f183a07cbe038b4b4f105c34\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sun Aug 14 09:10:10 2022 +0200\n\n    Core_Resource_AddIdentity(): if (call_owner != fusion_id), return DFB_FAILURE\n\ncommit 33c7613704c0055019d6085dbddcd5b972fb1c9f\nMerge: e629f8b 402acc7\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Thu Aug 11 07:16:42 2022 +0200\n\n    Merge pull request #41 from caramelli/master\n    \n    Core/LayerContext: Add dfb_layer_context_set_cursor_shape() and dfb_layer_context_get_cursor_shape()\n\ncommit 402acc7c68497321ad732d4c8594df63bb7f30e2\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Aug 11 07:10:26 2022 +0200\n\n    Update ChangeLog\n\ncommit 5c309b21c5094d540f3835d37ee17f3dff8cfe68\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Aug 11 07:10:17 2022 +0200\n\n    Core/LayerContext: Add dfb_layer_context_set_cursor_shape() and dfb_layer_context_get_cursor_shape()\n\ncommit e629f8baefc649b0488846992ffea1f9b442676b\nMerge: 61ceb79 462e44a\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Tue Aug 9 03:55:00 2022 +0200\n\n    Merge pull request #40 from caramelli/master\n    \n    IDirectFBWindow: by default the cursor surface is not set => cursor_flags = DWCF_INVISIBLE\n\ncommit 462e44a28259d2ca2947142486cf5ce51cde2ed5\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Tue Aug 9 03:10:42 2022 +0200\n\n    Update ChangeLog\n\ncommit db66ecd667499014531a3a553c1c5d93acc9b414\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Tue Aug 9 03:09:24 2022 +0200\n\n    IDirectFBWindow: by default the cursor surface is not set => cursor_flags = DWCF_INVISIBLE\n\ncommit 61ceb79564a81905c5521018892c5816e9d9a4af\nMerge: 4a08b68 5dab035\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Fri Aug 5 09:28:21 2022 +0200\n\n    Merge pull request #39 from caramelli/master\n    \n    IDirectFBDisplayLayer: SetCursorShape() accept NULL for shape to restore default cursor\n\ncommit 5dab03540a293328363f6484a0170d37468cffcd\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Fri Aug 5 09:27:45 2022 +0200\n\n    Update ChangeLog\n\ncommit b603d612311b99c55ef94d732b5048e74dc1dde8\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Fri Aug 5 09:27:37 2022 +0200\n\n    IDirectFBDisplayLayer: SetCursorShape() accept NULL for shape to restore default cursor\n\ncommit 4a08b6867fb69a5850bda36f3362591dbe632f8a\nMerge: 0377501 04f63f2\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Thu Aug 4 16:43:22 2022 +0200\n\n    Merge pull request #38 from caramelli/master\n    \n    Core/WindowStack: unused CoreDFB object in dfb_windowstack_cursor_enable()\n\ncommit 04f63f29661b63385fff8f4b5dad010b7f74a674\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Aug 4 16:11:48 2022 +0200\n\n    Update ChangeLog\n\ncommit 2c23979f3e978567fbc210af941d943fd91d3d6c\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Aug 4 16:10:24 2022 +0200\n\n    Core/WindowStack: unused CoreDFB object in dfb_windowstack_cursor_enable()\n\ncommit 0377501c0eb71f6d96342b57a63bfe41b6d8e663\nMerge: 39c7500 1d5a410\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sun Jul 17 11:45:10 2022 +0200\n\n    Merge pull request #37 from caramelli/master\n    \n    IDirectFBInputDevice: unused buttonmask, locks, modifiers...\n\ncommit 1d5a4109ce66101ca6d3e55c1fde2b23ec69dde8\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sun Jul 17 11:43:12 2022 +0200\n\n    IDirectFBInputDevice: unused buttonmask, locks, modifiers...\n\ncommit 39c75006b18de38e845ffbec66856ddc18c23136\nMerge: 7c956f6 e2c1690\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sun Jun 26 07:49:54 2022 +0200\n\n    Merge pull request #36 from caramelli/master\n    \n    WM/Default: Set the shape of the cursor bound to a window\n\ncommit e2c16907872af39a4ce53c4bce1318d563772caa\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sun Jun 26 07:42:30 2022 +0200\n\n    WM/Default: Set the shape of the cursor bound to a window\n\ncommit 7c956f69fc624616e3f3a4b0e95dc82bf865cb79\nMerge: 23cf9e4 508fc28\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Fri Jun 24 18:45:11 2022 +0200\n\n    Merge pull request #35 from caramelli/master\n    \n    Restore dfb_clip_edges() as a public function\n\ncommit 508fc2822a14b43ae660beb4a209e9a24f6ecc64\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Fri Jun 24 18:43:14 2022 +0200\n\n    Restore dfb_clip_edges() as a public function\n\ncommit 23cf9e4e0016c6ff0cb2c3edf0b8a77857a827d0\nMerge: 45da19c fafb9ad\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Thu Jun 2 15:12:22 2022 +0200\n\n    Merge pull request #33 from caramelli/master\n    \n    Add DSI to DFBScreenEncoderDescription\n\ncommit fafb9adbc80b5dae6ca0e92f29002d1ff46e643d\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Jun 2 15:08:30 2022 +0200\n\n    Update ChangeLog\n\ncommit 9439817cec072630c900eaf4dfbebfea82634c10\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Jun 2 15:08:23 2022 +0200\n\n    Add DSI to DFBScreenEncoderDescription\n\ncommit 45da19c04a67004f0228ad59b68b7975ca821dc9\nMerge: e019fbd f91877e\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed Jun 1 12:41:38 2022 +0200\n\n    Merge pull request #32 from caramelli/master\n    \n    Add support for multi-touch input device\n\ncommit f91877ed968907248c64e06aa9e9640bc0c3a4e2\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Jun 1 11:41:15 2022 +0200\n\n    Update ChangeLog\n\ncommit 6d8293dc6d4684e77c9aef4bae2898354b85dd23\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Jun 1 11:40:36 2022 +0200\n\n    Add support for multi-touch input device\n\ncommit e019fbd1be6683f608d861472e7f43caaede6a3b\nMerge: 2537495 bbf1c7b\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sat May 14 12:28:55 2022 +0200\n\n    Merge pull request #31 from caramelli/master\n    \n    Core/Layers: Increase the maximum number of layers\n\ncommit bbf1c7b4adb4b87f31675efbb6676e9bdd1ceb26\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat May 14 12:27:36 2022 +0200\n\n    Update ChangeLog\n\ncommit 7b7443a96e050fcf62bf0f8c2ebedd0aba81c4b3\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat May 14 12:27:23 2022 +0200\n\n    Core/Layers: Increase the maximum number of layers\n\ncommit 2537495e4fc014168b9249dd367e6d954327aea3\nMerge: 00aeac6 b7e82e1\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed May 11 09:56:46 2022 +0200\n\n    Merge pull request #30 from caramelli/master\n    \n    Fix issue with preallocated surfaces when application is slave\n\ncommit b7e82e1ae52992b7207b1ef6ac8326253ac42b75\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed May 11 09:55:25 2022 +0200\n\n    Update ChangeLog\n\ncommit 6e0a7e205fafe9f8b409e57b28f8390d05ed2945\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed May 11 09:55:01 2022 +0200\n\n    Fix issue with preallocated surfaces when application is slave\n\ncommit 00aeac631fca9a206270740ad166349b321feb90\nMerge: 98d4278 c75e202\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Tue May 3 17:31:49 2022 +0200\n\n    Merge pull request #29 from caramelli/master\n    \n    DFVFF: Add missing DIRECT_DEALLOCATE_INTERFACE( thiz )\n\ncommit c75e20207b9044f671c45829ce1ebd76b9fee790\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Tue May 3 17:30:29 2022 +0200\n\n    Update ChangeLog\n\ncommit 92f23cc01a45183d7022c97fbc2c66baea0b748a\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Tue May 3 17:30:02 2022 +0200\n\n    DFVFF: Add missing DIRECT_DEALLOCATE_INTERFACE( thiz )\n\ncommit 98d4278476ccaa7a787721cec30e503c23f84bf2\nMerge: 35a7c6b 291ace5\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sun May 1 09:31:40 2022 +0200\n\n    Merge pull request #28 from caramelli/master\n    \n    Fix uninitialised byte(s)\n\ncommit 291ace5a7fa6f0dc67ed37683513044331702be1\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sun May 1 09:30:52 2022 +0200\n\n    Fix uninitialised byte(s)\n\ncommit 35a7c6ba5300582218d323eca562ffc7d5537335\nMerge: 19049c5 5d32b0b\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sat Apr 30 14:25:32 2022 +0200\n\n    Merge pull request #27 from caramelli/master\n    \n    drmkms: Management of connectors not bound to an encoder\n\ncommit 5d32b0b88a0bd0be7d29d851ebffb48db31dccb1\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Sat Apr 30 14:23:36 2022 +0200\n\n    drmkms: Management of connectors not bound to an encoder\n\ncommit 19049c5d29210551d8626d30c307ce140573db30\nMerge: 1f2a613 34b8225\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Fri Apr 29 18:41:00 2022 +0200\n\n    Merge pull request #26 from caramelli/master\n    \n    Add -lrt for compatibility with old glibc\n\ncommit 34b8225b7c75074a87c50adef1ceb4a29a384fee\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Fri Apr 29 18:37:46 2022 +0200\n\n    Add -lrt for compatibility with old glibc\n\ncommit 1f2a613206dc1ddd7ed301f79468d5b3397ea11f\nMerge: d90c877 724b2f2\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Thu Apr 28 18:14:17 2022 +0200\n\n    Merge pull request #25 from caramelli/master\n    \n    Fix palette index check in InitLayers()\n\ncommit 724b2f259d5871485ec12aee5a5977303317c560\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Apr 28 18:12:00 2022 +0200\n\n    Fix palette index check in InitLayers()\n\ncommit d90c8770e1b844fcd4698592a2281b5a749ddce7\nMerge: 6b74bc4 3a428e9\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Thu Apr 28 14:18:15 2022 +0200\n\n    Merge pull request #24 from caramelli/master\n    \n    readdir_r() is deprecated\n\ncommit 3a428e985c2320b989921b1d5b0aaa846d8fe04f\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Thu Apr 28 14:18:22 2022 +0200\n\n    readdir_r() is deprecated\n\ncommit 6b74bc443cdcc1c1127581bbc1b02ed1fec16bf7\nMerge: 9d0781a 0505492\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed Mar 30 19:13:40 2022 +0200\n\n    Merge pull request #22 from caramelli/master\n    \n    Fix SYSCONFDIR\n\ncommit 0505492baf1b3abb4b2e08c07118a3c1d5161ec5\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Mar 30 19:09:28 2022 +0200\n\n    Update ChangeLog\n\ncommit 7ac237d1be6517acbc97b03dc85aa775e12dd484\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Mar 30 19:08:00 2022 +0200\n\n    Fix SYSCONFDIR\n\ncommit 9d0781a02e700e09bc7e7ae5fa4ffa1050950e28\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Feb 28 20:00:45 2022 +0100\n\n    build: Fix issues with build order and directfb_strings\n\ncommit 9406153d9dc1cdda12146afdd63e3fd0330b587b\nAuthor: Daniel Palmer <daniel@0x0f.com>\nDate:   Sun Feb 27 12:56:12 2022 +0900\n\n    build: Fix issues with build order and directfb_strings\n    \n    The header generated by directfb_strings is used in other places.\n    If the build is done in parallel and directfb_strings hasn't completed\n    yet the build will fail.\n    \n    Add directfb_strings as an input to the places that need it so that\n    it always happens before it's needed.\n\ncommit 4d1418f50f039cd18363fe58a6b75393eca93316\nAuthor: Daniel Palmer <daniel@0x0f.com>\nDate:   Thu Feb 17 22:25:42 2022 +0900\n\n    gfx: generic: Add NEON assembly support\n    \n    At some point Linaro added NEON assembly for generic\n    graphics. It looks like it never got upstreamed.\n    \n    This pulls in their assembly and wires it in the\n    same way MMX assembly is.\n    \n    Link: https://blueprints.launchpad.net/linaro-multimedia-project/+spec/engr-multimedia-directfb-neon-optimization\n\ncommit 30e3ebe19e9b94a9fedba565fa2b55de30f98cbc\nMerge: c3aa9c0 9f6b8f4\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Feb 14 11:13:38 2022 +0100\n\n    Merge pull request #17 from fifteenhex/valgrindfixes_20220214\n    \n    core: core: Fix use after free when calling fusion_shm_pool_destroy()\n\ncommit 9f6b8f45d2ac4bb6dcd15c3d0d6db1fe356aea4d\nAuthor: Daniel Palmer <daniel@0x0f.com>\nDate:   Mon Feb 14 18:06:15 2022 +0900\n\n    core: core: Fix use after free when calling fusion_shm_pool_destroy()\n    \n    fusion_shm_pool_destory() is called with shared->shmpool as it's\n    second argument but shared has just been freed in the in previous\n    line.\n    \n    Pull shared->shmpool out into a local variable and use that instead.\n\ncommit c3aa9c056209349dee935d69f2ca9b593687bcea\nMerge: 1209d65 c51e925\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Sun Feb 13 22:50:06 2022 +0100\n\n    Merge pull request #16 from fifteenhex/valgrind_fixes_20220213\n    \n    Valgrind fixes 20220213\n\ncommit c51e9255f05f599a2b5e8a0b2c62beeebdee8d56\nAuthor: Daniel Palmer <daniel@0x0f.com>\nDate:   Sat Feb 12 22:55:32 2022 +0900\n\n    input: linux: Initialise input event in set_led()\n    \n    Not all the fields in the struct are initialised so the\n    struct should be allocated with initialisation.\n\ncommit bf5d6d23050bb15d3d81a50d86b128d1de54e70f\nAuthor: Daniel Palmer <daniel@0x0f.com>\nDate:   Sat Feb 12 21:08:47 2022 +0900\n\n    system: drmkms: vt: Initialise vt_mode struct.\n    \n    Not all of the fields in vt_mode struct are filled so we will\n    be passing uninitilised data unless we ask for it to be zero initialised.\n\ncommit 1209d657c2534c6175477177cf3ef5fdb0c33634\nMerge: b3e66e4 75d2237\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Fri Feb 11 14:14:32 2022 +0100\n\n    Merge pull request #14 from fifteenhex/valgrind_fixes\n    \n    Valgrind splat fixes\n\ncommit 75d2237fccf638ece90919e3aba393a701f4ebc0\nAuthor: Daniel Palmer <daniel@0x0f.com>\nDate:   Fri Feb 11 11:28:09 2022 +0900\n\n    libdirect: signals: Use mark/sweep to free signal handlers\n    \n    Valgrind is complaining a lot about handlers being accessed after\n    they have been freed. To make this easier to debug refactor freeing\n    the actually memory into a single location and change the remove\n    function to just mark the handler as dead.\n\ncommit 270cd1b150e71d8d3d8f82c676db8915fdcc9cf5\nAuthor: Daniel Palmer <daniel@0x0f.com>\nDate:   Fri Feb 11 10:38:44 2022 +0900\n\n    libdirect: os: linux: thread: Fix passing of null pointer to prctl\n    \n    prctl(PR_GET_NAME, arg2, ...) expects a pointer to a 16 byte buffer\n    in arg2. Currently the code is checking if thread->name is null\n    and then calling prctl(PR_GET_NAME, thread->name, ...) if it is.\n    This results in a null pointer always being passed to prctl().\n    \n    Put a 16 byte buffer on the stack, pass that to prctl() if thread->name\n    is null, then copy the result into thread->name.\n\ncommit b3e66e4b8b78d443d9920f12b385e5c580f56570\nMerge: ef3583f ff02c1f\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed Feb 9 08:00:35 2022 +0100\n\n    Merge pull request #12 from caramelli/master\n    \n    Add support for NV61\n\ncommit ff02c1f7058a84d99c612fafdff7b02e83474e3f\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Feb 9 07:57:36 2022 +0100\n\n    Update ChangeLog\n\ncommit f6358663a118e8f3bf04c4a87442fd22e58efd5a\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Feb 9 07:57:14 2022 +0100\n\n    Add support for NV61\n\ncommit ef3583fd6d9484019dece42dc18f528b053f6beb\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Tue Feb 8 14:58:04 2022 +0100\n\n    Update ChangeLog\n\ncommit 521eebe4042d988c04930e0e148cf41ac3db085c\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Tue Feb 8 14:57:43 2022 +0100\n\n    Replace SIGUNUSED with the standard SIGSYS signal\n\ncommit ad206f371b4ad5f14e25ac6ab3906f226061eefc\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Tue Feb 8 14:54:06 2022 +0100\n\n    Update ChangeLog\n\ncommit 33de3256220022401644ffa264ccfdd6d7d50e00\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Tue Feb 8 14:51:50 2022 +0100\n\n    Declare CorePart variables with extern\n\ncommit c1df2aa105be7f24b99b205c92f31147c7ea9681\nMerge: 5ec744b 4f95de7\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed Feb 2 10:00:21 2022 +0100\n\n    Merge pull request #8 from caramelli/master\n    \n    Add pixel format conversion functions\n\ncommit 4f95de7d778bbcd5c3910945f1903b92e748989c\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Feb 2 09:59:21 2022 +0100\n\n    Update ChangeLog\n\ncommit d404af89d1f55a98c091417531be6f1e8f5d451e\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Feb 2 09:59:07 2022 +0100\n\n    Add pixel format conversion functions\n\ncommit 5ec744bbfaad38838051d41bad95d8159ebee93e\nMerge: dcfa6e8 47be2bd\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Wed Feb 2 09:37:26 2022 +0100\n\n    Merge pull request #7 from caramelli/master\n    \n    Add BT.2020 color space definition\n\ncommit 47be2bd015301a57ad77d2f29a6e0af58442bfd6\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Feb 2 09:34:50 2022 +0100\n\n    Update ChangeLog\n\ncommit d75e3b98b64622ffb6cab2d48c75900feac2a1e6\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Wed Feb 2 09:33:49 2022 +0100\n\n    Add BT.2020 color space definition\n\ncommit dcfa6e8bdfce590bb4e2a95beb17fa30c9f23a22\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Tue Jan 18 21:56:00 2022 +0100\n\n    DirectFB2 at FOSDEM 2022\n\ncommit cefad0b1bbda67ae2414e99c140c8234e96c366f\nMerge: e8e8bfc 1de2c28\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Tue Jan 18 21:53:06 2022 +0100\n\n    Merge pull request #4 from caramelli/master\n    \n    DFVFF: Restart from the beginning after stopping\n\ncommit 1de2c28a29b473832202d90b0d7f137bef7e4831\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Tue Jan 18 21:50:39 2022 +0100\n\n    Update ChangeLog\n\ncommit ed3efb3ada2e6bb6ef7d00e72c08f29a64e47808\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Tue Jan 18 21:44:42 2022 +0100\n\n    DFVFF: Restart from the beginning after stopping\n\ncommit e8e8bfcc7bdbffbbcc74e5ca55e50cf2fa8933b9\nMerge: 33e96c5 84697e1\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Tue Jan 11 06:28:27 2022 +0100\n\n    Merge pull request #3 from caramelli/master\n    \n    DFVFF: no interlaced support\n\ncommit 84697e114951385b0d262811b59b9055b5c796c4\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Tue Jan 11 06:24:40 2022 +0100\n\n    Update ChangeLog\n\ncommit decbeb69a473d30244958f29b1d45e6131ad3beb\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Tue Jan 11 06:23:41 2022 +0100\n\n    DFVFF: no interlaced support\n\ncommit 33e96c5c8030c1b37448bd43ea115f082cf056a8\nMerge: ac69e79 5a49ce4\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Jan 10 09:51:26 2022 +0100\n\n    Merge pull request #2 from caramelli/master\n    \n    Restore DirectFBGL interface version\n\ncommit 5a49ce419408b0c5e96b9c0c4a630f85e3155763\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Jan 10 09:43:33 2022 +0100\n\n    Update ChangeLog\n\ncommit b6c80b871c6fc4a76824d86b2b58ab52d27fb451\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Jan 10 09:38:34 2022 +0100\n\n    Restore DirectFBGL interface version\n\ncommit ac69e79742b633ef553da667a6d68308d7dedd89\nMerge: 39e2044 99a4109\nAuthor: DirectFB2 <80045286+directfb2@users.noreply.github.com>\nDate:   Mon Dec 6 15:45:17 2021 +0100\n\n    Merge pull request #1 from caramelli/master\n    \n    Revival of DirectFB\n\ncommit 99a41095baa5d84c39b035057b26ec1b51d080c5\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Dec 6 15:42:37 2021 +0100\n\n    Add ChangeLog\n\ncommit 84f00f65d763389c0fba5a28d150c418c8ce9990\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Dec 6 15:42:23 2021 +0100\n\n    Revival of DirectFB\n\ncommit 39e204404329144622d26586587657f6a4b6fb2c\nAuthor: Nicolas Caramelli <caramelli.devel@gmail.com>\nDate:   Mon Dec 6 15:37:21 2021 +0100\n\n    Initial revision\n"
  },
  {
    "path": "INSTALL",
    "content": "Installation Instructions\n=========================\n\nDirectFB2 is built using Meson.\n\nYou will also need a C compiler and fluxcomp for converting .flux interface description files to .c files.\n\nWith the default build of DirectFB2, only one application can be running (single application core). However you have the\noption to use the multi application core which allows multiple applications to run at the same time within a session.\nThe applications then communicate through a layer called Fusion implemented either completely in user space, or by\nrelying on the linux-fusion kernel module (which implements the critical parts of Fusion).\n\nTo build the single application core:\n\n  $ meson setup build/\n\nTo build the multi application core with Fusion implemented completely in user space:\n\n  $ meson setup -Dmulti=true build/\n\nor with Fusion based on the linux-fusion kernel module:\n\n  $ meson setup -Dmulti=true -Dmulti-kernel=true build/\n\nLinux\n=====\n\nOn Linux, start the build with:\n\n  $ meson compile -C build/\n\nAnd install DirectFB2 using:\n\n  $ meson install -C build/\n\nNext, install and run DirectFB applications, such as those available in DirectFB-examples.\n\nNuttX\n=====\n\nOn NuttX, copy the DirectFB2 directory to your NuttX apps/graphics/ directory.\n\nA defconfig file for the NuttX simulator is available.\nIt must be placed in a directory nuttx/boards/sim/sim/sim/configs/directfb/\n\nAdd a DirectFB application, such as those available in DirectFB-examples.\n\nConfigure the simulator:\n\n  ./tools/configure.sh sim:directfb\n\nAnd start the build with:\n\n  $ make\n\nRun the simulator using:\n\n  $ ./nuttx\n"
  },
  {
    "path": "Kconfig",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\nmenuconfig GRAPHICS_DIRECTFB2\n\tbool \"DirectFB2\"\n\tdefault n\n\t---help---\n\t\tEnable support for DirectFB2.\n"
  },
  {
    "path": "Make.defs",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\nifneq ($(CONFIG_GRAPHICS_DIRECTFB2),)\nCONFIGURED_APPS += $(APPDIR)/graphics/DirectFB2\n\nCFLAGS += ${INCDIR_PREFIX}$(APPDIR)/graphics/DirectFB2/include\nCFLAGS += ${INCDIR_PREFIX}$(APPDIR)/graphics/DirectFB2/lib\nendif\n"
  },
  {
    "path": "Makefile",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\ninclude $(APPDIR)/Make.defs\n\nCFLAGS += -I.\nCFLAGS += -Isrc\n\nCFLAGS += -DBUILDTIME=\\\"$(shell date -u \"+%Y-%m-%d\\ %H:%M\")\\\"\nCFLAGS += -DSYSCONFDIR=\\\"/etc\\\"\n\nDIRECT_CSRCS  = lib/direct/clock.c\nDIRECT_CSRCS += lib/direct/conf.c\nDIRECT_CSRCS += lib/direct/debug.c\nDIRECT_CSRCS += lib/direct/direct.c\nDIRECT_CSRCS += lib/direct/direct_result.c\nDIRECT_CSRCS += lib/direct/hash.c\nDIRECT_CSRCS += lib/direct/init.c\nDIRECT_CSRCS += lib/direct/interface.c\nDIRECT_CSRCS += lib/direct/log.c\nDIRECT_CSRCS += lib/direct/log_domain.c\nDIRECT_CSRCS += lib/direct/map.c\nDIRECT_CSRCS += lib/direct/mem.c\nDIRECT_CSRCS += lib/direct/memcpy.c\nDIRECT_CSRCS += lib/direct/messages.c\nDIRECT_CSRCS += lib/direct/modules.c\nDIRECT_CSRCS += lib/direct/result.c\nDIRECT_CSRCS += lib/direct/stream.c\nDIRECT_CSRCS += lib/direct/system.c\nDIRECT_CSRCS += lib/direct/thread.c\nDIRECT_CSRCS += lib/direct/trace.c\nDIRECT_CSRCS += lib/direct/util.c\nDIRECT_CSRCS += lib/direct/os/nuttx/clock.c\nDIRECT_CSRCS += lib/direct/os/nuttx/filesystem.c\nDIRECT_CSRCS += lib/direct/os/nuttx/log.c\nDIRECT_CSRCS += lib/direct/os/nuttx/mem.c\nDIRECT_CSRCS += lib/direct/os/nuttx/mutex.c\nDIRECT_CSRCS += lib/direct/os/nuttx/signals.c\nDIRECT_CSRCS += lib/direct/os/nuttx/system.c\nDIRECT_CSRCS += lib/direct/os/nuttx/thread.c\n\nFUSION_CSRCS  = lib/fusion/arena.c\nFUSION_CSRCS += lib/fusion/call.c\nFUSION_CSRCS += lib/fusion/conf.c\nFUSION_CSRCS += lib/fusion/fusion.c\nFUSION_CSRCS += lib/fusion/hash.c\nFUSION_CSRCS += lib/fusion/init.c\nFUSION_CSRCS += lib/fusion/lock.c\nFUSION_CSRCS += lib/fusion/object.c\nFUSION_CSRCS += lib/fusion/reactor.c\nFUSION_CSRCS += lib/fusion/ref.c\nFUSION_CSRCS += lib/fusion/shmalloc.c\nFUSION_CSRCS += lib/fusion/vector.c\nFUSION_CSRCS += lib/fusion/shm/fake.c\n\nDIRECTFB_CSRCS  = src/directfb.c\nDIRECTFB_CSRCS += src/directfb_result.c\nDIRECTFB_CSRCS += src/idirectfb.c\nDIRECTFB_CSRCS += src/init.c\nDIRECTFB_CSRCS += src/core/CoreDFB_real.c\nDIRECTFB_CSRCS += src/core/CoreGraphicsState_real.c\nDIRECTFB_CSRCS += src/core/CoreGraphicsStateClient.c\nDIRECTFB_CSRCS += src/core/CoreInputDevice_real.c\nDIRECTFB_CSRCS += src/core/CoreLayer_real.c\nDIRECTFB_CSRCS += src/core/CoreLayerContext_real.c\nDIRECTFB_CSRCS += src/core/CoreLayerRegion_real.c\nDIRECTFB_CSRCS += src/core/CorePalette_real.c\nDIRECTFB_CSRCS += src/core/CoreScreen_real.c\nDIRECTFB_CSRCS += src/core/CoreSlave_real.c\nDIRECTFB_CSRCS += src/core/CoreSurface_real.c\nDIRECTFB_CSRCS += src/core/CoreSurfaceAllocation_real.c\nDIRECTFB_CSRCS += src/core/CoreSurfaceClient_real.c\nDIRECTFB_CSRCS += src/core/CoreWindow_real.c\nDIRECTFB_CSRCS += src/core/CoreWindowStack_real.c\nDIRECTFB_CSRCS += src/core/clipboard.c\nDIRECTFB_CSRCS += src/core/colorhash.c\nDIRECTFB_CSRCS += src/core/core.c\nDIRECTFB_CSRCS += src/core/core_parts.c\nDIRECTFB_CSRCS += src/core/fonts.c\nDIRECTFB_CSRCS += src/core/gfxcard.c\nDIRECTFB_CSRCS += src/core/graphics_state.c\nDIRECTFB_CSRCS += src/core/input.c\nDIRECTFB_CSRCS += src/core/layer_context.c\nDIRECTFB_CSRCS += src/core/layer_control.c\nDIRECTFB_CSRCS += src/core/layer_region.c\nDIRECTFB_CSRCS += src/core/layers.c\nDIRECTFB_CSRCS += src/core/local_surface_pool.c\nDIRECTFB_CSRCS += src/core/palette.c\nDIRECTFB_CSRCS += src/core/prealloc_surface_pool_bridge.c\nDIRECTFB_CSRCS += src/core/prealloc_surface_pool.c\nDIRECTFB_CSRCS += src/core/screen.c\nDIRECTFB_CSRCS += src/core/screens.c\nDIRECTFB_CSRCS += src/core/state.c\nDIRECTFB_CSRCS += src/core/surface.c\nDIRECTFB_CSRCS += src/core/surface_allocation.c\nDIRECTFB_CSRCS += src/core/surface_buffer.c\nDIRECTFB_CSRCS += src/core/surface_client.c\nDIRECTFB_CSRCS += src/core/surface_core.c\nDIRECTFB_CSRCS += src/core/surface_pool.c\nDIRECTFB_CSRCS += src/core/surface_pool_bridge.c\nDIRECTFB_CSRCS += src/core/system.c\nDIRECTFB_CSRCS += src/core/windows.c\nDIRECTFB_CSRCS += src/core/windowstack.c\nDIRECTFB_CSRCS += src/core/wm.c\nDIRECTFB_CSRCS += src/display/idirectfbdisplaylayer.c\nDIRECTFB_CSRCS += src/display/idirectfbpalette.c\nDIRECTFB_CSRCS += src/display/idirectfbscreen.c\nDIRECTFB_CSRCS += src/display/idirectfbsurface.c\nDIRECTFB_CSRCS += src/display/idirectfbsurfaceallocation.c\nDIRECTFB_CSRCS += src/display/idirectfbsurface_layer.c\nDIRECTFB_CSRCS += src/display/idirectfbsurface_window.c\nDIRECTFB_CSRCS += src/gfx/clip.c\nDIRECTFB_CSRCS += src/gfx/convert.c\nDIRECTFB_CSRCS += src/gfx/util.c\nDIRECTFB_CSRCS += src/gfx/generic/generic.c\nDIRECTFB_CSRCS += src/gfx/generic/generic_blit.c\nDIRECTFB_CSRCS += src/gfx/generic/generic_draw_line.c\nDIRECTFB_CSRCS += src/gfx/generic/generic_fill_rectangle.c\nDIRECTFB_CSRCS += src/gfx/generic/generic_stretch_blit.c\nDIRECTFB_CSRCS += src/gfx/generic/generic_texture_triangles.c\nDIRECTFB_CSRCS += src/gfx/generic/generic_util.c\nDIRECTFB_CSRCS += src/input/idirectfbeventbuffer.c\nDIRECTFB_CSRCS += src/input/idirectfbinputdevice.c\nDIRECTFB_CSRCS += src/media/idirectfbdatabuffer.c\nDIRECTFB_CSRCS += src/media/idirectfbdatabuffer_file.c\nDIRECTFB_CSRCS += src/media/idirectfbdatabuffer_memory.c\nDIRECTFB_CSRCS += src/media/idirectfbdatabuffer_streamed.c\nDIRECTFB_CSRCS += src/media/idirectfbfont.c\nDIRECTFB_CSRCS += src/media/idirectfbimageprovider.c\nDIRECTFB_CSRCS += src/media/idirectfbvideoprovider.c\nDIRECTFB_CSRCS += src/misc/conf.c\nDIRECTFB_CSRCS += src/misc/gfx_util.c\nDIRECTFB_CSRCS += src/misc/util.c\nDIRECTFB_CSRCS += src/windows/idirectfbwindow.c\n\nFLUX_CSRCS  = src/core/CoreDFB.c\nFLUX_CSRCS += src/core/CoreGraphicsState.c\nFLUX_CSRCS += src/core/CoreInputDevice.c\nFLUX_CSRCS += src/core/CoreLayer.c\nFLUX_CSRCS += src/core/CoreLayerContext.c\nFLUX_CSRCS += src/core/CoreLayerRegion.c\nFLUX_CSRCS += src/core/CorePalette.c\nFLUX_CSRCS += src/core/CoreSlave.c\nFLUX_CSRCS += src/core/CoreScreen.c\nFLUX_CSRCS += src/core/CoreSurface.c\nFLUX_CSRCS += src/core/CoreSurfaceAllocation.c\nFLUX_CSRCS += src/core/CoreSurfaceClient.c\nFLUX_CSRCS += src/core/CoreWindow.c\nFLUX_CSRCS += src/core/CoreWindowStack.c\nFLUX_HDRS = $(patsubst %.c,%.h,$(FLUX_CSRCS))\n\nCSRCS = $(DIRECT_CSRCS) $(FUSION_CSRCS) $(DIRECTFB_CSRCS) $(FLUX_CSRCS)\n\nCORE_SYSTEM_CSRCS  = systems/nuttxfb/nuttxfb_layer.c\nCORE_SYSTEM_CSRCS += systems/nuttxfb/nuttxfb_screen.c\nCORE_SYSTEM_CSRCS += systems/nuttxfb/nuttxfb_surface_pool.c\nCORE_SYSTEM_CSRCS += systems/nuttxfb/nuttxfb_system.c\nCSRCS += $(CORE_SYSTEM_CSRCS)\n\nINPUT_DRIVER_CSRCS = inputdrivers/nuttx_input/nuttx_input.c\nCSRCS += $(INPUT_DRIVER_CSRCS)\n\nFONT_PROVIDER_CSRCS = interfaces/IDirectFBFont/idirectfbfont_dgiff.c\nCSRCS += $(FONT_PROVIDER_CSRCS)\n\nIMAGE_PROVIDER_CSRCS = interfaces/IDirectFBImageProvider/idirectfbimageprovider_dfiff.c\nCSRCS += $(IMAGE_PROVIDER_CSRCS)\n\nVIDEO_PROVIDER_CSRCS = interfaces/IDirectFBVideoProvider/idirectfbvideoprovider_dfvff.c\nCSRCS += $(VIDEO_PROVIDER_CSRCS)\n\nWINDOW_MANAGER_CSRCS = wm/default/default.c\nCSRCS += $(WINDOW_MANAGER_CSRCS)\n\nconfig.h:\n\t$(Q) echo \"#pragma once\" > $@; \\\n\t\techo \"#define SIZEOF_LONG 8\" >> $@\n\ninclude/directfb_build.h:\n\t$(Q) echo \"#pragma once\" > $@; \\\n\t\techo \"#define FLUXED_ARGS_BYTES 1024\" >> $@\n\ninclude/directfb_keynames.h: include/directfb_keyboard.h\n\t$(Q) ./include/gen_directfb_keynames.sh $^ > $@\n\ninclude/directfb_strings.h: include/directfb.h\n\t$(Q) ./include/gen_directfb_strings.sh $^ > $@\n\ninclude/directfb_version.h:\n\t$(Q) echo \"#pragma once\" > $@; \\\n\t\techo \"#define DIRECTFB_MAJOR_VERSION 2\" >> $@; \\\n\t\techo \"#define DIRECTFB_MICRO_VERSION 0\" >> $@; \\\n\t\techo \"#define DIRECTFB_MINOR_VERSION 0\" >> $@\n\nlib/direct/build.h:\n\t$(Q) echo \"#pragma once\" > $@; \\\n\t\techo \"#define DIRECT_BUILD_CTORS 0\" >> $@; \\\n\t\techo \"#define DIRECT_BUILD_DEBUG 0\" >> $@; \\\n\t\techo \"#define DIRECT_BUILD_DEBUGS 0\" >> $@; \\\n\t\techo \"#define DIRECT_BUILD_DYNLOAD 0\" >> $@; \\\n\t\techo \"#define DIRECT_BUILD_MEMCPY_PROBING 0\" >> $@; \\\n\t\techo \"#define DIRECT_BUILD_NETWORK 0\" >> $@; \\\n\t\techo \"#define DIRECT_BUILD_OS_NUTTX 1\" >> $@; \\\n\t\techo \"#define DIRECT_BUILD_PIPED_STREAM 0\" >> $@; \\\n\t\techo \"#define DIRECT_BUILD_SENTINELS 0\" >> $@; \\\n\t\techo \"#define DIRECT_BUILD_TEXT 1\" >> $@; \\\n\t\techo \"#define DIRECT_BUILD_TRACE 0\" >> $@\n\nlib/fusion/build.h:\n\t$(Q) echo \"#pragma once\" > $@; \\\n\t\techo \"#define FUSION_BUILD_MULTI 0\" >> $@\n\nsrc/build.h:\n\t$(Q) echo \"#pragma once\" > $@; \\\n\t\techo \"#define DFB_SMOOTH_SCALING 1\" >> $@; \\\n\t\techo \"#define DIRECTFB_VERSION_VENDOR \\\"\\\"\" >> $@\n\nFLUXCOMP ?= fluxcomp\nFLUX_ARGS = --call-mode --dispatch-error-abort --identity --include-prefix=core --object-ptrs --static-args-bytes=FLUXED_ARGS_BYTES\n\nsrc/core/%.c: src/core/%.flux\n\t$(FLUXCOMP) $(FLUX_ARGS) -c $^ -o=src/core\n\ncontext:: config.h include/directfb_build.h include/directfb_keynames.h include/directfb_strings.h include/directfb_version.h lib/direct/build.h lib/fusion/build.h src/build.h $(FLUX_CSRCS)\n\ndistclean::\n\t$(call DELFILE, config.h)\n\t$(call DELFILE, include/directfb_build.h)\n\t$(call DELFILE, include/directfb_keynames.h)\n\t$(call DELFILE, include/directfb_strings.h)\n\t$(call DELFILE, include/directfb_version.h)\n\t$(call DELFILE, lib/direct/build.h)\n\t$(call DELFILE, lib/fusion/build.h)\n\t$(call DELFILE, src/build.h)\n\t$(call DELFILE, $(FLUX_CSRCS))\n\t$(call DELFILE, $(FLUX_HDRS))\n\ninclude $(APPDIR)/Application.mk\n"
  },
  {
    "path": "NEWS",
    "content": "2.0.0\n-----\n\nMeson build system\n\nPure C implementation\n\nNo external dependency (except fluxcomp for converting .flux interface description files to .c files)\n\nStatic library support for MCU targets\n\nModularization of the source code, which now only contains:\n  - libdirect / libfusion / libdirectfb core libraries\n  - a generic system module and a generic input driver for supported operating systems:\n      - legacy Linux FBDev or modern DRM/KMS system module and Linux input driver\n      - NuttX Framebuffer system module and NuttX input driver\n  - the default WM module\n  - the DGIFF (DirectFB Glyph Image File Format) font provider\n  - the DFIFF (DirectFB Fast Image File Format) image provider\n  - the DFVFF (DirectFB Fast Video File Format) video provider\n\nSeparate packages for:\n  - additional system modules\n  - additional input drivers\n  - additional WM modules\n  - additional font/image/video providers\n  - GFX drivers (hardware acceleration)\n"
  },
  {
    "path": "README",
    "content": "DirectFB2\n=========\n\nDirectFB2 is a fork of DirectFB, a graphics library which was designed with embedded systems in mind.\n\nLinux and NuttX operating systems are supported.\n\nSee the file INSTALL for installation instructions.\n\nEnjoy!\n"
  },
  {
    "path": "README.md",
    "content": "The DirectFB2 open source project\n---------------------------------\n\nhttps://directfb2.github.io\n\n________________________________________________________________\n\n**2024-04-02** Various font/image/music/video providers available in [DirectFB2-media](https://github.com/directfb2/DirectFB2-media) (can be tested via [DirectFB-media-samples](https://github.com/directfb2/DirectFB-media-samples))\n\n**2023-10-06** OpenGL ES and EGL for DirectFB platform with [SwiftShaderGL-DirectFB](https://github.com/directfb2/SwiftShaderGL-DirectFB) (DirectFBGL accessible via [DirectFBGL-EGL](https://github.com/directfb2/DirectFBGL-EGL))\n\n**2023-07-17** OpenGL software rendering with [DirectFBGL-PortableGL](https://github.com/directfb2/DirectFBGL-PortableGL)\n\n**2023-06-12** Play with [DirectFB-examples](https://github.com/directfb2/DirectFB-examples) and [LiTE-examples](https://github.com/directfb2/LiTE-examples) on MCU devices using available NuttX support\n\n**2023-01-01** Restoring [FusionSound](https://github.com/directfb2/FusionSound2) to add sound in DirectFB apps\n\n**2022-12-02** All platforms supporting generic buffer management can use the [DirectFB2-eglgbm](https://github.com/directfb2/DirectFB2-eglgbm) system module\n\n**2022-11-09** Start Raspberry Pi boards again with [DirectFB2-eglrpi](https://github.com/directfb2/DirectFB2-eglrpi) system module and [DirectFB2-gles2](https://github.com/directfb2/DirectFB2-gles2) GFX driver (HW acceleration)\n\n**2022-10-30** [DFBTerm](https://github.com/directfb2/DFBTerm) and [Projektor](https://github.com/directfb2/Projektor) are DirectFB applications based on LiTE\n\n**2022-08-01** Create embedded UIs on top of DirectFB with [LiTE](https://github.com/directfb2/LiTE)\n\n**2022-06-02** Support multi-touch screens with [DirectFB2-tslib](https://github.com/directfb2/DirectFB2-tslib) or remote controls with [DirectFB2-lirc](https://github.com/directfb2/DirectFB2-lirc)\n\n**2022-02-05** DirectFB2 at [FOSDEM 2022](https://archive.fosdem.org/2022/schedule/event/directfb)\n\n**2021-12-06** Revival of [DirectFB](https://github.com/directfb2/DirectFB2)\n"
  },
  {
    "path": "dfb-update-pkgconfig.in",
    "content": "#!/bin/sh\n#\n#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\nmkpc() {\nif [ \"`echo $DESTDIR@PKGCONFIGDIR@/directfb-$1-*`\" != \"$DESTDIR@PKGCONFIGDIR@/directfb-$1-*\" ]; then\n  REQUIRES_PRIVATE=$(basename -s .pc -a $DESTDIR@PKGCONFIGDIR@/directfb-$1-* | tr '\\n' ' ' | sed 's/ $//')\nfi\n\ncat > $DESTDIR@PKGCONFIGDIR@/directfb-$1.pc << EOF\nName: DirectFB-$1\nDescription: DirectFB $1 modules\nVersion: @VERSION@\nRequires.private: $REQUIRES_PRIVATE\nEOF\n}\n\nmkpc gfxdriver\nmkpc inputdriver\nmkpc interface\nmkpc system\nmkpc wm\n"
  },
  {
    "path": "include/dfiff.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DFIFF_H__\n#define __DFIFF_H__\n\n#include <directfb.h>\n\ntypedef struct {\n     u8                    magic[5]; /* \"DFIFF\" magic */\n\n     u8                    major;    /* Major version number */\n     u8                    minor;    /* Minor version number */\n\n     u8                    flags;\n\n     u32                   width;\n     u32                   height;\n     DFBSurfacePixelFormat format;\n     u32                   pitch;\n} DFIFFHeader;\n\n#endif\n"
  },
  {
    "path": "include/dfvff.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DFVFF_H__\n#define __DFVFF_H__\n\n#include <directfb.h>\n\ntypedef struct {\n     u8                    magic[5];      /* \"DFVFF\" magic */\n\n     u8                    major;         /* Major version number */\n     u8                    minor;         /* Minor version number */\n\n     u8                    flags;\n\n     u32                   width;\n     u32                   height;\n     DFBSurfacePixelFormat format;\n     DFBSurfaceColorSpace  colorspace;\n     u32                   framerate_num;\n     u32                   framerate_den;\n} DFVFFHeader;\n\n#endif\n"
  },
  {
    "path": "include/dgiff.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DGIFF_H__\n#define __DGIFF_H__\n\n#include <directfb.h>\n\ntypedef struct {\n     u8  magic[5];  /* \"DGIFF\" magic */\n\n     u8  major;     /* Major version number */\n     u8  minor;     /* Minor version number */\n\n     u8  flags;\n\n     u32 num_faces;\n\n     u32 __pad;\n} DGIFFHeader;\n\ntypedef struct {\n     s32                     next_face;     /* byte offset from this to next face */\n\n     s32                     size;\n\n     s32                     ascender;\n     s32                     descender;\n     s32                     height;\n\n     s32                     max_advance;\n\n     u32                     pixelformat;\n\n     u32                     num_glyphs;\n     u32                     num_rows;\n\n     DFBSurfaceBlittingFlags blittingflags;\n} DGIFFFaceHeader;\n\ntypedef struct {\n     u32 unicode;\n\n     u32 row;\n\n     s32 offset;\n     s32 width;\n     s32 height;\n\n     s32 left;\n     s32 top;\n     s32 advance;\n} DGIFFGlyphInfo;\n\ntypedef struct {\n     s32 width;\n     s32 height;\n     s32 pitch;\n\n     u32 __pad;\n\n     /* Raw pixel data follows, 'height * pitch' bytes. */\n} DGIFFGlyphRow;\n\n#endif\n"
  },
  {
    "path": "include/directfb.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECTFB_H__\n#define __DIRECTFB_H__\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <direct/interface.h>\n#include <directfb_build.h>\n#include <directfb_keyboard.h>\n\n/*\n * Main interface of DirectFB.\n */\nD_DECLARE_INTERFACE( IDirectFB )\n\n/*\n * Interface to different display outputs, encoders, connector settings, power management and synchronization.\n */\nD_DECLARE_INTERFACE( IDirectFBScreen )\n\n/*\n * Layer interface for configuration, window stack usage or direct surface access, with shared/exclusive context.\n */\nD_DECLARE_INTERFACE( IDirectFBDisplayLayer )\n\n/*\n * Interface to a surface object, being a graphics context for rendering and state control, buffer operations, palette\n * access and sub area translate'n'clip logic.\n */\nD_DECLARE_INTERFACE( IDirectFBSurface )\n\n/*\n * Interface to a surface allocation object, being an actual buffer being allocated for a surface.\n */\nD_DECLARE_INTERFACE( IDirectFBSurfaceAllocation )\n\n/*\n * Interface for read/write access to the colors of a palette object and for cloning it.\n */\nD_DECLARE_INTERFACE( IDirectFBPalette )\n\n/*\n * Input device interface for keymap access, event buffers and state queries.\n */\nD_DECLARE_INTERFACE( IDirectFBInputDevice )\n\n/*\n * Interface to a local event buffer to send/receive events, wait for events, abort waiting or reset buffer.\n */\nD_DECLARE_INTERFACE( IDirectFBEventBuffer )\n\n/*\n * Interface to a window object, controlling appearance and focus, positioning and stacking, event buffers and surface\n * access.\n */\nD_DECLARE_INTERFACE( IDirectFBWindow )\n\n/*\n * Interface to a font provider, getting metrics, measuring strings or single characters, query/choose encodings.\n */\nD_DECLARE_INTERFACE( IDirectFBFont )\n\n/*\n * Interface to an image provider, retrieving information about the image and rendering it to a surface.\n */\nD_DECLARE_INTERFACE( IDirectFBImageProvider )\n\n/*\n * Interface to a video provider for playback with advanced control and basic stream information.\n */\nD_DECLARE_INTERFACE( IDirectFBVideoProvider )\n\n/*\n * Data buffer interface, providing unified access to different kinds of data storage and live feed.\n */\nD_DECLARE_INTERFACE( IDirectFBDataBuffer )\n\n/*\n * OpenGL interface.\n */\nD_DECLARE_INTERFACE( IDirectFBGL )\n\n/**********************************************************************************************************************/\n\n#define DIRECTFB_API\n\n/*\n * A boolean.\n */\ntypedef enum {\n     DFB_FALSE                             = 0,                  /* false */\n     DFB_TRUE                              = !DFB_FALSE          /* true */\n} DFBBoolean;\n\n/*\n * Return code of all interface methods and most functions.\n *\n * Whenever a method has to return any information, it is done\n * via output parameters.\n */\ntypedef enum {\n     /*\n      * Aliases for backward compatibility and uniform look in\n      * DirectFB code.\n      */\n     DFB_OK                                = DR_OK,              /* No error occurred. */\n     DFB_FAILURE                           = DR_FAILURE,         /* A general or unknown error occurred. */\n     DFB_INIT                              = DR_INIT,            /* A general initialization error occurred. */\n     DFB_BUG                               = DR_BUG,             /* Internal bug or inconsistency has been detected. */\n     DFB_DEAD                              = DR_DEAD,            /* Interface has a zero reference counter (available in\n                                                                    debug mode). */\n     DFB_UNSUPPORTED                       = DR_UNSUPPORTED,     /* The requested operation or an argument is\n                                                                    (currently) not supported. */\n     DFB_UNIMPLEMENTED                     = DR_UNIMPLEMENTED,   /* The requested operation is not implemented, yet. */\n     DFB_ACCESSDENIED                      = DR_ACCESSDENIED,    /* Access to the resource is denied. */\n     DFB_INVAREA                           = DR_INVAREA,         /* An invalid area has been specified or detected. */\n     DFB_INVARG                            = DR_INVARG,          /* An invalid argument has been specified. */\n     DFB_NOSYSTEMMEMORY                    = DR_NOLOCALMEMORY,   /* There's not enough system memory. */\n     DFB_NOSHAREDMEMORY                    = DR_NOSHAREDMEMORY,  /* There's not enough shared memory. */\n     DFB_LOCKED                            = DR_LOCKED,          /* The resource is (already) locked. */\n     DFB_BUFFEREMPTY                       = DR_BUFFEREMPTY,     /* The buffer is empty. */\n     DFB_FILENOTFOUND                      = DR_FILENOTFOUND,    /* The specified file has not been found. */\n     DFB_IO                                = DR_IO,              /* A general I/O error occurred. */\n     DFB_BUSY                              = DR_BUSY,            /* The resource or device is busy. */\n     DFB_NOIMPL                            = DR_NOIMPL,          /* No implementation for this interface or content type\n                                                                    has been found. */\n     DFB_TIMEOUT                           = DR_TIMEOUT,         /* The operation timed out. */\n     DFB_THIZNULL                          = DR_THIZNULL,        /* 'thiz' pointer is NULL. */\n     DFB_IDNOTFOUND                        = DR_IDNOTFOUND,      /* No resource has been found by the specified id. */\n     DFB_DESTROYED                         = DR_DESTROYED,       /* The requested object has been destroyed. */\n     DFB_FUSION                            = DR_FUSION,          /* Internal fusion error detected, most likely related\n                                                                    to IPC resources. */\n     DFB_BUFFERTOOLARGE                    = DR_BUFFERTOOLARGE,  /* Buffer is too large. */\n     DFB_INTERRUPTED                       = DR_INTERRUPTED,     /* The operation has been interrupted. */\n     DFB_NOCONTEXT                         = DR_NOCONTEXT,       /* No context available. */\n     DFB_TEMPUNAVAIL                       = DR_TEMPUNAVAIL,     /* Temporarily unavailable. */\n     DFB_LIMITEXCEEDED                     = DR_LIMITEXCEEDED,   /* Attempted to exceed limit, i.e. any kind of maximum\n                                                                    size, count etc. */\n     DFB_NOSUCHMETHOD                      = DR_NOSUCHMETHOD,    /* Requested method is not known. */\n     DFB_NOSUCHINSTANCE                    = DR_NOSUCHINSTANCE,  /* Requested instance is not known. */\n     DFB_ITEMNOTFOUND                      = DR_ITEMNOTFOUND,    /* No such item found. */\n     DFB_VERSIONMISMATCH                   = DR_VERSIONMISMATCH, /* Some versions didn't match. */\n     DFB_EOF                               = DR_EOF,             /* Reached end of file. */\n     DFB_SUSPENDED                         = DR_SUSPENDED,       /* The requested object is suspended. */\n     DFB_INCOMPLETE                        = DR_INCOMPLETE,      /* The operation has been executed, but not\n                                                                    completely. */\n     DFB_NOCORE                            = DR_NOCORE,          /* Core part not available. */\n\n     /*\n      * DirectFB specific result codes starting at this offset.\n      */\n     DFB__RESULT_BASE                      = D_RESULT_TYPE_CODE_BASE( 'D','F','B','1' ),\n\n     DFB_NOVIDEOMEMORY,                                          /* There's not enough video memory. */\n     DFB_MISSINGFONT,                                            /* No font has been set. */\n     DFB_MISSINGIMAGE,                                           /* No image has been set. */\n     DFB_NOALLOCATION,                                           /* No allocation. */\n     DFB_NOBUFFER,                                               /* No buffer. */\n\n     DFB__RESULT_END\n} DFBResult;\n\n/*\n * Return value of callback function of enumerations.\n */\ntypedef enum {\n     DFENUM_OK                             = 0,                  /* Proceed with enumeration. */\n     DFENUM_CANCEL                         = 1                   /* Cancel enumeration. */\n} DFBEnumerationResult;\n\n/**********************************************************************************************************************/\n\n/*\n * Dynamic version handling.\n */\nextern const unsigned int directfb_major_version;\nextern const unsigned int directfb_minor_version;\nextern const unsigned int directfb_micro_version;\n\n/*\n * Singleton.\n */\nextern IDirectFB *idirectfb_singleton;\n\n/*\n * Checks for a certain DirectFB version.\n * In case of an error a message is returned describing\n * the mismatch.\n */\nconst char DIRECTFB_API *DirectFBCheckVersion (\n     unsigned int                            required_major,     /* major version */\n     unsigned int                            required_minor,     /* minor version */\n     unsigned int                            required_micro      /* micro version */\n);\n\n/*\n * Retrieves usage information about supported command-line flags.\n */\nconst char DIRECTFB_API *DirectFBUsageString ( void );\n\n/*\n * Parses the command-line and initializes some variables.\n * You absolutely need to call this before doing anything else.\n * Removes all options used by DirectFB from argv.\n */\nDFBResult  DIRECTFB_API  DirectFBInit (\n     int                                    *argc,               /* pointer to main()'s argc */\n     char                                  **argv[]              /* pointer to main()'s argv */\n);\n\n#if !DIRECT_BUILD_CTORS\n\n#define StringizeDirectFBCoreSystemInit(name)             directfb_##name##_ctor()\n#define DirectFBCoreSystemInit(name)                      StringizeDirectFBCoreSystemInit( name )\n#define StringizeDirectFBCoreSystemInitProtoype(name)     void directfb_##name##_ctor( void )\n#define DirectFBCoreSystemInitProtoype(name)              StringizeDirectFBCoreSystemInitProtoype( name )\n\n#ifdef DFB_GRAPHICS_DRIVER\n#define StringizeGraphicsDriverInit(name)                 directfb_##name##_ctor()\n#define DirectFBGraphicsDriverInit(name)                  StringizeDirectFBGraphicsDriverInit( name )\n#define StringizeDirectFBGraphicsDriverInitProtoype(name) void directfb_##name##_ctor( void )\n#define DirectFBGraphicsDriverInitProtoype(name)          StringizeDirectFBGraphicsDriverInitProtoype( name )\n#else\n#define DirectFBGraphicsDriverInit(name)\n#define DirectFBGraphicsDriverInitProtoype(name)\n#endif\n\n#ifdef DFB_INPUT_DRIVER\n#define StringizeDirectFBInputDriverInit(name)            directfb_##name##_ctor()\n#define DirectFBInputDriverInit(name)                     StringizeDirectFBInputDriverInit( name )\n#define StringizeDirectFBInputDriverInitProtoype(name)    void directfb_##name##_ctor( void )\n#define DirectFBInputDriverInitProtoype(name)             StringizeDirectFBInputDriverInitProtoype( name )\n#else\n#define DirectFBInputDriverInit(name)\n#define DirectFBInputDriverInitProtoype(name)\n#endif\n\n#ifdef DFB_FONT_PROVIDER\n#define StringizeDirectFBFontProviderInit(name)           IDirectFBFont_##name##_ctor()\n#define DirectFBFontProviderInit(name)                    StringizeDirectFBFontProviderInit( name )\n#define StringizeDirectFBFontProviderInitProtoype(name)   void IDirectFBFont_##name##_ctor( void )\n#define DirectFBFontProviderInitProtoype(name)            StringizeDirectFBFontProviderInitProtoype( name )\n#else\n#define DirectFBFontProviderInit(name)\n#define DirectFBFontProviderInitProtoype(name)\n#endif\n\n#ifdef DFB_IMAGE_PROVIDER\n#define StringizeDirectFBImageProviderInit(name)          IDirectFBImageProvider_##name##_ctor()\n#define DirectFBImageProviderInit(name)                   StringizeDirectFBImageProviderInit( name )\n#define StringizeDirectFBImageProviderInitProtoype(name)  void IDirectFBImageProvider_##name##_ctor( void )\n#define DirectFBImageProviderInitProtoype(name)           StringizeDirectFBImageProviderInitProtoype( name )\n#else\n#define DirectFBImageProviderInit(name)\n#define DirectFBImageProviderInitProtoype(name)\n#endif\n\n#ifdef DFB_VIDEO_PROVIDER\n#define StringizeDirectFBVideoProviderInit(name)          IDirectFBVideoProvider_##name##_ctor()\n#define DirectFBVideoProviderInit(name)                   StringizeDirectFBVideoProviderInit( name )\n#define StringizeDirectFBVideoProviderInitProtoype(name)  void IDirectFBVideoProvider_##name##_ctor( void )\n#define DirectFBVideoProviderInitProtoype(name)           StringizeDirectFBVideoProviderInitProtoype( name )\n#else\n#define DirectFBVideoProviderInit(name)\n#define DirectFBVideoProviderInitProtoype(name)\n#endif\n\n#ifdef DFB_OPENGL_IMPLEMENTATION\n#define StringizeDirectFBGLInit(name)                     IDirectFBGL_##name##_ctor()\n#define DirectFBGLInit(name)                              StringizeDirectFBGLInit( name )\n#define StringizeDirectFBGLInitProtoype(name)             void IDirectFBGL_##name##_ctor( void )\n#define DirectFBGLInitProtoype(name)                      StringizeDirectFBGLInitProtoype( name )\n#else\n#define DirectFBGLInit(name)\n#define DirectFBGLInitProtoype(name)\n#endif\n\n#define StringizeDirectFBWindowManagerInit(name)          directfb_##name##_ctor()\n#define DirectFBWindowManagerInit(name)                   StringizeDirectFBWindowManagerInit( name )\n#define StringizeDirectFBWindowManagerInitProtoype(name)  void directfb_##name##_ctor( void )\n#define DirectFBWindowManagerInitProtoype(name)           StringizeDirectFBWindowManagerInitProtoype( name )\n\n#if defined(DFB_CORE_SYSTEM) && defined(DFB_WINDOW_MANAGER)\nDirectFBCoreSystemInitProtoype    ( DFB_CORE_SYSTEM );\nDirectFBGraphicsDriverInitProtoype( DFB_GRAPHICS_DRIVER );\nDirectFBInputDriverInitProtoype   ( DFB_INPUT_DRIVER );\nDirectFBFontProviderInitProtoype  ( DFB_FONT_PROVIDER );\nDirectFBImageProviderInitProtoype ( DFB_IMAGE_PROVIDER );\nDirectFBVideoProviderInitProtoype ( DFB_VIDEO_PROVIDER );\nDirectFBGLInitProtoype            ( DFB_OPENGL_IMPLEMENTATION );\nDirectFBWindowManagerInitProtoype ( DFB_WINDOW_MANAGER );\n\n#define DirectFBInit( argc_ptr, argv_ptr )                    \\\n     DirectFBInit              ( argc_ptr, argv_ptr );        \\\n     DirectFBCoreSystemInit    ( DFB_CORE_SYSTEM );           \\\n     DirectFBGraphicsDriverInit( DFB_GRAPHICS_DRIVER );       \\\n     DirectFBInputDriverInit   ( DFB_INPUT_DRIVER );          \\\n     DirectFBFontProviderInit  ( DFB_FONT_PROVIDER );         \\\n     DirectFBImageProviderInit ( DFB_IMAGE_PROVIDER );        \\\n     DirectFBVideoProviderInit ( DFB_VIDEO_PROVIDER );        \\\n     DirectFBGLInit            ( DFB_OPENGL_IMPLEMENTATION ); \\\n     DirectFBWindowManagerInit ( DFB_WINDOW_MANAGER );\n#endif\n\n#endif\n\n/*\n * Sets configuration parameters supported on command line and in\n * config file. Can only be called before DirectFBCreate but after\n * DirectFBInit.\n */\nDFBResult  DIRECTFB_API  DirectFBSetOption (\n     const char                             *name,               /* option name */\n     const char                             *value               /* option value */\n);\n\n/*\n * Creates the main interface.\n */\nDFBResult  DIRECTFB_API  DirectFBCreate (\n     IDirectFB                             **ret_interface       /* pointer to the created interface */\n);\n\n/*\n * Prints a description of the result code along with an\n * optional message that is put in front with a colon.\n */\nDFBResult  DIRECTFB_API  DirectFBError (\n     const char                             *msg,                /* optional message */\n     DFBResult                               result              /* result code to interpret */\n);\n\n/*\n * Returns a string describing result.\n */\nconst char DIRECTFB_API *DirectFBErrorString (\n     DFBResult                               result              /* result code to describe */\n);\n\n/*\n * Behaves like DirectFBError, but shuts down the calling\n * application.\n */\nDFBResult  DIRECTFB_API  DirectFBErrorFatal (\n     const char                             *msg,                /* optional message */\n     DFBResult                               result              /* result code to interpret */\n);\n\n/**********************************************************************************************************************/\n\n/*\n * A rectangle specified by two points.\n *\n * The defined rectangle includes the top left but not the\n * bottom right endpoint.\n */\ntypedef struct {\n     int                                     x1;                 /* X coordinate of top-left point (inclusive) */\n     int                                     y1;                 /* Y coordinate of top-left point (inclusive) */\n     int                                     x2;                 /* X coordinate of lower-right point (exclusive) */\n     int                                     y2;                 /* Y coordinate of lower-right point (exclusive) */\n} DFBBox;\n\n/*\n * A color defined by channels with 8bit each.\n */\ntypedef struct {\n     u8                                      a;                  /* alpha channel */\n     u8                                      r;                  /* red channel */\n     u8                                      g;                  /* green channel */\n     u8                                      b;                  /* blue channel */\n} DFBColor;\n\n/*\n * Flags defining which fields of a DFBColorAdjustment are\n * valid.\n */\ntypedef enum {\n     DCAF_NONE                             = 0x00000000,         /* None of these. */\n\n     DCAF_BRIGHTNESS                       = 0x00000001,         /* Brightness field is valid. */\n     DCAF_CONTRAST                         = 0x00000002,         /* Contrast field is valid. */\n     DCAF_HUE                              = 0x00000004,         /* Hue field is valid. */\n     DCAF_SATURATION                       = 0x00000008,         /* Saturation field is valid. */\n\n     DCAF_ALL                              = 0x0000000F          /* All of these. */\n} DFBColorAdjustmentFlags;\n\n/*\n * Color Adjustment used to adjust video colors.\n *\n * All fields are in the range 0x0 to 0xffff with 0x8000 as the\n * default value (no adjustment).\n */\ntypedef struct {\n     DFBColorAdjustmentFlags                 flags;              /* Validation of fields. */\n\n     u16                                     brightness;         /* Color brightness. */\n     u16                                     contrast;           /* Color contrast. */\n     u16                                     hue;                /* Color hue. */\n     u16                                     saturation;         /* Color saturation. */\n} DFBColorAdjustment;\n\n/*\n * A color key defined by R,G,B and eventually a color index.\n */\ntypedef struct {\n     u8                                      index;              /* color index */\n     u8                                      r;                  /* red channel */\n     u8                                      g;                  /* green channel */\n     u8                                      b;                  /* blue channel */\n} DFBColorKey;\n\n/*\n * Color key polarity.\n */\ntypedef enum {\n     DCKP_DEFAULT                          = 0x00000000,         /* default */\n     DCKP_OTHER                            = 0x00000001          /* other */\n} DFBColorKeyPolarity;\n\n/*\n * Extended color key definition.\n */\ntypedef struct {\n     DFBColorKeyPolarity                     polarity;           /* color key polarity */\n     DFBColor                                lower;              /* lower color key */\n     DFBColor                                upper;              /* upper color key */\n} DFBColorKeyExtended;\n\n/*\n * A color defined by channels with 8bit each.\n */\ntypedef struct {\n     u8                                      a;                  /* alpha channel */\n     u8                                      y;                  /* luma channel */\n     u8                                      u;                  /* chroma channel */\n     u8                                      v;                  /* chroma channel */\n} DFBColorYUV;\n\n/*\n * Convolution filter.\n */\ntypedef struct {\n     s32                                     kernel[9];          /* The kernel consists of 3x3 matrix. */\n     s32                                     scale;              /* Scale. */\n     s32                                     bias;               /* Bias. */\n} DFBConvolutionFilter;\n\n/*\n * A dimension specified by width and height.\n */\ntypedef struct {\n     int                                     w;                  /* width of it */\n     int                                     h;                  /* height of it */\n} DFBDimension;\n\n/*\n * Insets specify a distance from each edge of a rectangle.\n *\n * Positive values always mean outside.\n */\ntypedef struct {\n     int                                     l;                  /* distance from left edge */\n     int                                     t;                  /* distance from top edge */\n     int                                     r;                  /* distance from right edge */\n     int                                     b;                  /* distance from bottom edge */\n} DFBInsets;\n\n/*\n * A rectangle specified by normalized coordinates.\n *\n * E.g. using 0.0, 0.0, 1.0, 1.0 would specify the whole screen.\n */\ntypedef struct {\n     float                                   x;                  /* normalized X coordinate */\n     float                                   y;                  /* normalized Y coordinate */\n     float                                   w;                  /* normalized width */\n     float                                   h;                  /* normalized height */\n} DFBLocation;\n\n/*\n * A point specified by x/y coordinates.\n */\ntypedef struct {\n     int                                     x;                  /* X coordinate of it */\n     int                                     y;                  /* Y coordinate of it */\n} DFBPoint;\n\n/*\n * A rectangle specified by a point and a dimension.\n */\ntypedef struct {\n     int                                     x;                  /* X coordinate of its top-left point */\n     int                                     y;                  /* Y coordinate of its top-left point */\n     int                                     w;                  /* width of it */\n     int                                     h;                  /* height of it */\n} DFBRectangle;\n\n/*\n * A region specified by two points.\n *\n * The defined region includes both endpoints.\n */\ntypedef struct {\n     int                                     x1;                 /* X coordinate of top-left point */\n     int                                     y1;                 /* Y coordinate of top-left point */\n     int                                     x2;                 /* X coordinate of lower-right point */\n     int                                     y2;                 /* Y coordinate of lower-right point */\n} DFBRegion;\n\n/*\n * A horizontal line specified by x and width.\n */\ntypedef struct {\n     int                                     x;                  /* X coordinate */\n     int                                     w;                  /* width of span */\n} DFBSpan;\n\n/*\n * A trapezoid specified by two points with a width each.\n */\ntypedef struct {\n     int                                     x1;                 /* X coordinate of first span */\n     int                                     y1;                 /* Y coordinate of first span  */\n     int                                     w1;                 /* width of first span */\n     int                                     x2;                 /* X coordinate of second span */\n     int                                     y2;                 /* Y coordinate of second span */\n     int                                     w2;                 /* width of second span */\n} DFBTrapezoid;\n\n/*\n * A triangle specified by three points.\n */\ntypedef struct {\n     int                                     x1;                 /* X coordinate of first edge */\n     int                                     y1;                 /* Y coordinate of first edge */\n     int                                     x2;                 /* X coordinate of second edge */\n     int                                     y2;                 /* Y coordinate of second edge */\n     int                                     x3;                 /* X coordinate of third edge */\n     int                                     y3;                 /* Y coordinate of third edge */\n} DFBTriangle;\n\n/*\n * Way of building triangles from the list of vertices.\n */\ntypedef enum {\n     DTTF_LIST                             = 0x00000000,         /* 0/1/2  3/4/5  6/7/8 ... */\n     DTTF_STRIP                            = 0x00000001,         /* 0/1/2  1/2/3  2/3/4 ... */\n     DTTF_FAN                              = 0x00000002          /* 0/1/2  0/2/3  0/3/4 ... */\n} DFBTriangleFormation;\n\n/*\n * Transformed vertex of a textured triangle.\n */\ntypedef struct {\n     float                                   x;                  /* Destination X coordinate (in pixels) */\n     float                                   y;                  /* Destination Y coordinate (in pixels) */\n     float                                   z;                  /* Z coordinate */\n     float                                   w;                  /* W coordinate */\n\n     float                                   s;                  /* Texture S coordinate */\n     float                                   t;                  /* Texture T coordinate */\n} DFBVertex;\n\n/**********************************************************************************************************************/\n\ntypedef unsigned int DFBColorID;\ntypedef unsigned int DFBDisplayLayerID;\ntypedef unsigned int DFBDisplayLayerIDs;\ntypedef unsigned int DFBDisplayLayerSourceID;\ntypedef unsigned int DFBInputDeviceID;\ntypedef unsigned int DFBScreenID;\ntypedef unsigned int DFBSurfaceID;\ntypedef unsigned int DFBTextEncodingID;\ntypedef unsigned int DFBWindowID;\n\n/* Predefined color ids. */\n#define DCID_PRIMARY                         0x00000000          /* primary color */\n#define DCID_OUTLINE                         0x00000001          /* outline color */\n\n/* Predefined display layer ids. */\n#define DLID_PRIMARY                         0x00000000          /* primary layer */\n\n/* Predefined display layer source ids */\n#define DLSID_SURFACE                        0x00000000          /* surface layer source */\n\n/* Predefined input device ids. */\n#define DIDID_KEYBOARD                       0x00000000          /* primary keyboard */\n#define DIDID_MOUSE                          0x00000001          /* primary mouse */\n#define DIDID_JOYSTICK                       0x00000002          /* primary joystick */\n#define DIDID_REMOTE                         0x00000003          /* primary remote control */\n#define DIDID_BUTTONS                        0x00000004          /* primary buttons */\n#define DIDID_ANY                            0x00000010          /* no primary device */\n\n/* Predefined screen ids. */\n#define DSCID_PRIMARY                        0x00000000          /* primary screen */\n\n/* Predefined text encoding ids. */\n#define DTEID_UTF8                           0x00000000          /* UTF-8 */\n#define DTEID_OTHER                          0x00000001          /* Other */\n\n/*************\n * IDirectFB *\n *************/\n\n/*\n * The cooperative level controls the main interface's behaviour\n * in functions like SetVideoMode() or CreateSurface() for the\n * primary.\n */\ntypedef enum {\n     DFSCL_NORMAL                          = 0x00000000,         /* Normal shared access, primary surface will be the\n                                                                    buffer of an implicitly created window at the\n                                                                    resolution given by SetVideoMode(). */\n     DFSCL_FULLSCREEN                      = 0x00000001,         /* Application grabs the primary layer, SetVideoMode()\n                                                                    automates layer control. Primary surface is the\n                                                                    primary layer surface. */\n     DFSCL_EXCLUSIVE                       = 0x00000002          /* All but the primary layer will be disabled, the\n                                                                    application has full control over layers if desired,\n                                                                    other applications have no input/output/control.\n                                                                    Primary surface is the primary layer surface. */\n} DFBCooperativeLevel;\n\n/*\n * Mask of accelerated functions.\n */\ntypedef enum {\n     DFXL_NONE                             = 0x00000000,         /* None of these. */\n\n     DFXL_FILLRECTANGLE                    = 0x00000001,         /* FillRectangle() is accelerated. */\n     DFXL_DRAWRECTANGLE                    = 0x00000002,         /* DrawRectangle() is accelerated. */\n     DFXL_DRAWLINE                         = 0x00000004,         /* DrawLine() is accelerated. */\n     DFXL_FILLTRIANGLE                     = 0x00000008,         /* FillTriangle() is accelerated. */\n     DFXL_FILLTRAPEZOID                    = 0x00000010,         /* FillTrapezoids() is accelerated. */\n     DFXL_FILLQUADRANGLE                   = 0x00000020,         /* FillQuadrangles() is accelerated. */\n\n     DFXL_DRAWMONOGLYPH                    = 0x00001000,         /* DrawMonoGlyphs() is accelerated. */\n\n     DFXL_BLIT                             = 0x00010000,         /* Blit() is accelerated. */\n     DFXL_STRETCHBLIT                      = 0x00020000,         /* StretchBlit() is accelerated. */\n     DFXL_TEXTRIANGLES                     = 0x00040000,         /* TextureTriangles() is accelerated. */\n     DFXL_BLIT2                            = 0x00080000,         /* Blit2() is accelerated. */\n\n     DFXL_DRAWSTRING                       = 0x01000000,         /* DrawString() is accelerated. */\n\n     DFXL_ALL                              = 0x010F003F,         /* All drawing/blitting functions. */\n     DFXL_ALL_DRAW                         = 0x0000103F,         /* All drawing functions. */\n     DFXL_ALL_BLIT                         = 0x010F0000          /* All blitting functions. */\n} DFBAccelerationMask;\n\n#define DFB_DRAWING_FUNCTION(a)       ((a) & 0x0000FFFF)\n#define DFB_BLITTING_FUNCTION(a)      ((a) & 0xFFFF0000)\n\n/*\n * Flags controlling blitting commands.\n */\ntypedef enum {\n     DSBLIT_NOFX                           = 0x00000000,         /* uses none of the effects */\n     DSBLIT_BLEND_ALPHACHANNEL             = 0x00000001,         /* enables blending and uses\n                                                                    alphachannel from source */\n     DSBLIT_BLEND_COLORALPHA               = 0x00000002,         /* enables blending and uses\n                                                                    alpha value from color */\n     DSBLIT_COLORIZE                       = 0x00000004,         /* modulates source color with\n                                                                    the color's r/g/b values */\n     DSBLIT_SRC_COLORKEY                   = 0x00000008,         /* don't blit pixels matching the source color key */\n     DSBLIT_DST_COLORKEY                   = 0x00000010,         /* write to destination only if the destination pixel\n                                                                    matches the destination color key */\n     DSBLIT_SRC_PREMULTIPLY                = 0x00000020,         /* modulates the source color with the (modulated)\n                                                                    source alpha */\n     DSBLIT_DST_PREMULTIPLY                = 0x00000040,         /* modulates the dest. color with the dest. alpha */\n     DSBLIT_DEMULTIPLY                     = 0x00000080,         /* divides the color by the alpha before writing the\n                                                                    data to the destination */\n     DSBLIT_DEINTERLACE                    = 0x00000100,         /* deinterlaces the source during blitting by reading\n                                                                    only one field (every second line of full\n                                                                    image) scaling it vertically by factor two */\n     DSBLIT_SRC_PREMULTCOLOR               = 0x00000200,         /* modulates the source color with the color alpha */\n     DSBLIT_XOR                            = 0x00000400,         /* bitwise xor the destination pixels with the\n                                                                    source pixels after premultiplication */\n     DSBLIT_INDEX_TRANSLATION              = 0x00000800,         /* do fast indexed to indexed translation,\n                                                                    this flag is mutual exclusive with all others */\n     DSBLIT_ROTATE180                      = 0x00001000,         /* rotate the image by 180 degree */\n     DSBLIT_ROTATE90                       = 0x00002000,         /* rotate the image by 90 degree */\n     DSBLIT_ROTATE270                      = 0x00004000,         /* rotate the image by 270 degree */\n\n     DSBLIT_COLORKEY_PROTECT               = 0x00010000,         /* make sure written pixels don't match color key */\n     DSBLIT_SRC_COLORKEY_EXTENDED          = 0x00020000,         /* use extended source color key */\n     DSBLIT_DST_COLORKEY_EXTENDED          = 0x00040000,         /* use extended destination color key */\n\n     DSBLIT_SRC_MASK_ALPHA                 = 0x00100000,         /* modulate source alpha channel with alpha channel\n                                                                    from source mask */\n     DSBLIT_SRC_MASK_COLOR                 = 0x00200000,         /* modulate source color channels with color channels\n                                                                    from source mask */\n\n     DSBLIT_FLIP_HORIZONTAL                = 0x01000000,         /* flip the image horizontally */\n     DSBLIT_FLIP_VERTICAL                  = 0x02000000,         /* flip the image vertically */\n\n     DSBLIT_SRC_COLORMATRIX                = 0x08000000,         /* use source color matrix setting */\n     DSBLIT_SRC_CONVOLUTION                = 0x10000000          /* use source convolution filter */\n} DFBSurfaceBlittingFlags;\n\n/*\n * Flags controlling drawing commands.\n */\ntypedef enum {\n     DSDRAW_NOFX                           = 0x00000000,         /* uses none of the effects */\n     DSDRAW_BLEND                          = 0x00000001,         /* uses alpha from color */\n     DSDRAW_DST_COLORKEY                   = 0x00000002,         /* write to destination only if the destination pixel\n                                                                    matches the destination color key */\n     DSDRAW_SRC_PREMULTIPLY                = 0x00000004,         /* multiplies the color's rgb channels by the alpha\n                                                                    channel before drawing */\n     DSDRAW_DST_PREMULTIPLY                = 0x00000008,         /* modulates the dest. color with the dest. alpha */\n     DSDRAW_DEMULTIPLY                     = 0x00000010,         /* divides the color by the alpha before writing the\n                                                                    data to the destination */\n     DSDRAW_XOR                            = 0x00000020          /* bitwise xor the destination pixels with the\n                                                                    specified color after premultiplication */\n} DFBSurfaceDrawingFlags;\n\n#define DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH   40\n#define DFB_GRAPHICS_DRIVER_INFO_VENDOR_LENGTH 60\n\n/*\n * Driver information.\n */\ntypedef struct {\n     int                                     major;              /* Major version */\n     int                                     minor;              /* Minor version */\n\n     char name[DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH];            /* Driver name */\n     char vendor[DFB_GRAPHICS_DRIVER_INFO_VENDOR_LENGTH];        /* Driver vendor */\n} DFBGraphicsDriverInfo;\n\n#define DFB_GRAPHICS_DEVICE_DESC_NAME_LENGTH   48\n#define DFB_GRAPHICS_DEVICE_DESC_VENDOR_LENGTH 64\n\n/*\n * Description of the graphics device capabilities.\n */\ntypedef struct {\n     DFBAccelerationMask                     acceleration_mask;  /* Accelerated functions */\n     DFBSurfaceBlittingFlags                 blitting_flags;     /* Supported blitting flags */\n     DFBSurfaceDrawingFlags                  drawing_flags;      /* Supported drawing flags */\n     unsigned int                            video_memory;       /* Amount of video memory in bytes */\n\n     char name[DFB_GRAPHICS_DEVICE_DESC_NAME_LENGTH];            /* Device/Chipset name */\n     char vendor[DFB_GRAPHICS_DEVICE_DESC_VENDOR_LENGTH];        /* Device vendor */\n\n     DFBGraphicsDriverInfo                   driver;             /* Device driver information */\n} DFBGraphicsDeviceDescription;\n\n/*\n * Flags defining which fields of a DFBSurfaceDescription are\n * valid.\n */\ntypedef enum {\n     DSDESC_NONE                           = 0x00000000,         /* None of these. */\n\n     DSDESC_CAPS                           = 0x00000001,         /* caps field is valid. */\n     DSDESC_WIDTH                          = 0x00000002,         /* width field is valid. */\n     DSDESC_HEIGHT                         = 0x00000004,         /* height field is valid. */\n     DSDESC_PIXELFORMAT                    = 0x00000008,         /* pixelformat field is valid. */\n     DSDESC_PREALLOCATED                   = 0x00000010,         /* Surface uses data that has been preallocated by the\n                                                                    application. The field array preallocated has to be\n                                                                    set using the first element for the front buffer and\n                                                                    eventually the second one for the back buffer. */\n     DSDESC_PALETTE                        = 0x00000020,         /* Initialize the surfaces palette with the entries\n                                                                    specified in the description. */\n     DSDESC_COLORSPACE                     = 0x00000040,         /* colorspace field is valid. */\n\n     DSDESC_RESOURCE_ID                    = 0x00000100,         /* User defined resource id for general purpose\n                                                                    surfaces is specified, or resource id of window,\n                                                                    layer, user is returned. */\n     DSDESC_HINTS                          = 0x00000200,         /* Flags for optimized allocation and pixel format\n                                                                    selection are set. */\n\n     DSDESC_ALL                            = 0x0000037F          /* All of these. */\n} DFBSurfaceDescriptionFlags;\n\n/*\n * The surface capabilities.\n */\ntypedef enum {\n     DSCAPS_NONE                           = 0x00000000,         /* None of these. */\n\n     DSCAPS_PRIMARY                        = 0x00000001,         /* It's the primary surface. */\n     DSCAPS_SYSTEMONLY                     = 0x00000002,         /* Surface data is permanently stored in system memory.\n                                                                    There's no video memory allocation/storage. */\n     DSCAPS_VIDEOONLY                      = 0x00000004,         /* Surface data is permanently stored in video memory.\n                                                                    There's no system memory allocation/storage. */\n     DSCAPS_GL                             = 0x00000008,         /* Surface data is stored in memory that can be\n                                                                    accessed by a GL accelerator. */\n     DSCAPS_DOUBLE                         = 0x00000010,         /* Surface is double buffered. */\n     DSCAPS_SUBSURFACE                     = 0x00000020,         /* Surface is just a sub area of another\n                                                                    one sharing the surface data. */\n     DSCAPS_INTERLACED                     = 0x00000040,         /* Each buffer contains interlaced video (or graphics)\n                                                                    data consisting of two fields.\n                                                                    Their lines are stored interleaved. One field's\n                                                                    height is a half of the surface's height. */\n     DSCAPS_SEPARATED                      = 0x00000080,         /* For usage with DSCAPS_INTERLACED.\n                                                                    DSCAPS_SEPARATED specifies that the fields are not\n                                                                    interleaved line by line in the buffer.\n                                                                    The first field is followed by the second one. */\n     DSCAPS_STATIC_ALLOC                   = 0x00000100,         /* The amount of video or system memory allocated for\n                                                                    the surface is never less than its initial value.\n                                                                    This way a surface can be resized (smaller and\n                                                                    bigger up to the initial size) without reallocation\n                                                                    of the buffers. It's useful for surfaces that need a\n                                                                    guaranteed space in video memory after resizing. */\n     DSCAPS_TRIPLE                         = 0x00000200,         /* Surface is triple buffered. */\n\n     DSCAPS_PREMULTIPLIED                  = 0x00001000,         /* Surface stores data with premultiplied alpha. */\n\n     DSCAPS_DEPTH                          = 0x00010000,         /* A depth buffer is allocated. */\n     DSCAPS_STEREO                         = 0x00020000,         /* Both left & right buffers are allocated. Only valid\n                                                                    with windows and layers with the DLOP_STEREO or\n                                                                    DWCAPS_STEREO flags set. */\n\n     DSCAPS_SHARED                         = 0x00100000,         /* The surface will be accessible among processes. */\n\n     DSCAPS_ROTATED                        = 0x01000000,         /* The back buffers are allocated with swapped\n                                                                    width/height. */\n\n     DSCAPS_ALL                            = 0x011113FF,         /* All of these. */\n\n     DSCAPS_FLIPPING                       = DSCAPS_DOUBLE |\n                                             DSCAPS_TRIPLE       /* Surface needs Flip() calls to make\n                                                                    updates/changes visible/usable. */\n} DFBSurfaceCapabilities;\n\n/*\n * Encodes pixel format constants in the following way (bit 31 - 0):\n *\n * lkjj:hhgg | gfff:eeed | cccc:bbbb | baaa:aaaa\n *\n * a) pixelformat index\n * b) effective color (or index) bits per pixel of format\n * c) effective alpha bits per pixel of format\n * d) alpha channel present\n * e) bytes per \"pixel in a row\" (1/8 fragment, i.e. bits)\n * f) bytes per \"pixel in a row\" (decimal part, i.e. bytes)\n * g) smallest number of pixels aligned to byte boundary\n * h) multiplier for planes minus one (1/4 fragment)\n * j) multiplier for planes minus one (decimal part)\n * k) color and/or alpha lookup table present\n * l) alpha channel is inverted\n */\n#define DFB_SURFACE_PIXELFORMAT(index,color_bits,     \\\n                                alpha_bits,has_alpha, \\\n                                row_bits,row_bytes,   \\\n                                align,mul_f,mul_d,    \\\n                                has_lut,inv_alpha)    \\\n     ( (((index     ) & 0x7F)      ) |                \\\n       (((color_bits) & 0x1F) <<  7) |                \\\n       (((alpha_bits) & 0x0F) << 12) |                \\\n       (((has_alpha ) ? 1 :0) << 16) |                \\\n       (((row_bits  ) & 0x07) << 17) |                \\\n       (((row_bytes ) & 0x07) << 20) |                \\\n       (((align     ) & 0x07) << 23) |                \\\n       (((mul_f     ) & 0x03) << 26) |                \\\n       (((mul_d     ) & 0x03) << 28) |                \\\n       (((has_lut   ) ? 1 :0) << 30) |                \\\n       (((inv_alpha ) ? 1 :0) << 31) )\n\n/*\n * Pixel format of a surface.\n */\ntypedef enum {\n     /* unknown or unspecified format */\n     DSPF_UNKNOWN    = 0x00000000,\n\n     /* 16 bit  ARGB (2 byte, alpha 1@15, red 5@10, green 5@5, blue 5@0) */\n     DSPF_ARGB1555   = DFB_SURFACE_PIXELFORMAT(  0, 15, 1, 1, 0, 2, 0, 0, 0, 0, 0 ),\n\n     /* 16 bit   RGB (2 byte, red 5@11, green 6@5, blue 5@0) */\n     DSPF_RGB16      = DFB_SURFACE_PIXELFORMAT(  1, 16, 0, 0, 0, 2, 0, 0, 0, 0, 0 ),\n\n     /* 24 bit   RGB (3 byte, red 8@16, green 8@8, blue 8@0) */\n     DSPF_RGB24      = DFB_SURFACE_PIXELFORMAT(  2, 24, 0, 0, 0, 3, 0, 0, 0, 0, 0 ),\n\n     /* 24 bit   RGB (4 byte, nothing@24, red 8@16, green 8@8, blue 8@0) */\n     DSPF_RGB32      = DFB_SURFACE_PIXELFORMAT(  3, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0 ),\n\n     /* 32 bit  ARGB (4 byte, alpha 8@24, red 8@16, green 8@8, blue 8@0) */\n     DSPF_ARGB       = DFB_SURFACE_PIXELFORMAT(  4, 24, 8, 1, 0, 4, 0, 0, 0, 0, 0 ),\n\n     /*  8 bit alpha (1 byte, alpha 8@0), e.g. anti-aliased glyphs */\n     DSPF_A8         = DFB_SURFACE_PIXELFORMAT(  5,  0, 8, 1, 0, 1, 0, 0, 0, 0, 0 ),\n\n     /* 16 bit   YUV (4 byte/ 2 pixel, macropixel contains CbYCrY [31:0]) */\n     DSPF_YUY2       = DFB_SURFACE_PIXELFORMAT(  6, 16, 0, 0, 0, 2, 0, 0, 0, 0, 0 ),\n\n     /*  8 bit   RGB (1 byte, red 3@5, green 3@2, blue 2@0) */\n     DSPF_RGB332     = DFB_SURFACE_PIXELFORMAT(  7,  8, 0, 0, 0, 1, 0, 0, 0, 0, 0 ),\n\n     /* 16 bit   YUV (4 byte/ 2 pixel, macropixel contains YCbYCr [31:0]) */\n     DSPF_UYVY       = DFB_SURFACE_PIXELFORMAT(  8, 16, 0, 0, 0, 2, 0, 0, 0, 0, 0 ),\n\n     /* 12 bit   YUV (8 bit Y plane followed by quarter-size 8 bit U/V planes) */\n     DSPF_I420       = DFB_SURFACE_PIXELFORMAT(  9, 12, 0, 0, 0, 1, 0, 2, 0, 0, 0 ),\n\n     /* 12 bit   YUV (8 bit Y plane followed by quarter-size 8 bit V/U planes) */\n     DSPF_YV12       = DFB_SURFACE_PIXELFORMAT( 10, 12, 0, 0, 0, 1, 0, 2, 0, 0, 0 ),\n\n     /*  8 bit   LUT (8 bit color and alpha lookup from palette) */\n     DSPF_LUT8       = DFB_SURFACE_PIXELFORMAT( 11,  8, 0, 1, 0, 1, 0, 0, 0, 1, 0 ),\n\n     /*  8 bit  ALUT (1 byte, alpha 4@4, color lookup 4@0) */\n     DSPF_ALUT44     = DFB_SURFACE_PIXELFORMAT( 12,  4, 4, 1, 0, 1, 0, 0, 0, 1, 0 ),\n\n     /* 32 bit  ARGB (4 byte, inv. alpha 8@24, red 8@16, green 8@8, blue 8@0) */\n     DSPF_AiRGB      = DFB_SURFACE_PIXELFORMAT( 13, 24, 8, 1, 0, 4, 0, 0, 0, 0, 1 ),\n\n     /*  1 bit alpha (1 byte/ 8 pixel, most significant bit used first) */\n     DSPF_A1         = DFB_SURFACE_PIXELFORMAT( 14,  0, 1, 1, 1, 0, 7, 0, 0, 0, 0 ),\n\n     /* 12 bit   YUV (8 bit Y plane followed by quarter-size 16 bit Cb|Cr [7:0|7:0] plane) */\n     DSPF_NV12       = DFB_SURFACE_PIXELFORMAT( 15, 12, 0, 0, 0, 1, 0, 2, 0, 0, 0 ),\n\n     /* 16 bit   YUV (8 bit Y plane followed by half-size 16 bit Cb|Cr [7:0|7:0] plane) */\n     DSPF_NV16       = DFB_SURFACE_PIXELFORMAT( 16, 16, 0, 0, 0, 1, 0, 0, 1, 0, 0 ),\n\n     /* 16 bit  ARGB (2 byte, alpha 2@14, red 5@9, green 5@4, blue 4@0) */\n     DSPF_ARGB2554   = DFB_SURFACE_PIXELFORMAT( 17, 14, 2, 1, 0, 2, 0, 0, 0, 0, 0 ),\n\n     /* 16 bit  ARGB (2 byte, alpha 4@12, red 4@8, green 4@4, blue 4@0) */\n     DSPF_ARGB4444   = DFB_SURFACE_PIXELFORMAT( 18, 12, 4, 1, 0, 2, 0, 0, 0, 0, 0 ),\n\n     /* 16 bit  RGBA (2 byte, red 4@12, green 4@8, blue 4@4, alpha 4@0) */\n     DSPF_RGBA4444   = DFB_SURFACE_PIXELFORMAT( 19, 12, 4, 1, 0, 2, 0, 0, 0, 0, 0 ),\n\n     /* 12 bit   YUV (8 bit Y plane followed by quarter-size 16 bit Cr|Cb [7:0|7:0] plane) */\n     DSPF_NV21       = DFB_SURFACE_PIXELFORMAT( 20, 12, 0, 0, 0, 1, 0, 2, 0, 0, 0 ),\n\n     /* 32 bit  AYUV (4 byte, alpha 8@24, Y 8@16, Cb 8@8, Cr 8@0) */\n     DSPF_AYUV       = DFB_SURFACE_PIXELFORMAT( 21, 24, 8, 1, 0, 4, 0, 0, 0, 0, 0 ),\n\n     /*  4 bit alpha (1 byte/ 2 pixel, more significant nibble used first) */\n     DSPF_A4         = DFB_SURFACE_PIXELFORMAT( 22,  0, 4, 1, 4, 0, 1, 0, 0, 0, 0 ),\n\n     /*  1 bit alpha (3 byte, alpha 1@18, red 6@12, green 6@6, blue 6@0) */\n     DSPF_ARGB1666   = DFB_SURFACE_PIXELFORMAT( 23, 18, 1, 1, 0, 3, 0, 0, 0, 0, 0 ),\n\n     /*  6 bit alpha (3 byte, alpha 6@18, red 6@12, green 6@6, blue 6@0) */\n     DSPF_ARGB6666   = DFB_SURFACE_PIXELFORMAT( 24, 18, 6, 1, 0, 3, 0, 0, 0, 0, 0 ),\n\n     /* 24 bit   RGB (3 byte, nothing @18, red 6@12, green 6@6, blue 6@0) */\n     DSPF_RGB18      = DFB_SURFACE_PIXELFORMAT( 25, 18, 0, 0, 0, 3, 0, 0, 0, 0, 0 ),\n\n     /*  2 bit   LUT (1 byte/ 4 pixel, 2 bit color and alpha lookup from palette) */\n     DSPF_LUT2       = DFB_SURFACE_PIXELFORMAT( 26,  2, 0, 1, 2, 0, 3, 0, 0, 1, 0 ),\n\n     /* 16 bit   RGB (2 byte, nothing @12, red 4@8, green 4@4, blue 4@0) */\n     DSPF_RGB444     = DFB_SURFACE_PIXELFORMAT( 27, 12, 0, 0, 0, 2, 0, 0, 0, 0, 0 ),\n\n     /* 16 bit   RGB (2 byte, nothing @15, red 5@10, green 5@5, blue 5@0) */\n     DSPF_RGB555     = DFB_SURFACE_PIXELFORMAT( 28, 15, 0, 0, 0, 2, 0, 0, 0, 0, 0 ),\n\n     /* 16 bit   BGR (2 byte, nothing @15, blue 5@10, green 5@5, red 5@0) */\n     DSPF_BGR555     = DFB_SURFACE_PIXELFORMAT( 29, 15, 0, 0, 0, 2, 0, 0, 0, 0, 0 ),\n\n     /* 16 bit  RGBA (2 byte, red 5@11, green 5@6, blue 5@1, alpha 1@0) */\n     DSPF_RGBA5551   = DFB_SURFACE_PIXELFORMAT( 30, 15, 1, 1, 0, 2, 0, 0, 0, 0, 0 ),\n\n     /* 24 bit   YUV (8 bit Y plane followed by 8 bit U/V planes) */\n     DSPF_Y444       = DFB_SURFACE_PIXELFORMAT( 31, 24, 0, 0, 0, 1, 0, 0, 2, 0, 0 ),\n\n     /* 24 bit  ARGB (3 byte, alpha 8@16, red 5@11, green 6@5, blue 5@0) */\n     DSPF_ARGB8565   = DFB_SURFACE_PIXELFORMAT( 32, 16, 8, 1, 0, 3, 0, 0, 0, 0, 0 ),\n\n     /* 32 bit  AVYU (4 byte, alpha 8@24, Cr 8@16, Y 8@8, Cb 8@0) */\n     DSPF_AVYU       = DFB_SURFACE_PIXELFORMAT( 33, 24, 8, 1, 0, 4, 0, 0, 0, 0, 0 ),\n\n     /* 24 bit   VYU (3 byte, Cr 8@16, Y 8@8, Cb 8@0) */\n     DSPF_VYU        = DFB_SURFACE_PIXELFORMAT( 34, 24, 0, 0, 0, 3, 0, 0, 0, 0, 0 ),\n\n     /*  1 bit alpha (1 byte/ 8 pixel, least significant bit used first) */\n     DSPF_A1_LSB     = DFB_SURFACE_PIXELFORMAT( 35,  0, 1, 1, 1, 0, 7, 0, 0, 0, 0 ),\n\n     /* 16 bit   YUV (8 bit Y plane followed by half-size 8 bit V/U planes) */\n     DSPF_YV16       = DFB_SURFACE_PIXELFORMAT( 36, 16, 0, 0, 0, 1, 0, 0, 1, 0, 0 ),\n\n     /* 32 bit  ABGR (4 byte, alpha 8@24, blue 8@16, green 8@8, red 8@0) */\n     DSPF_ABGR       = DFB_SURFACE_PIXELFORMAT( 37, 24, 8, 1, 0, 4, 0, 0, 0, 0, 0 ),\n\n     /* 32 bit RGBAF (4 byte, red 8@24, green 8@16, blue 8@8, alpha 7@1, flash 1@0 */\n     DSPF_RGBAF88871 = DFB_SURFACE_PIXELFORMAT( 38, 24, 7, 1, 0, 4, 0, 0, 0, 0, 0 ),\n\n     /*  4 bit   LUT (1 byte/ 2 pixel, 4 bit color and alpha lookup from palette) */\n     DSPF_LUT4       = DFB_SURFACE_PIXELFORMAT( 39,  4, 0, 1, 4, 0, 1, 0, 0, 1, 0 ),\n\n     /* 16 bit   LUT (1 byte alpha and 8 bit color lookup from palette) */\n     DSPF_ALUT8      = DFB_SURFACE_PIXELFORMAT( 40,  8, 8, 1, 0, 2, 0, 0, 0, 1, 0 ),\n\n     /*  1 bit   LUT (1 byte/ 8 pixel, 1 bit color and alpha lookup from palette) */\n     DSPF_LUT1       = DFB_SURFACE_PIXELFORMAT( 41,  1, 0, 1, 1, 0, 7, 0, 0, 1, 0 ),\n\n     /* 16 bit   YUV (8 bit Y plane followed by half-size 16 bit Cr|Cb [7:0|7:0] plane) */\n     DSPF_NV61       = DFB_SURFACE_PIXELFORMAT( 42, 16, 0, 0, 0, 1, 0, 0, 1, 0, 0 ),\n\n     /* 16 bit   YUV (8 bit Y plane followed by half-size 8 bit U/V planes) */\n     DSPF_Y42B       = DFB_SURFACE_PIXELFORMAT( 43, 16, 0, 0, 0, 1, 0, 0, 1, 0, 0 ),\n\n     /* 24 bit   YUV (8 bit Y plane followed by 8 bit V/U planes) */\n     DSPF_YV24       = DFB_SURFACE_PIXELFORMAT( 44, 24, 0, 0, 0, 1, 0, 0, 2, 0, 0 ),\n\n     /* 24 bit   YUV (8 bit Y plane followed by 16 bit Cb|Cr [7:0|7:0] plane) */\n     DSPF_NV24       = DFB_SURFACE_PIXELFORMAT( 45, 24, 0, 0, 0, 1, 0, 0, 2, 0, 0 ),\n\n     /* 24 bit   YUV (8 bit Y plane followed by 16 bit Cr|Cb [7:0|7:0] plane) */\n     DSPF_NV42       = DFB_SURFACE_PIXELFORMAT( 46, 24, 0, 0, 0, 1, 0, 0, 2, 0, 0 ),\n\n     /* 24 bit   BGR (3 byte, blue 8@16, green 8@8, red 8@0) */\n     DSPF_BGR24      = DFB_SURFACE_PIXELFORMAT( 47, 24, 0, 0, 0, 3, 0, 0, 0, 0, 0 )\n} DFBSurfacePixelFormat;\n\n#define DSPF_YUV420P                         DSPF_I420\n#define DSPF_YUV422P                         DSPF_Y42B\n#define DSPF_YUV444P                         DSPF_Y444\n\n/* Number of pixelformats defined. */\n#define DFB_NUM_PIXELFORMATS                 48\n\n/* These macros extract information about the pixel format. */\n#define DFB_PIXELFORMAT_INDEX(fmt)            ((fmt) & 0x0000007F)\n\n#define DFB_COLOR_BITS_PER_PIXEL(fmt)        (((fmt) & 0x00000F80) >> 7)\n\n#define DFB_ALPHA_BITS_PER_PIXEL(fmt)        (((fmt) & 0x0000F000) >> 12)\n\n#define DFB_PIXELFORMAT_HAS_ALPHA(fmt)       (((fmt) & 0x00010000) != 0)\n\n#define DFB_BITS_PER_PIXEL(fmt)              (((fmt) & 0x007E0000) >> 17)\n\n#define DFB_BYTES_PER_PIXEL(fmt)             (((fmt) & 0x00700000) >> 20)\n\n#define DFB_BYTES_PER_LINE(fmt,width)        (((((fmt) & 0x007E0000) >> 17) * (width) + 7) >> 3)\n\n#define DFB_PIXELFORMAT_ALIGNMENT(fmt)       (((fmt) & 0x03800000) >> 23)\n\n#define DFB_PLANE_MULTIPLY(fmt,height)       ((((((fmt) & 0x3C000000) >> 26) + 4) * (height)) >> 2)\n\n#define DFB_PIXELFORMAT_IS_INDEXED(fmt)      (((fmt) & 0x40000000) != 0)\n\n#define DFB_PLANAR_PIXELFORMAT(fmt)          (((fmt) & 0x3C000000) != 0)\n\n#define DFB_PIXELFORMAT_INV_ALPHA(fmt)       (((fmt) & 0x80000000) != 0)\n\n#define DFB_COLOR_IS_RGB(fmt)        \\\n     (((fmt) == DSPF_ARGB1555)    || \\\n      ((fmt) == DSPF_RGB16)       || \\\n      ((fmt) == DSPF_RGB24)       || \\\n      ((fmt) == DSPF_RGB32)       || \\\n      ((fmt) == DSPF_ARGB)        || \\\n      ((fmt) == DSPF_RGB332)      || \\\n      ((fmt) == DSPF_AiRGB)       || \\\n      ((fmt) == DSPF_ARGB2554)    || \\\n      ((fmt) == DSPF_ARGB4444)    || \\\n      ((fmt) == DSPF_RGBA4444)    || \\\n      ((fmt) == DSPF_ARGB1666)    || \\\n      ((fmt) == DSPF_ARGB6666)    || \\\n      ((fmt) == DSPF_RGB18)       || \\\n      ((fmt) == DSPF_RGB444)      || \\\n      ((fmt) == DSPF_RGB555)      || \\\n      ((fmt) == DSPF_BGR555)      || \\\n      ((fmt) == DSPF_ARGB8565)    || \\\n      ((fmt) == DSPF_ABGR)        || \\\n      ((fmt) == DSPF_RGBAF88871)  || \\\n      ((fmt) == DSPF_BGR24))\n\n#define DFB_COLOR_IS_YUV(fmt)        \\\n     (((fmt) == DSPF_YUY2)        || \\\n      ((fmt) == DSPF_UYVY)        || \\\n      ((fmt) == DSPF_I420)        || \\\n      ((fmt) == DSPF_YV12)        || \\\n      ((fmt) == DSPF_NV12)        || \\\n      ((fmt) == DSPF_NV16)        || \\\n      ((fmt) == DSPF_NV21)        || \\\n      ((fmt) == DSPF_AYUV)        || \\\n      ((fmt) == DSPF_Y444)        || \\\n      ((fmt) == DSPF_AVYU)        || \\\n      ((fmt) == DSPF_VYU)         || \\\n      ((fmt) == DSPF_YV16)        || \\\n      ((fmt) == DSPF_NV61)        || \\\n      ((fmt) == DSPF_Y42B)        || \\\n      ((fmt) == DSPF_YV24)        || \\\n      ((fmt) == DSPF_NV24)        || \\\n      ((fmt) == DSPF_NV42))\n\n/*\n * Hint flags for optimized allocation, format selection etc.\n */\ntypedef enum {\n     DSHF_NONE                             = 0x00000000,         /* None of these. */\n\n     DSHF_LAYER                            = 0x00000001,         /* Surface optimized for display layer usage. */\n     DSHF_WINDOW                           = 0x00000002,         /* Surface optimized for being a window buffer. */\n     DSHF_CURSOR                           = 0x00000004,         /* Surface optimized for usage as a cursor shape. */\n     DSHF_FONT                             = 0x00000008,         /* Surface optimized for text rendering. */\n\n     DSHF_ALL                              = 0x0000000F          /* All of these. */\n} DFBSurfaceHintFlags;\n\n/*\n * Color space used by the colors in the surface.\n */\ntypedef enum {\n     DSCS_UNKNOWN                          = 0x00000000,         /* unknown color space */\n\n     DSCS_RGB                              = 0x00000001,         /* standard RGB */\n     DSCS_BT601                            = 0x00000002,         /* ITU BT.601 */\n\n     DSCS_BT709                            = 0x00000004,         /* ITU BT.709 */\n     DSCS_BT2020                           = 0x00000005          /* ITU BT.2020 */\n} DFBSurfaceColorSpace;\n\n#define DFB_COLORSPACE_IS_COMPATIBLE(cs,fmt)               \\\n     ((DFB_COLOR_IS_RGB((fmt)) &&  ((cs) == DSCS_RGB))  || \\\n      (DFB_COLOR_IS_YUV((fmt)) && (((cs) == DSCS_BT601) || \\\n                                   ((cs) == DSCS_BT709) || \\\n                                   ((cs) == DSCS_BT2020))))\n\n#define DFB_COLORSPACE_DEFAULT(fmt) \\\n     (DFB_COLOR_IS_RGB((fmt)) ? DSCS_RGB : DFB_COLOR_IS_YUV((fmt)) ? DSCS_BT601 : DSCS_UNKNOWN)\n\n/*\n * Description of the surface that is to be created.\n */\ntypedef struct {\n     DFBSurfaceDescriptionFlags              flags;              /* field validation */\n\n     DFBSurfaceCapabilities                  caps;               /* capabilities */\n     int                                     width;              /* pixel width */\n     int                                     height;             /* pixel height */\n     DFBSurfacePixelFormat                   pixelformat;        /* pixel format */\n     struct {\n          void                              *data;               /* data pointer of existing buffer */\n          int                                pitch;              /* pitch of buffer */\n     } preallocated[3];                                          /* preallocated data */\n     struct {\n          const DFBColor                    *entries;            /* palette entries */\n          unsigned int                       size;               /* number of entries */\n     } palette;                                                  /* initial palette */\n     unsigned long                           resource_id;        /* universal resource id, either user specified for\n                                                                    general purpose surfaces or id of layer or window */\n     DFBSurfaceHintFlags                     hints;              /* usage hints for optimized allocation,\n                                                                    format selection, etc */\n     DFBSurfaceColorSpace                    colorspace;         /* color space */\n} DFBSurfaceDescription;\n\n/*\n * Flags defining which fields of a DFBPaletteDescription are\n * valid.\n */\ntypedef enum {\n     DPDESC_CAPS                           = 0x00000001,         /* Specify palette capabilities. */\n     DPDESC_SIZE                           = 0x00000002,         /* Specify number of entries. */\n     DPDESC_ENTRIES                        = 0x00000004,         /* Initialize the palette with the\n                                                                    entries specified in the description. */\n     DPDESC_COLORSPACE                     = 0x00000008          /* Specify palette color space. */\n} DFBPaletteDescriptionFlags;\n\n/*\n * The palette capabilities.\n */\ntypedef enum {\n     DPCAPS_NONE                           = 0x00000000          /* None of these. */\n} DFBPaletteCapabilities;\n\n/*\n * Description of the palette that is to be created.\n */\ntypedef struct {\n     DFBPaletteDescriptionFlags              flags;              /* Validation of fields. */\n\n     DFBPaletteCapabilities                  caps;               /* Palette capabilities. */\n     unsigned int                            size;               /* Number of entries. */\n     const DFBColor                         *entries;            /* Preset palette entries. */\n     DFBSurfaceColorSpace                    colorspace;         /* Palette color space. */\n} DFBPaletteDescription;\n\n/*\n * Capabilities of a screen.\n */\ntypedef enum {\n     DSCCAPS_NONE                          = 0x00000000,         /* None of these. */\n\n     DSCCAPS_VSYNC                         = 0x00000001,         /* Synchronization with the\n                                                                    vertical retrace supported. */\n     DSCCAPS_POWER_MANAGEMENT              = 0x00000002,         /* Power management supported. */\n\n     DSCCAPS_MIXERS                        = 0x00000010,         /* Has mixers. */\n     DSCCAPS_ENCODERS                      = 0x00000020,         /* Has encoders. */\n     DSCCAPS_OUTPUTS                       = 0x00000040,         /* Has outputs. */\n\n     DSCCAPS_ALL                           = 0x00000073          /* All of these. */\n} DFBScreenCapabilities;\n\n#define DFB_SCREEN_DESC_NAME_LENGTH          32\n\n/*\n * Description of the display encoder capabilities.\n */\ntypedef struct {\n     DFBScreenCapabilities                   caps;               /* Capability flags of the screen. */\n\n     char name[DFB_SCREEN_DESC_NAME_LENGTH];                     /* Rough description. */\n\n     int                                     mixers;             /* Number of mixers available. */\n     int                                     encoders;           /* Number of display encoders available. */\n     int                                     outputs;            /* Number of output connectors available. */\n} DFBScreenDescription;\n\n/*\n * Type of display layer for basic classification.\n */\ntypedef enum {\n     DLTF_NONE                             = 0x00000000,         /* Unclassified, no specific type. */\n\n     DLTF_GRAPHICS                         = 0x00000001,         /* Can be used for graphics output. */\n     DLTF_VIDEO                            = 0x00000002,         /* Can be used for live video output.*/\n     DLTF_STILL_PICTURE                    = 0x00000004,         /* Can be used for single frames. */\n     DLTF_BACKGROUND                       = 0x00000008,         /* Can be used as a background layer.*/\n\n     DLTF_ALL                              = 0x0000000F          /* All type flags set. */\n} DFBDisplayLayerTypeFlags;\n\n/*\n * Capabilities of a display layer.\n */\ntypedef enum {\n     DLCAPS_NONE                           = 0x00000000,         /* None of these. */\n\n     DLCAPS_SURFACE                        = 0x00000001,         /* The layer has a surface that can be drawn to. This\n                                                                    may not be provided by layers that display realtime\n                                                                    data, e.g. from an MPEG decoder chip. Playback\n                                                                    control may be provided by an external API. */\n     DLCAPS_OPACITY                        = 0x00000002,         /* The layer supports blending with layer(s) below\n                                                                    based on a global alpha factor. */\n     DLCAPS_ALPHACHANNEL                   = 0x00000004,         /* The layer supports blending with layer(s) below\n                                                                    based on each pixel's alpha value. */\n     DLCAPS_SCREEN_LOCATION                = 0x00000008,         /* The layer location on the screen can be changed,\n                                                                    this includes position and size as normalized\n                                                                    values.\n                                                                    This implies DLCAPS_SCREEN_POSITION and _SIZE. */\n     DLCAPS_FLICKER_FILTERING              = 0x00000010,         /* Flicker filtering can be enabled for smooth output\n                                                                    on interlaced display devices. */\n     DLCAPS_DEINTERLACING                  = 0x00000020,         /* The layer provides optional deinterlacing for\n                                                                    displaying interlaced video data on progressive\n                                                                    display devices. */\n     DLCAPS_SRC_COLORKEY                   = 0x00000040,         /* A specific color can be declared as transparent. */\n     DLCAPS_DST_COLORKEY                   = 0x00000080,         /* A specific color of layers below can be specified\n                                                                    as the color of the only locations where the layer\n                                                                    is visible. */\n     DLCAPS_BRIGHTNESS                     = 0x00000100,         /* Adjustment of brightness is supported. */\n     DLCAPS_CONTRAST                       = 0x00000200,         /* Adjustment of contrast is supported. */\n     DLCAPS_HUE                            = 0x00000400,         /* Adjustment of hue is supported. */\n     DLCAPS_SATURATION                     = 0x00000800,         /* Adjustment of saturation is supported. */\n     DLCAPS_LEVELS                         = 0x00001000,         /* Adjustment of the layer's level\n                                                                    (z position) is supported. */\n     DLCAPS_FIELD_PARITY                   = 0x00002000,         /* Field parity can be selected */\n     DLCAPS_WINDOWS                        = 0x00004000,         /* Hardware window support. */\n     DLCAPS_SOURCES                        = 0x00008000,         /* Sources can be selected. */\n     DLCAPS_ALPHA_RAMP                     = 0x00010000,         /* Alpha values for formats with one or two alpha bits\n                                                                    can be chosen, i.e. using ARGB1555 or ARGB2554 the\n                                                                    user can define the meaning of the two or four\n                                                                    possibilities. In short, this feature provides a\n                                                                    lookup table for the alpha bits of these formats. */\n     DLCAPS_PREMULTIPLIED                  = 0x00020000,         /* Surfaces with premultiplied alpha are supported. */\n\n     DLCAPS_SCREEN_POSITION                = 0x00100000,         /* The layer position on the screen can be changed. */\n     DLCAPS_SCREEN_SIZE                    = 0x00200000,         /* The layer size (defined by its source rectangle)\n                                                                    can be scaled to a different size on the screen\n                                                                    (defined by its screen/destination rectangle or\n                                                                    its normalized size) and does not have to be 1:1\n                                                                    with it. */\n     DLCAPS_CLIP_REGIONS                   = 0x00400000,         /* Supports SetClipRegions(). */\n\n     DLCAPS_LR_MONO                        = 0x01000000,         /* Supports L/R mono stereoscopic display. */\n     DLCAPS_STEREO                         = 0x02000000,         /* Supports independent L/R stereoscopic display. */\n\n     DLCAPS_ALL                            = 0x0373FFFF          /* All of these. */\n} DFBDisplayLayerCapabilities;\n\n#define DFB_DISPLAY_LAYER_DESC_NAME_LENGTH   32\n\n/*\n * Description of the display layer capabilities.\n */\ntypedef struct {\n     DFBDisplayLayerTypeFlags                type;               /* Classification of the display layer. */\n     DFBDisplayLayerCapabilities             caps;               /* Capability flags of the display layer. */\n\n     char name[DFB_DISPLAY_LAYER_DESC_NAME_LENGTH];              /* Display layer name. */\n\n     int                                     level;              /* Default level. */\n     int                                     regions;            /* Number of concurrent regions supported:\n                                                                      -1 = unlimited,\n                                                                       0 = unknown/one,\n                                                                      >0 = actual number */\n     int                                     sources;            /* Number of selectable sources. */\n     int                                     clip_regions;       /* Number of clipping regions. */\n     DFBSurfaceCapabilities                  surface_caps;       /* Capabilities. */\n     unsigned int                            surface_accessor;   /* Accessor. */\n} DFBDisplayLayerDescription;\n\n/*\n * Type of input device for basic classification.\n */\ntypedef enum {\n     DIDTF_NONE                            = 0x00000000,         /* Unclassified, no specific type. */\n\n     DIDTF_KEYBOARD                        = 0x00000001,         /* Is a keyboard. */\n     DIDTF_MOUSE                           = 0x00000002,         /* Is a mouse. */\n     DIDTF_JOYSTICK                        = 0x00000004,         /* Is a joystick. */\n     DIDTF_REMOTE                          = 0x00000008,         /* Is a remote control. */\n     DIDTF_VIRTUAL                         = 0x00000010,         /* Is a virtual input device. */\n     DIDTF_BUTTONS                         = 0x00000020,         /* Is buttons. */\n\n     DIDTF_ALL                             = 0x0000003F          /* All type flags set. */\n} DFBInputDeviceTypeFlags;\n\n/*\n * Basic input device features.\n */\ntypedef enum {\n     DICAPS_KEYS                           = 0x00000001,         /* device supports key events */\n     DICAPS_AXES                           = 0x00000002,         /* device supports axis events */\n     DICAPS_BUTTONS                        = 0x00000004,         /* device supports button events */\n\n     DICAPS_ALL                            = 0x00000007          /* all capabilities */\n} DFBInputDeviceCapabilities;\n\n/*\n * Axis identifier (index) for mouse or joystick.\n *\n * The X, Y and Z axis are predefined. To access other axes,\n * use DIAI_FIRST plus a zero based index, e.g. the 4th axis\n * would be (DIAI_FIRST + 3).\n */\ntypedef enum {\n     DIAI_X                                = 0x00000000,         /* X axis */\n     DIAI_Y                                = 0x00000001,         /* Y axis */\n     DIAI_Z                                = 0x00000002,         /* Z axis */\n     DIAI_FIRST                            = DIAI_X,             /* other axis:\n                                                                    DIAI_FIRST + zero based index */\n     DIAI_LAST                             = 0x0000001F          /* 32 axes maximum */\n} DFBInputDeviceAxisIdentifier;\n\n/*\n * Identifier (index) for e.g. mouse or joystick buttons.\n */\ntypedef enum {\n     DIBI_LEFT                             = 0x00000000,         /* left mouse button */\n     DIBI_RIGHT                            = 0x00000001,         /* right mouse button */\n     DIBI_MIDDLE                           = 0x00000002,         /* middle mouse button */\n     DIBI_FIRST                            = DIBI_LEFT,          /* other buttons:\n                                                                    DIBI_FIRST + zero based index */\n     DIBI_LAST                             = 0x0000001F          /* 32 buttons maximum */\n} DFBInputDeviceButtonIdentifier;\n\n#define DFB_INPUT_DEVICE_DESC_NAME_LENGTH    32\n#define DFB_INPUT_DEVICE_DESC_VENDOR_LENGTH  40\n\n/*\n * Description of the input device capabilities.\n */\ntypedef struct {\n     DFBInputDeviceTypeFlags                 type;               /* classification of input device */\n     DFBInputDeviceCapabilities              caps;               /* capabilities, validates the following fields */\n     int                                     min_keycode;        /* minimum hardware keycode or -1 if no differentiation\n                                                                    between hardware keys is made */\n     int                                     max_keycode;        /* maximum hardware keycode or -1 if no differentiation\n                                                                    between hardware keys is made */\n     DFBInputDeviceAxisIdentifier            max_axis;           /* highest axis identifier */\n     DFBInputDeviceButtonIdentifier          max_button;         /* highest button identifier */\n\n     char name[DFB_INPUT_DEVICE_DESC_NAME_LENGTH];               /* device name */\n     char vendor[DFB_INPUT_DEVICE_DESC_VENDOR_LENGTH];           /* device vendor */\n\n     int                                     vendor_id;          /* vendor ID */\n     int                                     product_id;         /* product ID */\n} DFBInputDeviceDescription;\n\n/*\n * Flags defining which fields of a DFBFontDescription are\n * valid.\n */\ntypedef enum {\n     DFDESC_ATTRIBUTES                     = 0x00000001,         /* attributes field is valid */\n     DFDESC_HEIGHT                         = 0x00000002,         /* height is specified */\n     DFDESC_WIDTH                          = 0x00000004,         /* width is specified */\n     DFDESC_INDEX                          = 0x00000008,         /* index is specified */\n     DFDESC_FIXEDADVANCE                   = 0x00000010,         /* specify a fixed advance overriding any character\n                                                                    advance of fixed or proportional fonts */\n     DFDESC_FRACT_HEIGHT                   = 0x00000020,         /* fractional height is set */\n     DFDESC_FRACT_WIDTH                    = 0x00000040,         /* fractional width is set */\n     DFDESC_OUTLINE_WIDTH                  = 0x00000080,         /* outline width is set */\n     DFDESC_OUTLINE_OPACITY                = 0x00000100,         /* outline opacity is set */\n     DFDESC_ROTATION                       = 0x00000200          /* rotation is set */\n} DFBFontDescriptionFlags;\n\n/*\n * Flags describing how to load a font.\n *\n * These flags describe how a font is loaded and affect how the\n * glyphs are drawn. There is no way to change this after the\n * font has been loaded.\n * If you need to render a font with different attributes, you\n * have to create multiple FontProviders of the same font file.\n */\ntypedef enum {\n     DFFA_NONE                             = 0x00000000,         /* none of these flags */\n\n     DFFA_NOKERNING                        = 0x00000001,         /* don't use kerning */\n     DFFA_NOHINTING                        = 0x00000002,         /* don't use hinting */\n     DFFA_MONOCHROME                       = 0x00000004,         /* don't use anti-aliasing */\n     DFFA_NOCHARMAP                        = 0x00000008,         /* no char map, glyph indices are specified directly */\n     DFFA_FIXEDCLIP                        = 0x00000010,         /* width fixed advance, clip to it */\n     DFFA_NOBITMAP                         = 0x00000020,         /* ignore bitmap strikes; for bitmap-only fonts this\n                                                                    flag is ignored */\n     DFFA_OUTLINED                         = 0x00000040,         /* outlined font */\n     DFFA_AUTOHINTING                      = 0x00000080,         /* prefer auto-hinter over the font's native hinter */\n     DFFA_SOFTHINTING                      = 0x00000100,         /* use a lighter hinting algorithm that produces glyphs\n                                                                    that are more fuzzy but better resemble the original\n                                                                    shape */\n     DFFA_STYLE_ITALIC                     = 0x00000200,         /* load italic style */\n     DFFA_VERTICAL_LAYOUT                  = 0x00000400,         /* load vertical layout */\n     DFFA_STYLE_BOLD                       = 0x00000800          /* load bold style */\n} DFBFontAttributes;\n\n/*\n * Description of how to load glyphs from a font file.\n *\n * The attributes control how the glyphs are rendered. Width and\n * height can be used to specify the desired face size in\n * pixels. If you are loading a non-scalable font, you shouldn't\n * specify a font size.\n * Please note that the height value in the DFBFontDescription\n * doesn't correspond to the height returned by GetHeight().\n * The index field controls which face is loaded from a font\n * file that provides a collection of faces.\n * Fractional sizes (fract_height and fract_width) are 26.6\n * fixed point integers and override the pixel sizes if both are\n * specified.\n * Outline parameters are ignored if DFFA_OUTLINED is not used.\n * To change the default values of 1.0 each use\n * DFDESC_OUTLINE_WIDTH and/or DFDESC_OUTLINE_OPACITY.\n * The rotation value is a 0.24 fixed point number of rotations.\n * Use the macros DFB_DEGREES and DFB_RADIANS to convert from\n * those units.\n */\ntypedef struct {\n     DFBFontDescriptionFlags                 flags;              /* field validation */\n\n     DFBFontAttributes                       attributes;         /* font attributes */\n     int                                     height;             /* font height */\n     int                                     width;              /* font width */\n     unsigned int                            index;              /* font index */\n     int                                     fixed_advance;      /* fixed advance */\n     int                                     fract_height;       /* fractional height */\n     int                                     fract_width;        /* fractional width */\n     int                                     outline_width;      /* outline width as 16.16 fixed point integer */\n     int                                     outline_opacity;    /* outline opacity as 16.16 fixed point integer */\n     int                                     rotation;           /* font rotation */\n} DFBFontDescription;\n\n/*\n * Flags defining which fields of a DFBDataBufferDescription are\n * valid.\n */\ntypedef enum {\n     DBDESC_FILE                           = 0x00000001,         /* Create a static buffer for the\n                                                                    specified filename. */\n     DBDESC_MEMORY                         = 0x00000002          /* Create a static buffer for the\n                                                                    specified memory area. */\n} DFBDataBufferDescriptionFlags;\n\n/*\n * Description of a data buffer that is to be created.\n */\ntypedef struct {\n     DFBDataBufferDescriptionFlags           flags;              /* field validation */\n\n     const char                             *file;               /* for file based data buffers */\n     struct {\n          const void                        *data;               /* static data pointer */\n          unsigned int                       length;             /* length of buffer */\n     } memory;                                                   /* memory based buffers */\n} DFBDataBufferDescription;\n\n/*\n * Called for each supported video mode.\n */\ntypedef DFBEnumerationResult (*DFBVideoModeCallback) (\n     int                                     width,\n     int                                     height,\n     int                                     bpp,\n     void                                   *callbackdata\n);\n\n/*\n * Called for each existing screen.\n * 'screen_id' can be used to get an interface to the screen.\n */\ntypedef DFBEnumerationResult (*DFBScreenCallback) (\n     DFBScreenID                             screen_id,\n     DFBScreenDescription                    desc,\n     void                                   *callbackdata\n);\n\n/*\n * Called for each existing display layer.\n * 'layer_id' can be used to get an interface to the layer.\n */\ntypedef DFBEnumerationResult (*DFBDisplayLayerCallback) (\n     DFBDisplayLayerID                       layer_id,\n     DFBDisplayLayerDescription              desc,\n     void                                   *callbackdata\n);\n\n/*\n * Called for each existing input device.\n * 'device_id' can be used to get an interface to the device.\n */\ntypedef DFBEnumerationResult (*DFBInputDeviceCallback) (\n     DFBInputDeviceID                        device_id,\n     DFBInputDeviceDescription               desc,\n     void                                   *callbackdata\n);\n\n/*\n * IDirectFB is the main interface. It can be retrieved by a\n * call to DirectFBCreate(). It's the only interface with a\n * global creation facility. Other interfaces are created by\n * this interface or interfaces created by it.\n *\n * Hardware capabilities such as the amount of video memory or\n * a list of supported drawing/blitting functions and flags can\n * be retrieved. It also provides enumeration of all supported\n * video modes.\n *\n * Input devices and display layers> that are present can be\n * enumerated via a callback mechanism.The callback is given the\n * capabilities and the device or layer ID.\n * An interface to specific input devices or display layers\n * can be retrieved by passing the device or layer ID to the\n * corresponding method.\n *\n * Surfaces for general purpose use can be created via\n * CreateSurface(). These surfaces are so called \"offscreen\n * surfaces\" and could be used for sprites or icons.\n *\n * The primary surface is an abstraction and API shortcut for\n * getting a surface for visual output. Fullscreen games for\n * example have the whole screen as their primary surface.\n * Alternatively fullscreen applications can be forced to run\n * in a window. The primary surface is also created via\n * CreateSurface() but with the special capability\n * DSCAPS_PRIMARY.\n *\n * The cooperative level selects the type of the primary\n * surface. With a call to SetCooperativeLevel() the\n * application can choose between the surface of an implicitly\n * created window and the surface of the primary layer\n * (deactivating the window stack). The application doesn't need\n * to have any extra functionality to run in a window. If the\n * application is forced to run in a window the call to\n * SetCooperativeLevel() fails with DFB_ACCESSDENIED.\n * Applications that want to be \"window aware\" shouldn't exit on\n * this error.\n *\n * The video mode can be changed via SetVideoMode() and is the\n * size and depth of the primary surface, i.e. the * screen when\n * in exclusive cooperative level.\n * Without exclusive access SetVideoMode() sets the size of the\n * implicitly created window.\n *\n * Event buffers can be created with an option to automatically\n * attach input devices matching the specified capabilities.\n * If DICAPS_NONE is passed, an event buffer with nothing\n * attached to is created. An event buffer can be attached to\n * input devices and windows.\n *\n * Fonts, images and videos are created by this interface. There\n * are different implementations for different content types. On\n * creation a suitable implementation is automatically chosen.\n */\nD_DEFINE_INTERFACE( IDirectFB,\n\n   /** Cooperative level, video mode **/\n\n     /*\n      * Put the interface into the specified cooperative level.\n      *\n      * Function fails with DFB_LOCKED if another instance is\n      * already in a cooperative level other than DFSCL_NORMAL.\n      */\n     DFBResult (*SetCooperativeLevel) (\n          IDirectFB                         *thiz,\n          DFBCooperativeLevel                level\n     );\n\n     /*\n      * Switch the current video mode (primary layer).\n      *\n      * If in shared cooperative level this function sets the\n      * resolution of the window that is created implicitly for\n      * the primary surface.\n      * The following values are valid for bpp:\n      *   2, 8, 12, 14, 15, 18, 24, 32.\n      * These will result in the following formats, respectively\n      * DSPF_LUT2, DSPF_LUT8, DSPF_ARGB4444, DSPF_ARGB2554,\n      * DSPF_ARGB1555, DSPF_RGB16, DSPF_RGB18, DSPF_RGB24,\n      * DSPF_RGB32.\n      */\n     DFBResult (*SetVideoMode) (\n          IDirectFB                         *thiz,\n          int                                width,\n          int                                height,\n          int                                bpp\n     );\n\n   /** Hardware capabilities **/\n\n     /*\n      * Get a description of the graphics device.\n      *\n      * For more detailed information use GetAccelerationMask().\n      */\n     DFBResult (*GetDeviceDescription) (\n          IDirectFB                         *thiz,\n          DFBGraphicsDeviceDescription      *ret_desc\n     );\n\n     /*\n      * Enumerate supported video modes.\n      *\n      * Calls the given callback for all available video modes.\n      * Useful to select a certain mode to be used with\n      * SetVideoMode().\n      */\n     DFBResult (*EnumVideoModes) (\n          IDirectFB                         *thiz,\n          DFBVideoModeCallback               callback,\n          void                              *callbackdata\n     );\n\n   /** Surfaces & Palettes **/\n\n     /*\n      * Create a surface matching the specified description.\n      */\n     DFBResult (*CreateSurface) (\n          IDirectFB                         *thiz,\n          const DFBSurfaceDescription       *desc,\n          IDirectFBSurface                 **ret_interface\n     );\n\n     /*\n      * Create a palette matching the specified description.\n      *\n      * Passing a NULL description creates a default palette\n      * with 256 entries filled with colors matching the\n      * RGB332 format.\n      */\n     DFBResult (*CreatePalette) (\n          IDirectFB                         *thiz,\n          const DFBPaletteDescription       *desc,\n          IDirectFBPalette                 **ret_interface\n     );\n\n   /** Screens **/\n\n     /*\n      * Enumerate all existing screen.\n      *\n      * Calls the given callback for each available screen.\n      * The callback is passed the screen id that can be used\n      * to retrieve an interface to a specific screen using\n      * GetScreen().\n      */\n     DFBResult (*EnumScreens) (\n          IDirectFB                         *thiz,\n          DFBScreenCallback                  callback,\n          void                              *callbackdata\n     );\n\n     /*\n      * Retrieve an interface to a specific screen.\n      */\n     DFBResult (*GetScreen) (\n          IDirectFB                         *thiz,\n          DFBScreenID                        screen_id,\n          IDirectFBScreen                  **ret_interface\n     );\n\n   /** Display Layers **/\n\n     /*\n      * Enumerate all existing display layers.\n      *\n      * Calls the given callback for each available display\n      * layer. The callback is passed the layer id that can be\n      * used to retrieve an interface to a specific layer using\n      * GetDisplayLayer().\n      */\n     DFBResult (*EnumDisplayLayers) (\n          IDirectFB                         *thiz,\n          DFBDisplayLayerCallback            callback,\n          void                              *callbackdata\n     );\n\n     /*\n      * Retrieve an interface to a specific display layer.\n      *\n      * The default 'layer_id' is DLID_PRIMARY.\n      * Others can be obtained using EnumDisplayLayers().\n      */\n     DFBResult (*GetDisplayLayer) (\n          IDirectFB                         *thiz,\n          DFBDisplayLayerID                  layer_id,\n          IDirectFBDisplayLayer            **ret_interface\n     );\n\n   /** Input Devices **/\n\n     /*\n      * Enumerate all existing input devices.\n      *\n      * Calls the given callback for all available input\n      * devices.\n      * The callback is passed the device id that can be used to\n      * retrieve an interface on a specific device using\n      * GetInputDevice().\n      */\n     DFBResult (*EnumInputDevices) (\n          IDirectFB                         *thiz,\n          DFBInputDeviceCallback             callback,\n          void                              *callbackdata\n     );\n\n     /*\n      * Retrieve an interface to a specific input device.\n      */\n     DFBResult (*GetInputDevice) (\n          IDirectFB                         *thiz,\n          DFBInputDeviceID                   device_id,\n          IDirectFBInputDevice             **ret_interface\n     );\n\n     /*\n      * Create a buffer for events.\n      *\n      * Creates an empty event buffer without event sources\n      * connected to it.\n      */\n     DFBResult (*CreateEventBuffer) (\n          IDirectFB                         *thiz,\n          IDirectFBEventBuffer             **ret_interface\n     );\n\n     /*\n      * Create a buffer for events with input devices connected.\n      *\n      * Creates an event buffer and attaches all input devices\n      * with matching capabilities. If no input devices match,\n      * e.g. by specifying DICAPS_NONE, a buffer will be\n      * returned that has no event sources connected to it.\n      * If 'global' is DFB_FALSE, events will only be delivered\n      * if this instance of IDirectFB has a focused primary\n      * (either running fullscreen or running in windowed mode\n      * with the window being focused).\n      * If 'global' is DFB_TRUE no event will be discarded.\n      */\n     DFBResult (*CreateInputEventBuffer) (\n          IDirectFB                         *thiz,\n          DFBInputDeviceCapabilities         caps,\n          DFBBoolean                         global,\n          IDirectFBEventBuffer             **ret_interface\n     );\n\n   /** Media **/\n\n     /*\n      * Create an image provider for the specified file.\n      */\n     DFBResult (*CreateImageProvider) (\n          IDirectFB                         *thiz,\n          const char                        *filename,\n          IDirectFBImageProvider           **ret_interface\n     );\n\n     /*\n      * Create a video provider.\n      */\n     DFBResult (*CreateVideoProvider) (\n          IDirectFB                         *thiz,\n          const char                        *filename,\n          IDirectFBVideoProvider           **ret_interface\n     );\n\n     /*\n      * Load a font from the specified file given a description\n      * of how to load the glyphs.\n      */\n     DFBResult (*CreateFont) (\n          IDirectFB                         *thiz,\n          const char                        *filename,\n          const DFBFontDescription          *desc,\n          IDirectFBFont                    **ret_interface\n     );\n\n     /*\n      * Create a data buffer.\n      *\n      * If no description is specified (NULL), a streamed\n      * data buffer is created.\n      */\n     DFBResult (*CreateDataBuffer) (\n          IDirectFB                         *thiz,\n          const DFBDataBufferDescription    *desc,\n          IDirectFBDataBuffer              **ret_interface\n     );\n\n   /** Clipboard **/\n\n     /*\n      * Set clipboard content.\n      */\n     DFBResult (*SetClipboardData) (\n          IDirectFB                         *thiz,\n          const char                        *mime_type,\n          const void                        *clip_data,\n          unsigned int                       size,\n          struct timeval                    *timestamp\n     );\n\n     /*\n      * Get clipboard content.\n      *\n      * Memory returned in '*ret_mimetype' and '*ret_clip_data'\n      * has to be freed.\n      */\n     DFBResult (*GetClipboardData) (\n          IDirectFB                         *thiz,\n          char                             **ret_mimetype,\n          void                             **ret_clip_data,\n          unsigned int                      *ret_size\n     );\n\n     /*\n      * Get time stamp of last SetClipboardData() call.\n      */\n     DFBResult (*GetClipboardTimeStamp) (\n          IDirectFB                         *thiz,\n          struct timeval                    *ret_timestamp\n     );\n\n   /** Misc **/\n\n     /*\n      * Suspend, no other calls are allowed until Resume()\n      * has been called.\n      */\n     DFBResult (*Suspend) (\n          IDirectFB                         *thiz\n     );\n\n     /*\n      * Resume, only to be called after Suspend().\n      */\n     DFBResult (*Resume) (\n          IDirectFB                         *thiz\n     );\n\n     /*\n      * Wait until graphics card is idle,\n      * i.e. finish all drawing/blitting functions.\n      */\n     DFBResult (*WaitIdle) (\n          IDirectFB                         *thiz\n     );\n\n     /*\n      * Wait for next vertical retrace.\n      */\n     DFBResult (*WaitForSync) (\n          IDirectFB                         *thiz\n     );\n\n   /** Extensions **/\n\n     /*\n      * Load an implementation of a specific interface type.\n      *\n      * This methods loads an interface implementation of the\n      * specified 'type' of interface, e.g. \"IDirectFBWindows\".\n      * A specific implementation can be forced with the\n      * optional 'implementation' argument.\n      * Implementations are passed 'arg' during probing and\n      * construction.\n      * If an implementation has been successfully probed and\n      * the interface has been constructed, the resulting\n      * interface pointer is stored in 'interface'.\n      */\n     DFBResult (*GetInterface) (\n          IDirectFB                         *thiz,\n          const char                        *type,\n          const char                        *implementation,\n          void                              *arg,\n          void                             **ret_interface\n     );\n\n   /** Surfaces **/\n\n     /*\n      * Get a surface by ID.\n      */\n     DFBResult (*GetSurface) (\n          IDirectFB                         *thiz,\n          DFBSurfaceID                       surface_id,\n          IDirectFBSurface                 **ret_interface\n     );\n\n     /*\n      * Get surface pixel format suitable for fonts.\n      */\n     DFBResult (*GetFontSurfaceFormat) (\n          IDirectFB                         *thiz,\n          DFBSurfacePixelFormat             *ret_fontformat\n     );\n)\n\n/*******************\n * IDirectFBScreen *\n *******************/\n\n/*\n * Screen Power Mode.\n */\ntypedef enum {\n     DSPM_ON                               = 0x00000000,         /* On. */\n     DSPM_STANDBY                          = 0x00000001,         /* Standby. */\n     DSPM_SUSPEND                          = 0x00000002,         /* Suspend. */\n     DSPM_OFF                              = 0x00000003          /* Off. */\n} DFBScreenPowerMode;\n\n/*\n * Capabilities of a mixer.\n */\ntypedef enum {\n     DSMCAPS_NONE                          = 0x00000000,         /* None of these. */\n\n     DSMCAPS_FULL                          = 0x00000001,         /* Can mix full tree as specified in the\n                                                                    description. */\n     DSMCAPS_SUB_LEVEL                     = 0x00000002,         /* Can set a maximum layer level,\n                                                                    e.g. to exclude an OSD from VCR output. */\n     DSMCAPS_SUB_LAYERS                    = 0x00000004,         /* Can select a number of layers individually\n                                                                    as specified in the description. */\n     DSMCAPS_BACKGROUND                    = 0x00000008          /* Background color is configurable. */\n} DFBScreenMixerCapabilities;\n\n#define DFB_SCREEN_MIXER_DESC_NAME_LENGTH    24\n\n/*\n * Description of a mixer.\n */\ntypedef struct {\n     DFBScreenMixerCapabilities              caps;               /* Mixer capabilities. */\n     DFBDisplayLayerIDs                      layers;             /* Visible layers if the full tree is selected. */\n     int                                     sub_num;            /* Number of layers that can be selected\n                                                                    in sub mode. */\n     DFBDisplayLayerIDs                      sub_layers;         /* Layers available for sub mode\n                                                                    with layer selection. */\n\n     char name[DFB_SCREEN_MIXER_DESC_NAME_LENGTH];               /* Mixer name. */\n} DFBScreenMixerDescription;\n\n/*\n * Flags for mixer configuration.\n */\ntypedef enum {\n     DSMCONF_NONE                          = 0x00000000,         /* None of these. */\n\n     DSMCONF_TREE                          = 0x00000001,         /* (Sub) tree is selected. */\n     DSMCONF_LEVEL                         = 0x00000002,         /* Level is specified. */\n     DSMCONF_LAYERS                        = 0x00000004,         /* Layer selection is set. */\n\n     DSMCONF_BACKGROUND                    = 0x00000010,         /* Background color is set. */\n\n     DSMCONF_ALL                           = 0x00000017          /* All of these. */\n} DFBScreenMixerConfigFlags;\n\n/*\n * (Sub) tree selection.\n */\ntypedef enum {\n     DSMT_UNKNOWN                          = 0x00000000,         /* Unknown mode */\n\n     DSMT_FULL                             = 0x00000001,         /* Full tree. */\n     DSMT_SUB_LEVEL                        = 0x00000002,         /* Sub tree via maximum level. */\n     DSMT_SUB_LAYERS                       = 0x00000003          /* Sub tree via layer selection. */\n} DFBScreenMixerTree;\n\n/*\n * Configuration of a mixer.\n */\ntypedef struct {\n     DFBScreenMixerConfigFlags               flags;              /* Validates struct members. */\n\n     DFBScreenMixerTree                      tree;               /* Selected (sub) tree. */\n     int                                     level;              /* Maximum level of sub level mode. */\n     DFBDisplayLayerIDs                      layers;             /* Layers for sub layers mode. */\n     DFBColor                                background;         /* Background color. */\n} DFBScreenMixerConfig;\n\n/*\n * Capabilities of a display encoder.\n */\ntypedef enum {\n     DSECAPS_NONE                          = 0x00000000,         /* None of these. */\n\n     DSECAPS_TV_STANDARDS                  = 0x00000001,         /* TV standards can be selected. */\n     DSECAPS_TEST_PICTURE                  = 0x00000002,         /* Test picture generation supported. */\n     DSECAPS_MIXER_SEL                     = 0x00000004,         /* Mixer can be selected. */\n     DSECAPS_OUT_SIGNALS                   = 0x00000008,         /* Different output signals are supported. */\n     DSECAPS_SCANMODE                      = 0x00000010,         /* Can switch between interlaced and progressive\n                                                                    output. */\n     DSECAPS_FREQUENCY                     = 0x00000020,         /* Can switch between different frequencies. */\n\n     DSECAPS_BRIGHTNESS                    = 0x00000100,         /* Adjustment of brightness is supported. */\n     DSECAPS_CONTRAST                      = 0x00000200,         /* Adjustment of contrast is supported. */\n     DSECAPS_HUE                           = 0x00000400,         /* Adjustment of hue is supported. */\n     DSECAPS_SATURATION                    = 0x00000800,         /* Adjustment of saturation is supported. */\n     DSECAPS_CONNECTORS                    = 0x00001000,         /* Select output connector(s). */\n     DSECAPS_SLOW_BLANKING                 = 0x00002000,         /* Slow Blanking on outputs is supported. */\n     DSECAPS_RESOLUTION                    = 0x00004000,         /* Different encoder resolutions supported */\n     DSECAPS_FRAMING                       = 0x00008000,         /* Can select picture framing mode for stereo */\n     DSECAPS_ASPECT_RATIO                  = 0x00010000,         /* Can specify display aspect ratio */\n\n     DSECAPS_ALL                           = 0x0001FF3F          /* All of these. */\n} DFBScreenEncoderCapabilities;\n\n/*\n * Type of display encoder.\n */\ntypedef enum {\n     DSET_UNKNOWN                          = 0x00000000,         /* Unknown type */\n\n     DSET_CRTC                             = 0x00000001,         /* Encoder is a CRTC. */\n     DSET_TV                               = 0x00000002,         /* TV output encoder. */\n     DSET_DIGITAL                          = 0x00000004          /* Support signals other than SD TV standards. */\n} DFBScreenEncoderType;\n\n/*\n * TV standards.\n */\ntypedef enum {\n     DSETV_UNKNOWN                         = 0x00000000,         /* Unknown standard */\n\n     DSETV_PAL                             = 0x00000001,         /* PAL */\n     DSETV_NTSC                            = 0x00000002,         /* NTSC */\n     DSETV_SECAM                           = 0x00000004,         /* SECAM */\n     DSETV_PAL_60                          = 0x00000008,         /* PAL-60 */\n     DSETV_PAL_BG                          = 0x00000010,         /* PAL BG support (specific) */\n     DSETV_PAL_I                           = 0x00000020,         /* PAL I support (specific) */\n     DSETV_PAL_M                           = 0x00000040,         /* PAL M support (specific) */\n     DSETV_PAL_N                           = 0x00000080,         /* PAL N support (specific) */\n     DSETV_PAL_NC                          = 0x00000100,         /* PAL NC support (specific) */\n     DSETV_NTSC_M_JPN                      = 0x00000200,         /* NTSC_JPN support */\n     DSETV_DIGITAL                         = 0x00000400,         /* TV standards from the digital domain */\n     DSETV_NTSC_443                        = 0x00000800,         /* NTSC with 4.43MHz colour carrier */\n\n     DSETV_ALL                             = 0x00000FFF          /* All TV Standards */\n} DFBScreenEncoderTVStandards;\n\n/*\n * Type of output signal.\n */\ntypedef enum {\n     DSOS_NONE                             = 0x00000000,         /* No signal */\n\n     DSOS_VGA                              = 0x00000001,         /* VGA signal */\n     DSOS_YC                               = 0x00000002,         /* Y/C signal */\n     DSOS_CVBS                             = 0x00000004,         /* CVBS signal */\n     DSOS_RGB                              = 0x00000008,         /* R/G/B signal */\n     DSOS_YCBCR                            = 0x00000010,         /* Y/Cb/Cr signal */\n     DSOS_HDMI                             = 0x00000020,         /* HDMI signal */\n     DSOS_656                              = 0x00000040,         /* 656 Digital output signal */\n     DSOS_DSI                              = 0x00000080          /* DSI signal */\n} DFBScreenOutputSignals;\n\n/*\n * Type of output connector.\n */\ntypedef enum {\n     DSOC_UNKNOWN                          = 0x00000000,         /* Unknown type */\n\n     DSOC_VGA                              = 0x00000001,         /* VGA connector */\n     DSOC_SCART                            = 0x00000002,         /* SCART connector */\n     DSOC_YC                               = 0x00000004,         /* Y/C connector */\n     DSOC_CVBS                             = 0x00000008,         /* CVBS connector */\n     DSOC_SCART2                           = 0x00000010,         /* 2nd SCART connector */\n     DSOC_COMPONENT                        = 0x00000020,         /* Component video connector */\n     DSOC_HDMI                             = 0x00000040,         /* HDMI connector */\n     DSOC_656                              = 0x00000080,         /* DVO connector */\n     DSOC_DSI                              = 0x00000100          /* DSI connector */\n} DFBScreenOutputConnectors;\n\n/*\n * Resolutions.\n */\ntypedef enum {\n    DSOR_UNKNOWN                           = 0x00000000,         /* Unknown Resolution */\n\n    DSOR_640_480                           = 0x00000001,         /* 640x480 Resolution */\n    DSOR_720_480                           = 0x00000002,         /* 720x480 Resolution */\n    DSOR_720_576                           = 0x00000004,         /* 720x576 Resolution */\n    DSOR_800_600                           = 0x00000008,         /* 800x600 Resolution */\n    DSOR_1024_768                          = 0x00000010,         /* 1024x768 Resolution */\n    DSOR_1152_864                          = 0x00000020,         /* 1152x864 Resolution */\n    DSOR_1280_720                          = 0x00000040,         /* 1280x720 Resolution */\n    DSOR_1280_768                          = 0x00000080,         /* 1280x768 Resolution */\n    DSOR_1280_960                          = 0x00000100,         /* 1280x960 Resolution */\n    DSOR_1280_1024                         = 0x00000200,         /* 1280x1024 Resolution */\n    DSOR_1400_1050                         = 0x00000400,         /* 1400x1050 Resolution */\n    DSOR_1600_1200                         = 0x00000800,         /* 1600x1200 Resolution */\n    DSOR_1920_1080                         = 0x00001000,         /* 1920x1080 Resolution */\n    DSOR_960_540                           = 0x00002000,         /* 960x540 Resolution */\n    DSOR_1440_540                          = 0x00004000,         /* 1440x540 Resolution */\n    DSOR_800_480                           = 0x00008000,         /* 800x480 Resolution */\n    DSOR_1024_600                          = 0x00010000,         /* 1024x600 Resolution */\n    DSOR_1366_768                          = 0x00020000,         /* 1366x768 Resolution */\n    DSOR_1920_1200                         = 0x00040000,         /* 1920x1200 Resolution */\n    DSOR_2560_1440                         = 0x00080000,         /* 2560x1440 Resolution */\n    DSOR_2560_1600                         = 0x00100000,         /* 2650x1600 Resolution */\n    DSOR_3840_2160                         = 0x00200000,         /* 3840x2160 Resolution */\n    DSOR_4096_2160                         = 0x00400000,         /* 4096x2160 Resolution */\n\n    DSOR_ALL                               = 0x004FFFFF          /* All Resolutions */\n} DFBScreenOutputResolution;\n\n/*\n * Encoder picture delivery method.\n */\ntypedef enum {\n     DSEPF_UNKNOWN                         = 0x00000000,         /* Unknown encoder picture framing */\n\n     DSEPF_MONO                            = 0x00000001,         /* Normal output to non-stereoscopic (3D) TV.\n                                                                    No L/R content provided to TV. Frame is output on\n                                                                    each vsync. */\n     DSEPF_STEREO_SIDE_BY_SIDE_HALF        = 0x00000002,         /* L/R frames are downscaled horizontally by 2 and\n                                                                    packed side-by-side into a single frame, left on\n                                                                    left half of frame. The packed frame is output on\n                                                                    each vsync. Some stereoscopic TV's support this mode\n                                                                    using HDMI v1.3 and a special menu configuration. */\n     DSEPF_STEREO_TOP_AND_BOTTOM           = 0x00000004,         /* L/R frames are downscaled vertically by 2 and packed\n                                                                    into a single frame, left on top. The packed frame\n                                                                    is output on each vsync. Some stereoscopic TV's\n                                                                    support this mode using HDMI v1.3 and a special menu\n                                                                    configuration. */\n     DSEPF_STEREO_FRAME_PACKING            = 0x00000008,         /* Full resolution L/R frames or fields are delivered\n                                                                    sequentially to the TV, alternating left & right\n                                                                    with an active space between each video frame. Vsync\n                                                                    occurs after each sequence of: vblank, left eye\n                                                                    video frame, active space, right eye video frame.\n                                                                    Requires HDMI v1.4a. */\n     DSEPF_STEREO_SIDE_BY_SIDE_FULL        = 0x00000010,         /* L/R frames are packed side-by-side into a double\n                                                                    width single frame, left on left half of frame.\n                                                                    The packed frame is output on each vsync.\n                                                                    Requires HDMI v1.4a. */\n\n     DSEPF_ALL                             = 0x0000001F          /* All of these. */\n} DFBScreenEncoderPictureFraming;\n\n/*\n * Display aspect ratio.\n */\ntypedef enum {\n    DFB_ASPECT_RATIO_eAuto                 = 0x00000000,         /* 4x3 for SD and 480p, 16x9 for HD (including 720p,\n                                                                    1080i, etc.) */\n    DFB_ASPECT_RATIO_e4x3                  = 0x00000001,         /* 4x3 */\n    DFB_ASPECT_RATIO_e16x9                 = 0x00000002          /* 16x9 */\n} DFBDisplayAspectRatio;\n\n#define DFB_SCREEN_ENCODER_DESC_NAME_LENGTH  24\n\n/*\n * Description of a display encoder.\n */\ntypedef struct {\n     DFBScreenEncoderCapabilities            caps;               /* Encoder capabilities. */\n     DFBScreenEncoderType                    type;               /* Type of encoder. */\n     DFBScreenEncoderTVStandards             tv_standards;       /* Supported TV standards. */\n     DFBScreenOutputSignals                  out_signals;        /* Supported output signals. */\n     DFBScreenOutputConnectors               all_connectors;     /* Supported output connectors */\n     DFBScreenOutputResolution               all_resolutions;    /* Supported Resolutions. */\n\n     char name[DFB_SCREEN_ENCODER_DESC_NAME_LENGTH];             /* Encoder name. */\n\n     DFBScreenEncoderPictureFraming          all_framing;        /* Supported HDMI signaling modes. */\n     DFBDisplayAspectRatio                   all_aspect_ratio;   /* Supported display aspect ratios. */\n} DFBScreenEncoderDescription;\n\n/*\n * Flags for display encoder configuration.\n */\ntypedef enum {\n     DSECONF_NONE                          = 0x00000000,         /* None of these. */\n\n     DSECONF_TV_STANDARD                   = 0x00000001,         /* Set TV standard. */\n     DSECONF_TEST_PICTURE                  = 0x00000002,         /* Set test picture mode. */\n     DSECONF_MIXER                         = 0x00000004,         /* Select mixer. */\n     DSECONF_OUT_SIGNALS                   = 0x00000008,         /* Select generated output signal(s). */\n     DSECONF_SCANMODE                      = 0x00000010,         /* Select interlaced or progressive output. */\n     DSECONF_TEST_COLOR                    = 0x00000020,         /* Set color for DSETP_SINGLE. */\n     DSECONF_ADJUSTMENT                    = 0x00000040,         /* Set color adjustment. */\n     DSECONF_FREQUENCY                     = 0x00000080,         /* Set Output Frequency*/\n     DSECONF_CONNECTORS                    = 0x00000100,         /* Select output connector(s). */\n     DSECONF_SLOW_BLANKING                 = 0x00000200,         /* Can select slow blanking support. */\n     DSECONF_RESOLUTION                    = 0x00000400,         /* Can change resolution of the encoder.*/\n     DSECONF_FRAMING                       = 0x00000800,         /* Set method for delivering pictures to display. */\n     DSECONF_ASPECT_RATIO                  = 0x00001000,         /* Set display aspect ratio. */\n\n     DSECONF_ALL                           = 0x00001FFF          /* All of these. */\n} DFBScreenEncoderConfigFlags;\n\n/*\n * Test picture mode.\n */\ntypedef enum {\n     DSETP_OFF                             = 0x00000000,         /* Disable test picture. */\n\n     DSETP_MULTI                           = 0x00000001,         /* Show color bars. */\n     DSETP_SINGLE                          = 0x00000002,         /* Whole screen as defined in configuration. */\n\n     DSETP_WHITE                           = 0x00000010,         /* Whole screen (ff, ff, ff). */\n     DSETP_YELLOW                          = 0x00000020,         /* Whole screen (ff, ff, 00). */\n     DSETP_CYAN                            = 0x00000030,         /* Whole screen (00, ff, ff). */\n     DSETP_GREEN                           = 0x00000040,         /* Whole screen (00, ff, 00). */\n     DSETP_MAGENTA                         = 0x00000050,         /* Whole screen (ff, 00, ff). */\n     DSETP_RED                             = 0x00000060,         /* Whole screen (ff, 00, 00). */\n     DSETP_BLUE                            = 0x00000070,         /* Whole screen (00, 00, ff). */\n     DSETP_BLACK                           = 0x00000080          /* Whole screen (00, 00, 00). */\n} DFBScreenEncoderTestPicture;\n\n/*\n * Type of slow blanking signalling.\n */\ntypedef enum {\n     DSOSB_OFF                             = 0x00000000,         /* No signal. */\n     DSOSB_16x9                            = 0x00000001,         /* 16x9 Widescreen signalling. */\n     DSOSB_4x3                             = 0x00000002,         /* 4x3 widescreen signalling. */\n     DSOSB_FOLLOW                          = 0x00000004,         /* Follow signalling. */\n     DSOSB_MONITOR                         = 0x00000008          /* Monitor. */\n} DFBScreenOutputSlowBlankingSignals;\n\n/*\n * Scan modes.\n */\ntypedef enum {\n     DSESM_UNKNOWN                         = 0x00000000,         /* Unknown mode. */\n\n     DSESM_INTERLACED                      = 0x00000001,         /* Interlaced scan mode. */\n     DSESM_PROGRESSIVE                     = 0x00000002          /* Progressive scan mode. */\n} DFBScreenEncoderScanMode;\n\n/*\n * Frequency of output signal.\n */\ntypedef enum {\n     DSEF_UNKNOWN                          = 0x00000000,         /* Unknown Frequency. */\n\n     DSEF_25HZ                             = 0x00000001,         /* 25 Hz Output. */\n     DSEF_29_97HZ                          = 0x00000002,         /* 29.97 Hz Output. */\n     DSEF_50HZ                             = 0x00000004,         /* 50 Hz Output. */\n     DSEF_59_94HZ                          = 0x00000008,         /* 59.94 Hz Output. */\n     DSEF_60HZ                             = 0x00000010,         /* 60 Hz Output. */\n     DSEF_75HZ                             = 0x00000020,         /* 75 Hz Output. */\n     DSEF_30HZ                             = 0x00000040,         /* 30 Hz Output. */\n     DSEF_24HZ                             = 0x00000080,         /* 24 Hz Output. */\n     DSEF_23_976HZ                         = 0x00000100          /* 23.976 Hz Output. */\n} DFBScreenEncoderFrequency;\n\n/*\n * Configuration of a display encoder.\n */\ntypedef struct {\n     DFBScreenEncoderConfigFlags             flags;              /* Validates struct members. */\n\n     DFBScreenEncoderTVStandards             tv_standard;        /* TV standard. */\n     DFBScreenEncoderTestPicture             test_picture;       /* Test picture mode. */\n     int                                     mixer;              /* Selected mixer. */\n     DFBScreenOutputSignals                  out_signals;        /* Generated output signals. */\n     DFBScreenOutputConnectors               out_connectors;     /* Selected output connector(s). */\n     DFBScreenOutputSlowBlankingSignals      slow_blanking;      /* Slow Blanking signals. */\n     DFBScreenEncoderScanMode                scanmode;           /* Interlaced or progressive output. */\n     DFBColor                                test_color;         /* Color for DSETP_SINGLE. */\n     DFBColorAdjustment                      adjustment;         /* Color adjustment. */\n     DFBScreenEncoderFrequency               frequency;          /* Selected Output Frequency*/\n     DFBScreenOutputResolution               resolution;         /* Selected Output resolution*/\n     DFBScreenEncoderPictureFraming          framing;            /* Selected picture delivery method. */\n     DFBDisplayAspectRatio                   aspect_ratio;       /* screen aspect ratio */\n} DFBScreenEncoderConfig;\n\n/*\n * Capabilities of an output.\n */\ntypedef enum {\n     DSOCAPS_NONE                          = 0x00000000,         /* None of these. */\n\n     DSOCAPS_CONNECTORS                    = 0x00000001,         /* Output connectors are available. */\n\n     DSOCAPS_ENCODER_SEL                   = 0x00000010,         /* Encoder can be selected. */\n     DSOCAPS_SIGNAL_SEL                    = 0x00000020,         /* Signal(s) can be selected. */\n     DSOCAPS_CONNECTOR_SEL                 = 0x00000040,         /* Connector(s) can be selected. */\n     DSOCAPS_SLOW_BLANKING                 = 0x00000080,         /* Slow Blanking on outputs is supported. */\n     DSOCAPS_RESOLUTION                    = 0x00000100,         /* Output Resolution can be changed. */\n\n     DSOCAPS_ALL                           = 0x000001F1          /* All of these. */\n} DFBScreenOutputCapabilities;\n\n#define DFB_SCREEN_OUTPUT_DESC_NAME_LENGTH   24\n\n/*\n * Description of a screen output.\n */\ntypedef struct {\n     DFBScreenOutputCapabilities             caps;               /* Screen capabilities. */\n\n     DFBScreenOutputConnectors               all_connectors;     /* Output connectors. */\n     DFBScreenOutputSignals                  all_signals;        /* Output signals. */\n     DFBScreenOutputResolution               all_resolutions;    /* Output Resolutions */\n\n     char name[DFB_SCREEN_OUTPUT_DESC_NAME_LENGTH];              /* Output name */\n} DFBScreenOutputDescription;\n\n/*\n * Flags for screen output configuration.\n */\ntypedef enum {\n     DSOCONF_NONE                          = 0x00000000,         /* None of these. */\n\n     DSOCONF_ENCODER                       = 0x00000001,         /* Set encoder the signal(s) comes from. */\n     DSOCONF_SIGNALS                       = 0x00000002,         /* Select signal(s) from encoder. */\n     DSOCONF_CONNECTORS                    = 0x00000004,         /* Select output connector(s). */\n     DSOCONF_SLOW_BLANKING                 = 0x00000008,         /* Can select slow blanking support. */\n     DSOCONF_RESOLUTION                    = 0x00000010,         /* Can change output resolution */\n\n     DSOCONF_ALL                           = 0x0000001F          /* All of these. */\n} DFBScreenOutputConfigFlags;\n\n/*\n * Configuration of an output.\n */\ntypedef struct {\n     DFBScreenOutputConfigFlags              flags;              /* Validates struct members. */\n\n     int                                     encoder;            /* Chosen encoder. */\n     DFBScreenOutputSignals                  out_signals;        /* Selected encoder signal(s). */\n     DFBScreenOutputConnectors               out_connectors;     /* Selected output connector(s). */\n     DFBScreenOutputSlowBlankingSignals      slow_blanking;      /* Slow Blanking signals. */\n     DFBScreenOutputResolution               resolution;         /* Output Resolution */\n} DFBScreenOutputConfig;\n\n/*\n * IDirectFBScreen is the screen interface.\n */\nD_DEFINE_INTERFACE( IDirectFBScreen,\n\n   /** Retrieving information **/\n\n     /*\n      * Get the unique screen ID.\n      */\n     DFBResult (*GetID) (\n          IDirectFBScreen                   *thiz,\n          DFBScreenID                       *ret_screen_id\n     );\n\n     /*\n      * Get a description of this screen, i.e. the capabilities.\n      */\n     DFBResult (*GetDescription) (\n          IDirectFBScreen                   *thiz,\n          DFBScreenDescription              *ret_desc\n     );\n\n     /*\n      * Get the screen's width and height in pixels.\n      */\n     DFBResult (*GetSize) (\n          IDirectFBScreen                   *thiz,\n          int                               *ret_width,\n          int                               *ret_height\n     );\n\n   /** Display Layers **/\n\n     /*\n      * Enumerate all existing display layers for this screen.\n      *\n      * Calls the given callback for each available display\n      * layer. The callback is passed the layer id that can be\n      * used to retrieve an interface to a specific layer using\n      * GetDisplayLayer().\n      */\n     DFBResult (*EnumDisplayLayers) (\n          IDirectFBScreen                   *thiz,\n          DFBDisplayLayerCallback            callback,\n          void                              *callbackdata\n     );\n\n   /** Power management **/\n\n     /*\n      * Set screen power mode.\n      */\n     DFBResult (*SetPowerMode) (\n          IDirectFBScreen                   *thiz,\n          DFBScreenPowerMode                 mode\n     );\n\n   /** Synchronization **/\n\n     /*\n      * Wait for next vertical retrace.\n      */\n     DFBResult (*WaitForSync) (\n          IDirectFBScreen                   *thiz\n     );\n\n   /** Mixers **/\n\n     /*\n      * Get a description of available mixers.\n      *\n      * All descriptions are written to the array pointed to by\n      * 'ret_descriptions'. The number of mixers is returned by\n      * GetDescription().\n      */\n     DFBResult (*GetMixerDescriptions) (\n          IDirectFBScreen                   *thiz,\n          DFBScreenMixerDescription         *ret_descriptions\n     );\n\n     /*\n      * Get current mixer configuration.\n      */\n     DFBResult (*GetMixerConfiguration) (\n          IDirectFBScreen                   *thiz,\n          int                                mixer,\n          DFBScreenMixerConfig              *ret_config\n     );\n\n     /*\n      * Test mixer configuration.\n      *\n      * If configuration fails and 'ret_failed' is not NULL, it\n      * will indicate which fields of the configuration caused\n      * the error.\n      */\n     DFBResult (*TestMixerConfiguration) (\n          IDirectFBScreen                   *thiz,\n          int                                mixer,\n          const DFBScreenMixerConfig        *config,\n          DFBScreenMixerConfigFlags         *ret_failed\n     );\n\n     /*\n      * Set mixer configuration.\n      */\n     DFBResult (*SetMixerConfiguration) (\n          IDirectFBScreen                   *thiz,\n          int                                mixer,\n          const DFBScreenMixerConfig        *config\n     );\n\n   /** Encoders **/\n\n     /*\n      * Get a description of available display encoders.\n      *\n      * All descriptions are written to the array pointed to by\n      * 'ret_descriptions'. The number of encoders is returned\n      * by GetDescription().\n      */\n     DFBResult (*GetEncoderDescriptions) (\n          IDirectFBScreen                   *thiz,\n          DFBScreenEncoderDescription       *ret_descriptions\n     );\n\n     /*\n      * Get current encoder configuration.\n      */\n     DFBResult (*GetEncoderConfiguration) (\n          IDirectFBScreen                   *thiz,\n          int                                encoder,\n          DFBScreenEncoderConfig            *ret_config\n     );\n\n     /*\n      * Test encoder configuration.\n      *\n      * If configuration fails and 'ret_failed' is not NULL, it\n      * will indicate which fields of the configuration caused\n      * the error.\n      */\n     DFBResult (*TestEncoderConfiguration) (\n          IDirectFBScreen                   *thiz,\n          int                                encoder,\n          const DFBScreenEncoderConfig      *config,\n          DFBScreenEncoderConfigFlags       *ret_failed\n     );\n\n     /*\n      * Set encoder configuration.\n      */\n     DFBResult (*SetEncoderConfiguration) (\n          IDirectFBScreen                   *thiz,\n          int                                encoder,\n          const DFBScreenEncoderConfig      *config\n     );\n\n   /** Outputs **/\n\n     /*\n      * Get a description of available outputs.\n      *\n      * All descriptions are written to the array pointed to by\n      * 'ret_descriptions'. The number of outputs is returned\n      * by GetDescription().\n      */\n     DFBResult (*GetOutputDescriptions) (\n          IDirectFBScreen                   *thiz,\n          DFBScreenOutputDescription        *ret_descriptions\n     );\n\n     /*\n      * Get current output configuration.\n      */\n     DFBResult (*GetOutputConfiguration) (\n          IDirectFBScreen                   *thiz,\n          int                                output,\n          DFBScreenOutputConfig             *ret_config\n     );\n\n     /*\n      * Test output configuration.\n      *\n      * If configuration fails and 'ret_failed' is not NULL, it\n      * will indicate which fields of the configuration caused\n      * the error.\n      */\n     DFBResult (*TestOutputConfiguration) (\n          IDirectFBScreen                   *thiz,\n          int                                output,\n          const DFBScreenOutputConfig       *config,\n          DFBScreenOutputConfigFlags        *ret_failed\n     );\n\n     /*\n      * Set output configuration.\n      */\n     DFBResult (*SetOutputConfiguration) (\n          IDirectFBScreen                   *thiz,\n          int                                output,\n          const DFBScreenOutputConfig       *config\n     );\n\n   /** Synchronization **/\n\n     /*\n      * Return current VSync count.\n      */\n     DFBResult (*GetVSyncCount) (\n          IDirectFBScreen                   *thiz,\n          unsigned long                     *ret_count\n     );\n)\n\n/*************************\n * IDirectFBDisplayLayer *\n *************************/\n\n/*\n * Capabilities of a display layer source.\n */\ntypedef enum {\n     DDLSCAPS_NONE                         = 0x00000000,         /* None of these. */\n\n     DDLSCAPS_SURFACE                      = 0x00000001,         /* Source has an accessable surface. */\n\n     DDLSCAPS_ALL                          = 0x00000001          /* All of these. */\n} DFBDisplayLayerSourceCaps;\n\n#define DFB_DISPLAY_LAYER_SOURCE_DESC_NAME_LENGTH 24\n\n/*\n * Description of a display layer source.\n */\ntypedef struct {\n     DFBDisplayLayerSourceID                 source_id;          /* ID of the source. */\n\n     char name[DFB_DISPLAY_LAYER_SOURCE_DESC_NAME_LENGTH];       /* Name of the source. */\n\n     DFBDisplayLayerSourceCaps               caps;               /* Capabilites of the source. */\n} DFBDisplayLayerSourceDescription;\n\n/*\n * Cooperative level handling the access permissions.\n */\ntypedef enum {\n     DLSCL_SHARED                          = 0x00000000,         /* Shared access. */\n     DLSCL_EXCLUSIVE                       = 0x00000001,         /* Exclusive access, fullscreen/mode switching. */\n     DLSCL_ADMINISTRATIVE                  = 0x00000002          /* Administrative access, enumerate windows,\n                                                                    control them. */\n} DFBDisplayLayerCooperativeLevel;\n\n/*\n * Layer configuration flags.\n */\ntypedef enum {\n     DLCONF_NONE                           = 0x00000000,         /* none of these */\n\n     DLCONF_WIDTH                          = 0x00000001,         /* layer width */\n     DLCONF_HEIGHT                         = 0x00000002,         /* layer height */\n     DLCONF_PIXELFORMAT                    = 0x00000004,         /* pixel format */\n     DLCONF_BUFFERMODE                     = 0x00000008,         /* buffer mode */\n     DLCONF_OPTIONS                        = 0x00000010,         /* layer options */\n     DLCONF_SOURCE                         = 0x00000020,         /* layer source */\n     DLCONF_SURFACE_CAPS                   = 0x00000040,         /* surface capabilities */\n     DLCONF_COLORSPACE                     = 0x00000080,         /* color space */\n\n     DLCONF_ALL                            = 0x000000FF          /* all of these */\n} DFBDisplayLayerConfigFlags;\n\n/*\n * Layer Buffer Mode.\n */\ntypedef enum {\n     DLBM_UNKNOWN                          = 0x00000000,         /* unknown buffer mode */\n\n     DLBM_FRONTONLY                        = 0x00000001,         /* no backbuffer */\n     DLBM_BACKVIDEO                        = 0x00000002,         /* backbuffer in video memory */\n     DLBM_BACKSYSTEM                       = 0x00000004,         /* backbuffer in system memory */\n     DLBM_TRIPLE                           = 0x00000008,         /* triple buffering */\n     DLBM_WINDOWS                          = 0x00000010          /* no layer buffers at all,\n                                                                    using buffer of each window */\n} DFBDisplayLayerBufferMode;\n\n/*\n * Layer options used to enable some capabilities like\n * flicker filtering or colorkeying.\n */\ntypedef enum {\n     DLOP_NONE                             = 0x00000000,         /* None of these. */\n\n     DLOP_ALPHACHANNEL                     = 0x00000001,         /* Make usage of alpha channel for blending on a pixel\n                                                                    per pixel basis. */\n     DLOP_FLICKER_FILTERING                = 0x00000002,         /* Enable flicker filtering. */\n     DLOP_DEINTERLACING                    = 0x00000004,         /* Enable deinterlacing of an interlaced source. */\n     DLOP_SRC_COLORKEY                     = 0x00000008,         /* Enable source color key. */\n     DLOP_DST_COLORKEY                     = 0x00000010,         /* Enable destination color key. */\n     DLOP_OPACITY                          = 0x00000020,         /* Make usage of the global alpha factor set by\n                                                                    SetOpacity(). */\n     DLOP_FIELD_PARITY                     = 0x00000040,         /* Set field parity. */\n\n     DLOP_LR_MONO                          = 0x00000100,         /* Layer has a single set of surface buffers and a\n                                                                    stereo depth. The number of buffers in each set is\n                                                                    deteremined by DSCAPS_DOUBLE, DSCAPS_TRIPLE, etc.\n                                                                    If they exist, the windows on this layer must not be\n                                                                    stereo or L/R mono, otherwise window information\n                                                                    will be lost when they are composited to the layer.\n                                                                    The layer contents (composited windows if they\n                                                                    exist) will be shifted horizontally left and right\n                                                                    by the stereo depth value when the layer is\n                                                                    composited on the display screen. */\n     DLOP_STEREO                           = 0x00000200,         /* Layer has two independent sets of surface buffers\n                                                                    (left eye and right eye buffers), each with unique\n                                                                    content. The number of buffers in each set is\n                                                                    deteremined by DSCAPS_DOUBLE, DSCAPS_TRIPLE, etc.\n                                                                    This option is required if any of the windows on\n                                                                    this layer have DWCAPS_STEREO or DWCAPS_LR_MONO set,\n                                                                    otherwise the stereo or L/R depth content of the\n                                                                    windows cannot be preserved when compositing to the\n                                                                    layer. */\n\n     DLOP_ALL                              = 0x000003FF          /* All of these. */\n} DFBDisplayLayerOptions;\n\n/*\n * Layer configuration.\n */\ntypedef struct {\n     DFBDisplayLayerConfigFlags              flags;              /* Validates struct members. */\n\n     int                                     width;              /* Pixel width. */\n     int                                     height;             /* Pixel height. */\n     DFBSurfacePixelFormat                   pixelformat;        /* Pixel format. */\n     DFBSurfaceColorSpace                    colorspace;         /* Color space. */\n     DFBDisplayLayerBufferMode               buffermode;         /* Buffer mode. */\n     DFBDisplayLayerOptions                  options;            /* Enable capabilities. */\n     DFBDisplayLayerSourceID                 source;             /* Selected layer source. */\n     DFBSurfaceCapabilities                  surface_caps;       /* Choose surface capabilities, available:\n                                                                    INTERLACED, SEPARATED, PREMULTIPLIED. */\n} DFBDisplayLayerConfig;\n\n#define DLSO_FIXED_LIMIT                     0x7f                /* Stereo fixed depth value must be between\n                                                                    +DLSO_FIXED_LIMIT and -DLSO_FIXED_LIMIT. */\n\n/*\n * Background mode defining how to erase/initialize the area for\n * a windowstack repaint.\n */\ntypedef enum {\n     DLBM_DONTCARE                         = 0x00000000,         /* do not clear the layer before repainting the window\n                                                                    stack */\n     DLBM_COLOR                            = 0x00000001,         /* fill with solid color set by SetBackgroundColor() */\n     DLBM_IMAGE                            = 0x00000002,         /* use an image set by SetBackgroundImage() */\n     DLBM_TILE                             = 0x00000003          /* use a tiled image set by SetBackgroundImage() */\n} DFBDisplayLayerBackgroundMode;\n\n/*\n * Flags defining which fields of a DFBWindowDescription are\n * valid.\n */\ntypedef enum {\n     DWDESC_CAPS                           = 0x00000001,         /* caps field is valid. */\n     DWDESC_WIDTH                          = 0x00000002,         /* width field is valid. */\n     DWDESC_HEIGHT                         = 0x00000004,         /* height field is valid. */\n     DWDESC_PIXELFORMAT                    = 0x00000008,         /* pixelformat field is valid */\n     DWDESC_POSX                           = 0x00000010,         /* posx field is valid */\n     DWDESC_POSY                           = 0x00000020,         /* posy field is valid */\n     DWDESC_SURFACE_CAPS                   = 0x00000040,         /* Create the window surface with\n                                                                    special capabilities. */\n     DWDESC_PARENT                         = 0x00000080,         /* This window has a parent according to\n                                                                    parent_id field. */\n     DWDESC_OPTIONS                        = 0x00000100,         /* Initial window options have been set. */\n     DWDESC_STACKING                       = 0x00000200,         /* Initial stacking class has been set. */\n     DWDESC_TOPLEVEL_ID                    = 0x00000400,         /* The top level window is set in toplevel_id field. */\n     DWDESC_COLORSPACE                     = 0x00000800,         /* colorspace field is valid */\n     DWDESC_RESOURCE_ID                    = 0x00001000          /* resource_id for window surface creation\n                                                                    has been set. */\n} DFBWindowDescriptionFlags;\n\n/*\n * Capabilities a window can have.\n */\ntypedef enum {\n     DWCAPS_NONE                           = 0x00000000,         /* None of these. */\n\n     DWCAPS_ALPHACHANNEL                   = 0x00000001,         /* The window has an alphachannel for pixel-per-pixel\n                                                                    blending. */\n     DWCAPS_DOUBLEBUFFER                   = 0x00000002,         /* The window's surface is double buffered.\n                                                                    This is very useful to avoid visibility of content\n                                                                    that is still in preparation. Normally a window's\n                                                                    content can get visible before an update if there is\n                                                                    another reason causing a window stack repaint. */\n     DWCAPS_INPUTONLY                      = 0x00000004,         /* The window has no surface. You can not draw to it\n                                                                    but it receives events. */\n     DWCAPS_NODECORATION                   = 0x00000008,         /* The window won't be decorated. */\n     DWCAPS_SUBWINDOW                      = 0x00000010,         /* Not a top level window. */\n     DWCAPS_COLOR                          = 0x00000020,         /* The window has no buffer.\n                                                                    It consumes no backing store. It is filled with a\n                                                                    constant color and it receives events. The color is\n                                                                    never specified premultiplied. */\n\n     DWCAPS_NOFOCUS                        = 0x00000100,         /* Window will never get focus or receive key events,\n                                                                    unless it grabs them. */\n\n     DWCAPS_LR_MONO                        = 0x00001000,         /* Window has a single set of surface buffers and a\n                                                                    stereo depth. The number of buffers in each set is\n                                                                    deteremined by DSCAPS_DOUBLE, DSCAPS_TRIPLE, etc.\n                                                                    Selecting this option requires the underlying layer\n                                                                    to have DLOP_STEREO set, otherwise the stereo depth\n                                                                    for the left and right eye cannot be preserved when\n                                                                    compositing to the underlying layer. The buffer is\n                                                                    composited to both the left and right eye buffers of\n                                                                    the layer with an x-axis right and left shift of\n                                                                    depth pixels, respectively. */\n     DWCAPS_STEREO                         = 0x00002000,         /* Window has 2 independent sets of surface buffers\n                                                                    (left eye & right eye buffers), each with unique\n                                                                    content.\n                                                                    The number of buffers in each set is deteremined by\n                                                                    DSCAPS_DOUBLE, DSCAPS_TRIPLE, etc as usual.\n                                                                    Selecting this option requires the underlying layer\n                                                                    to have DLOP_STEREO set, otherwise the independent\n                                                                    content of the left and right eye cannot be\n                                                                    preserved when compositing to the layer. */\n\n     DWCAPS_ALL                            = 0x0000313F          /* All of these. */\n} DFBWindowCapabilities;\n\n/*\n * Flags controlling the appearance and behaviour of the window.\n */\ntypedef enum {\n     DWOP_NONE                             = 0x00000000,         /* None of these. */\n\n     DWOP_COLORKEYING                      = 0x00000001,         /* Enable color key. */\n     DWOP_ALPHACHANNEL                     = 0x00000002,         /* Enable alpha blending using the window's alpha\n                                                                    channel. */\n     DWOP_OPAQUE_REGION                    = 0x00000004,         /* Overrides DWOP_ALPHACHANNEL for the region set by\n                                                                    SetOpaqueRegion() */\n     DWOP_SHAPED                           = 0x00000008,         /* Window doesn't receive mouse events for invisible\n                                                                    regions, must be used with DWOP_ALPHACHANNEL or\n                                                                    DWOP_COLORKEYING. */\n     DWOP_KEEP_POSITION                    = 0x00000010,         /* Window can't be moved with the mouse. */\n     DWOP_KEEP_SIZE                        = 0x00000020,         /* Window can't be resized with the mouse. */\n     DWOP_KEEP_STACKING                    = 0x00000040,         /* Window can't be raised or lowered with the mouse. */\n\n     DWOP_GHOST                            = 0x00001000,         /* Never get focus or input, clicks will go through,\n                                                                    implies DWOP_KEEP. */\n     DWOP_INDESTRUCTIBLE                   = 0x00002000,         /* Window can't be destroyed by internal shortcut. */\n     DWOP_INPUTONLY                        = 0x00004000,         /* The window will be input only. It will receive\n                                                                    events but is not shown. Note that toggling this bit\n                                                                    will not free/assign the window surface. */\n     DWOP_STEREO_SIDE_BY_SIDE_HALF         = 0x00008000,         /* Treat single buffer as combined left/right buffers,\n                                                                    side by side. */\n     DWOP_SCALE                            = 0x00010000,         /* Surface won't be changed if window size on screen\n                                                                    changes. The surface can be resized separately using\n                                                                    ResizeSurface(). */\n\n     DWOP_KEEP_ABOVE                       = 0x00100000,         /* Keep window above parent window. */\n     DWOP_KEEP_UNDER                       = 0x00200000,         /* Keep window under parent window. */\n     DWOP_FOLLOW_BOUNDS                    = 0x00400000,         /* Follow window bounds from parent. */\n\n     DWOP_ALL                              = 0x0071F07F          /* all possible options */\n} DFBWindowOptions;\n\n/*\n * The stacking class restricts the stacking order of windows.\n */\ntypedef enum {\n     DWSC_MIDDLE                           = 0x00000000,        /* This is the default stacking class of new windows. */\n     DWSC_UPPER                            = 0x00000001,        /* Window is always above windows in the middle stacking\n                                                                   class. Only windows that are also in the upper\n                                                                   stacking class can get above them. */\n     DWSC_LOWER                            = 0x00000002         /* Window is always below windows in the middle stacking\n                                                                   class. Only windows that are also in the lower\n                                                                   stacking class can get below them. */\n} DFBWindowStackingClass;\n\n/*\n * Description of the window that is to be created.\n */\ntypedef struct {\n     DFBWindowDescriptionFlags               flags;              /* field validation */\n\n     DFBWindowCapabilities                   caps;               /* capabilities */\n     int                                     width;              /* pixel width */\n     int                                     height;             /* pixel height */\n     DFBSurfacePixelFormat                   pixelformat;        /* pixel format */\n     int                                     posx;               /* distance from left layer border */\n     int                                     posy;               /* distance from upper layer border */\n     DFBSurfaceCapabilities                  surface_caps;       /* surface capabilities */\n     DFBWindowID                             parent_id;          /* window id of parent window */\n     DFBWindowOptions                        options;            /* initial window options */\n     DFBWindowStackingClass                  stacking;           /* initial stacking class */\n     unsigned long                           resource_id;        /* resource id used to create the window surface */\n     DFBWindowID                             toplevel_id;        /* top level window: if not zero, window will be a sub\n                                                                    window */\n     DFBSurfaceColorSpace                    colorspace;         /* color space */\n} DFBWindowDescription;\n\n/*\n * IDirectFBDisplayLayer is the display layer interface.\n */\nD_DEFINE_INTERFACE( IDirectFBDisplayLayer,\n\n   /** Retrieving information **/\n\n     /*\n      * Get the unique layer ID.\n      */\n     DFBResult (*GetID) (\n          IDirectFBDisplayLayer             *thiz,\n          DFBDisplayLayerID                 *ret_layer_id\n     );\n\n     /*\n      * Get a description of this display layer,\n        i.e. the capabilities.\n      */\n     DFBResult (*GetDescription) (\n          IDirectFBDisplayLayer             *thiz,\n          DFBDisplayLayerDescription        *ret_desc\n     );\n\n     /*\n      * Get a description of available sources.\n      *\n      * All descriptions are written to the array pointed to by\n      * ret_descriptions. The number of sources is returned by\n      * GetDescription().\n      */\n     DFBResult (*GetSourceDescriptions) (\n          IDirectFBDisplayLayer             *thiz,\n          DFBDisplayLayerSourceDescription  *ret_descriptions\n     );\n\n     /*\n      * For an interlaced display, this returns the currently\n      * inactive field: 0 for the top field, and 1 for the\n      * bottom field.\n      *\n      * The inactive field is the one you should draw to next\n      * to avoid tearing, the active field is the one currently\n      * being displayed.\n      * For a progressive output, this should always return 0.\n      */\n     DFBResult (*GetCurrentOutputField) (\n          IDirectFBDisplayLayer             *thiz,\n          int                               *ret_field\n     );\n\n   /** Interfaces **/\n\n     /*\n      * Get an interface to layer's surface.\n      *\n      * Only available in exclusive mode.\n      */\n     DFBResult (*GetSurface) (\n          IDirectFBDisplayLayer             *thiz,\n          IDirectFBSurface                 **ret_interface\n     );\n\n     /*\n      * Get an interface to the screen to which the layer\n      * belongs.\n      */\n     DFBResult (*GetScreen) (\n          IDirectFBDisplayLayer             *thiz,\n          IDirectFBScreen                  **ret_interface\n     );\n\n   /** Configuration **/\n\n     /*\n      * Set cooperative level to get control over the layer or\n      * the windows within this layer.\n      */\n     DFBResult (*SetCooperativeLevel) (\n          IDirectFBDisplayLayer             *thiz,\n          DFBDisplayLayerCooperativeLevel    level\n     );\n\n     /*\n      * Get current layer configuration.\n      */\n     DFBResult (*GetConfiguration) (\n          IDirectFBDisplayLayer             *thiz,\n          DFBDisplayLayerConfig             *ret_config\n     );\n\n     /*\n      * Test layer configuration.\n      *\n      * If configuration fails and 'ret_failed' is not NULL, it\n      * will indicate which fields of the configuration caused\n      * the error.\n      */\n     DFBResult (*TestConfiguration) (\n          IDirectFBDisplayLayer             *thiz,\n          const DFBDisplayLayerConfig       *config,\n          DFBDisplayLayerConfigFlags        *ret_failed\n     );\n\n     /*\n      * Set layer configuration.\n      *\n      * Only available in exclusive or administrative mode.\n      */\n     DFBResult (*SetConfiguration) (\n          IDirectFBDisplayLayer             *thiz,\n          const DFBDisplayLayerConfig       *config\n     );\n\n   /** Layout **/\n\n     /*\n      * Set location on screen as normalized values.\n      *\n      * So the whole screen is 0.0, 0.0, 1.0, 1.0.\n      */\n     DFBResult (*SetScreenLocation) (\n          IDirectFBDisplayLayer             *thiz,\n          float                              x,\n          float                              y,\n          float                              width,\n          float                              height\n     );\n\n     /*\n      * Set location on screen in pixels.\n      */\n     DFBResult (*SetScreenPosition) (\n          IDirectFBDisplayLayer             *thiz,\n          int                                x,\n          int                                y\n     );\n\n     /*\n      * Set location on screen in pixels.\n      */\n     DFBResult (*SetScreenRectangle) (\n          IDirectFBDisplayLayer             *thiz,\n          int                                x,\n          int                                y,\n          int                                width,\n          int                                height\n     );\n\n     /*\n      * Get stereo depth.\n      */\n     DFBResult (*GetStereoDepth) (\n         IDirectFBDisplayLayer              *thiz,\n         bool                               *follow_video,\n         int                                *ret_z\n    );\n\n     /*\n      * Set stereo depth.\n      *\n      * If 'follow_video' is true then the pixel offset value\n      * from the video metadata will be used to set the\n      * perceived depth.\n      * Otherwise, the z value specified will cause the left eye\n      * buffer content to be shifted on the x-axis by +z and the\n      * right eye buffer to be shifted by -z. A positive z value\n      * will cause the layer to appear closer than the TV plane\n      * while a negative z value will make the layer appear\n      * farther away. The depth is limited to a value between\n      * +DLSO_FIXED_LIMIT and -DLSO_FIXED_LIMIT.\n      */\n     DFBResult (*SetStereoDepth) (\n         IDirectFBDisplayLayer              *thiz,\n         bool                                follow_video,\n         int                                 z\n    );\n\n   /** Misc Settings **/\n\n     /*\n      * Set global alpha factor for blending with\n      * layer(s) below.\n      */\n     DFBResult (*SetOpacity) (\n          IDirectFBDisplayLayer             *thiz,\n          u8                                 opacity\n     );\n\n     /*\n      * Set the source rectangle.\n      *\n      * Only this part of the layer will be displayed.\n      */\n     DFBResult (*SetSourceRectangle) (\n          IDirectFBDisplayLayer             *thiz,\n          int                                x,\n          int                                y,\n          int                                width,\n          int                                height\n     );\n\n     /*\n      * For an interlaced display, this sets the field parity.\n      *\n      * 'field' is set to 0 for top field first, and set to 1\n      * for bottom field first.\n      */\n     DFBResult (*SetFieldParity) (\n          IDirectFBDisplayLayer             *thiz,\n          int                                field\n     );\n\n     /*\n      * Set the clipping region(s).\n      *\n      * If supported, this method sets the clipping 'regions'\n      * that are used to to enable or disable visibility of\n      * parts of the layer. The 'num_regions' must not exceed\n      * the limit as stated in the display layer description.\n      * If 'positive' is DFB_TRUE the layer will be shown only\n      * in these regions, otherwise it's shown as usual except\n      * in these regions.\n      */\n     DFBResult (*SetClipRegions) (\n          IDirectFBDisplayLayer             *thiz,\n          const DFBRegion                   *regions,\n          int                                num_regions,\n          DFBBoolean                         positive\n     );\n\n   /** Color keys **/\n\n     /*\n      * Set the source color key.\n      *\n      * If a pixel of the layer matches this color the\n      * underlying pixel is visible at this point.\n      */\n     DFBResult (*SetSrcColorKey) (\n          IDirectFBDisplayLayer             *thiz,\n          u8                                 r,\n          u8                                 g,\n          u8                                 b\n     );\n\n     /*\n      * Set the destination color key.\n      *\n      * The layer is only visible at points where the underlying\n      * pixel matches this color.\n      */\n     DFBResult (*SetDstColorKey) (\n          IDirectFBDisplayLayer             *thiz,\n          u8                                 r,\n          u8                                 g,\n          u8                                 b\n     );\n\n   /** Z Order **/\n\n     /*\n      * Get the current display layer level.\n      *\n      * The level describes the z axis position of a layer. The\n      * primary layer is always on level zero unless a special\n      * driver adds support for level adjustment on the primary\n      * layer. Layers above have a positive level, e.g. video\n      * overlays. Layers below have a negative level, e.g. video\n      * underlays or background layers.\n      */\n     DFBResult (*GetLevel) (\n          IDirectFBDisplayLayer             *thiz,\n          int                               *ret_level\n     );\n\n     /*\n      * Set the display layer level.\n      *\n      * Moves the layer to the specified level. The order of all\n      * other layers won't be changed. Note that only a few\n      * layers support level adjustment which is reflected by\n      * their capabilities.\n      */\n     DFBResult (*SetLevel) (\n          IDirectFBDisplayLayer             *thiz,\n          int                                level\n     );\n\n   /** Background handling **/\n\n     /*\n      * Set the erase behaviour for windowstack repaints.\n      *\n      * Only available in exclusive or administrative mode.\n      */\n     DFBResult (*SetBackgroundMode) (\n          IDirectFBDisplayLayer             *thiz,\n          DFBDisplayLayerBackgroundMode      mode\n     );\n\n     /*\n      * Set the background image for the imaged background mode.\n      *\n      * Only available in exclusive or administrative mode.\n      */\n     DFBResult (*SetBackgroundImage) (\n          IDirectFBDisplayLayer             *thiz,\n          IDirectFBSurface                  *surface\n     );\n\n     /*\n      * Set the color for a solid colored background.\n      *\n      * Only available in exclusive or administrative mode.\n      */\n     DFBResult (*SetBackgroundColor) (\n          IDirectFBDisplayLayer             *thiz,\n          u8                                 r,\n          u8                                 g,\n          u8                                 b,\n          u8                                 a\n     );\n\n   /** Color adjustment **/\n\n     /*\n      * Get the layers color adjustment.\n      */\n     DFBResult (*GetColorAdjustment) (\n          IDirectFBDisplayLayer             *thiz,\n          DFBColorAdjustment                *ret_adj\n     );\n\n     /*\n      * Set the layers color adjustment.\n      *\n      * Only available in exclusive or administrative mode.\n      *\n      * This function only has an effect if the underlying\n      * hardware supports this operation. Check the layers\n      * capabilities to find out if this is the case.\n      */\n     DFBResult (*SetColorAdjustment) (\n          IDirectFBDisplayLayer             *thiz,\n          const DFBColorAdjustment          *adj\n     );\n\n   /** Windows **/\n\n     /*\n      * Create a window within this layer given a description of\n      * the window that is to be created.\n      */\n     DFBResult (*CreateWindow) (\n          IDirectFBDisplayLayer             *thiz,\n          const DFBWindowDescription        *desc,\n          IDirectFBWindow                  **ret_interface\n     );\n\n     /*\n      * Retrieve an interface to an existing window.\n      *\n      * The window is identified by its window id.\n      */\n     DFBResult (*GetWindow) (\n          IDirectFBDisplayLayer             *thiz,\n          DFBWindowID                        window_id,\n          IDirectFBWindow                  **ret_interface\n     );\n\n   /** Cursor handling **/\n\n     /*\n      * Enable/disable the mouse cursor for this layer.\n      *\n      * Windows on a layer will only receive motion events if\n      * the cursor is enabled. This function is only available\n      * in exclusive/administrative mode.\n      */\n     DFBResult (*EnableCursor) (\n          IDirectFBDisplayLayer             *thiz,\n          int                                enable\n     );\n\n     /*\n      * Return the x/y coordinates of the layer's mouse cursor.\n      */\n     DFBResult (*GetCursorPosition) (\n          IDirectFBDisplayLayer             *thiz,\n          int                               *ret_x,\n          int                               *ret_y\n     );\n\n     /*\n      * Move cursor to specified position.\n      *\n      * Handles movement like a real one, i.e. generates events.\n      */\n     DFBResult (*WarpCursor) (\n          IDirectFBDisplayLayer             *thiz,\n          int                                x,\n          int                                y\n     );\n\n     /*\n      * Set cursor acceleration.\n      *\n      * Sets the acceleration of cursor movements. The amount\n      * beyond the 'threshold' will be multiplied with the\n      * acceleration factor. The acceleration factor is\n      * 'numerator' / 'denominator'.\n      */\n     DFBResult (*SetCursorAcceleration) (\n          IDirectFBDisplayLayer             *thiz,\n          int                                numerator,\n          int                                denominator,\n          int                                threshold\n     );\n\n     /*\n      * Set the cursor shape and the hotspot.\n      *\n      * Passing NULL will restore the default cursor shape.\n      */\n     DFBResult (*SetCursorShape) (\n          IDirectFBDisplayLayer             *thiz,\n          IDirectFBSurface                  *shape,\n          int                                hot_x,\n          int                                hot_y\n     );\n\n     /*\n      * Set the cursor opacity.\n      *\n      * This function is especially useful if you want to hide\n      * the cursor but still want windows on this display layer\n      * to receive motion events.\n      * In this case, simply set the cursor opacity to zero.\n      */\n     DFBResult (*SetCursorOpacity) (\n          IDirectFBDisplayLayer             *thiz,\n          u8                                 opacity\n     );\n\n   /** Synchronization **/\n\n     /*\n      * Wait for next vertical retrace.\n      */\n     DFBResult (*WaitForSync) (\n          IDirectFBDisplayLayer             *thiz\n     );\n\n   /** Contexts **/\n\n     /*\n      * Switch the layer context.\n      *\n      * Switches to the shared context unless 'exclusive' is\n      * DFB_TRUE and the cooperative level of this interface is\n      * DLSCL_EXCLUSIVE.\n      */\n     DFBResult (*SwitchContext) (\n          IDirectFBDisplayLayer             *thiz,\n          DFBBoolean                         exclusive\n     );\n\n   /** Rotation **/\n\n     /*\n      * Set the rotation of data within the layer.\n      *\n      * Only available in exclusive or administrative mode.\n      * Any 'rotation' other than 0, 90, 180 or 270 is not\n      * supported. No layer hardware feature usage, only rotated\n      * blitting is used.\n      */\n     DFBResult (*SetRotation) (\n          IDirectFBDisplayLayer             *thiz,\n          int                                rotation\n     );\n\n     /*\n      * Get the rotation of data within the layer.\n      */\n     DFBResult (*GetRotation) (\n          IDirectFBDisplayLayer             *thiz,\n          int                               *ret_rotation\n     );\n\n   /** Windows **/\n\n     /*\n      * Retrieve an interface to an existing window.\n      *\n      * The window is identified by its surface resource id.\n      */\n     DFBResult (*GetWindowByResourceID) (\n          IDirectFBDisplayLayer             *thiz,\n          unsigned long                      resource_id,\n          IDirectFBWindow                  **ret_interface\n     );\n\n   /** Surface **/\n\n     /*\n      * Set the surface to be shown by the layer.\n      *\n      * Only available in exclusive mode.\n      */\n     DFBResult (*SetSurface) (\n          IDirectFBDisplayLayer             *thiz,\n          IDirectFBSurface                  *surface\n     );\n)\n\n/********************\n * IDirectFBSurface *\n ********************/\n\n/*\n * Stereo eye buffer.\n */\ntypedef enum {\n     DSSE_NONE                             = 0x00000000,         /* None */\n\n     DSSE_LEFT                             = 0x00000001,         /* Left eye buffers to be used for all future\n                                                                    operations on this surface. */\n     DSSE_RIGHT                            = 0x00000002          /* Right eye buffers to be used for all future\n                                                                    operations on this surface. */\n} DFBSurfaceStereoEye;\n\n/*\n * Flags defining the type of data access.\n * These are important for surface swapping management.\n */\ntypedef enum {\n     DSLF_READ                             = 0x00000001,         /* Request read access while surface is locked. */\n     DSLF_WRITE                            = 0x00000002          /* Request write access. If specified and surface has a\n                                                                    back buffer, it will be used. Otherwise, the front\n                                                                    buffer is used. */\n} DFBSurfaceLockFlags;\n\n/*\n * Flipping flags controlling the behaviour of Flip().\n */\ntypedef enum {\n     DSFLIP_NONE                           = 0x00000000,         /* None of these. */\n\n     DSFLIP_WAIT                           = 0x00000001,         /* Flip() returns upon vertical sync. Flipping is\n                                                                    still done immediately unless DSFLIP_ONSYNC is\n                                                                    specified, too. */\n     DSFLIP_BLIT                           = 0x00000002,         /* Copy from back buffer to front buffer rather than\n                                                                    just swapping these buffers.\n                                                                    This behaviour is enforced if the region passed to\n                                                                    Flip() is not NULL or if the surface being flipped\n                                                                    is a sub surface. */\n     DSFLIP_ONSYNC                         = 0x00000004,         /* Do the actual flipping upon the next vertical sync.\n                                                                    The Flip() method will still return immediately\n                                                                    unless DSFLIP_WAIT is specified, too. */\n     DSFLIP_PIPELINE                       = 0x00000008,         /* Advanced synchronization with the accelerator.\n                                                                    It is especially for accelerators with a command\n                                                                    buffer that can store more graphics operations than\n                                                                    required to render one frame. */\n     DSFLIP_ONCE                           = 0x00000010,         /* Cause Flip() to wait until all other updating window\n                                                                    surfaces are being flipped. */\n\n     DSFLIP_QUEUE                          = 0x00000100,         /* Queuing updates */\n     DSFLIP_FLUSH                          = 0x00000200,         /* Flushing */\n     DSFLIP_SWAP                           = 0x00000400,         /* Cause real flip even though region was specified. */\n     DSFLIP_UPDATE                         = 0x00000800,         /* Update from front only, no swapping */\n     DSFLIP_NOWAIT                         = 0x00001000,\n\n     DSFLIP_WAITFORSYNC                    = DSFLIP_WAIT |\n                                             DSFLIP_ONSYNC       /* Flip() returns after the actual flipping performed\n                                                                    during the next vertical sync  */\n} DFBSurfaceFlipFlags;\n\n/*\n * Blend functions to use for source and destination blending.\n *\n * pixel color = sc * cf[sf] + dc * cf[df]\n * pixel alpha = sa * af[sf] + da * af[df]\n * sc = source color\n * sa = source alpha\n * dc = destination color\n * da = destination alpha\n * sf = source blend function\n * df = destination blend function\n * cf[x] = color factor for blend function x\n * af[x] = alpha factor for blend function x\n *\n */\ntypedef enum {\n     DSBF_UNKNOWN                          = 0x00000000,         /* unknown blend function */\n\n     DSBF_ZERO                             = 0x00000001,         /* cf:    0           af:    0 */\n     DSBF_ONE                              = 0x00000002,         /* cf:    1           af:    1 */\n     DSBF_SRCCOLOR                         = 0x00000003,         /* cf:   sc           af:   sa */\n     DSBF_INVSRCCOLOR                      = 0x00000004,         /* cf: 1-sc           af: 1-sa */\n     DSBF_SRCALPHA                         = 0x00000005,         /* cf:   sa           af:   sa */\n     DSBF_INVSRCALPHA                      = 0x00000006,         /* cf: 1-sa           af: 1-sa */\n     DSBF_DESTALPHA                        = 0x00000007,         /* cf:   da           af:   da */\n     DSBF_INVDESTALPHA                     = 0x00000008,         /* cf: 1-da           af: 1-da */\n     DSBF_DESTCOLOR                        = 0x00000009,         /* cf:   dc           af:   da */\n     DSBF_INVDESTCOLOR                     = 0x0000000A,         /* cf: 1-dc           af: 1-da */\n     DSBF_SRCALPHASAT                      = 0x0000000B          /* cf: min(sa, 1-da)  af:    1 */\n} DFBSurfaceBlendFunction;\n\n/*\n * Available Porter/Duff rules.\n *\n * pixel = (source * fs + destination * fd)\n * sa = source alpha,\n * da = destination alpha\n */\ntypedef enum {\n     DSPD_NONE                             = 0x00000000,         /* fs:   sa           fd: 1-sa */\n\n     DSPD_CLEAR                            = 0x00000001,         /* fs:    0           fd:    0 */\n     DSPD_SRC                              = 0x00000002,         /* fs:    1           fd:    0 */\n     DSPD_SRC_OVER                         = 0x00000003,         /* fs:    1           fd: 1-sa */\n     DSPD_DST_OVER                         = 0x00000004,         /* fs: 1-da           fd:    1 */\n     DSPD_SRC_IN                           = 0x00000005,         /* fs:   da           fd:    0 */\n     DSPD_DST_IN                           = 0x00000006,         /* fs:    0           fd:   sa */\n     DSPD_SRC_OUT                          = 0x00000007,         /* fs: 1-da           fd:    0 */\n     DSPD_DST_OUT                          = 0x00000008,         /* fs:    0           fd: 1-sa */\n     DSPD_SRC_ATOP                         = 0x00000009,         /* fs:   da           fd: 1-sa */\n     DSPD_DST_ATOP                         = 0x0000000A,         /* fs: 1-da           fd:   sa */\n     DSPD_ADD                              = 0x0000000B,         /* fs:    1           fd:    1 */\n     DSPD_XOR                              = 0x0000000C,         /* fs: 1-da           fd: 1-sa */\n     DSPD_DST                              = 0x0000000D          /* fs:    0           fd:    1 */\n} DFBSurfacePorterDuffRule;\n\n/*\n * Flags controlling the text layout.\n */\ntypedef enum {\n     DSTF_NONE                             = 0x00000000,         /* no flags */\n\n     DSTF_LEFT                             = 0x00000000,         /* left aligned */\n     DSTF_CENTER                           = 0x00000001,         /* horizontally centered */\n     DSTF_RIGHT                            = 0x00000002,         /* right aligned */\n     DSTF_TOP                              = 0x00000004,         /* 'y' specifies the top instead of the baseline */\n     DSTF_BOTTOM                           = 0x00000008,         /* 'y' specifies the bottom instead of the baseline */\n     DSTF_OUTLINE                          = 0x00000010,         /* enables outline rendering */\n     DSTF_BLEND_FUNCS                      = 0x00000020,         /* keeps src/dst blend functions as set on\n                                                                    destination */\n     DSTF_TOPLEFT                          = DSTF_TOP |\n                                             DSTF_LEFT,          /* left aligned, 'y' specifying the top */\n     DSTF_TOPCENTER                        = DSTF_TOP |\n                                             DSTF_CENTER,        /* horizontally centered, 'y' specifying the top */\n     DSTF_TOPRIGHT                         = DSTF_TOP |\n                                             DSTF_RIGHT,         /* right aligned, 'y' specifying the top */\n     DSTF_BOTTOMLEFT                       = DSTF_BOTTOM |\n                                             DSTF_LEFT,          /* left aligned, 'y' specifying the bottom */\n     DSTF_BOTTOMCENTER                     = DSTF_BOTTOM |\n                                             DSTF_CENTER,        /* horizontally centered, 'y' specifying the bottom */\n     DSTF_BOTTOMRIGHT                      = DSTF_BOTTOM |\n                                             DSTF_RIGHT          /* right aligned, 'y' specifying the bottom */\n} DFBSurfaceTextFlags;\n\n/*\n * Options for drawing and blitting operations.\n */\ntypedef enum {\n     DSRO_NONE                             = 0x00000000,         /* None of these. */\n\n     DSRO_SMOOTH_UPSCALE                   = 0x00000001,         /* Use interpolation for upscale StretchBlit(). */\n     DSRO_SMOOTH_DOWNSCALE                 = 0x00000002,         /* Use interpolation for downscale StretchBlit(). */\n     DSRO_MATRIX                           = 0x00000004,         /* Use the transformation matrix set via\n                                                                    SetMatrix(). */\n     DSRO_ANTIALIAS                        = 0x00000008,         /* Enable anti-aliasing for edges (alpha blending must\n                                                                    be enabled). */\n\n     DSRO_ALL                              = 0x0000000F          /* All of these. */\n} DFBSurfaceRenderOptions;\n\n/*\n * Flags controlling surface masks set via SetSourceMask().\n */\ntypedef enum {\n     DSMF_NONE                             = 0x00000000,         /* None of these. */\n\n     DSMF_STENCIL                          = 0x00000001,         /* Take 'x' and 'y' as fixed start coordinates in the\n                                                                    mask. */\n\n     DSMF_ALL                              = 0x00000001          /* All of these. */\n} DFBSurfaceMaskFlags;\n\n/*\n * Monochrome glyph attributes.\n */\ntypedef struct {\n     int                                     width;              /* glyph width */\n     int                                     height;             /* glyph height */\n     int                                     rowbyte;            /* glyph rowbyte */\n     int                                     bitoffset;          /* glyph bitoffset */\n     int                                     fgcolor;            /* foreground color */\n     int                                     bgcolor;            /* background color */\n     int                                     hzoom;              /* horizontal zoom factor */\n     int                                     vzoom;              /* vertical zoom factor */\n} DFBMonoGlyphAttributes;\n\n/*\n * Frame time configuration flags.\n */\ntypedef enum {\n     DFTCF_NONE                            = 0x00000000,         /* None of these. */\n\n     DFTCF_INTERVAL                        = 0x00000001,         /* Interval is specified, otherwise the interval is set\n                                                                    automatically depending on screen refresh. */\n     DFTCF_MAX_ADVANCE                     = 0x00000002,         /* Maximum time to render in advance, GetFrameTime()\n                                                                    will block to keep the limit. */\n\n     DFTCF_ALL                             = 0x00000003,         /* All of these. */\n} DFBFrameTimeConfigFlags;\n\n/*\n * Frame time configuration.\n */\ntypedef struct {\n     DFBFrameTimeConfigFlags                 flags;              /* Validation of fields. */\n\n     long long                               interval;           /* Interval time. */\n     long long                               max_advance;        /* Maximum time ahead for rendering frames. */\n} DFBFrameTimeConfig;\n\n/*\n * Buffer role.\n */\ntypedef enum {\n     DSBR_FRONT                            = 0x00000000,         /* Front buffer. */\n     DSBR_BACK                             = 0x00000001,         /* Back buffer */\n     DSBR_IDLE                             = 0x00000002          /* Idle buffer. */\n} DFBSurfaceBufferRole;\n\n/*\n * IDirectFBSurface is the surface interface.\n */\nD_DEFINE_INTERFACE( IDirectFBSurface,\n\n   /** Retrieving information **/\n\n     /*\n      * Return the capabilities of this surface.\n      */\n     DFBResult (*GetCapabilities) (\n          IDirectFBSurface                  *thiz,\n          DFBSurfaceCapabilities            *ret_caps\n     );\n\n     /*\n      * Get the surface's position in pixels.\n      */\n     DFBResult (*GetPosition) (\n          IDirectFBSurface                  *thiz,\n          int                               *ret_x,\n          int                               *ret_y\n     );\n\n     /*\n      * Get the surface's width and height in pixels.\n      */\n     DFBResult (*GetSize) (\n          IDirectFBSurface                  *thiz,\n          int                               *ret_width,\n          int                               *ret_height\n     );\n\n     /*\n      * Created sub surfaces might be clipped by their parents,\n      * this function returns the resulting rectangle relative\n      * to this surface.\n      *\n      * For non sub surfaces this function returns\n      * { 0, 0, width, height }.\n      */\n     DFBResult (*GetVisibleRectangle) (\n          IDirectFBSurface                  *thiz,\n          DFBRectangle                      *ret_rect\n     );\n\n     /*\n      * Get the current pixel format.\n      */\n     DFBResult (*GetPixelFormat) (\n          IDirectFBSurface                  *thiz,\n          DFBSurfacePixelFormat             *ret_pixelformat\n     );\n\n     /*\n      * Get the current color space.\n      */\n     DFBResult (*GetColorSpace) (\n          IDirectFBSurface                  *thiz,\n          DFBSurfaceColorSpace              *ret_colorspace\n     );\n\n     /*\n      * Get a mask of drawing functions that are hardware\n      * accelerated with the current settings.\n      *\n      * If a source surface is specified the mask will also\n      * contain accelerated blitting functions. Note that there\n      * is no guarantee that these will actually be accelerated\n      * since the surface storage (video/system) is examined\n      * only when something actually gets drawn or blitted.\n      */\n     DFBResult (*GetAccelerationMask) (\n          IDirectFBSurface                  *thiz,\n          IDirectFBSurface                  *source,\n          DFBAccelerationMask               *ret_mask\n     );\n\n   /** Palette & Alpha Ramp **/\n\n     /*\n      * Get access to the surface's palette.\n      *\n      * Returns an interface that can be used to gain read\n      * and/or write access to the surface's palette.\n      */\n     DFBResult (*GetPalette) (\n          IDirectFBSurface                  *thiz,\n          IDirectFBPalette                 **ret_interface\n     );\n\n     /*\n      * Change the surface's palette.\n      */\n     DFBResult (*SetPalette) (\n          IDirectFBSurface                  *thiz,\n          IDirectFBPalette                  *palette\n     );\n\n     /*\n      * Set the alpha ramp for formats with one or two\n      * alpha bits.\n      *\n      * Either all four values or the first and the last one\n      * are used, depending on the format.\n      * Default values are: 0x00, 0x55, 0xaa, 0xff.\n      */\n     DFBResult (*SetAlphaRamp) (\n          IDirectFBSurface                  *thiz,\n          u8                                 a0,\n          u8                                 a1,\n          u8                                 a2,\n          u8                                 a3\n     );\n\n   /** Buffer operations **/\n\n     /*\n      * Get the current stereo eye.\n      *\n      * Only applicable to window/layer surfaces with the\n      * DWCAPS_STEREO or DLOP_STEREO option. This method will\n      * retrieve which set of buffers (left or right) is\n      * currently active for operations on this surface.\n      */\n     DFBResult (*GetStereoEye) (\n          IDirectFBSurface                  *thiz,\n          DFBSurfaceStereoEye               *ret_eye\n     );\n\n     /*\n      * Select the stereo eye for future operations.\n      *\n      * Only applicable to window/layer surfaces with the\n      * DWCAPS_STEREO or DLOP_STEREO option. This method will\n      * specify which set of buffers (left or right) is to be\n      * used for future operations on this surface.\n      */\n     DFBResult (*SetStereoEye) (\n          IDirectFBSurface                  *thiz,\n          DFBSurfaceStereoEye                eye\n     );\n\n     /*\n      * Lock the surface for the access type specified.\n      *\n      * Returns a data pointer and the line pitch of it.\n      * Note: if the surface is double/triple buffered and the\n      * DSLF_WRITE flag is specified, the pointer is to the back\n      * buffer. In all other cases, the pointer is to the front\n      * buffer.\n      */\n     DFBResult (*Lock) (\n          IDirectFBSurface                  *thiz,\n          DFBSurfaceLockFlags                flags,\n          void                             **ret_ptr,\n          int                               *ret_pitch\n     );\n\n     /*\n      * Return the framebuffer offset of a locked surface.\n      */\n     DFBResult (*GetFramebufferOffset) (\n          IDirectFBSurface                  *thiz,\n          int                               *offset\n     );\n\n     /*\n      * Unlock the surface after direct access.\n      */\n     DFBResult (*Unlock) (\n          IDirectFBSurface                  *thiz\n     );\n\n     /*\n      * Flip/Update surface buffers.\n      *\n      * If no region is specified the whole surface is flipped,\n      * otherwise blitting is used to update the region.\n      * If surface capabilities don't include DSCAPS_FLIPPING,\n      * this method has the effect to make visible changes\n      * made to the surface contents.\n      */\n     DFBResult (*Flip) (\n          IDirectFBSurface                  *thiz,\n          const DFBRegion                   *region,\n          DFBSurfaceFlipFlags                flags\n     );\n\n     /*\n      * Flip/Update stereo surface buffers.\n      *\n      * Flips both the left and right buffers simultaneously to\n      * ensure synchronization between the two.\n      * Only applicable to window and layer surfaces with the\n      * DWCAPS_STEREO or DLOP_STEREO option. This method will\n      * fail with all other surfaces.\n      * If no region is specified the whole surface is flipped,\n      * otherwise blitting is used to update the region.\n      * If surface capabilities don't include DSCAPS_FLIPPING,\n      * this method has the effect to make visible changes made\n      * to the surface contents.\n      */\n     DFBResult (*FlipStereo) (\n          IDirectFBSurface                  *thiz,\n          const DFBRegion                   *left_region,\n          const DFBRegion                   *right_region,\n          DFBSurfaceFlipFlags                flags\n     );\n\n     /*\n      * Set the active field.\n      *\n      * Interlaced surfaces consist of two fields. Software\n      * driven deinterlacing uses this method to manually switch\n      * the field that is displayed, e.g. scaled up vertically\n      * by two.\n      */\n     DFBResult (*SetField) (\n          IDirectFBSurface                  *thiz,\n          int                                field\n     );\n\n     /*\n      * Clear the surface and its depth buffer if existent.\n      *\n      * Fills the whole (sub) surface with the specified color\n      * while ignoring drawing flags and color of the current\n      * state, but limited to the current clip.\n      * As with all drawing and blitting functions the\n      * backbuffer is written to. If you are initializing a\n      * double buffered surface you may want to clear both\n      * buffers by doing a Clear-Flip-Clear sequence.\n      */\n     DFBResult (*Clear) (\n          IDirectFBSurface                  *thiz,\n          u8                                 r,\n          u8                                 g,\n          u8                                 b,\n          u8                                 a\n     );\n\n   /** Drawing/blitting control **/\n\n     /*\n      * Set the clipping region used to limit the area for\n      * drawing, blitting and text functions.\n      *\n      * If no region is specified (NULL passed) the clip is set\n      * to the surface extents (initial clip).\n      */\n     DFBResult (*SetClip) (\n          IDirectFBSurface                  *thiz,\n          const DFBRegion                   *clip\n     );\n\n     /*\n      * Get the clipping region used to limit the area for\n      * drawing, blitting and text functions.\n      */\n     DFBResult (*GetClip) (\n          IDirectFBSurface                  *thiz,\n          DFBRegion                         *ret_clip\n     );\n\n     /*\n      * Set the color used for drawing/text functions or\n      * alpha/color modulation (blitting functions).\n      *\n      * If you are not using the alpha value it should be set to\n      * 0xff to ensure visibility when the code is ported to or\n      * used for surfaces with an alpha channel.\n      */\n     DFBResult (*SetColor) (\n          IDirectFBSurface                  *thiz,\n          u8                                 r,\n          u8                                 g,\n          u8                                 b,\n          u8                                 a\n     );\n\n     /*\n      * Set the color like with SetColor() but using an index to\n      * the color/alpha lookup table.\n      *\n      * This method is only supported by surfaces with an\n      * indexed pixelformat, e.g. DSPF_LUT8. For these formats\n      * this method should be used instead of SetColor().\n      */\n     DFBResult (*SetColorIndex) (\n          IDirectFBSurface                  *thiz,\n          unsigned int                       index\n     );\n\n     /*\n      * Set the blend function that applies to the source.\n      */\n     DFBResult (*SetSrcBlendFunction) (\n          IDirectFBSurface                  *thiz,\n          DFBSurfaceBlendFunction            function\n     );\n\n     /*\n      * Set the blend function that applies to the destination.\n      */\n     DFBResult (*SetDstBlendFunction) (\n          IDirectFBSurface                  *thiz,\n          DFBSurfaceBlendFunction            function\n     );\n\n     /*\n      * Set the source and destination blend function by\n      * specifying a Porter/Duff rule.\n      */\n     DFBResult (*SetPorterDuff) (\n          IDirectFBSurface                  *thiz,\n          DFBSurfacePorterDuffRule           rule\n     );\n\n     /*\n      * Set the source color key, i.e. the color that is\n      * excluded when blitting from this surface to another\n      * that has source color keying enabled.\n      */\n     DFBResult (*SetSrcColorKey) (\n          IDirectFBSurface                  *thiz,\n          u8                                 r,\n          u8                                 g,\n          u8                                 b\n     );\n\n     /*\n      * Set the source color key like with SetSrcColorKey() but\n      * using an index to the color/alpha lookup table.\n      *\n      * This method is only supported by surfaces with an\n      * indexed pixelformat, e.g. DSPF_LUT8. For these formats\n      * this method should be used instead of SetSrcColorKey().\n      */\n     DFBResult (*SetSrcColorKeyIndex) (\n          IDirectFBSurface                  *thiz,\n          unsigned int                       index\n     );\n\n     /*\n      * Set the destination color key, i.e. the only color that\n      * gets overwritten by drawing and blitting to this surface\n      * when destination color keying is enabled.\n      */\n     DFBResult (*SetDstColorKey) (\n          IDirectFBSurface                  *thiz,\n          u8                                 r,\n          u8                                 g,\n          u8                                 b\n     );\n\n     /*\n      * Set the destination color key like with SetDstColorKey()\n      * but using an index to the color/alpha lookup table.\n      *\n      * This method is only supported by surfaces with an\n      * indexed pixelformat, e.g. DSPF_LUT8. For these formats\n      * this method should be used instead of SetDstColorKey().\n      */\n     DFBResult (*SetDstColorKeyIndex) (\n          IDirectFBSurface                  *thiz,\n          unsigned int                       index\n     );\n\n   /** Blitting functions **/\n\n     /*\n      * Set the flags for all subsequent blitting commands.\n      */\n     DFBResult (*SetBlittingFlags) (\n          IDirectFBSurface                  *thiz,\n          DFBSurfaceBlittingFlags            flags\n     );\n\n     /*\n      * Blit an area from the source to this surface.\n      *\n      * Pass a NULL rectangle to use the whole source surface.\n      * Source may be the same surface.\n      */\n     DFBResult (*Blit) (\n          IDirectFBSurface                  *thiz,\n          IDirectFBSurface                  *source,\n          const DFBRectangle                *source_rect,\n          int                                x,\n          int                                y\n     );\n\n     /*\n      * Blit an area from the source tiled to this surface.\n      *\n      * Pass a NULL rectangle to use the whole source surface.\n      * Source may be the same surface.\n      */\n     DFBResult (*TileBlit) (\n          IDirectFBSurface                  *thiz,\n          IDirectFBSurface                  *source,\n          const DFBRectangle                *source_rect,\n          int                                x,\n          int                                y\n     );\n\n     /*\n      * Blit a bunch of areas at once.\n      *\n      * Source may be the same surface.\n      */\n     DFBResult (*BatchBlit) (\n          IDirectFBSurface                  *thiz,\n          IDirectFBSurface                  *source,\n          const DFBRectangle                *source_rects,\n          const DFBPoint                    *dest_points,\n          int                                num\n     );\n\n     /*\n      * Blit an area scaled from the source to the destination\n      * rectangle.\n      *\n      * Pass a NULL rectangle to use the whole source surface.\n      */\n     DFBResult (*StretchBlit) (\n          IDirectFBSurface                  *thiz,\n          IDirectFBSurface                  *source,\n          const DFBRectangle                *source_rect,\n          const DFBRectangle                *dest_rect\n     );\n\n     /*\n      * Texture mapping support.\n      *\n      * Maps a 'texture' onto triangles being built from\n      * 'vertices' according to the chosen 'formation'.\n      * Optional 'indices' can be used to avoid rearrangement\n      * of vertex lists, otherwise the vertex list is processed\n      * consecutively, i.e. as if 'indices' are ascending\n      * numbers starting at zero.\n      * Either the number of 'indices' or the number of\n      * 'vertices' is specified by 'num' and has to be three\n      * at least. If the chosen 'formation' is DTTF_LIST,\n      * it also has to be a multiple of three.\n      */\n     DFBResult (*TextureTriangles) (\n          IDirectFBSurface                  *thiz,\n          IDirectFBSurface                  *texture,\n          const DFBVertex                   *vertices,\n          const int                         *indices,\n          int                                num,\n          DFBTriangleFormation               formation\n     );\n\n   /** Drawing functions **/\n\n     /*\n      * Set the flags for all subsequent drawing commands.\n      */\n     DFBResult (*SetDrawingFlags) (\n          IDirectFBSurface                  *thiz,\n          DFBSurfaceDrawingFlags             flags\n     );\n\n     /*\n      * Fill the specified rectangle with the given color\n      * following the drawing flags.\n      */\n     DFBResult (*FillRectangle) (\n          IDirectFBSurface                  *thiz,\n          int                                x,\n          int                                y,\n          int                                w,\n          int                                h\n     );\n\n     /*\n      * Draw an outline of the specified rectangle with the\n      * given color following the drawing flags.\n      */\n     DFBResult (*DrawRectangle) (\n          IDirectFBSurface                  *thiz,\n          int                                x,\n          int                                y,\n          int                                w,\n          int                                h\n     );\n\n     /*\n      * Draw a line from one point to the other with the given\n      * color following the drawing flags.\n      */\n     DFBResult (*DrawLine) (\n          IDirectFBSurface                  *thiz,\n          int                                x1,\n          int                                y1,\n          int                                x2,\n          int                                y2\n     );\n\n     /*\n      * Draw lines.\n      *\n      * Draw 'num_lines' lines with the given color following\n      * the drawing flags. Each line specified by a DFBRegion.\n      */\n     DFBResult (*DrawLines) (\n          IDirectFBSurface                  *thiz,\n          const DFBRegion                   *lines,\n          unsigned int                       num_lines\n     );\n\n     /*\n      * Fill a non-textured triangle with the given color\n      * following the drawing flags.\n      */\n     DFBResult (*FillTriangle) (\n          IDirectFBSurface                  *thiz,\n          int                                x1,\n          int                                y1,\n          int                                x2,\n          int                                y2,\n          int                                x3,\n          int                                y3\n     );\n\n     /*\n      * Fill a bunch of rectangles with a single call.\n      *\n      * Fill 'num_rects' rectangles with the current color\n      * following the drawing flags. Each rectangle specified\n      * by a DFBRectangle.\n      */\n     DFBResult (*FillRectangles) (\n          IDirectFBSurface                  *thiz,\n          const DFBRectangle                *rects,\n          unsigned int                       num_rects\n     );\n\n     /*\n      * Fill spans.\n      *\n      * Fill 'num_spans' spans with the given color following\n      * the drawing flags. Each span is specified by a DFBSpan.\n      */\n     DFBResult (*FillSpans) (\n          IDirectFBSurface                  *thiz,\n          int                                y,\n          const DFBSpan                     *spans,\n          unsigned int                       num_spans\n     );\n\n     /*\n      * Fill a bunch of triangles with a single call.\n      *\n      * Fill 'num_tris' triangles with the current color\n      * following the drawing flags. Each triangle specified\n      * by a DFBTriangle.\n      */\n     DFBResult (*FillTriangles) (\n          IDirectFBSurface                  *thiz,\n          const DFBTriangle                 *tris,\n          unsigned int                       num_tris\n     );\n\n   /** Text functions **/\n\n     /*\n      * Set the font used by DrawString() and DrawGlyph().\n      * You can pass NULL here to unset the font.\n      */\n     DFBResult (*SetFont) (\n          IDirectFBSurface                  *thiz,\n          IDirectFBFont                     *font\n     );\n\n     /*\n      * Get the font associated with a surface.\n      *\n      * This function increases the font's reference count.\n      */\n     DFBResult (*GetFont) (\n          IDirectFBSurface                  *thiz,\n          IDirectFBFont                    **ret_interface\n     );\n\n     /*\n      * Draw a string at the specified position with the given\n      * color following the specified flags.\n      *\n      * Bytes specifies the number of bytes to take from the\n      * string or -1 for the complete NULL-terminated string.\n      * You need to set a font using the SetFont() method before\n      * calling this function.\n      */\n     DFBResult (*DrawString) (\n          IDirectFBSurface                  *thiz,\n          const char                        *text,\n          int                                bytes,\n          int                                x,\n          int                                y,\n          DFBSurfaceTextFlags                flags\n     );\n\n     /*\n      * Draw a single glyph specified by its character code at\n      * the specified position with the given color following\n      * the specified flags.\n      *\n      * If font was loaded with the DFFA_NOCHARMAP flag, index\n      * specifies the raw glyph index in the font.\n      * You need to set a font using the SetFont() method before\n      * calling this function.\n      */\n     DFBResult (*DrawGlyph) (\n          IDirectFBSurface                  *thiz,\n          unsigned int                       character,\n          int                                x,\n          int                                y,\n          DFBSurfaceTextFlags                flags\n     );\n\n     /*\n      * Change the encoding used for text rendering.\n      */\n     DFBResult (*SetEncoding) (\n          IDirectFBSurface                  *thiz,\n          DFBTextEncodingID                  encoding\n     );\n\n   /** Lightweight helpers **/\n\n     /*\n      * Get an interface to a sub area of this surface.\n      *\n      * No image data is duplicated, this is a clipped graphics\n      * within the original surface. This is very helpful for\n      * lightweight components in a GUI toolkit. The new\n      * surface's state (color, drawing flags, etc.) is\n      * independent from this one. So it's a handy graphics\n      * context. If no rectangle is specified, the whole surface\n      * (or a part if this surface is a subsurface itself) is\n      * represented by the new one.\n      */\n     DFBResult (*GetSubSurface) (\n          IDirectFBSurface                  *thiz,\n          const DFBRectangle                *rect,\n          IDirectFBSurface                 **ret_interface\n     );\n\n   /** OpenGL **/\n\n     /*\n      * Get a unique OpenGL context for this surface.\n      */\n     DFBResult (*GetGL) (\n          IDirectFBSurface                  *thiz,\n          IDirectFBGL                      **ret_interface\n     );\n\n   /** Debug **/\n\n     /*\n      * Dump the contents of the surface to one or two files.\n      *\n      * Create a PPM file containing the RGB data and a PGM file\n      * with the alpha data if present.\n      * The complete filenames will be\n      * 'directory'/'prefix'_####.ppm for RGB and\n      * 'directory'/'prefix'_####.pgm for the alpha channel\n      * if present.\n      * No existing files will be overwritten.\n      */\n     DFBResult (*Dump) (\n          IDirectFBSurface                  *thiz,\n          const char                        *directory,\n          const char                        *prefix\n     );\n\n     /*\n      * Disable hardware acceleration.\n      *\n      * If any function in 'mask' is set, acceleration will not\n      * be used for it. Default is DFXL_NONE.\n      */\n     DFBResult (*DisableAcceleration) (\n          IDirectFBSurface                  *thiz,\n          DFBAccelerationMask                mask\n     );\n\n   /** Resources **/\n\n     /*\n      * Release possible reference to source surface.\n      *\n      * For performance reasons the last surface that has been\n      * used for Blit() and others stays attached to the state\n      * of the destination surface to save the overhead of\n      * reprogramming the same values each time. The worst case\n      * is generation of thumbnails using StretchBlit() from a\n      * huge surface to a small one. The small thumbnail surface\n      * keeps the big one alive, because no other blitting will\n      * be done to the small surface afterwards. To solve this,\n      * here is the method to use in such a case.\n      */\n     DFBResult (*ReleaseSource) (\n          IDirectFBSurface                  *thiz\n     );\n\n   /** Blitting control **/\n\n     /*\n      * Set index translation table.\n      *\n      * Set the translation table used for fast indexed to\n      * indexed pixel format conversion. A negative index means\n      * that the pixel will not be written.\n      * Undefined indices will be treated like negative ones.\n      */\n     DFBResult (*SetIndexTranslation) (\n          IDirectFBSurface                  *thiz,\n          const int                         *indices,\n          int                                num_indices\n     );\n\n   /** Rendering **/\n\n     /*\n      * Set options affecting the output of drawing and blitting\n      * operations.\n      *\n      * None of these is mandatory and therefore unsupported\n      * flags will not cause a software fallback.\n      */\n     DFBResult (*SetRenderOptions) (\n          IDirectFBSurface                  *thiz,\n          DFBSurfaceRenderOptions            options\n     );\n\n   /** Drawing/blitting control **/\n\n     /*\n      * Set the transformation matrix.\n      *\n      * Enable usage of this matrix by setting DSRO_MATRIX via\n      * SetRenderOptions().\n      * The order in the array is from left to right and from\n      * top to bottom.\n      * All drawing and blitting will be transformed:\n      *   X' = (X * v0 + Y * v1 + v2) / (X * v6 + Y * v7 + v8)\n      *   Y' = (X * v3 + Y * v4 + v5) / (X * v6 + Y * v7 + v8)\n      */\n     DFBResult (*SetMatrix) (\n          IDirectFBSurface                  *thiz,\n          const s32                         *matrix\n     );\n\n     /*\n      * Set the surface to be used as a mask for blitting.\n      *\n      * The 'mask' applies when DSBLIT_SRC_MASK_ALPHA or\n      * DSBLIT_SRC_MASK_COLOR is used.\n      * Depending on the 'flags' reading either starts at a\n      * fixed location in the mask with absolute 'x' and 'y',\n      * or at the same location as in the source, with 'x'and\n      * and 'y' used as an offset.\n      */\n     DFBResult (*SetSourceMask) (\n          IDirectFBSurface                  *thiz,\n          IDirectFBSurface                  *mask,\n          int                                x,\n          int                                y,\n          DFBSurfaceMaskFlags                flags\n     );\n\n   /** Lightweight helpers **/\n\n     /*\n      * Make this a sub surface or adjust the rectangle of this\n      * sub surface.\n      */\n     DFBResult (*MakeSubSurface) (\n          IDirectFBSurface                  *thiz,\n          IDirectFBSurface                  *from,\n          const DFBRectangle                *rect\n     );\n\n   /** Direct Write/Read **/\n\n     /*\n      * Write to the surface without the need for (Un)Lock().\n      *\n      * 'rect' defines the area inside the surface.\n      * 'ptr' and 'pitch' specify the source.\n      * The format of the surface and the source data must be\n      * the same.\n      */\n     DFBResult (*Write) (\n          IDirectFBSurface                  *thiz,\n          const DFBRectangle                *rect,\n          const void                        *ptr,\n          int                                pitch\n     );\n\n     /*\n      * Read from the surface without the need for (Un)Lock().\n      *\n      * 'rect' defines the area inside the surface to be read.\n      * 'ptr' and 'pitch' specify the destination.\n      * The destination data will have the same format as the\n      * surface.\n      */\n     DFBResult (*Read) (\n          IDirectFBSurface                  *thiz,\n          const DFBRectangle                *rect,\n          void                              *ptr,\n          int                                pitch\n     );\n\n   /** Drawing/blitting control **/\n\n     /*\n      * Set color values used for drawing/text functions or\n      * alpha/color modulation (blitting functions).\n      */\n     DFBResult (*SetColors) (\n          IDirectFBSurface                  *thiz,\n          const DFBColorID                  *ids,\n          const DFBColor                    *colors,\n          unsigned int                       num\n     );\n\n   /** Blitting functions **/\n\n     /*\n      * Blit a bunch of areas at once using secondary source for\n      * reading instead of destination.\n      *\n      * Source may be the same surface.\n      */\n     DFBResult (*BatchBlit2) (\n          IDirectFBSurface                  *thiz,\n          IDirectFBSurface                  *source,\n          IDirectFBSurface                  *source2,\n          const DFBRectangle                *source_rects,\n          const DFBPoint                    *dest_points,\n          const DFBPoint                    *source2_points,\n          int                                num\n     );\n\n   /** Buffer operations **/\n\n     /*\n      * Return the physical address of a locked surface.\n      *\n      * The surface must exist in a video memory pool.\n      */\n     DFBResult (*GetPhysicalAddress) (\n          IDirectFBSurface                  *thiz,\n          unsigned long                     *addr\n     );\n\n   /** Drawing functions **/\n\n     /*\n      * Fill a bunch of trapezoids with a single call.\n      *\n      * Fill 'num_traps' trapezoids with the current color\n      * following the drawing flags. Each trapezoid specified\n      * by a DFBTrapezoid.\n      */\n     DFBResult (*FillTrapezoids) (\n          IDirectFBSurface                  *thiz,\n          const DFBTrapezoid                *traps,\n          unsigned int                       num_traps\n     );\n\n     /*\n      * Fill quadrangles with the given color following the\n      * drawing flags.\n      */\n     DFBResult (*FillQuadrangles) (\n          IDirectFBSurface                  *thiz,\n          const DFBPoint                    *points,\n          unsigned int                       num_points\n     );\n\n   /** Extended color keys **/\n\n     /*\n      * Set extended source color keying.\n      */\n     DFBResult (*SetSrcColorKeyExtended) (\n          IDirectFBSurface                  *thiz,\n          const DFBColorKeyExtended         *colorkey_extended\n     );\n\n     /*\n      * Set extended destination color keying.\n      */\n     DFBResult (*SetDstColorKeyExtended) (\n          IDirectFBSurface                  *thiz,\n          const DFBColorKeyExtended         *colorkey_extended\n     );\n\n   /** Drawing functions **/\n\n     /*\n      * Blit monochrome glyph data with attributes.\n      */\n     DFBResult (*DrawMonoGlyphs) (\n           IDirectFBSurface                 *thiz,\n           const void                       *glyph[],\n           const DFBMonoGlyphAttributes     *attributes,\n           const DFBPoint                   *dest_points,\n           unsigned int                      num\n     );\n\n   /** Blitting control **/\n\n     /*\n      * Set the source color matrix.\n      *\n      * Enable usage of this matrix by setting\n      * DSBLIT_SRC_COLORMATRIX via SetBlittingFlags().\n      * The order in the array is from left to right and from\n      * top to bottom.\n      * All RGB values will be transformed:\n      *   R' = R * v0 + G * v1 + B * v2  + v3\n      *   G' = R * v4 + G * v5 + B * v6  + v7\n      *   B' = R * v8 + G * v9 + B * v10 + v11\n      */\n     DFBResult (*SetSrcColorMatrix) (\n          IDirectFBSurface                  *thiz,\n          const s32                         *matrix\n     );\n\n     /*\n      * Set the source convolution filter.\n      *\n      * Enable usage of this filter by setting\n      * DSBLIT_SRC_CONVOLUTION via SetBlittingFlags().\n      */\n     DFBResult (*SetSrcConvolution) (\n          IDirectFBSurface                  *thiz,\n          const DFBConvolutionFilter        *filter\n     );\n\n   /** Retrieving information **/\n\n     /*\n      * Get the unique surface ID.\n      */\n     DFBResult (*GetID) (\n          IDirectFBSurface                  *thiz,\n          DFBSurfaceID                      *ret_surface_id\n     );\n\n   /** Process security **/\n\n     /*\n      * Allow access.\n      */\n     DFBResult (*AllowAccess) (\n          IDirectFBSurface                  *thiz,\n          const char                        *executable\n     );\n\n  /** Event buffers **/\n\n     /*\n      * Create an event buffer for this surface and attach it.\n      */\n     DFBResult (*CreateEventBuffer) (\n          IDirectFBSurface                  *thiz,\n          IDirectFBEventBuffer             **ret_interface\n     );\n\n     /*\n      * Attach an existing event buffer to this surface.\n      *\n      * Note: attaching multiple times generates multiple\n      * events.\n      */\n     DFBResult (*AttachEventBuffer) (\n          IDirectFBSurface                  *thiz,\n          IDirectFBEventBuffer              *buffer\n     );\n\n     /*\n      * Detach an event buffer from this surface.\n      */\n     DFBResult (*DetachEventBuffer) (\n          IDirectFBSurface                  *thiz,\n          IDirectFBEventBuffer              *buffer\n     );\n\n   /** Blitting functions **/\n     /*\n      * Blit a bunch of areas scaled from the source to the\n      * destination rectangles.\n      *\n      * 'source_rects' and 'dest_rects' will be modified.\n      */\n     DFBResult (*BatchStretchBlit) (\n          IDirectFBSurface                  *thiz,\n          IDirectFBSurface                  *source,\n          const DFBRectangle                *source_rects,\n          const DFBRectangle                *dest_rects,\n          int                                num\n     );\n\n   /** Client **/\n\n     /*\n      * Put in client mode for frame synchronization.\n      */\n     DFBResult (*MakeClient) (\n          IDirectFBSurface                  *thiz\n     );\n\n     /*\n      * Acknowledge frame.\n      */\n     DFBResult (*FrameAck) (\n          IDirectFBSurface                  *thiz,\n          u32                                flip_count\n     );\n\n   /** Debug **/\n\n     /*\n      * Dump the contents of the surface to one or two files in\n      * raw format.\n      *\n      * Create a RAW file containing the ARGB data.\n      * The complete filename will be:\n      * 'directory'/'prefix'_####.raw for ARGB.\n      * No existing files will be overwritten.\n      */\n     DFBResult (*DumpRaw) (\n          IDirectFBSurface                  *thiz,\n          const char                        *directory,\n          const char                        *prefix\n     );\n\n   /** Timing **/\n\n     /*\n      * Retrieve timestamp for next frame to be rendered.\n      */\n     DFBResult (*GetFrameTime) (\n          IDirectFBSurface                  *thiz,\n          long long                         *ret_micros\n     );\n\n     /*\n      * Set configuration for GetFrameTime().\n      */\n     DFBResult (*SetFrameTimeConfig) (\n          IDirectFBSurface                  *thiz,\n          const DFBFrameTimeConfig          *config\n     );\n\n  /** Allocations **/\n\n     /*\n      * Add implementation specific handle as buffer allocation.\n      */\n     DFBResult (*Allocate) (\n          IDirectFBSurface                  *thiz,\n          DFBSurfaceBufferRole               role,\n          DFBSurfaceStereoEye                eye,\n          const char                        *key,\n          u64                                handle,\n          IDirectFBSurfaceAllocation       **ret_interface\n     );\n\n     /*\n      * Acquire implementation specific handle from surface.\n      */\n     DFBResult (*GetAllocation) (\n          IDirectFBSurface                  *thiz,\n          DFBSurfaceBufferRole               role,\n          DFBSurfaceStereoEye                eye,\n          const char                        *key,\n          IDirectFBSurfaceAllocation       **ret_interface\n     );\n\n     /*\n      * Acquire implementation specific handles from surface.\n      */\n     DFBResult (*GetAllocations) (\n          IDirectFBSurface                  *thiz,\n          const char                        *key,\n          unsigned int                       max_num,\n          unsigned int                      *ret_num,\n          IDirectFBSurfaceAllocation       **ret_interface_left,\n          IDirectFBSurfaceAllocation       **ret_interface_right\n     );\n\n   /** Interface **/\n\n     /*\n      * Flush pending drawing operations.\n      *\n      * This function flushes the internal buffer like done\n      * implicitly by Flip().\n      * This can be used to transfer the interface to another\n      * thread, as call buffers are bound to each thread.\n      */\n     DFBResult (*Flush) (\n          IDirectFBSurface                  *thiz\n     );\n)\n\n/******************************\n * IDirectFBSurfaceAllocation *\n ******************************/\n\n/*\n * IDirectFBSurfaceAllocation is the surface allocation\n * interface.\n */\nD_DEFINE_INTERFACE( IDirectFBSurfaceAllocation,\n\n   /** Retrieving information **/\n\n     /*\n      * Get a description of the allocation's surface.\n      */\n     DFBResult (*GetDescription) (\n          IDirectFBSurfaceAllocation        *thiz,\n          DFBSurfaceDescription             *ret_desc\n     );\n\n   /** Access **/\n\n     /*\n      * Get the surface allocation data.\n      */\n     DFBResult (*GetHandle) (\n          IDirectFBSurfaceAllocation        *thiz,\n          u64                               *ret_handle\n     );\n\n     /*\n      * Get the surface allocation pitch.\n      */\n     DFBResult (*GetPitch) (\n          IDirectFBSurfaceAllocation        *thiz,\n          int                               *ret_pitch\n     );\n\n     /*\n      * Updated the allocation's surface.\n      */\n     DFBResult (*Updated) (\n          IDirectFBSurfaceAllocation        *thiz,\n          const DFBBox                      *updates,\n          unsigned int                       num_updates\n     );\n)\n\n/********************\n * IDirectFBPalette *\n ********************/\n\n/*\n * IDirectFBPalette is the palette interface.\n */\nD_DEFINE_INTERFACE( IDirectFBPalette,\n\n   /** Retrieving information **/\n\n     /*\n      * Return the capabilities of this palette.\n      */\n     DFBResult (*GetCapabilities) (\n          IDirectFBPalette                  *thiz,\n          DFBPaletteCapabilities            *ret_caps\n     );\n\n     /*\n      * Get the number of entries in the palette.\n      */\n     DFBResult (*GetSize) (\n          IDirectFBPalette                  *thiz,\n          unsigned int                      *ret_size\n     );\n\n   /** Palette entries **/\n\n     /*\n      * Write entries to the palette.\n      *\n      * Writes the specified number of entries to the palette\n      * at the specified offset.\n      */\n     DFBResult (*SetEntries) (\n          IDirectFBPalette                  *thiz,\n          const DFBColor                    *entries,\n          unsigned int                       num_entries,\n          unsigned int                       offset\n     );\n\n     /*\n      * Read entries from the palette.\n      *\n      * Reads the specified number of entries from the palette\n      * at the specified offset.\n      */\n     DFBResult (*GetEntries) (\n          IDirectFBPalette                  *thiz,\n          DFBColor                          *ret_entries,\n          unsigned int                       num_entries,\n          unsigned int                       offset\n     );\n\n     /*\n      * Find the best matching entry.\n      *\n      * Searches the map for an entry which best matches the\n      * specified color.\n      */\n     DFBResult (*FindBestMatch) (\n          IDirectFBPalette                  *thiz,\n          u8                                 r,\n          u8                                 g,\n          u8                                 b,\n          u8                                 a,\n          unsigned int                      *ret_index\n     );\n\n   /** Clone **/\n\n     /*\n      * Create a copy of the palette.\n      */\n     DFBResult (*CreateCopy) (\n          IDirectFBPalette                  *thiz,\n          IDirectFBPalette                 **ret_interface\n     );\n\n\n   /** YUV Palette **/\n\n     /*\n      * Write entries to the palette.\n      *\n      * Writes the specified number of entries to the palette\n      * at the specified offset.\n      */\n     DFBResult (*SetEntriesYUV) (\n          IDirectFBPalette                  *thiz,\n          const DFBColorYUV                 *entries,\n          unsigned int                       num_entries,\n          unsigned int                       offset\n     );\n\n     /*\n      * Read entries from the palette.\n      *\n      * Reads the specified number of entries from the palette\n      * at the specified offset.\n      */\n     DFBResult (*GetEntriesYUV) (\n          IDirectFBPalette                  *thiz,\n          DFBColorYUV                       *ret_entries,\n          unsigned int                       num_entries,\n          unsigned int                       offset\n     );\n\n     /*\n      * Find the best matching entry.\n      *\n      * Searches the map for an entry which best matches the\n      * specified color.\n      */\n     DFBResult (*FindBestMatchYUV) (\n          IDirectFBPalette                  *thiz,\n          u8                                 y,\n          u8                                 u,\n          u8                                 v,\n          u8                                 a,\n          unsigned int                      *ret_index\n     );\n)\n\n/************************\n * IDirectFBInputDevice *\n ************************/\n\n/*\n * Specifies whether a key is currently down.\n */\ntypedef enum {\n     DIKS_UP                               = 0x00000000,         /* key is not pressed */\n     DIKS_DOWN                             = 0x00000001          /* key is pressed */\n} DFBInputDeviceKeyState;\n\n/*\n * Flags specifying which modifiers are currently pressed.\n */\ntypedef enum {\n     DIMM_SHIFT                            = (1<<DIMKI_SHIFT),   /* Shift key is pressed */\n     DIMM_CONTROL                          = (1<<DIMKI_CONTROL), /* Control key is pressed */\n     DIMM_ALT                              = (1<<DIMKI_ALT),     /* Alt key is pressed */\n     DIMM_ALTGR                            = (1<<DIMKI_ALTGR),   /* AltGr key is pressed */\n     DIMM_META                             = (1<<DIMKI_META),    /* Meta key is pressed */\n     DIMM_SUPER                            = (1<<DIMKI_SUPER),   /* Super key is pressed */\n     DIMM_HYPER                            = (1<<DIMKI_HYPER)    /* Hyper key is pressed */\n} DFBInputDeviceModifierMask;\n\n/*\n * Flags specifying which buttons are currently down.\n */\ntypedef enum {\n     DIBM_LEFT                             = 0x00000001,         /* left mouse button */\n     DIBM_RIGHT                            = 0x00000002,         /* right mouse button */\n     DIBM_MIDDLE                           = 0x00000004          /* middle mouse button */\n} DFBInputDeviceButtonMask;\n\n/*\n * Specifies whether a button is currently pressed.\n */\ntypedef enum {\n     DIBS_UP                               = 0x00000000,         /* button is not pressed */\n     DIBS_DOWN                             = 0x00000001          /* button is pressed */\n} DFBInputDeviceButtonState;\n\n/*\n * Input device configuration flags.\n */\ntypedef enum {\n     DIDCONF_NONE                          = 0x00000000,         /* None of these. */\n\n     DIDCONF_SENSITIVITY                   = 0x00000001,         /* Set sensitivity. */\n     DIDCONF_MAX_SLOTS                     = 0x00000002,         /* Set the number of possible touch contacts. */\n\n     DIDCONF_ALL                           = 0x00000003          /* All of these. */\n} DFBInputDeviceConfigFlags;\n\n/*\n * Input device configuration.\n */\ntypedef struct {\n     DFBInputDeviceConfigFlags               flags;              /* Validation of fields. */\n\n     int                                     sensitivity;        /* Sensitivity value for X/Y axes. */\n     int                                     max_slots;          /* Maximum mumber of possible touch contacts. */\n} DFBInputDeviceConfig;\n\n/*\n * IDirectFBInputDevice is the input device interface.\n */\nD_DEFINE_INTERFACE( IDirectFBInputDevice,\n\n   /** Retrieving information **/\n\n     /*\n      * Get the unique device ID.\n      */\n     DFBResult (*GetID) (\n          IDirectFBInputDevice              *thiz,\n          DFBInputDeviceID                  *ret_device_id\n     );\n\n     /*\n      * Get a description of this device, i.e. the capabilities.\n      */\n     DFBResult (*GetDescription) (\n          IDirectFBInputDevice              *thiz,\n          DFBInputDeviceDescription         *ret_desc\n     );\n\n   /** Key mapping **/\n\n     /*\n      * Fetch one entry from the keymap for a specific hardware\n      * keycode.\n      */\n     DFBResult (*GetKeymapEntry) (\n          IDirectFBInputDevice              *thiz,\n          int                                keycode,\n          DFBInputDeviceKeymapEntry         *ret_entry\n     );\n\n     /*\n      * Set one entry of the keymap to the specified entry.\n      *\n      * Each entry has 4 modifier combinations for going from\n      * key to symbol.\n      */\n     DFBResult (*SetKeymapEntry) (\n          IDirectFBInputDevice              *thiz,\n          int                                keycode,\n          DFBInputDeviceKeymapEntry         *entry\n     );\n\n     /*\n      * Load a keymap from the specified file.\n      *\n      * All specified keys will overwrite the current keymap.\n      * On return of an error, the keymap is in an unspecified\n      * state. The file must be ASCII containing lines:\n      * keycode <hw code> = <key id> = <symbol> .... (up to 4)\n      */\n     DFBResult (*LoadKeymap) (\n          IDirectFBInputDevice              *thiz,\n          char                              *filename\n     );\n\n   /** Event buffers **/\n\n     /*\n      * Create an event buffer for this device and attach it.\n      */\n     DFBResult (*CreateEventBuffer) (\n          IDirectFBInputDevice              *thiz,\n          IDirectFBEventBuffer             **ret_interface\n     );\n\n     /*\n      * Attach an existing event buffer to this device.\n      *\n      * Note: attaching multiple times generates multiple\n      * events.\n      *\n      */\n     DFBResult (*AttachEventBuffer) (\n          IDirectFBInputDevice              *thiz,\n          IDirectFBEventBuffer              *buffer\n     );\n\n     /*\n      * Detach an event buffer from this device.\n      */\n     DFBResult (*DetachEventBuffer) (\n          IDirectFBInputDevice              *thiz,\n          IDirectFBEventBuffer              *buffer\n     );\n\n   /** General state queries **/\n\n     /*\n      * Get the current state of one key.\n      */\n     DFBResult (*GetKeyState) (\n          IDirectFBInputDevice              *thiz,\n          DFBInputDeviceKeyIdentifier        key_id,\n          DFBInputDeviceKeyState            *ret_state\n     );\n\n     /*\n      * Get the current modifier mask.\n      */\n     DFBResult (*GetModifiers) (\n          IDirectFBInputDevice              *thiz,\n          DFBInputDeviceModifierMask        *ret_modifiers\n     );\n\n     /*\n      * Get the current state of the key locks.\n      */\n     DFBResult (*GetLockState) (\n          IDirectFBInputDevice              *thiz,\n          DFBInputDeviceLockState           *ret_locks\n     );\n\n     /*\n      * Get a mask of currently pressed buttons.\n      *\n      * The first button corrensponds to the right most bit.\n      */\n     DFBResult (*GetButtons) (\n          IDirectFBInputDevice              *thiz,\n          DFBInputDeviceButtonMask          *ret_buttons\n     );\n\n     /*\n      * Get the state of a button.\n      */\n     DFBResult (*GetButtonState) (\n          IDirectFBInputDevice              *thiz,\n          DFBInputDeviceButtonIdentifier     button,\n          DFBInputDeviceButtonState         *ret_state\n     );\n\n     /*\n      * Get the current value of the specified axis.\n      */\n     DFBResult (*GetAxis) (\n          IDirectFBInputDevice              *thiz,\n          DFBInputDeviceAxisIdentifier       axis,\n          int                               *ret_pos\n     );\n\n   /** Specialized queries **/\n\n     /*\n      * Utility function combining two calls to GetAxis().\n      *\n      * You may leave one of the x/y arguments NULL.\n      */\n     DFBResult (*GetXY) (\n          IDirectFBInputDevice              *thiz,\n          int                               *ret_x,\n          int                               *ret_y\n     );\n\n   /** Configuration **/\n\n     /*\n      * Change config values for the input device.\n      */\n     DFBResult (*SetConfiguration) (\n          IDirectFBInputDevice              *thiz,\n          const DFBInputDeviceConfig        *config\n     );\n)\n\n/************************\n * IDirectFBEventBuffer *\n ************************/\n\n/*\n * Event class.\n */\ntypedef enum {\n     DFEC_NONE                             = 0x00000000,         /* none of these */\n\n     DFEC_INPUT                            = 0x00000001,         /* raw input event */\n     DFEC_WINDOW                           = 0x00000002,         /* windowing event */\n     DFEC_USER                             = 0x00000003,         /* custom event for the user */\n     DFEC_UNIVERSAL                        = 0x00000004,         /* universal event for custom usage\n                                                                    with variable size */\n     DFEC_VIDEOPROVIDER                    = 0x00000005,         /* video provider event */\n     DFEC_SURFACE                          = 0x00000006          /* surface event */\n} DFBEventClass;\n\n/*\n * The type of an input event.\n */\ntypedef enum {\n     DIET_UNKNOWN                          = 0x00000000,         /* unknown event */\n\n     DIET_KEYPRESS                         = 0x00000001,         /* a key is been pressed */\n     DIET_KEYRELEASE                       = 0x00000002,         /* a key is been released */\n     DIET_BUTTONPRESS                      = 0x00000003,         /* a (mouse) button is been pressed */\n     DIET_BUTTONRELEASE                    = 0x00000004,         /* a (mouse) button is been released */\n     DIET_AXISMOTION                       = 0x00000005,         /* mouse/joystick movement */\n} DFBInputEventType;\n\n/*\n * Flags defining which additional (optional) event fields are\n * valid.\n */\ntypedef enum {\n     DIEF_NONE                             = 0x00000000,         /* No additional fields. */\n\n     DIEF_TIMESTAMP                        = 0x00000001,         /* Timestamp is valid. */\n     DIEF_AXISABS                          = 0x00000002,         /* Axis and axisabs are valid. */\n     DIEF_AXISREL                          = 0x00000004,         /* Axis and axisrel are valid. */\n     DIEF_KEYCODE                          = 0x00000008,         /* Used internally by the input core,\n                                                                    always set at application level. */\n     DIEF_KEYID                            = 0x00000010,         /* Used internally by the input core,\n                                                                    always set at application level. */\n     DIEF_KEYSYMBOL                        = 0x00000020,         /* Used internally by the input core,\n                                                                    always set at application level. */\n     DIEF_MODIFIERS                        = 0x00000040,         /* Used internally by the input core,\n                                                                    always set at application level. */\n     DIEF_LOCKS                            = 0x00000080,         /* Used internally by the input core,\n                                                                    always set at application level. */\n     DIEF_BUTTONS                          = 0x00000100,         /* Used internally by the input core,\n                                                                    always set at application level. */\n     DIEF_GLOBAL                           = 0x00000200,         /* Only for event buffers created by\n                                                                    CreateInputEventBuffer() with global events enabled.\n                                                                    Indicates that the event would have been filtered if\n                                                                    the buffer hadn't been global. */\n     DIEF_REPEAT                           = 0x00000400,         /* Repeated event, e.g. key or button press. */\n     DIEF_FOLLOW                           = 0x00000800,         /* Another event will follow immediately,\n                                                                    e.g. x/y axis. */\n     DIEF_MIN                              = 0x00001000,         /* Minimum value is set,\n                                                                    e.g. for absolute axis motion. */\n     DIEF_MAX                              = 0x00002000          /* Maximum value is set,\n                                                                    e.g. for absolute axis motion. */\n} DFBInputEventFlags;\n\n/*\n * An input event, item of an input buffer.\n */\ntypedef struct {\n     DFBEventClass                           clazz;              /* clazz of event */\n     DFBInputEventType                       type;               /* type of event */\n     DFBInputDeviceID                        device_id;          /* source of event */\n     DFBInputEventFlags                      flags;              /* which optional fields are valid */\n     struct timeval                          timestamp;          /* time of event creation */\n     int                                     key_code;           /* hardware keycode, no mapping, -1 if device\n                                                                    doesn't differentiate between several keys */\n     DFBInputDeviceKeyIdentifier             key_id;             /* basic mapping, modifier independent */\n     DFBInputDeviceKeySymbol                 key_symbol;         /* advanced mapping, unicode compatible,\n                                                                    modifier dependent */\n     DFBInputDeviceModifierMask              modifiers;          /* pressed modifiers (optional) */\n     DFBInputDeviceLockState                 locks;              /* active locks (optional) */\n     DFBInputDeviceButtonIdentifier          button;             /* in case of a button event */\n     DFBInputDeviceButtonMask                buttons;            /* mask of currently pressed buttons */\n     DFBInputDeviceAxisIdentifier            axis;               /* in case of an axis event */\n     int                                     axisabs;            /* absolute mouse/joystick coordinate */\n     int                                     axisrel;            /* relative mouse/joystick movement */\n     int                                     min;                /* minimum possible value */\n     int                                     max;                /* maximum possible value */\n     int                                     slot_id;            /* touch contact */\n} DFBInputEvent;\n\n/*\n * Window Event Types.\n *\n * Can also be used as flags for event filters.\n */\ntypedef enum {\n     DWET_NONE                             = 0x00000000,         /* None of these. */\n\n     DWET_POSITION                         = 0x00000001,         /* Window has been moved by window manager or the\n                                                                    application itself. */\n     DWET_SIZE                             = 0x00000002,         /* Window has been resized by window manager or the\n                                                                    application itself. */\n     DWET_CLOSE                            = 0x00000004,         /* Closing this window has been requested only. */\n     DWET_DESTROYED                        = 0x00000008,         /* Window got destroyed by global deinitialization\n                                                                    function or the application itself. */\n     DWET_GOTFOCUS                         = 0x00000010,         /* Window got focus. */\n     DWET_LOSTFOCUS                        = 0x00000020,         /* Window lost focus. */\n\n     DWET_KEYDOWN                          = 0x00000100,         /* A key has gone down while window has focus. */\n     DWET_KEYUP                            = 0x00000200,         /* A key has gone up while window has focus. */\n\n     DWET_BUTTONDOWN                       = 0x00010000,         /* Mouse button went down in the window. */\n     DWET_BUTTONUP                         = 0x00020000,         /* Mouse button went up in the window. */\n     DWET_MOTION                           = 0x00040000,         /* Mouse cursor changed its position in window. */\n     DWET_ENTER                            = 0x00080000,         /* Mouse cursor entered the window. */\n     DWET_LEAVE                            = 0x00100000,         /* Mouse cursor left the window. */\n     DWET_WHEEL                            = 0x00200000,         /* Mouse wheel was moved while window has focus. */\n\n     DWET_POSITION_SIZE                    = DWET_POSITION |\n                                             DWET_SIZE,          /* Initially sent to window when it's created. */\n\n     DWET_UPDATE                           = 0x01000000,         /* Update event (upon Flip), this way another process\n                                                                    can capture the output of the application. */\n\n     DWET_ALL                              = 0x013F033F          /* All event types. */\n} DFBWindowEventType;\n\n/*\n * Flags for a window event.\n */\ntypedef enum {\n     DWEF_NONE                             = 0x00000000,         /* None of these. */\n\n     DWEF_RETURNED                         = 0x00000001,         /* This is a returned event, e.g. unconsumed key. */\n     DWEF_RELATIVE                         = 0x00000002,         /* This is a relative motion event. */\n     DWEF_REPEAT                           = 0x00000010,         /* This is a repeat event, e.g. repeating key */\n     DWEF_DEVICE_ID                        = 0x00000020,         /* device_id field of DFBInputEvent is valid. */\n\n     DWEF_ALL                              = 0x00000033          /* All of these. */\n} DFBWindowEventFlags;\n\n/*\n * Event from the windowing system.\n */\ntypedef struct {\n     DFBEventClass                           clazz;              /* clazz of event */\n     DFBWindowEventType                      type;               /* type of event */\n\n     /* used by DWET_KEYDOWN, DWET_KEYUP */\n     DFBWindowEventFlags                     flags;              /* event flags */\n     DFBWindowID                             window_id;          /* window id */\n\n     /* used by DWET_MOVE, DWET_MOTION, DWET_BUTTONDOWN,\n        DWET_BUTTONUP, DWET_ENTER, DWET_LEAVE */\n     int                                     x;                  /* x position of window or coordinate within window */\n     int                                     y;                  /* y position of window or coordinate within window */\n\n     /* used by DWET_MOTION, DWET_BUTTONDOWN, DWET_BUTTONUP,\n        DWET_ENTER, DWET_LEAVE */\n     int                                     cx;                 /* x cursor position */\n     int                                     cy;                 /* y cursor position */\n\n     /* used by DWET_WHEEL */\n     int                                     step;               /* wheel step */\n\n     /* used by DWET_RESIZE */\n     int                                     w;                  /* width of window */\n     int                                     h;                  /* height of window */\n\n     /* used by DWET_KEYDOWN, DWET_KEYUP */\n     int                                     key_code;           /* hardware keycode, no mapping, -1 if device doesn't\n                                                                    differentiate between several keys */\n     DFBInputDeviceKeyIdentifier             key_id;             /* basic mapping, modifier independent */\n     DFBInputDeviceKeySymbol                 key_symbol;         /* advanced mapping, unicode compatible,\n                                                                    modifier dependent */\n     DFBInputDeviceModifierMask              modifiers;          /* pressed modifiers */\n     DFBInputDeviceLockState                 locks;              /* active locks */\n\n     /* used by DWET_BUTTONDOWN, DWET_BUTTONUP */\n     DFBInputDeviceButtonIdentifier          button;             /* button being pressed or released */\n\n     /* used by DWET_MOTION, DWET_BUTTONDOWN, DWET_BUTTONUP */\n     DFBInputDeviceButtonMask                buttons;            /* mask of currently pressed buttons */\n\n     struct timeval                          timestamp;          /* time stamp */\n     DFBInputDeviceID                        device_id;          /* source of event */\n} DFBWindowEvent;\n\n/*\n * Event for usage by the user.\n */\ntypedef struct {\n     DFBEventClass                           clazz;              /* clazz of event */\n     unsigned int                            type;               /* custom type */\n     void                                   *data;               /* custom data */\n} DFBUserEvent;\n\n/*\n * Universal event for custom usage with variable size.\n */\ntypedef struct {\n     DFBEventClass                           clazz;              /* clazz of event */\n     unsigned int                            size;               /* size of this event, minimum is\n                                                                    sizeof(DFBUniversalEvent) */\n\n     /* custom data follows, size of this data is\n        'size' - sizeof(DFBUniversalEvent) */\n} DFBUniversalEvent;\n\n/*\n * Video Provider Event Types.\n *\n * Can also be used as flags for event filters.\n */\ntypedef enum {\n     DVPET_NONE                            = 0x00000000,         /* None of these. */\n\n     DVPET_STARTED                         = 0x00000001,         /* The video provider has started the playback. */\n     DVPET_STOPPED                         = 0x00000002,         /* The video provider has stopped the playback. */\n     DVPET_SPEEDCHANGE                     = 0x00000004,         /* A speed change has occurred. */\n     DVPET_STREAMCHANGE                    = 0x00000008,         /* A stream description change has occurred. */\n     DVPET_FATALERROR                      = 0x00000010,         /* A fatal error has occurred: restart must be done. */\n     DVPET_FINISHED                        = 0x00000020,         /* The video provider has finished the playback. */\n     DVPET_SURFACECHANGE                   = 0x00000040,         /* A surface description change has occurred. */\n     DVPET_FRAMEDECODED                    = 0x00000080,         /* A frame has been decoded by the decoder. */\n     DVPET_FRAMEDISPLAYED                  = 0x00000100,         /* A frame has been rendered to the output. */\n     DVPET_DATAEXHAUSTED                   = 0x00000200,         /* There is no more data available for consumption. */\n     DVPET_VIDEOACTION                     = 0x00000400,         /* An action is required on the video provider. */\n     DVPET_DATALOW                         = 0x00000800,         /* The stream buffer is running low in data. */\n     DVPET_DATAHIGH                        = 0x00001000,         /* The stream buffer is high. */\n     DVPET_BUFFERTIMELOW                   = 0x00002000,         /* The stream buffer has less than requested playout\n                                                                    time buffered. */\n     DVPET_BUFFERTIMEHIGH                  = 0x00004000,         /* The stream buffer has more than requested playout\n                                                                    time buffered. */\n\n     DVPET_ALL                             = 0x00007FFF          /* All event types. */\n} DFBVideoProviderEventType;\n\n/*\n * Video Provider Event Types.\n *\n * Can also be used as flags for event filters.\n */\ntypedef enum {\n     DVPEDST_UNKNOWN                       = 0x00000000,         /* Event is valid for unknown data. */\n\n     DVPEDST_AUDIO                         = 0x00000001,         /* Event is valid for audio. */\n     DVPEDST_VIDEO                         = 0x00000002,         /* Event is valid for video. */\n     DVPEDST_DATA                          = 0x00000004,         /* Event is valid for data. */\n\n     DVPEDST_ALL                           = 0x00000007          /* Event is valid for all data types. */\n\n} DFBVideoProviderEventDataSubType;\n\n/*\n * Event from the video provider\n */\ntypedef struct {\n     DFBEventClass                           clazz;              /* clazz of event */\n     DFBVideoProviderEventType               type;               /* type of event */\n     DFBVideoProviderEventDataSubType        data_type;          /* data type that this event is applicable for */\n     int                                     data[4];            /* custom data */\n} DFBVideoProviderEvent;\n\n/*\n * Surface Event Types.\n *\n * Can also be used as flags for event filters.\n */\ntypedef enum {\n     DSEVT_NONE                            = 0x00000000,         /* None of these. */\n\n     DSEVT_DESTROYED                       = 0x00000001,         /* Surface got destroyed by global deinitialization\n                                                                    function or the application itself. */\n     DSEVT_UPDATE                          = 0x00000002,         /* Update event. */\n\n     DSEVT_ALL                             = 0x00000003          /* All event types. */\n} DFBSurfaceEventType;\n\n/*\n * Event from surface\n */\ntypedef struct {\n     DFBEventClass                           clazz;              /* clazz of event */\n\n     /* all types */\n     DFBSurfaceEventType                     type;               /* type of event */\n     DFBSurfaceID                            surface_id;         /* source of event */\n     long long                               time_stamp;         /* time stamp */\n\n     /* DSEVT_UPDATE */\n     DFBRegion                               update;             /* region update */\n     DFBRegion                               update_right;       /* right region update */\n     unsigned int                            flip_count;         /* serial number of frame, modulo number of buffers */\n     DFBSurfaceFlipFlags                     flip_flags;         /* flipping flags */\n} DFBSurfaceEvent;\n\n/*\n * General container for events.\n */\ntypedef union {\n     DFBEventClass                           clazz;              /* clazz of event */\n     DFBInputEvent                           input;              /* field for input events */\n     DFBWindowEvent                          window;             /* field for window events */\n     DFBUserEvent                            user;               /* field for user-defined events */\n     DFBUniversalEvent                       universal;          /* field for universal events */\n     DFBVideoProviderEvent                   videoprovider;      /* field for video provider */\n     DFBSurfaceEvent                         surface;            /* field for surface events */\n} DFBEvent;\n\n#define DFB_EVENT(e)                         ((DFBEvent*) (e))\n\n/*\n * Statistics about event buffer queue.\n */\ntypedef struct {\n     unsigned int                            num_events;         /* Total number of events in the queue. */\n\n     unsigned int                            DFEC_INPUT;         /* Number of input events. */\n     unsigned int                            DFEC_WINDOW;        /* Number of window events. */\n     unsigned int                            DFEC_USER;          /* Number of user events. */\n     unsigned int                            DFEC_UNIVERSAL;     /* Number of universal events. */\n     unsigned int                            DFEC_VIDEOPROVIDER; /* Number of video provider events. */\n\n     unsigned int                            DIET_KEYPRESS;\n     unsigned int                            DIET_KEYRELEASE;\n     unsigned int                            DIET_BUTTONPRESS;\n     unsigned int                            DIET_BUTTONRELEASE;\n     unsigned int                            DIET_AXISMOTION;\n\n     unsigned int                            DWET_POSITION;\n     unsigned int                            DWET_SIZE;\n     unsigned int                            DWET_CLOSE;\n     unsigned int                            DWET_DESTROYED;\n     unsigned int                            DWET_GOTFOCUS;\n     unsigned int                            DWET_LOSTFOCUS;\n     unsigned int                            DWET_KEYDOWN;\n     unsigned int                            DWET_KEYUP;\n     unsigned int                            DWET_BUTTONDOWN;\n     unsigned int                            DWET_BUTTONUP;\n     unsigned int                            DWET_MOTION;\n     unsigned int                            DWET_ENTER;\n     unsigned int                            DWET_LEAVE;\n     unsigned int                            DWET_WHEEL;\n     unsigned int                            DWET_POSITION_SIZE;\n\n     unsigned int                            DVPET_STARTED;\n     unsigned int                            DVPET_STOPPED;\n     unsigned int                            DVPET_SPEEDCHANGE;\n     unsigned int                            DVPET_STREAMCHANGE;\n     unsigned int                            DVPET_FATALERROR;\n     unsigned int                            DVPET_FINISHED;\n     unsigned int                            DVPET_SURFACECHANGE;\n     unsigned int                            DVPET_FRAMEDECODED;\n     unsigned int                            DVPET_FRAMEDISPLAYED;\n     unsigned int                            DVPET_DATAEXHAUSTED;\n     unsigned int                            DVPET_DATALOW;\n     unsigned int                            DVPET_VIDEOACTION;\n     unsigned int                            DVPET_DATAHIGH;\n     unsigned int                            DVPET_BUFFERTIMELOW;\n     unsigned int                            DVPET_BUFFERTIMEHIGH;\n} DFBEventBufferStats;\n\n/*\n * IDirectFBEventBuffer is the event buffer interface.\n */\nD_DEFINE_INTERFACE( IDirectFBEventBuffer,\n\n   /** Buffer handling **/\n\n     /*\n      * Clear all events stored in this buffer.\n      */\n     DFBResult (*Reset) (\n          IDirectFBEventBuffer              *thiz\n     );\n\n   /** Waiting for events **/\n\n     /*\n      * Wait for the next event to occur.\n      *\n      * Thread is idle in the meantime.\n      */\n     DFBResult (*WaitForEvent) (\n          IDirectFBEventBuffer              *thiz\n     );\n\n     /*\n      * Block until next event to occur or timeout is reached.\n      *\n      * Thread is idle in the meantime.\n      */\n     DFBResult (*WaitForEventWithTimeout) (\n          IDirectFBEventBuffer              *thiz,\n          unsigned int                       seconds,\n          unsigned int                       milli_seconds\n     );\n\n   /** Fetching events **/\n\n     /*\n      * Get the next event and remove it from the FIFO.\n      */\n     DFBResult (*GetEvent) (\n          IDirectFBEventBuffer              *thiz,\n          DFBEvent                          *ret_event\n     );\n\n     /*\n      * Get the next event but leave it there.\n      */\n     DFBResult (*PeekEvent) (\n          IDirectFBEventBuffer              *thiz,\n          DFBEvent                          *ret_event\n     );\n\n     /*\n      * Check if there is a pending event in the queue.\n      */\n     DFBResult (*HasEvent) (\n          IDirectFBEventBuffer              *thiz\n     );\n\n   /** Sending events **/\n\n     /*\n      * Put an event into the FIFO.\n      *\n      * This function does not wait until the event got fetched.\n      */\n     DFBResult (*PostEvent) (\n          IDirectFBEventBuffer              *thiz,\n          const DFBEvent                    *event\n     );\n\n     /*\n      * Wake up any thread waiting for events in this buffer.\n      *\n      * This method causes any WaitForEvent() or\n      * WaitForEventWithTimeout() call to return with\n      * DFB_INTERRUPTED.\n      */\n     DFBResult (*WakeUp) (\n          IDirectFBEventBuffer              *thiz\n     );\n\n   /** Special handling **/\n\n     /*\n      * Create a file descriptor for reading events.\n      *\n      * This method provides an alternative for reading events\n      * from an event buffer. It creates a file descriptor which\n      * can be used in select(), poll() or read().\n      * In general only non-threaded applications which already\n      * use select() or poll() need it.\n      * This method flushes the event buffer. After calling this\n      * method all other methods except PostEvent() will return\n      * DFB_UNSUPPORTED.\n      * Calling this method again will return DFB_BUSY.\n      */\n     DFBResult (*CreateFileDescriptor) (\n          IDirectFBEventBuffer              *thiz,\n          int                               *ret_fd\n     );\n\n   /** Statistics **/\n\n     /*\n      * Enable/disable collection of event buffer statistics.\n      */\n     DFBResult (*EnableStatistics) (\n          IDirectFBEventBuffer              *thiz,\n          DFBBoolean                         enable\n     );\n\n     /*\n      * Query collected event buffer statistics.\n      */\n     DFBResult (*GetStatistics) (\n          IDirectFBEventBuffer              *thiz,\n          DFBEventBufferStats               *ret_stats\n     );\n)\n\n/*******************\n * IDirectFBWindow *\n *******************/\n\n/*\n * The key selection defines a mode for filtering keys while the\n * window is having the focus.\n */\ntypedef enum {\n     DWKS_ALL                              = 0x00000000,         /* Select all keys (default). */\n     DWKS_NONE                             = 0x00000001,         /* Don't select any key. */\n     DWKS_LIST                             = 0x00000002          /* Select a list of keys. */\n} DFBWindowKeySelection;\n\n/*\n * Window geometry mode.\n */\ntypedef enum {\n     DWGM_DEFAULT                          = 0x00000000,         /* Use default values. */\n     DWGM_FOLLOW                           = 0x00000001,         /* Use values of parent window. */\n     DWGM_RECTANGLE                        = 0x00000002,         /* Use pixel values as defined. */\n     DWGM_LOCATION                         = 0x00000003          /* Use relative values as defined. */\n} DFBWindowGeometryMode;\n\n/*\n * Window geometry for positioning and scaling of windows\n * relative to their own bounds.\n */\ntypedef struct {\n     DFBWindowGeometryMode                   mode;               /* geometry mode */\n     DFBRectangle                            rectangle;          /* rectangle */\n     DFBLocation                             location;           /* location */\n} DFBWindowGeometry;\n\n/*\n * Flags for window cursor.\n */\ntypedef enum {\n     DWCF_NONE                             = 0x00000000,         /* None of these. */\n\n     DWCF_RELATIVE                         = 0x00000001,         /* Receive relative coordinates instead of absolute. */\n     DWCF_EXPLICIT                         = 0x00000002,         /* If window has focus it's also the pointer window. */\n     DWCF_UNCLIPPED                        = 0x00000004,         /* Pointer is not clipped against stack boundaries. */\n     DWCF_TRAPPED                          = 0x00000008,         /* Pointer is clipped against the window boundaries. */\n     DWCF_FIXED                            = 0x00000010,         /* Pointer does not move at all, but still may send\n                                                                    relative motion. */\n     DWCF_INVISIBLE                        = 0x00000020,         /* Window cursor is not visible. */\n\n     DWCF_ALL                              = 0x0000003F          /* All of these. */\n} DFBWindowCursorFlags;\n\n/*\n * These are hints for the window manager that indicate what\n * type of function the window has. The window manager can use\n * this when determining decoration and behaviour of the window.\n * The hint must be set before mapping the window.\n */\ntypedef enum {\n     DWTH_NORMAL                           = 0x00000000,         /* Normal toplevel window. */\n     DWTH_DIALOG                           = 0x00000001,         /* Dialog window. */\n     DWTH_MENU                             = 0x00000002,         /* Window used to implement a menu. */\n     DWTH_TOOLBAR                          = 0x00000003,         /* Window used to implement toolbars. */\n     DWTH_SPLASHSCREEN                     = 0x00000004,         /* Window used to display a splash screen during\n                                                                    application startup. */\n     DWTH_UTLIITY                          = 0x00000005,         /* Utility windows which are not detached toolbars or\n                                                                    dialogs. */\n     DWTH_DOCK                             = 0x00000006,         /* Used for creating dock or panel windows. */\n     DWTH_DESKTOP                          = 0x00000007,         /* Used for creating the desktop background window. */\n     DWTH_DROPDOWN_MENU                    = 0x00000008,         /* A menu that belongs to a menubar. */\n     DWTH_POPUP_MENU                       = 0x00000009,         /* A menu that does not belong to a menubar, e.g. a\n                                                                    context menu. */\n     DWTH_TOOLTIP                          = 0x0000000A,         /* A tooltip. */\n     DWTH_NOTIFICATION                     = 0x0000000B,         /* A notification, typically a bubble that belongs to a\n                                                                    status icon. */\n     DWTH_COMBO                            = 0x0000000C,         /* A popup from a combo box. */\n     DWTH_DND                              = 0x0000000D          /* A window that is used to implement a DND cursor. */\n} DFBWindowTypeHint;\n\n/*\n * Flags for window hint.\n */\ntypedef enum {\n     DWHF_NONE                             = 0x00000000,         /* None of these. */\n\n     DWHF_MODAL                            = 0x00000001,         /* Set modal hint. */\n     DWHF_SKIP_TASKBAR                     = 0x00000002,         /* Set skip taskbar hint. */\n     DWHF_SKIP_PAGER                       = 0x00000004,         /* Set skip pager hint. */\n     DWHF_URGENCY                          = 0x00000008,         /* Set urgency hint. */\n\n     DWHF_ALL                              = 0x0000000F          /* All of these. */\n} DFBWindowHintFlags;\n\n/*\n * Window surface swapping policy.\n */\ntypedef enum {\n     DWSP_SYSTEMONLY                       = 0x00000000,         /* Never try to swap into video memory. */\n     DWSP_VIDEOLOW                         = 0x00000001,         /* Try to store in video memory, low priority. */\n     DWSP_VIDEOHIGH                        = 0x00000002,         /* Try to store in video memory, high priority. */\n     DWSP_VIDEOONLY                        = 0x00000003          /* Always and only store in video memory. */\n} DFBWindowSurfacePolicy;\n\n/*\n * IDirectFBWindow is the window interface.\n */\nD_DEFINE_INTERFACE( IDirectFBWindow,\n\n   /** Retrieving information **/\n\n     /*\n      * Get the unique window ID.\n      */\n     DFBResult (*GetID) (\n          IDirectFBWindow                   *thiz,\n          DFBWindowID                       *ret_window_id\n     );\n\n     /*\n      * Get the current position of this window.\n      */\n     DFBResult (*GetPosition) (\n          IDirectFBWindow                   *thiz,\n          int                               *ret_x,\n          int                               *ret_y\n     );\n\n     /*\n      * Get the size of the window in pixels.\n      */\n     DFBResult (*GetSize) (\n          IDirectFBWindow                   *thiz,\n          int                               *ret_width,\n          int                               *ret_height\n     );\n\n   /** Close & Destroy **/\n\n     /*\n      * Send a close message to the window.\n      *\n      * This function sends a message of type DWET_CLOSE to the\n      * window. It does not actually close window.\n      */\n     DFBResult (*Close) (\n          IDirectFBWindow                   *thiz\n     );\n\n     /*\n      * Destroy the window and sends a destruction message.\n      *\n      * This function sends a message of type DWET_DESTROY to\n      * the window after removing it from the window stack and\n      * freeing its data.\n      */\n     DFBResult (*Destroy) (\n          IDirectFBWindow               *thiz\n     );\n\n   /** Surface & Scaling **/\n\n     /*\n      * Get an interface to the backing store surface.\n      *\n      * This surface has to be flipped to make previous drawing\n      * commands visible, i.e. to repaint the windowstack for\n      * that region.\n      */\n     DFBResult (*GetSurface) (\n          IDirectFBWindow                   *thiz,\n          IDirectFBSurface                 **ret_interface\n     );\n\n     /*\n      * Resize the surface of a scalable window.\n      *\n      * This requires the option DWOP_SCALE.\n      */\n     DFBResult (*ResizeSurface) (\n          IDirectFBWindow                   *thiz,\n          int                                width,\n          int                                height\n     );\n\n   /** Events **/\n\n     /*\n      * Create an event buffer for this window and attach it.\n      */\n     DFBResult (*CreateEventBuffer) (\n          IDirectFBWindow                   *thiz,\n          IDirectFBEventBuffer             **ret_interface\n     );\n\n     /*\n      * Attach an existing event buffer to this window.\n      *\n      * Note: attaching multiple times generates multiple\n      * events.\n      */\n     DFBResult (*AttachEventBuffer) (\n          IDirectFBWindow                   *thiz,\n          IDirectFBEventBuffer              *buffer\n     );\n\n     /*\n      * Detach an event buffer from this window.\n      */\n     DFBResult (*DetachEventBuffer) (\n          IDirectFBWindow                   *thiz,\n          IDirectFBEventBuffer              *buffer\n     );\n\n     /*\n      * Enable specific events to be sent to the window.\n      *\n      * The argument is a mask of events that will be set in the\n      * window's event mask.\n      * The default event mask is DWET_ALL.\n      */\n     DFBResult (*EnableEvents) (\n          IDirectFBWindow                   *thiz,\n          DFBWindowEventType                 mask\n     );\n\n     /*\n      * Disable specific events from being sent to the window.\n      *\n      * The argument is a mask of events that will be cleared in\n      * the window's event mask.\n      * The default event mask is DWET_ALL.\n      */\n     DFBResult (*DisableEvents) (\n          IDirectFBWindow                   *thiz,\n          DFBWindowEventType                 mask\n     );\n\n   /** Options **/\n\n     /*\n      * Set options controlling appearance and behaviour of the\n      * window.\n      */\n     DFBResult (*SetOptions) (\n          IDirectFBWindow                   *thiz,\n          DFBWindowOptions                   options\n     );\n\n     /*\n      * Get options controlling appearance and behaviour of the\n      * window.\n      */\n     DFBResult (*GetOptions) (\n          IDirectFBWindow                   *thiz,\n          DFBWindowOptions                  *ret_options\n     );\n\n     /*\n      * Set the window color, or colorises the window.\n      *\n      * In case you specified DWCAPS_COLOR, this sets the window\n      * draw color. In case you didn't, it colorises the window\n      * with this color; this will darken the window.\n      */\n     DFBResult (*SetColor) (\n          IDirectFBWindow                   *thiz,\n          u8                                 r,\n          u8                                 g,\n          u8                                 b,\n          u8                                 a\n     );\n\n     /*\n      * Set the window color key.\n      *\n      * If a pixel of the window matches this color the\n      * underlying window or the background is visible at this\n      * point.\n      */\n     DFBResult (*SetColorKey) (\n          IDirectFBWindow                   *thiz,\n          u8                                 r,\n          u8                                 g,\n          u8                                 b\n     );\n\n     /*\n      * Set the window color key (indexed).\n      *\n      * If a pixel (indexed format) of the window matches this\n      * color index the underlying window or the background is\n      * visible at this point.\n      */\n     DFBResult (*SetColorKeyIndex) (\n          IDirectFBWindow                   *thiz,\n          unsigned int                       index\n     );\n\n     /*\n      * Set the window's global opacity factor.\n      *\n      * Set it to 0 to hide a window. Setting it to 0xff makes\n      * the window opaque if it has no alpha channel.\n      */\n     DFBResult (*SetOpacity) (\n          IDirectFBWindow                   *thiz,\n          u8                                 opacity\n     );\n\n     /*\n      * Disable alpha channel blending for one region of the\n      * window.\n      *\n      * If DWOP_ALPHACHANNEL and DWOP_OPAQUE_REGION are set but\n      * not DWOP_COLORKEYING and the opacity of the window is\n      * 0xff, the window gets rendered without alpha blending\n      * within the specified region. This is extremely useful\n      * for alpha blended window decorations while the main\n      * content stays opaque and gets rendered faster.\n      */\n     DFBResult (*SetOpaqueRegion) (\n          IDirectFBWindow                   *thiz,\n          int                                x1,\n          int                                y1,\n          int                                x2,\n          int                                y2\n     );\n\n     /*\n      * Get the current opacity factor of this window.\n      */\n     DFBResult (*GetOpacity) (\n          IDirectFBWindow                   *thiz,\n          u8                                *ret_opacity\n     );\n\n     /*\n      * Bind a cursor shape to this window.\n      *\n      * This method will set a per-window cursor shape.\n      * Everytime the cursor enters this window, the specified\n      * shape is set. Passing NULL will unbind a set shape and\n      * release its surface.\n      */\n     DFBResult (*SetCursorShape) (\n          IDirectFBWindow                   *thiz,\n          IDirectFBSurface                  *shape,\n          int                                hot_x,\n          int                                hot_y\n     );\n\n   /** Position and Size **/\n\n     /*\n      * Move the window by the specified distance.\n      */\n     DFBResult (*Move) (\n          IDirectFBWindow                   *thiz,\n          int                                dx,\n          int                                dy\n     );\n\n     /*\n      * Move the window to the specified coordinates.\n      */\n     DFBResult (*MoveTo) (\n          IDirectFBWindow                   *thiz,\n          int                                x,\n          int                                y\n     );\n\n     /*\n      * Resize the window.\n      */\n     DFBResult (*Resize) (\n          IDirectFBWindow                   *thiz,\n          int                                width,\n          int                                height\n     );\n\n     /*\n      * Set position and size in one step.\n      */\n     DFBResult (*SetBounds) (\n          IDirectFBWindow                   *thiz,\n          int                                x,\n          int                                y,\n          int                                width,\n          int                                height\n     );\n\n   /** Stacking **/\n\n     /*\n      * Put the window into a specific stacking class.\n      */\n     DFBResult (*SetStackingClass) (\n          IDirectFBWindow                   *thiz,\n          DFBWindowStackingClass             stacking_class\n     );\n\n     /*\n      * Raise the window by one within the window stack.\n      */\n     DFBResult (*Raise) (\n          IDirectFBWindow                   *thiz\n     );\n\n     /*\n      * Lower the window by one within the window stack.\n      */\n     DFBResult (*Lower) (\n          IDirectFBWindow                   *thiz\n     );\n\n     /*\n      * Put the window on the top of the window stack.\n      */\n     DFBResult (*RaiseToTop) (\n          IDirectFBWindow                   *thiz\n     );\n\n     /*\n      * Send a window to the bottom of the window stack.\n      */\n     DFBResult (*LowerToBottom) (\n          IDirectFBWindow                   *thiz\n     );\n\n     /*\n      * Put a window on top of another window.\n      */\n     DFBResult (*PutAtop) (\n          IDirectFBWindow                   *thiz,\n          IDirectFBWindow                   *lower\n     );\n\n     /*\n      * Put a window below another window.\n      */\n     DFBResult (*PutBelow) (\n          IDirectFBWindow                   *thiz,\n          IDirectFBWindow                   *upper\n     );\n\n   /** Binding **/\n\n     /*\n      * Bind a window at the specified position of this window.\n      *\n      * After binding, bound window will be automatically moved\n      * when this window moves to a new position. Binding the\n      * same window to multiple windows is not supported.\n      * Subsequent call to Bind() automatically unbounds the\n      * bound window before binding it again.\n      * To move the bound window to a new position call Bind()\n      * again with the new coordinates.\n      */\n     DFBResult (*Bind) (\n          IDirectFBWindow                   *thiz,\n          IDirectFBWindow                   *window,\n          int                                x,\n          int                                y\n     );\n\n     /*\n      * Unbind a window from this window.\n      */\n     DFBResult (*Unbind) (\n          IDirectFBWindow                   *thiz,\n          IDirectFBWindow                   *window\n     );\n\n   /** Focus handling **/\n\n     /*\n      * Pass the focus to this window.\n      */\n     DFBResult (*RequestFocus) (\n          IDirectFBWindow                   *thiz\n     );\n\n     /*\n      * Grab the keyboard, i.e. all following keyboard events\n      * are sent to this window ignoring the focus.\n      */\n     DFBResult (*GrabKeyboard) (\n          IDirectFBWindow                   *thiz\n     );\n\n     /*\n      * Ungrab the keyboard, i.e. switch to standard key event\n      * dispatching.\n      */\n     DFBResult (*UngrabKeyboard) (\n          IDirectFBWindow                   *thiz\n     );\n\n     /*\n      * Grab the pointer, i.e. all following mouse events are\n      * sent to this window ignoring the focus.\n      */\n     DFBResult (*GrabPointer) (\n          IDirectFBWindow                   *thiz\n     );\n\n     /*\n      * Ungrab the pointer, i.e. switch to standard mouse event\n      * dispatching.\n      */\n     DFBResult (*UngrabPointer) (\n          IDirectFBWindow                   *thiz\n     );\n\n     /*\n      * Grab a specific key, i.e. all following events of this\n      * key are sent to this window ignoring the focus.\n      */\n     DFBResult (*GrabKey) (\n          IDirectFBWindow                   *thiz,\n          DFBInputDeviceKeySymbol            symbol,\n          DFBInputDeviceModifierMask         modifiers\n     );\n\n     /*\n      * Ungrab a specific key, i.e. switch to standard key event\n      * dispatching.\n      */\n     DFBResult (*UngrabKey) (\n          IDirectFBWindow                   *thiz,\n          DFBInputDeviceKeySymbol            symbol,\n          DFBInputDeviceModifierMask         modifiers\n     );\n\n   /** Key selection **/\n\n     /*\n      * Selects a mode for filtering keys while being focused.\n      *\n      * The 'selection' defines whether all, none or a specific\n      * set of keys is selected. In case of a specific set, the\n      * 'keys' array with 'num_keys' has to be provided.\n      */\n     DFBResult (*SetKeySelection) (\n          IDirectFBWindow                   *thiz,\n          DFBWindowKeySelection              selection,\n          const DFBInputDeviceKeySymbol     *keys,\n          unsigned int                       num_keys\n     );\n\n     /*\n      * Grab all unselected (filtered out) keys.\n      *\n      * Unselected keys are those not selected by the focused\n      * window. These keys won't be sent to that window. Instead\n      * one window in the stack can collect them.\n      */\n     DFBResult (*GrabUnselectedKeys) (\n          IDirectFBWindow                   *thiz\n     );\n\n     /*\n      * Release the grab of unselected (filtered out) keys.\n      */\n     DFBResult (*UngrabUnselectedKeys) (\n          IDirectFBWindow                   *thiz\n     );\n\n   /** Advanced Geometry **/\n\n     /*\n      * Set area of surface to be shown in window.\n      */\n     DFBResult (*SetSrcGeometry) (\n          IDirectFBWindow                   *thiz,\n          const DFBWindowGeometry           *geometry\n     );\n\n     /*\n      * Set destination location of window within its bounds.\n      */\n     DFBResult (*SetDstGeometry) (\n          IDirectFBWindow                   *thiz,\n          const DFBWindowGeometry           *geometry\n     );\n\n     /*\n      * Get stereo depth.\n      */\n     DFBResult (*GetStereoDepth) (\n         IDirectFBWindow                    *thiz,\n         int                                *ret_z\n     );\n\n     /*\n      * Set stereo depth.\n      *\n      * The depth value specified will cause the left eye buffer\n      * content to be shifted on the x-axis by +z and the right\n      * eye buffer to be shifted by -z value. A positive z value\n      * will cause the layer to appear closer than the TV plane\n      * while a negative z value will make the layer appear\n      * farther away. The depth is limited to a value between\n      * +DLSO_FIXED_LIMIT and -DLSO_FIXED_LIMIT.\n      */\n     DFBResult (*SetStereoDepth) (\n         IDirectFBWindow                    *thiz,\n         int                                 z\n     );\n\n   /** Properties **/\n\n     /*\n      * Set property controlling appearance and behaviour of the\n      * window.\n      */\n     DFBResult (*SetProperty) (\n          IDirectFBWindow                   *thiz,\n          const char                        *key,\n          void                              *value,\n          void                             **ret_old_value\n     );\n\n     /*\n      * Get property controlling appearance and behaviour of the\n      * window.\n      */\n     DFBResult (*GetProperty) (\n          IDirectFBWindow                   *thiz,\n          const char                        *key,\n          void                             **ret_value\n     );\n\n     /*\n      * Remove property controlling appearance and behaviour of\n      * the window.\n      */\n     DFBResult (*RemoveProperty) (\n          IDirectFBWindow                   *thiz,\n          const char                        *key,\n          void                             **ret_value\n     );\n\n     /*\n      * Set window rotation.\n      */\n     DFBResult (*SetRotation) (\n          IDirectFBWindow                   *thiz,\n          int                                rotation\n     );\n\n   /** Association **/\n\n     /*\n      * Change the window association.\n      *\n      * If 'window_id' is 0, the window will be dissociated.\n      */\n     DFBResult (*SetAssociation) (\n          IDirectFBWindow                   *thiz,\n          DFBWindowID                        window_id\n     );\n\n   /** Application ID **/\n\n     /*\n      * Set application ID.\n      *\n      * The usage of the application ID is not imposed and can\n      * be used at will by the application. Any change will be\n      * notified, and as such, an application manager can be\n      * used to act on any change.\n      */\n     DFBResult (*SetApplicationID) (\n          IDirectFBWindow                   *thiz,\n          unsigned long                      application_id\n     );\n\n     /*\n      * Get current application ID.\n      */\n     DFBResult (*GetApplicationID) (\n          IDirectFBWindow                   *thiz,\n          unsigned long                     *ret_application_id\n     );\n\n   /** Updates **/\n\n     /*\n      * Signal start of window content updates.\n      */\n     DFBResult (*BeginUpdates) (\n          IDirectFBWindow                   *thiz,\n          const DFBRegion                   *update\n     );\n\n   /** Events **/\n\n     /*\n      * Send event.\n      */\n     DFBResult (*SendEvent) (\n          IDirectFBWindow                   *thiz,\n          const DFBWindowEvent              *event\n     );\n\n   /** Cursor **/\n\n     /*\n      * Set cursor flags (active when in focus).\n      */\n     DFBResult (*SetCursorFlags) (\n          IDirectFBWindow                   *thiz,\n          DFBWindowCursorFlags               flags\n     );\n\n     /*\n      * Set cursor resolution.\n      *\n      * The default cursor resolution is the surface dimensions.\n      */\n     DFBResult (*SetCursorResolution) (\n          IDirectFBWindow                   *thiz,\n          const DFBDimension                *resolution\n     );\n\n     /*\n      * Set cursor position within window coordinates.\n      */\n     DFBResult (*SetCursorPosition) (\n          IDirectFBWindow                   *thiz,\n          int                                x,\n          int                                y\n     );\n\n   /** Geometry **/\n\n     /*\n      * Set area of surface to be shown in window.\n      * Set destination location of window within its bounds.\n      */\n     DFBResult (*SetGeometry) (\n          IDirectFBWindow                   *thiz,\n          const DFBWindowGeometry           *src,\n          const DFBWindowGeometry           *dst\n     );\n\n   /** Extended **/\n\n     /*\n      * Set the window type hint.\n      */\n     DFBResult (*SetTypeHint) (\n          IDirectFBWindow                   *thiz,\n          DFBWindowTypeHint                  type_hint\n     );\n\n     /*\n      * Change window hint flags.\n      */\n     DFBResult (*ChangeHintFlags) (\n          IDirectFBWindow                   *thiz,\n          DFBWindowHintFlags                 clear,\n          DFBWindowHintFlags                 set\n     );\n\n   /** Policy **/\n\n     /*\n      * Get the window surface swapping policy.\n      */\n     DFBResult (*GetPolicy) (\n          IDirectFBWindow                   *thiz,\n          DFBWindowSurfacePolicy            *ret_policy\n     );\n)\n\n/*****************\n * IDirectFBFont *\n *****************/\n\n/*\n * Called for each provided text encoding.\n */\ntypedef DFBEnumerationResult (*DFBTextEncodingCallback) (\n     DFBTextEncodingID                       encoding_id,\n     const char                             *name,\n     void                                   *callbackdata\n);\n\n/*\n * IDirectFBFont is the font interface.\n */\nD_DEFINE_INTERFACE( IDirectFBFont,\n\n   /** Retrieving information **/\n\n     /*\n      * Get the distance from the baseline to the top of the\n      * logical extents of this font.\n      */\n     DFBResult (*GetAscender) (\n          IDirectFBFont                     *thiz,\n          int                               *ret_ascender\n     );\n\n     /*\n      * Get the distance from the baseline to the bottom of the\n      * logical extents of this font.\n      */\n     DFBResult (*GetDescender) (\n          IDirectFBFont                     *thiz,\n          int                               *ret_descender\n     );\n\n     /*\n      * Get the logical height of this font.\n      *\n      * This is the distance from one baseline to the next when\n      * writing several lines of text. Note that this value does\n      * not correspond the height value specified when loading\n      * the font.\n      */\n     DFBResult (*GetHeight) (\n          IDirectFBFont                     *thiz,\n          int                               *ret_height\n     );\n\n     /*\n      * Get the maximum character width.\n      *\n      * Not all fonts specify it correcly.\n      */\n     DFBResult (*GetMaxAdvance) (\n          IDirectFBFont                     *thiz,\n          int                               *ret_maxadvance\n     );\n\n     /*\n      * Get the kerning to apply between two glyphs specified by\n      * their character codes.\n      */\n     DFBResult (*GetKerning) (\n          IDirectFBFont                     *thiz,\n          unsigned int                       prev,\n          unsigned int                       current,\n          int                               *ret_kern_x,\n          int                               *ret_kern_y\n     );\n\n   /** Measurements **/\n\n     /*\n      * Get the logical width of the specified string as if it\n      * were drawn with this font.\n      *\n      * 'bytes' specifies the number of bytes to take from the\n      * string or -1 for the complete NULL-terminated string.\n      * The returned width may be different than the actual\n      * drawn width of the 'text' since this function returns\n      * the logical width that should be used to layout 'text'.\n      * A negative width indicates right-to-left rendering.\n      */\n     DFBResult (*GetStringWidth) (\n          IDirectFBFont                     *thiz,\n          const char                        *text,\n          int                                bytes,\n          int                               *ret_width\n     );\n\n     /*\n      * Get the logical and real extents of the specified string\n      * as if it were drawn with this font.\n      *\n      * 'bytes' specifies the number of bytes to take from the\n      * string or -1 for the complete NULL-terminated string.\n      * The logical rectangle describes the typographic extents\n      * and should be used to layout 'text'. The ink rectangle\n      * describes the smallest rectangle containing all pixels\n      * that are touched when drawing the string. If you only\n      * need one of the rectangles, pass NULL for the other one.\n      * The ink rectangle is guaranteed to be a valid rectangle\n      * with positive width and height, while the logical\n      * rectangle may have negative width indicating\n      * right-to-left layout.\n      * The rectangle offsets are reported relative to the\n      * baseline and refer to the text being drawn using\n      * DSTF_LEFT.\n      */\n     DFBResult (*GetStringExtents) (\n          IDirectFBFont                     *thiz,\n          const char                        *text,\n          int                                bytes,\n          DFBRectangle                      *ret_logical_rect,\n          DFBRectangle                      *ret_ink_rect\n     );\n\n     /*\n      * Get the extents of a glyph specified by its character\n      * code.\n      *\n      * The rectangle describes the smallest rectangle\n      * containing all pixels that are touched when drawing the\n      * glyph. It is reported relative to the baseline. If you\n      * only need the advance, pass NULL for the rectangle.\n      * The advance describes the horizontal offset to the next\n      * glyph (without kerning applied). It may be a negative\n      * value indicating left-to-right rendering. If you don't\n      * need this value, pass NULL for advance.\n      */\n     DFBResult (*GetGlyphExtents) (\n          IDirectFBFont                     *thiz,\n          unsigned int                       character,\n          DFBRectangle                      *ret_rect,\n          int                               *ret_advance\n     );\n\n     /*\n      * Get the next explicit or automatic break within a string\n      * along with the logical width of the text, the string\n      * length, and a pointer to the next text line.\n      *\n      * The 'bytes' specifies the maximum number of bytes to\n      * take from the string or -1 for complete NULL-terminated\n      * string.\n      * The 'max_width' specifies logical width of column onto\n      * which the 'text' will be drawn. Then the logical width\n      * of fitted text is returned in 'ret_width'. The returned\n      * width may overlap the max width specified if there's\n      * only one character that fits.\n      * The number of characters that fit into this column is\n      * returned by the 'ret_str_length'. Note that you can not\n      * use this value as the number of bytes to take when using\n      * DrawString() as it represents the number of characters,\n      * not the number of bytes.\n      * In 'ret_next_line' a pointer to the next line of text is\n      * returned. This will point to NULL or the end of the\n      * string if there's no more break.\n      */\n     DFBResult (*GetStringBreak) (\n          IDirectFBFont                     *thiz,\n          const char                        *text,\n          int                                bytes,\n          int                                max_width,\n          int                               *ret_width,\n          int                               *ret_str_length,\n          const char                       **ret_next_line\n     );\n\n   /** Encodings **/\n\n     /*\n      * Change the default encoding used when the font is set\n      * at a surface.\n      */\n     DFBResult (*SetEncoding) (\n          IDirectFBFont                     *thiz,\n          DFBTextEncodingID                  encoding\n     );\n\n     /*\n      * Enumerate all provided text encodings.\n      */\n     DFBResult (*EnumEncodings) (\n          IDirectFBFont                     *thiz,\n          DFBTextEncodingCallback            callback,\n          void                              *callbackdata\n     );\n\n     /*\n      * Find an encoding by its name.\n      */\n     DFBResult (*FindEncoding) (\n          IDirectFBFont                     *thiz,\n          const char                        *name,\n          DFBTextEncodingID                 *ret_encoding\n     );\n\n   /** Resources **/\n\n     /*\n      * Dispose resources used by the font.\n      *\n      * Keeps font usable, recreating resources as needed.\n      */\n     DFBResult (*Dispose) (\n          IDirectFBFont                     *thiz\n     );\n\n   /** Measurements **/\n\n     /*\n      * Get the line spacing vector of this font.\n      *\n      * This is the displacement vector from one line to the\n      * next when writing several lines of text. It differs\n      * from the height only when the font is rotated.\n      */\n     DFBResult (*GetLineSpacingVector) (\n          IDirectFBFont                     *thiz,\n          int                               *ret_xspacing,\n          int                               *ret_yspacing\n     );\n\n     /*\n      * Get the extents of a glyph specified by its character\n      * code (extended version).\n      *\n      * The rectangle describes the smallest rectangle\n      * containing all pixels that are touched when drawing the\n      * glyph. It is reported relative to the baseline. If you\n      * only need the advance, pass NULL for the rectangle.\n      * The advance describes the horizontal offset to the next\n      * glyph (without kerning applied). It may be a negative\n      * value indicating left-to-right rendering. If you don't\n      * need this value, pass NULL for advance.\n      */\n     DFBResult (*GetGlyphExtentsXY) (\n          IDirectFBFont                     *thiz,\n          unsigned int                       character,\n          DFBRectangle                      *ret_rect,\n          int                               *ret_xadvance,\n          int                               *ret_yadvance\n     );\n\n     /*\n      * Get the position and thickness of the underline.\n      */\n     DFBResult (*GetUnderline) (\n          IDirectFBFont                     *thiz,\n          int                               *ret_underline_position,\n          int                               *ret_underline_thichness\n     );\n\n   /** Retrieving information **/\n\n     /*\n      * Get the description of the font.\n      */\n     DFBResult (*GetDescription) (\n          IDirectFBFont                     *thiz,\n          DFBFontDescription                *ret_desc\n     );\n)\n\n/**************************\n * IDirectFBImageProvider *\n **************************/\n\n/*\n * Capabilities of an image.\n */\ntypedef enum {\n     DICAPS_NONE                           = 0x00000000,         /* None of these. */\n\n     DICAPS_ALPHACHANNEL                   = 0x00000001,         /* The image data contains an alphachannel. */\n     DICAPS_COLORKEY                       = 0x00000002          /* The image has a colorkey */\n} DFBImageCapabilities;\n\n/*\n * Information about an image.\n */\ntypedef struct {\n     DFBImageCapabilities                    caps;               /* capabilities */\n     u8                                      colorkey_r;         /* colorkey red channel */\n     u8                                      colorkey_g;         /* colorkey green channel */\n     u8                                      colorkey_b;         /* colorkey blue channel */\n} DFBImageDescription;\n\n/*\n * Flags used by an image provider.\n */\ntypedef enum {\n     DIRENDER_NONE                         = 0x00000000,         /* None of these. */\n\n     DIRENDER_FAST                         = 0x00000001,         /* Select fast rendering method. */\n\n     DIRENDER_ALL                          = 0x00000001          /* All of these. */\n} DIRenderFlags;\n\n/*\n * Return value of progressive image loading callback.\n */\ntypedef enum {\n     DIRCR_OK                              = 0x00000000,         /* No error occurred. */\n     DIRCR_ABORT                           = 0x00000001          /* Abort error */\n} DIRenderCallbackResult;\n\n/*\n * Called whenever a chunk of the image is decoded.\n */\ntypedef DIRenderCallbackResult (*DIRenderCallback) (\n     DFBRectangle                           *rect,\n     void                                   *ctx\n);\n\n/*\n * IDirectFBImageProvider is the image provider interface.\n */\nD_DEFINE_INTERFACE( IDirectFBImageProvider,\n\n   /** Retrieving information **/\n\n     /*\n      * Get a surface description that best matches the image\n      * contained in the file.\n      *\n      * For opaque image formats the pixel format of the primary\n      * layer is used. For images with alpha channel an ARGB\n      * surface description is returned.\n      */\n     DFBResult (*GetSurfaceDescription) (\n          IDirectFBImageProvider            *thiz,\n          DFBSurfaceDescription             *ret_desc\n     );\n\n     /*\n      * Get a description of the image.\n      *\n      * This includes stuff that does not belong into the\n      * surface description, e.g. a colorkey.\n      */\n     DFBResult (*GetImageDescription) (\n          IDirectFBImageProvider            *thiz,\n          DFBImageDescription               *ret_desc\n     );\n\n   /** Rendering **/\n\n     /*\n      * Render the file contents into the destination contents\n      * doing automatic scaling and color format conversion.\n      *\n      * If the image file has an alpha channel, it is rendered\n      * with alpha channel if the destination surface is of the\n      * ARGB pixelformat. Otherwise, transparent areas are\n      * blended over a black background.\n      * If a destination rectangle is specified, the rectangle\n      * is clipped to the destination surface. If NULL is passed\n      * as destination rectangle, the whole destination surface\n      * is taken. The image is stretched to fill the rectangle.\n      */\n     DFBResult (*RenderTo) (\n          IDirectFBImageProvider            *thiz,\n          IDirectFBSurface                  *destination,\n          const DFBRectangle                *dest_rect\n     );\n\n     /*\n      * Register a callback for progressive image loading.\n      *\n      * The function is called each time a chunk of the image is\n      * decoded.\n      */\n     DFBResult (*SetRenderCallback) (\n          IDirectFBImageProvider            *thiz,\n          DIRenderCallback                   callback,\n          void                              *ctx\n     );\n\n     /*\n      * Set hint for preferred image decoding method.\n      */\n     DFBResult (*SetRenderFlags) (\n          IDirectFBImageProvider            *thiz,\n          DIRenderFlags                      flags\n     );\n)\n\n/**************************\n * IDirectFBVideoProvider *\n **************************/\n\n/*\n * The video provider capabilities.\n */\ntypedef enum {\n     DVCAPS_BASIC                          = 0x00000000,         /* basic ops (play, stop) */\n     DVCAPS_SEEK                           = 0x00000001,         /* supports seek to a position */\n     DVCAPS_SCALE                          = 0x00000002,         /* can scale the video */\n     DVCAPS_INTERLACED                     = 0x00000004,         /* supports interlaced surfaces */\n     DVCAPS_SPEED                          = 0x00000008,         /* supports changing playback speed */\n     DVCAPS_BRIGHTNESS                     = 0x00000010,         /* supports brightness adjustment */\n     DVCAPS_CONTRAST                       = 0x00000020,         /* supports contrast adjustment */\n     DVCAPS_HUE                            = 0x00000040,         /* supports hue adjustment */\n     DVCAPS_SATURATION                     = 0x00000080,         /* supports saturation adjustment */\n     DVCAPS_INTERACTIVE                    = 0x00000100,         /* supports sending an input or window event */\n     DVCAPS_VOLUME                         = 0x00000200          /* supports volume adjustment */\n} DFBVideoProviderCapabilities;\n\n/*\n * Capabilities of an audio/video stream.\n */\ntypedef enum {\n     DVSCAPS_NONE                          = 0x00000000,         /* None of these. */\n\n     DVSCAPS_VIDEO                         = 0x00000001,         /* Stream contains video. */\n     DVSCAPS_AUDIO                         = 0x00000002          /* Stream contains audio. */\n} DFBStreamCapabilities;\n\n#define DFB_STREAM_DESC_ENCODING_LENGTH       30\n#define DFB_STREAM_DESC_TITLE_LENGTH         255\n#define DFB_STREAM_DESC_AUTHOR_LENGTH        255\n#define DFB_STREAM_DESC_ALBUM_LENGTH         255\n#define DFB_STREAM_DESC_GENRE_LENGTH          32\n#define DFB_STREAM_DESC_COMMENT_LENGTH       255\n\n/*\n * Information about an audio/video stream.\n */\ntypedef struct {\n     DFBStreamCapabilities                   caps;               /* capabilities */\n\n     struct {\n          char encoding[DFB_STREAM_DESC_ENCODING_LENGTH];        /* encoding (e.g. \"h264\") */\n\n          double                             framerate;          /* number of frames per second */\n          double                             aspect;             /* frame aspect ratio */\n          int                                bitrate;            /* amount of bits per second */\n          int                                afd;                /* active format descriptor */\n          int                                width;              /* width as reported by sequence header */\n          int                                height;             /* height as reported by sequence header */\n     } video;                                                    /* struct containing encoding properties for video */\n\n     struct {\n          char encoding[DFB_STREAM_DESC_ENCODING_LENGTH];        /* encoding (e.g. \"aac\") */\n\n          int                                samplerate;         /* number of samples per second */\n          int                                channels;           /* number of channels per sample */\n          int                                bitrate;            /* amount of bits per second */\n     } audio;                                                    /* struct containing encoding properties for audio */\n\n     char title[DFB_STREAM_DESC_TITLE_LENGTH];                   /* title */\n     char author[DFB_STREAM_DESC_AUTHOR_LENGTH];                 /* author */\n     char album[DFB_STREAM_DESC_ALBUM_LENGTH];                   /* album */\n\n     short                                   year;               /* year */\n\n     char genre[DFB_STREAM_DESC_GENRE_LENGTH];                   /* genre */\n     char comment[DFB_STREAM_DESC_COMMENT_LENGTH];               /* comment */\n} DFBStreamDescription;\n\n/*\n * Status of a video provider.\n */\ntypedef enum {\n     DVSTATE_UNKNOWN                       = 0x00000000,         /* unknown status */\n\n     DVSTATE_PLAY                          = 0x00000001,         /* playing */\n     DVSTATE_STOP                          = 0x00000002,         /* playback was stopped */\n     DVSTATE_FINISHED                      = 0x00000003,         /* playback is finished */\n     DVSTATE_BUFFERING                     = 0x00000004          /* buffering, playback is running */\n} DFBVideoProviderStatus;\n\n/*\n * Flags controlling playback mode of a video provider.\n */\ntypedef enum {\n     DVPLAY_NOFX                           = 0x00000000,         /* normal playback */\n     DVPLAY_REWIND                         = 0x00000001,         /* reverse playback */\n     DVPLAY_LOOPING                        = 0x00000002          /* automatically restart playback when end-of-stream is\n                                                                    reached */\n} DFBVideoProviderPlaybackFlags;\n\n/*\n * Buffer levels and occupancy for audio/video input buffers.\n */\ntypedef struct {\n     DFBStreamCapabilities                   valid;              /* Validation of audio/video. */\n\n     struct {\n         unsigned int                        buffer_size;        /* Size in bytes of the input buffer to video\n                                                                    decoder. */\n         unsigned int                        minimum_level;      /* The level at which a DVPET_DATALOW event will be\n                                                                    generated. */\n         unsigned int                        maximum_level;      /* The level at which a DVPET_DATAHIGH event will be\n                                                                    generated. */\n         unsigned int                        current_level;      /* Current fill level of video input buffer. */\n     } video;                                                    /* Video buffer occupancy. */\n     struct {\n         unsigned int                        buffer_size;        /* Size in bytes of the input buffer to audio\n                                                                    decoder. */\n         unsigned int                        minimum_level;      /* The level at which a DVPET_DATALOW event will be\n                                                                    generated. */\n         unsigned int                        maximum_level;      /* The level at which a DVPET_DATAHIGH event will be\n                                                                    generated. */\n         unsigned int                        current_level;      /* Current fill level of audio input buffer.*/\n     } audio;                                                    /* Audio buffer occupancy. */\n} DFBBufferOccupancy;\n\n/*\n * Buffer thresholds for audio/video.\n */\ntypedef struct {\n     DFBStreamCapabilities                   selection;          /* Validation of audio/video. */\n\n     struct {\n          unsigned int                       minimum_level;      /* The level at which a DVPET_DATALOW event will be\n                                                                    generated. */\n          unsigned int                       maximum_level;      /* The level at which a DVPET_DATAHIGH event will be\n                                                                    generated. */\n          unsigned int                       minimum_time;       /* The buffering time at which a DVPET_BUFFERTIMELOW\n                                                                    event will be generated. */\n          unsigned int                       maximum_time;       /* The buffering time at which a DVPET_BUFFERTIMEHIGH\n                                                                    event will be generated. */\n     } video;                                                    /* Video buffer thresholds. */\n     struct {\n          unsigned int                       minimum_level;      /* The level at which a DVPET_DATALOW event will be\n                                                                    generated. */\n          unsigned int                       maximum_level;      /* The level at which a DVPET_DATAHIGH event will be\n                                                                    generated. */\n          unsigned int                       minimum_time;       /* The buffering time at which a DVPET_BUFFERTIMELOW\n                                                                    event will be generated. */\n          unsigned int                       maximum_time;       /* The buffering time at which a DVPET_BUFFERTIMEHIGH\n                                                                    event will be generated. */\n     } audio;                                                    /* Audio buffer thresholds. */\n} DFBBufferThresholds;\n\n/*\n * Called for each written frame.\n */\ntypedef void (*DVFrameCallback) (\n     void                                   *ctx\n);\n\n/*\n * IDirectFBVideoProvider is the video provider interface.\n */\nD_DEFINE_INTERFACE( IDirectFBVideoProvider,\n\n   /** Retrieving information **/\n\n     /*\n      * Retrieve information about the video provider's\n      * capabilities.\n      */\n     DFBResult (*GetCapabilities) (\n          IDirectFBVideoProvider            *thiz,\n          DFBVideoProviderCapabilities      *ret_caps\n     );\n\n     /*\n      * Get a surface description that best matches the video\n      * contained in the file.\n      */\n     DFBResult (*GetSurfaceDescription) (\n          IDirectFBVideoProvider            *thiz,\n          DFBSurfaceDescription             *ret_desc\n     );\n\n     /*\n      * Get a description of the video stream.\n      */\n     DFBResult (*GetStreamDescription) (\n          IDirectFBVideoProvider            *thiz,\n          DFBStreamDescription              *ret_desc\n     );\n\n   /** Playback **/\n\n     /*\n      * Play the video rendering it into the specified rectangle\n      * of the destination surface.\n      *\n      * Optionally a callback can be registered that is called\n      * for each rendered frame. This is especially important if\n      * you are playing to a flipping surface. In this case, you\n      * should flip the destination surface in your callback.\n      */\n     DFBResult (*PlayTo) (\n          IDirectFBVideoProvider            *thiz,\n          IDirectFBSurface                  *destination,\n          const DFBRectangle                *dest_rect,\n          DVFrameCallback                    callback,\n          void                              *ctx\n     );\n\n     /*\n      * Stop rendering into the destination surface.\n      */\n     DFBResult (*Stop) (\n          IDirectFBVideoProvider            *thiz\n     );\n\n     /*\n      * Get the status of the playback.\n      */\n     DFBResult (*GetStatus) (\n          IDirectFBVideoProvider            *thiz,\n          DFBVideoProviderStatus            *ret_status\n     );\n\n   /** Media Control **/\n\n     /*\n      * Seek to a position within the stream.\n      */\n     DFBResult (*SeekTo) (\n          IDirectFBVideoProvider            *thiz,\n          double                             seconds\n     );\n\n     /*\n      * Get current position within the stream.\n      */\n     DFBResult (*GetPos) (\n          IDirectFBVideoProvider            *thiz,\n          double                            *ret_seconds\n     );\n\n     /*\n      * Get the length of the stream.\n      */\n     DFBResult (*GetLength) (\n          IDirectFBVideoProvider            *thiz,\n          double                            *ret_seconds\n     );\n\n   /** Color Adjustment **/\n\n     /*\n      * Get the current video color settings.\n      */\n     DFBResult (*GetColorAdjustment) (\n          IDirectFBVideoProvider            *thiz,\n          DFBColorAdjustment                *ret_adj\n     );\n\n     /*\n      * Adjust the video colors.\n      */\n     DFBResult (*SetColorAdjustment) (\n          IDirectFBVideoProvider            *thiz,\n          const DFBColorAdjustment          *adj\n     );\n\n   /** Interactivity **/\n\n     /*\n      * Send an input or window event.\n      *\n      * This method allows to redirect events to an interactive\n      * video provider. Events must be relative to the specified\n      * rectangle of the destination surface.\n      */\n     DFBResult (*SendEvent) (\n          IDirectFBVideoProvider            *thiz,\n          const DFBEvent                    *event\n     );\n\n   /** Advanced control **/\n\n     /*\n      * Set the flags controlling playback mode.\n      */\n     DFBResult (*SetPlaybackFlags) (\n          IDirectFBVideoProvider            *thiz,\n          DFBVideoProviderPlaybackFlags      flags\n     );\n\n     /*\n      * Set the speed multiplier.\n      *\n      * Values below 1.0 reduce playback speed while values over\n      * 1.0 increase it.\n      * Specifying a value of 0.0 has the effect of putting the\n      * playback in pause mode.\n      */\n     DFBResult (*SetSpeed) (\n          IDirectFBVideoProvider            *thiz,\n          double                             multiplier\n     );\n\n     /*\n      * Get current speed multiplier.\n      */\n     DFBResult (*GetSpeed) (\n          IDirectFBVideoProvider            *thiz,\n          double                            *ret_multiplier\n     );\n\n     /*\n      * Set volume level.\n      *\n      * Values between 0.0 and 1.0 adjust the volume level.\n      * Values over 1.0 increase the amplification level.\n      */\n     DFBResult (*SetVolume) (\n          IDirectFBVideoProvider            *thiz,\n          float                              level\n     );\n\n     /*\n      * Get volume level.\n      */\n     DFBResult (*GetVolume) (\n          IDirectFBVideoProvider            *thiz,\n          float                             *ret_level\n     );\n\n  /** Event buffers **/\n\n     /*\n      * Create an event buffer for this video provider and\n      * attach it.\n      */\n     DFBResult (*CreateEventBuffer) (\n          IDirectFBVideoProvider             *thiz,\n          IDirectFBEventBuffer             **ret_interface\n     );\n\n     /*\n      * Attach an existing event buffer to this video provider.\n      */\n     DFBResult (*AttachEventBuffer) (\n          IDirectFBVideoProvider            *thiz,\n          IDirectFBEventBuffer              *buffer\n     );\n\n     /*\n      * Enable specific events to be sent from the video\n      * provider.\n      *\n      * The argument is a mask of events that will be set in the\n      * videoproviders's event mask.\n      * The default event mask is DVPET_ALL.\n      */\n     DFBResult (*EnableEvents) (\n          IDirectFBVideoProvider            *thiz,\n          DFBVideoProviderEventType          mask\n     );\n\n     /*\n      * Disable specific events from being sent from the video\n      * provider.\n      *\n      * The argument is a mask of events that will be cleared in\n      * the video providers's event mask.\n      * The default event mask is DVPET_ALL.\n      */\n     DFBResult (*DisableEvents) (\n          IDirectFBVideoProvider            *thiz,\n          DFBVideoProviderEventType          mask\n     );\n\n     /*\n      * Detach an event buffer from this video provider.\n      */\n     DFBResult (*DetachEventBuffer) (\n          IDirectFBVideoProvider            *thiz,\n          IDirectFBEventBuffer              *buffer\n     );\n\n  /** Buffer control **/\n\n     /*\n      * Get buffer occupancy (audio/video) when playing stream.\n      */\n     DFBResult (*GetBufferOccupancy) (\n          IDirectFBVideoProvider            *thiz,\n          DFBBufferOccupancy                *ret_occ\n     );\n\n     /*\n      * Set buffer thresholds for the audio/video playback.\n      */\n     DFBResult (*SetBufferThresholds) (\n          IDirectFBVideoProvider            *thiz,\n          DFBBufferThresholds                thresh\n     );\n\n     /*\n      * Get buffer thresholds for the audio/video playback.\n      */\n     DFBResult (*GetBufferThresholds) (\n          IDirectFBVideoProvider            *thiz,\n          DFBBufferThresholds               *ret_thresh\n     );\n\n   /** Playback **/\n\n     /*\n      * Update the video rendering into the specified rectangle\n      * of the destination surface.\n      */\n     DFBResult (*SetDestination) (\n          IDirectFBVideoProvider            *thiz,\n          IDirectFBSurface                  *destination,\n          const DFBRectangle                *dest_rect\n     );\n)\n\n/***********************\n * IDirectFBDataBuffer *\n ***********************/\n\n/*\n * IDirectFBDataBuffer is the data buffer interface.\n */\nD_DEFINE_INTERFACE( IDirectFBDataBuffer,\n\n   /** Buffer handling **/\n\n     /*\n      * Flush all data in this buffer.\n      *\n      * This method only applies to streaming buffers.\n      */\n     DFBResult (*Flush) (\n          IDirectFBDataBuffer               *thiz\n     );\n\n     /*\n      * Finish writing into a streaming buffer.\n      *\n      * Subsequent calls to PutData() will fail, while attempts\n      * to fetch data from the buffer will return EOF unless\n      * there is still data available.\n      */\n     DFBResult (*Finish) (\n          IDirectFBDataBuffer               *thiz\n     );\n\n     /*\n      * Seek to a given byte position.\n      *\n      * This method only applies to static buffers.\n      */\n     DFBResult (*SeekTo) (\n          IDirectFBDataBuffer               *thiz,\n          unsigned int                       offset\n     );\n\n     /*\n      * Get the current byte position within a static buffer.\n      *\n      * This method only applies to static buffers.\n      */\n     DFBResult (*GetPosition) (\n          IDirectFBDataBuffer               *thiz,\n          unsigned int                      *ret_offset\n     );\n\n     /*\n      * Get the length of a static or streaming buffer in bytes.\n      *\n      * The length of a static buffer is its static size.\n      * A streaming buffer has a variable length reflecting the\n      * amount of buffered data.\n      */\n     DFBResult (*GetLength) (\n          IDirectFBDataBuffer               *thiz,\n          unsigned int                      *ret_length\n     );\n\n   /** Waiting for data **/\n\n     /*\n      * Wait for data to be available.\n      *\n      * This method blocks until at least the specified number\n      * of bytes is available.\n      */\n     DFBResult (*WaitForData) (\n          IDirectFBDataBuffer               *thiz,\n          unsigned int                       length\n     );\n\n     /*\n      * Wait for data to be available within an amount of time.\n      *\n      * This method blocks until at least the specified number\n      * of bytes is available or the timeout is reached.\n      */\n     DFBResult (*WaitForDataWithTimeout) (\n          IDirectFBDataBuffer               *thiz,\n          unsigned int                       length,\n          unsigned int                       seconds,\n          unsigned int                       milli_seconds\n     );\n\n   /** Retrieving data **/\n\n     /*\n      * Fetch data from a streaming or static buffer.\n      *\n      * Static buffers will increase the data pointer.\n      * Streaming buffers will flush the data portion.\n      * The maximum number of bytes to fetch is specified by\n      * 'length', the actual number of bytes fetched is returned\n      * via 'ret_read'.\n      */\n     DFBResult (*GetData) (\n          IDirectFBDataBuffer               *thiz,\n          unsigned int                       length,\n          void                              *ret_data_ptr,\n          unsigned int                      *ret_read\n     );\n\n     /*\n      * Peek data from a streaming or static buffer.\n      *\n      * Unlike GetData() this method won't increase the data\n      * pointer or flush any portions of the data held.\n      *\n      * Additionally an offset relative to the current data\n      * pointer or beginning of the streaming buffer can be\n      * specified.\n      * The maximum number of bytes to peek is specified by\n      * 'length', the actual number of bytes peeked is returned\n      * via 'ret_read'.\n      */\n     DFBResult (*PeekData) (\n          IDirectFBDataBuffer               *thiz,\n          unsigned int                       length,\n          int                                offset,\n          void                              *ret_data_ptr,\n          unsigned int                      *ret_read\n     );\n\n     /*\n      * Check if there is data available.\n      */\n     DFBResult (*HasData) (\n          IDirectFBDataBuffer               *thiz\n     );\n\n   /** Providing data **/\n\n     /*\n      * Append a block of data to a streaming buffer.\n      *\n      * This method does not wait until the data got fetched.\n      * Static buffers don't support this method.\n      */\n     DFBResult (*PutData) (\n          IDirectFBDataBuffer               *thiz,\n          const void                        *data_ptr,\n          unsigned int                       length\n     );\n\n   /** Media from data **/\n\n     /*\n      * Create an image provider using the buffers data.\n      */\n     DFBResult (*CreateImageProvider) (\n          IDirectFBDataBuffer               *thiz,\n          IDirectFBImageProvider           **ret_interface\n     );\n\n     /*\n      * Create a video provider using the buffers data.\n      */\n     DFBResult (*CreateVideoProvider) (\n          IDirectFBDataBuffer               *thiz,\n          IDirectFBVideoProvider           **ret_interface\n     );\n\n     /*\n      * Load a font using the buffer's data, given a description\n      * of how to load the glyphs.\n      */\n     DFBResult (*CreateFont) (\n          IDirectFBDataBuffer               *thiz,\n          const DFBFontDescription          *desc,\n          IDirectFBFont                    **ret_interface\n     );\n)\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/directfb_keyboard.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECTFB_KEYBOARD_H__\n#define __DIRECTFB_KEYBOARD_H__\n\n/*\n * DirectFB key types (for advanced mapping).\n */\ntypedef enum {\n     DIKT_UNICODE                  = 0x0000,                     /* Unicode 3.x character (compatible to Latin-1) */\n     DIKT_SPECIAL                  = 0xF000,                     /* Special key (e.g. Cursor Up or Menu) */\n     DIKT_FUNCTION                 = 0xF100,                     /* Function key (F1 - Fn) */\n     DIKT_MODIFIER                 = 0xF200,                     /* Modifier key */\n     DIKT_LOCK                     = 0xF300,                     /* Lock key (e.g. CapsLock) */\n     DIKT_DEAD                     = 0xF400,                     /* Dead key (e.g. dead grave) */\n     DIKT_CUSTOM                   = 0xF500,                     /* Custom key (vendor specific) */\n     DIKT_IDENTIFIER               = 0xF600                      /* DirectFB key identifier */\n} DFBInputDeviceKeyType;\n\n#define DFB_KEY(type,index)          ((DIKT_##type) | (index))\n\n#define DFB_KEY_TYPE(symbol)         ((((symbol) & ~0xFFF) == 0xF000) ? (symbol) & 0xFF00 : DIKT_UNICODE)\n\n#define DFB_KEY_IS_ASCII(symbol)     ((symbol) < 128)\n\n#define DFB_FUNCTION_KEY(n)          (DFB_KEY( FUNCTION, n ))\n#define DFB_MODIFIER_KEY(i)          (DFB_KEY( MODIFIER, (1 << i) ))\n#define DFB_CUSTOM_KEY(n)            (DFB_KEY( CUSTOM, n ))\n\n#define DFB_LOWER_CASE(symbol)       (((symbol) >= 'A' && (symbol) <= 'Z') ? ((symbol) |  0x20) : (symbol))\n#define DFB_UPPER_CASE(symbol)       (((symbol) >= 'a' && (symbol) <= 'z') ? ((symbol) & ~0x20) : (symbol))\n\n/*\n * DirectFB modifier key identifiers (for advanced mapping).\n */\ntypedef enum {\n     DIMKI_SHIFT,\n     DIMKI_CONTROL,\n     DIMKI_ALT,\n     DIMKI_ALTGR,\n     DIMKI_META,\n     DIMKI_SUPER,\n     DIMKI_HYPER,\n\n     DIMKI_FIRST                   = DIMKI_SHIFT,\n     DIMKI_LAST                    = DIMKI_HYPER\n} DFBInputDeviceModifierKeyIdentifier;\n\n/*\n * DirectFB key identifiers (for basic mapping).\n */\ntypedef enum {\n     DIKI_UNKNOWN                  = DFB_KEY( IDENTIFIER, 0 ),\n\n     DIKI_A,\n     DIKI_B,\n     DIKI_C,\n     DIKI_D,\n     DIKI_E,\n     DIKI_F,\n     DIKI_G,\n     DIKI_H,\n     DIKI_I,\n     DIKI_J,\n     DIKI_K,\n     DIKI_L,\n     DIKI_M,\n     DIKI_N,\n     DIKI_O,\n     DIKI_P,\n     DIKI_Q,\n     DIKI_R,\n     DIKI_S,\n     DIKI_T,\n     DIKI_U,\n     DIKI_V,\n     DIKI_W,\n     DIKI_X,\n     DIKI_Y,\n     DIKI_Z,\n\n     DIKI_0,\n     DIKI_1,\n     DIKI_2,\n     DIKI_3,\n     DIKI_4,\n     DIKI_5,\n     DIKI_6,\n     DIKI_7,\n     DIKI_8,\n     DIKI_9,\n\n     DIKI_F1,\n     DIKI_F2,\n     DIKI_F3,\n     DIKI_F4,\n     DIKI_F5,\n     DIKI_F6,\n     DIKI_F7,\n     DIKI_F8,\n     DIKI_F9,\n     DIKI_F10,\n     DIKI_F11,\n     DIKI_F12,\n\n     DIKI_SHIFT_L,\n     DIKI_SHIFT_R,\n     DIKI_CONTROL_L,\n     DIKI_CONTROL_R,\n     DIKI_ALT_L,\n     DIKI_ALT_R,\n     DIKI_META_L,\n     DIKI_META_R,\n     DIKI_SUPER_L,\n     DIKI_SUPER_R,\n     DIKI_HYPER_L,\n     DIKI_HYPER_R,\n\n     DIKI_CAPS_LOCK,\n     DIKI_NUM_LOCK,\n     DIKI_SCROLL_LOCK,\n\n     DIKI_ESCAPE,\n     DIKI_LEFT,\n     DIKI_RIGHT,\n     DIKI_UP,\n     DIKI_DOWN,\n     DIKI_TAB,\n     DIKI_ENTER,\n     DIKI_SPACE,\n     DIKI_BACKSPACE,\n     DIKI_INSERT,\n     DIKI_DELETE,\n     DIKI_HOME,\n     DIKI_END,\n     DIKI_PAGE_UP,\n     DIKI_PAGE_DOWN,\n     DIKI_PRINT,\n     DIKI_PAUSE,\n\n     /*\n      * The labels on these keys depend on the type of keyboard.\n      * We've choosen the names from a US keyboard layout.\n      */\n     DIKI_QUOTE_LEFT,\n     DIKI_MINUS_SIGN,\n     DIKI_EQUALS_SIGN,\n     DIKI_BRACKET_LEFT,\n     DIKI_BRACKET_RIGHT,\n     DIKI_BACKSLASH,\n     DIKI_SEMICOLON,\n     DIKI_QUOTE_RIGHT,\n     DIKI_COMMA,\n     DIKI_PERIOD,\n     DIKI_SLASH,\n\n     DIKI_LESS_SIGN,\n\n     DIKI_KP_DIV,\n     DIKI_KP_MULT,\n     DIKI_KP_MINUS,\n     DIKI_KP_PLUS,\n     DIKI_KP_ENTER,\n     DIKI_KP_SPACE,\n     DIKI_KP_TAB,\n     DIKI_KP_F1,\n     DIKI_KP_F2,\n     DIKI_KP_F3,\n     DIKI_KP_F4,\n     DIKI_KP_EQUAL,\n     DIKI_KP_SEPARATOR,\n\n     DIKI_KP_DECIMAL,\n     DIKI_KP_0,\n     DIKI_KP_1,\n     DIKI_KP_2,\n     DIKI_KP_3,\n     DIKI_KP_4,\n     DIKI_KP_5,\n     DIKI_KP_6,\n     DIKI_KP_7,\n     DIKI_KP_8,\n     DIKI_KP_9,\n\n     DIKI_KEYDEF_END,\n     DIKI_NUMBER_OF_KEYS           = DIKI_KEYDEF_END - DFB_KEY( IDENTIFIER, 0 )\n} DFBInputDeviceKeyIdentifier;\n\n/*\n * DirectFB key symbols (for advanced mapping).\n */\ntypedef enum {\n     /*\n      * Unicode excerpt - Controls and Basic Latin\n      * Any Unicode 3.x character can be used as a key symbol.\n      * The values of this enum are compatible with Unicode.\n      */\n     DIKS_NULL                     = DFB_KEY( UNICODE, 0x00 ),\n     DIKS_BACKSPACE                = DFB_KEY( UNICODE, 0x08 ),\n     DIKS_TAB                      = DFB_KEY( UNICODE, 0x09 ),\n     DIKS_RETURN                   = DFB_KEY( UNICODE, 0x0D ),\n     DIKS_CANCEL                   = DFB_KEY( UNICODE, 0x18 ),\n     DIKS_ESCAPE                   = DFB_KEY( UNICODE, 0x1B ),\n     DIKS_SPACE                    = DFB_KEY( UNICODE, 0x20 ),\n     DIKS_EXCLAMATION_MARK         = DFB_KEY( UNICODE, 0x21 ),\n     DIKS_QUOTATION                = DFB_KEY( UNICODE, 0x22 ),\n     DIKS_NUMBER_SIGN              = DFB_KEY( UNICODE, 0x23 ),\n     DIKS_DOLLAR_SIGN              = DFB_KEY( UNICODE, 0x24 ),\n     DIKS_PERCENT_SIGN             = DFB_KEY( UNICODE, 0x25 ),\n     DIKS_AMPERSAND                = DFB_KEY( UNICODE, 0x26 ),\n     DIKS_APOSTROPHE               = DFB_KEY( UNICODE, 0x27 ),\n     DIKS_PARENTHESIS_LEFT         = DFB_KEY( UNICODE, 0x28 ),\n     DIKS_PARENTHESIS_RIGHT        = DFB_KEY( UNICODE, 0x29 ),\n     DIKS_ASTERISK                 = DFB_KEY( UNICODE, 0x2A ),\n     DIKS_PLUS_SIGN                = DFB_KEY( UNICODE, 0x2B ),\n     DIKS_COMMA                    = DFB_KEY( UNICODE, 0x2C ),\n     DIKS_MINUS_SIGN               = DFB_KEY( UNICODE, 0x2D ),\n     DIKS_PERIOD                   = DFB_KEY( UNICODE, 0x2E ),\n     DIKS_SLASH                    = DFB_KEY( UNICODE, 0x2F ),\n     DIKS_0                        = DFB_KEY( UNICODE, 0x30 ),\n     DIKS_1                        = DFB_KEY( UNICODE, 0x31 ),\n     DIKS_2                        = DFB_KEY( UNICODE, 0x32 ),\n     DIKS_3                        = DFB_KEY( UNICODE, 0x33 ),\n     DIKS_4                        = DFB_KEY( UNICODE, 0x34 ),\n     DIKS_5                        = DFB_KEY( UNICODE, 0x35 ),\n     DIKS_6                        = DFB_KEY( UNICODE, 0x36 ),\n     DIKS_7                        = DFB_KEY( UNICODE, 0x37 ),\n     DIKS_8                        = DFB_KEY( UNICODE, 0x38 ),\n     DIKS_9                        = DFB_KEY( UNICODE, 0x39 ),\n     DIKS_COLON                    = DFB_KEY( UNICODE, 0x3A ),\n     DIKS_SEMICOLON                = DFB_KEY( UNICODE, 0x3B ),\n     DIKS_LESS_THAN_SIGN           = DFB_KEY( UNICODE, 0x3C ),\n     DIKS_EQUALS_SIGN              = DFB_KEY( UNICODE, 0x3D ),\n     DIKS_GREATER_THAN_SIGN        = DFB_KEY( UNICODE, 0x3E ),\n     DIKS_QUESTION_MARK            = DFB_KEY( UNICODE, 0x3F ),\n     DIKS_AT                       = DFB_KEY( UNICODE, 0x40 ),\n     DIKS_CAPITAL_A                = DFB_KEY( UNICODE, 0x41 ),\n     DIKS_CAPITAL_B                = DFB_KEY( UNICODE, 0x42 ),\n     DIKS_CAPITAL_C                = DFB_KEY( UNICODE, 0x43 ),\n     DIKS_CAPITAL_D                = DFB_KEY( UNICODE, 0x44 ),\n     DIKS_CAPITAL_E                = DFB_KEY( UNICODE, 0x45 ),\n     DIKS_CAPITAL_F                = DFB_KEY( UNICODE, 0x46 ),\n     DIKS_CAPITAL_G                = DFB_KEY( UNICODE, 0x47 ),\n     DIKS_CAPITAL_H                = DFB_KEY( UNICODE, 0x48 ),\n     DIKS_CAPITAL_I                = DFB_KEY( UNICODE, 0x49 ),\n     DIKS_CAPITAL_J                = DFB_KEY( UNICODE, 0x4A ),\n     DIKS_CAPITAL_K                = DFB_KEY( UNICODE, 0x4B ),\n     DIKS_CAPITAL_L                = DFB_KEY( UNICODE, 0x4C ),\n     DIKS_CAPITAL_M                = DFB_KEY( UNICODE, 0x4D ),\n     DIKS_CAPITAL_N                = DFB_KEY( UNICODE, 0x4E ),\n     DIKS_CAPITAL_O                = DFB_KEY( UNICODE, 0x4F ),\n     DIKS_CAPITAL_P                = DFB_KEY( UNICODE, 0x50 ),\n     DIKS_CAPITAL_Q                = DFB_KEY( UNICODE, 0x51 ),\n     DIKS_CAPITAL_R                = DFB_KEY( UNICODE, 0x52 ),\n     DIKS_CAPITAL_S                = DFB_KEY( UNICODE, 0x53 ),\n     DIKS_CAPITAL_T                = DFB_KEY( UNICODE, 0x54 ),\n     DIKS_CAPITAL_U                = DFB_KEY( UNICODE, 0x55 ),\n     DIKS_CAPITAL_V                = DFB_KEY( UNICODE, 0x56 ),\n     DIKS_CAPITAL_W                = DFB_KEY( UNICODE, 0x57 ),\n     DIKS_CAPITAL_X                = DFB_KEY( UNICODE, 0x58 ),\n     DIKS_CAPITAL_Y                = DFB_KEY( UNICODE, 0x59 ),\n     DIKS_CAPITAL_Z                = DFB_KEY( UNICODE, 0x5A ),\n     DIKS_SQUARE_BRACKET_LEFT      = DFB_KEY( UNICODE, 0x5B ),\n     DIKS_BACKSLASH                = DFB_KEY( UNICODE, 0x5C ),\n     DIKS_SQUARE_BRACKET_RIGHT     = DFB_KEY( UNICODE, 0x5D ),\n     DIKS_CIRCUMFLEX_ACCENT        = DFB_KEY( UNICODE, 0x5E ),\n     DIKS_UNDERSCORE               = DFB_KEY( UNICODE, 0x5F ),\n     DIKS_GRAVE_ACCENT             = DFB_KEY( UNICODE, 0x60 ),\n     DIKS_SMALL_A                  = DFB_KEY( UNICODE, 0x61 ),\n     DIKS_SMALL_B                  = DFB_KEY( UNICODE, 0x62 ),\n     DIKS_SMALL_C                  = DFB_KEY( UNICODE, 0x63 ),\n     DIKS_SMALL_D                  = DFB_KEY( UNICODE, 0x64 ),\n     DIKS_SMALL_E                  = DFB_KEY( UNICODE, 0x65 ),\n     DIKS_SMALL_F                  = DFB_KEY( UNICODE, 0x66 ),\n     DIKS_SMALL_G                  = DFB_KEY( UNICODE, 0x67 ),\n     DIKS_SMALL_H                  = DFB_KEY( UNICODE, 0x68 ),\n     DIKS_SMALL_I                  = DFB_KEY( UNICODE, 0x69 ),\n     DIKS_SMALL_J                  = DFB_KEY( UNICODE, 0x6A ),\n     DIKS_SMALL_K                  = DFB_KEY( UNICODE, 0x6B ),\n     DIKS_SMALL_L                  = DFB_KEY( UNICODE, 0x6C ),\n     DIKS_SMALL_M                  = DFB_KEY( UNICODE, 0x6D ),\n     DIKS_SMALL_N                  = DFB_KEY( UNICODE, 0x6E ),\n     DIKS_SMALL_O                  = DFB_KEY( UNICODE, 0x6F ),\n     DIKS_SMALL_P                  = DFB_KEY( UNICODE, 0x70 ),\n     DIKS_SMALL_Q                  = DFB_KEY( UNICODE, 0x71 ),\n     DIKS_SMALL_R                  = DFB_KEY( UNICODE, 0x72 ),\n     DIKS_SMALL_S                  = DFB_KEY( UNICODE, 0x73 ),\n     DIKS_SMALL_T                  = DFB_KEY( UNICODE, 0x74 ),\n     DIKS_SMALL_U                  = DFB_KEY( UNICODE, 0x75 ),\n     DIKS_SMALL_V                  = DFB_KEY( UNICODE, 0x76 ),\n     DIKS_SMALL_W                  = DFB_KEY( UNICODE, 0x77 ),\n     DIKS_SMALL_X                  = DFB_KEY( UNICODE, 0x78 ),\n     DIKS_SMALL_Y                  = DFB_KEY( UNICODE, 0x79 ),\n     DIKS_SMALL_Z                  = DFB_KEY( UNICODE, 0x7A ),\n     DIKS_CURLY_BRACKET_LEFT       = DFB_KEY( UNICODE, 0x7B ),\n     DIKS_VERTICAL_BAR             = DFB_KEY( UNICODE, 0x7C ),\n     DIKS_CURLY_BRACKET_RIGHT      = DFB_KEY( UNICODE, 0x7D ),\n     DIKS_TILDE                    = DFB_KEY( UNICODE, 0x7E ),\n     DIKS_DELETE                   = DFB_KEY( UNICODE, 0x7F ),\n\n     DIKS_ENTER                    = DIKS_RETURN,\n\n     /*\n      * Unicode private area - DirectFB Special keys\n      */\n     DIKS_CURSOR_LEFT              = DFB_KEY( SPECIAL, 0x00 ),\n     DIKS_CURSOR_RIGHT             = DFB_KEY( SPECIAL, 0x01 ),\n     DIKS_CURSOR_UP                = DFB_KEY( SPECIAL, 0x02 ),\n     DIKS_CURSOR_DOWN              = DFB_KEY( SPECIAL, 0x03 ),\n     DIKS_INSERT                   = DFB_KEY( SPECIAL, 0x04 ),\n     DIKS_HOME                     = DFB_KEY( SPECIAL, 0x05 ),\n     DIKS_END                      = DFB_KEY( SPECIAL, 0x06 ),\n     DIKS_PAGE_UP                  = DFB_KEY( SPECIAL, 0x07 ),\n     DIKS_PAGE_DOWN                = DFB_KEY( SPECIAL, 0x08 ),\n     DIKS_PRINT                    = DFB_KEY( SPECIAL, 0x09 ),\n     DIKS_PAUSE                    = DFB_KEY( SPECIAL, 0x0A ),\n     DIKS_OK                       = DFB_KEY( SPECIAL, 0x0B ),\n     DIKS_SELECT                   = DFB_KEY( SPECIAL, 0x0C ),\n     DIKS_GOTO                     = DFB_KEY( SPECIAL, 0x0D ),\n     DIKS_CLEAR                    = DFB_KEY( SPECIAL, 0x0E ),\n     DIKS_POWER                    = DFB_KEY( SPECIAL, 0x0F ),\n     DIKS_POWER2                   = DFB_KEY( SPECIAL, 0x10 ),\n     DIKS_OPTION                   = DFB_KEY( SPECIAL, 0x11 ),\n     DIKS_MENU                     = DFB_KEY( SPECIAL, 0x12 ),\n     DIKS_HELP                     = DFB_KEY( SPECIAL, 0x13 ),\n     DIKS_INFO                     = DFB_KEY( SPECIAL, 0x14 ),\n     DIKS_TIME                     = DFB_KEY( SPECIAL, 0x15 ),\n     DIKS_VENDOR                   = DFB_KEY( SPECIAL, 0x16 ),\n\n     DIKS_ARCHIVE                  = DFB_KEY( SPECIAL, 0x17 ),\n     DIKS_PROGRAM                  = DFB_KEY( SPECIAL, 0x18 ),\n     DIKS_CHANNEL                  = DFB_KEY( SPECIAL, 0x19 ),\n     DIKS_FAVORITES                = DFB_KEY( SPECIAL, 0x1A ),\n     DIKS_EPG                      = DFB_KEY( SPECIAL, 0x1B ),\n     DIKS_PVR                      = DFB_KEY( SPECIAL, 0x1C ),\n     DIKS_MHP                      = DFB_KEY( SPECIAL, 0x1D ),\n     DIKS_LANGUAGE                 = DFB_KEY( SPECIAL, 0x1E ),\n     DIKS_TITLE                    = DFB_KEY( SPECIAL, 0x1F ),\n     DIKS_SUBTITLE                 = DFB_KEY( SPECIAL, 0x20 ),\n     DIKS_ANGLE                    = DFB_KEY( SPECIAL, 0x21 ),\n     DIKS_ZOOM                     = DFB_KEY( SPECIAL, 0x22 ),\n     DIKS_MODE                     = DFB_KEY( SPECIAL, 0x23 ),\n     DIKS_KEYBOARD                 = DFB_KEY( SPECIAL, 0x24 ),\n     DIKS_PC                       = DFB_KEY( SPECIAL, 0x25 ),\n     DIKS_SCREEN                   = DFB_KEY( SPECIAL, 0x26 ),\n\n     DIKS_TV                       = DFB_KEY( SPECIAL, 0x27 ),\n     DIKS_TV2                      = DFB_KEY( SPECIAL, 0x28 ),\n     DIKS_VCR                      = DFB_KEY( SPECIAL, 0x29 ),\n     DIKS_VCR2                     = DFB_KEY( SPECIAL, 0x2A ),\n     DIKS_SAT                      = DFB_KEY( SPECIAL, 0x2B ),\n     DIKS_SAT2                     = DFB_KEY( SPECIAL, 0x2C ),\n     DIKS_CD                       = DFB_KEY( SPECIAL, 0x2D ),\n     DIKS_TAPE                     = DFB_KEY( SPECIAL, 0x2E ),\n     DIKS_RADIO                    = DFB_KEY( SPECIAL, 0x2F ),\n     DIKS_TUNER                    = DFB_KEY( SPECIAL, 0x30 ),\n     DIKS_PLAYER                   = DFB_KEY( SPECIAL, 0x31 ),\n     DIKS_TEXT                     = DFB_KEY( SPECIAL, 0x32 ),\n     DIKS_DVD                      = DFB_KEY( SPECIAL, 0x33 ),\n     DIKS_AUX                      = DFB_KEY( SPECIAL, 0x34 ),\n     DIKS_MP3                      = DFB_KEY( SPECIAL, 0x35 ),\n     DIKS_PHONE                    = DFB_KEY( SPECIAL, 0x36 ),\n     DIKS_AUDIO                    = DFB_KEY( SPECIAL, 0x37 ),\n     DIKS_VIDEO                    = DFB_KEY( SPECIAL, 0x38 ),\n\n     DIKS_INTERNET                 = DFB_KEY( SPECIAL, 0x39 ),\n     DIKS_MAIL                     = DFB_KEY( SPECIAL, 0x3A ),\n     DIKS_NEWS                     = DFB_KEY( SPECIAL, 0x3B ),\n     DIKS_DIRECTORY                = DFB_KEY( SPECIAL, 0x3C ),\n     DIKS_LIST                     = DFB_KEY( SPECIAL, 0x3D ),\n     DIKS_CALCULATOR               = DFB_KEY( SPECIAL, 0x3E ),\n     DIKS_MEMO                     = DFB_KEY( SPECIAL, 0x3F ),\n     DIKS_CALENDAR                 = DFB_KEY( SPECIAL, 0x40 ),\n     DIKS_EDITOR                   = DFB_KEY( SPECIAL, 0x41 ),\n\n     DIKS_RED                      = DFB_KEY( SPECIAL, 0x42 ),\n     DIKS_GREEN                    = DFB_KEY( SPECIAL, 0x43 ),\n     DIKS_YELLOW                   = DFB_KEY( SPECIAL, 0x44 ),\n     DIKS_BLUE                     = DFB_KEY( SPECIAL, 0x45 ),\n\n     DIKS_CHANNEL_UP               = DFB_KEY( SPECIAL, 0x46 ),\n     DIKS_CHANNEL_DOWN             = DFB_KEY( SPECIAL, 0x47 ),\n     DIKS_BACK                     = DFB_KEY( SPECIAL, 0x48 ),\n     DIKS_FORWARD                  = DFB_KEY( SPECIAL, 0x49 ),\n     DIKS_FIRST                    = DFB_KEY( SPECIAL, 0x4A ),\n     DIKS_LAST                     = DFB_KEY( SPECIAL, 0x4B ),\n     DIKS_VOLUME_UP                = DFB_KEY( SPECIAL, 0x4C ),\n     DIKS_VOLUME_DOWN              = DFB_KEY( SPECIAL, 0x4D ),\n     DIKS_MUTE                     = DFB_KEY( SPECIAL, 0x4E ),\n     DIKS_AB                       = DFB_KEY( SPECIAL, 0x4F ),\n     DIKS_PLAYPAUSE                = DFB_KEY( SPECIAL, 0x50 ),\n     DIKS_PLAY                     = DFB_KEY( SPECIAL, 0x51 ),\n     DIKS_STOP                     = DFB_KEY( SPECIAL, 0x52 ),\n     DIKS_RESTART                  = DFB_KEY( SPECIAL, 0x53 ),\n     DIKS_SLOW                     = DFB_KEY( SPECIAL, 0x54 ),\n     DIKS_FAST                     = DFB_KEY( SPECIAL, 0x55 ),\n     DIKS_RECORD                   = DFB_KEY( SPECIAL, 0x56 ),\n     DIKS_EJECT                    = DFB_KEY( SPECIAL, 0x57 ),\n     DIKS_SHUFFLE                  = DFB_KEY( SPECIAL, 0x58 ),\n     DIKS_REWIND                   = DFB_KEY( SPECIAL, 0x59 ),\n     DIKS_FASTFORWARD              = DFB_KEY( SPECIAL, 0x5A ),\n     DIKS_PREVIOUS                 = DFB_KEY( SPECIAL, 0x5B ),\n     DIKS_NEXT                     = DFB_KEY( SPECIAL, 0x5C ),\n     DIKS_BEGIN                    = DFB_KEY( SPECIAL, 0x5D ),\n\n     DIKS_DIGITS                   = DFB_KEY( SPECIAL, 0x5E ),\n     DIKS_TEEN                     = DFB_KEY( SPECIAL, 0x5F ),\n     DIKS_TWEN                     = DFB_KEY( SPECIAL, 0x60 ),\n\n     DIKS_BREAK                    = DFB_KEY( SPECIAL, 0x61 ),\n     DIKS_EXIT                     = DFB_KEY( SPECIAL, 0x62 ),\n     DIKS_SETUP                    = DFB_KEY( SPECIAL, 0x63 ),\n\n     DIKS_CURSOR_LEFT_UP           = DFB_KEY( SPECIAL, 0x64 ),\n     DIKS_CURSOR_LEFT_DOWN         = DFB_KEY( SPECIAL, 0x65 ),\n     DIKS_CURSOR_UP_RIGHT          = DFB_KEY( SPECIAL, 0x66 ),\n     DIKS_CURSOR_DOWN_RIGHT        = DFB_KEY( SPECIAL, 0x67 ),\n\n     DIKS_PIP                      = DFB_KEY( SPECIAL, 0x68 ),\n     DIKS_SWAP                     = DFB_KEY( SPECIAL, 0x69 ),\n     DIKS_FREEZE                   = DFB_KEY( SPECIAL, 0x6A ),\n     DIKS_MOVE                     = DFB_KEY( SPECIAL, 0x6B ),\n\n     DIKS_CALL                     = DFB_KEY( SPECIAL, 0x6C ),\n     DIKS_SPEAKER                  = DFB_KEY( SPECIAL, 0x6D ),\n     DIKS_SAVE                     = DFB_KEY( SPECIAL, 0x6E ),\n     DIKS_REDIAL                   = DFB_KEY( SPECIAL, 0x6F ),\n     DIKS_FLASH                    = DFB_KEY( SPECIAL, 0x70 ),\n     DIKS_HOLD                     = DFB_KEY( SPECIAL, 0x71 ),\n\n     /*\n      * Unicode private area - DirectFB Function keys\n      */\n     DIKS_F1                       = DFB_FUNCTION_KEY(  1 ),\n     DIKS_F2                       = DFB_FUNCTION_KEY(  2 ),\n     DIKS_F3                       = DFB_FUNCTION_KEY(  3 ),\n     DIKS_F4                       = DFB_FUNCTION_KEY(  4 ),\n     DIKS_F5                       = DFB_FUNCTION_KEY(  5 ),\n     DIKS_F6                       = DFB_FUNCTION_KEY(  6 ),\n     DIKS_F7                       = DFB_FUNCTION_KEY(  7 ),\n     DIKS_F8                       = DFB_FUNCTION_KEY(  8 ),\n     DIKS_F9                       = DFB_FUNCTION_KEY(  9 ),\n     DIKS_F10                      = DFB_FUNCTION_KEY( 10 ),\n     DIKS_F11                      = DFB_FUNCTION_KEY( 11 ),\n     DIKS_F12                      = DFB_FUNCTION_KEY( 12 ),\n\n     /*\n      * Unicode private area - DirectFB Modifier keys\n      */\n     DIKS_SHIFT                    = DFB_MODIFIER_KEY( DIMKI_SHIFT ),\n     DIKS_CONTROL                  = DFB_MODIFIER_KEY( DIMKI_CONTROL ),\n     DIKS_ALT                      = DFB_MODIFIER_KEY( DIMKI_ALT ),\n     DIKS_ALTGR                    = DFB_MODIFIER_KEY( DIMKI_ALTGR ),\n     DIKS_META                     = DFB_MODIFIER_KEY( DIMKI_META ),\n     DIKS_SUPER                    = DFB_MODIFIER_KEY( DIMKI_SUPER ),\n     DIKS_HYPER                    = DFB_MODIFIER_KEY( DIMKI_HYPER ),\n\n     /*\n      * Unicode private area - DirectFB Lock keys\n      */\n     DIKS_CAPS_LOCK                = DFB_KEY( LOCK, 0x00 ),\n     DIKS_NUM_LOCK                 = DFB_KEY( LOCK, 0x01 ),\n     DIKS_SCROLL_LOCK              = DFB_KEY( LOCK, 0x02 ),\n\n     /*\n      * Unicode private area - DirectFB Dead keys\n      */\n     DIKS_DEAD_ABOVEDOT            = DFB_KEY( DEAD, 0x00 ),\n     DIKS_DEAD_ABOVERING           = DFB_KEY( DEAD, 0x01 ),\n     DIKS_DEAD_ACUTE               = DFB_KEY( DEAD, 0x02 ),\n     DIKS_DEAD_BREVE               = DFB_KEY( DEAD, 0x03 ),\n     DIKS_DEAD_CARON               = DFB_KEY( DEAD, 0x04 ),\n     DIKS_DEAD_CEDILLA             = DFB_KEY( DEAD, 0x05 ),\n     DIKS_DEAD_CIRCUMFLEX          = DFB_KEY( DEAD, 0x06 ),\n     DIKS_DEAD_DIAERESIS           = DFB_KEY( DEAD, 0x07 ),\n     DIKS_DEAD_DOUBLEACUTE         = DFB_KEY( DEAD, 0x08 ),\n     DIKS_DEAD_GRAVE               = DFB_KEY( DEAD, 0x09 ),\n     DIKS_DEAD_IOTA                = DFB_KEY( DEAD, 0x0A ),\n     DIKS_DEAD_MACRON              = DFB_KEY( DEAD, 0x0B ),\n     DIKS_DEAD_OGONEK              = DFB_KEY( DEAD, 0x0C ),\n     DIKS_DEAD_SEMIVOICED_SOUND    = DFB_KEY( DEAD, 0x0D ),\n     DIKS_DEAD_TILDE               = DFB_KEY( DEAD, 0x0E ),\n     DIKS_DEAD_VOICED_SOUND        = DFB_KEY( DEAD, 0x0F ),\n\n     /*\n      * Unicode private area - DirectFB Custom keys\n      */\n     DIKS_CUSTOM0                  = DFB_CUSTOM_KEY( 0 ),\n     DIKS_CUSTOM1                  = DFB_CUSTOM_KEY( 1 ),\n     DIKS_CUSTOM2                  = DFB_CUSTOM_KEY( 2 ),\n     DIKS_CUSTOM3                  = DFB_CUSTOM_KEY( 3 ),\n     DIKS_CUSTOM4                  = DFB_CUSTOM_KEY( 4 ),\n     DIKS_CUSTOM5                  = DFB_CUSTOM_KEY( 5 ),\n     DIKS_CUSTOM6                  = DFB_CUSTOM_KEY( 6 ),\n     DIKS_CUSTOM7                  = DFB_CUSTOM_KEY( 7 ),\n     DIKS_CUSTOM8                  = DFB_CUSTOM_KEY( 8 ),\n     DIKS_CUSTOM9                  = DFB_CUSTOM_KEY( 9 ),\n     DIKS_CUSTOM10                 = DFB_CUSTOM_KEY( 10 ),\n     DIKS_CUSTOM11                 = DFB_CUSTOM_KEY( 11 ),\n     DIKS_CUSTOM12                 = DFB_CUSTOM_KEY( 12 ),\n     DIKS_CUSTOM13                 = DFB_CUSTOM_KEY( 13 ),\n     DIKS_CUSTOM14                 = DFB_CUSTOM_KEY( 14 ),\n     DIKS_CUSTOM15                 = DFB_CUSTOM_KEY( 15 ),\n     DIKS_CUSTOM16                 = DFB_CUSTOM_KEY( 16 ),\n     DIKS_CUSTOM17                 = DFB_CUSTOM_KEY( 17 ),\n     DIKS_CUSTOM18                 = DFB_CUSTOM_KEY( 18 ),\n     DIKS_CUSTOM19                 = DFB_CUSTOM_KEY( 19 ),\n     DIKS_CUSTOM20                 = DFB_CUSTOM_KEY( 20 ),\n     DIKS_CUSTOM21                 = DFB_CUSTOM_KEY( 21 ),\n     DIKS_CUSTOM22                 = DFB_CUSTOM_KEY( 22 ),\n     DIKS_CUSTOM23                 = DFB_CUSTOM_KEY( 23 ),\n     DIKS_CUSTOM24                 = DFB_CUSTOM_KEY( 24 ),\n     DIKS_CUSTOM25                 = DFB_CUSTOM_KEY( 25 ),\n     DIKS_CUSTOM26                 = DFB_CUSTOM_KEY( 26 ),\n     DIKS_CUSTOM27                 = DFB_CUSTOM_KEY( 27 ),\n     DIKS_CUSTOM28                 = DFB_CUSTOM_KEY( 28 ),\n     DIKS_CUSTOM29                 = DFB_CUSTOM_KEY( 29 ),\n     DIKS_CUSTOM30                 = DFB_CUSTOM_KEY( 30 ),\n     DIKS_CUSTOM31                 = DFB_CUSTOM_KEY( 31 ),\n     DIKS_CUSTOM32                 = DFB_CUSTOM_KEY( 32 ),\n     DIKS_CUSTOM33                 = DFB_CUSTOM_KEY( 33 ),\n     DIKS_CUSTOM34                 = DFB_CUSTOM_KEY( 34 ),\n     DIKS_CUSTOM35                 = DFB_CUSTOM_KEY( 35 ),\n     DIKS_CUSTOM36                 = DFB_CUSTOM_KEY( 36 ),\n     DIKS_CUSTOM37                 = DFB_CUSTOM_KEY( 37 ),\n     DIKS_CUSTOM38                 = DFB_CUSTOM_KEY( 38 ),\n     DIKS_CUSTOM39                 = DFB_CUSTOM_KEY( 39 ),\n     DIKS_CUSTOM40                 = DFB_CUSTOM_KEY( 40 ),\n     DIKS_CUSTOM41                 = DFB_CUSTOM_KEY( 41 ),\n     DIKS_CUSTOM42                 = DFB_CUSTOM_KEY( 42 ),\n     DIKS_CUSTOM43                 = DFB_CUSTOM_KEY( 43 ),\n     DIKS_CUSTOM44                 = DFB_CUSTOM_KEY( 44 ),\n     DIKS_CUSTOM45                 = DFB_CUSTOM_KEY( 45 ),\n     DIKS_CUSTOM46                 = DFB_CUSTOM_KEY( 46 ),\n     DIKS_CUSTOM47                 = DFB_CUSTOM_KEY( 47 ),\n     DIKS_CUSTOM48                 = DFB_CUSTOM_KEY( 48 ),\n     DIKS_CUSTOM49                 = DFB_CUSTOM_KEY( 49 ),\n     DIKS_CUSTOM50                 = DFB_CUSTOM_KEY( 50 ),\n     DIKS_CUSTOM51                 = DFB_CUSTOM_KEY( 51 ),\n     DIKS_CUSTOM52                 = DFB_CUSTOM_KEY( 52 ),\n     DIKS_CUSTOM53                 = DFB_CUSTOM_KEY( 53 ),\n     DIKS_CUSTOM54                 = DFB_CUSTOM_KEY( 54 ),\n     DIKS_CUSTOM55                 = DFB_CUSTOM_KEY( 55 ),\n     DIKS_CUSTOM56                 = DFB_CUSTOM_KEY( 56 ),\n     DIKS_CUSTOM57                 = DFB_CUSTOM_KEY( 57 ),\n     DIKS_CUSTOM58                 = DFB_CUSTOM_KEY( 58 ),\n     DIKS_CUSTOM59                 = DFB_CUSTOM_KEY( 59 ),\n     DIKS_CUSTOM60                 = DFB_CUSTOM_KEY( 60 ),\n     DIKS_CUSTOM61                 = DFB_CUSTOM_KEY( 61 ),\n     DIKS_CUSTOM62                 = DFB_CUSTOM_KEY( 62 ),\n     DIKS_CUSTOM63                 = DFB_CUSTOM_KEY( 63 ),\n     DIKS_CUSTOM64                 = DFB_CUSTOM_KEY( 64 ),\n     DIKS_CUSTOM65                 = DFB_CUSTOM_KEY( 65 ),\n     DIKS_CUSTOM66                 = DFB_CUSTOM_KEY( 66 ),\n     DIKS_CUSTOM67                 = DFB_CUSTOM_KEY( 67 ),\n     DIKS_CUSTOM68                 = DFB_CUSTOM_KEY( 68 ),\n     DIKS_CUSTOM69                 = DFB_CUSTOM_KEY( 69 ),\n     DIKS_CUSTOM70                 = DFB_CUSTOM_KEY( 70 ),\n     DIKS_CUSTOM71                 = DFB_CUSTOM_KEY( 71 ),\n     DIKS_CUSTOM72                 = DFB_CUSTOM_KEY( 72 ),\n     DIKS_CUSTOM73                 = DFB_CUSTOM_KEY( 73 ),\n     DIKS_CUSTOM74                 = DFB_CUSTOM_KEY( 74 ),\n     DIKS_CUSTOM75                 = DFB_CUSTOM_KEY( 75 ),\n     DIKS_CUSTOM76                 = DFB_CUSTOM_KEY( 76 ),\n     DIKS_CUSTOM77                 = DFB_CUSTOM_KEY( 77 ),\n     DIKS_CUSTOM78                 = DFB_CUSTOM_KEY( 78 ),\n     DIKS_CUSTOM79                 = DFB_CUSTOM_KEY( 79 ),\n     DIKS_CUSTOM80                 = DFB_CUSTOM_KEY( 80 ),\n     DIKS_CUSTOM81                 = DFB_CUSTOM_KEY( 81 ),\n     DIKS_CUSTOM82                 = DFB_CUSTOM_KEY( 82 ),\n     DIKS_CUSTOM83                 = DFB_CUSTOM_KEY( 83 ),\n     DIKS_CUSTOM84                 = DFB_CUSTOM_KEY( 84 ),\n     DIKS_CUSTOM85                 = DFB_CUSTOM_KEY( 85 ),\n     DIKS_CUSTOM86                 = DFB_CUSTOM_KEY( 86 ),\n     DIKS_CUSTOM87                 = DFB_CUSTOM_KEY( 87 ),\n     DIKS_CUSTOM88                 = DFB_CUSTOM_KEY( 88 ),\n     DIKS_CUSTOM89                 = DFB_CUSTOM_KEY( 89 ),\n     DIKS_CUSTOM90                 = DFB_CUSTOM_KEY( 90 ),\n     DIKS_CUSTOM91                 = DFB_CUSTOM_KEY( 91 ),\n     DIKS_CUSTOM92                 = DFB_CUSTOM_KEY( 92 ),\n     DIKS_CUSTOM93                 = DFB_CUSTOM_KEY( 93 ),\n     DIKS_CUSTOM94                 = DFB_CUSTOM_KEY( 94 ),\n     DIKS_CUSTOM95                 = DFB_CUSTOM_KEY( 95 ),\n     DIKS_CUSTOM96                 = DFB_CUSTOM_KEY( 96 ),\n     DIKS_CUSTOM97                 = DFB_CUSTOM_KEY( 97 ),\n     DIKS_CUSTOM98                 = DFB_CUSTOM_KEY( 98 ),\n     DIKS_CUSTOM99                 = DFB_CUSTOM_KEY( 99 ),\n     DIKS_CUSTOM100                = DFB_CUSTOM_KEY( 100 ),\n     DIKS_CUSTOM101                = DFB_CUSTOM_KEY( 101 ),\n     DIKS_CUSTOM102                = DFB_CUSTOM_KEY( 102 ),\n     DIKS_CUSTOM103                = DFB_CUSTOM_KEY( 103 ),\n     DIKS_CUSTOM104                = DFB_CUSTOM_KEY( 104 ),\n     DIKS_CUSTOM105                = DFB_CUSTOM_KEY( 105 ),\n     DIKS_CUSTOM106                = DFB_CUSTOM_KEY( 106 ),\n     DIKS_CUSTOM107                = DFB_CUSTOM_KEY( 107 ),\n     DIKS_CUSTOM108                = DFB_CUSTOM_KEY( 108 ),\n     DIKS_CUSTOM109                = DFB_CUSTOM_KEY( 109 ),\n     DIKS_CUSTOM110                = DFB_CUSTOM_KEY( 110 ),\n     DIKS_CUSTOM111                = DFB_CUSTOM_KEY( 111 ),\n     DIKS_CUSTOM112                = DFB_CUSTOM_KEY( 112 ),\n     DIKS_CUSTOM113                = DFB_CUSTOM_KEY( 113 ),\n     DIKS_CUSTOM114                = DFB_CUSTOM_KEY( 114 ),\n     DIKS_CUSTOM115                = DFB_CUSTOM_KEY( 115 ),\n     DIKS_CUSTOM116                = DFB_CUSTOM_KEY( 116 ),\n     DIKS_CUSTOM117                = DFB_CUSTOM_KEY( 117 ),\n     DIKS_CUSTOM118                = DFB_CUSTOM_KEY( 118 ),\n     DIKS_CUSTOM119                = DFB_CUSTOM_KEY( 119 ),\n     DIKS_CUSTOM120                = DFB_CUSTOM_KEY( 120 ),\n     DIKS_CUSTOM121                = DFB_CUSTOM_KEY( 121 ),\n     DIKS_CUSTOM122                = DFB_CUSTOM_KEY( 122 ),\n     DIKS_CUSTOM123                = DFB_CUSTOM_KEY( 123 ),\n     DIKS_CUSTOM124                = DFB_CUSTOM_KEY( 124 ),\n     DIKS_CUSTOM125                = DFB_CUSTOM_KEY( 125 ),\n     DIKS_CUSTOM126                = DFB_CUSTOM_KEY( 126 ),\n     DIKS_CUSTOM127                = DFB_CUSTOM_KEY( 127 ),\n     DIKS_CUSTOM128                = DFB_CUSTOM_KEY( 128 ),\n     DIKS_CUSTOM129                = DFB_CUSTOM_KEY( 129 ),\n     DIKS_CUSTOM130                = DFB_CUSTOM_KEY( 130 ),\n     DIKS_CUSTOM131                = DFB_CUSTOM_KEY( 131 ),\n     DIKS_CUSTOM132                = DFB_CUSTOM_KEY( 132 ),\n     DIKS_CUSTOM133                = DFB_CUSTOM_KEY( 133 ),\n     DIKS_CUSTOM134                = DFB_CUSTOM_KEY( 134 ),\n     DIKS_CUSTOM135                = DFB_CUSTOM_KEY( 135 ),\n     DIKS_CUSTOM136                = DFB_CUSTOM_KEY( 136 ),\n     DIKS_CUSTOM137                = DFB_CUSTOM_KEY( 137 ),\n     DIKS_CUSTOM138                = DFB_CUSTOM_KEY( 138 ),\n     DIKS_CUSTOM139                = DFB_CUSTOM_KEY( 139 ),\n     DIKS_CUSTOM140                = DFB_CUSTOM_KEY( 140 ),\n     DIKS_CUSTOM141                = DFB_CUSTOM_KEY( 141 ),\n     DIKS_CUSTOM142                = DFB_CUSTOM_KEY( 142 ),\n     DIKS_CUSTOM143                = DFB_CUSTOM_KEY( 143 ),\n     DIKS_CUSTOM144                = DFB_CUSTOM_KEY( 144 ),\n     DIKS_CUSTOM145                = DFB_CUSTOM_KEY( 145 ),\n     DIKS_CUSTOM146                = DFB_CUSTOM_KEY( 146 ),\n     DIKS_CUSTOM147                = DFB_CUSTOM_KEY( 147 ),\n     DIKS_CUSTOM148                = DFB_CUSTOM_KEY( 148 ),\n     DIKS_CUSTOM149                = DFB_CUSTOM_KEY( 149 ),\n     DIKS_CUSTOM150                = DFB_CUSTOM_KEY( 150 ),\n     DIKS_CUSTOM151                = DFB_CUSTOM_KEY( 151 ),\n     DIKS_CUSTOM152                = DFB_CUSTOM_KEY( 152 ),\n     DIKS_CUSTOM153                = DFB_CUSTOM_KEY( 153 ),\n     DIKS_CUSTOM154                = DFB_CUSTOM_KEY( 154 ),\n     DIKS_CUSTOM155                = DFB_CUSTOM_KEY( 155 ),\n     DIKS_CUSTOM156                = DFB_CUSTOM_KEY( 156 ),\n     DIKS_CUSTOM157                = DFB_CUSTOM_KEY( 157 ),\n     DIKS_CUSTOM158                = DFB_CUSTOM_KEY( 158 ),\n     DIKS_CUSTOM159                = DFB_CUSTOM_KEY( 159 ),\n     DIKS_CUSTOM160                = DFB_CUSTOM_KEY( 160 ),\n     DIKS_CUSTOM161                = DFB_CUSTOM_KEY( 161 ),\n     DIKS_CUSTOM162                = DFB_CUSTOM_KEY( 162 ),\n     DIKS_CUSTOM163                = DFB_CUSTOM_KEY( 163 ),\n     DIKS_CUSTOM164                = DFB_CUSTOM_KEY( 164 ),\n     DIKS_CUSTOM165                = DFB_CUSTOM_KEY( 165 ),\n     DIKS_CUSTOM166                = DFB_CUSTOM_KEY( 166 ),\n     DIKS_CUSTOM167                = DFB_CUSTOM_KEY( 167 ),\n     DIKS_CUSTOM168                = DFB_CUSTOM_KEY( 168 ),\n     DIKS_CUSTOM169                = DFB_CUSTOM_KEY( 169 ),\n     DIKS_CUSTOM170                = DFB_CUSTOM_KEY( 170 ),\n     DIKS_CUSTOM171                = DFB_CUSTOM_KEY( 171 ),\n     DIKS_CUSTOM172                = DFB_CUSTOM_KEY( 172 ),\n     DIKS_CUSTOM173                = DFB_CUSTOM_KEY( 173 ),\n     DIKS_CUSTOM174                = DFB_CUSTOM_KEY( 174 ),\n     DIKS_CUSTOM175                = DFB_CUSTOM_KEY( 175 ),\n     DIKS_CUSTOM176                = DFB_CUSTOM_KEY( 176 ),\n     DIKS_CUSTOM177                = DFB_CUSTOM_KEY( 177 ),\n     DIKS_CUSTOM178                = DFB_CUSTOM_KEY( 178 ),\n     DIKS_CUSTOM179                = DFB_CUSTOM_KEY( 179 ),\n     DIKS_CUSTOM180                = DFB_CUSTOM_KEY( 180 ),\n     DIKS_CUSTOM181                = DFB_CUSTOM_KEY( 181 ),\n     DIKS_CUSTOM182                = DFB_CUSTOM_KEY( 182 ),\n     DIKS_CUSTOM183                = DFB_CUSTOM_KEY( 183 ),\n     DIKS_CUSTOM184                = DFB_CUSTOM_KEY( 184 ),\n     DIKS_CUSTOM185                = DFB_CUSTOM_KEY( 185 ),\n     DIKS_CUSTOM186                = DFB_CUSTOM_KEY( 186 ),\n     DIKS_CUSTOM187                = DFB_CUSTOM_KEY( 187 ),\n     DIKS_CUSTOM188                = DFB_CUSTOM_KEY( 188 ),\n     DIKS_CUSTOM189                = DFB_CUSTOM_KEY( 189 ),\n     DIKS_CUSTOM190                = DFB_CUSTOM_KEY( 190 ),\n     DIKS_CUSTOM191                = DFB_CUSTOM_KEY( 191 ),\n     DIKS_CUSTOM192                = DFB_CUSTOM_KEY( 192 ),\n     DIKS_CUSTOM193                = DFB_CUSTOM_KEY( 193 ),\n     DIKS_CUSTOM194                = DFB_CUSTOM_KEY( 194 ),\n     DIKS_CUSTOM195                = DFB_CUSTOM_KEY( 195 ),\n     DIKS_CUSTOM196                = DFB_CUSTOM_KEY( 196 ),\n     DIKS_CUSTOM197                = DFB_CUSTOM_KEY( 197 ),\n     DIKS_CUSTOM198                = DFB_CUSTOM_KEY( 198 ),\n     DIKS_CUSTOM199                = DFB_CUSTOM_KEY( 199 ),\n     DIKS_CUSTOM200                = DFB_CUSTOM_KEY( 200 ),\n     DIKS_CUSTOM201                = DFB_CUSTOM_KEY( 201 ),\n     DIKS_CUSTOM202                = DFB_CUSTOM_KEY( 202 ),\n     DIKS_CUSTOM203                = DFB_CUSTOM_KEY( 203 ),\n     DIKS_CUSTOM204                = DFB_CUSTOM_KEY( 204 ),\n     DIKS_CUSTOM205                = DFB_CUSTOM_KEY( 205 ),\n     DIKS_CUSTOM206                = DFB_CUSTOM_KEY( 206 ),\n     DIKS_CUSTOM207                = DFB_CUSTOM_KEY( 207 ),\n     DIKS_CUSTOM208                = DFB_CUSTOM_KEY( 208 ),\n     DIKS_CUSTOM209                = DFB_CUSTOM_KEY( 209 ),\n     DIKS_CUSTOM210                = DFB_CUSTOM_KEY( 210 ),\n     DIKS_CUSTOM211                = DFB_CUSTOM_KEY( 211 ),\n     DIKS_CUSTOM212                = DFB_CUSTOM_KEY( 212 ),\n     DIKS_CUSTOM213                = DFB_CUSTOM_KEY( 213 ),\n     DIKS_CUSTOM214                = DFB_CUSTOM_KEY( 214 ),\n     DIKS_CUSTOM215                = DFB_CUSTOM_KEY( 215 ),\n     DIKS_CUSTOM216                = DFB_CUSTOM_KEY( 216 ),\n     DIKS_CUSTOM217                = DFB_CUSTOM_KEY( 217 ),\n     DIKS_CUSTOM218                = DFB_CUSTOM_KEY( 218 ),\n     DIKS_CUSTOM219                = DFB_CUSTOM_KEY( 219 ),\n     DIKS_CUSTOM220                = DFB_CUSTOM_KEY( 220 ),\n     DIKS_CUSTOM221                = DFB_CUSTOM_KEY( 221 ),\n     DIKS_CUSTOM222                = DFB_CUSTOM_KEY( 222 ),\n     DIKS_CUSTOM223                = DFB_CUSTOM_KEY( 223 ),\n     DIKS_CUSTOM224                = DFB_CUSTOM_KEY( 224 ),\n     DIKS_CUSTOM225                = DFB_CUSTOM_KEY( 225 ),\n     DIKS_CUSTOM226                = DFB_CUSTOM_KEY( 226 ),\n     DIKS_CUSTOM227                = DFB_CUSTOM_KEY( 227 ),\n     DIKS_CUSTOM228                = DFB_CUSTOM_KEY( 228 ),\n     DIKS_CUSTOM229                = DFB_CUSTOM_KEY( 229 ),\n     DIKS_CUSTOM230                = DFB_CUSTOM_KEY( 230 ),\n     DIKS_CUSTOM231                = DFB_CUSTOM_KEY( 231 ),\n     DIKS_CUSTOM232                = DFB_CUSTOM_KEY( 232 ),\n     DIKS_CUSTOM233                = DFB_CUSTOM_KEY( 233 ),\n     DIKS_CUSTOM234                = DFB_CUSTOM_KEY( 234 ),\n     DIKS_CUSTOM235                = DFB_CUSTOM_KEY( 235 ),\n     DIKS_CUSTOM236                = DFB_CUSTOM_KEY( 236 ),\n     DIKS_CUSTOM237                = DFB_CUSTOM_KEY( 237 ),\n     DIKS_CUSTOM238                = DFB_CUSTOM_KEY( 238 ),\n     DIKS_CUSTOM239                = DFB_CUSTOM_KEY( 239 ),\n     DIKS_CUSTOM240                = DFB_CUSTOM_KEY( 240 ),\n     DIKS_CUSTOM241                = DFB_CUSTOM_KEY( 241 ),\n     DIKS_CUSTOM242                = DFB_CUSTOM_KEY( 242 ),\n     DIKS_CUSTOM243                = DFB_CUSTOM_KEY( 243 ),\n     DIKS_CUSTOM244                = DFB_CUSTOM_KEY( 244 ),\n     DIKS_CUSTOM245                = DFB_CUSTOM_KEY( 245 ),\n     DIKS_CUSTOM246                = DFB_CUSTOM_KEY( 246 ),\n     DIKS_CUSTOM247                = DFB_CUSTOM_KEY( 247 ),\n     DIKS_CUSTOM248                = DFB_CUSTOM_KEY( 248 ),\n     DIKS_CUSTOM249                = DFB_CUSTOM_KEY( 249 ),\n     DIKS_CUSTOM250                = DFB_CUSTOM_KEY( 250 ),\n     DIKS_CUSTOM251                = DFB_CUSTOM_KEY( 251 ),\n     DIKS_CUSTOM252                = DFB_CUSTOM_KEY( 252 ),\n     DIKS_CUSTOM253                = DFB_CUSTOM_KEY( 253 ),\n     DIKS_CUSTOM254                = DFB_CUSTOM_KEY( 254 ),\n     DIKS_CUSTOM255                = DFB_CUSTOM_KEY( 255 )\n} DFBInputDeviceKeySymbol;\n\n/*\n * Flags specifying the key locks that are currently active.\n */\ntypedef enum {\n     DILS_SCROLL                   = 0x00000001,                 /* scroll-lock active? */\n     DILS_NUM                      = 0x00000002,                 /* num-lock active? */\n     DILS_CAPS                     = 0x00000004                  /* caps-lock active? */\n} DFBInputDeviceLockState;\n\n/*\n * Groups and levels as an index to the symbol array.\n */\ntypedef enum {\n     DIKSI_BASE                    = 0x00000000,                 /* base group, base level (no modifier pressed) */\n     DIKSI_BASE_SHIFT              = 0x00000001,                 /* base group, shifted level (with Shift pressed) */\n     DIKSI_ALT                     = 0x00000002,                 /* alternative group, base level (with AltGr pressed) */\n     DIKSI_ALT_SHIFT               = 0x00000003,                 /* alternative group, shifted level (with AltGr and\n                                                                    Shift pressed) */\n     DIKSI_LAST                    = DIKSI_ALT_SHIFT\n} DFBInputDeviceKeymapSymbolIndex;\n\n/*\n * One entry in the keymap of an input device.\n */\ntypedef struct {\n     int                             code;                       /* hardware key code */\n     DFBInputDeviceLockState         locks;                      /* locks activating shifted level */\n     DFBInputDeviceKeyIdentifier     identifier;                 /* basic mapping */\n     DFBInputDeviceKeySymbol         symbols[DIKSI_LAST+1];      /* advanced key mapping */\n} DFBInputDeviceKeymapEntry;\n\n#endif\n"
  },
  {
    "path": "include/directfb_util.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECTFB_UTIL_H__\n#define __DIRECTFB_UTIL_H__\n\n#include <directfb.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**********************************************************************************************************************/\n\n/*\n * Adds the id to the bitmask of layer ids.\n */\n#define DFB_DISPLAYLAYER_IDS_ADD(ids,id)     (ids) |=  (1 << (id))\n\n/*\n * Removes the id from the bitmask of layer ids.\n */\n#define DFB_DISPLAYLAYER_IDS_REMOVE(ids,id)  (ids) &= ~(1 << (id))\n\n/*\n * Checks if the bitmask of layer ids contains the id.\n */\n#define DFB_DISPLAYLAYER_IDS_HAVE(ids,id)    ((ids) & (1 << (id)))\n\n/*\n * Empties (clears) the bitmask of layer ids.\n */\n#define DFB_DISPLAYLAYER_IDS_EMPTY(ids)      (ids) = 0\n\n/**********************************************************************************************************************/\n\n/*\n * Macro to compare two points.\n */\n#define DFB_POINT_EQUAL(a,b)      ((a).x == (b).x &&         \\\n                                   (a).y == (b).y)\n\n/*\n * Macro to compare two rectangles.\n */\n#define DFB_RECTANGLE_EQUAL(a,b)  ((a).x == (b).x &&         \\\n                                   (a).y == (b).y &&         \\\n                                   (a).w == (b).w &&         \\\n                                   (a).h == (b).h)\n\n/*\n * Macro to compare two locations.\n */\n#define DFB_LOCATION_EQUAL(a,b)   ((a).x == (b).x &&         \\\n                                   (a).y == (b).y &&         \\\n                                   (a).w == (b).w &&         \\\n                                   (a).h == (b).h)\n\n/*\n * Macro to compare two regions.\n */\n#define DFB_REGION_EQUAL(a,b)     ((a).x1 == (b).x1 &&       \\\n                                   (a).y1 == (b).y1 &&       \\\n                                   (a).x2 == (b).x2 &&       \\\n                                   (a).y2 == (b).y2)\n\n/*\n * Macro to compare two colors.\n */\n#define DFB_COLOR_EQUAL(x,y)      ((x).a == (y).a &&         \\\n                                   (x).r == (y).r &&         \\\n                                   (x).g == (y).g &&         \\\n                                   (x).b == (y).b)\n\n/*\n * Macro to compare two color keys.\n */\n#define DFB_COLORKEY_EQUAL(x,y)   ((x).index == (y).index && \\\n                                   (x).r == (y).r &&         \\\n                                   (x).g == (y).g &&         \\\n                                   (x).b == (y).b)\n\n/**********************************************************************************************************************/\n\nbool DIRECTFB_API dfb_region_rectangle_intersect          ( DFBRegion          *region,\n                                                            const DFBRectangle *rect );\n\nbool DIRECTFB_API dfb_unsafe_region_intersect             ( DFBRegion          *region,\n                                                            int                 x1,\n                                                            int                 y1,\n                                                            int                 x2,\n                                                            int                 y2 );\n\nbool DIRECTFB_API dfb_unsafe_region_rectangle_intersect   ( DFBRegion          *region,\n                                                            const DFBRectangle *rect );\n\nbool DIRECTFB_API dfb_rectangle_intersect_by_unsafe_region( DFBRectangle       *rectangle,\n                                                            DFBRegion          *region );\n\nbool DIRECTFB_API dfb_rectangle_intersect_by_region       ( DFBRectangle       *rectangle,\n                                                            const DFBRegion    *region );\n\nbool DIRECTFB_API dfb_rectangle_intersect                 ( DFBRectangle       *rectangle,\n                                                            const DFBRectangle *clip );\n\nvoid DIRECTFB_API dfb_rectangle_union                     ( DFBRectangle       *rect1,\n                                                            const DFBRectangle *rect2 );\n\n/**********************************************************************************************************************/\n\n#define DFB_RECTANGLE_CHECK(r)    \\\n      ((r) != NULL &&             \\\n       (r)->x1 <= (r)->x2 &&      \\\n       (r)->y1 <= (r)->y2)\n\n#define DFB_RECTANGLE_CHECK_IF(r) \\\n      ((r) == NULL ||             \\\n       ((r)->w >= 0 &&            \\\n        (r)->h >= 0))\n\n#define DFB_RECT_FORMAT                                \"%4d,%4d-%4dx%4d\"\n\n#define DFB_RECTANGLE_VALS(r)                          (r)->x, (r)->y, (r)->w, (r)->h\n\n#define DFB_RECTANGLE_EMPTY(r)                         ((r)->w == 0 || (r)->h == 0)\n#define DFB_RECTANGLE_FULL(r)                          (!DFB_RECTANGLE_EMPTY(r))\n\n#define DFB_RECTANGLE_VALS_FROM_DIMENSION(d)           0, 0, (d)->w, (d)->h\n#define DFB_RECTANGLE_INIT_FROM_DIMENSION(d)           (DFBRectangle) { DFB_RECTANGLE_VALS_FROM_DIMENSION(d) }\n\n#define DFB_RECTANGLE_VALS_FROM_DIMENSION_VALS(w,h)    0, 0, (w), (h)\n#define DFB_RECTANGLE_INIT_FROM_DIMENSION_VALS(w,h)    (DFBRectangle) { DFB_RECTANGLE_VALS_FROM_DIMENSION_VALS(w,h) }\n\n#define DFB_RECTANGLE_VALS_FROM_REGION(r)              (r)->x1, (r)->y1, (r)->x2-(r)->x1+1, (r)->y2-(r)->y1+1\n#define DFB_RECTANGLE_INIT_FROM_REGION(r)              (DFBRectangle) { DFB_RECTANGLE_VALS_FROM_REGION(r) }\n\n#define DFB_RECTANGLE_VALS_FROM_REGION_TRANSLATED \\\n                                              (r,x,y)  (r)->x1+(x), (r)->y1+(y), (r)->x2-(r)->x1+1, (r)->y2-(r)->y1+1\n#define DFB_RECTANGLE_INIT_FROM_REGION_TRANSLATED \\\n                                              (r,x,y)  (DFBRectangle) { DFB_RECTANGLE_VALS_FROM_REGION_TRANSLATED(r, \\\n                                                                                                                  x, \\\n                                                                                                                  y) }\n\n#define DFB_RECTANGLE_VALS_FROM_BOX(b)                 (b)->x1, (b)->y1, (b)->x2-(b)->x1, (b)->y2-(b)->y1\n#define DFB_RECTANGLE_INIT_FROM_BOX(b)                 (DFBRectangle) { DFB_RECTANGLE_VALS_FROM_BOX(b) }\n\n#define DFB_RECTANGLE_VALS_FROM_BOX_TRANSLATED(b,x,y)  (b)->x1+(x), (b)->y1+(y), (b)->x2-(b)->x1, (b)->y2-(b)->y1\n#define DFB_RECTANGLE_INIT_FROM_BOX_TRANSLATED(b,x,y)  (DFBRectangle) { DFB_RECTANGLE_VALS_FROM_BOX_TRANSLATED(b,x,y) }\n\n#define DFB_RECTANGLE_VALS_FROM_BOX_VALS(x1,y1,x2,y2)  (b)->x1, (b)->y1, (b)->x2-(b)->x1, (b)->y2-(b)->y1\n#define DFB_RECTANGLE_INIT_FROM_BOX_VALS(x1,y1,x2,y2)  (DFBRectangle) { DFB_RECTANGLE_VALS_FROM_BOX_VALS(x1,y1,x2,y2) }\n\n#define DFB_RECTANGLE_CONTAINS_POINT(r,X,Y)            (((X) >= (r)->x) && ((X) < (r)->x+(r)->w) && \\\n                                                        ((Y) >= (r)->y) && ((Y) < (r)->y+(r)->h))\n\n/**********************************************************************************************************************/\n\n#define DFB_REGION_CHECK(r)    \\\n      ((r) != NULL &&          \\\n       (r)->x1 <= (r)->x2 &&   \\\n       (r)->y1 <= (r)->y2)\n\n#define DFB_REGION_CHECK_IF(r) \\\n      ((r) == NULL ||          \\\n       ((r)->x1 <= (r)->x2 &&  \\\n        (r)->y1 <= (r)->y2))\n\n#define DFB_REGION_FORMAT                              \"%4d,%4d-%4d,%4d\"\n\n#define DFB_REGION_VALS(r)                             (r)->x1, (r)->y1, (r)->x2, (r)->y2\n\n#define DFB_REGION_VALS_FROM_DIMENSION(d)              0, 0, (d)->w-1, (d)->h-1\n#define DFB_REGION_INIT_FROM_DIMENSION(d)              (DFBRegion) { DFB_REGION_VALS_FROM_DIMENSION(d) }\n\n#define DFB_REGION_VALS_FROM_RECTANGLE(r)              (r)->x, (r)->y, (r)->x+(r)->w-1, (r)->y+(r)->h-1\n#define DFB_REGION_INIT_FROM_RECTANGLE(r)              (DFBRegion) { DFB_REGION_VALS_FROM_RECTANGLE(r) }\n\n#define DFB_REGION_VALS_FROM_RECTANGLE_VALS(x,y,w,h)   (x), (y), (x)+(w)-1, (y)+(h)-1\n#define DFB_REGION_INIT_FROM_RECTANGLE_VALS(x,y,w,h)   (DFBRegion) { DFB_REGION_VALS_FROM_RECTANGLE_VALS(x,y,w,h) }\n\n#define DFB_REGION_VALS_FROM_BOX(b)                    (b)->x1, (b)->y1, (b)->x2-1, (b)->y2-1\n#define DFB_REGION_INIT_FROM_BOX(b)                    (DFBRegion) { DFB_REGION_VALS_FROM_BOX(b) }\n\n#define DFB_REGION_VALS_TRANSLATED(r,x,y)              (r)->x1+x, (r)->y1+y, (r)->x2+x, (r)->y2+y\n#define DFB_REGION_INIT_TRANSLATED(r,x,y)              (DFBRegion) { DFB_REGION_VALS_TRANSLATED(r,x,y) }\n\n#define DFB_REGION_VALS_INTERSECTED(r,X1,Y1,X2,Y2)     (r)->x1 > (X1) ? (r)->x1 : (X1), \\\n                                                       (r)->y1 > (Y1) ? (r)->y1 : (Y1), \\\n                                                       (r)->x2 < (X2) ? (r)->x2 : (X2), \\\n                                                       (r)->y2 < (Y2) ? (r)->y2 : (Y2)\n#define DFB_REGION_INIT_INTERSECTED(r,X1,Y1,X2,Y2)     (DFBRegion) { DFB_REGION_VALS_INTERSECTED(r,X1,Y1,X2,Y2) }\n\n#define DFB_REGION_CONTAINS_POINT(r,X,Y)               (((X) >= (r)->x1) && ((X) <= (r)->x2) && \\\n                                                        ((Y) >= (r)->y1) && ((Y) <= (r)->y2))\n\n/**********************************************************************************************************************/\n\n#define DFB_BOX_CHECK(b)      \\\n      ((b) != NULL &&         \\\n       (b)->x1 <= (b)->x2 &&  \\\n       (b)->y1 <= (b)->y2)\n\n#define DFB_BOX_CHECK_IF(r)   \\\n      ((b) == NULL ||         \\\n       ((b)->x1 <= (b)->x2 && \\\n        (b)->y1 <= (b)->y2))\n\n#define DFB_BOX_VALS(b)                                (b)->x1, (b)->y1, (b)->x2, (b)->y2\n#define DFB_BOX_INIT(x1,y1,x2,y2)                      (DFBBox) { x1, y1, x2, y2 }\n\n#define DFB_BOX_WIDTH(b)                               ((b)->x2 - (b)->x1)\n#define DFB_BOX_HEIGHT(b)                              ((b)->y2 - (b)->y1)\n#define DFB_BOX_SIZE(b)                                (DFB_BOX_WIDTH(b) * DFB_BOX_HEIGHT(b))\n\n#define DFB_BOX_EQUAL(b1,b2)                           (((b1) == (b2)) ||                                \\\n                                                         ((b1)->x1 == (b2)->x1 &&                        \\\n                                                         (b1)->y1 == (b2)->y1 && (b1)->x2 == (b2)->x2 && \\\n                                                         (b1)->y2 == (b2)->y2))\n#define DFB_BOX_EMPTY(b)                               ((b)->x1 == (b)->x2 || (b)->y1 == (b)->y2)\n#define DFB_BOX_FULL(b)                                (!DFB_BOX_EMPTY(b))\n#define DFB_BOX_RESET(b)                               do { (b)->x2 = (b)->x1; (b)->y2 = (b)->y1; } while (0)\n\n#define DFB_BOX_VALS_FROM_DIMENSION(d)                 0, 0, (d)->w, (d)->h\n#define DFB_BOX_INIT_FROM_DIMENSION(d)                 (DFBBox) { DFB_BOX_VALS_FROM_DIMENSION(d) }\n\n#define DFB_BOX_VALS_FROM_DIMENSION_VALS(w,h)          0, 0, (w), (h)\n#define DFB_BOX_INIT_FROM_DIMENSION_VALS(w,h)          (DFBBox) { DFB_BOX_VALS_FROM_DIMENSION_VALS(w,h) }\n\n#define DFB_BOX_VALS_FROM_RECTANGLE(r)                 (r)->x, (r)->y, (r)->x+(r)->w, (r)->y+(r)->h\n#define DFB_BOX_INIT_FROM_RECTANGLE(r)                 (DFBBox) { DFB_BOX_VALS_FROM_RECTANGLE(r) }\n\n#define DFB_BOX_VALS_FROM_RECTANGLE_VALS(x,y,w,h)      (x), (y), (x)+(w), (y)+(h)\n#define DFB_BOX_INIT_FROM_RECTANGLE_VALS(X,Y,W,H)      (DFBBox) { DFB_BOX_VALS_FROM_RECTANGLE_VALS(X,Y,W,H) }\n\n#define DFB_BOX_VALS_FROM_REGION(r)                    (r)->x1, (r)->y1, (r)->x2+1, (r)->y2+1\n#define DFB_BOX_INIT_FROM_REGION(r)                    (DFBBox) { DFB_BOX_VALS_FROM_REGION(r) }\n\n#define DFB_BOX_VALS_TRANSLATED(b,x,y)                 (b)->x1+x, (b)->y1+y, (b)->x2+x, (b)->y2+y\n#define DFB_BOX_INIT_TRANSLATED(b,x,y)                 (DFBBox) { DFB_BOX_VALS_TRANSLATED(b,x,y) }\n\n#define DFB_BOX_VALS_AT_ZERO(b)                        0, 0, DFB_BOX_WIDTH(b), DFB_BOX_HEIGHT(b)\n#define DFB_BOX_INIT_AT_ZERO(b)                        (DFBBox) { DFB_BOX_VALS_AT_ZERO(b) }\n\n/**********************************************************************************************************************/\n\n#define DFB_DIMENSION_VALS(d)                          (d)->w, (d)->h\n#define DFB_DIMENSION_INIT(w,h)                        (DFBDimension) { w, h }\n\n#define DFB_DIMENSION_VALS_FROM_BOX(b)                 DFB_BOX_WIDTH(b), DFB_BOX_HEIGHT(b)\n#define DFB_DIMENSION_INIT_FROM_BOX(b)                 (DFBDimension) { DFB_DIMENSION_VALS_FROM_BOX(b) }\n\n/**********************************************************************************************************************/\n\n#define DFB_LINE_FORMAT                                \"%4d,%4d-%4d,%4d\"\n\n#define DFB_LINE_VALS(l)                               (l)->x1, (l)->y1, (l)->x2, (l)->y2\n\n/**********************************************************************************************************************/\n\n#define DFB_POINT_VALS(p)                              (p)->x, (p)->y\n#define DFB_POINT_INIT(x,y)                            (DFBPoint) { x, y }\n\n#define DFB_POINT_VALS_FROM_BOX(b)                     (b)->x1, (b)->y1\n#define DFB_POINT_INIT_FROM_BOX(b)                     (DFBPoint) { DFB_POINT_VALS_FROM_BOX(b) }\n\n/**********************************************************************************************************************/\n\n#define DFB_TRIANGLE_FORMAT                            \"%4d,%4d-%4d,%4d-%4d,%4d\"\n\n#define DFB_TRIANGLE_VALS(t)                           (t)->x1, (t)->y1, (t)->x2, (t)->y2, (t)->x3, (t)->y3\n#define DFB_TRIANGLE_INIT(x1,y1,x2,y2,x3,y3)           (DFBTriangle) { x1, y1, x2, y2, x3, y3 }\n\n/**********************************************************************************************************************/\n\n#define DFB_SPAN_VALS(s)                               (s)->x, (s)->w\n#define DFB_SPAN_INIT(x,w)                             (DFBSpan) { x, w }\n#define DFB_SPAN_VALS_AT(s,y)                          (s)->x, y, (s)->w\n\n/**********************************************************************************************************************/\n\n#define DFB_COLOR_FORMAT                               \"%02x %02x %02x %02x\"\n\n#define DFB_COLOR_VALS(c)                              (c)->a, (c)->r, (c)->g, (c)->b\n#define DFB_COLOR_INIT(a,r,g,b)                        (DFBColor) { a, r, g, b }\n\n/**********************************************************************************************************************/\n\n#define DFB_COLORKEY_VALS(c)                           (c)->r, (c)->g, (c)->b, (c)->index\n#define DFB_COLORKEY_INIT(r,g,b,index)                 (DFBColorKey) { r, g, b, index }\n\n/**********************************************************************************************************************/\n\n#if D_DEBUG_ENABLED\n\n#define DFB_RECTANGLE_ASSERT(r)                                                                          \\\n     do {                                                                                                \\\n          D_ASSERT( (r) != NULL );                                                                       \\\n          D_ASSERT( (r)->w >= 0 );                                                                       \\\n          D_ASSERT( (r)->h >= 0 );                                                                       \\\n     } while (0)\n\n#define DFB_RECTANGLE_ASSERT_IF(r)                                                                       \\\n     do {                                                                                                \\\n          if ((r) != NULL) {                                                                             \\\n               D_ASSERT( (r)->w >= 0 );                                                                  \\\n               D_ASSERT( (r)->h >= 0 );                                                                  \\\n          }                                                                                              \\\n     } while (0)\n\n#define DFB_REGION_ASSERT(r)                                                                             \\\n     do {                                                                                                \\\n          D_ASSERT( (r) != NULL );                                                                       \\\n          D_ASSERT( (r)->x1 <= (r)->x2 );                                                                \\\n          D_ASSERT( (r)->y1 <= (r)->y2 );                                                                \\\n     } while (0)\n\n#define DFB_REGION_ASSERT_IF(r)                                                                          \\\n     do {                                                                                                \\\n          if ((r) != NULL) {                                                                             \\\n               D_ASSERT( (r)->x1 <= (r)->x2 );                                                           \\\n               D_ASSERT( (r)->y1 <= (r)->y2 );                                                           \\\n          }                                                                                              \\\n     } while (0)\n\n#define DFB_BOX_ASSERT(b)                                                                                \\\n     do {                                                                                                \\\n          D_ASSERT( (b) != NULL );                                                                       \\\n          D_ASSERT( (b)->x1 <= (b)->x2 );                                                                \\\n          D_ASSERT( (b)->y1 <= (b)->y2 );                                                                \\\n     } while (0)\n\n#define DFB_BOX_ASSERT_IF(b)                                                                             \\\n     do {                                                                                                \\\n          if ((b) != NULL) {                                                                             \\\n               D_ASSERT( (b)->x1 <= (b)->x2 );                                                           \\\n               D_ASSERT( (b)->y1 <= (b)->y2 );                                                           \\\n          }                                                                                              \\\n     } while (0)\n\n#define DFB_RECTANGLES_DEBUG_AT(Domain,rects,num)                                                        \\\n     do {                                                                                                \\\n          unsigned int i;                                                                                \\\n                                                                                                         \\\n          for (i = 0; i < (num); i++)                                                                    \\\n               D_DEBUG_AT( Domain, \"  -> [%3u] %4d,%4d-%4dx%4d\\n\", i, DFB_RECTANGLE_VALS(&(rects)[i]) ); \\\n     } while (0)\n\n#define DFB_RECTANGLES2_DEBUG_AT(Domain,rects,rects2,num)                                                \\\n     do {                                                                                                \\\n          unsigned int i;                                                                                \\\n                                                                                                         \\\n          for (i = 0; i < (num); i++)                                                                    \\\n               D_DEBUG_AT( Domain, \"  -> [%3u] %4d,%4d-%4dx%4d <- %4d,%4d-%4dx%4d\\n\", i,                 \\\n                           DFB_RECTANGLE_VALS(&(rects)[i]), DFB_RECTANGLE_VALS(&(rects2)[i]) );          \\\n     } while (0)\n\n#define DFB_RECTANGLES_POINTS_DEBUG_AT(Domain,rects,points,num)                                          \\\n     do {                                                                                                \\\n          unsigned int i;                                                                                \\\n                                                                                                         \\\n          for (i = 0; i < (num); i++)                                                                    \\\n               D_DEBUG_AT( Domain, \"  -> [%3u] %4d,%4d-%4dx%4d <- %4d,%4d\\n\", i,                         \\\n                           DFB_RECTANGLE_VALS(&(rects)[i]), DFB_POINT_VALS(&(points)[i]) );              \\\n     } while (0)\n\n#define DFB_REGIONS_DEBUG_AT(Domain,regs,num)                                                            \\\n     do {                                                                                                \\\n          unsigned int i;                                                                                \\\n                                                                                                         \\\n          for (i = 0; i < (num); i++)                                                                    \\\n               D_DEBUG_AT( Domain, \"  -> [%3u] %4d,%4d-%4dx%4d\\n\", i,                                    \\\n                           DFB_RECTANGLE_VALS_FROM_REGION(&((regs)[i])) );                               \\\n     } while (0)\n\n#define DFB_BOXES_DEBUG_AT(Domain,boxes,num)                                                             \\\n     do {                                                                                                \\\n          unsigned int i;                                                                                \\\n                                                                                                         \\\n          for (i = 0; i < (num); i++)                                                                    \\\n               D_DEBUG_AT( Domain, \"  -> [%3u] %4d,%4d-%4dx%4d\\n\", i,                                    \\\n                      DFB_RECTANGLE_VALS_FROM_BOX(&(boxes)[i]) );                                        \\\n     } while (0)\n\n#define DFB_BOXES2_DEBUG_AT(Domain,boxes,boxes2,num)                                                     \\\n     do {                                                                                                \\\n          unsigned int i;                                                                                \\\n                                                                                                         \\\n          for (i = 0; i < (num); i++)                                                                    \\\n               D_DEBUG_AT( Domain, \"  -> [%3u] %4d,%4d-%4dx%4d <- %4d,%4d-%4dx%4d\\n\", i,                 \\\n                           DFB_RECTANGLE_VALS_FROM_BOX(&(boxes)[i]),                                     \\\n                           DFB_RECTANGLE_VALS_FROM_BOX(&(boxes2)[i]) );                                  \\\n     } while (0)\n\n#define DFB_LINES_DEBUG_AT(Domain,lines,num)                                                             \\\n     do {                                                                                                \\\n          unsigned int i;                                                                                \\\n                                                                                                         \\\n          for (i = 0; i < (num); i++)                                                                    \\\n               D_DEBUG_AT( Domain, \"  -> [%3u] %4d,%4d-%4d,%4d\\n\", i, DFB_LINE_VALS(&(lines)[i]) );      \\\n     } while (0)\n\n#define DFB_POINTS_DEBUG_AT(Domain,points,num)                                                           \\\n     do {                                                                                                \\\n          unsigned int i;                                                                                \\\n                                                                                                         \\\n          for (i = 0; i < (num); i++)                                                                    \\\n               D_DEBUG_AT( Domain, \"  -> [%3u] %4d,%4d\\n\", i, DFB_POINT_VALS(&(points)[i]) );            \\\n     } while (0)\n\n#define DFB_TRIANGLES_DEBUG_AT(Domain,tris,num)                                                          \\\n     do {                                                                                                \\\n          unsigned int i;                                                                                \\\n                                                                                                         \\\n          for (i = 0; i < (num); i++)                                                                    \\\n               D_DEBUG_AT( Domain, \"  -> [%3u] %4d,%4d-%4d,%4d-%4d,%4d\\n\", i,                            \\\n                           DFB_TRIANGLE_VALS(&(tris)[i]) );\\\n     } while (0)\n\n#define DFB_SPANS_DEBUG_AT(Domain,spans,num,y)                                                           \\\n     do {                                                                                                \\\n          unsigned int i;                                                                                \\\n                                                                                                         \\\n          for (i = 0; i < (num); i++)                                                                    \\\n               D_DEBUG_AT( Domain, \"  -> [%3u] %4d,%4d-%4d\\n\", i, DFB_SPAN_VALS_AT(&(spans)[i],y+i) );   \\\n     } while (0)\n\n#else\n\n#define DFB_RECTANGLE_ASSERT(r)                                                                          \\\n     do {                                                                                                \\\n     } while (0)\n\n#define DFB_RECTANGLE_ASSERT_IF(r)                                                                       \\\n     do {                                                                                                \\\n     } while (0)\n\n#define DFB_REGION_ASSERT(r)                                                                             \\\n     do {                                                                                                \\\n     } while (0)\n\n#define DFB_REGION_ASSERT_IF(r)                                                                          \\\n     do {                                                                                                \\\n     } while (0)\n\n#define DFB_BOX_ASSERT(b)                                                                                \\\n     do {                                                                                                \\\n     } while (0)\n\n#define DFB_BOX_ASSERT_IF(b)                                                                             \\\n     do {                                                                                                \\\n     } while (0)\n\n#define DFB_RECTANGLES_DEBUG_AT(Domain,rects,num)                                                        \\\n     do {                                                                                                \\\n     } while (0)\n\n#define DFB_RECTANGLES2_DEBUG_AT(Domain,rects,rects2,num)                                                \\\n     do {                                                                                                \\\n     } while (0)\n\n#define DFB_RECTANGLES_POINTS_DEBUG_AT(Domain,rects,points,num)                                          \\\n     do {                                                                                                \\\n     } while (0)\n\n#define DFB_REGIONS_DEBUG_AT(Domain,regs,num)                                                            \\\n     do {                                                                                                \\\n     } while (0)\n\n#define DFB_BOXES_DEBUG_AT(Domain,boxes,num)                                                             \\\n     do {                                                                                                \\\n     } while (0)\n\n#define DFB_BOXES2_DEBUG_AT(Domain,boxes,boxes2,num)                                                     \\\n     do {                                                                                                \\\n     } while (0)\n\n#define DFB_LINES_DEBUG_AT(Domain,lines,num)                                                             \\\n     do {                                                                                                \\\n     } while (0)\n\n#define DFB_POINTS_DEBUG_AT(Domain,points,num)                                                           \\\n     do {                                                                                                \\\n     } while (0)\n\n#define DFB_TRIANGLES_DEBUG_AT(Domain,tris,num)                                                          \\\n     do {                                                                                                \\\n     } while (0)\n\n#define DFB_SPANS_DEBUG_AT(Domain,spans,num,y)                                                           \\\n     do {                                                                                                \\\n     } while (0)\n\n#endif\n\n/**********************************************************************************************************************/\n\nstatic __inline__ void\ndfb_rectangle_from_region( DFBRectangle    *rect,\n                           const DFBRegion *region )\n{\n     D_ASSERT( rect != NULL );\n     DFB_REGION_ASSERT( region );\n\n     rect->x = region->x1;\n     rect->y = region->y1;\n     rect->w = region->x2 - region->x1 + 1;\n     rect->h = region->y2 - region->y1 + 1;\n}\n\nstatic __inline__ void\ndfb_rectangle_from_box( DFBRectangle *rect,\n                        const DFBBox *box )\n{\n     D_ASSERT( rect != NULL );\n     DFB_BOX_ASSERT( box );\n\n     rect->x = box->x1;\n     rect->y = box->y1;\n     rect->w = box->x2 - box->x1;\n     rect->h = box->y2 - box->y1;\n}\n\nstatic __inline__ void\ndfb_rectangle_from_rectangle_plus_insets( DFBRectangle       *rect,\n                                          const DFBRectangle *inner,\n                                          const DFBInsets    *insets )\n{\n     D_ASSERT( rect != NULL );\n     DFB_RECTANGLE_ASSERT( inner );\n     D_ASSERT( insets != NULL );\n\n     rect->x = inner->x - insets->l;\n     rect->y = inner->y - insets->t;\n     rect->w = inner->w + insets->l + insets->r;\n     rect->h = inner->h + insets->t + insets->b;\n}\n\nstatic __inline__ void\ndfb_rectangle_from_rotated( DFBRectangle       *rectangle,\n                            const DFBRectangle *from,\n                            const DFBDimension *size,\n                            int                 rotation )\n{\n     D_ASSERT( rectangle != NULL );\n     DFB_RECTANGLE_ASSERT( from );\n     D_ASSERT( size != NULL );\n     D_ASSERT( size->w > 0 );\n     D_ASSERT( size->h > 0 );\n\n     D_ASSUME( rotation == 0 || rotation == 90 || rotation == 180 || rotation == 270 );\n\n     switch (rotation) {\n          default:\n               D_BUG( \"invalid rotation %d\", rotation );\n          case 0:\n               *rectangle = *from;\n               break;\n\n          case 90:\n               rectangle->x = from->y;\n               rectangle->y = size->w - from->x - from->w;\n               rectangle->w = from->h;\n               rectangle->h = from->w;\n               break;\n\n          case 180:\n               rectangle->x = size->w - from->x - from->w;\n               rectangle->y = size->h - from->y - from->h;\n               rectangle->w = from->w;\n               rectangle->h = from->h;\n               break;\n\n          case 270:\n               rectangle->x = size->h - from->y - from->h;\n               rectangle->y = from->x;\n               rectangle->w = from->h;\n               rectangle->h = from->w;\n               break;\n     }\n}\n\nstatic __inline__ void\ndfb_rectangle_translate( DFBRectangle *rect,\n                         int           dx,\n                         int           dy )\n{\n     DFB_RECTANGLE_ASSERT( rect );\n\n     rect->x += dx;\n     rect->y += dy;\n}\n\nstatic __inline__ void\ndfb_rectangle_resize( DFBRectangle *rect,\n                      int           width,\n                      int           height )\n{\n     DFB_RECTANGLE_ASSERT( rect );\n     D_ASSERT( width >= 0 );\n     D_ASSERT( height >= 0 );\n\n     rect->w = width;\n     rect->h = height;\n}\n\nstatic __inline__ bool\ndfb_rectangle_region_intersects( const DFBRectangle *rect,\n                                 const DFBRegion    *region )\n{\n     DFB_RECTANGLE_ASSERT( rect );\n     DFB_REGION_ASSERT( region );\n\n     return (rect->x <= region->x2          &&\n             rect->y <= region->y2          &&\n             rect->x + rect->w > region->x1 &&\n             rect->y + rect->h > region->y1);\n}\n\nstatic __inline__ bool\ndfb_rectangle_box_intersect( DFBRectangle *rect,\n                             const DFBBox *box )\n{\n     DFB_RECTANGLE_ASSERT( rect );\n     DFB_BOX_ASSERT( box );\n\n     if (DFB_BOX_EMPTY( box )         ||\n         box->x2 <= rect->x           ||\n         box->y2 <= rect->y           ||\n         box->x1 >= rect->x + rect->w ||\n         box->y1 >= rect->y + rect->h)\n     {\n          rect->w = rect->h = 0;\n\n          return false;\n     }\n\n     if (rect->x < box->x1) {\n          rect->w -= box->x1 - rect->x;\n          rect->x  = box->x1;\n     }\n\n     if (rect->y < box->y1) {\n          rect->h -= box->y1 - rect->y;\n          rect->y  = box->y1;\n     }\n\n     if (rect->x + rect->w > box->x2)\n          rect->w = box->x2 - rect->x;\n\n     if (rect->y + rect->h > box->y2)\n          rect->h = box->y2 - rect->y;\n\n     return true;\n}\n\nstatic __inline__ void\ndfb_rectangle_subtract( DFBRectangle    *rect,\n                        const DFBInsets *insets )\n{\n     D_ASSERT( rect != NULL );\n     D_ASSERT( insets != NULL );\n\n     rect->x += insets->l;\n     rect->y += insets->t;\n     rect->w -= insets->l + insets->r;\n     rect->h -= insets->t + insets->b;\n\n     if (rect->w <= 0 || rect->h <= 0)\n          rect->w = rect->h = 0;\n}\n\n/**********************************************************************************************************************/\n\nstatic __inline__ void\ndfb_region_from_rectangle( DFBRegion          *region,\n                           const DFBRectangle *rect )\n{\n     D_ASSERT( region != NULL );\n     DFB_RECTANGLE_ASSERT( rect );\n     D_ASSERT( rect->w > 0 );\n     D_ASSERT( rect->h > 0 );\n\n     region->x1 = rect->x;\n     region->y1 = rect->y;\n     region->x2 = rect->x + rect->w - 1;\n     region->y2 = rect->y + rect->h - 1;\n}\n\nstatic __inline__ void\ndfb_region_from_rectangle_translated( DFBRegion          *region,\n                                      const DFBRectangle *rect,\n                                      const DFBPoint     *offset )\n{\n     D_ASSERT( region != NULL );\n     D_ASSERT( offset != NULL );\n     DFB_RECTANGLE_ASSERT( rect );\n     D_ASSERT( rect->w > 0 );\n     D_ASSERT( rect->h > 0 );\n\n     region->x1 = offset->x + rect->x;\n     region->y1 = offset->y + rect->y;\n     region->x2 = offset->x + rect->x + rect->w - 1;\n     region->y2 = offset->y + rect->y + rect->h - 1;\n}\n\nstatic __inline__ void\ndfb_region_from_rotated( DFBRegion          *region,\n                         const DFBRegion    *from,\n                         const DFBDimension *size,\n                         int                 rotation )\n{\n     D_ASSERT( region != NULL );\n     DFB_REGION_ASSERT( from );\n     D_ASSERT( size != NULL );\n     D_ASSERT( size->w > 0 );\n     D_ASSERT( size->h > 0 );\n\n     D_ASSUME( rotation == 0 || rotation == 90 || rotation == 180 || rotation == 270 );\n\n     switch (rotation) {\n          default:\n               D_BUG( \"invalid rotation %d\", rotation );\n          case 0:\n               *region = *from;\n               break;\n\n          case 90:\n               region->x1 = from->y1;\n               region->y1 = size->w - from->x2 - 1;\n               region->x2 = from->y2;\n               region->y2 = size->w - from->x1 - 1;\n               break;\n\n          case 180:\n               region->x1 = size->w - from->x2 - 1;\n               region->y1 = size->h - from->y2 - 1;\n               region->x2 = size->w - from->x1 - 1;\n               region->y2 = size->h - from->y1 - 1;\n               break;\n\n          case 270:\n               region->x1 = size->h - from->y2 - 1;\n               region->y1 = from->x1;\n               region->x2 = size->h - from->y1 - 1;\n               region->y2 = from->x2;\n               break;\n     }\n}\n\nstatic __inline__ void\ndfb_region_translate( DFBRegion *region,\n                      int        dx,\n                      int        dy )\n{\n     D_ASSERT( region != NULL );\n\n     region->x1 += dx;\n     region->y1 += dy;\n     region->x2 += dx;\n     region->y2 += dy;\n}\n\nstatic __inline__ void\ndfb_region_resize( DFBRegion *region,\n                   int        width,\n                   int        height )\n{\n     D_ASSERT( region != NULL );\n     D_ASSERT( width >= 0 );\n     D_ASSERT( height >= 0 );\n\n     region->x2 = region->x1 + width - 1;\n     region->y2 = region->y1 + height - 1;\n}\n\nstatic __inline__ bool\ndfb_region_intersects( const DFBRegion *region,\n                       int              x1,\n                       int              y1,\n                       int              x2,\n                       int              y2 )\n{\n     D_ASSERT( region != NULL );\n     D_ASSERT( x1 <= x2 );\n     D_ASSERT( y1 <= y2 );\n\n     return (region->x1 <= x2 &&\n             region->y1 <= y2 &&\n             region->x2 >= x1 &&\n             region->y2 >= y1);\n}\n\nstatic __inline__ bool\ndfb_region_region_intersects( const DFBRegion *region,\n                              const DFBRegion *other )\n{\n     DFB_REGION_ASSERT( region );\n     DFB_REGION_ASSERT( other );\n\n     return (region->x1 <= other->x2 &&\n             region->y1 <= other->y2 &&\n             region->x2 >= other->x1 &&\n             region->y2 >= other->y1);\n}\n\nstatic __inline__ bool\ndfb_region_intersect( DFBRegion *region,\n                      int        x1,\n                      int        y1,\n                      int        x2,\n                      int        y2 )\n{\n     D_ASSERT( region != NULL );\n\n     if (region->x2 < x1 ||\n         region->y2 < y1 ||\n         region->x1 > x2 ||\n         region->y1 > y2)\n          return false;\n\n     if (region->x1 < x1)\n          region->x1 = x1;\n\n     if (region->y1 < y1)\n          region->y1 = y1;\n\n     if (region->x2 > x2)\n          region->x2 = x2;\n\n     if (region->y2 > y2)\n          region->y2 = y2;\n\n     return true;\n}\n\nstatic __inline__ bool\ndfb_region_region_intersect( DFBRegion       *region,\n                             const DFBRegion *clip )\n{\n     D_ASSERT( region != NULL );\n\n     if (region->x2 < clip->x1 ||\n         region->y2 < clip->y1 ||\n         region->x1 > clip->x2 ||\n         region->y1 > clip->y2)\n          return false;\n\n     if (region->x1 < clip->x1)\n          region->x1 = clip->x1;\n\n     if (region->y1 < clip->y1)\n          region->y1 = clip->y1;\n\n     if (region->x2 > clip->x2)\n          region->x2 = clip->x2;\n\n     if (region->y2 > clip->y2)\n          region->y2 = clip->y2;\n\n     return true;\n}\n\nstatic __inline__ bool\ndfb_region_region_contains( const DFBRegion *a,\n                            const DFBRegion *b )\n{\n     D_ASSERT( a != NULL );\n     D_ASSERT( b != NULL );\n\n     if (a->x1 > b->x1)\n          return false;\n\n     if (a->y1 > b->y1)\n          return false;\n\n     if (a->x2 < b->x2)\n          return false;\n\n     if (a->y2 < b->y2)\n          return false;\n\n     return true;\n}\n\nstatic __inline__ bool\ndfb_region_region_extends( const DFBRegion *a,\n                           const DFBRegion *b )\n{\n     if (a->x1 == b->x1 && a->x2 == b->x2)\n          return (a->y1 == b->y2 - 1) || (a->y2 == b->y1 - 1);\n\n     if (a->y1 == b->y1 && a->y2 == b->y2)\n          return (a->x1 == b->x2 - 1) || (a->x2 == b->x1 - 1);\n\n     return false;\n}\n\nstatic __inline__ void\ndfb_region_region_union( DFBRegion       *region,\n                         const DFBRegion *other )\n{\n     DFB_REGION_ASSERT( region );\n     DFB_REGION_ASSERT( other );\n\n     if (region->x1 > other->x1)\n          region->x1 = other->x1;\n\n     if (region->y1 > other->y1)\n          region->y1 = other->y1;\n\n     if (region->x2 < other->x2)\n          region->x2 = other->x2;\n\n     if (region->y2 < other->y2)\n          region->y2 = other->y2;\n}\n\nstatic __inline__ void\ndfb_region_clip( DFBRegion *region,\n                 int        x1,\n                 int        y1,\n                 int        x2,\n                 int        y2 )\n{\n     DFB_REGION_ASSERT( region );\n     D_ASSERT( dfb_region_intersects( region, x1, y1, x2, y2 ) );\n\n     if (region->x1 < x1)\n          region->x1 = x1;\n\n     if (region->y1 < y1)\n          region->y1 = y1;\n\n     if (region->x2 > x2)\n          region->x2 = x2;\n\n     if (region->y2 > y2)\n          region->y2 = y2;\n}\n\nstatic __inline__ void\ndfb_regions_unite( DFBRegion       *united,\n                   const DFBRegion *regions,\n                   unsigned int     num_regions )\n{\n     unsigned int i;\n\n     D_ASSERT( united != NULL );\n     D_ASSERT( regions != NULL );\n     D_ASSERT( num_regions > 0 );\n\n     *united = regions[0];\n\n     for (i = 1; i < num_regions; i++) {\n          DFB_REGION_ASSERT( &regions[i] );\n\n          dfb_region_region_union( united, &regions[i] );\n     }\n}\n\n/**********************************************************************************************************************/\n\nstatic __inline__ void\ndfb_box_from_rectangle( DFBBox             *box,\n                        const DFBRectangle *rect )\n{\n     D_ASSERT( box != NULL );\n     DFB_RECTANGLE_ASSERT( rect );\n\n     box->x1 = rect->x;\n     box->y1 = rect->y;\n     box->x2 = rect->x + rect->w;\n     box->y2 = rect->y + rect->h;\n}\n\nstatic __inline__ void\ndfb_box_from_rectangle_translated( DFBBox             *box,\n                                   const DFBRectangle *rect,\n                                   const DFBPoint     *offset )\n{\n     D_ASSERT( box != NULL );\n     DFB_RECTANGLE_ASSERT( rect );\n     D_ASSERT( offset != NULL );\n\n     box->x1 = offset->x + rect->x;\n     box->y1 = offset->y + rect->y;\n     box->x2 = offset->x + rect->x + rect->w;\n     box->y2 = offset->y + rect->y + rect->h;\n}\n\nstatic __inline__ void\ndfb_box_from_rotated( DFBBox             *box,\n                      const DFBBox       *from,\n                      const DFBDimension *size,\n                      int                 rotation )\n{\n     D_ASSERT( box != NULL );\n     DFB_BOX_ASSERT( from );\n     D_ASSERT( size != NULL );\n     D_ASSERT( size->w > 0 );\n     D_ASSERT( size->h > 0 );\n\n     D_ASSUME( rotation == 0 || rotation == 90 || rotation == 180 || rotation == 270 );\n\n     switch (rotation) {\n          default:\n               D_BUG( \"invalid rotation %d\", rotation );\n          case 0:\n               *box = *from;\n               break;\n\n          case 90:\n               box->x1 = from->y1;\n               box->y1 = size->w - from->x2;\n               box->x2 = from->y2;\n               box->y2 = size->w - from->x1;\n               break;\n\n          case 180:\n               box->x1 = size->w - from->x2;\n               box->y1 = size->h - from->y2;\n               box->x2 = size->w - from->x1;\n               box->y2 = size->h - from->y1;\n               break;\n\n          case 270:\n               box->x1 = size->h - from->y2;\n               box->y1 = from->x1;\n               box->x2 = size->h - from->y1;\n               box->y2 = from->x2;\n               break;\n     }\n}\n\nstatic __inline__ void\ndfb_box_translate( DFBBox *box,\n                   int     dx,\n                   int     dy )\n{\n     D_ASSERT( box != NULL );\n\n     box->x1 += dx;\n     box->y1 += dy;\n     box->x2 += dx;\n     box->y2 += dy;\n}\n\nstatic __inline__ void\ndfb_box_resize( DFBBox *box,\n                int     width,\n                int     height )\n{\n     D_ASSERT( box != NULL );\n     D_ASSERT( width >= 0 );\n     D_ASSERT( height >= 0 );\n\n     box->x2 = box->x1 + width;\n     box->y2 = box->y1 + height;\n}\n\nstatic __inline__ bool\ndfb_box_box_contains( const DFBBox *a,\n                      const DFBBox *b )\n{\n     D_ASSERT( a != NULL );\n     D_ASSERT( b != NULL );\n\n     if (a->x1 > b->x1)\n          return false;\n\n     if (a->y1 > b->y1)\n          return false;\n\n     if (a->x2 < b->x2)\n          return false;\n\n     if (a->y2 < b->y2)\n          return false;\n\n     return true;\n}\n\nstatic __inline__ bool\ndfb_box_intersects( const DFBBox *box,\n                    int           x1,\n                    int           y1,\n                    int           x2,\n                    int           y2 )\n{\n     DFB_BOX_ASSERT( box );\n     D_ASSERT( x1 <= x2 );\n     D_ASSERT( y1 <= y2 );\n\n     return (box->x1 < x2 &&\n             box->y1 < y2 &&\n             box->x2 > x1 &&\n             box->y2 > y1);\n}\n\nstatic __inline__ bool\ndfb_box_box_intersects( const DFBBox *box,\n                        const DFBBox *other )\n{\n     DFB_BOX_ASSERT( box );\n     DFB_BOX_ASSERT( other );\n\n     return (box->x1 < other->x2 &&\n             box->y1 < other->y2 &&\n             box->x2 > other->x1 &&\n             box->y2 > other->y1);\n}\n\nstatic __inline__ bool\ndfb_box_intersect( DFBBox *box,\n                   int     x1,\n                   int     y1,\n                   int     x2,\n                   int     y2 )\n{\n     DFB_BOX_ASSERT( box );\n     D_ASSERT( x1 <= x2 );\n     D_ASSERT( y1 <= y2 );\n\n     if (DFB_BOX_EMPTY( box ))\n          return false;\n\n     if (box->x2 <= x1 ||\n         box->y2 <= y1 ||\n         box->x1 >= x2 ||\n         box->y1 >= y2)\n          return false;\n\n     if (box->x1 < x1)\n          box->x1 = x1;\n\n     if (box->y1 < y1)\n          box->y1 = y1;\n\n     if (box->x2 > x2)\n          box->x2 = x2;\n\n     if (box->y2 > y2)\n          box->y2 = y2;\n\n     return true;\n}\n\nstatic __inline__ bool\ndfb_box_box_intersect( DFBBox       *box,\n                       const DFBBox *clip )\n{\n     DFB_BOX_ASSERT( box );\n     DFB_BOX_ASSERT( clip );\n\n     if (DFB_BOX_EMPTY( box ))\n          return false;\n\n     if (DFB_BOX_EMPTY( clip ) ||\n         box->x2 <= clip->x1 ||\n         box->y2 <= clip->y1 ||\n         box->x1 >= clip->x2 ||\n         box->y1 >= clip->y2)\n     {\n          return false;\n     }\n\n     if (box->x1 < clip->x1)\n          box->x1 = clip->x1;\n\n     if (box->y1 < clip->y1)\n          box->y1 = clip->y1;\n\n     if (box->x2 > clip->x2)\n          box->x2 = clip->x2;\n\n     if (box->y2 > clip->y2)\n          box->y2 = clip->y2;\n\n     return true;\n}\n\nstatic __inline__ bool\ndfb_box_region_intersects( const DFBBox    *box,\n                           const DFBRegion *clip )\n{\n     DFB_BOX_ASSERT( box );\n     D_ASSERT( clip != NULL );\n\n     if (DFB_BOX_EMPTY( box ))\n          return false;\n\n     if (clip->x1 > clip->x2 ||\n         clip->y1 > clip->y2 ||\n         box->x2 <= clip->x1 ||\n         box->y2 <= clip->y1 ||\n         box->x1 > clip->x2 ||\n         box->y1 > clip->y2)\n     {\n          return false;\n     }\n\n     return true;\n}\n\nstatic __inline__ bool\ndfb_box_region_intersect( DFBBox          *box,\n                          const DFBRegion *clip )\n{\n     DFB_BOX_ASSERT( box );\n     D_ASSERT( clip != NULL );\n\n     if (DFB_BOX_EMPTY( box ))\n          return false;\n\n     if (clip->x1 > clip->x2 ||\n         clip->y1 > clip->y2 ||\n         box->x2 <= clip->x1 ||\n         box->y2 <= clip->y1 ||\n         box->x1 > clip->x2 ||\n         box->y1 > clip->y2)\n     {\n          box->x2 = box->x1;\n          box->y2 = box->y1;\n\n          return false;\n     }\n\n     if (box->x1 < clip->x1)\n          box->x1 = clip->x1;\n\n     if (box->y1 < clip->y1)\n          box->y1 = clip->y1;\n\n     if (box->x2 > clip->x2 + 1)\n          box->x2 = clip->x2 + 1;\n\n     if (box->y2 > clip->y2 + 1)\n          box->y2 = clip->y2 + 1;\n\n     return true;\n}\n\nstatic __inline__ bool\ndfb_box_box_extends( const DFBBox *a,\n                     const DFBBox *b )\n{\n     DFB_BOX_ASSERT( a );\n     DFB_BOX_ASSERT( b );\n\n     if (a->x1 == b->x1 && a->x2 == b->x2)\n          return (a->y1 == b->y2) || (a->y2 == b->y1);\n\n     if (a->y1 == b->y1 && a->y2 == b->y2)\n          return (a->x1 == b->x2) || (a->x2 == b->x1);\n\n     return false;\n}\n\nstatic __inline__ void\ndfb_box_box_union( DFBBox       *box,\n                   const DFBBox *other )\n{\n     DFB_BOX_ASSERT( box );\n     DFB_BOX_ASSERT( other );\n\n     if (DFB_BOX_EMPTY( other ))\n          return;\n\n     if (DFB_BOX_EMPTY( box )) {\n          *box = *other;\n     }\n     else {\n          if (box->x1 > other->x1)\n               box->x1 = other->x1;\n\n          if (box->y1 > other->y1)\n               box->y1 = other->y1;\n\n          if (box->x2 < other->x2)\n               box->x2 = other->x2;\n\n          if (box->y2 < other->y2)\n               box->y2 = other->y2;\n     }\n}\n\nstatic __inline__ void\ndfb_box_region_union( DFBBox          *box,\n                      const DFBRegion *region )\n{\n     DFB_BOX_ASSERT( box );\n     DFB_REGION_ASSERT( region );\n\n     if (DFB_BOX_EMPTY( box )) {\n          box->x1 = region->x1;\n          box->y1 = region->y1;\n          box->x2 = region->x2 + 1;\n          box->y2 = region->y2 + 1;\n     }\n     else {\n          if (box->x1 > region->x1)\n               box->x1 = region->x1;\n\n          if (box->y1 > region->y1)\n               box->y1 = region->y1;\n\n          if (box->x2 < region->x2 + 1)\n               box->x2 = region->x2 + 1;\n\n          if (box->y2 < region->y2 + 1)\n               box->y2 = region->y2 + 1;\n     }\n}\n\nstatic __inline__ void\ndfb_box_clip( DFBBox *box,\n              int     x1,\n              int     y1,\n              int     x2,\n              int     y2 )\n{\n     DFB_BOX_ASSERT( box );\n     D_ASSERT( dfb_box_intersects( box, x1, y1, x2, y2 ) );\n\n     if (box->x1 < x1)\n          box->x1 = x1;\n\n     if (box->y1 < y1)\n          box->y1 = y1;\n\n     if (box->x2 > x2)\n          box->x2 = x2;\n\n     if (box->y2 > y2)\n          box->y2 = y2;\n}\n\n/**********************************************************************************************************************/\n\n/*\n * Compute line segment intersection. Return true if intersection point exists within the given segment.\n */\nstatic __inline__ bool\ndfb_line_segment_intersect( const DFBRegion *line,\n                            const DFBRegion *seg,\n                            int             *x,\n                            int             *y )\n{\n     int x1, x2, x3, x4;\n     int y1, y2, y3, y4;\n     int num, den;\n\n     D_ASSERT( line != NULL );\n     D_ASSERT( seg != NULL );\n\n     x1 = seg->x1;  y1 = seg->y1;  x2 = seg->y2;  y2 = seg->y2;\n     x3 = line->x1; y3 = line->y1; x4 = line->x2; y4 = line->y2;\n\n     num = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);\n     den = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);\n\n     if (!den) /* parallel */\n          return false;\n\n     if (num && ((num < 0) != (den < 0) || abs(num) > abs(den))) /* not within segment */\n          return false;\n\n     if (x)\n          *x = (s64) (x2 - x1) * num / den + x1;\n     if (y)\n          *y = (s64) (y2 - y1) * num / den + y1;\n\n     return true;\n}\n\n/**********************************************************************************************************************/\n\nstatic __inline__ void\ndfb_point_from_rotated_region( DFBPoint           *point,\n                               const DFBRegion    *from,\n                               const DFBDimension *size,\n                               int                 rotation )\n{\n     D_ASSERT( point != NULL );\n     DFB_REGION_ASSERT( from );\n     D_ASSERT( size != NULL );\n     D_ASSERT( size->w > 0 );\n     D_ASSERT( size->h > 0 );\n\n     D_ASSUME( rotation == 0 || rotation == 90 || rotation == 180 || rotation == 270 );\n\n     switch (rotation) {\n          default:\n               D_BUG( \"invalid rotation %d\", rotation );\n          case 0:\n               point->x = from->x1;\n               point->y = from->y1;\n               break;\n\n          case 90:\n               point->x = from->y1;\n               point->y = size->w - from->x2 - 1;\n               break;\n\n          case 180:\n               point->x = size->w - from->x2 - 1;\n               point->y = size->h - from->y2 - 1;\n               break;\n\n          case 270:\n               point->x = size->h - from->y2 - 1;\n               point->y = from->x1;\n               break;\n     }\n\n     D_ASSERT( point->x >= 0 );\n     D_ASSERT( point->y >= 0 );\n     D_ASSERT( point->x < size->w );\n     D_ASSERT( point->y < size->h );\n}\n\nstatic __inline__ void\ndfb_point_translate( DFBPoint *point,\n                     int       dx,\n                     int       dy )\n{\n     D_ASSERT( point != NULL );\n\n     point->x += dx;\n     point->y += dy;\n}\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int        magic;\n\n     DFBRegion *regions;\n     int        max_regions;\n     int        num_regions;\n\n     DFBRegion  bounding;\n} DFBUpdates;\n\n#define DFB_UPDATES_ASSERT(updates)                                                               \\\n     do {                                                                                         \\\n          D_MAGIC_ASSERT( updates, DFBUpdates );                                                  \\\n          D_ASSERT( (updates)->regions != NULL );                                                 \\\n          D_ASSERT( (updates)->max_regions > 0 );                                                 \\\n          D_ASSERT( (updates)->num_regions <= (updates)->max_regions );                           \\\n     } while (0)\n\n#define DFB_UPDATES_DEBUG_AT(d,updates)                                                           \\\n     do {                                                                                         \\\n          D_DEBUG_AT( d, \" =--[ \" #updates \" has %d regions ]\\n\", (updates)->num_regions );       \\\n          DFB_REGIONS_DEBUG_AT( d, (updates)->regions, (unsigned int) ((updates)->num_regions) ); \\\n     } while (0)\n\n\nvoid DIRECTFB_API dfb_updates_init          ( DFBUpdates      *updates,\n                                              DFBRegion       *regions,\n                                              int              max_regions );\n\nvoid DIRECTFB_API dfb_updates_deinit        ( DFBUpdates      *updates );\n\nvoid DIRECTFB_API dfb_updates_add           ( DFBUpdates      *updates,\n                                              const DFBRegion *region );\n\nvoid DIRECTFB_API dfb_updates_add_rect      ( DFBUpdates      *updates,\n                                              int              x,\n                                              int              y,\n                                              int              w,\n                                              int              h );\n\nvoid DIRECTFB_API dfb_updates_stat          ( DFBUpdates      *updates,\n                                              int             *ret_total,\n                                              int             *ret_bounding );\n\nvoid DIRECTFB_API dfb_updates_get_rectangles( DFBUpdates      *updates,\n                                              DFBRectangle    *ret_rects,\n                                              int             *ret_num );\n\nvoid DIRECTFB_API dfb_updates_reset         ( DFBUpdates      *updates );\n\n/**********************************************************************************************************************/\n\nconst char DIRECTFB_API *dfb_input_event_type_name ( DFBInputEventType     type );\nconst char DIRECTFB_API *dfb_pixelformat_name      ( DFBSurfacePixelFormat format );\nconst char DIRECTFB_API *dfb_colorspace_name       ( DFBSurfaceColorSpace  colorspace );\nconst char DIRECTFB_API *dfb_window_event_type_name( DFBWindowEventType    type );\n\n/**********************************************************************************************************************/\n\nDFBSurfacePixelFormat DIRECTFB_API dfb_pixelformat_for_depth( int         depth );\nDFBSurfacePixelFormat DIRECTFB_API dfb_pixelformat_parse    ( const char *format );\nDFBSurfaceColorSpace  DIRECTFB_API dfb_colorspace_parse     ( const char *colorspace );\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/directfb_windows.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECTFB_WINDOWS_H__\n#define __DIRECTFB_WINDOWS_H__\n\n#include <directfb.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * Window stack interface.\n */\nD_DECLARE_INTERFACE( IDirectFBWindows )\n\n/********************\n * IDirectFBWindows *\n ********************/\n\n/*\n * Window configuration flags.\n */\ntypedef enum {\n     DWCONF_NONE                           = 0x00000000,         /* none of these flags */\n\n     DWCONF_POSITION                       = 0x00000001,         /* position */\n     DWCONF_SIZE                           = 0x00000002,         /* size */\n     DWCONF_OPACITY                        = 0x00000004,         /* opacity */\n     DWCONF_STACKING                       = 0x00000008,         /* stacking */\n     DWCONF_OPTIONS                        = 0x00000010,         /* options */\n     DWCONF_EVENTS                         = 0x00000020,         /* events */\n     DWCONF_ASSOCIATION                    = 0x00000040,         /* association */\n\n     DWCONF_COLOR_KEY                      = 0x00000100,         /* color key */\n     DWCONF_OPAQUE                         = 0x00000200,         /* opaque */\n     DWCONF_COLOR                          = 0x00000400,         /* color */\n     DWCONF_STEREO_DEPTH                   = 0x00000800,         /* stereo depth */\n     DWCONF_KEY_SELECTION                  = 0x00001000,         /* key selection */\n     DWCONF_CURSOR_FLAGS                   = 0x00002000,         /* cursor flags */\n     DWCONF_CURSOR_RESOLUTION              = 0x00004000,         /* cursor resolution */\n\n     DWCONF_SRC_GEOMETRY                   = 0x00010000,         /* source geometry */\n     DWCONF_DST_GEOMETRY                   = 0x00020000,         /* destination geometry */\n     DWCONF_ROTATION                       = 0x00040000,         /* rotation */\n     DWCONF_APPLICATION_ID                 = 0x00080000,         /* application id */\n     DWCONF_TYPE_HINT                      = 0x00100000,         /* type hint */\n     DWCONF_HINT_FLAGS                     = 0x00200000,         /* hint flags */\n\n     DWCONF_ALL                            = 0x003F7F7F          /* all of these */\n} DFBWindowConfigFlags;\n\n/*\n * Window configuration.\n */\ntypedef struct {\n     DFBRectangle                            bounds;             /* position and size */\n     int                                     opacity;            /* global alpha factor */\n     DFBWindowStackingClass                  stacking;           /* level boundaries */\n     DFBWindowOptions                        options;            /* flags for appearance/behaviour */\n     DFBWindowEventType                      events;             /* mask of enabled events */\n     DFBWindowID                             association;        /* ID of window which this is associated to */\n     u32                                     color_key;          /* transparent pixel */\n     DFBRegion                               opaque;             /* region of the window forced to be opaque */\n     DFBColor                                color;              /* constant color (no surface needed) */\n     DFBWindowKeySelection                   key_selection;      /* how to filter keys in focus */\n     DFBWindowCursorFlags                    cursor_flags;       /* cursor flags */\n     DFBDimension                            cursor_resolution;  /* cursor resolution */\n     DFBWindowGeometry                       src_geometry;       /* advanced source geometry */\n     DFBWindowGeometry                       dst_geometry;       /* advanced destination geometry */\n     int                                     rotation;           /* rotation */\n     u64                                     application_id;     /* application id */\n     int                                     stereo_depth;       /* stereo depth */\n     DFBWindowTypeHint                       type_hint;          /* type hint */\n     DFBWindowHintFlags                      hint_flags;         /* hint flags */\n} DFBWindowConfig;\n\n/*\n * Window state flags.\n */\ntypedef enum {\n     DWSTATE_NONE                          = 0x00000000,         /* None of these. */\n\n     DWSTATE_INSERTED                      = 0x00000001,         /* Window is inserted. */\n     DWSTATE_FOCUSED                       = 0x00000002,         /* Window is focused. */\n     DWSTATE_ENTERED                       = 0x00000004,         /* Window is entered. */\n\n     DWSTATE_ALL                           = 0x00000007          /* All of these. */\n} DFBWindowStateFlags;\n\n/*\n * Window state.\n */\ntypedef struct {\n     DFBWindowStateFlags                     flags;              /* Window state flags. */\n} DFBWindowState;\n\n/*\n * Window information.\n */\ntypedef struct {\n     DFBWindowID                             window_id;          /* Window ID */\n     DFBWindowCapabilities                   caps;               /* Window capabilities */\n     u64                                     resource_id;        /* Resource ID */\n     DFBWindowConfig                         config;             /* Window configuration. */\n     DFBWindowState                          state;              /* Window state */\n     u32                                     process_id;         /* Fusion ID or other element identifying process. */\n     u32                                     instance_id;        /* ID of the instance of an application. */\n} DFBWindowInfo;\n\n/*\n * Windows watcher callbacks.\n */\ntypedef struct {\n     /*\n      * Add window, called for each window existing at watcher\n      * registration and each added afterwards.\n      */\n     void (*WindowAdd) (\n          void                              *context,\n          const DFBWindowInfo               *info\n     );\n\n     /*\n      * Remove window, called for each window being removed.\n      */\n     void (*WindowRemove) (\n          void                              *context,\n          DFBWindowID                        window_id\n     );\n\n     /*\n      * Change window configuration, called for each window\n      * changing its configuration. The flags specify which\n      * of the items have changed actually.\n      */\n     void (*WindowConfig) (\n          void                              *context,\n          DFBWindowID                        window_id,\n          const DFBWindowConfig             *config,\n          DFBWindowConfigFlags               flags\n     );\n\n     /*\n      * Update window state, called for each window changing its\n      * state. In case of insertion of a window, prior to this,\n      * the watcher will receive the WindowRestack() call, which\n      * contains the z-position at which the window has been\n      * inserted.\n      */\n     void (*WindowState) (\n          void                              *context,\n          DFBWindowID                        window_id,\n          const DFBWindowState              *state\n     );\n\n     /*\n      * Update window z-position, called for each window\n      * changing its z-position. In case of insertion of a\n      * window, after this call, the watcher will receive the\n      * WindowState() call, which indicates insertion of the\n      * window. Upon reinsertion, only this call will be\n      * received.\n      */\n     void (*WindowRestack) (\n          void                              *context,\n          DFBWindowID                        window_id,\n          unsigned int                       index\n     );\n\n     /*\n      * Switch window focus, called for each window getting the\n      * focus.\n      */\n     void (*WindowFocus) (\n          void                              *context,\n          DFBWindowID                        window_id\n     );\n} DFBWindowsWatcher;\n\n/*\n * IDirectFBWindows is the window stack interface.\n */\nD_DEFINE_INTERFACE( IDirectFBWindows,\n\n   /** Watching **/\n\n     /*\n      * Register a new windows watcher.\n      */\n     DFBResult (*RegisterWatcher) (\n          IDirectFBWindows                  *thiz,\n          const DFBWindowsWatcher           *watcher,\n          void                              *context\n     );\n\n     /*\n      * Unregister a windows watcher.\n      */\n     DFBResult (*UnregisterWatcher) (\n          IDirectFBWindows                  *thiz,\n          void                              *context\n     );\n)\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/directfbgl.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECTFBGL_H__\n#define __DIRECTFBGL_H__\n\n#include <directfb.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/***************\n * IDirectFBGL *\n ***************/\n\n/*\n * The DirectFBGL interface version.\n */\n#ifndef DIRECTFBGL_INTERFACE_VERSION\n#define DIRECTFBGL_INTERFACE_VERSION 2\n#endif\n\n/*\n * Attributes of an OpenGL context.\n */\ntypedef struct {\n     int                                     buffer_size;        /* depth of the color buffer */\n     int                                     depth_size;         /* number of bits in the depth buffer */\n     int                                     stencil_size;       /* number of bits in the stencil buffer */\n     int                                     aux_buffers;        /* number of auxiliary color buffers */\n     int                                     red_size;           /* number of bits of red in the framebuffer */\n     int                                     green_size;         /* number of bits of green in the framebuffer */\n     int                                     blue_size;          /* number of bits of blue in the framebuffer */\n     int                                     alpha_size;         /* number of bits of alpha in the framebuffer */\n     int                                     accum_red_size;     /* number of bits of red in the accumulation\n                                                                    buffer */\n     int                                     accum_green_size;   /* number of bits of green in the accumulation\n                                                                    buffer */\n     int                                     accum_blue_size;    /* number of bits of blue in the accumulation\n                                                                    buffer */\n     int                                     accum_alpha_size;   /* number of bits of alpha in the accumulation\n                                                                    buffer */\n     DFBBoolean                              double_buffer;      /* true if color buffers have front/back buffer\n                                                                    pairs */\n     DFBBoolean                              stereo;             /* true if color buffers have left/right pairs */\n} DFBGLAttributes;\n\n/*\n * IDirectFBGL is the OpenGL interface.\n */\nD_DEFINE_INTERFACE( IDirectFBGL,\n\n   /** Context handling **/\n\n     /*\n      * Acquire the hardware lock.\n      */\n     DFBResult (*Lock) (\n          IDirectFBGL                       *thiz\n     );\n\n     /*\n      * Release the lock.\n      */\n     DFBResult (*Unlock) (\n          IDirectFBGL                       *thiz\n     );\n\n     /*\n      * Query the OpenGL attributes.\n      */\n     DFBResult (*GetAttributes) (\n          IDirectFBGL                       *thiz,\n          DFBGLAttributes                   *ret_attributes\n     );\n\n     /*\n      * Get the address of an OpenGL function.\n      */\n     DFBResult (*GetProcAddress) (\n          IDirectFBGL                       *thiz,\n          const char                        *name,\n          void                             **ret_address\n     );\n\n#if DIRECTFBGL_INTERFACE_VERSION > 1\n     /*\n      * Swap buffers.\n      */\n     DFBResult (*SwapBuffers) (\n          IDirectFBGL                       *thiz\n     );\n#endif\n)\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/gen_directfb_keynames.sh",
    "content": "#!/bin/sh\n#\n#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\nmknames() {\nENUM=$1\nPREFIX=$2\nNULL=$3\nNAME=$4\nVALUE=$5\nHEADER=$6\n\ncat << EOF\n\nstruct DFB${NAME}Name {\n     ${ENUM} ${VALUE};\n     const char *name;\n};\n\n#define DirectFB${NAME}Names(Identifier) struct DFB${NAME}Name Identifier[] = { \\\\\nEOF\n\negrep \"^ +${PREFIX}_[0-9A-Za-z_]+[ ,]\" $HEADER | grep -v ${PREFIX}_${NULL} | perl -p -e \"s/^\\\\s*(${PREFIX}_)([\\\\w_]+)[ ,].*/     \\\\{ \\\\1\\\\2, \\\\\\\"\\\\2\\\\\\\" \\\\}, \\\\\\\\/\"\n\ncat << EOF\n     { ($ENUM) ${PREFIX}_${NULL}, \"${NULL}\" } \\\\\n};\nEOF\n}\n\necho \\#ifndef __DIRECTFB_KEYNAMES_H__\necho \\#define __DIRECTFB_KEYNAMES_H__\necho\necho \\#include \\<directfb_keyboard.h\\>\nmknames DFBInputDeviceKeySymbol     DIKS NULL    KeySymbol     symbol     $1 | grep -v DIKS_ENTER\nmknames DFBInputDeviceKeyIdentifier DIKI UNKNOWN KeyIdentifier identifier $1 | grep -v DIKI_NUMBER_OF_KEYS | grep -v DIKI_KEYDEF_END\necho\necho \\#endif\n"
  },
  {
    "path": "include/gen_directfb_strings.sh",
    "content": "#!/bin/sh\n#\n#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\nmknames() {\nENUM=$1\nPREFIX=$2\nNULL=$3\nNAME=$4\nVALUE=$5\nHEADER=$6\n\ncat << EOF\n\nstruct DFB${NAME}Name {\n     ${ENUM} ${VALUE};\n     const char *name;\n};\n\n#define DirectFB${NAME}Names(Identifier) struct DFB${NAME}Name Identifier[] = { \\\\\nEOF\n\negrep \"^ +${PREFIX}_[0-9A-Za-z_]+[ ,]\" $HEADER | grep -v ${PREFIX}_${NULL} | perl -p -e \"s/^\\\\s*(${PREFIX}_)([\\\\w_]+)[ ,].*/     \\\\{ \\\\1\\\\2, \\\\\\\"\\\\2\\\\\\\" \\\\}, \\\\\\\\/\"\n\ncat << EOF\n     { ($ENUM) ${PREFIX}_${NULL}, \"${NULL}\" } \\\\\n};\nEOF\n}\n\necho \\#ifndef __DIRECTFB_STRINGS_H__\necho \\#define __DIRECTFB_STRINGS_H__\necho\necho \\#include \\<directfb.h\\>\nmknames DFBSurfacePixelFormat DSPF UNKNOWN PixelFormat format $1\nmknames DFBSurfacePorterDuffRule DSPD NONE PorterDuffRule rule $1\nmknames DFBSurfaceCapabilities DSCAPS NONE SurfaceCapabilities capability $1 | grep -v DSCAPS_FLIPPING | grep -v DSCAPS_ALL\nmknames DFBSurfaceColorSpace DSCS UNKNOWN ColorSpace colorspace $1\nmknames DFBInputDeviceTypeFlags DIDTF NONE InputDeviceTypeFlags type $1 | grep -v DIDTF_ALL\nmknames DFBSurfaceDrawingFlags DSDRAW NOFX SurfaceDrawingFlags flag $1 | grep -v DSDRAW_ALL\nmknames DFBSurfaceBlittingFlags DSBLIT NOFX SurfaceBlittingFlags flag $1 | grep -v DSBLIT_ALL\nmknames DFBSurfaceFlipFlags DSFLIP NONE SurfaceFlipFlags flag $1 | grep -v DSFLIP_ALL\nmknames DFBSurfaceBlendFunction DSBF UNKNOWN SurfaceBlendFunction function $1\nmknames DFBInputDeviceCapabilities DICAPS NONE InputDeviceCapabilities capability $1 | grep -v DICAPS_ALL | grep -v DICAPS_ALPHACHANNEL | grep -v DICAPS_COLORKEY\nmknames DFBDisplayLayerTypeFlags DLTF NONE DisplayLayerTypeFlags type $1 | grep -v DLTF_ALL\nmknames DFBDisplayLayerCapabilities DLCAPS NONE DisplayLayerCapabilities capability $1 | grep -v DLCAPS_ALL\nmknames DFBDisplayLayerBufferMode DLBM UNKNOWN DisplayLayerBufferMode mode $1 | grep -v DLBM_DONTCARE | grep -v DLBM_COLOR | grep -v DLBM_IMAGE | grep -v DLBM_TILE\nmknames DFBWindowCapabilities DWCAPS NONE WindowCapabilities capability $1 | grep -v DWCAPS_ALL\nmknames DFBDisplayLayerOptions DLOP NONE DisplayLayerOptions option $1 | grep -v DLOP_ALL\nmknames DFBWindowOptions DWOP NONE WindowOptions option $1 | grep -v DWOP_ALL\nmknames DFBScreenCapabilities DSCCAPS NONE ScreenCapabilities capability $1 | grep -v DSCCAPS_ALL\nmknames DFBScreenEncoderCapabilities DSECAPS NONE ScreenEncoderCapabilities capability $1 | grep -v DSECAPS_ALL\nmknames DFBScreenEncoderType DSET UNKNOWN ScreenEncoderType type $1 | grep -v DSET_ALL\nmknames DFBScreenEncoderTVStandards DSETV UNKNOWN ScreenEncoderTVStandards standard $1 | grep -v DSETV_ALL\nmknames DFBScreenOutputCapabilities DSOCAPS NONE ScreenOutputCapabilities capability $1 | grep -v DSOCAPS_ALL\nmknames DFBScreenOutputConnectors DSOC UNKNOWN ScreenOutputConnectors connector $1 | grep -v DSOC_ALL\nmknames DFBScreenOutputSignals DSOS NONE ScreenOutputSignals signal $1 | grep -v DSOS_ALL\nmknames DFBScreenOutputSlowBlankingSignals DSOSB OFF ScreenOutputSlowBlankingSignals slow_signal $1 | grep -v DSOSB_ALL\nmknames DFBScreenOutputResolution DSOR UNKNOWN ScreenOutputResolution resolution $1 | grep -v DSOR_ALL\nmknames DFBScreenMixerCapabilities DSMCAPS NONE ScreenMixerCapabilities capability $1 | grep -v DSMCAPS_ALL\nmknames DFBScreenMixerTree DSMT UNKNOWN ScreenMixerTree tree $1 | grep -v DSMT_ALL\nmknames DFBScreenEncoderTestPicture DSETP OFF ScreenEncoderTestPicture test_picture $1 | grep -v DSETP_ALL\nmknames DFBScreenEncoderScanMode DSESM UNKNOWN ScreenEncoderScanMode scan_mode $1 | grep -v DSESM_ALL\nmknames DFBScreenEncoderConfigFlags DSECONF UNKNOWN ScreenEncoderConfigFlags config_flags $1 | grep -v DSECONF_ALL\nmknames DFBScreenEncoderFrequency DSEF UNKNOWN ScreenEncoderFrequency frequency $1 | grep -v DSEF_ALL\nmknames DFBScreenEncoderPictureFraming DSEPF UNKNOWN ScreenEncoderPictureFraming framing $1 | grep -v DSEPF_ALL\nmknames DFBAccelerationMask DFXL NONE AccelerationMask mask $1 | grep -v DFXL_ALL\necho\necho \\#endif\n"
  },
  {
    "path": "include/meson.build",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\ndirectfb_headers = [\n  'dfiff.h',\n  'dfvff.h',\n  'dgiff.h',\n  'directfb.h',\n  'directfb_keyboard.h',\n  'directfb_util.h',\n  'directfb_windows.h',\n  'directfbgl.h',\n]\n\ndirectfb_version_conf = configuration_data()\n\ndirectfb_version_conf.set('DIRECTFB_MAJOR_VERSION', directfb_major_version)\ndirectfb_version_conf.set('DIRECTFB_MINOR_VERSION', directfb_minor_version)\ndirectfb_version_conf.set('DIRECTFB_MICRO_VERSION', directfb_micro_version)\n\nconfigure_file(configuration: directfb_version_conf,\n               output: 'directfb_version.h',\n               install: true,\n               install_dir: get_option('includedir') / 'directfb')\n\ndirectfb_build_conf = configuration_data()\n\ndirectfb_build_conf.set('FLUXED_ARGS_BYTES', get_option('args-size'))\n\nconfigure_file(configuration: directfb_build_conf,\n               output: 'directfb_build.h',\n               install: true,\n               install_dir: get_option('includedir') / 'directfb')\n\ndirectfb_keynames = custom_target('directfb_keynames',\n                                  command: ['gen_directfb_keynames.sh', '@INPUT@'],\n                                  input: 'directfb_keyboard.h',\n                                  output: 'directfb_keynames.h',\n                                  capture: true,\n                                  install: true,\n                                  install_dir: get_option('includedir') / 'directfb')\n\ndirectfb_strings = custom_target('directfb_strings',\n                                 command: ['gen_directfb_strings.sh', '@INPUT@'],\n                                 input: 'directfb.h',\n                                 output: 'directfb_strings.h',\n                                 capture: true,\n                                 install: true,\n                                 install_dir: get_option('includedir') / 'directfb')\n\ninstall_headers(directfb_headers, subdir: 'directfb')\n"
  },
  {
    "path": "inputdrivers/linux_input/linux_input.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#define DFB_INPUTDRIVER_HAS_AXIS_INFO\n#define DFB_INPUTDRIVER_HAS_SET_CONFIGURATION\n#include <direct/build.h>\n#if DIRECT_BUILD_NETWORK\n#define DISABLE_INPUT_HOTPLUG_FUNCTION_STUB\n#endif /* DIRECT_BUILD_NETWORK */\n\n#include <core/input_driver.h>\n#include <direct/thread.h>\n#include <fusion/vector.h>\n#include <linux/input.h>\n#include <linux/keyboard.h>\n#include <sys/kd.h>\n\nD_DEBUG_DOMAIN( Linux_Input, \"Input/Linux\", \"Linux Input Driver\" );\n\nDFB_INPUT_DRIVER( linux_input )\n\n/**********************************************************************************************************************/\n\n#define NBITS(x) ((((x) - 1) / (sizeof(long) * 8)) + 1)\n\ntypedef struct {\n     CoreInputDevice         *device;\n     int                      index;\n\n     int                      fd;\n\n     bool                     grab;\n\n     bool                     has_keys;\n     bool                     has_leds;\n     unsigned long            led_state[NBITS(LED_CNT)];\n     DFBInputDeviceLockState  locks;\n\n     bool                     touchpad;\n     bool                     touch_abs;\n\n     int                      sensitivity;\n\n     int                      dx;\n     int                      dy;\n\n     int                      vt_fd;\n\n     DirectThread            *thread;\n     int                      quitpipe[2];\n} LinuxInputData;\n\n/* The maximum amount of evdev devices with static minors, from 13:64 to 13:95 */\n#define MAX_LINUX_INPUT_DEVICES 32\n\n/* Input devices are stored in the device_names and device_nums arrays: entries with the same index in device_names and\ndevice_nums are the same in two different forms (one is /dev/input/eventX, the other is X. */\nstatic char *device_names[MAX_LINUX_INPUT_DEVICES];\nstatic int   device_nums[MAX_LINUX_INPUT_DEVICES] = { 0 };\n\n/* Number of entries in the device_names and device_nums arrays. */\nstatic int   num_devices = 0;\n\n#define MAX_LINUX_INPUT_EVENTS 64\n\n/* Input events filled on read. */\nstruct input_event input_events[MAX_LINUX_INPUT_EVENTS];\n\n#if !defined(input_event_sec) && !defined(input_event_usec)\n#define input_event_sec  time.tv_sec\n#define input_event_usec time.tv_usec\n#endif\n\n/**********************************************************************************************************************/\n\n#define OFF(x)              ((x) % (sizeof(long) * 8))\n#define LONG(x)             ((x) / (sizeof(long) * 8))\n#define test_bit(bit,array) ((array[LONG(bit)] >> OFF(bit)) & 1)\n\nstatic const int basic_keycodes[] = {\n     DIKI_UNKNOWN, DIKI_ESCAPE,\n     DIKI_1, DIKI_2, DIKI_3, DIKI_4, DIKI_5, DIKI_6, DIKI_7, DIKI_8, DIKI_9, DIKI_0,\n     DIKI_MINUS_SIGN, DIKI_EQUALS_SIGN, DIKI_BACKSPACE, DIKI_TAB,\n     DIKI_Q, DIKI_W, DIKI_E, DIKI_R, DIKI_T, DIKI_Y, DIKI_U, DIKI_I, DIKI_O, DIKI_P,\n     DIKI_BRACKET_LEFT, DIKI_BRACKET_RIGHT, DIKI_ENTER, DIKI_CONTROL_L,\n     DIKI_A, DIKI_S, DIKI_D, DIKI_F, DIKI_G, DIKI_H, DIKI_J, DIKI_K, DIKI_L,\n     DIKI_SEMICOLON, DIKI_QUOTE_RIGHT, DIKI_QUOTE_LEFT, DIKI_SHIFT_L, DIKI_BACKSLASH,\n     DIKI_Z, DIKI_X, DIKI_C, DIKI_V, DIKI_B, DIKI_N, DIKI_M,\n     DIKI_COMMA, DIKI_PERIOD, DIKI_SLASH, DIKI_SHIFT_R, DIKI_KP_MULT, DIKI_ALT_L, DIKI_SPACE, DIKI_CAPS_LOCK,\n     DIKI_F1, DIKI_F2, DIKI_F3, DIKI_F4, DIKI_F5, DIKI_F6, DIKI_F7, DIKI_F8, DIKI_F9, DIKI_F10,\n     DIKI_NUM_LOCK, DIKI_SCROLL_LOCK,\n     DIKI_KP_7, DIKI_KP_8, DIKI_KP_9, DIKI_KP_MINUS,\n     DIKI_KP_4, DIKI_KP_5, DIKI_KP_6, DIKI_KP_PLUS,\n     DIKI_KP_1, DIKI_KP_2, DIKI_KP_3,\n     DIKI_KP_0, DIKI_KP_DECIMAL,\n     DIKI_BACKSLASH, DFB_FUNCTION_KEY(13), DIKI_LESS_SIGN, DIKI_F11, DIKI_F12, DFB_FUNCTION_KEY(14),\n     DFB_FUNCTION_KEY(15), DFB_FUNCTION_KEY(16), DFB_FUNCTION_KEY(17),\n     DFB_FUNCTION_KEY(18), DFB_FUNCTION_KEY(19), DFB_FUNCTION_KEY(20),\n     DIKI_KP_ENTER, DIKI_CONTROL_R, DIKI_KP_DIV, DIKI_PRINT, DIKS_ALTGR, DIKI_UNKNOWN, DIKI_HOME,\n     DIKI_UP, DIKI_PAGE_UP, DIKI_LEFT, DIKI_RIGHT, DIKI_END, DIKI_DOWN, DIKI_PAGE_DOWN, DIKI_INSERT, DIKI_DELETE,\n     DIKI_UNKNOWN, DIKS_MUTE, DIKS_VOLUME_DOWN, DIKS_VOLUME_UP, DIKS_POWER, DIKI_KP_EQUAL, DIKI_UNKNOWN, DIKS_PAUSE,\n     DFB_FUNCTION_KEY(21), DFB_FUNCTION_KEY(22), DFB_FUNCTION_KEY(23), DFB_FUNCTION_KEY(24), DIKI_KP_SEPARATOR,\n     DIKI_META_L, DIKI_META_R, DIKI_SUPER_L, DIKS_STOP, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN,\n     DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN,\n     DIKS_HELP, DIKS_MENU, DIKS_CALCULATOR, DIKS_SETUP,\n     DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN,\n     DIKS_CUSTOM1, DIKS_CUSTOM2, DIKS_INTERNET, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKS_MAIL,\n     DIKI_UNKNOWN, DIKI_UNKNOWN, DIKS_BACK, DIKS_FORWARD, DIKS_EJECT, DIKS_EJECT, DIKS_EJECT,\n     DIKS_NEXT, DIKS_PLAYPAUSE, DIKS_PREVIOUS, DIKS_STOP, DIKS_RECORD, DIKS_REWIND, DIKS_PHONE, DIKI_UNKNOWN,\n     DIKS_SETUP, DIKI_UNKNOWN, DIKS_SHUFFLE, DIKS_EXIT, DIKI_UNKNOWN, DIKS_EDITOR,\n     DIKS_PAGE_UP, DIKS_PAGE_DOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN,\n     DFB_FUNCTION_KEY(13), DFB_FUNCTION_KEY(14), DFB_FUNCTION_KEY(15), DFB_FUNCTION_KEY(16),\n     DFB_FUNCTION_KEY(17), DFB_FUNCTION_KEY(18), DFB_FUNCTION_KEY(19), DFB_FUNCTION_KEY(20),\n     DFB_FUNCTION_KEY(21), DFB_FUNCTION_KEY(22), DFB_FUNCTION_KEY(23), DFB_FUNCTION_KEY(24),\n     DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN,\n     DIKS_PLAY, DIKS_PAUSE, DIKS_CUSTOM3, DIKS_CUSTOM4, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN,\n     DIKS_PLAY, DIKS_FASTFORWARD, DIKI_UNKNOWN, DIKS_PRINT, DIKI_UNKNOWN, DIKI_UNKNOWN,\n     DIKS_AUDIO, DIKS_HELP, DIKS_MAIL,\n     DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN,\n     DIKS_CANCEL, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN\n};\n\nstatic const int ext_keycodes[] = {\n     DIKS_OK, DIKS_SELECT, DIKS_GOTO, DIKS_CLEAR, DIKS_POWER2, DIKS_OPTION, DIKS_INFO, DIKS_TIME, DIKS_VENDOR,\n     DIKS_ARCHIVE, DIKS_PROGRAM, DIKS_CHANNEL, DIKS_FAVORITES, DIKS_EPG, DIKS_PVR, DIKS_MHP, DIKS_LANGUAGE,\n     DIKS_TITLE, DIKS_SUBTITLE, DIKS_ANGLE, DIKS_ZOOM, DIKS_MODE, DIKS_KEYBOARD, DIKS_SCREEN, DIKS_PC,\n     DIKS_TV, DIKS_TV2, DIKS_VCR, DIKS_VCR2, DIKS_SAT, DIKS_SAT2, DIKS_CD, DIKS_TAPE, DIKS_RADIO, DIKS_TUNER,\n     DIKS_PLAYER, DIKS_TEXT, DIKS_DVD, DIKS_AUX, DIKS_MP3, DIKS_AUDIO, DIKS_VIDEO, DIKS_DIRECTORY, DIKS_LIST,\n     DIKS_MEMO, DIKS_CALENDAR, DIKS_RED, DIKS_GREEN, DIKS_YELLOW, DIKS_BLUE, DIKS_CHANNEL_UP, DIKS_CHANNEL_DOWN,\n     DIKS_FIRST, DIKS_LAST, DIKS_AB, DIKS_NEXT, DIKS_RESTART, DIKS_SLOW, DIKS_SHUFFLE, DIKS_BREAK, DIKS_PREVIOUS,\n     DIKS_DIGITS, DIKS_TEEN, DIKS_TWEN\n};\n\n/**********************************************************************************************************************/\n\nstatic void\nconfig_values_parse( FusionVector *vector,\n                     const char   *arg )\n{\n     char *values = D_STRDUP( arg );\n     char *s      = values;\n     char *r, *p  = NULL;\n\n     if (!values) {\n          D_OOM();\n          return;\n     }\n\n     while ((r = direct_strtok_r( s, \",\", &p ))) {\n          direct_trim( &r );\n\n          r = D_STRDUP( r );\n          if (!r)\n               D_OOM();\n          else\n               fusion_vector_add( vector, r );\n\n          s = NULL;\n     }\n\n     D_FREE( values );\n}\n\nstatic void\nconfig_values_free( FusionVector *vector )\n{\n     char *value;\n     int   i;\n\n     fusion_vector_foreach (value, i, *vector)\n          D_FREE( value );\n\n     fusion_vector_destroy( vector );\n}\n\n/**********************************************************************************************************************/\n\nenum {\n     TOUCHPAD_FSM_START,\n     TOUCHPAD_FSM_MAIN,\n     TOUCHPAD_FSM_DRAG_START,\n     TOUCHPAD_FSM_DRAG_MAIN,\n};\n\nstruct touchpad_axis {\n     int old, min, max;\n};\n\nstruct touchpad_fsm_state {\n     int                  fsm_state;\n     struct touchpad_axis x;\n     struct touchpad_axis y;\n     struct timeval       timeout;\n};\n\n#define ACCEL_THRESHOLD 25\n#define ACCEL_NUM        3\n#define ACCEL_DENOM      1\n\nstatic bool\ntimeout_is_set( const struct timeval *timeout )\n{\n     return timeout->tv_sec || timeout->tv_usec;\n}\n\nstatic bool\ntimeout_passed( const struct timeval *timeout,\n                const struct timeval *current )\n{\n     return !timeout_is_set( timeout )        ||\n            current->tv_sec > timeout->tv_sec ||\n            (current->tv_sec == timeout->tv_sec && current->tv_usec > timeout->tv_usec);\n}\n\nstatic void\ntimeout_clear( struct timeval *timeout )\n{\n     timeout->tv_sec  = 0;\n     timeout->tv_usec = 0;\n}\n\nstatic void\ntimeout_add( struct timeval       *timeout,\n             const struct timeval *add )\n{\n     timeout->tv_sec  += add->tv_sec;\n     timeout->tv_usec += add->tv_usec;\n\n     while (timeout->tv_usec >= 1000000) {\n          timeout->tv_sec++;\n          timeout->tv_usec -= 1000000;\n     }\n}\n\nstatic void\ntimeout_sub( struct timeval       *timeout,\n             const struct timeval *sub )\n{\n     timeout->tv_sec  -= sub->tv_sec;\n     timeout->tv_usec -= sub->tv_usec;\n\n     while (timeout->tv_usec < 0) {\n          timeout->tv_sec--;\n          timeout->tv_usec += 1000000;\n     }\n}\n\nstatic void\ntouchpad_fsm_init( struct touchpad_fsm_state *state )\n{\n     state->x.old = -1;\n     state->y.old = -1;\n     state->fsm_state = TOUCHPAD_FSM_START;\n\n     timeout_clear( &state->timeout );\n}\n\nstatic int\ntouchpad_normalize( const struct touchpad_axis *axis,\n                    int                         value )\n{\n     return ((value - axis->min) << 9) / (axis->max - axis->min);\n}\n\nstatic int\ntouchpad_translate( struct touchpad_fsm_state *state,\n                    bool                       touch_abs,\n                    const struct input_event  *levt,\n                    DFBInputEvent             *devt )\n{\n     struct touchpad_axis *axis = NULL;\n     int abs, rel;\n\n     devt->flags             = DIEF_TIMESTAMP | (touch_abs ? DIEF_AXISABS : DIEF_AXISREL);\n     devt->timestamp.tv_sec  = levt->input_event_sec;\n     devt->timestamp.tv_usec = levt->input_event_usec;\n     devt->type              = DIET_AXISMOTION;\n\n     switch (levt->code) {\n          case ABS_X:\n               axis       = &state->x;\n               devt->axis = DIAI_X;\n               break;\n          case ABS_Y:\n               axis       = &state->y;\n               devt->axis = DIAI_Y;\n               break;\n          default:\n               return 0;\n     }\n\n     abs = touchpad_normalize( axis, levt->value );\n\n     if (axis->old == -1)\n          axis->old = abs;\n\n     rel = abs - axis->old;\n\n     if (rel > ACCEL_THRESHOLD)\n          rel += (rel - ACCEL_THRESHOLD) * ACCEL_NUM / ACCEL_DENOM;\n     else if (rel < -ACCEL_THRESHOLD)\n          rel += (rel + ACCEL_THRESHOLD) * ACCEL_NUM / ACCEL_DENOM;\n\n     axis->old     = abs;\n     devt->axisrel = rel;\n     devt->axisabs = levt->value;\n\n     return 1;\n}\n\nstatic bool\ntouchpad_finger_landing( const struct input_event *levt )\n{\n     return levt->type == EV_KEY && levt->code == BTN_TOUCH && levt->value == 1;\n}\n\nstatic bool\ntouchpad_finger_leaving( const struct input_event *levt )\n{\n     return levt->type == EV_KEY && levt->code == BTN_TOUCH && levt->value == 0;\n}\n\nstatic bool\ntouchpad_finger_moving( const struct input_event *levt )\n{\n     return levt->type == EV_ABS && (levt->code == ABS_X || levt->code == ABS_Y);\n}\n\nstatic int\ntouchpad_fsm( struct touchpad_fsm_state *state,\n              bool                       touch_abs,\n              const struct input_event  *levt,\n              DFBInputEvent             *devt )\n{\n     struct timeval levt_time;\n     struct timeval timeout = { 0, 125000 };\n\n     if (!levt) {\n          if (state->fsm_state == TOUCHPAD_FSM_DRAG_START) {\n               devt->flags     = DIEF_TIMESTAMP;\n               devt->timestamp = state->timeout;\n               devt->type      = DIET_BUTTONRELEASE;\n               devt->button    = DIBI_FIRST;\n\n               touchpad_fsm_init( state );\n\n               return 1;\n          }\n\n          timeout_clear( &state->timeout );\n\n          return 0;\n     }\n\n     levt_time.tv_sec  = levt->input_event_sec;\n     levt_time.tv_usec = levt->input_event_usec;\n\n     if ((levt->type == EV_SYN && levt->code == SYN_REPORT)         ||\n         (levt->type == EV_ABS && levt->code == ABS_PRESSURE)       ||\n         (levt->type == EV_ABS && levt->code == ABS_TOOL_WIDTH)     ||\n         (levt->type == EV_KEY && levt->code == BTN_TOOL_FINGER)    ||\n         (levt->type == EV_KEY && levt->code == BTN_TOOL_DOUBLETAP) ||\n         (levt->type == EV_KEY && levt->code == BTN_TOOL_TRIPLETAP)) {\n          if (state->fsm_state == TOUCHPAD_FSM_DRAG_START && timeout_passed( &state->timeout, &levt_time )) {\n               devt->flags     = DIEF_TIMESTAMP;\n               devt->timestamp = state->timeout;\n               devt->type      = DIET_BUTTONRELEASE;\n               devt->button    = DIBI_FIRST;\n\n               touchpad_fsm_init( state );\n\n               return 1;\n          }\n\n          return 0;\n     }\n\n     /* Use translate_event() for other events. */\n     if (!(levt->type == EV_KEY && levt->code == BTN_TOUCH) &&\n         !(levt->type == EV_ABS && (levt->code == ABS_X || levt->code == ABS_Y)))\n          return -1;\n\n     switch (state->fsm_state) {\n          case TOUCHPAD_FSM_START:\n               if (touchpad_finger_landing( levt )) {\n                    state->fsm_state = TOUCHPAD_FSM_MAIN;\n                    state->timeout   = levt_time;\n\n                    timeout_add( &state->timeout, &timeout );\n               }\n               return 0;\n\n          case TOUCHPAD_FSM_MAIN:\n               if (touchpad_finger_moving( levt )) {\n                    return touchpad_translate( state, touch_abs, levt, devt );\n               }\n               else if (touchpad_finger_leaving( levt )) {\n                    if (!timeout_passed( &state->timeout, &levt_time )) {\n                         devt->flags     = DIEF_TIMESTAMP;\n                         devt->timestamp = levt_time;\n                         devt->type      = DIET_BUTTONPRESS;\n                         devt->button    = DIBI_FIRST;\n\n                         touchpad_fsm_init( state );\n\n                         state->fsm_state = TOUCHPAD_FSM_DRAG_START;\n                         state->timeout   = levt_time;\n\n                         timeout_add( &state->timeout, &timeout );\n\n                         return 1;\n                    }\n                    else {\n                         touchpad_fsm_init( state );\n                    }\n               }\n               return 0;\n\n          case TOUCHPAD_FSM_DRAG_START:\n               if (timeout_passed( &state->timeout, &levt_time )) {\n                    devt->flags     = DIEF_TIMESTAMP;\n                    devt->timestamp = state->timeout;\n                    devt->type      = DIET_BUTTONRELEASE;\n                    devt->button    = DIBI_FIRST;\n\n                    touchpad_fsm_init( state );\n\n                    return 1;\n               }\n               else {\n                    if (touchpad_finger_landing( levt )) {\n                         state->fsm_state = TOUCHPAD_FSM_DRAG_MAIN;\n                         state->timeout   = levt_time;\n\n                         timeout_add( &state->timeout, &timeout );\n                    }\n               }\n               return 0;\n\n          case TOUCHPAD_FSM_DRAG_MAIN:\n               if (touchpad_finger_moving( levt )) {\n                    return touchpad_translate( state, touch_abs, levt, devt );\n               }\n               else if (touchpad_finger_leaving( levt )) {\n                    devt->flags     = DIEF_TIMESTAMP;\n                    devt->timestamp = levt_time;\n                    devt->type      = DIET_BUTTONRELEASE;\n                    devt->button    = DIBI_FIRST;\n\n                    touchpad_fsm_init( state );\n\n                    return 1;\n               }\n               return 0;\n\n          default:\n               return 0;\n     }\n\n     return 0;\n}\n\n/**********************************************************************************************************************/\n\nstatic DFBInputDeviceKeySymbol\nkeyboard_get_symbol( int                             code,\n                     unsigned short                  value,\n                     DFBInputDeviceKeymapSymbolIndex level )\n{\n     unsigned char type  = KTYP( value );\n     unsigned char index = KVAL( value );\n     int           base  = (level == DIKSI_BASE);\n\n     switch (type) {\n          case KT_FN:\n               if (index < 20)\n                    return DFB_FUNCTION_KEY(index + 1);\n               break;\n          case KT_LETTER:\n          case KT_LATIN:\n               switch (index) {\n                    case 0x1c:\n                         return DIKS_PRINT;\n                    case 0x7f:\n                         return DIKS_BACKSPACE;\n                    case 0xa4:\n                         return 0x20ac; /* euro currency sign */\n                    default:\n                         return index;\n               }\n               break;\n          case KT_DEAD:\n               switch (value) {\n                    case K_DGRAVE:\n                         return DIKS_DEAD_GRAVE;\n                    case K_DACUTE:\n                         return DIKS_DEAD_ACUTE;\n                    case K_DCIRCM:\n                         return DIKS_DEAD_CIRCUMFLEX;\n                    case K_DTILDE:\n                         return DIKS_DEAD_TILDE;\n                    case K_DDIERE:\n                         return DIKS_DEAD_DIAERESIS;\n                    case K_DCEDIL:\n                         return DIKS_DEAD_CEDILLA;\n                    default:\n                         break;\n               }\n               break;\n          case KT_PAD:\n               if (index <= 9 && level != DIKSI_BASE)\n                    return DIKS_0 + index;\n               break;\n     }\n\n     switch (value) {\n          case K_LEFT:    return DIKS_CURSOR_LEFT;\n          case K_RIGHT:   return DIKS_CURSOR_RIGHT;\n          case K_UP:      return DIKS_CURSOR_UP;\n          case K_DOWN:    return DIKS_CURSOR_DOWN;\n          case K_ENTER:   return DIKS_ENTER;\n          case K_CTRL:    return DIKS_CONTROL;\n          case K_SHIFT:   return DIKS_SHIFT;\n          case K_ALT:     return DIKS_ALT;\n          case K_ALTGR:   return DIKS_ALTGR;\n          case K_INSERT:  return DIKS_INSERT;\n          case K_REMOVE:  return DIKS_DELETE;\n          case K_FIND:    return DIKS_HOME;\n          case K_SELECT:  return DIKS_END;\n          case K_PGUP:    return DIKS_PAGE_UP;\n          case K_PGDN:    return DIKS_PAGE_DOWN;\n          case K_NUM:     return DIKS_NUM_LOCK;\n          case K_HOLD:    return DIKS_SCROLL_LOCK;\n          case K_PAUSE:   return DIKS_PAUSE;\n          case K_BREAK:   return DIKS_BREAK;\n          case K_CAPS:    return DIKS_CAPS_LOCK;\n          case K_P0:      return DIKS_INSERT;\n          case K_P1:      return DIKS_END;\n          case K_P2:      return DIKS_CURSOR_DOWN;\n          case K_P3:      return DIKS_PAGE_DOWN;\n          case K_P4:      return DIKS_CURSOR_LEFT;\n          case K_P5:      return DIKS_BEGIN;\n          case K_P6:      return DIKS_CURSOR_RIGHT;\n          case K_P7:      return DIKS_HOME;\n          case K_P8:      return DIKS_CURSOR_UP;\n          case K_P9:      return DIKS_PAGE_UP;\n          case K_PPLUS:   return DIKS_PLUS_SIGN;\n          case K_PMINUS:  return DIKS_MINUS_SIGN;\n          case K_PSTAR:   return DIKS_ASTERISK;\n          case K_PSLASH:  return DIKS_SLASH;\n          case K_PENTER:  return DIKS_ENTER;\n          case K_PCOMMA:  return base ? DIKS_DELETE : DIKS_COMMA;\n          case K_PDOT:    return base ? DIKS_DELETE : DIKS_PERIOD;\n          case K_PPARENL: return DIKS_PARENTHESIS_LEFT;\n          case K_PPARENR: return DIKS_PARENTHESIS_RIGHT;\n     }\n\n     /* Special keys not in the map. */\n\n     if (code == 99) /* print key */\n          return DIKS_PRINT;\n\n     if (code == 124) /* keypad equal key */\n          return DIKS_EQUALS_SIGN;\n\n     if (code == 125) /* left windows key */\n          return DIKS_META;\n\n     if (code == 126) /* right windows key */\n          return DIKS_META;\n\n     if (code == 127) /* context menu key */\n          return DIKS_SUPER;\n\n     return DIKS_NULL;\n}\n\nstatic DFBInputDeviceKeyIdentifier\nkeyboard_get_identifier( int            code,\n                         unsigned short value )\n{\n     unsigned char type  = KTYP( value );\n     unsigned char index = KVAL( value );\n\n     if (type == KT_PAD) {\n          if (index <= 9)\n               return DIKI_KP_0 + index;\n\n          switch (value) {\n               case K_PSLASH: return DIKI_KP_DIV;\n               case K_PSTAR:  return DIKI_KP_MULT;\n               case K_PMINUS: return DIKI_KP_MINUS;\n               case K_PPLUS:  return DIKI_KP_PLUS;\n               case K_PENTER: return DIKI_KP_ENTER;\n               case K_PCOMMA:\n               case K_PDOT:   return DIKI_KP_DECIMAL;\n          }\n     }\n\n     switch (code) {\n          case 12:  return DIKI_MINUS_SIGN;\n          case 13:  return DIKI_EQUALS_SIGN;\n          case 26:  return DIKI_BRACKET_LEFT;\n          case 27:  return DIKI_BRACKET_RIGHT;\n          case 39:  return DIKI_SEMICOLON;\n          case 40:  return DIKI_QUOTE_RIGHT;\n          case 41:  return DIKI_QUOTE_LEFT;\n          case 43:  return DIKI_BACKSLASH;\n          case 51:  return DIKI_COMMA;\n          case 52:  return DIKI_PERIOD;\n          case 53:  return DIKI_SLASH;\n          case 54:  return DIKI_SHIFT_R;\n          case 97:  return DIKI_CONTROL_R;\n          case 100: return DIKI_ALT_R;\n          case 124: return DIKI_KP_EQUAL;\n          case 125: return DIKI_META_L;\n          case 126: return DIKI_META_R;\n          case 127: return DIKI_SUPER_R;\n     }\n\n     return DIKI_UNKNOWN;\n}\n\nstatic unsigned short\nkeyboard_read_value( const LinuxInputData *data,\n                     unsigned char         table,\n                     unsigned char         index )\n{\n     struct kbentry entry;\n\n     entry.kb_table = table;\n     entry.kb_index = index;\n     entry.kb_value = 0;\n\n     if (ioctl( data->vt_fd, KDGKBENT, &entry )) {\n          D_PERROR( \"Input/Linux: KDGKBENT( table %d, index %d ) failed!\\n\", table, index );\n          return 0;\n     }\n\n     return entry.kb_value;\n}\n\n/**********************************************************************************************************************/\n\n/*\n * Translate a Linux input keycode into a DirectFB keycode.\n */\nstatic int\nkey_translate( unsigned short code )\n{\n     if (code < D_ARRAY_SIZE(basic_keycodes))\n          return basic_keycodes[code];\n\n     if (code >= KEY_OK)\n          if (code - KEY_OK < D_ARRAY_SIZE(ext_keycodes))\n               return ext_keycodes[code-KEY_OK];\n\n     return DIKI_UNKNOWN;\n}\n\n/*\n * Translate key and button events.\n */\nstatic bool\nkey_event( const struct input_event *levt,\n           DFBInputEvent            *devt )\n{\n     int code = levt->code;\n\n     /* Map touchscreen events to button mouse. */\n     if (code == BTN_TOUCH || code == BTN_TOOL_FINGER)\n          code = BTN_MOUSE;\n\n     if ((code >= BTN_MOUSE && code < BTN_JOYSTICK) || code == BTN_TOUCH) {\n          /* Ignore repeat events for buttons. */\n          if (levt->value == 2)\n               return false;\n\n          devt->type   = levt->value ? DIET_BUTTONPRESS : DIET_BUTTONRELEASE;\n          devt->button = DIBI_FIRST + code - BTN_MOUSE;\n     }\n     else {\n          int key = key_translate( code );\n\n          if (key == DIKI_UNKNOWN)\n               return false;\n\n          devt->type = levt->value ? DIET_KEYPRESS : DIET_KEYRELEASE;\n\n          if (DFB_KEY_TYPE( key ) == DIKT_IDENTIFIER) {\n               devt->key_id  = key;\n               devt->flags  |= DIEF_KEYID;\n          }\n          else {\n               devt->key_symbol  = key;\n               devt->flags      |= DIEF_KEYSYMBOL;\n          }\n\n          devt->key_code  = code;\n          devt->flags    |= DIEF_KEYCODE;\n     }\n\n     if (levt->value == 2)\n          devt->flags |= DIEF_REPEAT;\n\n     return true;\n}\n\n/*\n * Translate relative axis events.\n */\nstatic bool\nrel_event( const LinuxInputData     *data,\n           const struct input_event *levt,\n           DFBInputEvent            *devt )\n{\n     switch (levt->code) {\n          case REL_X:\n               devt->axis = DIAI_X;\n               devt->axisrel = levt->value * data->sensitivity / 0x100;\n               break;\n\n          case REL_Y:\n               devt->axis = DIAI_Y;\n               devt->axisrel = levt->value * data->sensitivity / 0x100;\n               break;\n\n          case REL_Z:\n          case REL_WHEEL:\n               devt->axis = DIAI_Z;\n               devt->axisrel = -levt->value;\n               break;\n\n          default:\n               if (levt->code > REL_MAX || levt->code > DIAI_LAST)\n                    return false;\n               devt->axis = levt->code;\n               devt->axisrel = levt->value;\n     }\n\n     devt->type   = DIET_AXISMOTION;\n     devt->flags |= DIEF_AXISREL;\n\n     return true;\n}\n\n/*\n * Translate absolute axis events.\n */\nstatic bool\nabs_event( const struct input_event *levt,\n           DFBInputEvent            *devt )\n{\n     switch (levt->code) {\n          case ABS_X:\n               devt->axis = DIAI_X;\n               break;\n\n          case ABS_Y:\n               devt->axis = DIAI_Y;\n               break;\n\n          case ABS_Z:\n          case ABS_WHEEL:\n               devt->axis = DIAI_Z;\n               break;\n\n          default:\n               if (levt->code >= ABS_PRESSURE || levt->code > DIAI_LAST)\n                    return false;\n               devt->axis = levt->code;\n     }\n\n     devt->type     = DIET_AXISMOTION;\n     devt->flags   |= DIEF_AXISABS;\n     devt->axisabs  = levt->value;\n\n     return true;\n}\n\n/*\n * Translate a Linux input event into a DirectFB input event.\n */\nstatic bool\ntranslate_event( const LinuxInputData     *data,\n                 const struct input_event *levt,\n                 DFBInputEvent            *devt )\n{\n     devt->flags             = DIEF_TIMESTAMP;\n     devt->timestamp.tv_sec  = levt->input_event_sec;\n     devt->timestamp.tv_usec = levt->input_event_usec;\n\n     switch (levt->type) {\n          case EV_KEY:\n               return key_event( levt, devt );\n\n          case EV_REL:\n               return rel_event( data, levt, devt );\n\n          case EV_ABS:\n               return abs_event( levt, devt );\n\n          default:\n               ;\n     }\n\n     return false;\n}\n\n/**********************************************************************************************************************/\n\nstatic void\nset_led( const LinuxInputData *data,\n         int                   led,\n         int                   state )\n{\n     struct input_event levt;\n     int                res;\n\n     D_UNUSED_P( res );\n\n     memset( &levt, 0, sizeof(levt) );\n     levt.type  = EV_LED;\n     levt.code  = led;\n     levt.value = state;\n\n     res = write( data->fd, &levt, sizeof(levt) );\n}\n\nstatic void\nflush_xy( LinuxInputData *data,\n          bool            last )\n{\n     DFBInputEvent devt = { .type = DIET_UNKNOWN };\n\n     if (data->dx) {\n          devt.type    = DIET_AXISMOTION;\n          devt.flags   = DIEF_AXISREL;\n          devt.axis    = DIAI_X;\n          devt.axisrel = data->dx;\n\n          /* Signal immediately following event. */\n          if (!last || data->dy)\n               devt.flags |= DIEF_FOLLOW;\n\n          dfb_input_dispatch( data->device, &devt );\n\n          data->dx = 0;\n     }\n\n     if (data->dy) {\n          devt.type    = DIET_AXISMOTION;\n          devt.flags   = DIEF_AXISREL;\n          devt.axis    = DIAI_Y;\n          devt.axisrel = data->dy;\n\n          /* Signal immediately following event. */\n          if (!last)\n               devt.flags |= DIEF_FOLLOW;\n\n          dfb_input_dispatch( data->device, &devt );\n\n          data->dy = 0;\n     }\n}\n\n/**********************************************************************************************************************/\n\nstatic void *\ndevinput_event_thread( DirectThread *thread,\n                       void         *arg )\n{\n     LinuxInputData            *data = arg;\n     int                        status;\n     int                        fdmax;\n     unsigned int               i;\n     bool                       mouse_motion_compression;\n     struct touchpad_fsm_state  fsm_state;\n\n     D_DEBUG_AT( Linux_Input, \"%s()\\n\", __FUNCTION__ );\n\n     /* Mouse motion event compression. */\n     if (direct_config_has_name( \"motion-compression\" ) && !direct_config_has_name( \"no-motion-compression\" ))\n          mouse_motion_compression = true;\n     else\n          mouse_motion_compression = false;\n\n     fdmax = MAX( data->fd, data->quitpipe[0] );\n\n     /* Query the touchpad min/max coordinates. */\n     if (data->touchpad) {\n          struct input_absinfo absinfo;\n\n          touchpad_fsm_init( &fsm_state );\n\n          ioctl( data->fd, EVIOCGABS( ABS_X ), &absinfo );\n          fsm_state.x.min = absinfo.minimum;\n          fsm_state.x.max = absinfo.maximum;\n\n          ioctl( data->fd, EVIOCGABS( ABS_Y ), &absinfo );\n          fsm_state.y.min = absinfo.minimum;\n          fsm_state.y.max = absinfo.maximum;\n     }\n\n     /* Query the keys. */\n     if (data->has_keys) {\n          unsigned long keybit[NBITS(KEY_CNT)];\n          unsigned long keystate[NBITS(KEY_CNT)];\n\n          /* Get key bits. */\n          ioctl( data->fd, EVIOCGBIT( EV_KEY, sizeof(keybit) ), keybit );\n\n          /* Get key states. */\n          ioctl( data->fd, EVIOCGKEY( sizeof(keystate) ), keystate );\n\n          /* For each key, synthetize a press or release event depending on the key state. */\n          for (i = 0; i <= KEY_CNT; i++) {\n               if (test_bit( i, keybit )) {\n                    const int key = key_translate( i );\n\n                    if (DFB_KEY_TYPE( key ) == DIKT_IDENTIFIER) {\n                         DFBInputEvent devt;\n\n                         devt.type     = test_bit( i, keystate ) ? DIET_KEYPRESS : DIET_KEYRELEASE;\n                         devt.flags    = DIEF_KEYID | DIEF_KEYCODE;\n                         devt.key_id   = key;\n                         devt.key_code = i;\n\n                         dfb_input_dispatch( data->device, &devt );\n                    }\n               }\n          }\n     }\n\n     while (1) {\n          DFBInputEvent devt = { .type = DIET_UNKNOWN };\n          fd_set        set;\n          ssize_t       len;\n\n          /* Get input event. */\n          FD_ZERO( &set );\n          FD_SET( data->fd, &set );\n          FD_SET( data->quitpipe[0], &set );\n\n          if (data->touchpad && timeout_is_set( &fsm_state.timeout )) {\n               struct timeval time;\n               gettimeofday( &time, NULL );\n\n               if (!timeout_passed( &fsm_state.timeout, &time )) {\n                    struct timeval timeout = fsm_state.timeout;\n\n                    timeout_sub( &timeout, &time );\n\n                    status = select( fdmax + 1, &set, NULL, NULL, &timeout );\n               }\n               else\n                    status = 0;\n          }\n          else\n               status = select( fdmax + 1, &set, NULL, NULL, NULL );\n\n          if (status < 0 && errno != EINTR)\n               break;\n\n          if (status > 0 && FD_ISSET( data->quitpipe[0], &set ))\n               break;\n\n          if (status < 0)\n               continue;\n\n          /* Check timeout. */\n          if (status == 0) {\n               if (data->touchpad && touchpad_fsm( &fsm_state, data->touch_abs, NULL, &devt ) > 0)\n                    dfb_input_dispatch( data->device, &devt );\n\n               continue;\n          }\n\n          len = read( data->fd, input_events, sizeof(input_events) );\n          if (len < 0 && errno != EINTR)\n               break;\n\n          if (len <= 0)\n               continue;\n\n          for (i = 0; i < len / sizeof(input_events[0]); i++) {\n               DFBInputEvent evt = { .type = DIET_UNKNOWN };\n\n               if (data->touchpad) {\n                    status = touchpad_fsm( &fsm_state, data->touch_abs, &input_events[i], &evt );\n                    if (status < 0) {\n                         /* Not handled. Try the direct approach. */\n                         if (!translate_event( data, &input_events[i], &evt ))\n                              continue;\n                    }\n                    else if (status == 0) {\n                         /* Handled but no further processing is necessary. */\n                         continue;\n                    }\n               }\n               else {\n                    if (!translate_event( data, &input_events[i], &evt ))\n                         continue;\n               }\n\n               /* Flush previous event with DIEF_FOLLOW. */\n               if (devt.type != DIET_UNKNOWN) {\n                    flush_xy( data, false );\n\n                    /* Signal immediately following event. */\n                    devt.flags |= DIEF_FOLLOW;\n\n                    dfb_input_dispatch( data->device, &devt );\n\n                    if (data->has_leds && (devt.locks != data->locks)) {\n                         set_led( data, LED_SCROLLL, devt.locks & DILS_SCROLL );\n                         set_led( data, LED_NUML,    devt.locks & DILS_NUM );\n                         set_led( data, LED_CAPSL,   devt.locks & DILS_CAPS );\n                         data->locks = devt.locks;\n                    }\n\n                    devt.type  = DIET_UNKNOWN;\n                    devt.flags = DIEF_NONE;\n               }\n\n               devt = evt;\n\n               if (D_FLAGS_IS_SET( devt.flags, DIEF_AXISREL ) &&\n                   devt.type == DIET_AXISMOTION               &&\n                   mouse_motion_compression) {\n                    switch (devt.axis) {\n                         case DIAI_X:\n                              data->dx += devt.axisrel;\n                              continue;\n\n                         case DIAI_Y:\n                              data->dy += devt.axisrel;\n                              continue;\n\n                         default:\n                              break;\n                    }\n               }\n          }\n\n          /* Flush last event without DIEF_FOLLOW. */\n          if (devt.type != DIET_UNKNOWN) {\n               flush_xy( data, false );\n\n               /* Event is dispatched. */\n               dfb_input_dispatch( data->device, &devt );\n\n               if (data->has_leds && (devt.locks != data->locks)) {\n                    set_led( data, LED_SCROLLL, devt.locks & DILS_SCROLL );\n                    set_led( data, LED_NUML,    devt.locks & DILS_NUM );\n                    set_led( data, LED_CAPSL,   devt.locks & DILS_CAPS );\n                    data->locks = devt.locks;\n               }\n          }\n          else\n               flush_xy( data, true );\n     }\n\n     D_DEBUG_AT( Linux_Input, \"DevInput Event thread terminated\\n\" );\n\n     return NULL;\n}\n\nstatic void\nget_device_info( int              fd,\n                 InputDeviceInfo *device_info,\n                 bool            *touchpad )\n{\n     int             i;\n     unsigned int    num_keys     = 0;\n     unsigned int    num_ext_keys = 0;\n     unsigned int    num_buttons  = 0;\n     unsigned int    num_rels     = 0;\n     unsigned int    num_abs      = 0;\n     unsigned long   evbit[NBITS(EV_CNT)];\n     unsigned long   keybit[NBITS(KEY_CNT)];\n     unsigned long   relbit[NBITS(REL_CNT)];\n     unsigned long   absbit[NBITS(ABS_CNT)];\n     struct input_id devinfo;\n\n     D_DEBUG_AT( Linux_Input, \"%s()\\n\", __FUNCTION__ );\n\n     /* Get device name. */\n     ioctl( fd, EVIOCGNAME( DFB_INPUT_DEVICE_DESC_NAME_LENGTH - 1 ), device_info->desc.name );\n\n     D_DEBUG_AT( Linux_Input, \"  -> name '%s'\\n\", device_info->desc.name );\n\n     /* Set device vendor. */\n     snprintf( device_info->desc.vendor, DFB_INPUT_DEVICE_DESC_VENDOR_LENGTH, \"Linux\" );\n\n     /* Get event type bits. */\n     ioctl( fd, EVIOCGBIT( 0, sizeof(evbit) ), evbit );\n\n     if (test_bit( EV_KEY, evbit )) {\n          /* Get keyboard bits. */\n          ioctl( fd, EVIOCGBIT( EV_KEY, sizeof(keybit) ), keybit );\n\n          /* Count typical keyboard keys only. */\n          for (i = KEY_Q; i <= KEY_M; i++)\n               if (test_bit( i, keybit ))\n                    num_keys++;\n\n          /* This might be a keyboard with just cursor keys (typically on front panels), handle as remote control. */\n          if (!num_keys)\n               for (i = KEY_HOME; i <= KEY_PAGEDOWN; i++)\n                    if (test_bit( i, keybit ))\n                         num_ext_keys++;\n\n          for (i = KEY_OK; i < KEY_CNT; i++)\n               if (test_bit( i, keybit ))\n                    num_ext_keys++;\n\n          for (i = BTN_MOUSE; i < BTN_JOYSTICK; i++)\n               if (test_bit( i, keybit ))\n                    num_buttons++;\n\n          if (num_keys || num_ext_keys)\n               device_info->desc.caps |= DICAPS_KEYS;\n     }\n\n     if (test_bit( EV_REL, evbit )) {\n          /* Get bits for relative axes. */\n          ioctl( fd, EVIOCGBIT( EV_REL, sizeof(relbit) ), relbit );\n\n          for (i = 0; i < REL_CNT; i++)\n               if (test_bit( i, relbit ))\n                    num_rels++;\n     }\n\n     if (test_bit( EV_ABS, evbit )) {\n          /* Get bits for absolute axes. */\n          ioctl( fd, EVIOCGBIT( EV_ABS, sizeof(absbit) ), absbit );\n\n          for (i = 0; i < ABS_PRESSURE; i++)\n               if (test_bit( i, absbit ))\n                    num_abs++;\n     }\n\n     /* Touchpad */\n     if (test_bit( EV_KEY, evbit ) &&\n         test_bit( BTN_TOUCH, keybit ) &&\n         test_bit( BTN_TOOL_FINGER, keybit) &&\n         test_bit( EV_ABS, evbit ) &&\n         test_bit( ABS_X, absbit ) &&\n         test_bit( ABS_Y, absbit ) &&\n         test_bit( ABS_PRESSURE, absbit ))\n          *touchpad = true;\n     else\n          *touchpad = false;\n\n     /* Mouse, Touchscreen or Joystick */\n     if ((test_bit( EV_KEY, evbit ) && (test_bit( BTN_TOUCH, keybit ) || test_bit( BTN_TOOL_FINGER, keybit ))) ||\n         ((num_rels >= 2 && num_buttons) || (num_abs == 2 && num_buttons == 1)))\n          device_info->desc.type |= DIDTF_MOUSE;\n     else if (num_abs && num_buttons)\n          device_info->desc.type |= DIDTF_JOYSTICK;\n\n     /* Keyboard */\n     if (num_keys > 20) {\n          device_info->desc.type |= DIDTF_KEYBOARD;\n\n          device_info->desc.min_keycode = 0;\n          device_info->desc.max_keycode = 127;\n     }\n\n     /* Remote Control */\n     if (num_ext_keys) {\n          device_info->desc.type |= DIDTF_REMOTE;\n     }\n\n     /* Buttons */\n     if (num_buttons) {\n          device_info->desc.caps       |= DICAPS_BUTTONS;\n          device_info->desc.max_button  = DIBI_FIRST + num_buttons - 1;\n     }\n\n     /* Axes */\n     if (num_rels || num_abs) {\n          device_info->desc.caps     |= DICAPS_AXES;\n          device_info->desc.max_axis  = DIAI_FIRST + MAX( num_rels, num_abs ) - 1;\n     }\n\n     /* Primary input device */\n     if (device_info->desc.type & DIDTF_KEYBOARD)\n          device_info->prefered_id = DIDID_KEYBOARD;\n     else if (device_info->desc.type & DIDTF_REMOTE)\n          device_info->prefered_id = DIDID_REMOTE;\n     else if (device_info->desc.type & DIDTF_JOYSTICK)\n          device_info->prefered_id = DIDID_JOYSTICK;\n     else if (device_info->desc.type & DIDTF_MOUSE)\n          device_info->prefered_id = DIDID_MOUSE;\n     else\n          device_info->prefered_id = DIDID_ANY;\n\n     /* Get VID and PID information. */\n     ioctl( fd, EVIOCGID, &devinfo );\n\n     device_info->desc.vendor_id  = devinfo.vendor;\n     device_info->desc.product_id = devinfo.product;\n\n     D_DEBUG_AT( Linux_Input, \"  -> ids %d/%d\\n\", device_info->desc.vendor_id, device_info->desc.product_id );\n}\n\nstatic bool\ncheck_device( const char *device )\n{\n     int             err;\n     int             fd;\n     InputDeviceInfo device_info;\n     bool            touchpad;\n     bool            linux_input_grab;\n     bool            linux_input_ir_only;\n\n     D_DEBUG_AT( Linux_Input, \"%s( '%s' )\\n\", __FUNCTION__, device );\n\n     /* Check if we are able to open the device. */\n     fd = open( device, O_RDWR );\n     if (fd < 0) {\n          D_DEBUG_AT( Linux_Input, \"  -> open failed!\\n\" );\n          return false;\n     }\n\n     /* Grab device. */\n     if (direct_config_has_name( \"linux-input-grab\" ) && !direct_config_has_name( \"no-linux-input-grab\" ))\n          linux_input_grab = true;\n     else\n          linux_input_grab = false;\n\n     /* Ignore non-IR device. */\n     if (direct_config_has_name( \"linux-input-ir-only\" ) && !direct_config_has_name( \"no-linux-input-ir-only\" ))\n          linux_input_ir_only = true;\n     else\n          linux_input_ir_only = false;\n\n     if (linux_input_grab) {\n          err = ioctl( fd, EVIOCGRAB, 1 );\n          if (err) {\n               D_PERROR( \"Input/Linux: Could not grab device!\\n\" );\n               close( fd );\n               return false;\n          }\n     }\n\n     /* Get device information. */\n     memset( &device_info, 0, sizeof(InputDeviceInfo) );\n\n     device_info.desc.min_keycode = -1;\n     device_info.desc.max_keycode = -1;\n\n     get_device_info( fd, &device_info, &touchpad );\n\n     if (linux_input_grab)\n          ioctl( fd, EVIOCGRAB, 0 );\n\n     close( fd );\n\n     if (!device_info.desc.caps) {\n         D_DEBUG_AT( Linux_Input, \"  -> no caps!\\n\" );\n         return false;\n     }\n\n     if (!linux_input_ir_only || (device_info.desc.type & DIDTF_REMOTE))\n          return true;\n\n     return false;\n}\n\n/**********************************************************************************************************************/\n\nstatic int\ndriver_get_available()\n{\n     const char   *value;\n     FusionVector  linux_input_devices;\n     int           i;\n     char         *skipdev;\n     char          buf[32];\n\n     if (num_devices) {\n          for (i = 0; i < num_devices; i++) {\n               D_FREE( device_names[i] );\n               device_names[i] = NULL;\n          }\n\n          num_devices = 0;\n\n          return 0;\n     }\n\n     /* Use the devices specified in the configuration. */\n     if ((value = direct_config_get_value( \"linux-input-devices\" ))) {\n          const char *device;\n\n          fusion_vector_init( &linux_input_devices, 2, NULL );\n\n          config_values_parse( &linux_input_devices, value );\n\n          fusion_vector_foreach (device, i, linux_input_devices) {\n               if (num_devices >= MAX_LINUX_INPUT_DEVICES)\n                    break;\n\n               /* Update the device_names and device_nums array entries too. */\n               if (check_device( device )) {\n                    D_ASSERT( device_names[num_devices] == NULL );\n                    device_names[num_devices] = D_STRDUP( device );\n                    device_nums[num_devices] = i;\n                    num_devices++;\n               }\n          }\n\n          config_values_free( &linux_input_devices );\n\n          return num_devices;\n     }\n\n     /* No devices specified. Try to guess some, set SKIP_INPUT_DEVICE to skip checking the specified input device. */\n     skipdev = getenv( \"SKIP_INPUT_DEVICE\" );\n\n     for (i = 0; i < MAX_LINUX_INPUT_DEVICES; i++) {\n          snprintf( buf, sizeof(buf), \"/dev/input/event%d\", i );\n\n          /* Initialize device_names and device_nums array entries. */\n          device_names[i] = NULL;\n          device_nums[i]  = MAX_LINUX_INPUT_DEVICES;\n\n          if (skipdev && !strcmp( skipdev, buf ))\n               continue;\n\n          /* Update the device_names and device_nums array entries too. */\n          if (check_device( buf )) {\n               D_ASSERT( device_names[num_devices] == NULL );\n               device_names[num_devices] = D_STRDUP( buf );\n               device_nums[num_devices] = i;\n               num_devices++;\n          }\n     }\n\n     return num_devices;\n}\n\nstatic void\ndriver_get_info( InputDriverInfo *driver_info )\n{\n     driver_info->version.major = 0;\n     driver_info->version.minor = 1;\n\n     snprintf( driver_info->name,   DFB_INPUT_DRIVER_INFO_NAME_LENGTH,   \"Linux Input\" );\n     snprintf( driver_info->vendor, DFB_INPUT_DRIVER_INFO_VENDOR_LENGTH, \"DirectFB\" );\n}\n\nstatic DFBResult\ndriver_open_device( CoreInputDevice  *device,\n                    unsigned int      number,\n                    InputDeviceInfo  *device_info,\n                    void            **driver_data )\n{\n     LinuxInputData *data;\n     int             err;\n     int             fd;\n     bool            linux_input_grab;\n     unsigned long   ledbit[NBITS(LED_CNT)];\n     bool            touchpad;\n\n     D_DEBUG_AT( Linux_Input, \"%s()\\n\", __FUNCTION__ );\n\n     /* Open device. */\n     fd = open( device_names[number], O_RDWR );\n     if (fd < 0) {\n          D_PERROR( \"Input/Linux: Could not open device '%s'!\\n\", device_names[number] );\n          return DFB_INIT;\n     }\n\n     /* Grab device. */\n     if (direct_config_has_name( \"linux-input-grab\" ) && !direct_config_has_name( \"no-linux-input-grab\" ))\n          linux_input_grab = true;\n     else\n          linux_input_grab = false;\n\n     if (linux_input_grab) {\n          err = ioctl( fd, EVIOCGRAB, 1 );\n          if (err) {\n               D_PERROR( \"Input/Linux: Could not grab device!\\n\" );\n               close( fd );\n               return DFB_INIT;\n          }\n     }\n\n     /* Fill device information. */\n     get_device_info( fd, device_info, &touchpad );\n\n     /* Allocate and fill private data. */\n     data = D_CALLOC( 1, sizeof(LinuxInputData) );\n     if (!data) {\n          if (linux_input_grab)\n               ioctl( fd, EVIOCGRAB, 0 );\n          close( fd );\n          return D_OOM();\n     }\n\n     data->device   = device;\n     data->index    = number;\n     data->fd       = fd;\n     data->grab     = linux_input_grab;\n     data->has_keys = (device_info->desc.caps & DICAPS_KEYS) != 0;\n\n     /* Check if the device has LEDs. */\n     err = ioctl( fd, EVIOCGBIT( EV_LED, sizeof(ledbit) ), ledbit );\n     if (err < 0)\n          D_PERROR( \"Input/Linux: Could not get LEDs bits!\" );\n     else\n          data->has_leds = test_bit( LED_SCROLLL, ledbit ) ||\n                           test_bit( LED_NUML,    ledbit ) ||\n                           test_bit( LED_CAPSL,   ledbit );\n\n     if (data->has_leds) {\n          /* Get LEDs state. */\n          err = ioctl( fd, EVIOCGLED( sizeof(data->led_state) ), data->led_state );\n          if (err < 0) {\n               D_PERROR( \"Input/Linux: Could not get LEDs state!\" );\n               goto error;\n          }\n\n          /* Turn off LEDs. */\n          set_led( data, LED_SCROLLL, 0 );\n          set_led( data, LED_NUML,    0 );\n          set_led( data, LED_CAPSL,   0 );\n     }\n\n     data->touchpad = touchpad;\n\n     if (data->touchpad) {\n         if (direct_config_has_name( \"linux-input-touch-abs\" ) && !direct_config_has_name( \"no-linux-input-touch-abs\" ))\n              data->touch_abs = true;\n     }\n\n     data->sensitivity = 0x100;\n\n     if (device_info->desc.min_keycode >= 0 && device_info->desc.max_keycode > device_info->desc.min_keycode) {\n          data->vt_fd = open( \"/dev/tty0\", O_RDWR | O_NOCTTY );\n\n          if (data->vt_fd < 0)\n               D_WARN( \"no keymap support\" );\n     }\n\n     /* Open a pipe to awake the devinput event thread when we want to quit. */\n     err = pipe( data->quitpipe );\n     if (err < 0) {\n          D_PERROR( \"Input/Linux: Could not open quit pipe!\" );\n          goto error;\n     }\n\n     /* Start devinput event thread. */\n     data->thread = direct_thread_create( DTT_INPUT, devinput_event_thread, data, \"DevInput Event\" );\n\n     *driver_data = data;\n\n     return DFB_OK;\n\nerror:\n     if (data->grab)\n          ioctl( fd, EVIOCGRAB, 0 );\n     if (data->vt_fd >= 0)\n          close( data->vt_fd );\n     close( fd );\n     D_FREE( data );\n\n     return DFB_INIT;\n}\n\nstatic DFBResult\ndriver_get_keymap_entry( CoreInputDevice           *device,\n                         void                      *driver_data,\n                         DFBInputDeviceKeymapEntry *entry )\n{\n     LinuxInputData              *data = driver_data;\n     int                          orig_mode;\n     int                          code = entry->code;\n     unsigned short               value;\n     DFBInputDeviceKeyIdentifier  identifier;\n\n     if (data->vt_fd < 0)\n          return DFB_UNSUPPORTED;\n\n     /* Save keyboard mode in order to restore it later. */\n     if (ioctl( data->vt_fd, KDGKBMODE, &orig_mode ) < 0) {\n          D_PERROR( \"Input/Linux: KDGKBMODE failed!\\n\" );\n          return DFB_INIT;\n     }\n\n     /* Switch to unicode mode to get the full keymap. */\n     if (ioctl( data->vt_fd, KDSKBMODE, K_UNICODE ) < 0) {\n          D_PERROR( \"Input/Linux: K_UNICODE failed!\\n\" );\n          return DFB_INIT;\n     }\n\n     /* Fetch the base level. */\n     value = keyboard_read_value( driver_data, K_NORMTAB, code );\n\n     /* Get the identifier for basic mapping. */\n     identifier = keyboard_get_identifier( code, value );\n\n     /* CapsLock is effective. */\n     if (KTYP( value ) == KT_LETTER)\n          entry->locks |= DILS_CAPS;\n\n     /* NumLock is effective. */\n     if (identifier >= DIKI_KP_DECIMAL && identifier <= DIKI_KP_9)\n          entry->locks |= DILS_NUM;\n\n     /* Write identifier to entry. */\n     entry->identifier = identifier;\n\n     /* Write base level symbol to entry. */\n     entry->symbols[DIKSI_BASE] = keyboard_get_symbol( code, value, DIKSI_BASE );\n\n     /* Fetch the shifted base level. */\n     value = keyboard_read_value( driver_data, K_SHIFTTAB, entry->code );\n\n     /* Write shifted base level symbol to entry. */\n     entry->symbols[DIKSI_BASE_SHIFT] = keyboard_get_symbol( code, value, DIKSI_BASE_SHIFT );\n\n     /* Fetch the alternative level. */\n     value = keyboard_read_value( driver_data, K_ALTTAB, entry->code );\n\n     /* Write alternative level symbol to entry. */\n     entry->symbols[DIKSI_ALT] = keyboard_get_symbol( code, value, DIKSI_ALT );\n\n     /* Fetch the shifted alternative level. */\n     value = keyboard_read_value( driver_data, K_ALTSHIFTTAB, entry->code );\n\n     /* Write shifted alternative level symbol to entry. */\n     entry->symbols[DIKSI_ALT_SHIFT] = keyboard_get_symbol( code, value, DIKSI_ALT_SHIFT );\n\n     /* Switch back to original keyboard mode. */\n     if (ioctl( data->vt_fd, KDSKBMODE, orig_mode ) < 0) {\n          D_PERROR( \"Input/Linux: KDSKBMODE failed!\\n\" );\n          return DFB_INIT;\n     }\n\n     return DFB_OK;\n}\n\nstatic void\ndriver_close_device( void *driver_data )\n{\n     LinuxInputData *data = driver_data;\n     ssize_t         res;\n\n     D_UNUSED_P( res );\n\n     D_DEBUG_AT( Linux_Input, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( data != NULL );\n\n     /* Write to the quit pipe to terminate the devinput event thread. */\n     res = write( data->quitpipe[1], \" \", 1 );\n\n     direct_thread_join( data->thread );\n     direct_thread_destroy( data->thread );\n\n     close( data->quitpipe[0] );\n     close( data->quitpipe[1] );\n\n     /* Restore LEDs state. */\n     if (data->has_leds) {\n          set_led( data, LED_SCROLLL, test_bit( LED_SCROLLL, data->led_state ) );\n          set_led( data, LED_NUML,    test_bit( LED_NUML,    data->led_state ) );\n          set_led( data, LED_CAPSL,   test_bit( LED_CAPSL,   data->led_state ) );\n     }\n\n     if (data->grab)\n          ioctl( data->fd, EVIOCGRAB, 0 );\n\n     if (data->vt_fd >= 0)\n          close( data->vt_fd );\n\n     close( data->fd );\n\n     D_FREE( data );\n}\n\n#if DIRECT_BUILD_NETWORK\n\n/**********************************************************************************************************************\n ********************************* Hot-plug functions *****************************************************************\n **********************************************************************************************************************/\n\ntypedef struct {\n     CoreDFB *core;\n     void    *driver;\n} HotplugThreadData;\n\n/* Socket file descriptor for getting udev events. */\nstatic int              socket_fd = 0;\n\n/* Thread for managing devinput hot-plug. */\nstatic DirectThread    *hotplug_thread = NULL;\n\n/* Pipe file descriptor for terminating the devinput hot-plug thread. */\nstatic int              hotplug_quitpipe[2];\n\n/* Mutex for handling the driver suspended. */\nstatic pthread_mutex_t  driver_suspended_lock;\n\n/* Flag for indicating that the driver is suspended. */\nstatic bool             driver_suspended = false;\n\n/*\n * Register /dev/input/eventX device node into the driver. Called when a new device node is created.\n */\nstatic DFBResult\nregister_device_node( int  event_num,\n                      int *index )\n{\n     int  i;\n     char buf[32];\n\n     D_DEBUG_AT( Linux_Input, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( index != NULL );\n\n     for (i = 0; i < MAX_LINUX_INPUT_DEVICES; i++) {\n          if (device_nums[i] == MAX_LINUX_INPUT_DEVICES) {\n               device_nums[i] = event_num;\n               *index = i;\n               num_devices++;\n\n               snprintf( buf, sizeof(buf), \"/dev/input/event%d\", event_num );\n\n               D_ASSERT( device_names[i] == NULL );\n               device_names[i] = D_STRDUP( buf );\n\n               return DFB_OK;\n          }\n     }\n\n     /* Too many input devices plugged in to be handled. */\n     D_DEBUG_AT( Linux_Input, \"  -> the amount of devices registered exceeds the limit %d\\n\", MAX_LINUX_INPUT_DEVICES );\n\n     return DFB_UNSUPPORTED;\n}\n\n/*\n * Unregister /dev/input/eventX device node from the driver. Called when a new device node is removed.\n */\nstatic DFBResult\nunregister_device_node( int  event_num,\n                        int *index )\n{\n     int i;\n\n     D_DEBUG_AT( Linux_Input, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( index != NULL );\n\n     for (i = 0; i < num_devices; i++) {\n          if (device_nums[i] == event_num) {\n               device_nums[i] = MAX_LINUX_INPUT_DEVICES;\n               num_devices--;\n               *index = i;\n\n               D_FREE( device_names[i] );\n               device_names[i] = NULL;\n\n               return DFB_OK;\n          }\n     }\n\n     return DFB_UNSUPPORTED;\n}\n\nstatic void *\ndevinput_hotplug_thread( DirectThread *thread,\n                         void         *arg )\n{\n     HotplugThreadData  *data = arg;\n     int                 status;\n     int                 fdmax;\n     struct sockaddr_un  sock_addr;\n\n     D_DEBUG_AT( Linux_Input, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( data != NULL );\n     D_ASSERT( data->core != NULL );\n     D_ASSERT( data->driver != NULL );\n\n     /* Open and bind the socket /org/kernel/udev/monitor */\n     socket_fd = socket( AF_UNIX, SOCK_DGRAM, 0 );\n     if (socket_fd == -1)\n          goto error;\n\n     memset( &sock_addr, 0, sizeof(sock_addr) );\n     sock_addr.sun_family = AF_UNIX;\n     strncpy( &sock_addr.sun_path[1], \"/org/kernel/udev/monitor\", sizeof(sock_addr.sun_path) - 1 );\n\n     status = bind( socket_fd, (struct sockaddr*) &sock_addr,\n                    sizeof(sock_addr.sun_family) + 1 + strlen( &sock_addr.sun_path[1] ) );\n     if (status < 0)\n          goto error;\n\n     fdmax = MAX( socket_fd, hotplug_quitpipe[0] );\n\n     while (1) {\n          DFBResult  ret;\n          fd_set     set;\n          char       udev_event[1024];\n          ssize_t    len;\n          char      *pos;\n          char      *event_content;\n          int        device_num, index;\n\n          /* Get udev event. */\n          FD_ZERO( &set );\n          FD_SET( socket_fd, &set );\n          FD_SET( hotplug_quitpipe[0], &set );\n\n          status = select( fdmax + 1, &set, NULL, NULL, NULL );\n          if (status < 0 && errno != EINTR)\n               break;\n\n          if (FD_ISSET( hotplug_quitpipe[0], &set ))\n               break;\n\n          if (FD_ISSET( socket_fd, &set )) {\n               len = recv( socket_fd, udev_event, sizeof(udev_event), 0 );\n               if (len <= 0) {\n                    D_DEBUG_AT( Linux_Input, \"Error receiving uevent message\\n\" );\n                    continue;\n               }\n          }\n\n          /* Analyze udev event. */\n          pos = strchr( udev_event, '@' );\n          if (pos == NULL)\n               continue;\n\n          /* Replace '@' with '\\0' to separate event type and event content. */\n          *pos = '\\0';\n\n          event_content = pos + 1;\n\n          pos = strstr( event_content, \"/event\" );\n          if (pos == NULL)\n               continue;\n\n          /* Get input device number. */\n          device_num = atoi( pos + 6 );\n\n          /* Attempt to lock the driver suspended mutex. */\n          pthread_mutex_lock( &driver_suspended_lock );\n          if (driver_suspended) {\n               /* Release the lock and stop udev event handling. */\n               D_DEBUG_AT( Linux_Input, \"Driver is suspended, no udev processing\\n\" );\n               pthread_mutex_unlock( &driver_suspended_lock );\n               continue;\n          }\n\n          /* Handle udev event since the driver is not suspended. */\n          if (!strcmp( udev_event, \"add\" )) {\n               D_DEBUG_AT( Linux_Input, \"Device node /dev/input/event%d is created by udev\\n\", device_num );\n\n               ret = register_device_node( device_num, &index );\n               if (ret == DFB_OK) {\n                    /* Handle the input device node creation. */\n                    ret = dfb_input_create_device( index, data->core, data->driver );\n                    if (ret != DFB_OK) {\n                         D_DEBUG_AT( Linux_Input, \"Failed to create the device for /dev/input/event%d\\n\", device_num );\n                    }\n               }\n          }\n          else if (!strcmp( udev_event, \"remove\" )) {\n               D_DEBUG_AT( Linux_Input, \"Device node /dev/input/event%d is removed by udev\\n\", device_num );\n\n               ret = unregister_device_node( device_num, &index );\n               if (ret == DFB_OK) {\n                    /* Handle the input device node removal. */\n                    ret = dfb_input_remove_device( index, data->driver );\n                    if (ret != DFB_OK) {\n                         D_DEBUG_AT( Linux_Input, \"Failed to remove the device for /dev/input/event%d\\n\", device_num );\n                    }\n               }\n          }\n\n          /* udev event handling is complete so release the lock. */\n          pthread_mutex_unlock( &driver_suspended_lock );\n     }\n\n     D_FREE( data );\n\n     D_DEBUG_AT( Linux_Input, \"DevInput Hotplug thread terminated\\n\" );\n\n     return NULL;\n\nerror:\n     D_DEBUG_AT( Linux_Input, \"Failed to open/bind udev socket\\n\" );\n\n     if (socket_fd > 0) {\n          close( socket_fd );\n          socket_fd = 0;\n     }\n\n     return NULL;\n}\n\nstatic DFBResult\ndriver_suspend()\n{\n     D_DEBUG_AT( Linux_Input, \"%s()\\n\", __FUNCTION__ );\n\n     if (pthread_mutex_lock( &driver_suspended_lock ))\n          return DFB_FAILURE;\n\n     /* Enter the suspended state by setting the driver_suspended flag to prevent handling of hot-plug events. */\n     driver_suspended = true;\n\n     pthread_mutex_unlock( &driver_suspended_lock );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndriver_resume()\n{\n     D_DEBUG_AT( Linux_Input, \"%s()\\n\", __FUNCTION__ );\n\n     if (pthread_mutex_lock( &driver_suspended_lock) )\n          return DFB_FAILURE;\n\n     /* Leave the suspended state by clearing the driver_suspended flag which will allow hot-plug events to be handled\n        again. */\n     driver_suspended = false;\n\n     pthread_mutex_unlock( &driver_suspended_lock );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nis_created( int   index,\n            void *driver_data )\n{\n     LinuxInputData *data = driver_data;\n\n     D_DEBUG_AT( Linux_Input, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( data != NULL );\n\n     if (index < 0 || index >= MAX_LINUX_INPUT_DEVICES) {\n          return DFB_UNSUPPORTED;\n     }\n\n     /* Check if the index is associated with an entry in the device_nums and device_names arrays. */\n     if (index != data->index) {\n          return DFB_UNSUPPORTED;\n     }\n\n     return DFB_OK;\n}\n\nstatic InputDriverCapability\nget_capability()\n{\n     InputDriverCapability capabilities = IDC_NONE;\n\n     D_DEBUG_AT( Linux_Input, \"%s()\\n\", __FUNCTION__ );\n     D_DEBUG_AT( Linux_Input, \"  -> returning HOTPLUG\\n\" );\n\n     capabilities |= IDC_HOTPLUG;\n\n     return capabilities;\n}\n\nstatic DFBResult\nlaunch_hotplug( CoreDFB *core,\n                void    *input_driver )\n{\n     DFBResult          ret;\n     HotplugThreadData *data;\n     int                err;\n\n     D_DEBUG_AT( Linux_Input, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( core != NULL );\n     D_ASSERT( input_driver != NULL );\n     D_ASSERT( hotplug_thread == NULL );\n\n     data = D_CALLOC( 1, sizeof(HotplugThreadData) );\n     if (!data) {\n          ret = D_OOM();\n          goto error;\n     }\n\n     data->core   = core;\n     data->driver = input_driver;\n\n     /* Open a pipe to awake the devinput hot-plug thread when we want to quit. */\n     err = pipe( hotplug_quitpipe );\n     if (err < 0) {\n          D_PERROR( \"Input/Linux: Could not open quit pipe for hot-plug!\" );\n          D_FREE( data );\n          ret = DFB_INIT;\n          goto error;\n     }\n\n     /* Initialize a mutex used to communicate with the devinput hot-plug thread when the driver is suspended. */\n     pthread_mutex_init( &driver_suspended_lock, NULL );\n\n     /* Start devinput hot-plug thread. */\n     hotplug_thread = direct_thread_create( DTT_INPUT, devinput_hotplug_thread, data, \"DevInput Hotplug\" );\n     if (!hotplug_thread) {\n          pthread_mutex_destroy( &driver_suspended_lock );\n          D_FREE( data );\n          ret = DFB_UNSUPPORTED;\n          goto error;\n     }\n\n     D_DEBUG_AT( Linux_Input, \"  -> hot-plug detection enabled\\n\" );\n\n     return DFB_OK;\n\nerror:\n     D_DEBUG_AT( Linux_Input, \"  -> failed to enable hot-plug detection\\n\" );\n\n     return ret;\n}\n\nstatic DFBResult\nstop_hotplug()\n{\n     int     err;\n     ssize_t res;\n\n     D_UNUSED_P( res );\n\n     D_ASSERT( hotplug_thread != NULL );\n\n     D_DEBUG_AT( Linux_Input, \"%s()\\n\", __FUNCTION__ );\n\n     /* The devinput hot-plug thread is not created. */\n     if (!hotplug_thread)\n          return DFB_OK;\n\n     /* Write to the hot-plug quit pipe to terminate the devinput hot-plug thread. */\n     res = write( hotplug_quitpipe[1], \" \", 1 );\n\n     direct_thread_join( hotplug_thread );\n     direct_thread_destroy( hotplug_thread );\n\n     close( hotplug_quitpipe[0] );\n     close( hotplug_quitpipe[1] );\n\n     hotplug_thread = NULL;\n\n     /* Destroy the suspended mutex. */\n     pthread_mutex_destroy( &driver_suspended_lock );\n\n     /* Shutdown the connection of the socket. */\n     if (socket_fd > 0) {\n          err = shutdown( socket_fd, SHUT_RDWR );\n          if (err < 0) {\n               D_PERROR( \"Input/Linux: Failed to shutdown socket!\\n\" );\n               return DFB_FAILURE;\n          }\n\n          close( socket_fd );\n          socket_fd = 0;\n     }\n\n     return DFB_OK;\n}\n\n#endif /* DIRECT_BUILD_NETWORK */\n\n/**********************************************************************************************************************\n ********************************* Axis info function *****************************************************************\n **********************************************************************************************************************/\n\nstatic DFBResult\ndriver_get_axis_info( CoreInputDevice              *device,\n                      void                         *driver_data,\n                      DFBInputDeviceAxisIdentifier  axis,\n                      InputDeviceAxisInfo          *ret_info )\n{\n     LinuxInputData *data = driver_data;\n\n     D_DEBUG_AT( Linux_Input, \"%s()\\n\", __FUNCTION__ );\n\n     if (data->touchpad && !data->touch_abs)\n          return DFB_OK;\n\n     if (axis <= ABS_PRESSURE && axis < DIAI_LAST) {\n          unsigned long absbit[NBITS(ABS_CNT)];\n\n          /* Check if we have an absolute axis. */\n          ioctl( data->fd, EVIOCGBIT( EV_ABS, sizeof(absbit) ), absbit );\n\n          if (test_bit( axis, absbit )) {\n               struct input_absinfo absinfo;\n\n               if (ioctl( data->fd, EVIOCGABS( axis ), &absinfo ) == 0 && (absinfo.minimum || absinfo.maximum)) {\n                    ret_info->flags   = IDAIF_ABS_MIN | IDAIF_ABS_MAX;\n                    ret_info->abs_min = absinfo.minimum;\n                    ret_info->abs_max = absinfo.maximum;\n               }\n          }\n     }\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************\n ********************************* Set configuration function *********************************************************\n **********************************************************************************************************************/\n\nstatic DFBResult\ndriver_set_configuration( CoreInputDevice            *device,\n                          void                       *driver_data,\n                          const DFBInputDeviceConfig *config )\n{\n     LinuxInputData *data = driver_data;\n\n     D_DEBUG_AT( Linux_Input, \"%s()\\n\", __FUNCTION__ );\n\n     if (config->flags & DIDCONF_SENSITIVITY)\n          data->sensitivity = config->sensitivity;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "inputdrivers/linux_input/meson.build",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\nif not cc.has_header('linux/input.h')\n  warning('Building without Linux Input support.')\n  subdir_done()\nendif\n\nlibrary('directfb_linux_input',\n        'linux_input.c',\n        build_rpath: get_option('prefix') / get_option('libdir'),\n        dependencies: directfb_dep,\n        install: true,\n        install_dir: moduledir / 'inputdrivers',\n        install_rpath: get_option('prefix') / get_option('libdir'))\n\nif get_option('default_library') == 'static'\n  pkgconfig.generate(filebase: 'directfb-inputdriver-linux_input',\n                     variables: 'moduledir=' + moduledir,\n                     name: 'DirectFB-inputdriver-linux_input',\n                     description: 'Linux input driver',\n                     libraries_private: ['-L${moduledir}/inputdrivers',\n                                         '-Wl,--whole-archive -ldirectfb_linux_input -Wl,--no-whole-archive'])\nendif\n"
  },
  {
    "path": "inputdrivers/nuttx_input/nuttx_input.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/input_driver.h>\n#include <direct/thread.h>\n#include <nuttx/input/buttons.h>\n#include <nuttx/input/keyboard.h>\n#include <nuttx/input/touchscreen.h>\n\nD_DEBUG_DOMAIN( NuttX_Input, \"Input/NuttX\", \"NuttX Input Driver\" );\n\nDFB_INPUT_DRIVER( nuttx_input )\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     CoreInputDevice *device;\n\n     int              fd;\n\n     unsigned int     id;\n\n     int16_t          last_x;\n     int16_t          last_y;\n\n     DirectThread    *thread;\n} NuttXData;\n\n#define MAX_NUTTX_INPUT_DEVICES 3\n\n/* Input devices are stored in the device_names array. */\nstatic char *device_names[MAX_NUTTX_INPUT_DEVICES];\n\n/* Number of entries in the device_names array. */\nstatic int   num_devices = 0;\n\n/**********************************************************************************************************************/\n\nstatic void *\ndevinput_event_thread( DirectThread *thread,\n                       void         *arg )\n{\n     NuttXData *data    = arg;\n     int        offsetx = 0;\n     int        offsety = 0;\n     int        threshx = 1;\n     int        threshy = 1;\n\n     D_DEBUG_AT( NuttX_Input, \"%s()\\n\", __FUNCTION__ );\n\n     /* Query the touchscreen X/Y offsets and thresholds. */\n     if (data->id == DIDID_MOUSE) {\n#if defined(TSIOC_GETOFFSETX) && defined(TSIOC_GETOFFSETY)\n          ioctl( data->fd, TSIOC_GETOFFSETX, &offsetx );\n          ioctl( data->fd, TSIOC_GETOFFSETY, &offsety );\n#endif\n#if defined(TSIOC_GETTHRESHX) && defined(TSIOC_GETTHRESHY)\n          ioctl( data->fd, TSIOC_GETTHRESHX, &threshx );\n          ioctl( data->fd, TSIOC_GETTHRESHY, &threshy );\n#endif\n     }\n\n     while (1) {\n          DFBInputEvent evt = { .type = DIET_UNKNOWN };\n          fd_set        set;\n          int           status;\n          ssize_t       len;\n\n          FD_ZERO( &set );\n          FD_SET( data->fd, &set );\n\n          status = select( data->fd + 1, &set, NULL, NULL, NULL );\n\n          if (status < 0 && errno != EINTR)\n               break;\n\n          if (status < 0)\n               continue;\n\n          if (data->id == DIDID_BUTTONS) {\n               btn_buttonset_t buttonset;\n\n               len = read( data->fd, &buttonset, sizeof(buttonset) );\n               if (len < 1)\n                    continue;\n\n               evt.type   = buttonset ? DIET_BUTTONRELEASE : DIET_BUTTONPRESS;\n               evt.flags  = DIEF_NONE;\n               evt.button = DIBI_FIRST;\n\n               dfb_input_dispatch( data->device, &evt );\n          }\n          else if (data->id == DIDID_KEYBOARD) {\n               struct keyboard_event_s keyboard_event;\n\n               len = read( data->fd, &keyboard_event, sizeof(keyboard_event) );\n               if (len < 1)\n                    continue;\n\n               evt.type       = keyboard_event.type ? DIET_KEYRELEASE : DIET_KEYPRESS;\n               evt.flags      = DIEF_KEYSYMBOL;\n               evt.key_symbol = keyboard_event.code;\n\n               dfb_input_dispatch( data->device, &evt );\n          }\n          else if (data->id == DIDID_MOUSE) {\n               struct touch_sample_s touch_sample;\n\n               len = read( data->fd, &touch_sample, sizeof(touch_sample) );\n               if (len < 1)\n                    continue;\n\n               if (touch_sample.point[0].flags & TOUCH_DOWN) {\n                    evt.type   = DIET_BUTTONPRESS;\n                    evt.flags  = DIEF_NONE;\n                    evt.button = DIBI_LEFT;\n\n                    dfb_input_dispatch( data->device, &evt );\n               }\n\n               if (touch_sample.point[0].flags & TOUCH_DOWN || touch_sample.point[0].flags & TOUCH_MOVE) {\n                    if (touch_sample.point[0].x != data->last_x) {\n                         evt.type    = DIET_AXISMOTION;\n                         evt.flags   = DIEF_AXISABS | DIEF_BUTTONS;\n                         evt.axis    = DIAI_X;\n                         evt.axisabs = (touch_sample.point[0].x - offsetx) / threshx;\n                         evt.buttons = DIBM_LEFT;\n\n                         dfb_input_dispatch( data->device, &evt );\n                    }\n\n                    if (touch_sample.point[0].y != data->last_y) {\n                         evt.type    = DIET_AXISMOTION;\n                         evt.flags   = DIEF_AXISABS | DIEF_BUTTONS;\n                         evt.axis    = DIAI_Y;\n                         evt.axisabs = touch_sample.point[0].y;\n                         evt.axisabs = (touch_sample.point[0].y - offsety) / threshy;\n                         evt.buttons = DIBM_LEFT;\n\n                         dfb_input_dispatch( data->device, &evt );\n                    }\n               }\n\n               if (touch_sample.point[0].flags & TOUCH_UP) {\n                    evt.type   = DIET_BUTTONRELEASE;\n                    evt.flags  = DIEF_NONE;\n                    evt.button = DIBI_LEFT;\n\n                    dfb_input_dispatch( data->device, &evt );\n               }\n\n               data->last_x = touch_sample.point[0].x;\n               data->last_y = touch_sample.point[0].y;\n          }\n     }\n\n     D_DEBUG_AT( NuttX_Input, \"DevInput Event thread terminated\\n\" );\n\n     return NULL;\n}\n\nstatic bool\ncheck_device( const char *device )\n{\n     int fd;\n\n     D_DEBUG_AT( NuttX_Input, \"%s( '%s' )\\n\", __FUNCTION__, device );\n\n     /* Check if we are able to open the device. */\n     fd = open( device, O_RDONLY );\n     if (fd < 0) {\n          D_DEBUG_AT( NuttX_Input, \"  -> open failed!\\n\" );\n          return false;\n     }\n\n     close( fd );\n\n     return true;\n}\n\n/**********************************************************************************************************************/\n\nstatic int\ndriver_get_available()\n{\n     char buf[32];\n     int  i;\n\n     if (num_devices) {\n          for (i = 0; i < num_devices; i++) {\n               D_FREE( device_names[i] );\n               device_names[i] = NULL;\n          }\n\n          num_devices = 0;\n\n          return 0;\n     }\n\n     /* Buttons device */\n     snprintf( buf, sizeof(buf), \"/dev/buttons\" );\n\n     if (check_device( buf )) {\n          D_ASSERT( device_names[num_devices] == NULL );\n          device_names[num_devices++] = D_STRDUP( buf );\n     }\n\n     /* Keyboard device */\n     snprintf( buf, sizeof(buf), \"/dev/kbd\" );\n\n     if (check_device( buf )) {\n          D_ASSERT( device_names[num_devices] == NULL );\n          device_names[num_devices++] = D_STRDUP( buf );\n     }\n\n     /* Touchscreen device */\n     snprintf( buf, sizeof(buf), \"/dev/input0\" );\n\n     if (check_device( buf )) {\n          D_ASSERT( device_names[num_devices] == NULL );\n          device_names[num_devices++] = D_STRDUP( buf );\n     }\n\n     return num_devices;\n}\n\nstatic void\ndriver_get_info( InputDriverInfo *driver_info )\n{\n     driver_info->version.major = 0;\n     driver_info->version.minor = 1;\n\n     snprintf( driver_info->name,   DFB_INPUT_DRIVER_INFO_NAME_LENGTH,   \"NuttX Input\" );\n     snprintf( driver_info->vendor, DFB_INPUT_DRIVER_INFO_VENDOR_LENGTH, \"DirectFB\" );\n}\n\nstatic DFBResult\ndriver_open_device( CoreInputDevice  *device,\n                    unsigned int      number,\n                    InputDeviceInfo  *device_info,\n                    void            **driver_data )\n{\n     NuttXData *data;\n     int        fd;\n\n     D_DEBUG_AT( NuttX_Input, \"%s()\\n\", __FUNCTION__ );\n\n     /* Open device. */\n     fd = open( device_names[number], O_RDONLY );\n     if (fd < 0) {\n          D_PERROR( \"Input/NuttX: Could not open device!\\n\" );\n          return DFB_INIT;\n     }\n\n     /* Fill device information. */\n     if (!strcmp( device_names[number], \"/dev/buttons\" )) {\n          device_info->prefered_id = DIDID_BUTTONS;\n          device_info->desc.type   = DIDTF_BUTTONS;\n          device_info->desc.caps   = DICAPS_BUTTONS;\n          snprintf( device_info->desc.name,   DFB_INPUT_DEVICE_DESC_NAME_LENGTH,   \"Buttons\" );\n          snprintf( device_info->desc.vendor, DFB_INPUT_DEVICE_DESC_VENDOR_LENGTH, \"NuttX\" );\n     }\n     else if (!strcmp( device_names[number], \"/dev/kbd\" )) {\n          device_info->prefered_id = DIDID_KEYBOARD;\n          device_info->desc.type   = DIDTF_KEYBOARD;\n          device_info->desc.caps   = DICAPS_KEYS;\n          snprintf( device_info->desc.name,   DFB_INPUT_DEVICE_DESC_NAME_LENGTH,   \"Keyboard\" );\n          snprintf( device_info->desc.vendor, DFB_INPUT_DEVICE_DESC_VENDOR_LENGTH, \"NuttX\" );\n     }\n     else if (!strcmp( device_names[number], \"/dev/input0\" )) {\n          device_info->prefered_id     = DIDID_MOUSE;\n          device_info->desc.type       = DIDTF_MOUSE;\n          device_info->desc.caps       = DICAPS_AXES | DICAPS_BUTTONS;\n          device_info->desc.max_axis   = DIAI_Y;\n          device_info->desc.max_button = DIBI_LEFT;\n          snprintf( device_info->desc.name,   DFB_INPUT_DEVICE_DESC_NAME_LENGTH,   \"Touchscreen\" );\n          snprintf( device_info->desc.vendor, DFB_INPUT_DEVICE_DESC_VENDOR_LENGTH, \"NuttX\" );\n     }\n\n     /* Allocate and fill private data. */\n     data = D_CALLOC( 1, sizeof(NuttXData) );\n     if (!data) {\n          close( fd );\n          return D_OOM();\n     }\n\n     data->device = device;\n     data->fd     = fd;\n     data->id     = device_info->prefered_id;\n\n     /* Start devinput event thread. */\n     data->thread = direct_thread_create( DTT_INPUT, devinput_event_thread, data, \"DevInput Event\" );\n\n     *driver_data = data;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndriver_get_keymap_entry( CoreInputDevice           *device,\n                         void                      *driver_data,\n                         DFBInputDeviceKeymapEntry *entry )\n{\n     return DFB_UNSUPPORTED;\n}\n\nstatic void\ndriver_close_device( void *driver_data )\n{\n     NuttXData *data = driver_data;\n\n     D_DEBUG_AT( NuttX_Input, \"%s()\\n\", __FUNCTION__ );\n\n     /* Terminate the devinput event thread. */\n     direct_thread_cancel( data->thread );\n\n     direct_thread_join( data->thread );\n     direct_thread_destroy( data->thread );\n\n     close( data->fd );\n\n     D_FREE( data );\n}\n"
  },
  {
    "path": "interfaces/ICoreResourceManager/icoreresourcemanager_default.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core.h>\n#include <core/surface.h>\n#include <directfb_util.h>\n\nD_DEBUG_DOMAIN( ICoreResourceManager_default, \"ICoreResourceManager/default\", \"Default Resource Manager\" );\nD_DEBUG_DOMAIN( ICoreResourceClient_default,  \"ICoreResourceClient/default\",  \"Default Resource Client\" );\n\nstatic DirectResult Probe    ( void                 *ctx );\n\nstatic DirectResult Construct( ICoreResourceManager *thiz,\n                               CoreDFB              *core );\n\n#include <direct/interface_implementation.h>\n\nDIRECT_INTERFACE_IMPLEMENTATION( ICoreResourceManager, default )\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int          ref;         /* reference counter */\n\n     FusionID     identity;\n\n     unsigned int surface_mem;\n} ICoreResourceClient_data;\n\n/**********************************************************************************************************************/\n\nstatic void\nICoreResourceClient_Destruct( ICoreResourceClient *thiz )\n{\n     D_DEBUG_AT( ICoreResourceClient_default, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     DIRECT_DEALLOCATE_INTERFACE( thiz );\n}\n\nstatic DirectResult\nICoreResourceClient_AddRef( ICoreResourceClient *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( ICoreResourceClient )\n\n     D_DEBUG_AT( ICoreResourceClient_default, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref++;\n\n     return DFB_OK;\n}\n\nstatic DirectResult\nICoreResourceClient_Release( ICoreResourceClient *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( ICoreResourceClient )\n\n     D_DEBUG_LOG( ICoreResourceClient_default, 1, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->ref == 0) {\n          D_LOG( ICoreResourceClient_default, INFO, \"Removing ID %lu\\n\", data->identity );\n\n          ICoreResourceClient_Destruct( thiz );\n     }\n\n     return DFB_OK;\n}\n\nstatic __inline__ unsigned int\nsurface_mem( const CoreSurfaceConfig *config )\n{\n     unsigned int mem;\n\n     mem = DFB_PLANE_MULTIPLY( config->format, config->size.h ) * DFB_BYTES_PER_LINE( config->format, config->size.w );\n\n     if (config->caps & DSCAPS_TRIPLE)\n          mem *= 3;\n     else if (config->caps & DSCAPS_DOUBLE)\n          mem *= 2;\n\n     return mem;\n}\n\nstatic DFBResult\nICoreResourceClient_CheckSurface( ICoreResourceClient     *thiz,\n                                  const CoreSurfaceConfig *config,\n                                  u64                      resource_id )\n{\n     DIRECT_INTERFACE_GET_DATA( ICoreResourceClient )\n\n     D_DEBUG_AT( ICoreResourceClient_default, \"%s( %p [%lu] )\\n\", __FUNCTION__, thiz, data->identity );\n\n     D_DEBUG_AT( ICoreResourceClient_default, \"  -> %dx%d %s %uk at %uk, resource id %llu\\n\",\n                 config->size.w, config->size.h, dfb_pixelformat_name( config->format ),\n                 surface_mem( config ) / 1024, data->surface_mem / 1024, (unsigned long long) resource_id );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nICoreResourceClient_CheckSurfaceUpdate( ICoreResourceClient     *thiz,\n                                        CoreSurface             *surface,\n                                        const CoreSurfaceConfig *config )\n{\n     DIRECT_INTERFACE_GET_DATA( ICoreResourceClient )\n\n     D_DEBUG_AT( ICoreResourceClient_default, \"%s( %p [%lu] )\\n\", __FUNCTION__, thiz, data->identity );\n\n     D_DEBUG_AT( ICoreResourceClient_default, \"  -> %u bytes\\n\", surface_mem( &surface->config ) );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nICoreResourceClient_AddSurface( ICoreResourceClient *thiz,\n                                CoreSurface         *surface )\n{\n     unsigned int mem;\n\n     DIRECT_INTERFACE_GET_DATA( ICoreResourceClient )\n\n     D_DEBUG_AT( ICoreResourceClient_default, \"%s( %p [%lu] )\\n\", __FUNCTION__, thiz, data->identity );\n\n     mem = surface_mem( &surface->config );\n\n     D_DEBUG_AT( ICoreResourceClient_default, \"  -> %u bytes\\n\", mem );\n\n     data->surface_mem += mem;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nICoreResourceClient_RemoveSurface( ICoreResourceClient *thiz,\n                                   CoreSurface         *surface )\n{\n     unsigned int mem;\n\n     DIRECT_INTERFACE_GET_DATA( ICoreResourceClient )\n\n     D_DEBUG_AT( ICoreResourceClient_default, \"%s( %p [%lu] )\\n\", __FUNCTION__, thiz, data->identity );\n\n     mem = surface_mem( &surface->config );\n\n     D_DEBUG_AT( ICoreResourceClient_default, \"  -> %u bytes\\n\", mem );\n\n     data->surface_mem -= mem;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nICoreResourceClient_UpdateSurface( ICoreResourceClient     *thiz,\n                                   CoreSurface             *surface,\n                                   const CoreSurfaceConfig *config )\n{\n     DIRECT_INTERFACE_GET_DATA( ICoreResourceClient )\n\n     D_DEBUG_AT( ICoreResourceClient_default, \"%s( %p [%lu] )\\n\", __FUNCTION__, thiz, data->identity );\n\n     data->surface_mem -= surface_mem( &surface->config );\n     data->surface_mem += surface_mem( config );\n\n     return DFB_OK;\n}\n\nDirectResult\nICoreResourceClient_Construct( ICoreResourceClient *thiz,\n                               CoreDFB             *core,\n                               FusionID             identity )\n{\n     char   buf[512];\n     size_t len;\n\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, ICoreResourceClient )\n\n     D_DEBUG_LOG( ICoreResourceClient_default, 1, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     fusion_get_fusionee_path( core->world, identity, buf, sizeof(buf), &len );\n\n     D_LOG( ICoreResourceClient_default, INFO, \"Adding ID %lu - '%s'\\n\", identity, buf );\n\n     data->ref      = 1;\n     data->identity = identity;\n\n     thiz->AddRef             = ICoreResourceClient_AddRef;\n     thiz->Release            = ICoreResourceClient_Release;\n     thiz->CheckSurface       = ICoreResourceClient_CheckSurface;\n     thiz->CheckSurfaceUpdate = ICoreResourceClient_CheckSurfaceUpdate;\n     thiz->AddSurface         = ICoreResourceClient_AddSurface;\n     thiz->RemoveSurface      = ICoreResourceClient_RemoveSurface;\n     thiz->UpdateSurface      = ICoreResourceClient_UpdateSurface;\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int ref;       /* reference counter */\n\n     CoreDFB *core;\n} ICoreResourceManager_data;\n\n/**********************************************************************************************************************/\n\nstatic void\nICoreResourceManager_Destruct( ICoreResourceManager *thiz )\n{\n     D_DEBUG_AT( ICoreResourceManager_default, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     DIRECT_DEALLOCATE_INTERFACE( thiz );\n}\n\nstatic DirectResult\nICoreResourceManager_AddRef( ICoreResourceManager *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( ICoreResourceManager )\n\n     D_DEBUG_AT( ICoreResourceManager_default, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref++;\n\n     return DFB_OK;\n}\n\nstatic DirectResult\nICoreResourceManager_Release( ICoreResourceManager *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( ICoreResourceManager )\n\n     D_DEBUG_AT( ICoreResourceManager_default, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->ref == 0)\n          ICoreResourceManager_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nICoreResourceManager_CreateClient( ICoreResourceManager  *thiz,\n                                   FusionID               identity,\n                                   ICoreResourceClient  **ret_interface )\n{\n     DIRECT_INTERFACE_GET_DATA( ICoreResourceManager )\n\n     D_DEBUG_LOG( ICoreResourceManager_default, 1, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     DIRECT_ALLOCATE_INTERFACE( *ret_interface, ICoreResourceClient );\n\n     return ICoreResourceClient_Construct( *ret_interface, data->core, identity );\n}\n\n/**********************************************************************************************************************/\n\nstatic DirectResult\nProbe( void *ctx )\n{\n     return DFB_OK;\n}\n\nstatic DirectResult\nConstruct( ICoreResourceManager *thiz,\n           CoreDFB              *core )\n{\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, ICoreResourceManager )\n\n     D_DEBUG_AT( ICoreResourceManager_default, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     D_LOG( ICoreResourceManager_default, NOTICE, \"Initializing resource manager 'default'\\n\" );\n\n     data->ref  = 1;\n     data->core = core;\n\n     thiz->AddRef       = ICoreResourceManager_AddRef;\n     thiz->Release      = ICoreResourceManager_Release;\n     thiz->CreateClient = ICoreResourceManager_CreateClient;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "interfaces/ICoreResourceManager/meson.build",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\nlibrary('icoreresourcemanager_default',\n        'icoreresourcemanager_default.c',\n        build_rpath: get_option('prefix') / get_option('libdir'),\n        dependencies: directfb_dep,\n        install: true,\n        install_dir: moduledir / 'interfaces/ICoreResourceManager',\n        install_rpath: get_option('prefix') / get_option('libdir'))\n\nif get_option('default_library') == 'static'\n  pkgconfig.generate(filebase: 'directfb-interface-resourcemanager_default',\n                     variables: 'moduledir=' + moduledir,\n                     name: 'DirectFB-interface-resourcemanager_default',\n                     description: 'Default resource manager',\n                     libraries_private: ['-L${moduledir}/interfaces/ICoreResourceManager',\n                                         '-Wl,--whole-archive -licoreresourcemanager_default -Wl,--no-whole-archive'])\nendif\n"
  },
  {
    "path": "interfaces/IDirectFBFont/idirectfbfont_dgiff.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/fonts.h>\n#include <core/surface.h>\n#include <dgiff.h>\n#include <direct/hash.h>\n#include <directfb_util.h>\n#include <media/idirectfbfont.h>\n\nD_DEBUG_DOMAIN( Font_DGIFF, \"Font/DGIFF\", \"DGIFF Font Provider\" );\n\nstatic DFBResult Probe    ( IDirectFBFont_ProbeContext *ctx );\n\nstatic DFBResult Construct( IDirectFBFont              *thiz,\n                            CoreDFB                    *core,\n                            IDirectFBFont_ProbeContext *ctx,\n                            DFBFontDescription         *desc );\n\n#include <direct/interface_implementation.h>\n\nDIRECT_INTERFACE_IMPLEMENTATION( IDirectFBFont, DGIFF )\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     CoreSurface **rows;     /* bitmaps of loaded glyphs */\n     int           num_rows;\n} DGIFFImplData;\n\n/**********************************************************************************************************************/\n\nstatic void\nIDirectFBFont_DGIFF_Destruct( IDirectFBFont *thiz )\n{\n     DGIFFImplData *data = ((IDirectFBFont_data*) thiz->priv)->font->impl_data;\n\n     D_DEBUG_AT( Font_DGIFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->rows) {\n          int i;\n\n          for (i = 0; i < data->num_rows; i++) {\n               if (data->rows[i])\n                    dfb_surface_unref( data->rows[i] );\n          }\n\n          D_FREE( data->rows );\n     }\n\n     D_FREE( data );\n\n     IDirectFBFont_Destruct( thiz );\n}\n\nstatic DirectResult\nIDirectFBFont_DGIFF_Release( IDirectFBFont *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     D_DEBUG_AT( Font_DGIFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->ref == 0)\n          IDirectFBFont_DGIFF_Destruct( thiz );\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic DFBResult\nProbe( IDirectFBFont_ProbeContext *ctx )\n{\n     /* Check the magic. */\n     if (!strncmp( (const char*) ctx->content, \"DGIFF\", 5 ))\n          return DFB_OK;\n\n     return DFB_UNSUPPORTED;\n}\n\nstatic DFBResult\nConstruct( IDirectFBFont              *thiz,\n           CoreDFB                    *core,\n           IDirectFBFont_ProbeContext *ctx,\n           DFBFontDescription         *desc )\n{\n     DFBResult              ret;\n     int                    i;\n     const DGIFFHeader     *header;\n     const DGIFFFaceHeader *faceheader;\n     DGIFFGlyphInfo        *glyphs;\n     DGIFFGlyphRow         *row;\n     CoreFont              *font = NULL;\n     DGIFFImplData         *data = NULL;\n\n     D_DEBUG_AT( Font_DGIFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     /* Check for valid description. */\n     if (!(desc->flags & DFDESC_HEIGHT))\n          return DFB_INVARG;\n\n     if (desc->flags & DFDESC_ROTATION)\n          return DFB_UNSUPPORTED;\n\n     D_DEBUG_AT( Font_DGIFF, \"  -> font at pixel height %d\\n\", desc->height );\n\n     header     = (void*) ctx->content;\n     faceheader = (void*) ctx->content + sizeof(DGIFFHeader);\n\n     /* Lookup requested face. */\n     for (i = 0; i < header->num_faces; i++) {\n          if (faceheader->size == desc->height)\n               break;\n\n          faceheader = (void*) faceheader + faceheader->next_face;\n     }\n\n     if (i == header->num_faces) {\n          D_ERROR( \"Font/DGIFF: Requested size %d not found!\\n\", desc->height );\n          ret = DFB_UNSUPPORTED;\n          goto error;\n     }\n\n     glyphs = (void*) (faceheader + 1);\n     row    = (void*) (glyphs + faceheader->num_glyphs);\n\n     /* Create the font object. */\n     ret = dfb_font_create( core, desc, &font );\n     if (ret)\n          goto error;\n\n     /* Fill font information. */\n     if (faceheader->blittingflags)\n          font->blittingflags = faceheader->blittingflags;\n\n     font->pixel_format = faceheader->pixelformat;\n     font->surface_caps = DSCAPS_NONE;\n     font->ascender     = faceheader->ascender;\n     font->descender    = faceheader->descender;\n     font->height       = faceheader->height;\n     font->maxadvance   = faceheader->max_advance;\n     font->up_unit_x    =  0.0;\n     font->up_unit_y    = -1.0;\n     font->flags        = CFF_SUBPIXEL_ADVANCE;\n\n     CORE_FONT_DEBUG_AT( Font_DGIFF, font );\n\n     /* Allocate implementation data. */\n     data = D_CALLOC( 1, sizeof(DGIFFImplData) );\n     if (!data) {\n          ret = D_OOM();\n          goto error;\n     }\n\n     data->num_rows = faceheader->num_rows;\n\n     /* Allocate array for glyph cache rows. */\n     data->rows = D_CALLOC( data->num_rows, sizeof(void*) );\n     if (!data->rows) {\n          ret = D_OOM();\n          goto error;\n     }\n\n     /* Build glyph cache rows. */\n     for (i = 0; i < data->num_rows; i++) {\n          ret = dfb_surface_create_simple( core, row->width, row->height, faceheader->pixelformat,\n                                           DFB_COLORSPACE_DEFAULT( faceheader->pixelformat ), DSCAPS_NONE, CSTF_NONE, 0,\n                                           NULL, &data->rows[i] );\n          if (ret) {\n               D_DERROR( ret, \"DGIFF/Font: Could not create %s %dx%d glyph row surface!\\n\",\n                         dfb_pixelformat_name( faceheader->pixelformat ), row->width, row->height );\n               goto error;\n          }\n\n          dfb_surface_write_buffer( data->rows[i], DSBR_BACK, row + 1, row->pitch, NULL );\n\n          /* Jump to next row. */\n          row = (void*) (row + 1) + row->pitch * row->height;\n     }\n\n     /* Build glyph info. */\n     for (i = 0; i < faceheader->num_glyphs; i++) {\n          CoreGlyphData  *glyph_data;\n          DGIFFGlyphInfo *glyph = &glyphs[i];\n\n          glyph_data = D_CALLOC( 1, sizeof(CoreGlyphData) );\n          if (!glyph_data) {\n               ret = D_OOM();\n               goto error;\n          }\n\n          glyph_data->surface  = data->rows[glyph->row];\n          glyph_data->start    = glyph->offset;\n          glyph_data->width    = glyph->width;\n          glyph_data->height   = glyph->height;\n          glyph_data->left     = glyph->left;\n          glyph_data->top      = glyph->top;\n          glyph_data->xadvance = glyph->advance << 8;\n          glyph_data->yadvance = 0;\n\n          D_MAGIC_SET( glyph_data, CoreGlyphData );\n\n          direct_hash_insert( font->layers[0].glyph_hash, glyph->unicode, glyph_data );\n\n          if (glyph->unicode < 128)\n               font->layers[0].glyph_data[glyph->unicode] = glyph_data;\n     }\n\n     font->impl_data = data;\n\n     IDirectFBFont_Construct( thiz, font );\n\n     thiz->Release = IDirectFBFont_DGIFF_Release;\n\n     return DFB_OK;\n\nerror:\n     if (font) {\n          if (data) {\n               if (data->rows) {\n                    for (i = 0; i < data->num_rows; i++) {\n                         if (data->rows[i])\n                              dfb_surface_unref( data->rows[i] );\n                    }\n\n                    D_FREE( data->rows );\n               }\n\n               D_FREE( data );\n          }\n\n          dfb_font_destroy( font );\n     }\n\n     return ret;\n}\n"
  },
  {
    "path": "interfaces/IDirectFBFont/meson.build",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\nlibrary('idirectfbfont_dgiff',\n        'idirectfbfont_dgiff.c',\n        build_rpath: get_option('prefix') / get_option('libdir'),\n        dependencies: directfb_dep,\n        install: true,\n        install_dir: moduledir / 'interfaces/IDirectFBFont',\n        install_rpath: get_option('prefix') / get_option('libdir'))\n\nif get_option('default_library') == 'static'\n  pkgconfig.generate(filebase: 'directfb-interface-font_dgiff',\n                     variables: 'moduledir=' + moduledir,\n                     name: 'DirectFB-interface-font_dgiff',\n                     description: 'DGIFF font provider',\n                     libraries_private: ['-L${moduledir}/interfaces/IDirectFBFont',\n                                         '-Wl,--whole-archive -lidirectfbfont_dgiff -Wl,--no-whole-archive'])\nendif\n"
  },
  {
    "path": "interfaces/IDirectFBImageProvider/idirectfbimageprovider_dfiff.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <dfiff.h>\n#include <direct/filesystem.h>\n#include <display/idirectfbsurface.h>\n#include <media/idirectfbdatabuffer.h>\n#include <media/idirectfbimageprovider.h>\n\nD_DEBUG_DOMAIN( ImageProvider_DFIFF, \"ImageProvider/DFIFF\", \"DFIFF Image Provider\" );\n\nstatic DFBResult Probe    ( IDirectFBImageProvider_ProbeContext *ctx );\n\nstatic DFBResult Construct( IDirectFBImageProvider              *thiz,\n                            IDirectFBDataBuffer                 *buffer,\n                            CoreDFB                             *core,\n                            IDirectFB                           *idirectfb );\n\n#include <direct/interface_implementation.h>\n\nDIRECT_INTERFACE_IMPLEMENTATION( IDirectFBImageProvider, DFIFF )\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int                    ref;                     /* reference counter */\n\n     IDirectFB             *idirectfb;\n\n     void                  *ptr;                     /* pointer to raw file data (mapped) */\n     int                    len;                     /* data length, i.e. file size */\n     int                    pitch;\n     bool                   premultiplied;\n\n     DFBSurfaceDescription  desc;\n\n     DIRenderCallback       render_callback;\n     void                  *render_callback_context;\n} IDirectFBImageProvider_DFIFF_data;\n\n#define DFIFF_FLAG_PREMULTIPLIED 0x02\n\n/**********************************************************************************************************************/\n\nstatic void\nIDirectFBImageProvider_DFIFF_Destruct( IDirectFBImageProvider *thiz )\n{\n     IDirectFBImageProvider_DFIFF_data *data = thiz->priv;\n\n     D_DEBUG_AT( ImageProvider_DFIFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->len)\n          D_FREE( data->ptr );\n     else if (data->len > 0)\n          direct_file_unmap( data->ptr, data->len );\n\n     DIRECT_DEALLOCATE_INTERFACE( thiz );\n}\n\nstatic DirectResult\nIDirectFBImageProvider_DFIFF_AddRef( IDirectFBImageProvider *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_DFIFF )\n\n     D_DEBUG_AT( ImageProvider_DFIFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref++;\n\n     return DFB_OK;\n}\n\nstatic DirectResult\nIDirectFBImageProvider_DFIFF_Release( IDirectFBImageProvider *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_DFIFF )\n\n     D_DEBUG_AT( ImageProvider_DFIFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->ref == 0)\n          IDirectFBImageProvider_DFIFF_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBImageProvider_DFIFF_GetSurfaceDescription( IDirectFBImageProvider *thiz,\n                                                    DFBSurfaceDescription  *ret_desc )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_DFIFF )\n\n     D_DEBUG_AT( ImageProvider_DFIFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_desc)\n          return DFB_INVARG;\n\n     *ret_desc = data->desc;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBImageProvider_DFIFF_GetImageDescription( IDirectFBImageProvider *thiz,\n                                                  DFBImageDescription    *ret_desc )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_DFIFF )\n\n     D_DEBUG_AT( ImageProvider_DFIFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_desc)\n          return DFB_INVARG;\n\n     ret_desc->caps = DFB_PIXELFORMAT_HAS_ALPHA( data->desc.pixelformat ) ? DICAPS_ALPHACHANNEL : DICAPS_NONE;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBImageProvider_DFIFF_RenderTo( IDirectFBImageProvider *thiz,\n                                       IDirectFBSurface       *destination,\n                                       const DFBRectangle     *dest_rect )\n{\n     DFBResult              ret;\n     IDirectFBSurface_data *dst_data;\n     DFBRectangle           rect;\n     DFBRectangle           clipped;\n     DFBSurfaceCapabilities caps;\n     DFBSurfacePixelFormat  pixelformat;\n     bool                   dest_premultiplied = false;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_DFIFF )\n\n     D_DEBUG_AT( ImageProvider_DFIFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!destination)\n          return DFB_INVARG;\n\n     dst_data = destination->priv;\n     if (!dst_data)\n          return DFB_DEAD;\n\n     if (dest_rect) {\n          if (dest_rect->w < 1 || dest_rect->h < 1)\n               return DFB_INVARG;\n\n          rect = *dest_rect;\n          rect.x += dst_data->area.wanted.x;\n          rect.y += dst_data->area.wanted.y;\n     }\n     else\n          rect = dst_data->area.wanted;\n\n     clipped = rect;\n\n     D_DEBUG_AT( ImageProvider_DFIFF, \"  -> clip    \"DFB_RECT_FORMAT\"\\n\", DFB_RECTANGLE_VALS( &dst_data->area.current ) );\n\n     if (!dfb_rectangle_intersect( &clipped, &dst_data->area.current ))\n          return DFB_INVAREA;\n\n     D_DEBUG_AT( ImageProvider_DFIFF, \"  -> clipped \"DFB_RECT_FORMAT\"\\n\", DFB_RECTANGLE_VALS( &clipped ) );\n\n     ret = destination->GetCapabilities( destination, &caps );\n     if (ret)\n          return ret;\n\n     if (caps & DSCAPS_PREMULTIPLIED)\n          dest_premultiplied = true;\n\n     ret = destination->GetPixelFormat( destination, &pixelformat );\n     if (ret)\n          return ret;\n\n     if (DFB_RECTANGLE_EQUAL( rect, clipped ) &&\n         rect.w == data->desc.width && rect.h == data->desc.height && pixelformat == data->desc.pixelformat &&\n         data->premultiplied == dest_premultiplied) {\n          ret = destination->Write( destination, &rect, data->ptr + sizeof(DFIFFHeader), data->pitch );\n          if (ret)\n               return ret;\n     }\n     else {\n          DFBRegion              clip = DFB_REGION_INIT_FROM_RECTANGLE( &clipped );\n          DFBRegion              old_clip;\n          DFBSurfaceDescription  desc;\n          IDirectFBSurface      *source;\n\n          desc = data->desc;\n\n          desc.flags                 |= DSDESC_PREALLOCATED;\n          desc.preallocated[0].data   = data->ptr + sizeof(DFIFFHeader);\n          desc.preallocated[0].pitch  = data->pitch;\n\n          ret = data->idirectfb->CreateSurface( data->idirectfb, &desc, &source );\n          if (ret)\n               return ret;\n\n          if (DFB_PIXELFORMAT_HAS_ALPHA( desc.pixelformat )) {\n               if (dest_premultiplied && !data->premultiplied)\n                    destination->SetBlittingFlags( destination, DSBLIT_SRC_PREMULTIPLY );\n               else if (!dest_premultiplied && data->premultiplied)\n                    destination->SetBlittingFlags( destination, DSBLIT_DEMULTIPLY );\n          }\n\n          destination->GetClip( destination, &old_clip );\n\n          destination->SetClip( destination, &clip );\n\n          destination->StretchBlit( destination, source, NULL, &rect );\n\n          destination->SetClip( destination, &old_clip );\n\n          destination->SetBlittingFlags( destination, DSBLIT_NOFX );\n\n          destination->ReleaseSource( destination );\n\n          source->Release( source );\n     }\n\n     if (data->render_callback) {\n          DFBRectangle r = { 0, 0, data->desc.width, data->desc.height };\n\n          data->render_callback( &r, data->render_callback_context );\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBImageProvider_DFIFF_SetRenderCallback( IDirectFBImageProvider *thiz,\n                                                DIRenderCallback        callback,\n                                                void                   *ctx )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_DFIFF )\n\n     D_DEBUG_AT( ImageProvider_DFIFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->render_callback         = callback;\n     data->render_callback_context = ctx;\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic DFBResult\nProbe( IDirectFBImageProvider_ProbeContext *ctx )\n{\n     /* Check the magic. */\n     if (!strncmp( (const char*) ctx->header, \"DFIFF\", 5 ))\n          return DFB_OK;\n\n     return DFB_UNSUPPORTED;\n}\n\nstatic DFBResult\nConstruct( IDirectFBImageProvider *thiz,\n           IDirectFBDataBuffer    *buffer,\n           CoreDFB                *core,\n           IDirectFB              *idirectfb )\n{\n     DFBResult                 ret;\n     DirectFile                fd;\n     int                       len;\n     const DFIFFHeader        *header;\n     void                     *ptr;\n     void                     *chunk       = NULL;\n     IDirectFBDataBuffer_data *buffer_data = buffer->priv;\n\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBImageProvider_DFIFF )\n\n     D_DEBUG_AT( ImageProvider_DFIFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref       = 1;\n     data->idirectfb = idirectfb;\n\n     if (buffer_data->buffer) {\n          len = -1;\n          ptr = buffer_data->buffer;\n     }\n     else if (buffer_data->filename) {\n          DirectFileInfo info;\n\n          /* Open the file. */\n          ret = direct_file_open( &fd, buffer_data->filename, O_RDONLY, 0 );\n          if (ret) {\n               D_DERROR( ret, \"ImageProvider/DFIFF: Failed to open file '%s'!\\n\", buffer_data->filename );\n               len = 0;\n               goto error;\n          }\n\n          /* Query file size. */\n          ret = direct_file_get_info( &fd, &info );\n          if (ret) {\n               D_DERROR( ret, \"ImageProvider/DFIFF: Failed during get_info() of '%s'!\\n\", buffer_data->filename );\n               len = -1;\n               goto error;\n          }\n          else\n               len = info.size;\n\n          /* Memory-mapped file. */\n          ret = direct_file_map( &fd, NULL, 0, len, DFP_READ, &ptr );\n          if (ret) {\n               D_DERROR( ret, \"ImageProvider/DFIFF: Failed during mmap() of '%s'!\\n\", buffer_data->filename );\n               goto error;\n          }\n\n          direct_file_close( &fd );\n     }\n     else {\n          unsigned int size = 0;\n\n          len = 0;\n\n          while (1) {\n               unsigned int bytes;\n\n               chunk = D_REALLOC( chunk, size + 4096 );\n               if (!chunk) {\n                    ret = D_OOM();\n                    goto error;\n               }\n\n               buffer->WaitForData( buffer, 4096 );\n               if (buffer->GetData( buffer, 4096, chunk + size, &bytes ))\n                    break;\n\n               size += bytes;\n          }\n\n          if (!size) {\n               ret = DFB_IO;\n               goto error;\n          }\n\n          ptr = chunk;\n     }\n\n     header = ptr;\n\n     data->ptr              = ptr;\n     data->len              = len;\n     data->pitch            = header->pitch;\n     data->premultiplied    = header->flags & DFIFF_FLAG_PREMULTIPLIED ? true : false;\n     data->desc.flags       = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT;\n     data->desc.width       = header->width;\n     data->desc.height      = header->height;\n     data->desc.pixelformat = header->format;\n\n     thiz->AddRef                = IDirectFBImageProvider_DFIFF_AddRef;\n     thiz->Release               = IDirectFBImageProvider_DFIFF_Release;\n     thiz->GetSurfaceDescription = IDirectFBImageProvider_DFIFF_GetSurfaceDescription;\n     thiz->GetImageDescription   = IDirectFBImageProvider_DFIFF_GetImageDescription;\n     thiz->RenderTo              = IDirectFBImageProvider_DFIFF_RenderTo;\n     thiz->SetRenderCallback     = IDirectFBImageProvider_DFIFF_SetRenderCallback;\n\n     return DFB_OK;\n\nerror:\n     if (len)\n          direct_file_close( &fd );\n\n     if (chunk)\n          D_FREE( chunk );\n\n     DIRECT_DEALLOCATE_INTERFACE( thiz );\n\n     return ret;\n}\n"
  },
  {
    "path": "interfaces/IDirectFBImageProvider/meson.build",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\nlibrary('idirectfbimageprovider_dfiff',\n        'idirectfbimageprovider_dfiff.c',\n        build_rpath: get_option('prefix') / get_option('libdir'),\n        dependencies: directfb_dep,\n        install: true,\n        install_dir: moduledir / 'interfaces/IDirectFBImageProvider',\n        install_rpath: get_option('prefix') / get_option('libdir'))\n\nif get_option('default_library') == 'static'\n  pkgconfig.generate(filebase: 'directfb-interface-imageprovider_dfiff',\n                     variables: 'moduledir=' + moduledir,\n                     name: 'DirectFB-interface-imageprovider_dfiff',\n                     description: 'DFIFF image provider',\n                     libraries_private: ['-L${moduledir}/interfaces/IDirectFBImageProvider',\n                                         '-Wl,--whole-archive -lidirectfbimageprovider_dfiff -Wl,--no-whole-archive'])\nendif\n"
  },
  {
    "path": "interfaces/IDirectFBVideoProvider/idirectfbvideoprovider_dfvff.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <dfvff.h>\n#include <direct/filesystem.h>\n#include <direct/list.h>\n#include <direct/memcpy.h>\n#include <direct/thread.h>\n#include <display/idirectfbsurface.h>\n#include <media/idirectfbdatabuffer.h>\n#include <media/idirectfbvideoprovider.h>\n\nD_DEBUG_DOMAIN( VideoProvider_DFVFF, \"VideoProvider/DFVFF\", \"DFVFF Video Provider\" );\n\nstatic DFBResult Probe    ( IDirectFBVideoProvider_ProbeContext *ctx );\n\nstatic DFBResult Construct( IDirectFBVideoProvider              *thiz,\n                            IDirectFBDataBuffer                 *buffer,\n                            CoreDFB                             *core,\n                            IDirectFB                           *idirectfb );\n\n\n#include <direct/interface_implementation.h>\n\nDIRECT_INTERFACE_IMPLEMENTATION( IDirectFBVideoProvider, DFVFF )\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     DirectLink            link;\n     IDirectFBEventBuffer *buffer;\n} EventLink;\n\ntypedef struct {\n     int                            ref;                    /* reference counter */\n\n     IDirectFB                     *idirectfb;\n\n     void                          *ptr;                    /* pointer to raw file data (mapped) */\n     int                            len;                    /* data length, i.e. file size */\n\n     DFBSurfaceDescription          desc;\n\n     double                         rate;\n     DFBVideoProviderStatus         status;\n     double                         speed;\n     DFBVideoProviderPlaybackFlags  flags;\n     int                            frame_size;\n     long                           nb_frames;\n     long                           frame;\n\n     DirectThread                  *thread;\n     DirectMutex                    lock;\n     DirectWaitQueue                cond;\n\n     bool                           seeked;\n\n     IDirectFBSurface              *dest;\n     DFBRectangle                   rect;\n\n     DVFrameCallback                frame_callback;\n     void                          *frame_callback_context;\n\n     DirectLink                    *events;\n     DFBVideoProviderEventType      events_mask;\n     DirectMutex                    events_lock;\n} IDirectFBVideoProvider_DFVFF_data;\n\n/**********************************************************************************************************************/\n\nstatic void\ndispatch_event( IDirectFBVideoProvider_DFVFF_data *data,\n                DFBVideoProviderEventType          type )\n{\n     EventLink             *link;\n     DFBVideoProviderEvent  event;\n\n     if (!data->events || !(data->events_mask & type))\n          return;\n\n     event.clazz = DFEC_VIDEOPROVIDER;\n     event.type  = type;\n\n     direct_mutex_lock( &data->events_lock );\n\n     direct_list_foreach (link, data->events) {\n          link->buffer->PostEvent( link->buffer, DFB_EVENT(&event) );\n     }\n\n     direct_mutex_unlock( &data->events_lock );\n}\n\nstatic void *\nDFVFFVideo( DirectThread *thread,\n            void         *arg )\n{\n     DFBResult                          ret;\n     int                                pitch;\n     void                              *ptr;\n     IDirectFBSurface                  *source;\n     void                              *frame_ptr;\n     int                                drop = 0;\n     IDirectFBVideoProvider_DFVFF_data *data = arg;\n\n     ret = data->idirectfb->CreateSurface( data->idirectfb, &data->desc, &source );\n     if (ret)\n          return NULL;\n\n     source->Lock( source, DSLF_WRITE, &ptr, &pitch );\n     source->Unlock( source );\n\n     frame_ptr = data->ptr + sizeof(DFVFFHeader);\n\n     dispatch_event( data, DVPET_STARTED );\n\n     while (data->status != DVSTATE_STOP) {\n          long long time;\n\n          time = direct_clock_get_abs_micros();\n\n          direct_mutex_lock( &data->lock );\n\n          if (drop) {\n               data->frame += drop;\n               data->frame  = MIN( data->frame, data->nb_frames - 1 );\n\n               drop = 0;\n\n               if (data->seeked) {\n                    direct_mutex_unlock( &data->lock );\n                    continue;\n               }\n          }\n          else {\n               if (data->seeked) {\n                    frame_ptr = data->ptr + sizeof(DFVFFHeader) + data->frame * data->frame_size;\n\n                    if (data->status == DVSTATE_FINISHED)\n                         data->status = DVSTATE_PLAY;\n\n                    data->seeked = false;\n               }\n\n               direct_memcpy( ptr, frame_ptr, data->frame_size );\n\n               data->dest->StretchBlit( data->dest, source, NULL, &data->rect );\n\n               if (data->frame_callback)\n                    data->frame_callback( data->frame_callback_context );\n          }\n\n          if (!data->speed) {\n               direct_waitqueue_wait( &data->cond, &data->lock );\n\n               if (data->seeked || data->status == DVSTATE_STOP) {\n                    direct_mutex_unlock( &data->lock );\n                    continue;\n               }\n          }\n          else {\n               long duration, delay;\n\n               duration = 1000000 / (data->rate * data->speed);\n\n               delay = direct_clock_get_abs_micros() - time;\n               if (delay > duration) {\n                    drop = delay / duration;\n                    direct_mutex_unlock( &data->lock );\n                    continue;\n               }\n\n               direct_waitqueue_wait_timeout( &data->cond, &data->lock, duration - delay );\n\n               if (data->seeked) {\n                    direct_mutex_unlock( &data->lock );\n                    continue;\n               }\n          }\n\n          data->frame++;\n\n          if (data->frame == data->nb_frames) {\n               if (data->flags & DVPLAY_LOOPING) {\n                    data->frame = 0;\n\n                    frame_ptr = data->ptr + sizeof(DFVFFHeader);\n               }\n               else {\n                    data->status = DVSTATE_FINISHED;\n                    dispatch_event( data, DVPET_FINISHED );\n                    direct_waitqueue_wait( &data->cond, &data->lock );\n               }\n          }\n          else\n               frame_ptr = data->ptr + sizeof(DFVFFHeader) + data->frame * data->frame_size;\n\n          direct_mutex_unlock( &data->lock );\n     }\n\n     source->Release( source );\n\n     return NULL;\n}\n\n/**********************************************************************************************************************/\n\nstatic void\nIDirectFBVideoProvider_DFVFF_Destruct( IDirectFBVideoProvider *thiz )\n{\n     EventLink                         *link, *tmp;\n     IDirectFBVideoProvider_DFVFF_data *data = thiz->priv;\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     thiz->Stop( thiz );\n\n     direct_waitqueue_deinit( &data->cond );\n     direct_mutex_deinit( &data->lock );\n\n     direct_list_foreach_safe (link, tmp, data->events) {\n          direct_list_remove( &data->events, &link->link );\n          link->buffer->Release( link->buffer );\n          D_FREE( link );\n     }\n\n     direct_mutex_deinit( &data->events_lock );\n\n     if (!data->len)\n          D_FREE( data->ptr );\n     else if (data->len > 0)\n          direct_file_unmap( data->ptr, data->len );\n\n     DIRECT_DEALLOCATE_INTERFACE( thiz );\n}\n\nstatic DirectResult\nIDirectFBVideoProvider_DFVFF_AddRef( IDirectFBVideoProvider *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref++;\n\n     return DFB_OK;\n}\n\nstatic DirectResult\nIDirectFBVideoProvider_DFVFF_Release( IDirectFBVideoProvider *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->ref == 0)\n          IDirectFBVideoProvider_DFVFF_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DFVFF_GetCapabilities( IDirectFBVideoProvider       *thiz,\n                                              DFBVideoProviderCapabilities *ret_caps )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_caps)\n          return DFB_INVARG;\n\n     *ret_caps = DVCAPS_BASIC | DVCAPS_SEEK | DVCAPS_SCALE | DVCAPS_SPEED;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DFVFF_GetSurfaceDescription( IDirectFBVideoProvider *thiz,\n                                                    DFBSurfaceDescription  *ret_desc )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_desc)\n          return DFB_INVARG;\n\n     *ret_desc = data->desc;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DFVFF_GetStreamDescription( IDirectFBVideoProvider *thiz,\n                                                   DFBStreamDescription   *ret_desc )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_desc)\n          return DFB_INVARG;\n\n     memset( ret_desc, 0, sizeof(DFBStreamDescription) );\n\n     ret_desc->caps = DVSCAPS_VIDEO;\n\n     snprintf( ret_desc->video.encoding, DFB_STREAM_DESC_ENCODING_LENGTH, \"rawvideo\" );\n\n     ret_desc->video.framerate = data->rate;\n     ret_desc->video.aspect    = (double) data->desc.width / data->desc.height;\n     ret_desc->video.bitrate   = data->rate * data->frame_size;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DFVFF_PlayTo( IDirectFBVideoProvider *thiz,\n                                     IDirectFBSurface       *destination,\n                                     const DFBRectangle     *dest_rect,\n                                     DVFrameCallback         callback,\n                                     void                   *ctx )\n{\n     IDirectFBSurface_data *dst_data;\n     DFBRectangle           rect;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!destination)\n          return DFB_INVARG;\n\n     dst_data = destination->priv;\n     if (!dst_data)\n          return DFB_DEAD;\n\n     if (dest_rect) {\n          if (dest_rect->w < 1 || dest_rect->h < 1)\n               return DFB_INVARG;\n\n          rect = *dest_rect;\n     }\n     else\n          rect = dst_data->area.wanted;\n\n     if (data->thread)\n          return DFB_OK;\n\n     direct_mutex_lock( &data->lock );\n\n     data->dest                   = destination;\n     data->rect                   = rect;\n     data->frame_callback         = callback;\n     data->frame_callback_context = ctx;\n\n     data->status = DVSTATE_PLAY;\n\n     data->thread = direct_thread_create( DTT_DEFAULT, DFVFFVideo, data, \"DFVFF Video\" );\n\n     direct_mutex_unlock( &data->lock );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DFVFF_Stop( IDirectFBVideoProvider *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->status == DVSTATE_STOP)\n          return DFB_OK;\n\n     data->status = DVSTATE_STOP;\n\n     if (data->thread) {\n          direct_waitqueue_signal( &data->cond );\n          direct_thread_join( data->thread );\n          direct_thread_destroy( data->thread );\n          data->thread = NULL;\n     }\n\n     data->frame = 0;\n\n     dispatch_event( data, DVPET_STOPPED );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DFVFF_GetStatus( IDirectFBVideoProvider *thiz,\n                                        DFBVideoProviderStatus *ret_status )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_status)\n          return DFB_INVARG;\n\n     *ret_status = data->status;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DFVFF_SeekTo( IDirectFBVideoProvider *thiz,\n                                     double                  seconds )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (seconds < 0.0)\n          return DFB_INVARG;\n\n     direct_mutex_lock( &data->lock );\n\n     data->frame = data->rate * seconds;\n     data->frame = MIN( data->frame, data->nb_frames - 1 );\n\n     data->seeked = true;\n\n     direct_waitqueue_signal( &data->cond );\n\n     direct_mutex_unlock( &data->lock );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DFVFF_GetPos( IDirectFBVideoProvider *thiz,\n                                     double                 *ret_seconds )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_seconds)\n          return DFB_INVARG;\n\n     direct_mutex_lock( &data->lock );\n\n     *ret_seconds = data->frame / data->rate;\n\n     direct_mutex_unlock( &data->lock );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DFVFF_GetLength( IDirectFBVideoProvider *thiz,\n                                        double                 *ret_seconds )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_seconds)\n          return DFB_INVARG;\n\n     *ret_seconds = data->nb_frames / data->rate;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DFVFF_SetPlaybackFlags( IDirectFBVideoProvider        *thiz,\n                                               DFBVideoProviderPlaybackFlags  flags )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (flags & ~DVPLAY_LOOPING)\n          return DFB_UNSUPPORTED;\n\n     data->flags = flags;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DFVFF_SetSpeed( IDirectFBVideoProvider *thiz,\n                                       double                  multiplier )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (multiplier < 0.0 || multiplier > 64.0)\n          return DFB_UNSUPPORTED;\n\n     if (multiplier == data->speed)\n          return DFB_OK;\n\n     direct_mutex_lock( &data->lock );\n\n     if (multiplier > data->speed && data->status != DVSTATE_FINISHED)\n          direct_waitqueue_signal( &data->cond );\n\n     data->speed = multiplier;\n\n     dispatch_event( data, DVPET_SPEEDCHANGE );\n\n     direct_mutex_unlock( &data->lock );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DFVFF_GetSpeed( IDirectFBVideoProvider *thiz,\n                                       double                 *ret_multiplier )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_multiplier)\n          return DFB_INVARG;\n\n     *ret_multiplier = data->speed;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DFVFF_CreateEventBuffer( IDirectFBVideoProvider  *thiz,\n                                                IDirectFBEventBuffer   **ret_interface )\n{\n     DFBResult             ret;\n     IDirectFBEventBuffer *buffer;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     ret = data->idirectfb->CreateEventBuffer( data->idirectfb, &buffer );\n     if (ret)\n          return ret;\n\n     ret = thiz->AttachEventBuffer( thiz, buffer );\n\n     buffer->Release( buffer );\n\n     *ret_interface = (ret == DFB_OK) ? buffer : NULL;\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DFVFF_AttachEventBuffer( IDirectFBVideoProvider *thiz,\n                                                IDirectFBEventBuffer   *buffer )\n{\n     DFBResult  ret;\n     EventLink *link;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!buffer)\n          return DFB_INVARG;\n\n     ret = buffer->AddRef( buffer );\n     if (ret)\n          return ret;\n\n     link = D_MALLOC( sizeof(EventLink) );\n     if (!link) {\n          buffer->Release( buffer );\n          return D_OOM();\n     }\n\n     link->buffer = buffer;\n\n     direct_mutex_lock( &data->events_lock );\n\n     direct_list_append( &data->events, &link->link );\n\n     direct_mutex_unlock( &data->events_lock );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DFVFF_EnableEvents( IDirectFBVideoProvider    *thiz,\n                                           DFBVideoProviderEventType  mask )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (mask & ~DVPET_ALL)\n          return DFB_INVARG;\n\n     data->events_mask |= mask;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DFVFF_DisableEvents( IDirectFBVideoProvider    *thiz,\n                                            DFBVideoProviderEventType  mask )\n{\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (mask & ~DVPET_ALL)\n          return DFB_INVARG;\n\n     data->events_mask &= ~mask;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DFVFF_DetachEventBuffer( IDirectFBVideoProvider *thiz,\n                                                IDirectFBEventBuffer   *buffer )\n{\n     DFBResult  ret = DFB_ITEMNOTFOUND;\n     EventLink *link;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!buffer)\n          return DFB_INVARG;\n\n     direct_mutex_lock( &data->events_lock );\n\n     direct_list_foreach (link, data->events) {\n          if (link->buffer == buffer) {\n               direct_list_remove( &data->events, &link->link );\n               link->buffer->Release( link->buffer );\n               D_FREE( link );\n               ret = DFB_OK;\n               break;\n          }\n     }\n\n     direct_mutex_unlock( &data->events_lock );\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DFVFF_SetDestination( IDirectFBVideoProvider *thiz,\n                                             IDirectFBSurface       *destination,\n                                             const DFBRectangle     *dest_rect )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p, %4d,%4d-%4dx%4d )\\n\", __FUNCTION__,\n                 thiz, dest_rect->x, dest_rect->y, dest_rect->w, dest_rect->h );\n\n     if (!dest_rect)\n          return DFB_INVARG;\n\n     if (dest_rect->w < 1 || dest_rect->h < 1)\n          return DFB_INVARG;\n\n     data->rect = *dest_rect;\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic DFBResult\nProbe( IDirectFBVideoProvider_ProbeContext *ctx )\n{\n     /* Check the magic. */\n     if (!strncmp( (const char*) ctx->header, \"DFVFF\", 5 ))\n          return DFB_OK;\n\n     return DFB_UNSUPPORTED;\n}\n\nstatic DFBResult\nConstruct( IDirectFBVideoProvider *thiz,\n           IDirectFBDataBuffer    *buffer,\n           CoreDFB                *core,\n           IDirectFB              *idirectfb )\n{\n     DFBResult                 ret;\n     DirectFile                fd;\n     int                       len;\n     const DFVFFHeader        *header;\n     void                     *ptr;\n     void                     *chunk       = NULL;\n     IDirectFBDataBuffer_data *buffer_data = buffer->priv;\n\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBVideoProvider_DFVFF )\n\n     D_DEBUG_AT( VideoProvider_DFVFF, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref       = 1;\n     data->idirectfb = idirectfb;\n\n     if (buffer_data->buffer) {\n          len = -1;\n          ptr = buffer_data->buffer;\n     }\n     else if (buffer_data->filename) {\n          DirectFileInfo info;\n\n          /* Open the file. */\n          ret = direct_file_open( &fd, buffer_data->filename, O_RDONLY, 0 );\n          if (ret) {\n               D_DERROR( ret, \"VideoProvider/DFVFF: Failed to open file '%s'!\\n\", buffer_data->filename );\n               len = 0;\n               goto error;\n          }\n\n          /* Query file size. */\n          ret = direct_file_get_info( &fd, &info );\n          if (ret) {\n               D_DERROR( ret, \"VideoProvider/DFVFF: Failed during get_info() of '%s'!\\n\", buffer_data->filename );\n               len = -1;\n               goto error;\n          }\n          else\n               len = info.size;\n\n          /* Memory-mapped file. */\n          ret = direct_file_map( &fd, NULL, 0, len, DFP_READ, &ptr );\n          if (ret) {\n               D_DERROR( ret, \"VideoProvider/DFVFF: Failed during mmap() of '%s'!\\n\", buffer_data->filename );\n               goto error;\n          }\n\n          direct_file_close( &fd );\n     }\n     else {\n          unsigned int size = 0;\n\n          len = 0;\n\n          while (1) {\n               unsigned int bytes;\n\n               chunk = D_REALLOC( chunk, size + 4096 );\n               if (!chunk) {\n                    ret = D_OOM();\n                    goto error;\n               }\n\n               buffer->WaitForData( buffer, 4096 );\n               if (buffer->GetData( buffer, 4096, chunk + size, &bytes ))\n                    break;\n\n               size += bytes;\n          }\n\n          if (!size) {\n               ret = DFB_IO;\n               goto error;\n          }\n\n          ptr = chunk;\n     }\n\n     header = ptr;\n\n     data->ptr              = ptr;\n     data->len              = len;\n     data->desc.flags       = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_COLORSPACE;\n     data->desc.width       = header->width;\n     data->desc.height      = header->height;\n     data->desc.pixelformat = header->format;\n     data->desc.colorspace  = header->colorspace;\n     data->rate             = (double) header->framerate_num / header->framerate_den;\n     data->status           = DVSTATE_STOP;\n     data->speed            = 1.0;\n     data->frame_size       = DFB_BYTES_PER_LINE( data->desc.pixelformat, data->desc.width ) *\n                              DFB_PLANE_MULTIPLY( data->desc.pixelformat, data->desc.height );\n     data->nb_frames        = (data->len - sizeof(DFVFFHeader)) / data->frame_size;\n     data->events_mask      = DVPET_ALL;\n\n     direct_mutex_init( &data->events_lock );\n\n     direct_mutex_init( &data->lock );\n     direct_waitqueue_init( &data->cond );\n\n     thiz->AddRef                = IDirectFBVideoProvider_DFVFF_AddRef;\n     thiz->Release               = IDirectFBVideoProvider_DFVFF_Release;\n     thiz->GetCapabilities       = IDirectFBVideoProvider_DFVFF_GetCapabilities;\n     thiz->GetSurfaceDescription = IDirectFBVideoProvider_DFVFF_GetSurfaceDescription;\n     thiz->GetStreamDescription  = IDirectFBVideoProvider_DFVFF_GetStreamDescription;\n     thiz->PlayTo                = IDirectFBVideoProvider_DFVFF_PlayTo;\n     thiz->Stop                  = IDirectFBVideoProvider_DFVFF_Stop;\n     thiz->GetStatus             = IDirectFBVideoProvider_DFVFF_GetStatus;\n     thiz->SeekTo                = IDirectFBVideoProvider_DFVFF_SeekTo;\n     thiz->GetPos                = IDirectFBVideoProvider_DFVFF_GetPos;\n     thiz->GetLength             = IDirectFBVideoProvider_DFVFF_GetLength;\n     thiz->SetPlaybackFlags      = IDirectFBVideoProvider_DFVFF_SetPlaybackFlags;\n     thiz->SetSpeed              = IDirectFBVideoProvider_DFVFF_SetSpeed;\n     thiz->GetSpeed              = IDirectFBVideoProvider_DFVFF_GetSpeed;\n     thiz->CreateEventBuffer     = IDirectFBVideoProvider_DFVFF_CreateEventBuffer;\n     thiz->AttachEventBuffer     = IDirectFBVideoProvider_DFVFF_AttachEventBuffer;\n     thiz->EnableEvents          = IDirectFBVideoProvider_DFVFF_EnableEvents;\n     thiz->DisableEvents         = IDirectFBVideoProvider_DFVFF_DisableEvents;\n     thiz->DetachEventBuffer     = IDirectFBVideoProvider_DFVFF_DetachEventBuffer;\n     thiz->SetDestination        = IDirectFBVideoProvider_DFVFF_SetDestination;\n\n     return DFB_OK;\n\nerror:\n     if (len)\n          direct_file_close( &fd );\n\n     if (chunk)\n          D_FREE( chunk );\n\n     DIRECT_DEALLOCATE_INTERFACE( thiz );\n\n     return ret;\n}\n"
  },
  {
    "path": "interfaces/IDirectFBVideoProvider/meson.build",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\nlibrary('idirectfbvideoprovider_dfvff',\n        'idirectfbvideoprovider_dfvff.c',\n        build_rpath: get_option('prefix') / get_option('libdir'),\n        dependencies: directfb_dep,\n        install: true,\n        install_dir: moduledir / 'interfaces/IDirectFBVideoProvider',\n        install_rpath: get_option('prefix') / get_option('libdir'))\n\nif get_option('default_library') == 'static'\n  pkgconfig.generate(filebase: 'directfb-interface-videoprovider_dfvff',\n                     variables: 'moduledir=' + moduledir,\n                     name: 'DirectFB-interface-videoprovider_dfvff',\n                     description: 'DFVFF video provider',\n                     libraries_private: ['-L${moduledir}/interfaces/IDirectFBVideoProvider',\n                                         '-Wl,--whole-archive -lidirectfbvideoprovider_dfvff -Wl,--no-whole-archive'])\nendif\n"
  },
  {
    "path": "interfaces/IDirectFBWindows/idirectfbwindows_default.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/wm.h>\n\nD_DEBUG_DOMAIN( IDirectFBWindows_default, \"IDirectFBWindows/Default\", \"Default Windows Watcher\" );\n\nstatic DirectResult Probe    ( void             *ctx );\n\nstatic DirectResult Construct( IDirectFBWindows *thiz,\n                               CoreDFB          *core );\n\n#include <direct/interface_implementation.h>\n\nDIRECT_INTERFACE_IMPLEMENTATION( IDirectFBWindows, default )\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     DirectLink         link;\n\n     DFBWindowsWatcher  watcher;\n     void              *context;\n\n     Reaction           reactions[CORE_WM_NUM_CHANNELS];\n} RegisteredWatcher;\n\ntypedef struct {\n     int         ref;      /* reference counter */\n\n     CoreDFB    *core;\n\n     DirectLink *watchers;\n} IDirectFBWindows_data;\n\n#define WM_ATTACH( Func, CHANNEL )                                                                                  \\\n     do {                                                                                                           \\\n          if (watcher->Func) {                                                                                      \\\n               ret = dfb_wm_attach( data->core, CORE_WM_##CHANNEL, IDirectFBWindows_WM_Reaction_##Func, registered, \\\n                                    &registered->reactions[CORE_WM_##CHANNEL] );                                    \\\n               if (ret) {                                                                                           \\\n                    D_DERROR( ret, \"IDirectFBWindows/Default: Failed to attach CORE_WM_\" #CHANNEL \"!\\n\" );          \\\n                    goto error;                                                                                     \\\n               }                                                                                                    \\\n          }                                                                                                         \\\n     } while (0)\n\n#define WM_DETACH()                                                                                                 \\\n     do {                                                                                                           \\\n          int i;                                                                                                    \\\n          for (i = CORE_WM_NUM_CHANNELS - 1; i >= 0 ; i--) {                                                       \\\n               if (registered->reactions[i].func)                                                                   \\\n                    dfb_wm_detach( data->core, &registered->reactions[i] );                                         \\\n          }                                                                                                         \\\n     } while (0)\n\n/**********************************************************************************************************************/\n\nstatic ReactionResult\nIDirectFBWindows_WM_Reaction_WindowAdd( const void *msg_data,\n                                        void       *ctx )\n{\n     const CoreWM_WindowAdd *add        = msg_data;\n     RegisteredWatcher      *registered = ctx;\n\n     D_DEBUG_AT( IDirectFBWindows_default, \"%s( %p, %p )\\n\", __FUNCTION__, add, registered );\n\n     D_ASSERT( registered->watcher.WindowAdd != NULL );\n\n     registered->watcher.WindowAdd( registered->context, &add->info );\n\n     return RS_OK;\n}\n\nstatic ReactionResult\nIDirectFBWindows_WM_Reaction_WindowRemove( const void *msg_data,\n                                           void       *ctx )\n{\n     const CoreWM_WindowRemove *remove     = msg_data;\n     RegisteredWatcher         *registered = ctx;\n\n     D_DEBUG_AT( IDirectFBWindows_default, \"%s( %p, %p )\\n\", __FUNCTION__, remove, registered );\n\n     D_ASSERT( registered->watcher.WindowRemove != NULL );\n\n     registered->watcher.WindowRemove( registered->context, remove->window_id );\n\n     return RS_OK;\n}\n\nstatic ReactionResult\nIDirectFBWindows_WM_Reaction_WindowConfig( const void *msg_data,\n                                           void       *ctx )\n{\n     const CoreWM_WindowConfig *config     = msg_data;\n     RegisteredWatcher         *registered = ctx;\n\n     D_DEBUG_AT( IDirectFBWindows_default, \"%s( %p, %p )\\n\", __FUNCTION__, config, registered );\n\n     D_ASSERT( registered->watcher.WindowConfig != NULL );\n\n     registered->watcher.WindowConfig( registered->context, config->window_id, &config->config, config->flags );\n\n     return RS_OK;\n}\n\nstatic ReactionResult\nIDirectFBWindows_WM_Reaction_WindowState( const void *msg_data,\n                                          void       *ctx )\n{\n     const CoreWM_WindowState *state      = msg_data;\n     RegisteredWatcher        *registered = ctx;\n\n     D_DEBUG_AT( IDirectFBWindows_default, \"%s( %p, %p )\\n\", __FUNCTION__, state, registered );\n\n     D_ASSERT( registered->watcher.WindowState != NULL );\n\n     registered->watcher.WindowState( registered->context, state->window_id, &state->state );\n\n     return RS_OK;\n}\n\nstatic ReactionResult\nIDirectFBWindows_WM_Reaction_WindowRestack( const void *msg_data,\n                                            void       *ctx )\n{\n     const CoreWM_WindowRestack *restack    = msg_data;\n     RegisteredWatcher          *registered = ctx;\n\n     D_DEBUG_AT( IDirectFBWindows_default, \"%s( %p, %p )\\n\", __FUNCTION__, restack, registered );\n\n     D_ASSERT( registered->watcher.WindowRestack != NULL );\n\n     registered->watcher.WindowRestack( registered->context, restack->window_id, restack->index );\n\n     return RS_OK;\n}\n\nstatic ReactionResult\nIDirectFBWindows_WM_Reaction_WindowFocus( const void *msg_data,\n                                          void       *ctx )\n{\n     const CoreWM_WindowFocus *focus      = msg_data;\n     RegisteredWatcher        *registered = ctx;\n\n     D_DEBUG_AT( IDirectFBWindows_default, \"%s( %p, %p )\\n\", __FUNCTION__, focus, registered );\n\n     D_ASSERT( registered->watcher.WindowFocus != NULL );\n\n     registered->watcher.WindowFocus( registered->context, focus->window_id );\n\n     return RS_OK;\n}\n\nstatic void\nIDirectFBWindows_Destruct( IDirectFBWindows *thiz )\n{\n     IDirectFBWindows_data *data = thiz->priv;\n     RegisteredWatcher     *registered, *next;\n\n     D_DEBUG_AT( IDirectFBWindows_default, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     direct_list_foreach_safe (registered, next, data->watchers) {\n          WM_DETACH();\n\n          D_FREE( registered );\n     }\n\n     DIRECT_DEALLOCATE_INTERFACE( thiz );\n}\n\nstatic DirectResult\nIDirectFBWindows_AddRef( IDirectFBWindows *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindows )\n\n     D_DEBUG_AT( IDirectFBWindows_default, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref++;\n\n     return DFB_OK;\n}\n\nstatic DirectResult\nIDirectFBWindows_Release( IDirectFBWindows *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindows )\n\n     D_DEBUG_AT( IDirectFBWindows_default, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->ref == 0)\n          IDirectFBWindows_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBWindows_RegisterWatcher( IDirectFBWindows        *thiz,\n                                  const DFBWindowsWatcher *watcher,\n                                  void                    *context )\n{\n     DFBResult          ret;\n     RegisteredWatcher *registered;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindows )\n\n     D_DEBUG_AT( IDirectFBWindows_default, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!watcher)\n          return DFB_INVARG;\n\n     if (!watcher->WindowAdd     &&\n         !watcher->WindowRemove  &&\n         !watcher->WindowConfig  &&\n         !watcher->WindowState   &&\n         !watcher->WindowRestack &&\n         !watcher->WindowFocus)\n          return DFB_INVARG;\n\n     registered = D_CALLOC( 1, sizeof(RegisteredWatcher) );\n     if (!registered)\n          return D_OOM();\n\n     registered->watcher = *watcher;\n     registered->context = context;\n\n     WM_ATTACH( WindowAdd,     WINDOW_ADD );\n     WM_ATTACH( WindowRemove,  WINDOW_REMOVE );\n     WM_ATTACH( WindowConfig,  WINDOW_CONFIG );\n     WM_ATTACH( WindowState,   WINDOW_STATE );\n     WM_ATTACH( WindowRestack, WINDOW_RESTACK );\n     WM_ATTACH( WindowFocus,   WINDOW_FOCUS );\n\n     direct_list_append( &data->watchers, &registered->link );\n\n     return DFB_OK;\n\n\nerror:\n     WM_DETACH();\n\n     D_FREE( registered );\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBWindows_UnregisterWatcher( IDirectFBWindows *thiz,\n                                    void             *context )\n{\n     RegisteredWatcher *registered;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindows )\n\n     D_DEBUG_AT( IDirectFBWindows_default, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     direct_list_foreach (registered, data->watchers) {\n          if (registered->context == context) {\n               WM_DETACH();\n\n               direct_list_remove( &data->watchers, &registered->link );\n\n               D_FREE( registered );\n\n               return DFB_OK;\n          }\n     }\n\n     return DFB_ITEMNOTFOUND;\n}\n\n/**********************************************************************************************************************/\n\nstatic DirectResult\nProbe( void *ctx )\n{\n     return DFB_OK;\n}\n\nstatic DirectResult\nConstruct( IDirectFBWindows *thiz,\n           CoreDFB          *core )\n{\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBWindows )\n\n     D_DEBUG_AT( IDirectFBWindows_default, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref  = 1;\n     data->core = core;\n\n     thiz->AddRef            = IDirectFBWindows_AddRef;\n     thiz->Release           = IDirectFBWindows_Release;\n     thiz->RegisterWatcher   = IDirectFBWindows_RegisterWatcher;\n     thiz->UnregisterWatcher = IDirectFBWindows_UnregisterWatcher;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "interfaces/IDirectFBWindows/meson.build",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\nlibrary('idirectfbwindows_default',\n        'idirectfbwindows_default.c',\n        build_rpath: get_option('prefix') / get_option('libdir'),\n        dependencies: directfb_dep,\n        install: true,\n        install_dir: moduledir / 'interfaces/IDirectFBWindows',\n        install_rpath: get_option('prefix') / get_option('libdir'))\n\nif get_option('default_library') == 'static'\n  pkgconfig.generate(filebase: 'directfb-interface-windows_default',\n                     variables: 'moduledir=' + moduledir,\n                     name: 'DirectFB-interface-windows_default',\n                     description: 'Default windows watcher',\n                     libraries_private: ['-L${moduledir}/interfaces/IDirectFBWindows',\n                                         '-Wl,--whole-archive -lidirectfbwindows_default -Wl,--no-whole-archive'])\nendif\n"
  },
  {
    "path": "lib/direct/atomic.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__ATOMIC_H__\n#define __DIRECT__ATOMIC_H__\n\n/**********************************************************************************************************************/\n\n#define D_SYNC_ADD_AND_FETCH(ptr,value) \\\n     __sync_add_and_fetch( ptr, value )\n\n#endif\n"
  },
  {
    "path": "lib/direct/clock.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/clock.h>\n#include <direct/debug.h>\n\nD_DEBUG_DOMAIN( Direct_Clock, \"Direct/Clock\", \"Direct Clock time measurement\" );\n\n/**********************************************************************************************************************/\n\n__dfb_no_instrument_function__\nlong long\ndirect_clock_get_micros()\n{\n     return direct_clock_get_time( DIRECT_CLOCK_MONOTONIC );\n}\n\n__dfb_no_instrument_function__\nlong long\ndirect_clock_get_millis()\n{\n     return direct_clock_get_time( DIRECT_CLOCK_MONOTONIC ) / 1000LL;\n}\n\n__dfb_no_instrument_function__\nlong long\ndirect_clock_get_abs_micros()\n{\n     return direct_clock_get_time( DIRECT_CLOCK_REALTIME );\n}\n\n__dfb_no_instrument_function__\nlong long\ndirect_clock_get_abs_millis()\n{\n     return direct_clock_get_time( DIRECT_CLOCK_REALTIME ) / 1000LL;\n}\n"
  },
  {
    "path": "lib/direct/clock.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__CLOCK_H__\n#define __DIRECT__CLOCK_H__\n\n#include <direct/os/clock.h>\n\n/**********************************************************************************************************************/\n\nlong long DIRECT_API direct_clock_get_abs_micros( void );\n\nlong long DIRECT_API direct_clock_get_abs_millis( void );\n\nlong long DIRECT_API direct_clock_get_micros    ( void );\n\nlong long DIRECT_API direct_clock_get_millis    ( void );\n\n#endif\n"
  },
  {
    "path": "lib/direct/compiler.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__COMPILER_H__\n#define __DIRECT__COMPILER_H__\n\n#include <direct/build.h>\n\n/**********************************************************************************************************************/\n\n#define D_FORMAT_PRINTF(n)             __attribute__((__format__(__printf__,n,n+1)))\n#define D_FORMAT_VPRINTF(n)            __attribute__((__format__(__printf__,n,0)))\n\n#define D_UNUSED                       __attribute__((unused))\n\n#define __dfb_no_instrument_function__ __attribute__((no_instrument_function))\n\n#if DIRECT_BUILD_CTORS\n#define __dfb_constructor__            __attribute__((constructor))\n#define __dfb_destructor__             __attribute__((destructor))\n#else\n#define __dfb_constructor__\n#define __dfb_destructor__\n#endif\n\n#endif\n"
  },
  {
    "path": "lib/direct/conf.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/conf.h>\n#include <direct/list.h>\n#include <direct/log.h>\n#include <direct/map.h>\n#include <direct/mem.h>\n#include <direct/messages.h>\n#include <direct/system.h>\n#include <direct/util.h>\n\nD_DEBUG_DOMAIN( Direct_Config, \"Direct/Config\", \"Direct Runtime Configuration options\" );\n\n/**********************************************************************************************************************/\n\nstatic DirectConfig conf = { 0 };\n\nDirectConfig *direct_config = &conf;\nconst char   *direct_config_usage =\n     \"libdirect options:\\n\"\n     \"  disable-module=<module_name>   Suppress loading of this module\\n\"\n     \"  module-dir=<directory>         Override default module search directory\\n\"\n     \"  memcpy=<method>                Skip memcpy() probing (help = show list)\\n\"\n     \"  [no-]quiet                     Disable text output except debug/oom/ooshm messages or direct logs\\n\"\n     \"  [no-]quiet=<type>              Only quiet certain message types (cumulative with 'quiet')\\n\"\n     \"                                 [ info | warning | error | once | unimplemented | banner | bug ]\\n\"\n     \"  [no-]fatal-messages            Enable trap for all message types except banner and info\\n\"\n     \"  [no-]fatal-messages=<type>     Enable trap for certain message types (cumulative with 'fatal-messages')\\n\"\n     \"                                 [ warning | error | once | unimplemented | bug | oom | ooshm ]\\n\"\n     \"  [no-]debug=<domain>            Configure debug messages domain (if no debug level is specified, default = 8)\\n\"\n     \"  debug-level=<level>            Set global debug messages level used by domains (default = 0 for no debug)\\n\"\n     \"                                 Overload 'log-level', the maximum debug messages level is 9\\n\"\n     \"  log=<domain>                   Configure direct logs domain (if no log level is specified, default = 6)\\n\"\n     \"  log-level=<level>              Set global direct logs level used by domains (default = 6 for verbose)\\n\"\n     \"                                 [ 0: none, 1: fatal, 2: error, 3: warning, 4: notice, 5: info, 6: verbose ]\\n\"\n     \"                                 Overload 'debug-level'\\n\"\n     \"  log-all                        Enable all debug messages and direct logs output\\n\"\n     \"  log-none                       Disable all debug messages and direct logs output\\n\"\n     \"  [no-]debugmem                  Enable memory allocation tracking\\n\"\n     \"  [no-]trace                     Enable stack trace support\\n\"\n     \"  [no-]nm-for-trace              Enable running nm in a child process to retrieve symbols\\n\"\n     \"  log-file=<name>                Write all messages to the specified file\\n\"\n     \"  log-udp=<host>:<port>          Send all messages via UDP to the specified host and port\\n\"\n     \"  fatal-level=<fatal_name>       Abort on NONE, ASSERT (default) or ASSUME (incl. ASSERT)\\n\"\n     \"  [no-]sighandler                Enable signal handling (default enabled)\\n\"\n     \"  [no-]sighandler-thread         Enable signal handler thread (default enabled)\\n\"\n     \"  dont-catch=<num>[,<num>...]    Don't catch these signals\\n\"\n     \"  [no-]thread-block-signals      Block all signals in new threads (default enabled)\\n\"\n     \"  thread-priority-scale=<100th>  Apply scaling factor on thread type based priorities\\n\"\n     \"  thread-priority=<priority>     Set priority for the default thread type (default = 100)\\n\"\n     \"  thread-scheduler=<policy>      Select thread scheduler\\n\"\n     \"  thread-stacksize=<stacksize>   Set thread stack size (default = auto)\\n\"\n     \"  default-interface-implementation=<type/name>\\n\"\n     \"                                 Probe interface_type/implementation_name first\\n\"\n     \"  log-delay-rand-loops=<loops>   Add random loops (of max loops) to central logging code for testing purpose\\n\"\n     \"  log-delay-rand-us=<us>         Add random sleep (of max us) to central logging code for testing purpose\\n\"\n     \"  log-delay-min-loops=<loops>    Set minimum busy loops after each log message\\n\"\n     \"  log-delay-min-us=<us>          Set minimum sleep after each log message\\n\"\n     \"  delay-trap-ms=<ms>             Set period to wait instead of raising\\n\"\n     \"\\n\";\n\nstatic DirectMap               *config_options = NULL;\nstatic bool                     config_option_compare( DirectMap *map, const void *key, void *object, void *ctx );\nstatic unsigned int             config_option_hash   ( DirectMap *map, const void *key, void *ctx );\nstatic DirectEnumerationResult  config_option_free   ( DirectMap *map, void *object, void *ctx );\n\n/**********************************************************************************************************************/\n\nvoid\n__D_conf_init()\n{\n     direct_map_create( 123, config_option_compare, config_option_hash, NULL, &config_options );\n\n     direct_config->log_level             = DIRECT_LOG_DEBUG_0;\n     direct_config->trace                 = true;\n     direct_config->fatal                 = DCFL_ASSERT;\n     direct_config->sighandler            = true;\n     direct_config->sighandler_thread     = true;\n     direct_config->thread_block_signals  = true;\n     direct_config->thread_priority_scale = 100;\n\n     char *args = direct_getenv( \"D_ARGS\" );\n\n     if (args) {\n          args = D_STRDUP( args );\n\n          char *p = NULL, *r, *s = args;\n\n          while ((r = direct_strtok_r( s, \",\", &p ))) {\n               char *v;\n\n               direct_trim( &r );\n\n               v = strchr( r, '=' );\n               if (v)\n                    *v++ = 0;\n\n               direct_config_set( r, v );\n\n               s = NULL;\n          }\n\n          D_FREE( args );\n     }\n}\n\nvoid\n__D_conf_deinit()\n{\n     if (config_options) {\n          direct_map_iterate( config_options, config_option_free, NULL );\n          direct_map_destroy( config_options );\n          config_options = NULL;\n     }\n}\n\n/**********************************************************************************************************************/\n\n#define OPTION_NAME_LENGTH 128\n\ntypedef struct {\n     char        name[OPTION_NAME_LENGTH];\n     DirectLink *values;\n} ConfigOption;\n\ntypedef struct {\n     DirectLink  link;\n     char       *value;\n} ConfigOptionValue;\n\nstatic void\nconfig_option_value_add( ConfigOption *option,\n                         const char   *name )\n{\n     ConfigOptionValue *value;\n\n     if (!name)\n          return;\n\n     value = D_CALLOC( 1, sizeof(ConfigOptionValue) + strlen( name ) + 1 );\n     if (!value) {\n          D_OOM();\n          return;\n     }\n\n     value->value = direct_snputs( (char*) (value + 1), name, OPTION_NAME_LENGTH );\n\n     direct_list_append( &option->values, &value->link );\n}\n\nstatic ConfigOption*\nconfig_option_create( const char *name,\n                      const char *value )\n{\n     ConfigOption *option;\n\n     option = D_CALLOC( 1, sizeof(ConfigOption) );\n     if (!option) {\n          D_OOM();\n          return NULL;\n     }\n\n     direct_snputs( option->name, name, OPTION_NAME_LENGTH );\n\n     config_option_value_add( option, value );\n\n     direct_map_insert( config_options, name, option );\n\n     return option;\n}\n\nstatic bool\nconfig_option_compare( DirectMap  *map,\n                       const void *key,\n                       void       *object,\n                       void       *ctx )\n{\n     const char   *map_key   = key;\n     ConfigOption *map_entry = object;\n\n     return strcmp( map_key, map_entry->name ) == 0;\n}\n\nstatic unsigned int\nconfig_option_hash( DirectMap  *map,\n                    const void *key,\n                    void       *ctx )\n{\n     size_t        i       = 0;\n     unsigned int  hash    = 0;\n     const char   *map_key = key;\n\n     while (map_key[i]) {\n          hash = hash * 131 + map_key[i];\n\n          i++;\n     }\n\n     return hash;\n}\n\nstatic DirectEnumerationResult\nconfig_option_free( DirectMap *map,\n                    void      *object,\n                    void      *ctx )\n{\n     ConfigOption      *option = object;\n     ConfigOptionValue *value, *next;\n\n     direct_list_foreach_safe (value, next, option->values) {\n          D_FREE( value );\n     }\n\n     D_FREE( option );\n\n     return DENUM_OK;\n}\n\n/**********************************************************************************************************************/\n\nDirectResult\ndirect_config_set( const char *name,\n                   const char *value )\n{\n     if (strcmp( name, \"disable-module\" ) == 0) {\n          if (value) {\n               int n = 0;\n\n               while (direct_config->disable_module &&\n                      direct_config->disable_module[n])\n                    n++;\n\n               direct_config->disable_module = D_REALLOC( direct_config->disable_module, sizeof(char*) * (n + 2) );\n\n               direct_config->disable_module[n] = D_STRDUP( value );\n               direct_config->disable_module[n+1] = NULL;\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No module name specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"module-dir\" ) == 0) {\n          if (value) {\n               if (direct_config->module_dir)\n                    D_FREE( direct_config->module_dir );\n               direct_config->module_dir = D_STRDUP( value );\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No directory name specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"memcpy\" ) == 0) {\n          if (value) {\n               if (direct_config->memcpy)\n                    D_FREE( direct_config->memcpy );\n               direct_config->memcpy = D_STRDUP( value );\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No method specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"quiet\" ) == 0 || strcmp( name, \"no-quiet\" ) == 0) {\n          /* Enable/disable all at once by default. */\n          DirectMessageType type = DMT_ALL;\n\n          /* Find out the specific message type being configured. */\n          if (value) {\n               if (!strcmp( value, \"info\" ))          type = DMT_INFO;          else\n               if (!strcmp( value, \"warning\" ))       type = DMT_WARNING;       else\n               if (!strcmp( value, \"error\" ))         type = DMT_ERROR;         else\n               if (!strcmp( value, \"once\" ))          type = DMT_ONCE;          else\n               if (!strcmp( value, \"unimplemented\" )) type = DMT_UNIMPLEMENTED; else\n               if (!strcmp( value, \"banner\" ))        type = DMT_BANNER;        else\n               if (!strcmp( value, \"bug\" ))           type = DMT_BUG;\n               else {\n                    D_ERROR( \"Direct/Config: '%s': Unknown message type '%s'!\\n\", name, value );\n                    return DR_INVARG;\n               }\n          }\n\n          /* Set/clear the corresponding flag in the configuration. */\n          if (name[0] == 'q')\n               D_FLAGS_SET( direct_config->quiet, type );\n          else\n               D_FLAGS_CLEAR( direct_config->quiet, type );\n     } else\n     if (strcmp( name, \"fatal-messages\" ) == 0 || strcmp( name, \"no-fatal-messages\" ) == 0) {\n          /* Enable/disable all at once by default. */\n          DirectMessageType type = DMT_ALL & ~(DMT_BANNER | DMT_INFO);\n\n          /* Find out the specific message type being configured. */\n          if (value) {\n               if (!strcmp( value, \"warning\" ))        type = DMT_WARNING;       else\n               if (!strcmp( value, \"error\" ))          type = DMT_ERROR;         else\n               if (!strcmp( value, \"once\" ))           type = DMT_ONCE;          else\n               if (!strcmp( value, \"unimplemented\" ))  type = DMT_UNIMPLEMENTED; else\n               if (!strcmp( value, \"bug\" ))            type = DMT_BUG;           else\n               if (!strcmp( value, \"oom\" ))            type = DMT_OOM;           else\n               if (!strcmp( value, \"ooshm\" ))          type = DMT_OOSHM;\n               else {\n                    D_ERROR( \"Direct/Config: '%s': Unknown message type '%s'!\\n\", name, value );\n                    return DR_INVARG;\n               }\n          }\n\n          /* Set/clear the corresponding flag in the configuration. */\n          if (name[0] == 'f')\n               D_FLAGS_SET( direct_config->fatal_messages, type );\n          else\n               D_FLAGS_CLEAR( direct_config->fatal_messages, type );\n     } else\n     if (strcmp( name, \"no-fatal-messages\" ) == 0) {\n          direct_config->fatal_messages = DMT_NONE;\n     } else\n     if (strcmp( name, \"debug\" ) == 0) {\n          if (value) {\n               DirectLogDomainConfig config = { 0 };\n\n               if (value[0] && value[1] == ':') {\n                    config.level = value[0] - '0' + DIRECT_LOG_DEBUG_0;\n\n                    value += 2;\n               }\n               else\n                    config.level = DIRECT_LOG_DEBUG;\n\n               direct_log_domain_configure( value, &config );\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No domain specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"no-debug\" ) == 0) {\n          if (value) {\n               DirectLogDomainConfig config = { 0 };\n\n               config.level = DIRECT_LOG_DEBUG_0;\n\n               direct_log_domain_configure( value, &config );\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No domain specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"debug-level\" ) == 0) {\n          if (value) {\n               char level;\n\n               if (sscanf( value, \"%c\", &level ) < 1) {\n                    D_ERROR( \"Direct/Config: '%s': Could not parse value!\\n\", name );\n                    return DR_INVARG;\n               }\n\n               direct_config->log_level = level - '0' + DIRECT_LOG_DEBUG_0;\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No value specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"log\" ) == 0) {\n          if (value) {\n               DirectLogDomainConfig config = { 0 };\n\n               if (value[0] && value[1] == ':') {\n                    config.level = value[0] - '0';\n\n                    value += 2;\n               }\n               else\n                    config.level = DIRECT_LOG_VERBOSE;\n\n               direct_log_domain_configure( value, &config );\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No domain specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"log-level\" ) == 0) {\n          if (value) {\n               char level;\n\n               if (sscanf( value, \"%c\", &level ) < 1) {\n                    D_ERROR( \"Direct/Config: '%s': Could not parse value!\\n\", name );\n                    return DR_INVARG;\n               }\n\n               direct_config->log_level = level - '0';\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No value specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"log-all\" ) == 0) {\n          direct_config->log_all = true;\n     } else\n     if (strcmp( name, \"log-none\" ) == 0) {\n          direct_config->log_none = true;\n     } else\n     if (strcmp( name, \"debugmem\" ) == 0) {\n          direct_config->debugmem = true;\n     } else\n     if (strcmp( name, \"no-debugmem\" ) == 0) {\n          direct_config->debugmem = false;\n     } else\n     if (strcmp( name, \"trace\" ) == 0) {\n          direct_config->trace = true;\n     } else\n     if (strcmp( name, \"no-trace\" ) == 0) {\n          direct_config->trace = false;\n     } else\n     if (strcmp( name, \"nm-for-trace\" ) == 0) {\n          direct_config->nm_for_trace = true;\n     } else\n     if (strcmp( name, \"no-nm-for-trace\" ) == 0) {\n          direct_config->nm_for_trace = false;\n     } else\n     if (strcmp( name, \"log-file\" ) == 0 || strcmp( name, \"log-udp\" ) == 0) {\n          if (value) {\n               DirectResult  ret;\n               DirectLog    *log;\n\n               ret = direct_log_create( strcmp( name, \"log-udp\" ) ? DLT_FILE : DLT_UDP, value, &log );\n               if (ret)\n                    return ret;\n\n               if (direct_config->log)\n                    direct_log_destroy( direct_config->log );\n\n               direct_config->log = log;\n\n               direct_log_set_default( log );\n          }\n          else {\n               if (strcmp( name, \"log-udp\" ))\n                    D_ERROR( \"Direct/Config: '%s': No file name specified!\\n\", name );\n               else\n                    D_ERROR( \"Direct/Config: '%s': No host and port specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"fatal-level\" ) == 0) {\n          if (value) {\n               if (!strcasecmp( value, \"none\" ))   direct_config->fatal = DCFL_NONE;   else\n               if (!strcasecmp( value, \"assert\" )) direct_config->fatal = DCFL_ASSERT; else\n               if (!strcasecmp( value, \"assume\" )) direct_config->fatal = DCFL_ASSUME;\n               else {\n                    D_ERROR( \"Direct/Config: '%s': Unknown level specified (use 'none', 'assert', 'assume')!\\n\", name );\n                    return DR_INVARG;\n               }\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No fatal level specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"sighandler\" ) == 0) {\n          direct_config->sighandler = true;\n     } else\n     if (strcmp( name, \"no-sighandler\" ) == 0) {\n          direct_config->sighandler = false;\n     } else\n     if (strcmp( name, \"sighandler-thread\" ) == 0) {\n          direct_config->sighandler_thread = true;\n     } else\n     if (strcmp( name, \"no-sighandler-thread\" ) == 0) {\n          direct_config->sighandler_thread = false;\n     } else\n     if (strcmp( name, \"dont-catch\" ) == 0) {\n          if (value) {\n               char *signals   = D_STRDUP( value );\n               char *p = NULL, *r, *s = signals;\n\n               while ((r = direct_strtok_r( s, \",\", &p ))) {\n                    char          *error;\n                    unsigned long  signum;\n\n                    direct_trim( &r );\n\n                    signum = strtoul( r, &error, 10 );\n\n                    if (*error) {\n                         D_ERROR( \"Direct/Config: '%s': Error in number at '%s'!\\n\", name, error );\n                         D_FREE( signals );\n                         return DR_INVARG;\n                    }\n\n                    sigaddset( &direct_config->dont_catch, signum );\n\n                    s = NULL;\n               }\n\n               D_FREE( signals );\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No signals specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"thread_block_signals\" ) == 0) {\n          direct_config->thread_block_signals = true;\n     } else\n     if (strcmp( name, \"no-thread_block_signals\" ) == 0) {\n          direct_config->thread_block_signals = false;\n     } else\n     if (strcmp( name, \"thread-priority-scale\" ) == 0) {\n          if (value) {\n               int scale;\n\n               if (sscanf( value, \"%d\", &scale ) < 1) {\n                    D_ERROR( \"Direct/Config: '%s': Could not parse value!\\n\", name );\n                    return DR_INVARG;\n               }\n\n               direct_config->thread_priority_scale = scale;\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No value specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"thread-priority\" ) == 0) {\n          if (value) {\n               int priority;\n\n               if (sscanf( value, \"%d\", &priority ) < 1) {\n                    D_ERROR( \"Direct/Config: '%s': Could not parse value!\\n\", name );\n                    return DR_INVARG;\n               }\n\n               direct_config->thread_priority = priority;\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No value specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"thread-scheduler\" ) == 0) {\n          if (value) {\n               if (!strcmp( value, \"other\" ))    direct_config->thread_scheduler = DCTS_OTHER;    else\n               if (!strcmp( value, \"fifo\" ))     direct_config->thread_scheduler = DCTS_FIFO;     else\n               if (!strcmp( value, \"rr\" ))       direct_config->thread_scheduler = DCTS_RR;       else\n               if (!strcmp( value, \"sporadic\" )) direct_config->thread_scheduler = DCTS_SPORADIC;\n               else {\n                    D_ERROR( \"Direct/Config: '%s': Unknown scheduler '%s'!\\n\", name, value );\n                    return DR_INVARG;\n               }\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No thread scheduler specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"thread-stacksize\" ) == 0) {\n          if (value) {\n               int size;\n\n               if (sscanf( value, \"%d\", &size ) < 1) {\n                    D_ERROR( \"Direct/Config: '%s': Could not parse value!\\n\", name );\n                    return DR_INVARG;\n               }\n\n               direct_config->thread_stack_size = size;\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No value specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"default-interface-implementation\" ) == 0) {\n          if (value) {\n               char  itype[255];\n               char *iname = 0;\n               int   n     = 0;\n\n               while (direct_config->default_interface_implementation_types &&\n                      direct_config->default_interface_implementation_types[n])\n                    n++;\n\n               direct_config->default_interface_implementation_types =\n                    D_REALLOC( direct_config->default_interface_implementation_types, sizeof(char*) * (n + 2) );\n               direct_config->default_interface_implementation_names =\n                    D_REALLOC( direct_config->default_interface_implementation_names, sizeof(char*) * (n + 2) );\n\n               iname = strstr( value, \"/\" );\n\n               if (!iname) {\n                    D_ERROR( \"Direct/Config: '%s': No interface/implementation specified!\\n\", name );\n                    return DR_INVARG;\n               }\n\n               if (iname <= value) {\n                    D_ERROR( \"Direct/Config: '%s': No interface specified!\\n\", name );\n                    return DR_INVARG;\n               }\n\n               if (strlen( iname ) < 2) {\n                    D_ERROR( \"Direct/Config: '%s': No implementation specified!\\n\", name );\n                    return DR_INVARG;\n               }\n\n               direct_snputs( itype, value, iname - value + 1 );\n\n               direct_config->default_interface_implementation_types[n] = D_STRDUP( itype );\n               direct_config->default_interface_implementation_types[n+1] = NULL;\n\n               direct_config->default_interface_implementation_names[n] = D_STRDUP( iname + 1 );\n               direct_config->default_interface_implementation_names[n+1] = NULL;\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No interface/implementation specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"log-delay-rand-loops\" ) == 0) {\n          if (value) {\n               int max;\n\n               if (sscanf( value, \"%d\", &max ) < 1) {\n                    D_ERROR( \"Direct/Config: '%s': Could not parse value!\\n\", name );\n                    return DR_INVARG;\n               }\n\n               direct_config->log_delay_rand_loops = max;\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No value specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"log-delay-rand-us\" ) == 0) {\n          if (value) {\n               int max;\n\n               if (sscanf( value, \"%d\", &max ) < 1) {\n                    D_ERROR( \"Direct/Config: '%s': Could not parse value!\\n\", name );\n                    return DR_INVARG;\n               }\n\n               direct_config->log_delay_rand_us = max;\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No value specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"log-delay-min-loops\" ) == 0) {\n          if (value) {\n               int min;\n\n               if (sscanf( value, \"%d\", &min ) < 1) {\n                    D_ERROR( \"Direct/Config: '%s': Could not parse value!\\n\", name );\n                    return DR_INVARG;\n               }\n\n               direct_config->log_delay_min_loops = min;\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No value specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"log-delay-min-us\" ) == 0) {\n          if (value) {\n               int min;\n\n               if (sscanf( value, \"%d\", &min ) < 1) {\n                    D_ERROR( \"Direct/Config: '%s': Could not parse value!\\n\", name );\n                    return DR_INVARG;\n               }\n\n               direct_config->log_delay_min_us = min;\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No value specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"delay-trap-ms\" ) == 0) {\n          if (value) {\n               int ms;\n\n               if (sscanf( value, \"%d\", &ms ) < 1) {\n                    D_ERROR( \"Direct/Config: '%s': Could not parse value!\\n\", name );\n                    return DR_INVARG;\n               }\n\n               direct_config->delay_trap_ms = ms;\n          }\n          else {\n               D_ERROR( \"Direct/Config: '%s': No value specified!\\n\", name );\n               return DR_INVARG;\n          }\n     }\n     else {\n          ConfigOption *option = direct_map_lookup( config_options, name );\n          if (option)\n               config_option_value_add( option, value );\n          else\n               config_option_create( name, value );\n     }\n\n     D_DEBUG_AT( Direct_Config, \"Set %s '%s'\\n\", name, value ?: \"\" );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_config_get( const char  *name,\n                   char       **values,\n                   const int    values_len,\n                   int         *ret_num )\n{\n     ConfigOption      *option;\n     ConfigOptionValue *value;\n     int                num = 0;\n\n     option = direct_map_lookup( config_options, name );\n     if (!option)\n          return DR_ITEMNOTFOUND;\n\n     *ret_num = 0;\n\n     if (!option->values)\n          return DR_OK;\n\n     direct_list_foreach (value, option->values) {\n          if (num >= values_len)\n               break;\n\n          values[num++] = value->value;\n     }\n\n     *ret_num = num;\n\n     return DR_OK;\n}\n\nbool\ndirect_config_has_name( const char *name )\n{\n     ConfigOption      *option;\n\n     option = direct_map_lookup( config_options, name );\n     if (!option)\n          return false;\n\n     return true;\n}\n\nconst char *\ndirect_config_get_value( const char *name )\n{\n     ConfigOption      *option;\n     ConfigOptionValue *value;\n\n     option = direct_map_lookup( config_options, name );\n     if (!option || !option->values)\n          return NULL;\n\n     value = direct_list_get_last( option->values );\n\n     D_ASSERT( value != NULL );\n\n     return value->value;\n}\n\nlong long\ndirect_config_get_int_value( const char *name )\n{\n     return direct_config_get_int_value_with_default( name, 0 );\n}\n\nlong long\ndirect_config_get_int_value_with_default( const char *name,\n                                          long long   def )\n{\n     ConfigOption      *option;\n     ConfigOptionValue *value;\n\n     option = direct_map_lookup( config_options, name );\n     if (!option || !option->values)\n          return def;\n\n     value = direct_list_get_last( option->values );\n\n     D_ASSERT( value != NULL );\n\n     return atoll( value->value );\n}\n"
  },
  {
    "path": "lib/direct/conf.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__CONF_H__\n#define __DIRECT__CONF_H__\n\n#include <direct/log_domain.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     DCFL_NONE   = 0x00000000, /* None is fatal. */\n     DCFL_ASSERT = 0x00000001, /* ASSERT is fatal. */\n     DCFL_ASSUME = 0x00000002  /* ASSERT and ASSUME are fatal. */\n} DirectConfigFatalLevel;\n\ntypedef enum {\n     DCTS_OTHER    = 0x00000000, /* Other scheduling. */\n     DCTS_FIFO     = 0x00000001, /* First in, first out scheduling. */\n     DCTS_RR       = 0x00000002, /* Round-robin scheduling. */\n     DCTS_SPORADIC = 0x00000003  /* Sporadic scheduling. */\n} DirectConfigThreadScheduler;\n\ntypedef enum {\n     DMT_NONE          = 0x00000000, /* No message type. */\n\n     DMT_BANNER        = 0x00000001, /* Startup banner. */\n     DMT_INFO          = 0x00000002, /* Info messages. */\n     DMT_WARNING       = 0x00000004, /* Warnings. */\n     DMT_ERROR         = 0x00000008, /* Error messages: regular, bugs, system call errors, dlopen errors. */\n     DMT_UNIMPLEMENTED = 0x00000010, /* Messages notifying unimplemented functionality. */\n     DMT_ONCE          = 0x00000020, /* One-shot messages. */\n\n     DMT_BUG           = 0x00000080, /* A bug occurred. */\n     DMT_OOM           = 0x00000100, /* Out of memory. */\n     DMT_OOSHM         = 0x00000200, /* Out of shared memory. */\n\n     DMT_ALL           = 0x000003BF  /* All types. */\n} DirectMessageType;\n\ntypedef struct {\n     char                        **disable_module;\n     char                         *module_dir;\n     char                         *memcpy;\n     DirectMessageType             quiet;\n     DirectMessageType             fatal_messages;\n     DirectLogLevel                log_level;\n     bool                          log_all;\n     bool                          log_none;\n     bool                          debugmem;\n     bool                          trace;\n     bool                          nm_for_trace;\n     DirectLog                    *log;\n     DirectConfigFatalLevel        fatal;\n     bool                          sighandler;\n     bool                          sighandler_thread;\n     sigset_t                      dont_catch;\n     bool                          thread_block_signals;\n     int                           thread_priority_scale;\n     int                           thread_priority;\n     DirectConfigThreadScheduler   thread_scheduler;\n     int                           thread_stack_size;\n     char                        **default_interface_implementation_types;\n     char                        **default_interface_implementation_names;\n     int                           log_delay_rand_loops;\n     int                           log_delay_rand_us;\n     int                           log_delay_min_loops;\n     int                           log_delay_min_us;\n     int                           delay_trap_ms;\n} DirectConfig;\n\n/**********************************************************************************************************************/\n\nextern DirectConfig DIRECT_API *direct_config;\n\nextern const char   DIRECT_API *direct_config_usage;\n\n/*\n * Set indiviual option.\n */\nDirectResult        DIRECT_API  direct_config_set                       ( const char  *name,\n                                                                          const char  *value );\n/*\n * Retrieve all values set on option 'name'.\n * Pass an array of char* pointers in 'values' and number of pointers in 'values_len'.\n * The actual returned number of values gets returned in 'ret_num'.\n * The returned pointers are not extra allocated so do not free them.\n */\nDirectResult        DIRECT_API  direct_config_get                       ( const char  *name,\n                                                                          char       **values,\n                                                                          const int    values_len,\n                                                                          int         *ret_num );\n\n/*\n * Check for an occurrence of the passed option.\n */\nbool                DIRECT_API  direct_config_has_name                  ( const char  *name );\n\n/*\n * Return the value for the last occurrence of the passed option's setting.\n */\nconst char          DIRECT_API *direct_config_get_value                 ( const char  *name );\n\n/*\n * Return the integer value for the last occurrence of the passed option's setting.\n */\nlong long           DIRECT_API  direct_config_get_int_value             ( const char  *name );\n\nlong long           DIRECT_API  direct_config_get_int_value_with_default( const char  *name,\n                                                                          long long    def );\n\n/**********************************************************************************************************************/\n\nvoid __D_conf_init  ( void );\nvoid __D_conf_deinit( void );\n\n#endif\n"
  },
  {
    "path": "lib/direct/debug.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/debug.h>\n\n#if DIRECT_BUILD_TEXT\n\n#include <direct/conf.h>\n\n#if DIRECT_BUILD_DEBUGS\n#include <direct/log.h>\n#include <direct/system.h>\n#include <direct/thread.h>\n#include <direct/trace.h>\n#endif /* DIRECT_BUILD_DEBUGS */\n\n#endif /* DIRECT_BUILD_TEXT */\n\n/**********************************************************************************************************************/\n\n#if DIRECT_BUILD_TEXT\n\n__dfb_no_instrument_function__\nvoid\ndirect_debug_at_always( DirectLogDomain *domain,\n                        const char      *format, ... )\n{\n     if (direct_config->log_level >= DIRECT_LOG_DEBUG) {\n          va_list ap;\n\n          va_start( ap, format );\n          direct_log_domain_vprintf( domain, DIRECT_LOG_NONE, format, ap );\n          va_end( ap );\n     }\n}\n\n#if DIRECT_BUILD_DEBUGS\n\n__dfb_no_instrument_function__\nvoid\ndirect_debug_log( DirectLogDomain *domain,\n                  unsigned int     debug_level,\n                  const char      *format, ... )\n{\n     va_list ap;\n\n     debug_level += DIRECT_LOG_DEBUG_0;\n\n     va_start( ap, format );\n     direct_log_domain_vprintf( domain, debug_level > DIRECT_LOG_DEBUG_9 ? DIRECT_LOG_DEBUG_9 : debug_level, format,\n                                ap );\n     va_end( ap );\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_debug_at( DirectLogDomain *domain,\n                 const char      *format, ... )\n{\n     va_list ap;\n\n     va_start( ap, format );\n     direct_log_domain_vprintf( domain, DIRECT_LOG_DEBUG, format, ap );\n     va_end( ap );\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_assertion( const char *exp,\n                  const char *func,\n                  const char *file,\n                  int         line )\n{\n     long long   millis = direct_clock_get_millis();\n     const char *name   = direct_thread_self_name();\n\n     direct_log_printf( NULL, \"(!) [%-15s %3lld.%03lld] (%5d) *** Assertion [%s] failed *** [%s:%d in %s()]\\n\",\n                        name ?: \"  NO NAME  \", millis / 1000LL, millis % 1000LL, direct_gettid(), exp,\n                        file, line, func );\n\n     direct_trace_print_stack( NULL );\n\n     if (direct_config->fatal >= DCFL_ASSERT)\n          direct_trap( \"Assertion\", SIGTRAP );\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_assumption( const char *exp,\n                   const char *func,\n                   const char *file,\n                   int         line )\n{\n     long long   millis = direct_clock_get_millis();\n     const char *name   = direct_thread_self_name();\n\n     direct_log_printf( NULL, \"(!) [%-15s %3lld.%03lld] (%5d) *** Assumption [%s] failed *** [%s:%d in %s()]\\n\",\n                        name ?: \"  NO NAME  \", millis / 1000LL, millis % 1000LL, direct_gettid(), exp,\n                        file, line, func );\n\n     direct_trace_print_stack( NULL );\n\n     if (direct_config->fatal >= DCFL_ASSUME)\n          direct_trap( \"Assumption\", SIGTRAP );\n}\n\n#else /* DIRECT_BUILD_DEBUGS */\n\nvoid\ndirect_debug_log( DirectLogDomain *domain,\n                  unsigned int     debug_level,\n                  const char      *format, ... )\n{\n}\n\nvoid\ndirect_debug_at( DirectLogDomain *domain,\n                 const char      *format, ... )\n{\n}\n\nvoid\ndirect_assertion( const char *exp,\n                  const char *func,\n                  const char *file,\n                  int         line )\n{\n}\n\nvoid\ndirect_assumption( const char *exp,\n                   const char *func,\n                   const char *file,\n                   int         line )\n{\n}\n\n#endif /* DIRECT_BUILD_DEBUGS */\n\n#endif /* DIRECT_BUILD_TEXT */\n"
  },
  {
    "path": "lib/direct/debug.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__DEBUG_H__\n#define __DIRECT__DEBUG_H__\n\n#include <direct/log_domain.h>\n\n#if DIRECT_BUILD_TEXT\n\n#if !DIRECT_BUILD_DEBUGS\n#ifdef DIRECT_ENABLE_DEBUG\n#define DIRECT_MINI_DEBUG\n#endif\n#undef DIRECT_ENABLE_DEBUG\n#endif /* DIRECT_BUILD_DEBUGS */\n\n#ifdef DIRECT_MINI_DEBUG\n#include <direct/conf.h>\n#include <direct/log.h>\n#include <direct/system.h>\n#include <direct/trace.h>\n#include <direct/thread.h>\n#endif /* DIRECT_MINI_DEBUG */\n\n#endif /* DIRECT_BUILD_TEXT */\n\n/**********************************************************************************************************************/\n\n#define D_DEBUG_DOMAIN(_identifier,_name,_description)                             \\\n     static DirectLogDomain _identifier D_UNUSED = {                               \\\n          _description, _name, sizeof(_name) - 1, 0, false, { DIRECT_LOG_NONE, 0 } \\\n     }\n\nstatic __inline__ void\ndirect_debug_config_domain( const char *name,\n                            bool        enable )\n{\n     direct_log_domain_config_level( name, enable ? DIRECT_LOG_ALL : DIRECT_LOG_NONE );\n}\n\n#if DIRECT_BUILD_TEXT\n\nvoid DIRECT_API direct_debug_at_always( DirectLogDomain *domain,\n                                        const char      *format, ... ) D_FORMAT_PRINTF(2);\n\n/*\n * debug level 1-9 (0 = verbose)\n */\nvoid DIRECT_API direct_debug_log      ( DirectLogDomain *domain,\n                                        unsigned int     debug_level,\n                                        const char      *format, ... ) D_FORMAT_PRINTF(3);\n\nvoid DIRECT_API direct_debug_at       ( DirectLogDomain *domain,\n                                        const char      *format, ... ) D_FORMAT_PRINTF(2);\n\nvoid DIRECT_API direct_assertion      ( const char      *exp,\n                                        const char      *func,\n                                        const char      *file,\n                                        int              line );\n\nvoid DIRECT_API direct_assumption     ( const char      *exp,\n                                        const char      *func,\n                                        const char      *file,\n                                        int              line );\n\n#if DIRECT_BUILD_DEBUG || defined(DIRECT_ENABLE_DEBUG)\n\n#define D_DEBUG_ENABLED 1\n\n#define D_DEBUG_LOG(d,l,...)                                                                                      \\\n     do {                                                                                                         \\\n          direct_debug_log( &d, l, __VA_ARGS__ );                                                                 \\\n     } while (0)\n\n#define D_DEBUG_AT(d,...)                                                                                         \\\n     do {                                                                                                         \\\n          direct_debug_at( &d, __VA_ARGS__ );                                                                     \\\n     } while (0)\n\n#define D_ASSERT(exp)                                                                                             \\\n     do {                                                                                                         \\\n          if (!(exp))                                                                                             \\\n               direct_assertion( #exp, __FUNCTION__, __FILE__, __LINE__ );                                        \\\n     } while (0)\n\n#define D_ASSUME(exp)                                                                                             \\\n     do {                                                                                                         \\\n          if (!(exp))                                                                                             \\\n               direct_assumption( #exp, __FUNCTION__, __FILE__, __LINE__ );                                       \\\n     } while (0)\n\n#elif defined(DIRECT_MINI_DEBUG)\n\n/*\n * mini debug mode\n */\n\n#define D_DEBUG_ENABLED 2\n\n#define D_DEBUG_LOG(d,l,...)                                                                                      \\\n     do {                                                                                                         \\\n          if (direct_config->log_level >= DIRECT_LOG_DEBUG)                                                       \\\n               direct_debug_at_always( &d, __VA_ARGS__ );                                                         \\\n     } while (0)\n\n#define D_DEBUG_AT(d,...)                                                                                         \\\n     do {                                                                                                         \\\n          if (direct_config->log_level >= DIRECT_LOG_DEBUG)                                                       \\\n               direct_debug_at_always( &d, __VA_ARGS__ );                                                         \\\n     } while (0)\n\n#define D_CHECK(exp,aa)                                                                                           \\\n     do {                                                                                                         \\\n          if (!(exp)) {                                                                                           \\\n               long long   millis = direct_clock_get_millis();                                                    \\\n               const char *name   = direct_thread_self_name();                                                    \\\n                                                                                                                  \\\n               direct_log_printf( NULL,                                                                           \\\n                                  \"(!) [%-15s %3lld.%03lld] (%5d) *** \" #aa \" [%s] failed *** [%s:%d in %s()]\\n\", \\\n                                  name ?: \"  NO NAME  \", millis / 1000LL, millis % 1000LL, direct_gettid(), #exp, \\\n                                  __FILE__, __LINE__, __FUNCTION__ );                                             \\\n                                                                                                                  \\\n               direct_trace_print_stack( NULL );                                                                  \\\n          }                                                                                                       \\\n     } while (0)\n\n#define D_ASSERT(exp)                                                                                             \\\n     D_CHECK( exp, Assertion )\n\n#define D_ASSUME(exp)                                                                                             \\\n     D_CHECK( exp, Assumption )\n\n#endif\n\n#endif /* DIRECT_BUILD_TEXT */\n\n/*\n * Fallback definitions, e.g. without DIRECT_BUILD_TEXT or DIRECT_BUILD_DEBUG or DIRECT_ENABLE_DEBUG\n */\n\n#ifndef D_DEBUG_ENABLED\n#define D_DEBUG_ENABLED 0\n#endif\n\n#ifndef D_DEBUG_LOG\n#define D_DEBUG_LOG(d,l,...)    do {} while (0)\n#endif\n\n#ifndef D_DEBUG_AT\n#define D_DEBUG_AT(d,...)       do {} while (0)\n#endif\n\n#ifndef D_ASSERT\n#define D_ASSERT(exp)           do {} while (0)\n#endif\n\n#ifndef D_ASSUME\n#define D_ASSUME(exp)           do {} while (0)\n#endif\n\n/*\n * Magic Assertions & Utilities\n */\n\n#if DIRECT_BUILD_DEBUGS\n\n#define D_MAGIC(spell)          ( ( ((spell)[sizeof(spell)*8/9] << 24) |         \\\n                                    ((spell)[sizeof(spell)*7/9] << 16) |         \\\n                                    ((spell)[sizeof(spell)*6/9] <<  8) |         \\\n                                    ((spell)[sizeof(spell)*5/9]      )   ) ^     \\\n                                  ( ((spell)[sizeof(spell)*4/9] << 24) |         \\\n                                    ((spell)[sizeof(spell)*3/9] << 16) |         \\\n                                    ((spell)[sizeof(spell)*2/9] <<  8) |         \\\n                                    ((spell)[sizeof(spell)*1/9]      )   ) )\n\n#define D_MAGIC_CHECK(o,m)      ((o) != NULL && (o)->magic == D_MAGIC(#m))\n\n#define D_MAGIC_SET(o,m)        do {                                             \\\n                                     D_ASSERT( (o) != NULL );                    \\\n                                     D_ASSUME( (o)->magic != D_MAGIC(#m) );      \\\n                                                                                 \\\n                                     (o)->magic = D_MAGIC(#m);                   \\\n                                } while (0)\n\n#define D_MAGIC_SET_ONLY(o,m)   do {                                             \\\n                                     D_ASSERT( (o) != NULL );                    \\\n                                                                                 \\\n                                     (o)->magic = D_MAGIC(#m);                   \\\n                                } while (0)\n\n#define D_MAGIC_ASSERT(o,m)     do {                                             \\\n                                     D_ASSERT( (o) != NULL );                    \\\n                                     D_ASSERT( (o)->magic == D_MAGIC(#m) );      \\\n                                } while (0)\n\n#define D_MAGIC_ASSUME(o,m)     do {                                             \\\n                                     D_ASSUME( (o) != NULL );                    \\\n                                     if (o)                                      \\\n                                          D_ASSUME( (o)->magic == D_MAGIC(#m) ); \\\n                                } while (0)\n\n#define D_MAGIC_ASSERT_IF(o,m)  do {                                             \\\n                                     if (o)                                      \\\n                                          D_ASSERT( (o)->magic == D_MAGIC(#m) ); \\\n                                } while (0)\n\n#define D_MAGIC_CLEAR(o)        do {                                             \\\n                                     D_ASSERT( (o) != NULL );                    \\\n                                     D_ASSUME( (o)->magic != 0 );                \\\n                                                                                 \\\n                                     (o)->magic = 0;                             \\\n                                } while (0)\n\n#else /* DIRECT_BUILD_DEBUGS */\n\n#define D_MAGIC_CHECK(o,m)      ((o) != NULL)\n\n#define D_MAGIC_SET(o,m)        do {} while (0)\n\n#define D_MAGIC_SET_ONLY(o,m)   do {} while (0)\n\n#define D_MAGIC_ASSERT(o,m)     do {} while (0)\n\n#define D_MAGIC_ASSUME(o,m)     do {} while (0)\n\n#define D_MAGIC_ASSERT_IF(o,m)  do {} while (0)\n\n#define D_MAGIC_CLEAR(o)        do {} while (0)\n\n#endif /* DIRECT_BUILD_DEBUGS */\n\n#define D_FLAGS_ASSERT(flags,f) D_ASSERT( D_FLAGS_ARE_IN( flags, f ) )\n\n#endif\n"
  },
  {
    "path": "lib/direct/direct.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/direct.h>\n#include <direct/interface.h>\n#include <direct/list.h>\n#include <direct/signals.h>\n#include <direct/thread.h>\n#include <direct/trace.h>\n\nD_DEBUG_DOMAIN( Direct_Main, \"Direct/Main\", \"Direct Main initialization and shutdown\" );\n\n/**********************************************************************************************************************/\n\nstruct __D_DirectCleanupHandler {\n     DirectLink                link;\n\n     int                       magic;\n\n     DirectCleanupHandlerFunc  func;\n     void                     *ctx;\n};\n\n/**********************************************************************************************************************/\n\nstatic int          refs;\nstatic DirectLink  *handlers;\nstatic DirectMutex  main_lock;\n\n/**********************************************************************************************************************/\n\nvoid\n__D_direct_init()\n{\n     direct_mutex_init( &main_lock );\n}\n\nvoid\n__D_direct_deinit()\n{\n     direct_print_memleaks();\n\n     direct_print_interface_leaks();\n\n     direct_mutex_deinit( &main_lock );\n}\n\n/**********************************************************************************************************************/\n\nDirectResult\ndirect_initialize()\n{\n     direct_clock_set_time( DIRECT_CLOCK_SESSION, 0 );\n\n     direct_mutex_lock( &main_lock );\n\n     D_DEBUG_AT( Direct_Main, \"%s() called... (from %s)\\n\", __FUNCTION__,\n                 direct_trace_lookup_symbol_at( direct_trace_get_caller() ) );\n\n     if (refs++) {\n          D_DEBUG_AT( Direct_Main, \"...%d references now\\n\", refs );\n          direct_mutex_unlock( &main_lock );\n          return DR_OK;\n     }\n     else if (!direct_thread_self_name())\n          direct_thread_set_name( \"Main Thread\" );\n\n     D_DEBUG_AT( Direct_Main, \"...first reference, initializing now\\n\" );\n\n     direct_signals_initialize();\n\n     direct_mutex_unlock( &main_lock );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_shutdown()\n{\n     direct_mutex_lock( &main_lock );\n\n     D_DEBUG_AT( Direct_Main, \"%s() called... (from %s)\\n\", __FUNCTION__,\n                 direct_trace_lookup_symbol_at( direct_trace_get_caller() ) );\n\n     if (refs == 1) {\n          D_DEBUG_AT( Direct_Main, \"...shutting down now\\n\" );\n\n          direct_signals_shutdown();\n\n          D_DEBUG_AT( Direct_Main, \"  -> done\\n\" );\n     }\n     else\n          D_DEBUG_AT( Direct_Main, \"...%d references left\\n\", refs - 1 );\n\n     refs--;\n\n     direct_mutex_unlock( &main_lock );\n\n     return DR_OK;\n}\n\nstatic void\ndirect_atexit_handler( void )\n{\n     DirectCleanupHandler *handler, *temp;\n\n     direct_list_foreach_safe (handler, temp, handlers) {\n          D_DEBUG_AT( Direct_Main, \"Calling cleanup func %p( %p )...\\n\", handler->func, handler->ctx );\n\n          direct_list_remove( &handlers, &handler->link );\n\n          handler->func( handler->ctx );\n\n          D_MAGIC_CLEAR( handler );\n\n          D_FREE( handler );\n     }\n}\n\nDirectResult\ndirect_cleanup_handler_add( DirectCleanupHandlerFunc   func,\n                            void                      *ctx,\n                            DirectCleanupHandler     **ret_handler )\n{\n     DirectCleanupHandler *handler;\n\n     D_ASSERT( func != NULL );\n     D_ASSERT( ret_handler != NULL );\n\n     D_DEBUG_AT( Direct_Main, \"Adding cleanup handler %p with context %p...\\n\", func, ctx );\n\n     handler = D_CALLOC( 1, sizeof(DirectCleanupHandler) );\n     if (!handler) {\n          return DR_NOLOCALMEMORY;\n     }\n\n     handler->func = func;\n     handler->ctx  = ctx;\n\n     D_MAGIC_SET( handler, DirectCleanupHandler );\n\n     direct_mutex_lock( &main_lock );\n\n     if (handlers == NULL)\n          atexit( direct_atexit_handler );\n\n     direct_list_append( &handlers, &handler->link );\n\n     direct_mutex_unlock( &main_lock );\n\n     *ret_handler = handler;\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_cleanup_handler_remove( DirectCleanupHandler *handler )\n{\n     D_MAGIC_ASSERT( handler, DirectCleanupHandler );\n\n     D_DEBUG_AT( Direct_Main, \"Removing cleanup handler %p with context %p...\\n\", handler->func, handler->ctx );\n\n     /* Safety check, in case handler is removed from within itself being invoked. */\n     if (handler->link.prev) {\n          direct_mutex_lock( &main_lock );\n          direct_list_remove( &handlers, &handler->link );\n          direct_mutex_unlock( &main_lock );\n\n          D_MAGIC_CLEAR( handler );\n\n          D_FREE( handler );\n     }\n\n     return DR_OK;\n}\n"
  },
  {
    "path": "lib/direct/direct.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__DIRECT_H__\n#define __DIRECT__DIRECT_H__\n\n#include <direct/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef void (*DirectCleanupHandlerFunc)( void *ctx );\n\n/**********************************************************************************************************************/\n\nDirectResult DIRECT_API direct_initialize            ( void );\n\nDirectResult DIRECT_API direct_shutdown              ( void );\n\nDirectResult DIRECT_API direct_cleanup_handler_add   ( DirectCleanupHandlerFunc   func,\n                                                       void                      *ctx,\n                                                       DirectCleanupHandler     **ret_handler );\n\nDirectResult DIRECT_API direct_cleanup_handler_remove( DirectCleanupHandler      *handler );\n\n/**********************************************************************************************************************/\n\nvoid __D_direct_init  ( void );\nvoid __D_direct_deinit( void );\n\n#endif\n"
  },
  {
    "path": "lib/direct/direct_result.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/direct_result.h>\n#include <direct/result.h>\n#include <direct/util.h>\n\n/**********************************************************************************************************************/\n\nstatic const char       *DirectResult__strings[DR__RESULT_END - DR__RESULT_BASE];\n\nstatic DirectResultType  DirectResult__type = {\n     0, 0, DR__RESULT_BASE, DirectResult__strings, D_ARRAY_SIZE(DirectResult__strings)\n};\n\n/**********************************************************************************************************************/\n\nvoid\n__D_direct_result_init()\n{\n     DirectResult__strings[0] = \"DirectResult\";\n\n     DirectResult__strings[D_RESULT_INDEX(DR_FAILURE)] = \"A general or unknown error occurred\";\n     DirectResult__strings[D_RESULT_INDEX(DR_INIT)] = \"A general initialization error occurred\";\n     DirectResult__strings[D_RESULT_INDEX(DR_BUG)] = \"Internal bug or inconsistency has been detected\";\n     DirectResult__strings[D_RESULT_INDEX(DR_DEAD)] = \"Interface has a zero reference counter (available in debug mode)\";\n     DirectResult__strings[D_RESULT_INDEX(DR_UNSUPPORTED)] = \"The requested operation or an argument is (currently) not supported\";\n     DirectResult__strings[D_RESULT_INDEX(DR_UNIMPLEMENTED)] = \"The requested operation is not implemented, yet\";\n     DirectResult__strings[D_RESULT_INDEX(DR_ACCESSDENIED)] = \"Access to the resource is denied\";\n     DirectResult__strings[D_RESULT_INDEX(DR_INVAREA)] = \"An invalid area has been specified or detected\";\n     DirectResult__strings[D_RESULT_INDEX(DR_INVARG)] = \"An invalid argument has been specified\";\n     DirectResult__strings[D_RESULT_INDEX(DR_NOLOCALMEMORY)] = \"There's not enough local system memory\";\n     DirectResult__strings[D_RESULT_INDEX(DR_NOSHAREDMEMORY)] = \"There's not enough shared system memory\";\n     DirectResult__strings[D_RESULT_INDEX(DR_LOCKED)] = \"The resource is (already) locked\";\n     DirectResult__strings[D_RESULT_INDEX(DR_BUFFEREMPTY)] = \"The buffer is empty\";\n     DirectResult__strings[D_RESULT_INDEX(DR_FILENOTFOUND)] = \"The specified file has not been found\";\n     DirectResult__strings[D_RESULT_INDEX(DR_IO)] = \"A general I/O error occurred\";\n     DirectResult__strings[D_RESULT_INDEX(DR_BUSY)] = \"The resource or device is busy\";\n     DirectResult__strings[D_RESULT_INDEX(DR_NOIMPL)] = \"No implementation for this interface or content type has been found\";\n     DirectResult__strings[D_RESULT_INDEX(DR_TIMEOUT)] = \"The operation timed out\";\n     DirectResult__strings[D_RESULT_INDEX(DR_THIZNULL)] = \"'thiz' pointer is NULL\";\n     DirectResult__strings[D_RESULT_INDEX(DR_IDNOTFOUND)] = \"No resource has been found by the specified id\";\n     DirectResult__strings[D_RESULT_INDEX(DR_DESTROYED)] = \"The requested object has been destroyed\";\n     DirectResult__strings[D_RESULT_INDEX(DR_FUSION)] = \"Internal fusion error detected, most likely related to IPC resources\";\n     DirectResult__strings[D_RESULT_INDEX(DR_BUFFERTOOLARGE)] = \"Buffer is too large\";\n     DirectResult__strings[D_RESULT_INDEX(DR_INTERRUPTED)] = \"The operation has been interrupted\";\n     DirectResult__strings[D_RESULT_INDEX(DR_NOCONTEXT)] = \"No context available\";\n     DirectResult__strings[D_RESULT_INDEX(DR_TEMPUNAVAIL)] = \"Temporarily unavailable\";\n     DirectResult__strings[D_RESULT_INDEX(DR_LIMITEXCEEDED)] = \"Attempted to exceed limit, i.e. any kind of maximum size, count etc\";\n     DirectResult__strings[D_RESULT_INDEX(DR_NOSUCHMETHOD)] = \"Requested method is not known\";\n     DirectResult__strings[D_RESULT_INDEX(DR_NOSUCHINSTANCE)] = \"Requested instance is not known\";\n     DirectResult__strings[D_RESULT_INDEX(DR_ITEMNOTFOUND)] = \"No such item found\";\n     DirectResult__strings[D_RESULT_INDEX(DR_VERSIONMISMATCH)] = \"Some versions didn't match\";\n     DirectResult__strings[D_RESULT_INDEX(DR_EOF)] = \"Reached end of file\";\n     DirectResult__strings[D_RESULT_INDEX(DR_SUSPENDED)] = \"The requested object is suspended\";\n     DirectResult__strings[D_RESULT_INDEX(DR_INCOMPLETE)] = \"The operation has been executed, but not completely\";\n     DirectResult__strings[D_RESULT_INDEX(DR_NOCORE)] = \"Core part not available\";\n     DirectResult__strings[D_RESULT_INDEX(DR_SIGNALLED)] = \"Received a signal, e.g. while waiting\";\n     DirectResult__strings[D_RESULT_INDEX(DR_TASK_NOT_FOUND)] = \"The corresponding task has not been found\";\n\n     DirectResultTypeRegister( &DirectResult__type );\n}\n\nvoid\n__D_direct_result_deinit()\n{\n     DirectResultTypeUnregister( &DirectResult__type );\n}\n"
  },
  {
    "path": "lib/direct/direct_result.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__DIRECT_RESULT_H__\n#define __DIRECT__DIRECT_RESULT_H__\n\n/**********************************************************************************************************************/\n\nvoid __D_direct_result_init  ( void );\nvoid __D_direct_result_deinit( void );\n\n#endif\n"
  },
  {
    "path": "lib/direct/filesystem.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__FILESYSTEM_H__\n#define __DIRECT__FILESYSTEM_H__\n\n#include <direct/os/filesystem.h>\n\n/**********************************************************************************************************************/\n\n#endif\n"
  },
  {
    "path": "lib/direct/hash.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/debug.h>\n#include <direct/hash.h>\n#include <direct/mem.h>\n#include <direct/messages.h>\n#include <direct/util.h>\n\nD_DEBUG_DOMAIN( Direct_Hash, \"Direct/Hash\", \"Direct Hash table\" );\n\n/**********************************************************************************************************************/\n\nstatic const unsigned int primes[] =\n{\n     11,\n     19,\n     37,\n     73,\n     109,\n     163,\n     251,\n     367,\n     557,\n     823,\n     1237,\n     1861,\n     2777,\n     4177,\n     6247,\n     9371,\n     14057,\n     21089,\n     31627,\n     47431,\n     71143,\n     106721,\n     160073,\n     240101,\n     360163,\n     540217,\n     810343,\n     1215497,\n     1823231,\n     2734867,\n     4102283,\n     6153409,\n     9230113,\n     13845163,\n};\n\nstatic const unsigned int nprimes = D_ARRAY_SIZE(primes);\n\nstatic unsigned int\nspaced_primes_closest( unsigned int num )\n{\n     unsigned int i;\n     for (i = 0; i < nprimes; i++)\n          if (primes[i] > num)\n               return primes[i];\n     return primes[nprimes-1];\n}\n\n#define DIRECT_HASH_MIN_SIZE 11\n#define DIRECT_HASH_MAX_SIZE 13845163\n\n/**********************************************************************************************************************/\n\nstatic __inline__ int\nlocate_key( const DirectHash *hash,\n            unsigned long     key )\n{\n     int                      pos;\n     const DirectHashElement *element;\n\n     D_MAGIC_ASSERT( hash, DirectHash );\n     D_ASSERT( hash->size > 0 );\n     D_ASSERT( hash->Elements != NULL );\n\n     pos = key % hash->size;\n\n     element = &hash->Elements[pos];\n\n     while (element->value) {\n          if (element->value != DIRECT_HASH_ELEMENT_REMOVED && element->key == key)\n               return pos;\n\n          if (++pos == hash->size)\n               pos = 0;\n\n          element = &hash->Elements[pos];\n     }\n\n     return -1;\n}\n\n/**********************************************************************************************************************/\n\nDirectResult\ndirect_hash_create( int          size,\n                    DirectHash **ret_hash )\n{\n     DirectHash *hash;\n\n     hash = D_CALLOC( 1, sizeof(DirectHash) );\n     if (!hash)\n          return D_OOM();\n\n     direct_hash_init( hash, size );\n\n     *ret_hash = hash;\n\n     return DR_OK;\n}\n\nvoid\ndirect_hash_destroy( DirectHash *hash )\n{\n     D_MAGIC_ASSERT( hash, DirectHash );\n\n     direct_hash_deinit( hash );\n\n     D_FREE( hash );\n}\n\nvoid\ndirect_hash_init( DirectHash *hash,\n                  int         size )\n{\n     if (size < DIRECT_HASH_MIN_SIZE)\n          size = DIRECT_HASH_MIN_SIZE;\n\n     D_DEBUG_AT( Direct_Hash, \"Creating hash table with initial capacity of %d...\\n\", size );\n\n     hash->size     = size;\n     hash->Elements = NULL;\n\n     D_MAGIC_SET( hash, DirectHash );\n}\n\nvoid\ndirect_hash_deinit( DirectHash *hash )\n{\n     D_MAGIC_ASSERT( hash, DirectHash );\n\n     D_MAGIC_CLEAR( hash );\n\n     if (hash->Elements) {\n          if (hash->disable_debugging_alloc)\n               direct_free( hash->Elements );\n          else\n               D_FREE( hash->Elements );\n\n          hash->Elements = NULL;\n     }\n}\n\nint\ndirect_hash_count( DirectHash *hash )\n{\n     D_MAGIC_ASSERT( hash, DirectHash );\n\n     return hash->count;\n}\n\nDirectResult\ndirect_hash_insert( DirectHash    *hash,\n                    unsigned long  key,\n                    void          *value )\n{\n     int                pos;\n     DirectHashElement *element;\n\n     D_MAGIC_ASSERT( hash, DirectHash );\n     D_ASSERT( hash->size > 0 );\n     D_ASSERT( value != NULL );\n\n     if (!hash->Elements) {\n          if (hash->disable_debugging_alloc)\n               hash->Elements = direct_calloc( hash->size, sizeof(DirectHashElement) );\n          else\n               hash->Elements = D_CALLOC( hash->size, sizeof(DirectHashElement) );\n\n          if (!hash->Elements)\n               return D_OOM();\n     }\n\n     if ((hash->count + hash->removed) > hash->size / 2) {\n          int                i, size;\n          DirectHashElement *elements;\n\n          size = spaced_primes_closest( hash->size );\n          if (size > DIRECT_HASH_MAX_SIZE)\n               size = DIRECT_HASH_MAX_SIZE;\n          if (size < DIRECT_HASH_MIN_SIZE)\n               size = DIRECT_HASH_MIN_SIZE;\n\n          D_DEBUG_AT( Direct_Hash, \"Resizing from %d to %d... (count %d, removed %d)\\n\",\n                      hash->size, size, hash->count, hash->removed );\n\n          if (hash->disable_debugging_alloc)\n               elements = direct_calloc( size, sizeof(DirectHashElement) );\n          else\n               elements = D_CALLOC( size, sizeof(DirectHashElement) );\n          if (!elements) {\n               D_WARN( \"out of memory\" );\n               return DR_NOLOCALMEMORY;\n          }\n\n          for (i = 0; i < hash->size; i++) {\n               DirectHashElement *insertElement;\n\n               element = &hash->Elements[i];\n\n               if (element->value && element->value != DIRECT_HASH_ELEMENT_REMOVED) {\n                    pos = element->key % size;\n\n                    insertElement = &elements[pos];\n                    while (insertElement->value && insertElement->value != DIRECT_HASH_ELEMENT_REMOVED) {\n                         if (++pos == size)\n                              pos = 0;\n\n                         insertElement = &elements[pos];\n                    }\n\n                    elements[pos] = *element;\n               }\n          }\n\n          if (hash->disable_debugging_alloc)\n               direct_free( hash->Elements );\n          else\n               D_FREE( hash->Elements );\n\n          hash->size     = size;\n          hash->Elements = elements;\n          hash->removed  = 0;\n     }\n\n     pos = key % hash->size;\n\n     D_DEBUG_AT( Direct_Hash, \"Attempting to insert key 0x%08lx at position %d\\n\", key, pos );\n\n     element = &hash->Elements[pos];\n\n     while (element->value && element->value != DIRECT_HASH_ELEMENT_REMOVED) {\n          if (element->key == key) {\n               D_BUG( \"key already exists\" );\n               return DR_BUG;\n          }\n\n          if (++pos == hash->size)\n               pos = 0;\n\n          element = &hash->Elements[pos];\n     }\n\n     if (element->value == DIRECT_HASH_ELEMENT_REMOVED)\n          hash->removed--;\n\n     element->key   = key;\n     element->value = value;\n\n     hash->count++;\n\n     D_DEBUG_AT( Direct_Hash, \"  -> inserted, count = %d, removed = %d, size = %d\\n\",\n                 hash->count, hash->removed, hash->size );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_hash_remove( DirectHash    *hash,\n                    unsigned long  key )\n{\n     int pos;\n\n     D_MAGIC_ASSERT( hash, DirectHash );\n\n     if (!hash->Elements)\n          return DR_BUFFEREMPTY;\n\n     pos = locate_key( hash, key );\n     if (pos == -1) {\n          D_WARN( \"key not found\" );\n          return DR_ITEMNOTFOUND;\n     }\n\n     hash->Elements[pos].value = DIRECT_HASH_ELEMENT_REMOVED;\n\n     hash->count--;\n     hash->removed++;\n\n     D_DEBUG_AT( Direct_Hash, \"Removed key 0x%08lx at %d, count = %d, removed = %d, size = %d\\n\",\n                 key, pos, hash->count, hash->removed, hash->size );\n\n     return DR_OK;\n}\n\nvoid *\ndirect_hash_lookup( const DirectHash *hash,\n                    unsigned long     key )\n{\n     int pos;\n\n     D_MAGIC_ASSERT( hash, DirectHash );\n\n     if (!hash->Elements)\n          return NULL;\n\n     pos = locate_key( hash, key );\n\n     return (pos != -1) ? hash->Elements[pos].value : NULL;\n}\n\nvoid\ndirect_hash_iterate( DirectHash             *hash,\n                     DirectHashIteratorFunc  func,\n                     void                   *ctx )\n{\n     int i;\n\n     D_MAGIC_ASSERT( hash, DirectHash );\n\n     if (!hash->Elements)\n          return;\n\n     for (i = 0; i < hash->size; i++) {\n          DirectHashElement *element = &hash->Elements[i];\n\n          if (!element->value || element->value == DIRECT_HASH_ELEMENT_REMOVED)\n               continue;\n\n          if (!func( hash, element->key, element->value, ctx ) )\n               return;\n     }\n}\n"
  },
  {
    "path": "lib/direct/hash.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__HASH_H__\n#define __DIRECT__HASH_H__\n\n#include <direct/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     unsigned long  key;\n     void          *value;\n} DirectHashElement;\n\nstruct __D_DirectHash {\n     int                magic;\n\n     int                size;\n\n     int                count;\n     int                removed;\n\n     DirectHashElement *Elements;\n\n     bool               disable_debugging_alloc;\n};\n\n/**********************************************************************************************************************/\n\n#define DIRECT_HASH_INIT(__size,__disable_debugging_alloc)              \\\n     {                                                                  \\\n          0x0b161321,                                                   \\\n          (__size < 17 ? 17 : __size),                                  \\\n          0,                                                            \\\n          0,                                                            \\\n          NULL,                                                         \\\n          __disable_debugging_alloc                                     \\\n     }\n\n#define DIRECT_HASH_ELEMENT_REMOVED ((void*) -1)\n\n#define DIRECT_HASH_ASSERT(hash)                                        \\\n     do {                                                               \\\n          D_MAGIC_ASSERT( hash, DirectHash );                           \\\n          D_ASSERT( (hash)->size > 0 );                                 \\\n          D_ASSERT( (hash)->Elements != NULL || (hash)->count == 0 );   \\\n          D_ASSERT( (hash)->Elements != NULL || (hash)->removed == 0 ); \\\n          D_ASSERT( (hash)->count + (hash)->removed < (hash)->size );   \\\n     } while (0)\n\ntypedef bool (*DirectHashIteratorFunc)( DirectHash *hash, unsigned long key, void *value, void *ctx );\n\n/**********************************************************************************************************************/\n\n/*\n * Full create including allocation ...\n */\nDirectResult DIRECT_API  direct_hash_create ( int                      size,\n                                              DirectHash             **ret_hash );\n\nvoid         DIRECT_API  direct_hash_destroy( DirectHash              *hash );\n\n/*\n * ... or just initialization of static data.\n */\nvoid         DIRECT_API  direct_hash_init   ( DirectHash              *hash,\n                                              int                      size );\n\nvoid         DIRECT_API  direct_hash_deinit ( DirectHash              *hash );\n\nint          DIRECT_API  direct_hash_count  ( DirectHash              *hash );\n\nDirectResult DIRECT_API  direct_hash_insert ( DirectHash              *hash,\n                                              unsigned long            key,\n                                              void                    *value );\n\nDirectResult DIRECT_API  direct_hash_remove ( DirectHash              *hash,\n                                               unsigned long            key );\n\nvoid         DIRECT_API *direct_hash_lookup ( const DirectHash        *hash,\n                                              unsigned long            key );\n\nvoid         DIRECT_API  direct_hash_iterate( DirectHash              *hash,\n                                              DirectHashIteratorFunc   func,\n                                              void                    *ctx );\n\n#endif\n"
  },
  {
    "path": "lib/direct/init.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/direct.h>\n#include <direct/direct_result.h>\n#include <direct/interface.h>\n#include <direct/log.h>\n#include <direct/result.h>\n#include <direct/thread.h>\n#include <direct/util.h>\n\n/**********************************************************************************************************************/\n\ntypedef void (*Func)( void );\n\nstatic Func init_funcs[] = {\n     __D_conf_init,\n     __D_direct_init,\n     __D_util_init,\n     __D_result_init,\n     __D_direct_result_init,\n     __D_mem_init,\n     __D_thread_init,\n     __D_log_init,\n     __D_log_domain_init,\n     __D_interface_init,\n     __D_interface_dbg_init,\n};\n\nstatic Func deinit_funcs[] = {\n     __D_interface_dbg_deinit,\n     __D_interface_deinit,\n     __D_log_domain_deinit,\n     __D_thread_deinit,\n     __D_mem_deinit,\n     __D_direct_result_deinit,\n     __D_result_deinit,\n     __D_util_deinit,\n     __D_direct_deinit,\n     __D_log_deinit,\n     __D_conf_deinit,\n};\n\n/**********************************************************************************************************************/\n\n__dfb_constructor__\nvoid\n__D_init_all( void )\n{\n     size_t i;\n\n     for (i = 0; i < D_ARRAY_SIZE(init_funcs); i++)\n          init_funcs[i]();\n}\n\n__dfb_destructor__\nvoid\n__D_deinit_all( void )\n{\n     size_t i;\n\n     for (i = 0; i < D_ARRAY_SIZE(deinit_funcs); i++)\n          deinit_funcs[i]();\n}\n"
  },
  {
    "path": "lib/direct/interface.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/filesystem.h>\n#include <direct/interface.h>\n#include <direct/list.h>\n#include <direct/mutex.h>\n#include <direct/util.h>\n\n#if DIRECT_BUILD_DEBUGS\n\n#include <direct/log.h>\n#include <direct/memcpy.h>\n#include <direct/trace.h>\n\n#endif /* DIRECT_BUILD_DEBUGS */\n\nD_DEBUG_DOMAIN( Direct_Interface, \"Direct/Interface\", \"Direct Interface\" );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     DirectLink            link;\n\n     int                   magic;\n\n     char                 *filename;\n     void                 *module_handle;\n\n     DirectInterfaceFuncs *funcs;\n\n     const char           *type;\n     const char           *implementation;\n\n     int                   references;\n} DirectInterfaceImplementation;\n\nstatic DirectMutex  implementations_mutex;\nstatic DirectLink  *implementations;\n\n#if DIRECT_BUILD_DEBUGS\ntypedef struct {\n     const void        *interface_ptr;\n     char              *name;\n     char              *what;\n\n     const char        *func;\n     const char        *file;\n     int                line;\n\n     DirectTraceBuffer *trace;\n} InterfaceDesc;\n\nstatic int            alloc_count;\nstatic int            alloc_capacity;\nstatic InterfaceDesc *alloc_list;\nstatic DirectMutex    alloc_lock;\n#endif /* DIRECT_BUILD_DEBUGS */\n\n/**********************************************************************************************************************/\n\nvoid\n__D_interface_init()\n{\n     direct_recursive_mutex_init( &implementations_mutex );\n}\n\nvoid\n__D_interface_deinit()\n{\n     direct_mutex_deinit( &implementations_mutex );\n}\n\n#if DIRECT_BUILD_DEBUGS\n\nvoid\n__D_interface_dbg_init()\n{\n     direct_mutex_init( &alloc_lock );\n}\n\nvoid\n__D_interface_dbg_deinit()\n{\n     direct_mutex_deinit( &alloc_lock );\n}\n\n#else /* DIRECT_BUILD_DEBUGS */\n\nvoid\n__D_interface_dbg_init()\n{\n}\n\nvoid\n__D_interface_dbg_deinit()\n{\n}\n\n#endif /* DIRECT_BUILD_DEBUGS */\n\n/**********************************************************************************************************************/\n\n__attribute__((noinline))\nvoid\nworkaround_func( void )\n{\n}\n\nstatic __inline__ int\nprobe_interface( DirectInterfaceImplementation  *impl,\n                 DirectInterfaceFuncs          **funcs,\n                 const char                     *type,\n                 const char                     *implementation,\n                 DirectInterfaceProbeFunc        probe,\n                 void                           *probe_ctx )\n{\n     if (type && strcmp( type, impl->type ))\n          return 0;\n\n     if (implementation && strcmp( implementation, impl->implementation ))\n          return 0;\n\n     D_DEBUG_AT( Direct_Interface, \"  -> probing '%s'...\\n\", impl->implementation );\n\n     if (probe && !probe( impl->funcs, probe_ctx ))\n          return 0;\n\n     *funcs = impl->funcs;\n     impl->references++;\n\n     return 1;\n}\n\n/**********************************************************************************************************************/\n\nvoid\nDirectRegisterInterface( DirectInterfaceFuncs *funcs )\n{\n     DirectInterfaceImplementation *impl;\n\n     D_DEBUG_AT( Direct_Interface, \"%s( %p )\\n\", __FUNCTION__, funcs );\n\n     impl = D_CALLOC( 1, sizeof(DirectInterfaceImplementation) );\n\n     D_DEBUG_AT( Direct_Interface, \"  -> %p\\n\", impl );\n\n     impl->funcs          = funcs;\n     impl->type           = funcs->GetType();\n     impl->implementation = funcs->GetImplementation();\n\n     D_MAGIC_SET( impl, DirectInterfaceImplementation );\n\n     D_DEBUG_AT( Direct_Interface, \"  -> %s | %s\\n\", impl->type, impl->implementation );\n\n     direct_mutex_lock( &implementations_mutex );\n     direct_list_prepend( &implementations, &impl->link );\n     direct_mutex_unlock( &implementations_mutex );\n}\n\nvoid\nDirectUnregisterInterface( DirectInterfaceFuncs *funcs )\n{\n     DirectInterfaceImplementation *impl;\n\n     D_DEBUG_AT( Direct_Interface, \"%s( %p )\\n\", __FUNCTION__, funcs );\n\n     direct_mutex_lock( &implementations_mutex );\n\n     direct_list_foreach (impl, implementations) {\n          D_MAGIC_ASSERT( impl, DirectInterfaceImplementation );\n\n          if (impl->funcs == funcs) {\n               D_FREE( impl->filename  );\n               direct_list_remove( &implementations, &impl->link );\n               break;\n          }\n     }\n\n     direct_mutex_unlock( &implementations_mutex );\n\n     if (!impl) {\n          D_BUG( \"implementation not found\" );\n          return;\n     }\n\n     D_DEBUG_AT( Direct_Interface, \"  -> %s | %s\\n\", impl->type, impl->implementation );\n\n     D_DEBUG_AT( Direct_Interface, \"  -> %p\\n\", impl );\n\n     D_MAGIC_CLEAR( impl );\n\n     D_FREE( impl );\n}\n\nDirectResult\nDirectProbeInterface( DirectInterfaceFuncs *funcs,\n                      void                 *ctx )\n{\n     return (funcs->Probe( ctx ) == DR_OK);\n}\n\nDirectResult\nDirectGetInterface( DirectInterfaceFuncs     **funcs,\n                    const char                *type,\n                    const char                *implementation,\n                    DirectInterfaceProbeFunc   probe,\n                    void                      *probe_ctx )\n{\n     int                            n   = 0;\n     int                            idx = -1;\n#if DIRECT_BUILD_DYNLOAD\n     DirectResult                   ret;\n     int                            len;\n     DirectDir                      dir;\n     char                          *interface_dir;\n     DirectEntry                    entry;\n     const char                    *path;\n#endif /* DIRECT_BUILD_DYNLOAD */\n     DirectInterfaceImplementation *impl;\n\n     D_DEBUG_AT( Direct_Interface, \"%s( %p, '%s', '%s', %p, %p )\\n\", __FUNCTION__,\n                 funcs, type, implementation, probe, probe_ctx );\n\n     direct_mutex_lock( &implementations_mutex );\n\n     /* Check whether there is a default existing implementation set for the type in config. */\n     if (type && !implementation && direct_config->default_interface_implementation_types) {\n          while (direct_config->default_interface_implementation_types[n]) {\n               idx = -1;\n\n               while (direct_config->default_interface_implementation_types[n]) {\n                    if (!strcmp( direct_config->default_interface_implementation_types[n++], type )) {\n                         idx = n - 1;\n                         break;\n                    }\n               }\n\n               if (idx < 0 && !direct_config->default_interface_implementation_types[n])\n                    break;\n\n               /* Check whether we have to check for a default implementation for the selected type. */\n               if (idx >= 0) {\n                    direct_list_foreach (impl, implementations) {\n                         if (probe_interface( impl, funcs, NULL,\n                                              direct_config->default_interface_implementation_names[idx],\n                                              probe, probe_ctx )) {\n                              D_INFO( \"Direct/Interface: Using '%s' cached default implementation of '%s'\\n\",\n                                      impl->implementation, impl->type );\n\n                              direct_mutex_unlock( &implementations_mutex );\n\n                              return DR_OK;\n                         }\n                    }\n               }\n               else\n                    break;\n          }\n\n          /* Check existing implementations without default. */\n          direct_list_foreach (impl, implementations) {\n               if (probe_interface( impl, funcs, type, implementation, probe, probe_ctx )) {\n                    if (impl->references == 1) {\n                         D_INFO( \"Direct/Interface: Using '%s' implementation of '%s'\\n\",\n                                 impl->implementation, impl->type );\n                    }\n\n                    direct_mutex_unlock( &implementations_mutex );\n\n                    return DR_OK;\n               }\n          }\n     }\n     else {\n          /* Check existing implementations without default. */\n          direct_list_foreach (impl, implementations) {\n               if (probe_interface( impl, funcs, type, implementation, probe, probe_ctx )) {\n                    if (impl->references == 1) {\n                         D_INFO( \"Direct/Interface: Using '%s' implementation of '%s'\\n\",\n                                 impl->implementation, impl->type );\n                    }\n\n                    direct_mutex_unlock( &implementations_mutex );\n\n                    return DR_OK;\n               }\n          }\n     }\n\n#if DIRECT_BUILD_DYNLOAD\n     /* Try to load it dynamically. */\n\n     /* NULL type means we can't find plugin, so stop immediately. */\n     if (type == NULL) {\n          direct_mutex_unlock( &implementations_mutex );\n          return DR_NOIMPL;\n     }\n\n     path = direct_config->module_dir;\n     if (!path)\n          path = MODULEDIR;\n\n     len = strlen( path ) + strlen( \"/interfaces/\" ) + strlen( type ) + 1;\n     interface_dir = alloca( len );\n     snprintf( interface_dir, len, \"%s%sinterfaces/%s\", path, path[strlen( path )-1] == '/' ? \"\" : \"/\", type );\n\n     ret = direct_dir_open( &dir, interface_dir );\n     if (ret) {\n          D_DERROR( ret, \"Direct/Interface: Could not open interface directory '%s'!\\n\", interface_dir );\n          direct_mutex_unlock( &implementations_mutex );\n          return ret;\n     }\n\n     if (direct_config->default_interface_implementation_types) {\n          n = 0;\n\n          while (direct_config->default_interface_implementation_types[n]) {\n               idx = -1;\n\n               while (direct_config->default_interface_implementation_types[n]) {\n                    if (!strcmp( direct_config->default_interface_implementation_types[n++], type )) {\n                         idx = n - 1;\n                         break;\n                    }\n               }\n\n               if (idx < 0 && !direct_config->default_interface_implementation_types[n])\n                    break;\n\n               /* Iterate directory. */\n               while (idx >= 0 && direct_dir_read( &dir, &entry ) == DR_OK) {\n                    char  buf[PATH_MAX];\n                    int   entry_len = strlen( entry.name );\n                    void *handle    = NULL;\n\n                    DirectInterfaceImplementation *old_impl = (DirectInterfaceImplementation*) implementations;\n                    DirectInterfaceImplementation *test_impl;\n\n                    if (entry_len < 4                  ||\n                        entry.name[entry_len-2] != 's' ||\n                        entry.name[entry_len-1] != 'o')\n                         continue;\n\n                    snprintf( buf, sizeof(buf), \"%s/%s\", interface_dir, entry.name );\n\n                    /* Check if it got already loaded. */\n                    direct_list_foreach (test_impl, implementations) {\n                         if (test_impl->filename && !strcmp( test_impl->filename, buf )) {\n                              impl = test_impl;\n                              handle = impl->module_handle;\n                              break;\n                         }\n                    }\n\n                    workaround_func();\n\n                    /* Open it if needed and check. */\n                    if (!handle) {\n                         handle = dlopen( buf, RTLD_NOW );\n\n                         /* Check if it registered itself. */\n                         if (handle) {\n                              impl = (DirectInterfaceImplementation*) implementations;\n\n                              if (old_impl == impl) {\n                                   dlclose( handle );\n                                   continue;\n                              }\n\n                              /* Keep filename and module handle. */\n                              impl->filename      = D_STRDUP( buf );\n                              impl->module_handle = handle;\n                         }\n                    }\n\n                    if (handle) {\n                         /* Check whether the dlopen'ed interface supports the required implementation. */\n                         if (!strcasecmp( impl->implementation,\n                                          direct_config->default_interface_implementation_names[idx] )) {\n                              if (probe_interface( impl, funcs, type, impl->implementation, probe, probe_ctx )) {\n                                   if (impl->references == 1)\n                                        D_INFO( \"Direct/Interface: Loaded '%s' implementation of '%s'\\n\",\n                                                impl->implementation, impl->type );\n\n                                   direct_dir_close( &dir );\n\n                                   direct_mutex_unlock( &implementations_mutex );\n\n                                   return DR_OK;\n                              }\n                              else\n                                   continue;\n                         }\n                         else\n                              continue;\n                    }\n                    else\n                         D_DLERROR( \"Direct/Interface: Unable to dlopen '%s'!\\n\", buf );\n               }\n\n               direct_dir_rewind( &dir );\n          }\n     }\n\n     /* Iterate directory. */\n     while (direct_dir_read( &dir, &entry ) == DR_OK) {\n          char  buf[PATH_MAX];\n          int   entry_len = strlen( entry.name );\n          void *handle    = NULL;\n\n          DirectInterfaceImplementation *old_impl = (DirectInterfaceImplementation*) implementations;\n          DirectInterfaceImplementation *test_impl;\n\n          if (entry_len < 4                  ||\n              entry.name[entry_len-2] != 's' ||\n              entry.name[entry_len-1] != 'o')\n               continue;\n\n          snprintf( buf, sizeof(buf), \"%s/%s\", interface_dir, entry.name );\n\n          /* Check if it got already loaded. */\n          direct_list_foreach (test_impl, implementations) {\n               if (test_impl->filename && !strcmp( test_impl->filename, buf )) {\n                   impl = test_impl;\n                   handle = impl->module_handle;\n                   break;\n               }\n          }\n\n          workaround_func();\n\n          /* Open it if needed and check. */\n          if (!handle) {\n               handle = dlopen( buf, RTLD_NOW );\n\n               /* Check if it registered itself. */\n               if (handle) {\n                    impl = (DirectInterfaceImplementation*) implementations;\n\n                    if (old_impl == impl) {\n                         dlclose( handle );\n                         continue;\n                    }\n\n                    /* Keep filename and module handle. */\n                    impl->filename      = D_STRDUP( buf );\n                    impl->module_handle = handle;\n               }\n          }\n\n          if (handle) {\n               if (probe_interface( impl, funcs, type, implementation, probe, probe_ctx )) {\n                    if (impl->references == 1)\n                         D_INFO( \"Direct/Interface: Loaded '%s' implementation of '%s'\\n\",\n                                 impl->implementation, impl->type );\n\n                    direct_dir_close( &dir );\n\n                    direct_mutex_unlock( &implementations_mutex );\n\n                    return DR_OK;\n               }\n               else\n                    continue;\n          }\n          else\n               D_DLERROR( \"Direct/Interface: Unable to dlopen '%s'!\\n\", buf );\n     }\n\n     direct_dir_close( &dir );\n#endif /* DIRECT_BUILD_DYNLOAD */\n\n     direct_mutex_unlock( &implementations_mutex );\n\n     return DR_NOIMPL;\n}\n\n/**********************************************************************************************************************/\n\n#if DIRECT_BUILD_DEBUGS\n\nvoid\ndirect_print_interface_leaks()\n{\n     int i;\n\n     direct_mutex_lock( &alloc_lock );\n\n     if (alloc_count) {\n          direct_log_printf( NULL, \"Interface instances remaining (%d): \\n\", alloc_count );\n\n          for (i = 0; i < alloc_count; i++) {\n               InterfaceDesc *desc = &alloc_list[i];\n\n               direct_log_printf( NULL, \"  - '%s' at %p (%s) allocated in %s (%s: %d)\\n\",\n                                  desc->name, desc->interface_ptr, desc->what, desc->func, desc->file, desc->line );\n\n               if (desc->trace)\n                    direct_trace_print_stack( desc->trace );\n          }\n     }\n\n     direct_mutex_unlock( &alloc_lock );\n}\n\n__dfb_no_instrument_function__\nstatic InterfaceDesc *\nallocate_interface_desc( void )\n{\n     int cap = alloc_capacity;\n\n     if (!cap)\n          cap = 64;\n     else if (cap == alloc_count)\n          cap <<= 1;\n\n     if (cap != alloc_capacity) {\n          alloc_capacity = cap;\n          alloc_list     = D_REALLOC( alloc_list, sizeof(InterfaceDesc) * cap );\n\n          D_ASSERT( alloc_list != NULL );\n     }\n\n     return &alloc_list[alloc_count++];\n}\n\n__dfb_no_instrument_function__\nstatic __inline__ void\nfill_interface_desc( InterfaceDesc     *desc,\n                     const void        *interface_ptr,\n                     const char        *name,\n                     const char        *func,\n                     const char        *file,\n                     int                line,\n                     const char        *what,\n                     DirectTraceBuffer *trace )\n{\n     desc->interface_ptr = interface_ptr;\n     desc->name          = D_STRDUP( name );\n     desc->what          = D_STRDUP( what );\n     desc->func          = func;\n     desc->file          = file;\n     desc->line          = line;\n     desc->trace         = trace;\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_dbg_interface_add( const char *func,\n                          const char *file,\n                          int         line,\n                          const char *what,\n                          const void *interface_ptr,\n                          const char *name )\n{\n     InterfaceDesc *desc;\n\n     direct_mutex_lock( &alloc_lock );\n\n     desc = allocate_interface_desc();\n\n     fill_interface_desc( desc, interface_ptr, name, func, file, line, what, direct_trace_copy_buffer( NULL ) );\n\n     direct_mutex_unlock( &alloc_lock );\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_dbg_interface_remove( const char *func,\n                             const char *file,\n                             int         line,\n                             const char *what,\n                             const void *interface_ptr )\n{\n     int i;\n\n     direct_mutex_lock( &alloc_lock );\n\n     for (i = 0; i < alloc_count; i++) {\n          InterfaceDesc *desc = &alloc_list[i];\n\n          if (desc->interface_ptr == interface_ptr) {\n               if (desc->trace)\n                    direct_trace_free_buffer( desc->trace );\n\n               D_FREE( desc->what );\n               D_FREE( desc->name );\n\n               if (i < --alloc_count)\n                    direct_memmove( desc, desc + 1, (alloc_count - i) * sizeof(InterfaceDesc) );\n\n               direct_mutex_unlock( &alloc_lock );\n\n               return;\n          }\n     }\n\n     direct_mutex_unlock( &alloc_lock );\n\n     D_ERROR( \"Direct/Interface: Unknown instance %p (%s) from [%s:%d in %s()]!\\n\",\n              interface_ptr, what, file, line, func );\n}\n\n#else /* DIRECT_BUILD_DEBUGS */\n\nvoid\ndirect_print_interface_leaks()\n{\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_dbg_interface_add( const char *func,\n                          const char *file,\n                          int         line,\n                          const char *what,\n                          const void *interface_ptr,\n                          const char *name )\n{\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_dbg_interface_remove( const char *func,\n                             const char *file,\n                             int         line,\n                             const char *what,\n                             const void *interface_ptr )\n{\n}\n\n#endif /* DIRECT_BUILD_DEBUGS */\n"
  },
  {
    "path": "lib/direct/interface.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__INTERFACE_H__\n#define __DIRECT__INTERFACE_H__\n\n#include <direct/debug.h>\n#include <direct/mem.h>\n#include <direct/messages.h>\n\n/**********************************************************************************************************************/\n\n/*\n * Forward declaration macro for interfaces.\n */\n#define D_DECLARE_INTERFACE(IFACE)                \\\n     typedef struct _##IFACE IFACE;\n\n/*\n * Macro for an interface definition.\n */\n#define D_DEFINE_INTERFACE(IFACE,...)             \\\n     struct _##IFACE {                            \\\n          void          *priv;                    \\\n          int            magic;                   \\\n          int            refs;                    \\\n                                                  \\\n          DirectResult (*AddRef) ( IFACE *thiz ); \\\n          DirectResult (*Release)( IFACE *thiz ); \\\n                                                  \\\n          __VA_ARGS__                             \\\n     };\n\n/*\n * Declare base interface.\n */\nD_DECLARE_INTERFACE( IAny )\n\n/*\n * Define base interface.\n */\nD_DEFINE_INTERFACE( IAny )\n\n/*\n * Function type for probing of interface implementations.\n */\ntypedef DirectResult (*DirectInterfaceGenericProbeFunc)    ( void *ctx, ... );\n\n/*\n * Function type for initialization of interface instances.\n */\ntypedef DirectResult (*DirectInterfaceGenericConstructFunc)( void *interface_ptr, ... );\n\n/*\n * Function table for interface implementations.\n */\ntypedef struct {\n     const char                          *(*GetType)          ( void );\n     const char                          *(*GetImplementation)( void );\n     DirectResult                         (*Allocate)         ( void **interface_ptr );\n     DirectResult                         (*Deallocate)       ( void *interface_ptr );\n\n     DirectInterfaceGenericProbeFunc        Probe;\n     DirectInterfaceGenericConstructFunc    Construct;\n} DirectInterfaceFuncs;\n\n/*\n * Callback type for user probing interface implementations\n */\ntypedef DirectResult (*DirectInterfaceProbeFunc)( DirectInterfaceFuncs *impl, void *ctx );\n\n/**********************************************************************************************************************/\n\n/*\n * Called by implementation modules during 'dlopen'ing or at startup if linked into the executable.\n */\nvoid         DIRECT_API DirectRegisterInterface     ( DirectInterfaceFuncs      *funcs );\n\n/*\n * Called at the executable termination.\n */\nvoid         DIRECT_API DirectUnregisterInterface   ( DirectInterfaceFuncs      *funcs );\n\n/*\n * Default probe function. Calls \"funcs->Probe(ctx)\".\n * Can be used as the 'probe' argument to DirectGetInterface.\n * 'probe_ctx' should then be set to the interface specific probe context.\n */\nDirectResult DIRECT_API DirectProbeInterface        ( DirectInterfaceFuncs      *funcs,\n                                                      void                      *ctx );\n\n/*\n * Loads an interface of a specific 'type'.\n * Optionally an 'implementation' can be chosen.\n * A 'probe' function can be used to check available implementations.\n * After success 'funcs' is set.\n */\nDirectResult DIRECT_API DirectGetInterface          ( DirectInterfaceFuncs     **funcs,\n                                                      const char                *type,\n                                                      const char                *implementation,\n                                                      DirectInterfaceProbeFunc   probe,\n                                                      void                      *probe_ctx );\n\nvoid         DIRECT_API direct_print_interface_leaks( void );\n\nvoid         DIRECT_API direct_dbg_interface_add    ( const char                *func,\n                                                      const char                *file,\n                                                      int                        line,\n                                                      const char                *what,\n                                                      const void                *interface_ptr,\n                                                      const char                *name );\n\nvoid         DIRECT_API direct_dbg_interface_remove ( const char                *func,\n                                                      const char                *file,\n                                                      int                        line,\n                                                      const char                *what,\n                                                      const void                *interface_ptr );\n\n/**********************************************************************************************************************/\n\n#if DIRECT_BUILD_DEBUG || defined(DIRECT_ENABLE_DEBUG)\n\n#define DIRECT_DBG_INTERFACE_ADD                                     direct_dbg_interface_add\n#define DIRECT_DBG_INTERFACE_REMOVE                                  direct_dbg_interface_remove\n\n#else /* DIRECT_BUILD_DEBUG || defined(DIRECT_ENABLE_DEBUG) */\n\n#define DIRECT_DBG_INTERFACE_ADD(func,file,line,what,interface,name) do {} while (0)\n#define DIRECT_DBG_INTERFACE_REMOVE(func,file,line,what,interface)   do {} while (0)\n\n#endif /* DIRECT_BUILD_DEBUG || defined(DIRECT_ENABLE_DEBUG) */\n\n#define DIRECT_ALLOCATE_INTERFACE(p,i)                                                  \\\n     do {                                                                               \\\n          (p) = (__typeof__(p)) D_CALLOC( 1, sizeof(i) );                               \\\n          if (p) {                                                                      \\\n               D_MAGIC_SET( (IAny*) (p), DirectInterface );                             \\\n                                                                                        \\\n               DIRECT_DBG_INTERFACE_ADD( __FUNCTION__, __FILE__, __LINE__, #p, p, #i ); \\\n          }                                                                             \\\n          else                                                                          \\\n               D_OOM();                                                                 \\\n     } while (0)\n\n#define DIRECT_ALLOCATE_INTERFACE_DATA(p,i)                                             \\\n     i##_data *data;                                                                    \\\n                                                                                        \\\n     D_MAGIC_ASSERT( (IAny*) (p), DirectInterface );                                    \\\n                                                                                        \\\n     if (!(p)->priv)                                                                    \\\n          (p)->priv = D_CALLOC( 1, sizeof(i##_data) );                                  \\\n                                                                                        \\\n     data = (i##_data*) ((p)->priv);\n\n#define DIRECT_DEALLOCATE_INTERFACE(p)                                                  \\\n     D_MAGIC_ASSERT( (IAny*) (p), DirectInterface );                                    \\\n                                                                                        \\\n     DIRECT_DBG_INTERFACE_REMOVE( __FUNCTION__, __FILE__, __LINE__, #p, p );            \\\n                                                                                        \\\n     if ((p)->priv) {                                                                   \\\n          D_FREE( (p)->priv );                                                          \\\n          (p)->priv = NULL;                                                             \\\n     }                                                                                  \\\n                                                                                        \\\n     D_MAGIC_CLEAR( (IAny*) (p) );                                                      \\\n                                                                                        \\\n     D_FREE( (p) );\n\n#define DIRECT_INTERFACE_GET_DATA(i)                                                    \\\n     i##_data *data;                                                                    \\\n                                                                                        \\\n     if (!thiz)                                                                         \\\n          return DR_THIZNULL;                                                           \\\n                                                                                        \\\n     D_MAGIC_ASSERT( (IAny*) thiz, DirectInterface );                                   \\\n                                                                                        \\\n     data = (i##_data*) thiz->priv;                                                     \\\n                                                                                        \\\n     if (!data)                                                                         \\\n          return DR_DEAD;\n\n/**********************************************************************************************************************/\n\nvoid __D_interface_init      ( void );\nvoid __D_interface_deinit    ( void );\n\nvoid __D_interface_dbg_init  ( void );\nvoid __D_interface_dbg_deinit( void );\n\n#endif\n"
  },
  {
    "path": "lib/direct/interface_implementation.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__INTERFACE_IMPLEMENTATION_H__\n#define __DIRECT__INTERFACE_IMPLEMENTATION_H__\n\n#include <direct/interface.h>\n\n/**********************************************************************************************************************/\n\nstatic const char   *GetType          ( void );\nstatic const char   *GetImplementation( void );\nstatic DirectResult  Allocate         ( void **ret_interface );\nstatic DirectResult  Deallocate       ( void  *interface_ptr );\n\nstatic DirectInterfaceFuncs interface_funcs = {\n     GetType,\n     GetImplementation,\n     Allocate,\n     Deallocate,\n     (void*) Probe,\n     (void*) Construct\n};\n\n#define DIRECT_INTERFACE_IMPLEMENTATION(type,impl)           \\\n                                                             \\\nstatic const char *                                          \\\nGetType()                                                    \\\n{                                                            \\\n     return #type;                                           \\\n}                                                            \\\n                                                             \\\nstatic const char *                                          \\\nGetImplementation()                                          \\\n{                                                            \\\n     return #impl;                                           \\\n}                                                            \\\n                                                             \\\nstatic DirectResult                                          \\\nAllocate( void **ret_interface )                             \\\n{                                                            \\\n     DIRECT_ALLOCATE_INTERFACE( *ret_interface, type );      \\\n     return DR_OK;                                           \\\n}                                                            \\\n                                                             \\\nstatic DirectResult                                          \\\nDeallocate( void *interface_ptr )                            \\\n{                                                            \\\n     DIRECT_DEALLOCATE_INTERFACE( (IAny*) (interface_ptr) ); \\\n     return DR_OK;                                           \\\n}                                                            \\\n                                                             \\\n__dfb_constructor__                                          \\\nvoid                                                         \\\ntype##_##impl##_ctor( void )                                 \\\n{                                                            \\\n     DirectRegisterInterface( &interface_funcs );            \\\n}                                                            \\\n                                                             \\\n__dfb_destructor__                                           \\\nvoid                                                         \\\ntype##_##impl##_dtor( void )                                 \\\n{                                                            \\\n     DirectUnregisterInterface( &interface_funcs );          \\\n}\n\n#endif\n"
  },
  {
    "path": "lib/direct/list.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__LIST_H__\n#define __DIRECT__LIST_H__\n\n#include <direct/debug.h>\n\n/**********************************************************************************************************************/\n\nstruct __D_DirectLink {\n     int         magic;\n\n     DirectLink *next;\n     DirectLink *prev; /* The prev pointer of the first element always points\n                          to the last element of the list, for fast appending. */\n};\n\n/**********************************************************************************************************************/\n\nstatic __inline__ void\ndirect_list_prepend( DirectLink **list,\n                     DirectLink  *link )\n{\n     DirectLink *first;\n\n     D_ASSERT( list != NULL );\n     D_ASSERT( link != NULL );\n\n     first = *list;\n\n     link->next = first;\n\n     if (first) {\n          D_MAGIC_ASSERT( first, DirectLink );\n\n          link->prev = first->prev;\n\n          first->prev = link;\n     }\n     else\n          link->prev = link;\n\n     *list = link;\n\n     D_MAGIC_SET( link, DirectLink );\n}\n\nstatic __inline__ void\ndirect_list_append( DirectLink **list,\n                    DirectLink  *link )\n{\n     DirectLink *first;\n\n     D_ASSERT( list != NULL );\n     D_ASSERT( link != NULL );\n\n     first = *list;\n\n     link->next = NULL;\n\n     if (first) {\n          DirectLink *last = first->prev;\n\n          D_MAGIC_ASSERT( first, DirectLink );\n          D_MAGIC_ASSERT( last, DirectLink );\n\n          link->prev = last;\n\n          last->next = first->prev = link;\n     }\n     else\n          *list = link->prev = link;\n\n     D_MAGIC_SET( link, DirectLink );\n}\n\nstatic __inline__ void\ndirect_list_insert( DirectLink **list,\n                    DirectLink  *link,\n                    DirectLink  *before )\n{\n     DirectLink *first;\n\n     D_ASSERT( list != NULL );\n     D_ASSERT( link != NULL );\n\n     first = *list;\n\n     D_MAGIC_ASSERT_IF( first, DirectLink );\n     D_MAGIC_ASSERT_IF( before, DirectLink );\n\n     if (first == before) {\n          direct_list_prepend( list, link );\n     }\n     else if (first == NULL || before == NULL) {\n          direct_list_append( list, link );\n     }\n     else {\n          DirectLink *prev = before->prev;\n\n          D_MAGIC_ASSERT( prev, DirectLink );\n\n          prev->next   = link;\n\n          link->prev   = prev;\n          link->next   = before;\n\n          before->prev = link;\n\n          D_MAGIC_SET( link, DirectLink );\n     }\n}\n\nstatic __inline__ bool\ndirect_list_contains_element_EXPENSIVE( DirectLink *list,\n                                        DirectLink *link )\n{\n     D_MAGIC_ASSERT_IF( list, DirectLink );\n\n     while (list) {\n          if (list == link)\n               return true;\n\n          list = list->next;\n     }\n\n     return false;\n}\n\nstatic __inline__ int\ndirect_list_count_elements_EXPENSIVE( DirectLink *list )\n{\n     int count = 0;\n\n     while (list) {\n          D_MAGIC_ASSERT( list, DirectLink );\n\n          count++;\n\n          list = list->next;\n     }\n\n     return count;\n}\n\n#if defined(__GNUC__) && __GNUC__ >= 10\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wanalyzer-null-dereference\"\n#endif\nstatic __inline__ bool\ndirect_list_remove( DirectLink **list,\n                    DirectLink  *link )\n{\n     DirectLink *next;\n     DirectLink *prev;\n\n     D_ASSERT( list != NULL );\n\n     D_ASSERT( direct_list_contains_element_EXPENSIVE( *list, link ) );\n\n     D_MAGIC_ASSERT( *list, DirectLink );\n     D_MAGIC_ASSERT( link, DirectLink );\n\n     next = link->next;\n     prev = link->prev;\n\n     if (next) {\n          D_MAGIC_ASSERT( next, DirectLink );\n\n          next->prev = prev;\n     }\n     else\n         (*list)->prev = prev;\n\n     if (link == *list)\n          *list = next;\n     else {\n          D_MAGIC_ASSERT( prev, DirectLink );\n\n          prev->next = next;\n     }\n\n     link->next = link->prev = NULL;\n\n     D_MAGIC_CLEAR( link );\n\n     return true;\n}\n\nstatic __inline__ void\ndirect_list_move_to_front( DirectLink **list,\n                           DirectLink  *link )\n{\n     DirectLink *next;\n     DirectLink *prev;\n     DirectLink *first;\n\n     D_ASSERT( list != NULL );\n\n     first = *list;\n\n     D_ASSERT( direct_list_contains_element_EXPENSIVE( first, link ) );\n\n     D_MAGIC_ASSERT( first, DirectLink );\n     D_MAGIC_ASSERT( link, DirectLink );\n\n     if (first == link)\n          return;\n\n     next = link->next;\n     prev = link->prev;\n\n     D_MAGIC_ASSERT_IF( next, DirectLink );\n     D_MAGIC_ASSERT( prev, DirectLink );\n\n     if (next) {\n          next->prev = prev;\n\n          link->prev = first->prev;\n     }\n     else\n          link->prev = prev;\n\n     prev->next = next;\n\n     link->next = first;\n\n     first->prev = link;\n\n     *list = link;\n}\n\nstatic __inline__ void *\ndirect_list_get_last( DirectLink *list )\n{\n     D_MAGIC_ASSERT_IF( list, DirectLink );\n\n     if (list) {\n          D_MAGIC_ASSERT( list->prev, DirectLink );\n\n          return list->prev;\n     }\n\n     return NULL;\n}\n\nstatic __inline__ void *\ndirect_list_get_next( DirectLink *list )\n{\n     D_MAGIC_ASSERT_IF( list, DirectLink );\n\n     if (list) {\n          D_MAGIC_ASSERT( list->prev, DirectLink );\n\n          return list->next;\n     }\n\n     return NULL;\n}\n#if defined __GNUC__ && __GNUC__ >= 10\n#pragma GCC diagnostic pop\n#endif\n\n/**********************************************************************************************************************/\n\n#define direct_list_check_link(link)                                                \\\n     ({                                                                             \\\n          D_MAGIC_ASSERT_IF( link, DirectLink );                                    \\\n          link != NULL;                                                             \\\n     })\n\n#define direct_list_foreach(elem,list)                                              \\\n     for (elem = (__typeof__(elem)) (list);                                         \\\n          direct_list_check_link( (DirectLink*) (elem) );                           \\\n          elem = (__typeof__(elem)) (((DirectLink*) (elem))->next))\n\n#define direct_list_foreach_safe(elem,temp,list)                                    \\\n     for (elem = (__typeof__(elem)) (list),                                         \\\n          temp = ((__typeof__(temp)) direct_list_get_next( (DirectLink*) (elem) )); \\\n          direct_list_check_link( (DirectLink*) (elem) );                           \\\n          elem = (__typeof__(elem)) (temp),                                         \\\n          temp = ((__typeof__(temp)) direct_list_get_next( (DirectLink*) (elem) )))\n\n#endif\n"
  },
  {
    "path": "lib/direct/log.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/debug.h>\n#include <direct/log.h>\n#include <direct/mem.h>\n#include <direct/messages.h>\n#include <direct/thread.h>\n\n/**********************************************************************************************************************/\n\nstatic DirectLog  fallback_log;\nstatic DirectLog *default_log;\n\n/**********************************************************************************************************************/\n\nvoid\n__D_log_init()\n{\n     DirectLog *fb = &fallback_log;\n\n     fb->type = DLT_STDERR;\n\n     direct_recursive_mutex_init( &fb->lock );\n\n     direct_log_init( fb, NULL );\n\n     D_MAGIC_SET( fb, DirectLog );\n}\n\nvoid\n__D_log_deinit()\n{\n     DirectLog *fb = &fallback_log;\n\n     direct_log_deinit( fb );\n\n     direct_mutex_deinit( &fb->lock );\n\n     D_MAGIC_CLEAR( fb );\n\n     default_log = NULL;\n}\n\n/**********************************************************************************************************************/\n\nDirectResult\ndirect_log_create( DirectLogType   type,\n                   const char     *param,\n                   DirectLog     **ret_log )\n{\n     DirectResult  ret;\n     DirectLog    *log;\n\n     log = direct_calloc( 1, sizeof(DirectLog) );\n     if (!log)\n          return D_OOM();\n\n     log->type = type;\n\n     direct_recursive_mutex_init( &log->lock );\n\n     ret = direct_log_init( log, param );\n     if (ret) {\n          direct_mutex_deinit( &log->lock );\n          direct_free( log );\n          return ret;\n     }\n\n     D_ASSERT( log->write != NULL );\n\n     D_MAGIC_SET( log, DirectLog );\n\n     *ret_log = log;\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_log_destroy( DirectLog *log )\n{\n     D_MAGIC_ASSERT( log, DirectLog );\n\n     D_ASSERT( &fallback_log != log );\n\n     if (log == default_log)\n          default_log = NULL;\n\n     direct_log_deinit( log );\n\n     direct_mutex_deinit( &log->lock );\n\n     D_MAGIC_CLEAR( log );\n\n     direct_free( log );\n\n     return DR_OK;\n}\n\n__dfb_no_instrument_function__\nDirectResult\ndirect_log_printf( DirectLog  *log,\n                   const char *format, ... )\n{\n     DirectResult  ret = 0;\n     va_list       args;\n     int           len;\n     char          buf[2000];\n     char         *ptr = buf;\n\n     /* Don't use D_MAGIC_ASSERT or any other macros/functions that might cause an endless loop. */\n\n     /* Use the default log if passed log is invalid. */\n     if (!D_MAGIC_CHECK( log, DirectLog ))\n          log = direct_log_default();\n\n     if (!D_MAGIC_CHECK( log, DirectLog ))\n          return DR_BUG;\n\n     va_start( args, format );\n     len = vsnprintf( buf, sizeof(buf), format, args );\n     va_end( args );\n\n     if (len < 0)\n          return DR_FAILURE;\n\n     if (len >= sizeof(buf)) {\n          ptr = direct_malloc( len + 1 );\n          if (!ptr)\n               return DR_NOLOCALMEMORY;\n\n          va_start( args, format );\n          len = vsnprintf( ptr, len + 1, format, args );\n          va_end( args );\n\n          if (len < 0) {\n               direct_free( ptr );\n               return DR_FAILURE;\n          }\n     }\n\n     ret = log->write( log, ptr, len );\n\n     if (ptr != buf)\n          direct_free( ptr );\n\n     direct_log_debug_delay( true );\n\n     return ret;\n}\n\nDirectResult\ndirect_log_set_default( DirectLog *log )\n{\n     D_MAGIC_ASSERT_IF( log, DirectLog );\n\n     default_log = log;\n\n     return DR_OK;\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_log_lock( DirectLog *log )\n{\n     D_MAGIC_ASSERT( log, DirectLog );\n\n     direct_mutex_lock( &log->lock );\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_log_unlock( DirectLog *log )\n{\n     D_MAGIC_ASSERT( log, DirectLog );\n\n     direct_mutex_unlock( &log->lock );\n}\n\nDirectResult\ndirect_log_flush( DirectLog *log )\n{\n     /* Don't use D_MAGIC_ASSERT or any other macros/functions that might cause an endless loop. */\n\n     /* Use the default log if passed log is invalid. */\n     if (!D_MAGIC_CHECK( log, DirectLog ))\n          log = direct_log_default();\n\n     if (!D_MAGIC_CHECK( log, DirectLog ))\n          return DR_BUG;\n\n     if (!log->flush)\n          return DR_UNSUPPORTED;\n\n     return log->flush( log );\n}\n\n__dfb_no_instrument_function__\nDirectLog *\ndirect_log_default()\n{\n     return default_log ?: &fallback_log;\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_log_debug_delay( bool min )\n{\n     unsigned int us = min ? direct_config->log_delay_min_us : 0;\n\n     if (direct_config->log_delay_rand_us) {\n          unsigned int r = rand() % direct_config->log_delay_rand_us;\n\n          if (us < r)\n               us = r;\n     }\n\n     if (us)\n          direct_thread_sleep( us );\n\n\n     unsigned int loops = min ? direct_config->log_delay_min_loops : 0;\n\n     if (direct_config->log_delay_rand_loops) {\n          unsigned int r = rand() % direct_config->log_delay_rand_loops;\n\n          if (loops < r)\n               loops = r;\n     }\n\n     if (loops) {\n          volatile long val = 0;\n          unsigned int  loop;\n\n          for (loop = 0; loop < loops; loop++)\n               val++;\n     }\n}\n"
  },
  {
    "path": "lib/direct/log.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__LOG_H__\n#define __DIRECT__LOG_H__\n\n#include <direct/compiler.h>\n#include <direct/os/log.h>\n\n/**********************************************************************************************************************/\n\n/*\n * Creates a logging facility.\n *\n * For each 'type' the 'param' has a different meaning:\n *   DLT_STDERR     ignored (leave NULL)\n *   DLT_FILE       file name\n *   DLT_UDP        <ip>:<port>\n */\nDirectResult DIRECT_API  direct_log_create     ( DirectLogType   type,\n                                                 const char     *param,\n                                                 DirectLog     **ret_log );\n\n/*\n * Destroys a logging facility.\n */\nDirectResult DIRECT_API  direct_log_destroy    ( DirectLog      *log );\n\n/*\n * Write to the log in a printf fashion.\n *\n * If log is NULL, the default log is used if it's valid, otherwise stderr is used as a fallback until now.\n */\nDirectResult DIRECT_API  direct_log_printf     ( DirectLog      *log,\n                                                 const char     *format, ... ) D_FORMAT_PRINTF(2);\n\n/*\n * Set the default log that is used when no valid log is passed.\n */\nDirectResult DIRECT_API  direct_log_set_default( DirectLog      *log );\n\n/*\n * Locks a logging facility for non-intermixed output of multiple calls in multiple threads.\n */\nvoid         DIRECT_API  direct_log_lock       ( DirectLog      *log );\n\n/*\n * Unlocks a logging facility.\n */\nvoid         DIRECT_API  direct_log_unlock     ( DirectLog      *log );\n\n/*\n * Flush the log data.\n */\nDirectResult DIRECT_API  direct_log_flush      ( DirectLog      *log );\n\n/*\n * Returns the default log.\n */\nDirectLog    DIRECT_API *direct_log_default    ( void );\n\n/*\n * Enable delay between log messages.\n */\nvoid         DIRECT_API  direct_log_debug_delay( bool            min );\n\n/**********************************************************************************************************************/\n\nvoid __D_log_init  ( void );\nvoid __D_log_deinit( void );\n\n#endif\n"
  },
  {
    "path": "lib/direct/log_domain.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/log_domain.h>\n\n#if DIRECT_BUILD_TEXT\n#include <direct/list.h>\n#include <direct/log.h>\n#include <direct/mem.h>\n#include <direct/messages.h>\n#include <direct/system.h>\n#include <direct/thread.h>\n#include <direct/trace.h>\n#endif /* DIRECT_BUILD_TEXT */\n\n/**********************************************************************************************************************/\n\n#if DIRECT_BUILD_TEXT\n\ntypedef struct {\n     DirectLink             link;\n\n     char                  *name;\n     DirectLogDomainConfig  config;\n} LogDomainEntry;\n\nstatic DirectMutex   domains_lock;\nstatic unsigned int  domains_age;\nstatic DirectLink   *domains;\n\n#endif /* DIRECT_BUILD_TEXT */\n\n/**********************************************************************************************************************/\n\n#if DIRECT_BUILD_TEXT\n\nvoid\n__D_log_domain_init()\n{\n     domains_age = 1;\n\n     direct_mutex_init( &domains_lock );\n}\n\nvoid\n__D_log_domain_deinit()\n{\n     direct_mutex_deinit( &domains_lock );\n}\n\n#else /* DIRECT_BUILD_TEXT */\n\nvoid\n__D_log_domain_init()\n{\n}\n\nvoid\n__D_log_domain_deinit()\n{\n}\n\n#endif /* DIRECT_BUILD_TEXT */\n\n/**********************************************************************************************************************/\n\n#if DIRECT_BUILD_TEXT\n\n__dfb_no_instrument_function__\nstatic __inline__ LogDomainEntry *\nlookup_domain( const char *name, bool sub )\n{\n     LogDomainEntry *entry;\n\n     direct_list_foreach (entry, domains) {\n          if (!strcasecmp( entry->name, name ))\n               return entry;\n     }\n\n     /* If the domain being registered contains a slash, but didn't exactly match an entry in directfbrc,\n        check to see if the domain is descended from an entry in directfbrc. */\n     if (sub && strchr(name, '/')) {\n          int passed_name_len = strlen( name );\n\n          direct_list_foreach (entry, domains) {\n               int entry_len = strlen( entry->name );\n               if ((passed_name_len > entry_len) && (name[entry_len] == '/') &&\n                   (!strncasecmp( entry->name, name, entry_len ))) {\n                    return entry;\n               }\n          }\n     }\n\n     return NULL;\n}\n\n__dfb_no_instrument_function__\nstatic DirectLogLevel\ncheck_domain( DirectLogDomain *domain )\n{\n     if (direct_config->log_none)\n          return DIRECT_LOG_NONE;\n\n     if (direct_config->log_all)\n          return DIRECT_LOG_ALL;\n\n     if (domain->age != domains_age) {\n          LogDomainEntry *entry;\n\n          if (direct_mutex_lock( &domains_lock ))\n               return DIRECT_LOG_ALL;\n\n          entry = lookup_domain( domain->name, true );\n\n          domain->age = domains_age;\n\n          if (entry) {\n               domain->registered = true;\n               domain->config     = entry->config;\n          }\n          else {\n               domain->config.level = direct_config->log_level;\n          }\n\n          direct_mutex_unlock( &domains_lock );\n     }\n\n     return domain->config.level;\n}\n\nvoid\ndirect_log_domain_configure( const char *name, const DirectLogDomainConfig *config )\n{\n     LogDomainEntry *entry;\n\n     if (direct_mutex_lock( &domains_lock ))\n          return;\n\n     entry = lookup_domain( name, false );\n     if (!entry) {\n          direct_mutex_unlock( &domains_lock );\n\n          entry = (LogDomainEntry*) direct_calloc( 1, sizeof(LogDomainEntry) );\n          if (!entry) {\n               return;\n          }\n\n          entry->name = direct_strdup( name );\n          if (!entry->name) {\n               direct_free( entry );\n               return;\n          }\n\n          if (direct_mutex_lock( &domains_lock )) {\n               direct_free( entry->name );\n               direct_free( entry );\n               return;\n          }\n\n          direct_list_prepend( &domains, &entry->link );\n     }\n\n     entry->config = *config;\n\n     if (!++domains_age)\n          domains_age++;\n\n     direct_mutex_unlock( &domains_lock );\n}\n\nbool\ndirect_log_domain_check( DirectLogDomain *domain )\n{\n     return check_domain( domain ) >= DIRECT_LOG_DEBUG;\n}\n\nbool\ndirect_log_domain_check_level( DirectLogDomain *domain,\n                               DirectLogLevel   level )\n{\n     return check_domain( domain ) >= level;\n}\n\n__dfb_no_instrument_function__\nDirectResult\ndirect_log_domain_vprintf( DirectLogDomain *domain,\n                           DirectLogLevel   level,\n                           const char      *format,\n                           va_list          ap )\n{\n     if (check_domain( domain ) >= level) {\n          char       buf[200];\n          char      *ptr = buf;\n          long long  micros = direct_clock_get_time( DIRECT_CLOCK_MONOTONIC );\n          long long  millis = micros / 1000LL;\n          int        indent = direct_trace_debug_indent() * 4;\n          int        len;\n          va_list    ap2;\n\n          /* Prepare user message. */\n          va_copy( ap2, ap );\n          len = vsnprintf( buf, sizeof(buf), format, ap2 );\n          va_end( ap2 );\n\n          if (len < 0)\n               return DR_FAILURE;\n\n          if (len >= sizeof(buf)) {\n               ptr = direct_malloc( len + 1 );\n               if (!ptr)\n                    return DR_NOLOCALMEMORY;\n\n               len = vsnprintf( ptr, len + 1, format, ap );\n               if (len < 0) {\n                    direct_free( ptr );\n                    return DR_FAILURE;\n               }\n          }\n\n          /* Wrap around when too high. */\n          indent &= 0x7f;\n\n          /* Fill up domain name column after the colon, prepending remaining space (excl. ': ') to indent. */\n          indent += (domain->name_len < 34 ? 34 : 50) - domain->name_len - 2;\n\n          /* Print full message. */\n          direct_log_printf( domain->config.log, \"(-) [%-16.16s %3lld.%03lld,%03lld] (%5d) %s: %*s%s\",\n                             direct_thread_self_name() ?: \"  NO NAME\",\n                             millis / 1000LL, millis % 1000LL, micros % 1000LL,\n                             direct_gettid(), domain->name, indent, \"\", ptr );\n\n          direct_log_flush( domain->config.log );\n\n          if (ptr != buf)\n               direct_free( ptr );\n     }\n     else\n          direct_log_debug_delay( false );\n\n     return DR_OK;\n}\n\n__dfb_no_instrument_function__\nDirectResult\ndirect_log_domain_log( DirectLogDomain *domain,\n                       DirectLogLevel   level,\n                       const char      *func,\n                       const char      *file,\n                       int              line,\n                       const char      *format, ... )\n{\n     if (check_domain( domain ) >= level) {\n          char          buf[200];\n          char         *ptr = buf;\n          long long     micros = direct_clock_get_time( DIRECT_CLOCK_MONOTONIC );\n          long long     millis = micros / 1000LL;\n          int           indent = direct_trace_debug_indent() * 4;\n          int           len;\n          va_list       ap;\n\n          /* Prepare user message. */\n          va_start( ap, format );\n          len = vsnprintf( buf, sizeof(buf), format, ap );\n          va_end( ap );\n\n          if (len < 0)\n               return DR_FAILURE;\n\n          if (len >= sizeof(buf)) {\n               ptr = direct_malloc( len + 1 );\n               if (!ptr)\n                    return DR_NOLOCALMEMORY;\n\n               va_start( ap, format );\n               len = vsnprintf( ptr, len + 1, format, ap );\n               va_end( ap );\n\n               if (len < 0) {\n                    direct_free( ptr );\n                    return DR_FAILURE;\n               }\n          }\n\n          /* Wrap around when too high. */\n          indent &= 0x7f;\n\n          /* Fill up domain name column after the colon, prepending remaining space (excl. ': ') to indent. */\n          indent += (domain->name_len < 27 ? 27 : 42) - domain->name_len - 2;\n\n          /* Print full message. */\n          direct_log_printf( domain->config.log,\n                             \"(%c) [%-16.16s %3lld.%03lld,%03lld] (%5d) %s: %*s [%s:%d in %s()] %s\",\n                             level > DIRECT_LOG_INFO    ? '-' :\n                             level > DIRECT_LOG_NOTICE  ? '*' :\n                             level > DIRECT_LOG_WARNING ? '+' :\n                             level > DIRECT_LOG_ERROR   ? '#' :\n                             level > DIRECT_LOG_FATAL   ? '!' :\n                             level > DIRECT_LOG_NONE    ? '=' : ' ',\n                             direct_thread_self_name() ?: \"  NO NAME\",\n                             millis / 1000LL, millis % 1000LL, micros % 1000LL,\n                             direct_gettid(), domain->name, indent, \"\", file, line, func, ptr );\n\n          direct_log_flush( domain->config.log );\n\n          if (ptr != buf)\n               direct_free( ptr );\n     }\n     else\n          direct_log_debug_delay( false );\n\n     return DR_OK;\n}\n\n#else /* DIRECT_BUILD_TEXT */\n\nvoid\ndirect_log_domain_configure( const char                  *name,\n                             const DirectLogDomainConfig *config )\n{\n}\n\nbool\ndirect_log_domain_check( DirectLogDomain *domain )\n{\n     return false;\n}\n\nbool\ndirect_log_domain_check_level( DirectLogDomain *domain,\n                               DirectLogLevel   level )\n{\n     return false;\n}\n\nDirectResult\ndirect_log_domain_vprintf( DirectLogDomain *domain,\n                           DirectLogLevel   level,\n                           const char      *format,\n                           va_list          ap )\n{\n     return DR_OK;\n}\n\nDirectResult\ndirect_log_domain_log( DirectLogDomain *domain,\n                       DirectLogLevel   level,\n                       const char      *func,\n                       const char      *file,\n                       int              line,\n                       const char      *format, ... )\n{\n     return DR_OK;\n}\n\n#endif /* DIRECT_BUILD_TEXT */\n"
  },
  {
    "path": "lib/direct/log_domain.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__LOG_DOMAIN_H__\n#define __DIRECT__LOG_DOMAIN_H__\n\n#include <direct/compiler.h>\n#include <direct/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     DIRECT_LOG_NONE    = 0x00000000,\n     DIRECT_LOG_FATAL   = 0x00000001,\n     DIRECT_LOG_ERROR   = 0x00000002,\n     DIRECT_LOG_WARNING = 0x00000003,\n     DIRECT_LOG_NOTICE  = 0x00000004,\n     DIRECT_LOG_INFO    = 0x00000005,\n     DIRECT_LOG_VERBOSE = 0x00000006,\n\n     DIRECT_LOG_DEBUG_0 = DIRECT_LOG_VERBOSE,\n\n     DIRECT_LOG_DEBUG_1 = 0x00000007,\n     DIRECT_LOG_DEBUG_2 = 0x00000008,\n     DIRECT_LOG_DEBUG_3 = 0x00000009,\n     DIRECT_LOG_DEBUG_4 = 0x0000000A,\n     DIRECT_LOG_DEBUG_5 = 0x0000000B,\n     DIRECT_LOG_DEBUG_6 = 0x0000000C,\n     DIRECT_LOG_DEBUG_7 = 0x0000000D,\n     DIRECT_LOG_DEBUG_8 = 0x0000000E,\n     DIRECT_LOG_DEBUG_9 = 0x0000000F,\n\n     DIRECT_LOG_ALL     = 0x00000010,\n\n     DIRECT_LOG_DEBUG   = DIRECT_LOG_DEBUG_8, /* Default debug level */\n} DirectLogLevel;\n\ntypedef struct {\n     DirectLogLevel  level;\n     DirectLog      *log;\n} DirectLogDomainConfig;\n\ntypedef struct {\n     const char            *description;\n     const char            *name;\n     int                    name_len;\n\n     unsigned int           age;\n     bool                   registered;\n\n     DirectLogDomainConfig  config;\n} DirectLogDomain;\n\n/**********************************************************************************************************************/\n\nvoid         DIRECT_API direct_log_domain_configure  ( const char                  *name,\n                                                       const DirectLogDomainConfig *config );\n\nbool         DIRECT_API direct_log_domain_check      ( DirectLogDomain             *domain );\n\nbool         DIRECT_API direct_log_domain_check_level( DirectLogDomain             *domain,\n                                                       DirectLogLevel               level );\n\nDirectResult DIRECT_API direct_log_domain_vprintf    ( DirectLogDomain             *domain,\n                                                       DirectLogLevel               level,\n                                                       const char                  *format,\n                                                       va_list                      ap )          D_FORMAT_VPRINTF(3);\n\nDirectResult DIRECT_API direct_log_domain_log        ( DirectLogDomain             *domain,\n                                                       DirectLogLevel               level,\n                                                       const char                  *func,\n                                                       const char                  *file,\n                                                       int                          line,\n                                                       const char                  *format, ... ) D_FORMAT_PRINTF(6);\n\n/**********************************************************************************************************************/\n\nstatic __inline__ void\ndirect_log_domain_config_level( const char     *name,\n                                DirectLogLevel  level )\n{\n     DirectLogDomainConfig config;\n\n     config.level = level;\n     config.log   = NULL;\n\n     direct_log_domain_configure( name, &config );\n}\n\n#define D_LOG(d,l,...)                                                                                  \\\n     do {                                                                                               \\\n          direct_log_domain_log( &(d), DIRECT_LOG_##l, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__ ); \\\n     } while (0)\n\n/**********************************************************************************************************************/\n\nvoid __D_log_domain_init  ( void );\nvoid __D_log_domain_deinit( void );\n\n#endif\n"
  },
  {
    "path": "lib/direct/map.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/debug.h>\n#include <direct/map.h>\n#include <direct/mem.h>\n#include <direct/messages.h>\n\nD_DEBUG_DOMAIN( Direct_Map, \"Direct/Map\", \"Direct Map implementation\" );\n\n/**********************************************************************************************************************/\n\n#define REMOVED ((void*) -1)\n\ntypedef struct {\n     unsigned int  hash;\n     void         *object;\n} MapEntry;\n\nstruct __D_DirectMap {\n     int                   magic;\n\n     unsigned int          size;\n\n     unsigned int          count;\n     unsigned int          removed;\n\n     MapEntry             *entries;\n\n     DirectMapCompareFunc  compare;\n     DirectMapHashFunc     hash;\n     void                 *ctx;\n};\n\n#define DIRECT_MAP_ASSERT(map)              \\\n     do {                                   \\\n          D_MAGIC_ASSERT( map, DirectMap ); \\\n     } while (0)\n\n/**********************************************************************************************************************/\n\nstatic int\nlocate_entry( DirectMap    *map,\n              unsigned int  hash,\n              const void   *key )\n{\n     int             pos;\n     const MapEntry *entry;\n\n     D_DEBUG_AT( Direct_Map, \"%s( hash %u )\\n\", __FUNCTION__, hash );\n\n     DIRECT_MAP_ASSERT( map );\n     D_ASSERT( key != NULL );\n\n     pos = hash % map->size;\n\n     entry = &map->entries[pos];\n\n     while (entry->object) {\n          if (entry->object != REMOVED && entry->hash == hash && map->compare( map, key, entry->object, map->ctx ))\n               return pos;\n\n          if (++pos == map->size)\n               pos = 0;\n\n          entry = &map->entries[pos];\n     }\n\n     return -1;\n}\n\nstatic DirectResult\nresize_map( DirectMap    *map,\n            unsigned int  size )\n{\n     unsigned int  i, pos;\n     MapEntry     *entries;\n\n     D_DEBUG_AT( Direct_Map, \"%s( size %u )\\n\", __FUNCTION__, size );\n\n     DIRECT_MAP_ASSERT( map );\n     D_ASSERT( size > 3 );\n\n     entries = D_CALLOC( size, sizeof(MapEntry) );\n     if (!entries)\n          return D_OOM();\n\n     for (i = 0; i < map->size; i++) {\n          MapEntry *entry = &map->entries[i];\n          MapEntry *insertElement;\n\n          if (entry->object && entry->object != REMOVED) {\n               pos = entry->hash % size;\n\n               insertElement = &entries[pos];\n               while (insertElement->object && insertElement->object != REMOVED) {\n                   if (++pos == size)\n                       pos = 0;\n                   insertElement = &entries[pos];\n               }\n\n               entries[pos] = *entry;\n          }\n     }\n\n     D_FREE( map->entries );\n\n     map->size    = size;\n     map->entries = entries;\n     map->removed = 0;\n\n     return DR_OK;\n}\n\n/**********************************************************************************************************************/\n\nDirectResult\ndirect_map_create( unsigned int           initial_size,\n                   DirectMapCompareFunc   compare_func,\n                   DirectMapHashFunc      hash_func,\n                   void                  *ctx,\n                   DirectMap            **ret_map )\n{\n     DirectMap *map;\n\n     D_DEBUG_AT( Direct_Map, \"%s( size %u, compare %p, hash %p )\\n\", __FUNCTION__,\n                 initial_size, compare_func, hash_func );\n\n     D_ASSERT( compare_func != NULL );\n     D_ASSERT( hash_func != NULL );\n     D_ASSERT( ret_map != NULL );\n\n     if (initial_size < 3)\n          initial_size = 3;\n\n     map = D_CALLOC( 1, sizeof(DirectMap) );\n     if (!map)\n          return D_OOM();\n\n     map->entries = D_CALLOC( initial_size, sizeof(MapEntry) );\n     if (!map->entries) {\n          D_FREE( map );\n          return D_OOM();\n     }\n\n     map->size    = initial_size;\n     map->compare = compare_func;\n     map->hash    = hash_func;\n     map->ctx     = ctx;\n\n     D_MAGIC_SET( map, DirectMap );\n\n     *ret_map = map;\n\n     return DR_OK;\n}\n\nvoid\ndirect_map_destroy( DirectMap *map )\n{\n     D_DEBUG_AT( Direct_Map, \"%s()\\n\", __FUNCTION__ );\n\n     DIRECT_MAP_ASSERT( map );\n\n     D_MAGIC_CLEAR( map );\n\n     D_FREE( map->entries );\n     D_FREE( map );\n}\n\nDirectResult\ndirect_map_insert( DirectMap  *map,\n                   const void *key,\n                   void       *object )\n{\n     unsigned int  hash;\n     int           pos;\n     MapEntry     *entry;\n\n     D_DEBUG_AT( Direct_Map, \"%s( key %p, object %p )\\n\", __FUNCTION__, key, object );\n\n     DIRECT_MAP_ASSERT( map );\n     D_ASSERT( key != NULL );\n     D_ASSERT( object != NULL );\n\n     if ((map->count + map->removed) > map->size / 4)\n          resize_map( map, map->size * 3 );\n\n     hash = map->hash( map, key, map->ctx );\n     pos  = hash % map->size;\n\n     D_DEBUG_AT( Direct_Map, \"  -> hash %u, pos %d\\n\", hash, pos );\n\n     entry = &map->entries[pos];\n\n     while (entry->object && entry->object != REMOVED) {\n          if (entry->hash == hash && map->compare( map, key, entry->object, map->ctx )) {\n               if (entry->object == object) {\n                    D_DEBUG_AT( Direct_Map, \"  -> same object with matching key already exists\\n\" );\n                    return DR_BUSY;\n               }\n               else {\n                    D_DEBUG_AT( Direct_Map, \"  -> different object with matching key already exists\\n\" );\n                    D_BUG( \"different object with matching key already exists\" );\n                    return DR_BUG;\n               }\n          }\n\n          if (++pos == map->size)\n               pos = 0;\n\n          entry = &map->entries[pos];\n     }\n\n     if (entry->object == REMOVED)\n          map->removed--;\n\n     entry->hash   = hash;\n     entry->object = object;\n\n     map->count++;\n\n     D_DEBUG_AT( Direct_Map, \"  -> new count = %u, removed = %u, size = %u\\n\", map->count, map->removed, map->size );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_map_remove( DirectMap  *map,\n                   const void *key )\n{\n     unsigned int hash;\n     int          pos;\n\n     D_DEBUG_AT( Direct_Map, \"%s( key %p )\\n\", __FUNCTION__, key );\n\n     DIRECT_MAP_ASSERT( map );\n     D_ASSERT( key != NULL );\n\n     hash = map->hash( map, key, map->ctx );\n\n     pos = locate_entry( map, hash, key );\n     if (pos == -1) {\n          D_WARN( \"object to remove not found\" );\n          return DR_ITEMNOTFOUND;\n     }\n\n     map->entries[pos].object = REMOVED;\n\n     map->count--;\n     map->removed++;\n\n     D_DEBUG_AT( Direct_Map, \"  -> new count = %u, removed = %u, size = %u\\n\", map->count, map->removed, map->size );\n\n     return DR_OK;\n}\n\nvoid *\ndirect_map_lookup( DirectMap  *map,\n                   const void *key )\n{\n     unsigned int hash;\n     int          pos;\n\n     D_DEBUG_AT( Direct_Map, \"%s( key %p )\\n\", __FUNCTION__, key );\n\n     DIRECT_MAP_ASSERT( map );\n     D_ASSERT( key != NULL );\n\n     hash = map->hash( map, key, map->ctx );\n\n     pos = locate_entry( map, hash, key );\n\n     return (pos != -1) ? map->entries[pos].object : NULL;\n}\n\nvoid\ndirect_map_iterate( DirectMap             *map,\n                    DirectMapIteratorFunc  func,\n                    void                  *ctx )\n{\n     unsigned int i;\n\n     D_DEBUG_AT( Direct_Map, \"%s( func %p )\\n\", __FUNCTION__, func );\n\n     DIRECT_MAP_ASSERT( map );\n     D_ASSERT( func != NULL );\n\n     for (i = 0; i < map->size; i++) {\n          MapEntry *entry = &map->entries[i];\n\n          if (entry->object && entry->object != REMOVED) {\n               switch (func( map, entry->object, ctx )) {\n                    case DENUM_OK:\n                         break;\n\n                    case DENUM_CANCEL:\n                         return;\n\n                    case DENUM_REMOVE:\n                         entry->object = REMOVED;\n\n                         map->count--;\n                         map->removed++;\n               }\n          }\n     }\n}\n"
  },
  {
    "path": "lib/direct/map.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__MAP_H__\n#define __DIRECT__MAP_H__\n\n#include <direct/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef bool                    (*DirectMapCompareFunc) ( DirectMap *map, const void *key, void *object, void *ctx );\n\ntypedef unsigned int            (*DirectMapHashFunc)    ( DirectMap *map, const void *key, void *ctx );\n\ntypedef DirectEnumerationResult (*DirectMapIteratorFunc)( DirectMap *map, void *object, void *ctx );\n\n/**********************************************************************************************************************/\n\nDirectResult DIRECT_API  direct_map_create ( unsigned int            initial_size,\n                                             DirectMapCompareFunc    compare_func,\n                                             DirectMapHashFunc       hash_func,\n                                             void                   *ctx,\n                                             DirectMap             **ret_map );\n\nvoid         DIRECT_API  direct_map_destroy( DirectMap              *map );\n\nDirectResult DIRECT_API  direct_map_insert ( DirectMap              *map,\n                                             const void             *key,\n                                             void                   *object );\n\nDirectResult DIRECT_API  direct_map_remove ( DirectMap              *map,\n                                             const void             *key );\n\nvoid         DIRECT_API *direct_map_lookup ( DirectMap              *map,\n                                             const void             *key );\n\nvoid         DIRECT_API  direct_map_iterate( DirectMap              *map,\n                                             DirectMapIteratorFunc   func,\n                                             void                   *ctx );\n\n#endif\n"
  },
  {
    "path": "lib/direct/mem.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/mem.h>\n\n#if DIRECT_BUILD_DEBUGS\n\n#include <direct/debug.h>\n#include <direct/hash.h>\n#include <direct/log.h>\n#include <direct/memcpy.h>\n#include <direct/messages.h>\n#include <direct/trace.h>\n#include <direct/util.h>\n\nD_DEBUG_DOMAIN( Direct_Mem, \"Direct/Mem\", \"Direct Memory allocation\" );\n\n#endif /* DIRECT_BUILD_DEBUGS */\n\n/**********************************************************************************************************************/\n\n#if DIRECT_BUILD_DEBUGS\n\n#define DISABLED_OFFSET 8\n\ntypedef struct {\n     void              *mem;\n     size_t             bytes;\n     const char        *func;\n     const char        *file;\n     int                line;\n     DirectTraceBuffer *trace;\n} MemDesc;\n\nstatic DirectHash  alloc_hash = DIRECT_HASH_INIT( 523, true );\nstatic DirectMutex alloc_lock;\n\n#endif /* DIRECT_BUILD_DEBUGS */\n\n/**********************************************************************************************************************/\n\n#if DIRECT_BUILD_DEBUGS\n\nvoid\n__D_mem_init()\n{\n     direct_mutex_init( &alloc_lock );\n}\n\nvoid\n__D_mem_deinit()\n{\n     direct_mutex_deinit( &alloc_lock );\n}\n\n#else /* DIRECT_BUILD_DEBUGS */\n\nvoid\n__D_mem_init()\n{\n}\n\nvoid\n__D_mem_deinit()\n{\n}\n\n#endif /* DIRECT_BUILD_DEBUGS */\n\n/**********************************************************************************************************************/\n\n#if DIRECT_BUILD_DEBUGS\n\nstatic bool\nlocal_alloc_hash_iterator( DirectHash    *hash,\n                           unsigned long  key,\n                           void          *value,\n                           void          *ctx )\n{\n     MemDesc       *desc  = value;\n     unsigned long *total = ctx;\n\n     direct_log_printf( NULL, \"\"_ZUn(7)\" bytes at %p allocated in %s (%s: %d)\\n\",\n                        desc->bytes, desc->mem, desc->func, desc->file, desc->line );\n\n     if (desc->trace)\n          direct_trace_print_stack( desc->trace );\n\n     *total += desc->bytes;\n\n     return true;\n}\n\nvoid\ndirect_print_memleaks()\n{\n     unsigned long total = 0;\n\n     /* Debug only. */\n     direct_mutex_lock( &alloc_lock );\n\n     if (alloc_hash.count) {\n          direct_log_printf( NULL, \"Local memory allocations remaining (%d): \\n\", alloc_hash.count );\n\n          direct_hash_iterate( &alloc_hash, local_alloc_hash_iterator, &total );\n     }\n\n     direct_mutex_unlock( &alloc_lock );\n\n     if (total)\n          direct_log_printf( NULL, \"%7lu bytes in total\\n\", total );\n}\n\n__dfb_no_instrument_function__\nstatic __inline__ MemDesc *\nfill_mem_desc( MemDesc           *desc,\n               int                bytes,\n               const char        *func,\n               const char        *file,\n               int                line,\n               DirectTraceBuffer *trace )\n{\n     D_ASSERT( desc != NULL );\n\n     desc->mem   = desc + 1;\n     desc->bytes = bytes;\n     desc->func  = func;\n     desc->file  = file;\n     desc->line  = line;\n     desc->trace = trace;\n\n     return desc;\n}\n\nvoid *\ndirect_dbg_malloc( const char *file,\n                   int         line,\n                   const char *func,\n                   size_t      bytes )\n{\n     void          *mem;\n     unsigned long *val;\n\n     D_DEBUG_AT( Direct_Mem, \"  +\"_ZUn(6)\" bytes [%s:%d in %s()]\\n\", bytes, file, line, func );\n\n     if (direct_config->debugmem) {\n          MemDesc *desc;\n\n          mem = direct_malloc( bytes + sizeof(MemDesc) );\n\n          D_DEBUG_AT( Direct_Mem, \"  '-> %p\\n\", mem );\n\n          if (!mem)\n               return NULL;\n\n          desc = fill_mem_desc( mem, bytes, func, file, line, direct_trace_copy_buffer(NULL) );\n\n          direct_mutex_lock( &alloc_lock );\n\n          direct_hash_insert( &alloc_hash, (unsigned long) desc->mem, desc );\n\n          direct_mutex_unlock( &alloc_lock );\n\n          return desc->mem;\n     }\n\n     mem = direct_malloc( bytes + DISABLED_OFFSET );\n     if (!mem)\n          return NULL;\n\n     D_DEBUG_AT( Direct_Mem, \"  '-> %p\\n\", mem );\n\n     val    = mem;\n     val[0] = ~0;\n\n     return (char*) mem + DISABLED_OFFSET;\n}\n\nvoid *\ndirect_dbg_calloc( const char *file,\n                   int         line,\n                   const char *func,\n                   size_t      count,\n                   size_t      bytes )\n{\n     void          *mem;\n     unsigned long *val;\n\n     D_DEBUG_AT( Direct_Mem, \"  +\"_ZUn(6)\" bytes [%s:%d in %s()]\\n\", count * bytes, file, line, func );\n\n     if (direct_config->debugmem) {\n          MemDesc *desc;\n\n          mem = direct_calloc( 1, count * bytes + sizeof(MemDesc) );\n\n          D_DEBUG_AT( Direct_Mem, \"  '-> %p\\n\", mem );\n\n          if (!mem)\n               return NULL;\n\n          desc = fill_mem_desc( mem, count * bytes, func, file, line, direct_trace_copy_buffer(NULL) );\n\n          direct_mutex_lock( &alloc_lock );\n\n          direct_hash_insert( &alloc_hash, (unsigned long) desc->mem, desc );\n\n          direct_mutex_unlock( &alloc_lock );\n\n          return desc->mem;\n     }\n\n     mem = direct_calloc( 1, count * bytes + DISABLED_OFFSET );\n\n     D_DEBUG_AT( Direct_Mem, \"  '-> %p\\n\", mem );\n\n     if (!mem)\n          return NULL;\n\n     val    = mem;\n     val[0] = ~0;\n\n     return (char*) mem + DISABLED_OFFSET;\n}\n\nvoid *\ndirect_dbg_realloc( const char *file,\n                    int         line,\n                    const char *func,\n                    const char *what,\n                    void       *mem,\n                    size_t      bytes )\n{\n     unsigned long *val;\n     MemDesc       *desc;\n\n     D_DEBUG_AT( Direct_Mem, \"  *\"_ZUn(6)\" bytes [%s:%d in %s()] '%s' <- %p\\n\", bytes, file, line, func, what, mem );\n\n     if (!mem)\n          return direct_dbg_malloc( file, line, func, bytes );\n\n     if (!bytes) {\n          direct_dbg_free( file, line, func, what, mem );\n          return NULL;\n     }\n\n     val = (unsigned long*) ((char*) mem - DISABLED_OFFSET);\n\n     if (val[0] == ~0) {\n          D_DEBUG_AT( Direct_Mem, \"  *\"_ZUn(6)\" bytes [%s:%d in %s()] '%s'\\n\", bytes, file, line, func, what );\n\n          val = direct_realloc( val, bytes + DISABLED_OFFSET );\n\n          D_DEBUG_AT( Direct_Mem, \"  '-> %p\\n\", val );\n\n          if (val) {\n               mem = val;\n               return (char*) mem + DISABLED_OFFSET;\n          }\n\n          return NULL;\n     }\n\n     direct_mutex_lock( &alloc_lock );\n\n     desc = (MemDesc*) ((char*) mem - sizeof(MemDesc));\n     D_ASSERT( desc->mem == mem );\n\n     if (direct_hash_remove( &alloc_hash, (unsigned long) mem )) {\n          D_ERROR( \"Direct/Mem: Not reallocating unknown %p ('%s') from [%s:%d in %s()] (corrupt/incomplete list)!\\n\",\n                   mem, what, file, line, func );\n\n          mem = direct_dbg_malloc( file, line, func, bytes );\n     }\n     else {\n          void *new_mem = direct_realloc( desc, bytes + sizeof(MemDesc) );\n\n          D_DEBUG_AT( Direct_Mem, \"  '-> %p\\n\", new_mem );\n\n          D_DEBUG_AT( Direct_Mem, \"  %c\"_ZUn(6)\" bytes [%s:%d in %s()] (%s\"_ZU\") <- %p -> %p '%s'\\n\",\n                      (bytes > desc->bytes) ? '>' : '<', bytes, file, line, func,\n                      (bytes > desc->bytes) ? \"+\" : \"\", bytes - desc->bytes, mem, new_mem, what );\n\n          if (desc->trace) {\n               direct_trace_free_buffer( desc->trace );\n               desc->trace = NULL;\n          }\n\n          if (!new_mem)\n               D_WARN( \"could not reallocate memory (%p: \"_ZU\"->\"_ZU\")\", mem, desc->bytes, bytes );\n          else\n               desc = fill_mem_desc( new_mem, bytes, func, file, line, direct_trace_copy_buffer(NULL) );\n\n\n          mem = desc->mem;\n     }\n\n     direct_mutex_unlock( &alloc_lock );\n\n     return mem;\n}\n\nchar *\ndirect_dbg_strdup( const char *file,\n                   int         line,\n                   const char *func,\n                   const char *string )\n{\n     void          *mem;\n     unsigned long *val;\n     size_t         bytes = string ? strlen( string ) + 1 : 1;\n\n     D_DEBUG_AT( Direct_Mem, \"  +\"_ZUn(6)\" bytes [%s:%d in %s()] <- \\\"%30s\\\"\\n\", bytes, file, line, func, string );\n\n     if (direct_config->debugmem) {\n          MemDesc *desc;\n\n          mem = direct_malloc( bytes + sizeof(MemDesc) );\n\n          D_DEBUG_AT( Direct_Mem, \"  '-> %p\\n\", mem );\n\n          if (!mem)\n               return NULL;\n\n          desc = fill_mem_desc( mem, bytes, func, file, line, direct_trace_copy_buffer(NULL) );\n\n          direct_mutex_lock( &alloc_lock );\n\n          direct_hash_insert( &alloc_hash, (unsigned long) desc->mem, desc );\n\n          direct_mutex_unlock( &alloc_lock );\n\n          if (string)\n               direct_memcpy( desc->mem, string, bytes );\n          else\n               *(u8*) desc->mem = 0;\n\n          return desc->mem;\n     }\n\n     mem = direct_malloc( bytes + DISABLED_OFFSET );\n\n     D_DEBUG_AT( Direct_Mem, \"  '-> %p\\n\", mem );\n\n     if (!mem)\n          return NULL;\n\n     val    = mem;\n     val[0] = ~0;\n\n     if (string)\n          direct_memcpy( (char*) mem + DISABLED_OFFSET, string, bytes );\n     else\n          *((u8*) mem + DISABLED_OFFSET) = 0;\n\n     return (char*) mem + DISABLED_OFFSET;\n}\n\nvoid\ndirect_dbg_free( const char *file,\n                 int         line,\n                 const char *func,\n                 const char *what,\n                 void       *mem )\n{\n     unsigned long *val;\n     MemDesc       *desc;\n\n     if (!mem) {\n          return;\n     }\n\n     val = (unsigned long*) ((char*) mem - DISABLED_OFFSET);\n\n     if (val[0] == ~0) {\n          D_DEBUG_AT( Direct_Mem, \"  - number of bytes of '%s' [%s:%d in %s()] -> %p\\n\", what, file, line, func, mem );\n\n          val[0] = 0;\n          direct_free( val );\n\n          return;\n     }\n\n     direct_mutex_lock( &alloc_lock );\n\n     desc = (MemDesc*) ((char*) mem - sizeof(MemDesc));\n\n     D_ASSERT( desc->mem == mem );\n\n     if (direct_hash_remove( &alloc_hash, (unsigned long) mem )) {\n          D_ERROR( \"Direct/Mem: Not freeing unknown %p ('%s') from [%s:%d in %s()] (corrupt/incomplete list)!\\n\",\n                   mem, what, file, line, func );\n     }\n     else {\n          D_DEBUG_AT( Direct_Mem, \"  -\"_ZUn(6)\" bytes [%s:%d in %s()] -> %p '%s'\\n\",\n                      desc->bytes, file, line, func, mem, what );\n\n          if (desc->trace)\n               direct_trace_free_buffer( desc->trace );\n\n          direct_free( desc );\n     }\n\n     direct_mutex_unlock( &alloc_lock );\n}\n\n#else /* DIRECT_BUILD_DEBUGS */\n\nvoid\ndirect_print_memleaks()\n{\n}\n\nvoid *\ndirect_dbg_malloc( const char *file,\n                   int         line,\n                   const char *func,\n                   size_t      bytes )\n{\n     return direct_malloc( bytes );\n}\n\nvoid *\ndirect_dbg_calloc( const char *file,\n                   int         line,\n                   const char *func,\n                   size_t      count,\n                   size_t      bytes )\n{\n     return direct_calloc( 1, count * bytes );\n}\n\nvoid *\ndirect_dbg_realloc( const char *file,\n                    int         line,\n                    const char *func,\n                    const char *what,\n                    void       *mem,\n                    size_t      bytes )\n{\n     return direct_realloc( mem, bytes );\n}\n\nchar *\ndirect_dbg_strdup( const char *file,\n                   int         line,\n                   const char *func,\n                   const char *string )\n{\n     return direct_strdup( string );\n}\n\nvoid\ndirect_dbg_free( const char *file,\n                 int         line,\n                 const char *func,\n                 const char *what,\n                 void       *mem )\n{\n     return direct_free( mem );\n}\n\n#endif /* DIRECT_BUILD_DEBUGS */\n"
  },
  {
    "path": "lib/direct/mem.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__MEM_H__\n#define __DIRECT__MEM_H__\n\n#include <direct/os/mem.h>\n\n/**********************************************************************************************************************/\n\nvoid DIRECT_API  direct_print_memleaks( void );\n\nvoid DIRECT_API *direct_dbg_malloc    ( const char *file,\n                                        int         line,\n                                        const char *func,\n                                        size_t      bytes );\n\nvoid DIRECT_API *direct_dbg_calloc    ( const char *file,\n                                        int         line,\n                                        const char *func,\n                                        size_t      count,\n                                        size_t      bytes );\n\nvoid DIRECT_API *direct_dbg_realloc   ( const char *file,\n                                        int         line,\n                                        const char *func,\n                                        const char *what,\n                                        void       *mem,\n                                        size_t      bytes );\n\nchar DIRECT_API *direct_dbg_strdup    ( const char *file,\n                                        int         line,\n                                        const char *func,\n                                        const char *str );\n\nvoid DIRECT_API  direct_dbg_free      ( const char *file,\n                                        int         line,\n                                        const char *func,\n                                        const char *what,\n                                        void       *mem );\n\n/**********************************************************************************************************************/\n\n#if DIRECT_BUILD_DEBUG || defined(DIRECT_ENABLE_DEBUG)\n\n#define D_MALLOC(bytes)       direct_dbg_malloc ( __FILE__, __LINE__, __FUNCTION__, bytes )\n#define D_CALLOC(count,bytes) direct_dbg_calloc ( __FILE__, __LINE__, __FUNCTION__, count, bytes )\n#define D_REALLOC(mem,bytes)  direct_dbg_realloc( __FILE__, __LINE__, __FUNCTION__, #mem, mem, bytes )\n#define D_STRDUP(str)         direct_dbg_strdup ( __FILE__, __LINE__, __FUNCTION__, str )\n#define D_FREE(mem)           direct_dbg_free   ( __FILE__, __LINE__, __FUNCTION__, #mem, mem )\n\n#else /* DIRECT_BUILD_DEBUG || defined(DIRECT_ENABLE_DEBUG) */\n\n#define D_MALLOC              direct_malloc\n#define D_CALLOC              direct_calloc\n#define D_REALLOC             direct_realloc\n#define D_STRDUP              direct_strdup\n#define D_FREE                direct_free\n\n#endif /* DIRECT_BUILD_DEBUG || defined(DIRECT_ENABLE_DEBUG) */\n\nvoid __D_mem_init  ( void );\nvoid __D_mem_deinit( void );\n\n#endif\n"
  },
  {
    "path": "lib/direct/memcpy.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <config.h>\n#include <direct/log.h>\n#include <direct/memcpy.h>\n#include <direct/messages.h>\n\n#if DIRECT_BUILD_MEMCPY_PROBING\n\n#include <direct/clock.h>\n#include <direct/debug.h>\n#include <direct/mem.h>\n\nD_DEBUG_DOMAIN( Direct_Memcpy, \"Direct/Memcpy\", \"Direct Memcpy routines\" );\n\n#endif\n\n/**********************************************************************************************************************/\n\n#if SIZEOF_LONG == 8\n\nstatic void *\ngeneric64_memcpy( void       *to,\n                  const void *from,\n                  size_t      len )\n{\n     u8       *d = (u8*) to;\n     const u8 *s = (const u8*) from;\n     size_t    n;\n\n     if (len >= 128) {\n          unsigned long delta;\n\n          /* Align destination to 8-byte boundary. */\n          delta = (unsigned long) d & 7;\n          if (delta) {\n               len -= 8 - delta;\n\n               if ((unsigned long) d & 1) {\n                    *d++ = *s++;\n               }\n               if ((unsigned long) d & 2) {\n                    *((u16*)d) = *((const u16*) s);\n                    d += 2; s += 2;\n               }\n               if ((unsigned long) d & 4) {\n                    *((u32*)d) = *((const u32*) s);\n                    d += 4; s += 4;\n               }\n          }\n\n          n    = len >> 6;\n          len &= 63;\n\n          for (; n; n--) {\n               ((u64*) d)[0] = ((const u64*) s)[0];\n               ((u64*) d)[1] = ((const u64*) s)[1];\n               ((u64*) d)[2] = ((const u64*) s)[2];\n               ((u64*) d)[3] = ((const u64*) s)[3];\n               ((u64*) d)[4] = ((const u64*) s)[4];\n               ((u64*) d)[5] = ((const u64*) s)[5];\n               ((u64*) d)[6] = ((const u64*) s)[6];\n               ((u64*) d)[7] = ((const u64*) s)[7];\n               d += 64; s += 64;\n          }\n     }\n\n     /* Now do the tail of the block. */\n     if (len) {\n          n = len >> 3;\n\n          for (; n; n--) {\n               *((u64*) d) = *((const u64*) s);\n               d += 8; s += 8;\n          }\n          if (len & 4) {\n               *((u32*) d) = *((const u32*) s);\n               d += 4; s += 4;\n          }\n          if (len & 2)  {\n               *((u16*) d) = *((const u16*) s);\n               d += 2; s += 2;\n          }\n          if (len & 1)\n               *d = *s;\n     }\n\n     return to;\n}\n\n#endif /* SIZEOF_LONG == 8 */\n\nstatic void *\nstd_memcpy( void       *to,\n            const void *from,\n            size_t      len )\n{\n     return memcpy( to, from, len );\n}\n\ntypedef void *(*memcpy_func)( void *to, const void *from, size_t len );\n\nstatic struct {\n     char                 *name;\n     char                 *desc;\n     memcpy_func           function;\n     unsigned long long    time;\n} memcpy_method[] =\n{\n     { NULL,        NULL,                     NULL,             0 },\n     { \"libc\",      \"libc memcpy()\",          std_memcpy,       0 },\n#if SIZEOF_LONG == 8\n     { \"generic64\", \"Generic 64bit memcpy()\", generic64_memcpy, 0 },\n#endif\n     { NULL,        NULL,                     NULL,             0 }\n};\n\nmemcpy_func direct_memcpy = std_memcpy;\n\nvoid\ndirect_find_best_memcpy()\n{\n     int i;\n#if DIRECT_BUILD_MEMCPY_PROBING\n     #define BUFSIZE 1024\n     #define ITERS 256\n     unsigned long long t;\n     char *buf1, *buf2;\n     int iter, j, best = 0;\n#endif\n\n     if (direct_config->memcpy) {\n          for (i = 1; memcpy_method[i].name; i++) {\n               if (!strcmp( direct_config->memcpy, memcpy_method[i].name )) {\n                    direct_memcpy = memcpy_method[i].function;\n\n                    D_INFO( \"Direct/Memcpy: Forced to use %s\\n\", memcpy_method[i].desc );\n\n                    return;\n               }\n          }\n     }\n\n     /* Skipping the memcpy() probing saves library size and startup time. */\n\n#if DIRECT_BUILD_MEMCPY_PROBING\n     if (!(buf1 = D_MALLOC( BUFSIZE * 500 )))\n          return;\n\n     if (!(buf2 = D_MALLOC( BUFSIZE * 500 ))) {\n          D_FREE( buf1 );\n          return;\n     }\n\n     D_DEBUG_AT( Direct_Memcpy, \"Benchmarking memcpy methods (smaller is better):\\n\" );\n\n     for (i = 1; memcpy_method[i].name; i++) {\n          t = direct_clock_get_time( DIRECT_CLOCK_MONOTONIC );\n\n          for (iter = 0; iter < ITERS; iter++)\n               for (j = 0; j < 500; j++)\n                    memcpy_method[i].function( buf1 + j * BUFSIZE, buf2 + j * BUFSIZE, BUFSIZE );\n\n          t = direct_clock_get_time( DIRECT_CLOCK_MONOTONIC ) - t;\n          memcpy_method[i].time = t;\n\n          D_DEBUG_AT( Direct_Memcpy, \"\\t%-10s  %20lld\\n\", memcpy_method[i].name, t );\n\n          if (best == 0 || t < memcpy_method[best].time)\n               best = i;\n     }\n\n     if (best) {\n          direct_memcpy = memcpy_method[best].function;\n\n          D_INFO( \"Direct/Memcpy: Using %s\\n\", memcpy_method[best].desc );\n     }\n\n     D_FREE( buf1 );\n     D_FREE( buf2 );\n#endif\n}\n\nvoid\ndirect_print_memcpy_routines()\n{\n     int i;\n\n     direct_log_printf( NULL, \"\\nPossible values for memcpy option are:\\n\\n\" );\n\n     for (i = 1; memcpy_method[i].name; i++) {\n          direct_log_printf( NULL, \"  %-10s  %-27s\\n\", memcpy_method[i].name, memcpy_method[i].desc );\n     }\n\n     direct_log_printf( NULL, \"\\n\" );\n}\n"
  },
  {
    "path": "lib/direct/memcpy.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__MEMCPY_H__\n#define __DIRECT__MEMCPY_H__\n\n#include <direct/types.h>\n\n/**********************************************************************************************************************/\n\nvoid        DIRECT_API  direct_find_best_memcpy     ( void );\n\nvoid        DIRECT_API  direct_print_memcpy_routines( void );\n\nextern void DIRECT_API *(*direct_memcpy)            ( void       *to,\n                                                      const void *from,\n                                                      size_t      len );\n\n/**********************************************************************************************************************/\n\nstatic __inline__ void *\ndirect_memmove( void       *to,\n                const void *from,\n                size_t      len )\n{\n     if ((from < to && ((const char*) from + len) < ((char*) to)) || (((char*) to + len) < ((const char*) from)))\n          return direct_memcpy( to, from, len );\n     else\n          return memmove( to, from, len );\n}\n\n#endif\n"
  },
  {
    "path": "lib/direct/meson.build",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\ndirect_sources = [\n  'clock.c',\n  'conf.c',\n  'debug.c',\n  'direct.c',\n  'direct_result.c',\n  'hash.c',\n  'init.c',\n  'interface.c',\n  'log.c',\n  'log_domain.c',\n  'map.c',\n  'mem.c',\n  'memcpy.c',\n  'messages.c',\n  'modules.c',\n  'result.c',\n  'stream.c',\n  'system.c',\n  'thread.c',\n  'trace.c',\n  'util.c'\n]\n\ndirect_headers = [\n  'atomic.h',\n  'clock.h',\n  'compiler.h',\n  'conf.h',\n  'debug.h',\n  'direct.h',\n  'filesystem.h',\n  'hash.h',\n  'interface.h',\n  'interface_implementation.h',\n  'list.h',\n  'log.h',\n  'log_domain.h',\n  'map.h',\n  'mem.h',\n  'memcpy.h',\n  'messages.h',\n  'modules.h',\n  'mutex.h',\n  'result.h',\n  'serial.h',\n  'signals.h',\n  'stream.h',\n  'system.h',\n  'thread.h',\n  'trace.h',\n  'types.h',\n  'utf8.h',\n  'util.h',\n  'waitqueue.h'\n]\n\nos_headers = [\n  'os/clock.h',\n  'os/filesystem.h',\n  'os/log.h',\n  'os/mem.h',\n  'os/mutex.h',\n  'os/signals.h',\n  'os/system.h',\n  'os/thread.h',\n  'os/types.h',\n  'os/waitqueue.h'\n]\n\nbuild_conf = configuration_data()\n\nbuild_conf.set10('DIRECT_BUILD_CTORS', get_option('constructors'))\n\nbuild_conf.set10('DIRECT_BUILD_DEBUG', get_option('debug'))\n\nif get_option('debug')\n  build_conf.set10('DIRECT_BUILD_DEBUGS', true)\nelse\n  build_conf.set10('DIRECT_BUILD_DEBUGS', get_option('debug-support'))\nendif\n\nbuild_conf.set10('DIRECT_BUILD_DYNLOAD', get_option('default_library') == 'shared')\n\nbuild_conf.set10('DIRECT_BUILD_MEMCPY_PROBING', get_option('memcpy-probing'))\n\nbuild_conf.set10('DIRECT_BUILD_NETWORK', get_option('network'))\n\nbuild_conf.set10('DIRECT_BUILD_PIPED_STREAM', get_option('piped-stream'))\n\nbuild_conf.set10('DIRECT_BUILD_SENTINELS', get_option('sentinels'))\n\nif get_option('os') == 'linux'\n  os_sources = [\n    'os/linux/clock.c',\n    'os/linux/filesystem.c',\n    'os/linux/log.c',\n    'os/linux/mem.c',\n    'os/linux/mutex.c',\n    'os/linux/signals.c',\n    'os/linux/system.c',\n    'os/linux/thread.c',\n  ]\n\n  os_linux_headers = [\n    'os/linux/filesystem.h',\n    'os/linux/mutex.h',\n    'os/linux/thread.h',\n    'os/linux/types.h',\n    'os/linux/waitqueue.h'\n  ]\n\n  build_conf.set('DIRECT_BUILD_OS_LINUX', true)\nelse\n  error('Unsupported OS')\nendif\n\nbuild_conf.set10('DIRECT_BUILD_TEXT', get_option('text'))\n\nif get_option('trace')\n  add_global_arguments('-finstrument-functions', language: 'c')\nendif\nbuild_conf.set10('DIRECT_BUILD_TRACE', get_option('trace'))\n\nconfigure_file(configuration: build_conf,\n               output: 'build.h',\n               install: true,\n               install_dir: get_option('includedir') / 'directfb/direct')\n\nlibdl_dep = []\nmoduledir_def = []\nif get_option('default_library') == 'shared'\n  libdl_dep = cc.find_library('dl')\n  moduledir_def = '-DMODULEDIR=\"@0@\"'.format(moduledir)\nendif\n\nlibdirect_private = []\nif get_option('default_library') == 'static' and get_option('constructors')\n  libdirect_private = ['-Wl,-u,__D_init_all']\nendif\n\nlibrt_dep = []\nif not cc.has_function('clock_gettime')\n  librt_dep = cc.find_library('rt')\n  if get_option('default_library') == 'static'\n    libdirect_private += ['-lrt']\n  endif\nendif\n\nthreads_dep = dependency('threads')\nif get_option('default_library') == 'static'\n  libdirect_private += ['-pthread']\nendif\n\nlibdirect = library('direct-@0@.@1@'.format(directfb_major_version, directfb_minor_version),\n                    direct_sources, os_sources,\n                    include_directories: [config_inc, lib_inc],\n                    c_args: moduledir_def,\n                    dependencies: [libdl_dep, librt_dep, threads_dep],\n                    version: '0.@0@.0'.format(directfb_micro_version),\n                    install: true)\n\ninstall_symlink('libdirect' + libsuffix,\n                pointing_to: 'libdirect-@0@.@1@'.format(directfb_major_version, directfb_minor_version) + libsuffix,\n                install_dir: get_option('prefix') / get_option('libdir'))\n\ninstall_headers(direct_headers,   subdir: 'directfb/direct')\ninstall_headers(os_headers,       subdir: 'directfb/direct/os')\nif get_option('os') == 'linux'\n  install_headers(os_linux_headers, subdir: 'directfb/direct/os/linux')\nendif\n\npkgconfig.generate(filebase: 'direct',\n                   name: 'Direct',\n                   description: 'DirectFB low-level library',\n                   libraries: '-L${libdir} -ldirect',\n                   libraries_private: libdirect_private,\n                   subdirs: 'directfb')\n\ndirect_dep = declare_dependency(include_directories: lib_inc, link_with: libdirect)\n"
  },
  {
    "path": "lib/direct/messages.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/messages.h>\n\n/**********************************************************************************************************************/\n\n#if DIRECT_BUILD_TEXT\n\n#include <direct/log.h>\n#include <direct/mem.h>\n#include <direct/result.h>\n#include <direct/system.h>\n#include <direct/trace.h>\n#include <direct/util.h>\n\n__dfb_no_instrument_function__\nvoid\ndirect_messages_info( const char *format, ... )\n{\n     char  buf[512];\n     char *ptr = buf;\n     int   len;\n\n     va_list ap;\n\n     va_start( ap, format );\n     len = vsnprintf( buf, sizeof(buf), format, ap );\n     va_end( ap );\n\n     if (len < 0)\n          return;\n\n     if (len >= sizeof(buf)) {\n          ptr = direct_malloc( len + 1 );\n          if (!ptr)\n               return;\n\n          va_start( ap, format );\n          len = vsnprintf( ptr, len + 1, format, ap );\n          va_end( ap );\n          if (len < 0) {\n               direct_free( ptr );\n               return;\n          }\n     }\n\n     direct_log_printf( NULL, \"(*) %s\", ptr );\n\n     if (ptr != buf)\n          direct_free( ptr );\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_messages_error( const char *format, ... )\n{\n     char  buf[512];\n     char *ptr = buf;\n     int   len;\n\n     va_list ap;\n\n     va_start( ap, format );\n     len = vsnprintf( buf, sizeof(buf), format, ap );\n     va_end( ap );\n\n     if (len < 0)\n          return;\n\n     if (len >= sizeof(buf)) {\n          ptr = direct_malloc( len + 1 );\n          if (!ptr)\n               return;\n\n          va_start( ap, format );\n          len = vsnprintf( ptr, len + 1, format, ap );\n          va_end( ap );\n          if (len < 0) {\n               direct_free( ptr );\n               return;\n          }\n     }\n\n     direct_log_printf( NULL, \"(!) %s\", ptr );\n\n     direct_trace_print_stack( NULL );\n\n     if (direct_config->fatal_messages & DMT_ERROR)\n          direct_trap( \"Error\", SIGABRT );\n\n     if (ptr != buf)\n          direct_free( ptr );\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_messages_derror( DirectResult result,\n                        const char *format, ... )\n{\n     char buf[512];\n\n     va_list ap;\n\n     va_start( ap, format );\n\n     vsnprintf( buf, sizeof(buf), format, ap );\n\n     va_end( ap );\n\n     direct_log_printf( NULL, \"(!) %s    --> %s\\n\", buf, DirectResultString( result ) );\n\n     direct_trace_print_stack( NULL );\n\n     if (direct_config->fatal_messages & DMT_ERROR)\n          direct_trap( \"DError\", SIGABRT );\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_messages_perror( int erno,\n                        const char *format, ... )\n{\n     char buf[512];\n\n     va_list ap;\n\n     va_start( ap, format );\n\n     vsnprintf( buf, sizeof(buf), format, ap );\n\n     va_end( ap );\n\n     direct_log_printf( NULL, \"(!) %s    --> %s\\n\", buf, direct_strerror( erno ) );\n\n     direct_trace_print_stack( NULL );\n\n     if (direct_config->fatal_messages & DMT_ERROR)\n          direct_trap( \"PError\", SIGABRT );\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_messages_dlerror( const char *dlerr,\n                         const char *format, ... )\n{\n     char buf[512];\n\n     va_list ap;\n\n     va_start( ap, format );\n\n     vsnprintf( buf, sizeof(buf), format, ap );\n\n     va_end( ap );\n\n     direct_log_printf( NULL, \"(!) %s    --> %s\\n\", buf, dlerr );\n\n     direct_trace_print_stack( NULL );\n\n     if (direct_config->fatal_messages & DMT_ERROR)\n          direct_trap( \"DlError\", SIGABRT );\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_messages_once( const char *func,\n                      const char *file,\n                      int         line,\n                      const char *format, ... )\n{\n     char buf[512];\n\n     va_list ap;\n\n     va_start( ap, format );\n\n     vsnprintf( buf, sizeof(buf), format, ap );\n\n     va_end( ap );\n\n     direct_log_printf( NULL, \"(!) *** ONCE [%s] *** [%s:%d in %s()]\\n\", buf, file, line, func );\n\n     direct_trace_print_stack( NULL );\n\n     if (direct_config->fatal_messages & DMT_ONCE)\n          direct_trap( \"Once\", SIGABRT );\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_messages_unimplemented( const char *func,\n                               const char *file,\n                               int         line )\n{\n     direct_log_printf( NULL, \"(+) *** UNIMPLEMENTED [%s] *** [%s:%d]\\n\", func, file, line );\n\n     direct_trace_print_stack( NULL );\n\n     if (direct_config->fatal_messages & DMT_UNIMPLEMENTED)\n          direct_trap( \"Unimplemented\", SIGABRT );\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_messages_bug( const char *func,\n                     const char *file,\n                     int         line,\n                     const char *format, ... )\n{\n     char buf[512];\n\n     va_list ap;\n\n     va_start( ap, format );\n\n     vsnprintf( buf, sizeof(buf), format, ap );\n\n     va_end( ap );\n\n     direct_log_printf( NULL, \"(+) *** BUG [%s] *** [%s:%d in %s()]\\n\", buf, file, line, func );\n\n     direct_trace_print_stack( NULL );\n\n     if (direct_config->fatal_messages & DMT_BUG)\n          direct_trap( \"Bug\", SIGABRT );\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_messages_warn( const char *func,\n                      const char *file,\n                      int         line,\n                      const char *format, ... )\n{\n     char buf[512];\n\n     va_list ap;\n\n     va_start( ap, format );\n\n     vsnprintf( buf, sizeof(buf), format, ap );\n\n     va_end( ap );\n\n     direct_log_printf( NULL, \"(#) *** WARNING [%s] *** [%s:%d in %s()]\\n\", buf, file, line, func );\n\n     direct_trace_print_stack( NULL );\n\n     if (direct_config->fatal_messages & DMT_WARNING)\n          direct_trap( \"Warning\", SIGABRT );\n}\n\n__dfb_no_instrument_function__\nint\ndirect_messages_oom( const char *func,\n                     const char *file,\n                     int         line )\n{\n     direct_log_printf( NULL, \"(=) *** OOM [out of memory] *** [%s:%d in %s()]\\n\", file, line, func );\n\n     direct_trace_print_stack( NULL );\n\n     if (direct_config->fatal_messages & DMT_OOM)\n          direct_trap( \"OOM\", SIGABRT );\n\n     return DR_NOLOCALMEMORY;\n}\n\n__dfb_no_instrument_function__\nint\ndirect_messages_ooshm( const char *func,\n                       const char *file,\n                       int         line )\n{\n     direct_log_printf( NULL, \"(=) *** OOSHM [out of shared memory] *** [%s:%d in %s()]\\n\", file, line, func );\n\n     direct_trace_print_stack( NULL );\n\n     if (direct_config->fatal_messages & DMT_OOSHM)\n          direct_trap( \"OOSHM\", SIGABRT );\n\n     return DR_NOSHAREDMEMORY;\n}\n\n#else /* DIRECT_BUILD_TEXT */\n\nvoid\ndirect_messages_info( const char *format, ... )\n{\n}\n\nvoid\ndirect_messages_error( const char *format, ... )\n{\n}\n\nvoid\ndirect_messages_derror( DirectResult result,\n                        const char *format, ... )\n{\n}\n\nvoid\ndirect_messages_perror( int erno,\n                        const char *format, ... )\n{\n}\n\nvoid\ndirect_messages_dlerror( const char *dlerr,\n                         const char *format, ... )\n{\n}\n\nvoid\ndirect_messages_once( const char *func,\n                      const char *file,\n                      int         line,\n                      const char *format, ... )\n{\n}\n\nvoid\ndirect_messages_unimplemented( const char *func,\n                               const char *file,\n                               int         line )\n{\n}\n\nvoid\ndirect_messages_bug( const char *func,\n                     const char *file,\n                     int         line,\n                     const char *format, ... )\n{\n}\n\nvoid\ndirect_messages_warn( const char *func,\n                      const char *file,\n                      int         line,\n                      const char *format, ... )\n{\n}\n\nint\ndirect_messages_oom( const char *func,\n                     const char *file,\n                     int         line )\n{\n     return DR_NOLOCALMEMORY;\n}\n\nint\ndirect_messages_ooshm( const char *func,\n                       const char *file,\n                       int         line )\n{\n     return DR_NOSHAREDMEMORY;\n}\n\n#endif /* DIRECT_BUILD_TEXT */\n"
  },
  {
    "path": "lib/direct/messages.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__MESSAGES_H__\n#define __DIRECT__MESSAGES_H__\n\n#include <direct/conf.h>\n\n/**********************************************************************************************************************/\n\nvoid DIRECT_API direct_messages_info         ( const char   *format, ... ) D_FORMAT_PRINTF(1);\n\nvoid DIRECT_API direct_messages_error        ( const char   *format, ... ) D_FORMAT_PRINTF(1);\n\nvoid DIRECT_API direct_messages_derror       ( DirectResult  result,\n                                               const char   *format, ... ) D_FORMAT_PRINTF(2);\n\nvoid DIRECT_API direct_messages_perror       ( int           erno,\n                                               const char   *format, ... ) D_FORMAT_PRINTF(2);\n\nvoid DIRECT_API direct_messages_dlerror      ( const char   *dlerr,\n                                               const char   *format, ... ) D_FORMAT_PRINTF(2);\n\nvoid DIRECT_API direct_messages_once         ( const char   *func,\n                                               const char   *file,\n                                               int           line,\n                                               const char   *format, ... ) D_FORMAT_PRINTF(4);\n\nvoid DIRECT_API direct_messages_unimplemented( const char   *func,\n                                               const char   *file,\n                                               int           line );\n\nvoid DIRECT_API direct_messages_bug          ( const char   *func,\n                                               const char   *file,\n                                               int           line,\n                                               const char   *format, ... ) D_FORMAT_PRINTF(4);\n\nvoid DIRECT_API direct_messages_warn         ( const char   *func,\n                                               const char   *file,\n                                               int           line,\n                                               const char   *format, ... ) D_FORMAT_PRINTF(4);\n\nint  DIRECT_API direct_messages_oom          ( const char   *func,\n                                               const char   *file,\n                                               int           line );\n\nint  DIRECT_API direct_messages_ooshm        ( const char   *func,\n                                               const char   *file,\n                                               int           line );\n\n#define D_INFO(...)       do {                                                                                  \\\n                               if (!(direct_config->quiet & DMT_INFO))                                          \\\n                                    direct_messages_info( __VA_ARGS__ );                                        \\\n                          } while (0)\n\n#define D_ERROR(...)      do {                                                                                  \\\n                               if (!(direct_config->quiet & DMT_ERROR))                                         \\\n                                    direct_messages_error( __VA_ARGS__ );                                       \\\n                          } while (0)\n\n#define D_DERROR(r,...)   do {                                                                                  \\\n                               if (!(direct_config->quiet & DMT_ERROR))                                         \\\n                                    direct_messages_derror( (DirectResult) r, __VA_ARGS__ );                    \\\n                          } while (0)\n\n#define D_PERROR(...)     do {                                                                                  \\\n                               if (!(direct_config->quiet & DMT_ERROR))                                         \\\n                                    direct_messages_perror( errno, __VA_ARGS__ );                               \\\n                          } while (0)\n\n#define D_DLERROR(...)    do {                                                                                  \\\n                               if (!(direct_config->quiet & DMT_ERROR))                                         \\\n                                    direct_messages_dlerror( dlerror(), __VA_ARGS__ );                          \\\n                          } while (0)\n\n#define D_ONCE(...)       do {                                                                                  \\\n                               if (!(direct_config->quiet & DMT_ONCE)) {                                        \\\n                                    static bool first = true;                                                   \\\n                                    if (first) {                                                                \\\n                                         direct_messages_once( __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__ ); \\\n                                         first = false;                                                         \\\n                                    }                                                                           \\\n                               }                                                                                \\\n                          } while (0)\n\n#define D_UNIMPLEMENTED() do {                                                                                  \\\n                              if (!(direct_config->quiet & DMT_UNIMPLEMENTED)) {                                \\\n                                   static bool first = true;                                                    \\\n                                   if (first) {                                                                 \\\n                                        direct_messages_unimplemented( __FUNCTION__, __FILE__, __LINE__ );      \\\n                                        first = false;                                                          \\\n                                   }                                                                            \\\n                              }                                                                                 \\\n                          } while (0)\n\n#define D_BUG(...)        do {                                                                                  \\\n                               if (!(direct_config->quiet & DMT_BUG))                                           \\\n                                    direct_messages_bug( __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__ );       \\\n                          } while (0)\n\n#define D_BREAK           D_BUG\n\n#define D_WARN(...)       do {                                                                                  \\\n                               if (!(direct_config->quiet & DMT_WARNING))                                       \\\n                                    direct_messages_warn( __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__ );      \\\n                          } while (0)\n\n#define D_OOM()           direct_messages_oom( __FUNCTION__, __FILE__, __LINE__ )\n\n#endif\n"
  },
  {
    "path": "lib/direct/modules.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/filesystem.h>\n#include <direct/mem.h>\n#include <direct/messages.h>\n#include <direct/modules.h>\n\nD_DEBUG_DOMAIN( Direct_Modules, \"Direct/Modules\", \"Direct Modules loading and registration\" );\n\n/**********************************************************************************************************************/\n\n#if DIRECT_BUILD_DYNLOAD\n\nstatic DirectModuleEntry *lookup_by_name( const DirectModuleDir *directory, const char *name );\nstatic DirectModuleEntry *lookup_by_file( const DirectModuleDir *directory, const char *file );\n\nstatic void *open_module  ( DirectModuleEntry *module );\nstatic bool  load_module  ( DirectModuleEntry *module );\nstatic void  unload_module( DirectModuleEntry *module );\n\n#endif /* DIRECT_BUILD_DYNLOAD */\n\n/**********************************************************************************************************************/\n\nstatic int\nsuppress_module( const char *name )\n{\n     int i = 0;\n\n     if (!direct_config || !direct_config->disable_module)\n          return 0;\n\n     while (direct_config->disable_module[i]) {\n          if (strcmp( direct_config->disable_module[i], name ) == 0) {\n               D_INFO( \"Direct/Modules: Suppress module '%s'\\n\", direct_config->disable_module[i] );\n               return 1;\n          }\n\n          i++;\n     }\n\n     return 0;\n}\n\nvoid\ndirect_modules_register( DirectModuleDir *directory,\n                         unsigned int     abi_version,\n                         const char      *name,\n                         const void      *funcs )\n{\n     DirectModuleEntry *entry;\n\n     D_ASSERT( directory != NULL );\n     D_ASSERT( name != NULL );\n     D_ASSERT( funcs != NULL );\n\n     D_DEBUG_AT( Direct_Modules, \"Registering '%s' ('%s')...\\n\", name, directory->path );\n\n#if DIRECT_BUILD_DYNLOAD\n     if ((entry = lookup_by_name( directory, name )) != NULL) {\n          D_DEBUG_AT( Direct_Modules, \"  -> found entry %p\\n\", entry );\n\n          D_MAGIC_ASSERT( entry, DirectModuleEntry );\n\n          entry->loaded = true;\n          entry->funcs  = funcs;\n\n          return;\n     }\n#endif /* DIRECT_BUILD_DYNLOAD */\n\n     if (directory->loading) {\n          entry = directory->loading;\n\n          D_MAGIC_ASSERT( entry, DirectModuleEntry );\n\n          directory->loading = NULL;\n     }\n     else {\n          entry = D_CALLOC( 1, sizeof(DirectModuleEntry) );\n          if (!entry) {\n               D_OOM();\n               return;\n          }\n\n          D_DEBUG_AT( Direct_Modules, \"  -> allocated entry %p\\n\", entry );\n\n          D_MAGIC_SET( entry, DirectModuleEntry );\n     }\n\n     entry->directory = directory;\n     entry->loaded    = true;\n     entry->name      = D_STRDUP( name );\n     entry->funcs     = funcs;\n     entry->disabled  = suppress_module( name );\n\n     if (abi_version != directory->abi_version) {\n          D_ERROR( \"Direct/Modules: ABI version of '%s' (%u) does not match %u!\\n\",\n                   entry->file ?: entry->name, abi_version, directory->abi_version );\n\n          entry->disabled = true;\n     }\n\n     direct_list_prepend( &directory->entries, &entry->link );\n\n     D_DEBUG_AT( Direct_Modules, \"...registered as %p\\n\", entry );\n}\n\nvoid\ndirect_modules_unregister( DirectModuleDir *directory,\n                           const char      *name )\n{\n#if DIRECT_BUILD_DYNLOAD\n     DirectModuleEntry *entry;\n#endif /* DIRECT_BUILD_DYNLOAD */\n\n     D_DEBUG_AT( Direct_Modules, \"Unregistering '%s' ('%s')...\\n\", name, directory->path );\n\n#if DIRECT_BUILD_DYNLOAD\n     entry = lookup_by_name( directory, name );\n     if (!entry) {\n          D_ERROR( \"Direct/Modules: Unregister failed, could not find '%s' module!\\n\", name );\n          return;\n     }\n\n     D_MAGIC_ASSERT( entry, DirectModuleEntry );\n\n     D_FREE( entry->name );\n     D_FREE( entry->file );\n\n     direct_list_remove( &directory->entries, &entry->link );\n\n     D_MAGIC_CLEAR( entry );\n\n     D_FREE( entry );\n#endif /* DIRECT_BUILD_DYNLOAD */\n\n     D_DEBUG_AT( Direct_Modules, \"...unregistered\\n\" );\n}\n\nint\ndirect_modules_explore_directory( DirectModuleDir *directory )\n{\n#if DIRECT_BUILD_DYNLOAD\n     DirectResult  ret;\n     DirectDir     dir;\n     DirectEntry   entry;\n     int           count = 0;\n     const char   *pathfront = \"\";\n     const char   *path;\n     char         *buf;\n\n     D_ASSERT( directory != NULL );\n     D_ASSERT( directory->path != NULL );\n\n     D_DEBUG_AT( Direct_Modules, \"%s( '%s' )\\n\", __FUNCTION__, directory->path );\n\n     path = directory->path;\n\n     if (path[0] != '/') {\n          pathfront = direct_config->module_dir;\n          if (!pathfront)\n               pathfront = MODULEDIR;\n     }\n\n     buf = alloca( strlen( pathfront ) + 1 + strlen( path ) + 1 ); /* pre, slash, post, 0 */\n     sprintf( buf, \"%s/%s\", pathfront, path );\n\n     ret = direct_dir_open( &dir, buf );\n     if (ret) {\n          D_DEBUG_AT( Direct_Modules, \"  -> error opening directory '%s'!\\n\", buf );\n          return 0;\n     }\n\n     while (direct_dir_read( &dir, &entry ) == DR_OK) {\n          void              *handle;\n          DirectModuleEntry *module;\n          int                entry_len = strlen( entry.name );\n\n          if (entry_len < 4                  ||\n              entry.name[entry_len-2] != 's' ||\n              entry.name[entry_len-1] != 'o')\n               continue;\n\n          if (lookup_by_file( directory, entry.name ))\n               continue;\n\n          module = D_CALLOC( 1, sizeof(DirectModuleEntry) );\n          if (!module)\n               continue;\n\n          D_DEBUG_AT( Direct_Modules, \"  -> allocated entry %p\\n\", module );\n\n          D_MAGIC_SET( module, DirectModuleEntry );\n\n          module->directory = directory;\n          module->dynamic   = true;\n          module->file      = D_STRDUP( entry.name );\n\n          if (!module->file) {\n               D_MAGIC_CLEAR( module );\n               D_FREE( module );\n               continue;\n          }\n\n          directory->loading = module;\n\n          if ((handle = open_module( module )) != NULL) {\n               if (!module->loaded) {\n                    dlclose( handle );\n\n                    D_ERROR( \"Direct/Modules: Module '%s' did not register itself after loading!\\n\", entry.name );\n\n                    module->disabled = true;\n\n                    direct_list_prepend( &directory->entries, &module->link );\n               }\n               else if (module->disabled) {\n                    module->loaded = false;\n\n                    dlclose( handle );\n               }\n               else {\n                    module->handle = handle;\n\n                    count++;\n               }\n          }\n          else {\n               module->disabled = true;\n\n               direct_list_prepend( &directory->entries, &module->link );\n          }\n\n          directory->loading = NULL;\n     }\n\n     direct_dir_close( &dir );\n\n     return count;\n#else /* DIRECT_BUILD_DYNLOAD */\n     return 0;\n#endif /* DIRECT_BUILD_DYNLOAD */\n}\n\nconst void *\ndirect_module_ref( DirectModuleEntry *module )\n{\n     D_MAGIC_ASSERT( module, DirectModuleEntry );\n\n     D_DEBUG_AT( Direct_Modules, \"%s( %p '%s', %d refs, loaded %d, dynamic %d, disabled %d )\\n\", __FUNCTION__,\n                 module, module->name, module->refs, module->loaded, module->dynamic, module->disabled );\n\n     if (module->disabled)\n          return NULL;\n\n#if DIRECT_BUILD_DYNLOAD\n     if (!module->loaded && !load_module( module )) {\n          D_DEBUG_AT( Direct_Modules, \"  -> load_module failed, returning NULL\\n\" );\n          return NULL;\n     }\n#endif /* DIRECT_BUILD_DYNLOAD */\n\n     module->refs++;\n\n     D_DEBUG_AT( Direct_Modules, \"  -> refs %d, funcs %p\\n\", module->refs, module->funcs );\n\n     return module->funcs;\n}\n\nvoid\ndirect_module_unref( DirectModuleEntry *module )\n{\n     D_MAGIC_ASSERT( module, DirectModuleEntry );\n\n     D_DEBUG_AT( Direct_Modules, \"%s( %p '%s', %d refs, loaded %d, dynamic %d, disabled %d )\\n\", __FUNCTION__,\n                 module, module->name, module->refs, module->loaded, module->dynamic, module->disabled );\n\n     D_ASSERT( module->refs > 0 );\n\n     if (--module->refs)\n          return;\n\n#if DIRECT_BUILD_DYNLOAD\n     if (module->dynamic)\n          unload_module( module );\n#endif /* DIRECT_BUILD_DYNLOAD */\n}\n\n/**********************************************************************************************************************/\n\n#if DIRECT_BUILD_DYNLOAD\n\nstatic DirectModuleEntry *\nlookup_by_name( const DirectModuleDir *directory,\n                const char            *name )\n{\n     DirectModuleEntry *entry;\n\n     D_ASSERT( directory != NULL );\n     D_ASSERT( name != NULL );\n\n     direct_list_foreach (entry, directory->entries) {\n          D_MAGIC_ASSERT( entry, DirectModuleEntry );\n\n          if (!entry->name)\n               continue;\n\n          if (!strcmp( entry->name, name ))\n               return entry;\n     }\n\n     return NULL;\n}\n\nstatic DirectModuleEntry *\nlookup_by_file( const DirectModuleDir *directory,\n                const char            *file )\n{\n     DirectModuleEntry *entry;\n\n     D_DEBUG_AT( Direct_Modules, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( directory != NULL );\n     D_ASSERT( file != NULL );\n\n     direct_list_foreach (entry, directory->entries) {\n          D_MAGIC_ASSERT( entry, DirectModuleEntry );\n\n          if (!entry->file)\n               continue;\n\n          if (!strcmp( entry->file, file ))\n               return entry;\n     }\n\n     return NULL;\n}\n\nstatic bool\nload_module( DirectModuleEntry *module )\n{\n     D_MAGIC_ASSERT( module, DirectModuleEntry );\n\n     D_DEBUG_AT( Direct_Modules, \"%s( %p '%s', %d refs )\\n\", __FUNCTION__, module, module->file, module->refs );\n\n     D_ASSERT( module->dynamic == true );\n     D_ASSERT( module->file != NULL );\n     D_ASSERT( module->loaded == false );\n     D_ASSERT( module->disabled == false );\n\n     module->handle = open_module( module );\n     if (module->handle)\n          module->loaded = true;\n\n     return module->loaded;\n}\n\nstatic void\nunload_module( DirectModuleEntry *module )\n{\n     void *handle;\n\n     D_MAGIC_ASSERT( module, DirectModuleEntry );\n\n     D_DEBUG_AT( Direct_Modules, \"%s( %p '%s', %d refs )\\n\", __FUNCTION__, module, module->file, module->refs );\n\n     D_ASSERT( module->dynamic == true );\n     D_ASSERT( module->loaded == true );\n\n     D_ASSUME( module->handle != NULL );\n\n     handle = module->handle;\n\n     if (handle) {\n          module->handle = NULL;\n          module->loaded = false;\n\n          dlclose( handle );\n     }\n}\n\nstatic void *\nopen_module( DirectModuleEntry *module )\n{\n     DirectModuleDir *directory;\n     const char      *pathfront = \"\";\n     const char      *path;\n     char            *buf;\n     void            *handle;\n\n     D_MAGIC_ASSERT( module, DirectModuleEntry );\n\n     D_DEBUG_AT( Direct_Modules, \"%s( %p '%s', %d refs )\\n\", __FUNCTION__, module, module->file, module->refs );\n\n     D_ASSERT( module->file != NULL );\n     D_ASSERT( module->directory != NULL );\n     D_ASSERT( module->directory->path != NULL );\n\n     directory = module->directory;\n     path      = directory->path;\n\n     if (path[0] != '/') {\n          pathfront = direct_config->module_dir;\n          if (!pathfront)\n               pathfront = MODULEDIR;\n     }\n\n     buf = alloca( strlen( pathfront ) + 1 + strlen( path ) + 1 + strlen( module->file ) + 1 );\n     sprintf( buf, \"%s/%s/%s\", pathfront, path, module->file );\n\n     D_DEBUG_AT( Direct_Modules, \"Loading '%s'...\\n\", buf );\n\n     handle = dlopen( buf, RTLD_NOW );\n\n     D_DEBUG_AT( Direct_Modules, \"  -> dlopen() returned %p\\n\", handle );\n\n     if (!handle)\n          D_DLERROR( \"Direct/Modules: Unable to dlopen '%s'!\\n\", buf );\n\n     return handle;\n}\n\n#endif /* DIRECT_BUILD_DYNLOAD */\n"
  },
  {
    "path": "lib/direct/modules.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__MODULES_H__\n#define __DIRECT__MODULES_H__\n\n#include <direct/types.h>\n#include <direct/list.h>\n\n/**********************************************************************************************************************/\n\nstruct __D_DirectModuleEntry {\n     DirectLink       link;\n\n     int              magic;\n\n     DirectModuleDir *directory;\n\n     bool             loaded;\n     bool             dynamic;\n     bool             disabled;\n\n     char            *name;\n     const void      *funcs;\n\n     int              refs;\n     char            *file;\n     void            *handle;\n};\n\nstruct __D_DirectModuleDir {\n     const char        *path;\n     unsigned int       abi_version;\n\n     DirectLink        *entries;\n\n     DirectModuleEntry *loading;\n};\n\n#define DECLARE_MODULE_DIRECTORY(d)    \\\n     extern DirectModuleDir d\n\n#define DEFINE_MODULE_DIRECTORY(d,p,n) \\\n     DirectModuleDir d = {             \\\n          p,                           \\\n          n,                           \\\n          NULL,                        \\\n          NULL,                        \\\n     }\n\n/**********************************************************************************************************************/\n\nvoid       DIRECT_API  direct_modules_register         ( DirectModuleDir   *directory,\n                                                         unsigned int       abi_version,\n                                                         const char        *name,\n                                                         const void        *funcs );\n\nvoid       DIRECT_API  direct_modules_unregister       ( DirectModuleDir   *directory,\n                                                         const char        *name );\n\nint        DIRECT_API  direct_modules_explore_directory( DirectModuleDir   *directory );\n\nconst void DIRECT_API *direct_module_ref               ( DirectModuleEntry *module );\n\nvoid       DIRECT_API  direct_module_unref             ( DirectModuleEntry *module );\n\n#endif\n"
  },
  {
    "path": "lib/direct/mutex.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__MUTEX_H__\n#define __DIRECT__MUTEX_H__\n\n#include <direct/os/mutex.h>\n\n/**********************************************************************************************************************/\n\n#endif\n"
  },
  {
    "path": "lib/direct/os/clock.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__CLOCK_H__\n#define __DIRECT__OS__CLOCK_H__\n\n#include <direct/os/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     DIRECT_CLOCK_SESSION            = 0x53551011, /* Derived from monotonic clock. */\n\n     DIRECT_CLOCK_REALTIME           = 0x00000000,\n     DIRECT_CLOCK_MONOTONIC          = 0x00000001,\n     DIRECT_CLOCK_PROCESS_CPUTIME_ID = 0x00000002,\n     DIRECT_CLOCK_THREAD_CPUTIME_ID  = 0x00000003\n} DirectClockType;\n\nlong long    DIRECT_API direct_clock_get_time  ( DirectClockType type );\n\nDirectResult DIRECT_API direct_clock_set_time  ( DirectClockType type,\n                                                 long long       micros );\n\nlong long    DIRECT_API direct_clock_resolution( DirectClockType type );\n\n#endif\n"
  },
  {
    "path": "lib/direct/os/filesystem.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__FILESYSTEM_H__\n#define __DIRECT__OS__FILESYSTEM_H__\n\n#include <direct/os/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     char name[256];\n} DirectEntry;\n\ntypedef enum {\n     DFP_NONE  = 0x00000000,\n\n     DFP_READ  = 0x00000001,\n     DFP_WRITE = 0x00000002,\n\n     DFP_ALL   = 0x00000003\n} DirectFilePermission;\n\ntypedef enum {\n     DFIF_NONE = 0x00000000,\n\n     DFIF_SIZE = 0x00000001,\n\n     DFIF_ALL  = 0x00000001\n} DirectFileInfoFlags;\n\ntypedef struct {\n     DirectFileInfoFlags flags;\n\n     size_t              size;\n} DirectFileInfo;\n\n#define R_OK 4\n#define W_OK 2\n#define F_OK 0\n\n/**********************************************************************************************************************/\n\nDirectResult DIRECT_API direct_dir_get_current( char                  *buf,\n                                                size_t                 length );\n\nDirectResult DIRECT_API direct_dir_change     ( const char            *name );\n\nDirectResult DIRECT_API direct_dir_create     ( const char            *name,\n                                                mode_t                 mode );\n\nDirectResult DIRECT_API direct_dir_open       ( DirectDir             *dir,\n                                                const char            *name );\n\nDirectResult DIRECT_API direct_dir_read       ( DirectDir             *dir,\n                                                DirectEntry           *entry );\n\nDirectResult DIRECT_API direct_dir_rewind     ( DirectDir             *dir );\n\nDirectResult DIRECT_API direct_dir_close      ( DirectDir             *dir );\n\nDirectResult DIRECT_API direct_dir_remove     ( const char            *name );\n\nDirectResult DIRECT_API direct_file_open      ( DirectFile            *file,\n                                                const char            *name,\n                                                int                    flags,\n                                                mode_t                 mode );\n\nDirectResult DIRECT_API direct_file_read      ( DirectFile            *file,\n                                                void                  *buffer,\n                                                size_t                 bytes,\n                                                size_t                *ret_bytes );\n\nDirectResult DIRECT_API direct_file_write     ( DirectFile            *file,\n                                                const void            *buffer,\n                                                size_t                 bytes,\n                                                size_t                *ret_bytes );\n\nDirectResult DIRECT_API direct_file_seek      ( DirectFile            *file,\n                                                off_t                  offset );\n\nDirectResult DIRECT_API direct_file_seek_to   ( DirectFile            *file,\n                                                off_t                  offset );\n\nDirectResult DIRECT_API direct_file_close     ( DirectFile            *file );\n\nDirectResult DIRECT_API direct_file_map       ( DirectFile            *file,\n                                                void                  *addr,\n                                                size_t                 offset,\n                                                size_t                 bytes,\n                                                DirectFilePermission   perms,\n                                                void                 **ret_addr );\n\nDirectResult DIRECT_API direct_file_unmap     ( void                  *addr,\n                                                size_t                 bytes );\n\nDirectResult DIRECT_API direct_file_get_info  ( DirectFile            *file,\n                                                DirectFileInfo        *ret_info );\n\nDirectResult DIRECT_API direct_file_chmod     ( DirectFile            *file,\n                                                mode_t                 mode );\n\nDirectResult DIRECT_API direct_file_chown     ( DirectFile            *file,\n                                                uid_t                  owner,\n                                                gid_t                  group );\n\nDirectResult DIRECT_API direct_file_truncate  ( DirectFile            *file,\n                                                off_t                  length );\n\nDirectResult DIRECT_API direct_file_get_string( DirectFile            *file,\n                                                char                  *buf,\n                                                size_t                 length );\n\nDirectResult DIRECT_API direct_popen          ( DirectFile            *file,\n                                                const char            *name,\n                                                int                    flags );\n\nDirectResult DIRECT_API direct_pclose         ( DirectFile            *file );\n\nDirectResult DIRECT_API direct_access         ( const char            *name,\n                                                int                    flags );\n\nDirectResult DIRECT_API direct_chmod          ( const char            *name,\n                                                mode_t                 mode );\n\nDirectResult DIRECT_API direct_chown          ( const char            *name,\n                                                uid_t                  owner,\n                                                gid_t                  group );\n\nDirectResult DIRECT_API direct_readlink       ( const char            *name,\n                                                char                  *buf,\n                                                size_t                 length,\n                                                ssize_t               *ret_length );\n\nDirectResult DIRECT_API direct_unlink         ( const char            *name );\n\nDirectResult DIRECT_API direct_filesystem_size( const char            *name,\n                                                size_t                *size );\n\n#endif\n"
  },
  {
    "path": "lib/direct/os/linux/clock.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/os/clock.h>\n#include <direct/messages.h>\n#include <direct/util.h>\n\n/**********************************************************************************************************************/\n\nstatic long long session_clock_offset;\n\n/**********************************************************************************************************************/\n\n__attribute__((no_instrument_function))\nlong long\ndirect_clock_get_time( DirectClockType type )\n{\n     long long       micros;\n     struct timespec spec;\n     clockid_t       clock_id;\n\n     switch (type) {\n          case DIRECT_CLOCK_REALTIME:\n               clock_id = CLOCK_REALTIME;\n               break;\n\n          case DIRECT_CLOCK_SESSION:\n          case DIRECT_CLOCK_MONOTONIC:\n               clock_id = CLOCK_MONOTONIC;\n               break;\n\n          case DIRECT_CLOCK_PROCESS_CPUTIME_ID:\n               clock_id = CLOCK_PROCESS_CPUTIME_ID;\n               break;\n\n          case DIRECT_CLOCK_THREAD_CPUTIME_ID:\n               clock_id = CLOCK_THREAD_CPUTIME_ID;\n               break;\n\n          default:\n               D_BUG( \"invalid clock type %u\", type );\n               return DR_INVARG;\n     }\n\n     if (clock_gettime( clock_id, &spec ) < 0) {\n          if (clock_id != CLOCK_REALTIME) {\n               D_WARN( \"clock with id %d not supported by system\", clock_id );\n               return direct_clock_get_time( DIRECT_CLOCK_REALTIME );\n          }\n\n          D_PERROR( \"Direct/Clock: Could not get real time clock!\\n\" );\n          return 0;\n     }\n\n     micros = spec.tv_sec * 1000000LL + spec.tv_nsec / 1000LL;\n\n     if (type == DIRECT_CLOCK_SESSION)\n          micros -= session_clock_offset;\n\n     return micros;\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_clock_set_time( DirectClockType type,\n                       long long       micros )\n{\n     DirectResult    ret;\n     clockid_t       clock_id;\n     struct timespec spec;\n\n     switch (type) {\n          case DIRECT_CLOCK_SESSION:\n               session_clock_offset = micros;\n               return DR_OK;\n\n          case DIRECT_CLOCK_REALTIME:\n               clock_id = CLOCK_REALTIME;\n               break;\n\n          case DIRECT_CLOCK_MONOTONIC:\n               clock_id = CLOCK_MONOTONIC;\n               break;\n\n          case DIRECT_CLOCK_PROCESS_CPUTIME_ID:\n               clock_id = CLOCK_PROCESS_CPUTIME_ID;\n               break;\n\n          case DIRECT_CLOCK_THREAD_CPUTIME_ID:\n               clock_id = CLOCK_THREAD_CPUTIME_ID;\n               break;\n\n          default:\n               D_BUG( \"invalid clock type %u\", type );\n               return DR_INVARG;\n     }\n\n     spec.tv_sec  = micros / 1000000LL;\n     spec.tv_nsec = micros % 1000000LL * 1000LL;\n\n     if (clock_settime( clock_id, &spec ) < 0) {\n          ret = errno2result( errno );\n          D_PERROR( \"Direct/Clock: Could not set clock with id %d!\\n\", clock_id );\n          return ret;\n     }\n\n     return DR_OK;\n}\n\n__attribute__((no_instrument_function))\nlong long\ndirect_clock_resolution( DirectClockType type )\n{\n     struct timespec spec;\n     clockid_t       clock_id;\n\n     switch (type) {\n          case DIRECT_CLOCK_SESSION:\n          case DIRECT_CLOCK_REALTIME:\n               clock_id = CLOCK_REALTIME;\n               break;\n\n          case DIRECT_CLOCK_MONOTONIC:\n               clock_id = CLOCK_MONOTONIC;\n               break;\n\n          case DIRECT_CLOCK_PROCESS_CPUTIME_ID:\n               clock_id = CLOCK_PROCESS_CPUTIME_ID;\n               break;\n\n          case DIRECT_CLOCK_THREAD_CPUTIME_ID:\n               clock_id = CLOCK_THREAD_CPUTIME_ID;\n               break;\n\n          default:\n               D_BUG( \"invalid clock type %u\", type );\n               return DR_INVARG;\n     }\n\n     if (clock_getres( clock_id, &spec ) < 0) {\n          if (clock_id != CLOCK_REALTIME) {\n               D_WARN( \"clock with id %d not supported by system\", clock_id );\n               return direct_clock_resolution( DIRECT_CLOCK_REALTIME );\n          }\n\n          D_PERROR( \"Direct/Clock: Could not get real time clock resolution!\\n\" );\n          return 0;\n     }\n\n     return spec.tv_sec * 1000000LL + spec.tv_nsec / 1000LL;\n}\n"
  },
  {
    "path": "lib/direct/os/linux/filesystem.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/debug.h>\n#include <direct/os/filesystem.h>\n#include <direct/messages.h>\n#include <direct/util.h>\n\n/**********************************************************************************************************************/\n\nDirectResult\ndirect_dir_get_current( char   *buf,\n                        size_t  length )\n{\n     D_ASSERT( buf != NULL );\n\n     if (!getcwd( buf, length ))\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_dir_change( const char *name )\n{\n     D_ASSERT( name != NULL );\n\n     if (chdir( name ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_dir_create( const char *name,\n                   mode_t      mode )\n{\n     D_ASSERT( name != NULL );\n\n     if (mkdir( name, mode ) < 0) {\n          if (errno == EEXIST)\n               return DR_BUSY;\n          else\n               return errno2result( errno );\n     }\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_dir_open( DirectDir  *dir,\n                 const char *name )\n{\n     D_ASSERT( dir != NULL );\n     D_ASSERT( name != NULL );\n\n     dir->dir = opendir( name );\n     if (!dir->dir)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_dir_read( DirectDir   *dir,\n                 DirectEntry *entry )\n{\n     struct dirent *ent;\n\n     D_ASSERT( dir != NULL );\n     D_ASSERT( entry != NULL );\n\n     ent = readdir( dir->dir );\n     if (!ent)\n          return errno ? errno2result( errno ) : DR_ITEMNOTFOUND;\n     else\n          strcpy( entry->name, ent->d_name );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_dir_rewind( DirectDir *dir )\n{\n     D_ASSERT( dir != NULL );\n\n     rewinddir( dir->dir );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_dir_close( DirectDir *dir )\n{\n     int err;\n\n     D_ASSERT( dir != NULL );\n\n     err = closedir( dir->dir );\n\n     dir->dir = NULL;\n\n     if (err < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_dir_remove( const char *name )\n{\n     D_ASSERT( name != NULL );\n\n     if (rmdir( name ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_open( DirectFile *file,\n                  const char *name,\n                  int         flags,\n                  mode_t      mode )\n{\n     D_ASSERT( file != NULL );\n     D_ASSERT( name != NULL );\n\n     file->file = NULL;\n\n     file->fd = open( name, flags, mode );\n     if (file->fd < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_read( DirectFile *file,\n                  void       *buffer,\n                  size_t      bytes,\n                  size_t     *ret_bytes )\n{\n     ssize_t num;\n\n     D_ASSERT( file != NULL );\n     D_ASSERT( buffer != NULL );\n\n     num = read( file->fd, buffer, bytes );\n     if (num < 0)\n          return errno2result( errno );\n\n     if (ret_bytes)\n          *ret_bytes = num;\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_write( DirectFile *file,\n                   const void *buffer,\n                   size_t      bytes,\n                   size_t     *ret_bytes )\n{\n     ssize_t num;\n\n     D_ASSERT( file != NULL );\n     D_ASSERT( buffer != NULL );\n\n     num = write( file->fd, buffer, bytes );\n     if (num < 0)\n          return errno2result( errno );\n\n     if (ret_bytes)\n          *ret_bytes = num;\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_seek( DirectFile *file,\n                  off_t       offset )\n{\n     D_ASSERT( file != NULL );\n\n     if (lseek( file->fd, offset, SEEK_CUR ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_seek_to( DirectFile *file,\n                     off_t       offset )\n{\n     D_ASSERT( file != NULL );\n\n     if (lseek( file->fd, offset, SEEK_SET ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_close( DirectFile *file )\n{\n     int err;\n\n     D_ASSERT( file != NULL );\n\n     if (file->file) {\n          err = fclose( file->file );\n\n          file->file = NULL;\n     }\n     else\n          err = close( file->fd );\n\n     file->fd = -1;\n\n     if (err < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_map( DirectFile            *file,\n                 void                  *addr,\n                 size_t                 offset,\n                 size_t                 bytes,\n                 DirectFilePermission   perms,\n                 void                 **ret_addr )\n{\n     void *map;\n     int   prot = 0;\n     int   flags = MAP_SHARED;\n\n     D_ASSERT( file != NULL );\n     D_ASSERT( ret_addr != NULL );\n\n     if (perms & DFP_READ)\n          prot |= PROT_READ;\n\n     if (perms & DFP_WRITE)\n          prot |= PROT_WRITE;\n\n     if (addr)\n          flags |= MAP_FIXED;\n\n     map = mmap( addr, bytes, prot, flags, file->fd, offset );\n     if (map == MAP_FAILED)\n          return errno2result( errno );\n\n     *ret_addr = map;\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_unmap( void   *addr,\n                   size_t  bytes )\n{\n     if (munmap( addr, bytes ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_get_info( DirectFile     *file,\n                      DirectFileInfo *ret_info )\n{\n     struct stat st;\n\n     D_ASSERT( file != NULL );\n     D_ASSERT( ret_info != NULL );\n\n     if (fstat( file->fd, &st ) < 0)\n          return errno2result( errno );\n\n     ret_info->flags = DFIF_SIZE;\n     ret_info->size  = st.st_size;\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_chmod( DirectFile *file,\n                   mode_t      mode )\n{\n     D_ASSERT( file != NULL );\n\n     if (fchmod( file->fd, mode ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_chown( DirectFile *file,\n                   uid_t       owner,\n                   gid_t       group )\n{\n     D_ASSERT( file != NULL );\n\n     if (fchown( file->fd, owner, group ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_truncate( DirectFile *file,\n                      off_t       length )\n{\n     D_ASSERT( file != NULL );\n\n     if (ftruncate( file->fd, length ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_get_string( DirectFile *file,\n                        char       *buf,\n                        size_t      length )\n{\n     D_ASSERT( file != NULL );\n     D_ASSERT( buf != NULL );\n\n     if (!file->file) {\n          file->file = fdopen( file->fd, \"r\" );\n          if (!file->file)\n               return errno2result( errno );\n     }\n\n     if (!fgets( buf, length, file->file )) {\n          if (feof( file->file ))\n               return DR_EOF;\n\n          return DR_FAILURE;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_popen( DirectFile *file,\n              const char *name,\n              int         flags )\n{\n     D_ASSERT( file != NULL );\n     D_ASSERT( name != NULL );\n\n     file->file = popen( name, (flags & O_WRONLY) ? \"w\" : (flags & O_RDWR) ? \"rw\" : \"r\" );\n     if (!file->file)\n          return errno2result( errno );\n\n     file->fd = fileno( file->file );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_pclose( DirectFile *file )\n{\n     D_ASSERT( file != NULL );\n     D_ASSERT( file->file != NULL );\n\n     if (pclose( file->file ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_access( const char *name,\n               int         flags )\n{\n     D_ASSERT( name != NULL );\n\n     if (access( name, flags ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_chmod( const char *name,\n              mode_t      mode )\n{\n     D_ASSERT( name != NULL );\n\n     if (chmod( name, mode ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_chown( const char *name,\n              uid_t       owner,\n              gid_t       group )\n{\n     D_ASSERT( name != NULL );\n\n     if (chown( name, owner, group ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_readlink( const char *name,\n                 char       *buf,\n                 size_t      length,\n                 ssize_t    *ret_length )\n{\n     ssize_t len;\n\n     D_ASSERT( name != NULL );\n\n     len = readlink( name, buf, length );\n     if (len < 0)\n          return errno2result( errno );\n\n     if (ret_length)\n          *ret_length = len;\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_unlink( const char *name )\n{\n     D_ASSERT( name != NULL );\n\n     if (unlink( name ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_filesystem_size( const char *name,\n                        size_t     *size )\n{\n     struct statfs stat;\n\n     D_ASSERT( name != NULL );\n\n     if (statfs( name, &stat ) < 0)\n          return errno2result( errno );\n\n     *size = stat.f_blocks * stat.f_bsize;\n\n     return DR_OK;\n}\n"
  },
  {
    "path": "lib/direct/os/linux/filesystem.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__LINUX__FILESYSTEM_H__\n#define __DIRECT__OS__LINUX__FILESYSTEM_H__\n\n#include <direct/os/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     DIR *dir;\n} DirectDir;\n\ntypedef struct {\n     int   fd;\n\n     FILE *file;\n} DirectFile;\n\n#endif\n"
  },
  {
    "path": "lib/direct/os/linux/log.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/build.h>\n#if DIRECT_BUILD_NETWORK\n#define _GNU_SOURCE /* To get EAI_ADDRFAMILY and EAI_NODATA definition. */\n#endif /* DIRECT_BUILD_NETWORK */\n\n#include <direct/os/log.h>\n#include <direct/messages.h>\n#include <direct/util.h>\n\n/**********************************************************************************************************************/\n\nstatic DirectResult init_stderr( DirectLog *log );\n\nstatic DirectResult init_file  ( DirectLog  *log, const char *filename );\n\nstatic DirectResult init_udp   ( DirectLog  *log, const char *hostport );\n\n/**********************************************************************************************************************/\n\nDirectResult\ndirect_log_init( DirectLog  *log,\n                 const char *param )\n{\n     switch (log->type) {\n          case DLT_STDERR:\n               return init_stderr( log );\n\n          case DLT_FILE:\n               return init_file( log, param );\n\n          case DLT_UDP:\n               return init_udp( log, param );\n\n          default:\n               break;\n     }\n\n     return DR_UNSUPPORTED;\n}\n\nDirectResult\ndirect_log_deinit( DirectLog *log )\n{\n     close( (long) log->data );\n\n     return DR_OK;\n}\n\n/**********************************************************************************************************************/\n\n__attribute__((no_instrument_function))\nstatic DirectResult\ncommon_log_write( DirectLog  *log,\n                  const char *buffer,\n                  size_t      bytes )\n{\n     ssize_t sz;\n\n     sz = write( (long) log->data, buffer, bytes );\n     if (sz < 0)\n          D_PERROR( \"Direct/Log: Could not write to log!\\n\" );\n\n     return DR_OK;\n}\n\n__attribute__((no_instrument_function))\nstatic DirectResult\ncommon_log_flush( DirectLog *log )\n{\n     if (log->type == DLT_STDERR && fflush( stderr ))\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\n__attribute__((no_instrument_function))\nstatic DirectResult\nstderr_log_write( DirectLog  *log,\n                  const char *buffer,\n                  size_t      bytes )\n{\n     fwrite( buffer, bytes, 1, stderr );\n\n     return DR_OK;\n}\n\nstatic DirectResult\ninit_stderr( DirectLog *log )\n{\n     log->data = (void*)(long) dup( fileno( stderr ) );\n\n     log->write      = stderr_log_write;\n     log->flush      = common_log_flush;\n\n     return DR_OK;\n}\n\nstatic DirectResult\ninit_file( DirectLog  *log,\n           const char *filename )\n{\n     DirectResult ret;\n     int          fd;\n\n     fd = open( filename, O_WRONLY | O_CREAT | O_APPEND, 0664 );\n     if (fd < 0) {\n          ret = errno2result( errno );\n          D_PERROR( \"Direct/Log: Could not open '%s' for writing!\\n\", filename );\n          return ret;\n     }\n\n     log->data = (void*)(long) fd;\n\n     log->write = common_log_write;\n     log->flush = common_log_flush;\n\n     return DR_OK;\n}\n\n#if DIRECT_BUILD_NETWORK\n\nstatic DirectResult\nparse_host_addr( const char       *hostport,\n                 struct addrinfo **ret_addr )\n{\n     int              err, i;\n     int              size = strlen( hostport ) + 1;\n     char             buf[size];\n     char            *hoststr = buf;\n     char            *portstr = NULL;\n     char            *end;\n     struct addrinfo  hints;\n\n     memcpy( buf, hostport, size );\n\n     for (i = 0; i < size; i++) {\n          if (buf[i] == ':') {\n               buf[i]  = 0;\n               portstr = &buf[i+1];\n               break;\n          }\n     }\n\n     if (!portstr) {\n          D_ERROR( \"Direct/Log: Parse error in '%s' that should be '<host>:<port>'!\\n\", hostport );\n          return DR_INVARG;\n     }\n\n     strtoul( portstr, &end, 10 );\n\n     if (end && *end) {\n          D_ERROR( \"Direct/Log: Parse error in port number '%s'!\\n\", portstr );\n          return DR_INVARG;\n     }\n\n     memset( &hints, 0, sizeof(hints) );\n     hints.ai_socktype = SOCK_DGRAM;\n     hints.ai_family   = PF_UNSPEC;\n\n     err = getaddrinfo( hoststr, portstr, &hints, ret_addr );\n     if (err) {\n          switch (err) {\n               case EAI_FAMILY:\n                    D_ERROR( \"Direct/Log: Unsupported address family!\\n\" );\n                    return DR_UNSUPPORTED;\n\n               case EAI_SOCKTYPE:\n                    D_ERROR( \"Direct/Log: Unsupported socket type!\\n\" );\n                    return DR_UNSUPPORTED;\n\n               case EAI_NONAME:\n                    D_ERROR( \"Direct/Log: Host not found!\\n\" );\n                    return DR_FAILURE;\n\n               case EAI_SERVICE:\n                    D_ERROR( \"Direct/Log: Port %s is unreachable!\\n\", portstr );\n                    return DR_FAILURE;\n\n               case EAI_ADDRFAMILY:\n               case EAI_NODATA:\n                    D_ERROR( \"Direct/Log: Host found, but has no address!\\n\" );\n                    return DR_FAILURE;\n\n               case EAI_MEMORY:\n                    return D_OOM();\n\n               case EAI_FAIL:\n                    D_ERROR( \"Direct/Log: A non-recoverable name server error occurred!\\n\" );\n                    return DR_FAILURE;\n\n               case EAI_AGAIN:\n                    D_ERROR( \"Direct/Log: Temporary error, try again!\\n\" );\n                    return DR_TEMPUNAVAIL;\n\n               default:\n                    D_ERROR( \"Direct/Log: Unknown error occurred!\\n\" );\n                    return DR_FAILURE;\n          }\n     }\n\n     return DR_OK;\n}\n\nstatic DirectResult\ninit_udp( DirectLog  *log,\n          const char *hostport )\n{\n     DirectResult     ret;\n     int              fd;\n     struct addrinfo *addr;\n\n     ret = parse_host_addr( hostport, &addr );\n     if (ret)\n          return ret;\n\n     fd = socket( addr->ai_family, SOCK_DGRAM, 0 );\n     if (fd < 0) {\n          ret = errno2result( errno );\n          D_PERROR( \"Direct/Log: Could not create a UDP socket!\\n\" );\n          freeaddrinfo( addr );\n          return ret;\n     }\n\n     ret = connect( fd, addr->ai_addr, addr->ai_addrlen );\n     if (ret) {\n          ret = errno2result( errno );\n          D_PERROR( \"Direct/Log: Could not connect UDP socket to '%s'!\\n\", hostport );\n          freeaddrinfo( addr );\n          close( fd );\n          return ret;\n     }\n\n     freeaddrinfo( addr );\n\n     log->data = (void*)(long) fd;\n\n     log->write = common_log_write;\n     log->flush = common_log_flush;\n\n     return DR_OK;\n}\n\n#else /* DIRECT_BUILD_NETWORK */\n\nstatic DirectResult\ninit_udp( DirectLog  *log,\n          const char *hostport )\n{\n     return DR_UNSUPPORTED;\n}\n\n#endif /* DIRECT_BUILD_NETWORK */\n"
  },
  {
    "path": "lib/direct/os/linux/mem.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/os/mem.h>\n\n#if DIRECT_BUILD_SENTINELS\n\n#include <direct/debug.h>\n\nD_DEBUG_DOMAIN( Direct_Sentinels, \"Direct/Sentinels\", \"Direct Sentinels\" );\n\n#endif /* DIRECT_BUILD_SENTINELS */\n\n/**********************************************************************************************************************/\n\n#if DIRECT_BUILD_SENTINELS\n\n#define PREFIX_SENTINEL 8\n#define SUFFIX_SENTINEL 8\n\n#define TOTAL_SENTINEL  ((PREFIX_SENTINEL) + (SUFFIX_SENTINEL))\n\n__attribute__((no_instrument_function))\nstatic inline void\ninstall_sentinels( void *p, size_t size )\n{\n     size_t  i;\n     size_t *ps     = p;\n     u8     *prefix = p;\n     u8     *suffix = p + PREFIX_SENTINEL + size;\n\n     D_DEBUG_AT( Direct_Sentinels, \"%s( %p, \"_ZU\" )\\n\", __FUNCTION__, p, size );\n\n     *ps = size;\n\n     for (i = sizeof(size_t); i < PREFIX_SENTINEL; i++)\n          prefix[i] = i;\n\n     for (i = 0; i < SUFFIX_SENTINEL; i++)\n          suffix[i] = i;\n}\n\n__attribute__((no_instrument_function))\nstatic inline void\nremove_sentinels( void *p )\n{\n     size_t  i;\n     size_t *ps     = p;\n     u8     *prefix = p;\n     u8     *suffix = p + PREFIX_SENTINEL + *ps;\n\n     D_DEBUG_AT( Direct_Sentinels, \"%s( %p )\\n\", __FUNCTION__, p );\n\n     for (i = sizeof(size_t); i < PREFIX_SENTINEL; i++)\n          prefix[i] = 0;\n\n     for (i = 0; i < SUFFIX_SENTINEL; i++)\n          suffix[i] = 0;\n}\n\n__attribute__((no_instrument_function))\nstatic inline void\ncheck_sentinels( void *p )\n{\n     size_t  i;\n     size_t *ps     = p;\n     u8     *prefix = p;\n     u8     *suffix = p + PREFIX_SENTINEL + *ps;\n\n     for (i = sizeof(size_t); i < PREFIX_SENTINEL; i++) {\n          if (prefix[i] != i)\n               D_DEBUG_AT( Direct_Sentinels, \"Sentinel error at prefix[\"_ZU\"] (%u) of \"_ZU\" bytes allocation!\\n\",\n                           i, prefix[i], *ps );\n     }\n\n     for (i = 0; i < SUFFIX_SENTINEL; i++) {\n          if (suffix[i] != i)\n               D_DEBUG_AT( Direct_Sentinels, \"Sentinel error at suffix[\"_ZU\"] (%u) of \"_ZU\" bytes allocation!\\n\",\n                           i, suffix[i], *ps );\n     }\n}\n\n__attribute__((no_instrument_function))\nvoid *\ndirect_malloc( size_t bytes )\n{\n     void *p = bytes ? malloc( bytes + TOTAL_SENTINEL ) : NULL;\n\n     if (!p)\n          return NULL;\n\n     install_sentinels( p, bytes );\n\n     return p + PREFIX_SENTINEL;\n}\n\n__attribute__((no_instrument_function))\nvoid *\ndirect_calloc( size_t count, size_t bytes)\n{\n     void *p = (count && bytes) ? calloc( 1, count * bytes + TOTAL_SENTINEL ) : NULL;\n\n     if (!p)\n          return NULL;\n\n     install_sentinels( p, count * bytes );\n\n     return p + PREFIX_SENTINEL;\n}\n\n__attribute__((no_instrument_function))\nvoid *\ndirect_realloc( void *mem, size_t bytes )\n{\n     void *p = mem ? mem - PREFIX_SENTINEL : NULL;\n\n     if (!mem)\n          return direct_malloc( bytes );\n\n     check_sentinels( p );\n\n     if (!bytes) {\n          direct_free( mem );\n          return NULL;\n     }\n\n     p = realloc( p, bytes + TOTAL_SENTINEL );\n\n     if (!p)\n          return NULL;\n\n     install_sentinels( p, bytes );\n\n     return p + PREFIX_SENTINEL;\n}\n\n__attribute__((no_instrument_function))\nchar *\ndirect_strdup( const char *str )\n{\n     int   n = strlen( str );\n     void *p = malloc( n+1 + TOTAL_SENTINEL );\n\n     if (!p)\n          return NULL;\n\n     memcpy( p + PREFIX_SENTINEL, str, n + 1 );\n\n     install_sentinels( p, n + 1 );\n\n     return p + PREFIX_SENTINEL;\n}\n\n__attribute__((no_instrument_function))\nvoid\ndirect_free( void *mem )\n{\n     void *p = mem ? mem - PREFIX_SENTINEL : NULL;\n\n     if (p) {\n          check_sentinels( p );\n\n          remove_sentinels( p );\n\n          free( p );\n     }\n}\n\n#else /* DIRECT_BUILD_SENTINELS */\n\n__attribute__((no_instrument_function))\nvoid *\ndirect_malloc( size_t bytes )\n{\n     return malloc( bytes );\n}\n\n__attribute__((no_instrument_function))\nvoid *\ndirect_calloc( size_t count, size_t bytes)\n{\n     return calloc( count, bytes );\n}\n\n__attribute__((no_instrument_function))\nvoid *\ndirect_realloc( void *mem, size_t bytes )\n{\n     return realloc( mem, bytes );\n}\n\n__attribute__((no_instrument_function))\nchar *\ndirect_strdup( const char *str )\n{\n     return strdup( str );\n}\n\n__attribute__((no_instrument_function))\nvoid\ndirect_free( void *mem )\n{\n     free( mem );\n}\n\n#endif /* DIRECT_BUILD_SENTINELS */\n"
  },
  {
    "path": "lib/direct/os/linux/mutex.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/messages.h>\n#include <direct/os/mutex.h>\n#include <direct/util.h>\n\n/**********************************************************************************************************************/\n\nDirectResult\ndirect_mutex_init( DirectMutex *mutex )\n{\n     int erno = pthread_mutex_init( &mutex->lock, NULL );\n\n     return errno2result( erno );\n}\n\nDirectResult\ndirect_recursive_mutex_init( DirectMutex *mutex )\n{\n     DirectResult        ret = DR_OK;\n     int                 erno;\n     pthread_mutexattr_t attr;\n\n     pthread_mutexattr_init( &attr );\n     pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );\n     erno = pthread_mutex_init( &mutex->lock, &attr );\n     if (erno) {\n          ret = errno2result( erno );\n          D_PERROR( \"Direct/Mutex: Could not initialize recursive mutex!\\n\" );\n     }\n\n     pthread_mutexattr_destroy( &attr );\n\n     return ret;\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_mutex_lock( DirectMutex *mutex )\n{\n     int erno = pthread_mutex_lock( &mutex->lock );\n\n     return errno2result( erno );\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_mutex_unlock( DirectMutex *mutex )\n{\n     int erno = pthread_mutex_unlock( &mutex->lock );\n\n     return errno2result( erno );\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_mutex_trylock( DirectMutex *mutex )\n{\n     int erno = pthread_mutex_trylock( &mutex->lock );\n\n     return errno2result( erno );\n}\n\nDirectResult\ndirect_mutex_deinit( DirectMutex *mutex )\n{\n     int erno = pthread_mutex_destroy( &mutex->lock );\n\n     return errno2result( erno );\n}\n\nDirectResult\ndirect_rwlock_init( DirectRWLock *rwlock )\n{\n     int erno = pthread_rwlock_init( &rwlock->lock, NULL );\n\n     return errno2result( erno );\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_rwlock_rdlock( DirectRWLock *rwlock )\n{\n     int erno = pthread_rwlock_rdlock( &rwlock->lock );\n\n     return errno2result( erno );\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_rwlock_wrlock( DirectRWLock *rwlock )\n{\n     int erno = pthread_rwlock_wrlock( &rwlock->lock );\n\n     return errno2result( erno );\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_rwlock_unlock( DirectRWLock *rwlock )\n{\n     int erno = pthread_rwlock_unlock( &rwlock->lock );\n\n     return errno2result( erno );\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_rwlock_trywrlock( DirectRWLock *rwlock )\n{\n     int erno = pthread_rwlock_trywrlock( &rwlock->lock );\n\n     return errno2result( erno );\n}\n\nDirectResult\ndirect_rwlock_deinit( DirectRWLock *rwlock )\n{\n     int erno = pthread_rwlock_destroy( &rwlock->lock );\n\n     return errno2result( erno );\n}\n"
  },
  {
    "path": "lib/direct/os/linux/mutex.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__LINUX__MUTEX_H__\n#define __DIRECT__OS__LINUX__MUTEX_H__\n\n#include <direct/os/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     pthread_mutex_t lock;\n} DirectMutex;\n\n#define DIRECT_MUTEX_INITIALIZER() { PTHREAD_MUTEX_INITIALIZER }\n\ntypedef struct {\n     pthread_rwlock_t lock;\n} DirectRWLock;\n\n#endif\n"
  },
  {
    "path": "lib/direct/os/linux/signals.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/interface.h>\n#include <direct/list.h>\n#include <direct/os/signals.h>\n#include <direct/system.h>\n#include <direct/thread.h>\n#include <direct/trace.h>\n\nD_DEBUG_DOMAIN( Direct_Signals, \"Direct/Signals\", \"Direct Signals handling\" );\n\n/**********************************************************************************************************************/\n\nstruct __D_DirectSignalHandler {\n     DirectLink               link;\n\n     int                      magic;\n\n     int                      num;\n     DirectSignalHandlerFunc  func;\n     void                    *ctx;\n\n     bool                     removed;\n};\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int              signum;\n     struct sigaction old_action;\n     struct sigaction new_action;\n} SigHandled;\n\nstatic int sigs_to_handle[] = {\n     SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGSEGV, SIGPIPE, SIGTERM, SIGXCPU, SIGXFSZ,\n     SIGSYS\n};\n\n#define NUM_SIGS_TO_HANDLE (D_ARRAY_SIZE(sigs_to_handle))\n\nstatic SigHandled    sigs_handled[NUM_SIGS_TO_HANDLE];\n\nstatic DirectLink   *handlers = NULL;\nstatic DirectMutex   handlers_lock;\n\nstatic DirectThread *sighandler_thread = NULL;\n\nstatic void *handle_signals( DirectThread *thread, void *arg );\n\nstatic void install_handlers( void );\nstatic void remove_handlers ( void );\n\n/**********************************************************************************************************************/\n\nDirectResult\ndirect_signals_initialize()\n{\n     sigset_t mask;\n     int      i;\n\n     D_DEBUG_AT( Direct_Signals, \"%s() initializing...\\n\", __FUNCTION__ );\n\n     direct_recursive_mutex_init( &handlers_lock );\n     if (direct_config->sighandler) {\n          if (direct_config->sighandler_thread) {\n               sigemptyset( &mask );\n               for (i = 0; i < NUM_SIGS_TO_HANDLE; i++)\n                    sigaddset( &mask, sigs_to_handle[i] );\n\n               sigprocmask( SIG_BLOCK, &mask, NULL );\n\n               sighandler_thread = direct_thread_create( DTT_CRITICAL, handle_signals, NULL, \"SigHandler\" );\n\n               D_ASSERT( sighandler_thread != NULL );\n          }\n          else\n               install_handlers();\n     }\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_signals_shutdown()\n{\n     D_DEBUG_AT( Direct_Signals, \"%s() shutting down...\\n\", __FUNCTION__ );\n\n     if (direct_config->sighandler_thread) {\n          if (sighandler_thread) {\n               direct_thread_kill( sighandler_thread, SIGSYS );\n               direct_thread_join( sighandler_thread );\n               direct_thread_destroy( sighandler_thread );\n               sighandler_thread = NULL;\n          }\n     }\n     else\n          remove_handlers();\n\n     direct_mutex_deinit( &handlers_lock );\n\n     return DR_OK;\n}\n\nvoid\ndirect_signals_block_all()\n{\n     sigset_t signals;\n\n     D_DEBUG_AT( Direct_Signals, \"Blocking all signals from now on\\n\" );\n\n     sigfillset( &signals );\n\n     sigprocmask( SIG_BLOCK, &signals, NULL );\n}\n\nDirectResult\ndirect_signal_handler_add( int                       num,\n                           DirectSignalHandlerFunc   func,\n                           void                     *ctx,\n                           DirectSignalHandler     **ret_handler )\n{\n     DirectSignalHandler *handler;\n\n     D_ASSERT( func != NULL );\n     D_ASSERT( ret_handler != NULL );\n\n     D_DEBUG_AT( Direct_Signals, \"Adding handler %p for signal %d with context %p...\\n\", func, num, ctx );\n\n     handler = D_CALLOC( 1, sizeof(DirectSignalHandler) );\n     if (!handler) {\n          return DR_NOLOCALMEMORY;\n     }\n\n     handler->num  = num;\n     handler->func = func;\n     handler->ctx  = ctx;\n\n     D_MAGIC_SET( handler, DirectSignalHandler );\n\n     direct_mutex_lock( &handlers_lock );\n     direct_list_append( &handlers, &handler->link );\n     direct_mutex_unlock( &handlers_lock );\n\n     *ret_handler = handler;\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_signal_handler_remove( DirectSignalHandler *handler )\n{\n     D_MAGIC_ASSERT( handler, DirectSignalHandler );\n\n     D_DEBUG_AT( Direct_Signals, \"Removing handler %p for signal %d with context %p...\\n\",\n                 handler->func, handler->num, handler->ctx );\n\n     /* Mark the handler for removal, freeing will actually come later. */\n     handler->removed = true;\n\n     return DR_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic bool\nshow_segv( const siginfo_t *info )\n{\n     switch (info->si_code) {\n          case SEGV_MAPERR:\n               D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (at %p, invalid address) <--\\n\",\n                      info->si_signo, info->si_addr );\n               return true;\n          case SEGV_ACCERR:\n               D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (at %p, invalid permissions) <--\\n\",\n                      info->si_signo, info->si_addr );\n               return true;\n     }\n     return false;\n}\n\nstatic bool\nshow_bus( const siginfo_t *info )\n{\n     switch (info->si_code) {\n          case BUS_ADRALN:\n               D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (at %p, invalid address alignment) <--\\n\",\n                      info->si_signo, info->si_addr );\n               return true;\n          case BUS_ADRERR:\n               D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (at %p, non-existent physical address) <--\\n\",\n                      info->si_signo, info->si_addr );\n               return true;\n          case BUS_OBJERR:\n               D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (at %p, object specific hardware error) <--\\n\",\n                      info->si_signo, info->si_addr );\n               return true;\n     }\n\n     return false;\n}\n\nstatic bool\nshow_ill( const siginfo_t *info )\n{\n     switch (info->si_code) {\n          case ILL_ILLOPC:\n               D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (at %p, illegal opcode) <--\\n\",\n                      info->si_signo, info->si_addr );\n               return true;\n          case ILL_ILLOPN:\n               D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (at %p, illegal operand) <--\\n\",\n                      info->si_signo, info->si_addr );\n               return true;\n          case ILL_ILLADR:\n               D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (at %p, illegal addressing mode) <--\\n\",\n                      info->si_signo, info->si_addr );\n               return true;\n          case ILL_ILLTRP:\n               D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (at %p, illegal trap) <--\\n\",\n                      info->si_signo, info->si_addr );\n               return true;\n          case ILL_PRVOPC:\n               D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (at %p, privileged opcode) <--\\n\",\n                      info->si_signo, info->si_addr );\n               return true;\n          case ILL_PRVREG:\n               D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (at %p, privileged register) <--\\n\",\n                      info->si_signo, info->si_addr );\n               return true;\n          case ILL_COPROC:\n               D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (at %p, coprocessor error) <--\\n\",\n                      info->si_signo, info->si_addr );\n               return true;\n          case ILL_BADSTK:\n               D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (at %p, internal stack error) <--\\n\",\n                      info->si_signo, info->si_addr );\n               return true;\n     }\n\n     return false;\n}\n\nstatic bool\nshow_fpe( const siginfo_t *info )\n{\n     switch (info->si_code) {\n          case FPE_INTDIV:\n               D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (at %p, integer divide by zero) <--\\n\",\n                      info->si_signo, info->si_addr );\n               return true;\n          case FPE_FLTDIV:\n               D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (at %p, floating point divide by zero) <--\\n\",\n                      info->si_signo, info->si_addr );\n               return true;\n     }\n\n     D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (at %p) <--\\n\", info->si_signo, info->si_addr );\n\n     return true;\n}\n\nstatic bool\nshow_any( const siginfo_t *info )\n{\n     switch (info->si_code) {\n          case SI_USER:\n               D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (sent by pid %d, uid %u) <--\\n\",\n                      info->si_signo, info->si_pid, info->si_uid );\n               return true;\n          case SI_QUEUE:\n               D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (queued by pid %d, uid %u, val %d) <--\\n\",\n                      info->si_signo, info->si_pid, info->si_uid, info->si_int );\n               return true;\n          case SI_KERNEL:\n               D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (sent by the kernel) <--\\n\",\n                      info->si_signo );\n               return true;\n     }\n\n     return false;\n}\n\nstatic void\ncall_handlers( int   num,\n               void *addr )\n{\n     DirectSignalHandler *handler, *temp;\n     DirectLink          *garbage = NULL;\n\n     if (num == SIGPIPE)\n          num = DIRECT_SIGNAL_DUMP_STACK;\n\n     /* Loop through all handlers. */\n     direct_mutex_lock( &handlers_lock );\n\n     direct_list_foreach_safe (handler, temp, handlers) {\n          if (handler->removed) {\n               direct_list_remove( &handlers, &handler->link );\n               direct_list_append( &garbage, &handler->link );\n               continue;\n          }\n\n          D_LOG( Direct_Signals, FATAL, \"  --> %d\\n\", handler->num );\n\n          if (handler->num != num && handler->num != DIRECT_SIGNAL_ANY)\n               continue;\n\n          if (handler->num == DIRECT_SIGNAL_ANY && num == DIRECT_SIGNAL_DUMP_STACK)\n               continue;\n\n          switch (handler->func( num, addr, handler->ctx )) {\n               case DSHR_OK:\n                    break;\n\n               case DSHR_REMOVE:\n                    direct_list_remove( &handlers, &handler->link );\n                    direct_list_append( &garbage, &handler->link );\n                    break;\n\n               case DSHR_RESUME:\n                    D_LOG( Direct_Signals, FATAL, \"    '-> cured!\\n\" );\n                    direct_mutex_unlock( &handlers_lock );\n                    return;\n\n               default:\n                    D_BUG( \"unknown result\" );\n                    break;\n          }\n     }\n\n     direct_list_foreach_safe (handler, temp, handlers) {\n          D_MAGIC_CLEAR( handler );\n          D_FREE( handler );\n     }\n\n     direct_mutex_unlock( &handlers_lock );\n}\n\nstatic void\nsignal_handler( int        num,\n                siginfo_t *info,\n                void      *uctx )\n{\n     void     *addr = NULL;\n     sigset_t  mask;\n\n     if (info && info > (siginfo_t*) 0x100) {\n          bool shown = false;\n\n          /* Kernel generated signal. */\n          if (info->si_code > 0 && info->si_code < 0x80) {\n               addr = info->si_addr;\n\n               switch (num) {\n                    case SIGSEGV:\n                         shown = show_segv( info );\n                         break;\n\n                    case SIGBUS:\n                         shown = show_bus( info );\n                         break;\n\n                    case SIGILL:\n                         shown = show_ill( info );\n                         break;\n\n                    case SIGFPE:\n                         shown = show_fpe( info );\n                         break;\n\n                    default:\n                         D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d <--\\n\", info->si_signo );\n                         addr  = NULL;\n                         shown = true;\n                         break;\n               }\n          }\n          else\n               shown = show_any( info );\n\n          if (!shown)\n               D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d (unknown origin) <--\\n\", info->si_signo );\n     }\n     else\n          D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d, no siginfo available <--\\n\", num );\n\n     direct_trace_print_stacks();\n\n     call_handlers( num, addr );\n\n     sigemptyset( &mask );\n     sigaddset( &mask, num );\n     sigprocmask( SIG_UNBLOCK, &mask, NULL );\n\n     direct_trap( \"SigHandler\", num );\n\n     sigprocmask( SIG_BLOCK, &mask, NULL );\n}\n\n/**********************************************************************************************************************/\n\nstatic void *\nhandle_signals( DirectThread *thread,\n                void         *arg )\n{\n     int       i;\n     int       res;\n     siginfo_t info;\n     sigset_t  mask;\n\n     D_DEBUG_AT( Direct_Signals, \"%s()\\n\", __FUNCTION__ );\n\n     sigemptyset( &mask );\n\n     for (i = 0; i < NUM_SIGS_TO_HANDLE; i++) {\n          if (direct_config->sighandler && !sigismember( &direct_config->dont_catch, sigs_to_handle[i] ))\n               sigaddset( &mask, sigs_to_handle[i] );\n     }\n\n     sigaddset( &mask, SIGSYS );\n     sigaddset( &mask, SIGPIPE );\n\n     sigprocmask( SIG_BLOCK, &mask, NULL );\n\n     while (1) {\n          D_DEBUG_AT( Direct_Signals, \"%s() -> waiting for a signal...\\n\", __FUNCTION__ );\n\n          res = sigwaitinfo( &mask, &info );\n\n          if (res == -1) {\n               D_DEBUG_AT( Direct_Signals, \"%s() -> got error %s\\n\", __FUNCTION__, direct_strerror( errno ) );\n          }\n          else {\n               if (SIGSYS == info.si_signo) {\n                    D_DEBUG_AT( Direct_Signals, \"  -> got close signal %d (me %d, from %d)\\n\", SIGSYS,\n                                direct_getpid(), info.si_pid );\n\n                    if (direct_getpid() == info.si_pid)\n                         break;\n\n                    D_DEBUG_AT( Direct_Signals, \"  -> not stopping signal handler from other process signal\\n\" );\n               }\n               else if (SIGPIPE == info.si_signo) {\n                    D_DEBUG_AT( Direct_Signals, \"  -> got dump signal %d (me %d, from %d)\\n\", SIGPIPE,\n                                direct_getpid(), info.si_pid );\n\n                    direct_trace_print_stacks();\n\n                    direct_print_interface_leaks();\n\n                    direct_print_memleaks();\n\n                    call_handlers( info.si_signo, NULL );\n               }\n               else {\n                    signal_handler( info.si_signo, &info, NULL );\n               }\n          }\n     }\n\n     D_DEBUG_AT( Direct_Signals, \"Returning from signal handler thread\\n\" );\n\n     return NULL;\n}\n\nstatic void\ninstall_handlers()\n{\n     int i;\n\n     D_DEBUG_AT( Direct_Signals, \"%s()\\n\", __FUNCTION__ );\n\n     for (i = 0; i < NUM_SIGS_TO_HANDLE; i++) {\n          sigs_handled[i].signum = -1;\n\n          if (direct_config->sighandler && !sigismember( &direct_config->dont_catch, sigs_to_handle[i] )) {\n               struct sigaction action;\n               int              signum = sigs_to_handle[i];\n\n               action.sa_sigaction = signal_handler;\n               action.sa_flags     = SA_SIGINFO;\n\n               if (signum != SIGSEGV)\n                    action.sa_flags |= SA_NODEFER;\n\n               sigemptyset( &action.sa_mask );\n\n               if (sigaction( signum, &action, &sigs_handled[i].old_action )) {\n                    D_PERROR( \"Direct/Signals: Unable to install signal handler for signal %d!\\n\", signum );\n                    continue;\n               }\n\n               sigs_handled[i].signum = signum;\n          }\n     }\n}\n\nstatic void\nremove_handlers()\n{\n     int i;\n\n     D_DEBUG_AT( Direct_Signals, \"%s()\\n\", __FUNCTION__ );\n\n     for (i = 0; i < NUM_SIGS_TO_HANDLE; i++) {\n          if (sigs_handled[i].signum != -1) {\n               int signum = sigs_handled[i].signum;\n\n               if (sigaction( signum, &sigs_handled[i].old_action, NULL )) {\n                    D_PERROR( \"Direct/Signals: Unable to restore previous handler for signal %d!\\n\", signum );\n               }\n\n               sigs_handled[i].signum = -1;\n          }\n     }\n}\n"
  },
  {
    "path": "lib/direct/os/linux/system.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/conf.h>\n#include <direct/debug.h>\n#if D_DEBUG_ENABLED\n#include <direct/atomic.h>\n#endif\n#include <direct/messages.h>\n#include <direct/os/system.h>\n#include <direct/os/thread.h>\n\n#if !defined(__NR_futex) && defined(__NR_futex_time64)\n#define __NR_futex __NR_futex_time64\n#endif\n\nD_DEBUG_DOMAIN( Direct_Futex, \"Direct/Futex\", \"Direct Futex\" );\nD_DEBUG_DOMAIN( Direct_Trap,  \"Direct/Trap\",  \"Direct Trap\" );\n\n/**********************************************************************************************************************/\n\n__attribute__((no_instrument_function))\nvoid\ndirect_sched_yield()\n{\n     sched_yield();\n}\n\nlong\ndirect_pagesize()\n{\n     return sysconf( _SC_PAGESIZE );\n}\n\nunsigned long\ndirect_page_align( unsigned long value )\n{\n     unsigned long mask = sysconf( _SC_PAGESIZE ) - 1;\n\n     return (value + mask) & ~mask;\n}\n\n__attribute__((no_instrument_function))\npid_t\ndirect_getpid()\n{\n     return getpid();\n}\n\n__attribute__((no_instrument_function))\npid_t\ndirect_gettid()\n{\n     return syscall( __NR_gettid );\n}\n\nvoid\ndirect_trap( const char *domain,\n             int         sig )\n{\n     union sigval val;\n\n     if (direct_config->delay_trap_ms) {\n          D_DEBUG_AT( Direct_Trap, \"Not raising signal %d from %s, waiting for %dms... attach gdb --pid=%d\\n\",\n                      sig, domain, direct_config->delay_trap_ms, getpid() );\n          direct_thread_sleep( direct_config->delay_trap_ms * 1000LL );\n          return;\n     }\n\n     D_DEBUG_AT( Direct_Trap, \"Raising signal %d from %s...\\n\", sig, domain );\n\n     val.sival_int = direct_gettid();\n\n     sigqueue( direct_gettid(), sig, val );\n\n     abort();\n\n     D_DEBUG_AT( Direct_Trap, \"...abort() returned as well, calling exit_group()\\n\" );\n\n     syscall( __NR_exit_group, DR_BUG );\n}\n\nDirectResult\ndirect_kill( pid_t pid,\n             int   sig )\n{\n     if (kill( pid, sig ) < 0) {\n          if (errno == ESRCH)\n               return DR_NOSUCHINSTANCE;\n          else\n               return errno2result( errno );\n     }\n\n     return DR_OK;\n}\n\nvoid\ndirect_sync()\n{\n     sync();\n}\n\nuid_t\ndirect_geteuid()\n{\n     return geteuid();\n}\n\nchar *\ndirect_getenv( const char *name )\n{\n     return getenv( name );\n}\n\nDirectResult\ndirect_futex( int                   *uaddr,\n              int                    op,\n              int                    val,\n              const struct timespec *timeout,\n              int                   *uaddr2,\n              int                    val3 )\n{\n#if D_DEBUG_ENABLED\n     unsigned int count;\n\n     switch (op) {\n          case FUTEX_WAIT:\n               count = D_SYNC_ADD_AND_FETCH( &__Direct_Futex_Wait_Count, 1 );\n               D_DEBUG_AT( Direct_Futex, \"## ## WAIT FOR --> %p <--  %d (<-%d) ## ## ## ## * %u\\n\", uaddr, *uaddr, val, count );\n               break;\n\n          case FUTEX_WAKE:\n               count = D_SYNC_ADD_AND_FETCH( &__Direct_Futex_Wake_Count, 1 );\n               D_DEBUG_AT( Direct_Futex, \"###   WAKE UP =--> %p <--= %d (->%d) ### ### ### * %u\\n\", uaddr, *uaddr, val, count );\n               break;\n\n          default:\n               D_DEBUG_AT( Direct_Futex, \"# #  UNKNOWN FUTEX OP  # #\\n\" );\n     }\n#endif\n\n     if (syscall( __NR_futex, uaddr, op, val, timeout, uaddr2, val3 ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nbool\ndirect_madvise()\n{\n     struct utsname uts;\n     int            i, j, k, l;\n\n     if (uname( &uts ) < 0) {\n          D_PERROR( \"Direct/System: uname() failed!\\n\" );\n          return false;\n     }\n\n     switch (sscanf( uts.release, \"%d.%d.%d.%d\", &i, &j, &k, &l )) {\n          case 3:\n               l = 0;\n          case 4:\n               if (((i << 24) | (j << 16) | (k << 8) | l) >= 0x02061302)\n                    return true;\n               break;\n\n          default:\n               D_WARN( \"could not parse kernel version '%s'\", uts.release );\n     }\n\n     return false;\n}\n"
  },
  {
    "path": "lib/direct/os/linux/thread.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#define _GNU_SOURCE /* To get pthread_getattr_np() declaration. */\n\n#include <direct/conf.h>\n#include <direct/debug.h>\n#include <direct/messages.h>\n#include <direct/os/mem.h>\n#include <direct/os/system.h>\n#include <direct/os/thread.h>\n#include <direct/trace.h>\n\nD_DEBUG_DOMAIN( Direct_Thread,     \"Direct/Thread\",      \"Direct Thread Management\" );\nD_DEBUG_DOMAIN( Direct_ThreadInit, \"Direct/Thread/Init\", \"Direct Thread Init\" );\n\n/**********************************************************************************************************************/\n\nstatic pthread_key_t thread_key;\nstatic DirectOnce    thread_init_once = DIRECT_ONCE_INIT();\n\n/*\n * Wrapper around pthread's main routine to pass additional arguments\n * and setup things like signal masks and scheduling priorities.\n */\n__attribute__((no_instrument_function))\nstatic void *direct_thread_main( void *arg );\n\n/**********************************************************************************************************************/\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_once( DirectOnce            *once,\n             DirectOnceInitHandler  handler )\n{\n     int erno = pthread_once( &once->once, handler );\n\n     return errno2result( erno );\n}\n\n__attribute__((no_instrument_function))\nstatic void\ninit_once( void )\n{\n     /* Create the key for the TSD (thread specific data). */\n     pthread_key_create( &thread_key, NULL );\n}\n\nDirectResult\ndirect_thread_init( DirectThread *thread )\n{\n     int                erno;\n     pthread_attr_t     attr;\n     struct sched_param param;\n     int                policy;\n     int                priority;\n\n     D_DEBUG_AT( Direct_ThreadInit, \"%s( %p, '%s' )\\n\", __FUNCTION__, thread->main, thread->name );\n\n     direct_once( &thread_init_once, init_once );\n\n     /* Initialize scheduling and other parameters. */\n     pthread_attr_init( &attr );\n\n     pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED );\n\n     /* Select scheduler. */\n     switch (direct_config->thread_scheduler) {\n          case DCTS_FIFO:\n               policy = SCHED_FIFO;\n               break;\n\n          case DCTS_RR:\n               policy = SCHED_RR;\n               break;\n\n          default:\n               policy = SCHED_OTHER;\n               break;\n     }\n\n     if (pthread_attr_setschedpolicy( &attr, policy ))\n          D_PERROR( \"Direct/Thread/Init: Could not set scheduling policy to %s!\\n\", direct_thread_policy_name( policy ) );\n\n     /* Read (back) value. */\n     pthread_attr_getschedpolicy( &attr, &policy );\n     thread->policy = policy;\n\n     /* Select priority. */\n     switch (thread->type) {\n          case DTT_CLEANUP:\n          case DTT_INPUT:\n          case DTT_OUTPUT:\n          case DTT_MESSAGING:\n          case DTT_CRITICAL:\n               priority = thread->type * direct_config->thread_priority_scale / 100;\n               break;\n\n          default:\n               priority = direct_config->thread_priority;\n               break;\n     }\n\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> priority %d [%d;%d]\\n\", priority,\n                 sched_get_priority_min( policy ), sched_get_priority_max( policy ) );\n\n     if (priority < sched_get_priority_min( policy ))\n          priority = sched_get_priority_min( policy );\n\n     if (priority > sched_get_priority_max( policy ))\n          priority = sched_get_priority_max( policy );\n\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> policy %s with priority set to %d\\n\", direct_thread_policy_name( policy ),\n                 priority );\n\n     param.sched_priority = priority;\n\n     if (pthread_attr_setschedparam( &attr, &param ))\n          D_PERROR( \"Direct/Thread/Init: Could not set scheduling priority to %d!\\n\", priority );\n\n     /* Select stack size. */\n     if (direct_config->thread_stack_size > 0) {\n          if (pthread_attr_setstacksize( &attr, direct_config->thread_stack_size ))\n               D_PERROR( \"Direct/Thread/Init: Could not set stack size to %d!\\n\", direct_config->thread_stack_size );\n     }\n\n     erno = pthread_create( &thread->handle, &attr, direct_thread_main, thread );\n     if (erno)\n          return errno2result( erno );\n\n     pthread_attr_destroy( &attr );\n\n     /* Read (back) value. */\n     pthread_getattr_np( thread->handle, &attr );\n     pthread_attr_getstacksize( &attr, &thread->stack_size );\n     pthread_attr_getschedparam( &attr, &param );\n     thread->priority = param.sched_priority;\n     pthread_attr_destroy( &attr );\n\n     return DR_OK;\n}\n\nvoid\ndirect_thread_deinit( DirectThread *thread )\n{\n     D_MAGIC_ASSERT( thread, DirectThread );\n\n     D_ASSUME( !pthread_equal( thread->handle, pthread_self() ) );\n     D_ASSUME( !thread->detached );\n\n     D_DEBUG_AT( Direct_ThreadInit, \"%s( %p, '%s' %d )\\n\", __FUNCTION__, thread->main, thread->name, thread->tid );\n\n     if (!thread->joined && !pthread_equal( thread->handle, pthread_self() )) {\n          if (thread->canceled)\n               D_DEBUG_AT( Direct_ThreadInit, \"  -> canceled but not joined!\\n\" );\n          else {\n               D_DEBUG_AT( Direct_ThreadInit, \"  -> still running!\\n\" );\n\n               if (thread->name)\n                    D_ERROR( \"Direct/Thread/Init: Canceling '%s' (%d)!\\n\", thread->name, thread->tid );\n               else\n                    D_ERROR( \"Direct/Thread/Init: Canceling %d!\\n\", thread->tid );\n\n               pthread_cancel( thread->handle );\n          }\n\n          pthread_join( thread->handle, NULL );\n     }\n}\n\n__attribute__((no_instrument_function))\nvoid\ndirect_thread_setcancelstate( DirectThreadCancelState state )\n{\n     switch (state) {\n          case DIRECT_THREAD_CANCEL_ENABLE:\n               pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL );\n\n          case DIRECT_THREAD_CANCEL_DISABLE:\n               pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, NULL );\n     }\n}\n\n__attribute__((no_instrument_function))\nDirectThread *\ndirect_thread_self()\n{\n     DirectThread *thread;\n\n     direct_once( &thread_init_once, init_once );\n\n     thread = pthread_getspecific( thread_key );\n\n     /* Support this function for non-direct threads. */\n     if (!thread) {\n          thread = calloc( 1, sizeof(DirectThread) );\n          if (!thread) {\n               D_OOM();\n               return NULL;\n          }\n\n          thread->handle = pthread_self();\n          thread->tid    = direct_gettid();\n\n          D_MAGIC_SET( thread, DirectThread );\n\n          pthread_setspecific( thread_key, thread );\n     }\n\n     return thread;\n}\n\n#if defined(__GNUC__) && __GNUC__ >= 10\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wanalyzer-malloc-leak\"\n#endif\n__attribute__((no_instrument_function))\nconst char *\ndirect_thread_self_name()\n{\n     DirectThread *thread = direct_thread_self();\n     char name[16];\n\n     /* This function is called by debugging functions, e.g. debug messages, assertions etc.\n        Therefore no assertions are made here, because they would loop forever if they fail. */\n\n     if (!thread)\n          return NULL;\n\n     if (!thread->name) {\n          prctl( PR_GET_NAME, name, 0, 0, 0 );\n          thread->name = strdup( name );\n     }\n\n     return thread->name;\n}\n\nvoid\ndirect_thread_set_name( const char *name )\n{\n     char         *copy;\n     DirectThread *thread;\n\n     D_DEBUG_AT( Direct_Thread, \"%s( '%s' )\\n\", __FUNCTION__, name );\n\n     thread = direct_thread_self();\n     if (!thread)\n          return;\n\n     /* Duplicate string. */\n     copy = strdup( name );\n     if (!copy) {\n          D_OOM();\n          return;\n     }\n\n     /* Free old string. */\n     if (thread->name)\n          free( thread->name );\n\n     /* Keep the copy. */\n     thread->name = copy;\n}\n#if defined(__GNUC__) && __GNUC__ >= 10\n#pragma GCC diagnostic pop\n#endif\n\nvoid\ndirect_thread_cancel( DirectThread *thread )\n{\n     D_MAGIC_ASSERT( thread, DirectThread );\n     D_ASSERT( thread->handle != -1 );\n     D_ASSERT( !pthread_equal( thread->handle, pthread_self() ) );\n\n     D_ASSUME( !thread->canceled );\n\n     D_DEBUG_AT( Direct_Thread, \"%s( %p, '%s' %d )\\n\", __FUNCTION__, thread->main, thread->name, thread->tid );\n\n     thread->canceled = true;\n\n     pthread_cancel( thread->handle );\n}\n\nvoid\ndirect_thread_detach( DirectThread *thread )\n{\n     D_MAGIC_ASSERT( thread, DirectThread );\n     D_ASSERT( thread->handle != -1 );\n     D_ASSERT( !pthread_equal( thread->handle, pthread_self() ) );\n\n     D_ASSUME( !thread->canceled );\n\n     D_DEBUG_AT( Direct_Thread, \"%s( %p, '%s' %d )\\n\", __FUNCTION__, thread->main, thread->name, thread->tid );\n\n     thread->detached = true;\n\n     pthread_detach( thread->handle );\n}\n\nvoid\ndirect_thread_testcancel( DirectThread *thread )\n{\n     D_MAGIC_ASSERT( thread, DirectThread );\n     D_ASSERT( thread->handle != -1 );\n     D_ASSERT( pthread_equal( thread->handle, pthread_self() ) );\n\n     /* Quick check before calling the pthread function. */\n     if (thread->canceled)\n          pthread_testcancel();\n}\n\nvoid\ndirect_thread_join( DirectThread *thread )\n{\n     D_MAGIC_ASSERT( thread, DirectThread );\n     D_ASSERT( thread->handle != -1 );\n\n     D_ASSUME( !pthread_equal( thread->handle, pthread_self() ) );\n     D_ASSUME( !thread->joining );\n     D_ASSUME( !thread->joined );\n     D_ASSUME( !thread->detached );\n\n     D_DEBUG_AT( Direct_Thread, \"%s( %p, '%s' %d )\\n\", __FUNCTION__, thread->main, thread->name, thread->tid );\n\n     if (thread->detached) {\n          D_DEBUG_AT( Direct_Thread, \"  -> detached\\n\" );\n          return;\n     }\n\n     if (!thread->joining && !pthread_equal( thread->handle, pthread_self() )) {\n          thread->joining = true;\n\n          D_DEBUG_AT( Direct_Thread, \"  -> joining...\\n\" );\n\n          pthread_join( thread->handle, NULL );\n\n          thread->joined = true;\n\n          D_DEBUG_AT( Direct_Thread, \"  -> joined\\n\" );\n     }\n}\n\nvoid\ndirect_thread_kill( DirectThread *thread,\n                    int           signal )\n{\n     D_MAGIC_ASSERT( thread, DirectThread );\n     D_ASSERT( thread->handle != -1 );\n\n     D_DEBUG_AT( Direct_Thread, \"%s( %p, '%s' %d, signal %d )\\n\", __FUNCTION__,\n                 thread->main, thread->name, thread->tid, signal );\n\n     pthread_kill( thread->handle, signal );\n}\n\nvoid\ndirect_thread_sleep( long long micros )\n{\n     usleep( micros );\n}\n\nvoid\ndirect_thread_atfork( DirectThreadPrepareHandler prepare,\n                      DirectThreadParentHandler  parent,\n                      DirectThreadChildHandler   child )\n{\n     pthread_atfork( prepare, parent, child );\n}\n\n/**********************************************************************************************************************/\n\nconst char *\ndirect_thread_type_name( DirectThreadType type )\n{\n     switch (type) {\n          case DTT_DEFAULT:\n               return \"DEFAULT\";\n\n          case DTT_CLEANUP:\n               return \"CLEANUP\";\n\n          case DTT_INPUT:\n               return \"INPUT\";\n\n          case DTT_OUTPUT:\n               return \"OUTPUT\";\n\n          case DTT_MESSAGING:\n               return \"MESSAGING\";\n\n          case DTT_CRITICAL:\n               return \"CRITICAL\";\n     }\n\n     return \"<unknown>\";\n}\n\nconst char *\ndirect_thread_policy_name( int policy )\n{\n     switch (policy) {\n          case SCHED_OTHER:\n               return \"OTHER\";\n\n          case SCHED_FIFO:\n               return \"FIFO\";\n\n          case SCHED_RR:\n               return \"RR\";\n     }\n\n     return \"<unknown>\";\n}\n\n/**********************************************************************************************************************/\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_tls_register( DirectTLS *tls,\n                     DirectTLSDestructor  destructor )\n{\n     int erno = pthread_key_create( &tls->key, destructor );\n\n     return errno2result( erno );\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_tls_unregister( DirectTLS *tls )\n{\n     int erno;\n\n     erno = pthread_key_delete( tls->key );\n     if (erno)\n          return errno2result( erno );\n\n     tls->key = (pthread_key_t) -1;\n\n     return DR_OK;\n}\n\n__attribute__((no_instrument_function))\nvoid *\ndirect_tls_get( DirectTLS *tls )\n{\n     void *value;\n\n     value = pthread_getspecific( tls->key );\n\n     return value;\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_tls_set( DirectTLS *tls,\n                void      *value )\n{\n     int erno = pthread_setspecific( tls->key, value );\n\n     return errno2result( erno );\n}\n\n/**********************************************************************************************************************/\n\nstatic void\ndirect_thread_cleanup( void *arg )\n{\n     DirectThread *thread = arg;\n\n     D_MAGIC_ASSERT( thread, DirectThread );\n\n     D_DEBUG_AT( Direct_Thread, \"%s( %p, '%s' %d )\\n\", __FUNCTION__, thread->main, thread->name, thread->tid );\n\n     if (thread->trace_buffer)\n          direct_trace_free_buffer( thread->trace_buffer );\n\n     if (thread->detached) {\n          D_MAGIC_CLEAR( thread );\n\n          if (thread->name)\n               free( thread->name );\n\n          free( thread );\n     }\n}\n\n__attribute__((no_instrument_function))\nstatic void *\ndirect_thread_main( void *arg )\n{\n     void         *res;\n     DirectThread *thread = arg;\n\n     prctl( PR_SET_NAME, thread->name, 0, 0, 0 );\n\n     pthread_setspecific( thread_key, thread );\n\n     D_DEBUG_AT( Direct_ThreadInit, \"%s( %p )\\n\", __FUNCTION__, arg );\n\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> starting...\\n\" );\n\n     D_MAGIC_ASSERT( thread, DirectThread );\n\n     pthread_cleanup_push( direct_thread_cleanup, thread );\n\n     thread->tid = direct_gettid();\n\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> tid %d\\n\", thread->tid );\n\n     _direct_thread_call_init_handlers( thread );\n\n     /* Have all signals handled by the main thread. */\n     if (direct_config->thread_block_signals) {\n          sigset_t signals;\n          sigfillset( &signals );\n          sigprocmask( SIG_BLOCK, &signals, NULL );\n     }\n\n     /* Lock the thread mutex. */\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> locking...\\n\" );\n     direct_mutex_lock( &thread->lock );\n\n     /* Indicate that our initialization has completed. */\n     thread->init = true;\n\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> signalling...\\n\" );\n     direct_waitqueue_signal( &thread->cond );\n\n     /* Unlock the thread mutex. */\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> unlocking...\\n\" );\n     direct_mutex_unlock( &thread->lock );\n\n     if (thread->joining) {\n          D_DEBUG_AT( Direct_ThreadInit, \"  -> being joined before entering main routine!\\n\" );\n          return NULL;\n     }\n\n     /* Call main routine. */\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> running...\\n\" );\n     res = thread->main( thread, thread->arg );\n\n     D_DEBUG_AT( Direct_Thread, \"  -> returning %p from '%s' (%s, %d)...\\n\",\n                 res, thread->name, direct_thread_type_name( thread->type ), thread->tid );\n\n     pthread_cleanup_pop( 1 );\n\n     return res;\n}\n"
  },
  {
    "path": "lib/direct/os/linux/thread.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__LINUX__THREAD_H__\n#define __DIRECT__OS__LINUX__THREAD_H__\n\n#include <direct/os/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef pthread_t DirectThreadHandle;\n\ntypedef struct {\n     pthread_once_t once;\n} DirectOnce;\n\n#define DIRECT_ONCE_INIT() { PTHREAD_ONCE_INIT }\n\ntypedef struct {\n     pthread_key_t key;\n} DirectTLS;\n\n#endif\n"
  },
  {
    "path": "lib/direct/os/linux/types.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__LINUX__TYPES_H__\n#define __DIRECT__OS__LINUX__TYPES_H__\n\n#include <dirent.h>\n#if DIRECT_BUILD_DYNLOAD\n#include <dlfcn.h>\n#endif\n#include <errno.h>\n#include <fcntl.h>\n#include <grp.h>\n#include <limits.h>\n#include <linux/unistd.h>\n#if DIRECT_BUILD_NETWORK\n#include <netdb.h>\n#endif\n#include <pthread.h>\n#include <signal.h>\n#include <stdarg.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#if defined(__i386__) || defined(__x86_64__)\n#include <sys/io.h>\n#endif\n#include <sys/ioctl.h>\n#include <sys/mman.h>\n#include <sys/prctl.h>\n#include <sys/stat.h>\n#include <sys/statfs.h>\n#include <sys/time.h>\n#include <sys/un.h>\n#include <sys/utsname.h>\n#include <unistd.h>\n\ntypedef unsigned int unichar;\n\ntypedef uint8_t  u8;\ntypedef uint16_t u16;\ntypedef uint32_t u32;\ntypedef uint64_t u64;\n\ntypedef int8_t   s8;\ntypedef int16_t  s16;\ntypedef int32_t  s32;\ntypedef int64_t  s64;\n\n#define _ZD \"%zd\"\n#define _ZU \"%zu\"\n#define _ZUn(x) \"%\" #x \"zu\"\n\n#endif\n"
  },
  {
    "path": "lib/direct/os/linux/waitqueue.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__LINUX__WAITQUEUE_H__\n#define __DIRECT__OS__LINUX__WAITQUEUE_H__\n\n#include <direct/os/mutex.h>\n#include <direct/util.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     pthread_cond_t cond;\n} DirectWaitQueue;\n\nstatic inline DirectResult\ndirect_waitqueue_init( DirectWaitQueue *queue )\n{\n     int erno = pthread_cond_init( &queue->cond, NULL );\n\n     return errno2result( erno );\n}\n\nstatic inline DirectResult\ndirect_waitqueue_wait( DirectWaitQueue *queue,\n                       DirectMutex     *mutex )\n{\n     int erno = pthread_cond_wait( &queue->cond, &mutex->lock );\n\n     return errno2result( erno );\n}\n\nstatic inline DirectResult\ndirect_waitqueue_wait_timeout( DirectWaitQueue *queue,\n                               DirectMutex     *mutex,\n                               unsigned long    micros )\n{\n     struct timeval  now;\n     struct timespec timeout;\n     long            seconds      = micros / 1000000;\n     long            nano_seconds = (micros % 1000000) * 1000;\n\n     gettimeofday( &now, NULL );\n\n     timeout.tv_sec  = now.tv_sec + seconds;\n     timeout.tv_nsec = (now.tv_usec * 1000) + nano_seconds;\n\n     timeout.tv_sec  += timeout.tv_nsec / 1000000000;\n     timeout.tv_nsec %= 1000000000;\n\n     if (pthread_cond_timedwait( &queue->cond, &mutex->lock, &timeout ) == ETIMEDOUT)\n          return DR_TIMEOUT;\n\n     return DR_OK;\n}\n\nstatic inline DirectResult\ndirect_waitqueue_signal( DirectWaitQueue *queue )\n{\n     int erno = pthread_cond_signal( &queue->cond );\n\n     return errno2result( erno );\n}\n\nstatic inline DirectResult\ndirect_waitqueue_broadcast( DirectWaitQueue *queue )\n{\n     int erno = pthread_cond_broadcast( &queue->cond );\n\n     return errno2result( erno );\n}\n\nstatic inline DirectResult\ndirect_waitqueue_deinit( DirectWaitQueue *queue )\n{\n     int erno = pthread_cond_destroy( &queue->cond );\n\n     return errno2result( erno );\n}\n\n#endif\n"
  },
  {
    "path": "lib/direct/os/log.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__LOG_H__\n#define __DIRECT__OS__LOG_H__\n\n#include <direct/os/mutex.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     DLT_STDERR = 0x00000000, /* Simply print out log on stderr. */\n     DLT_FILE   = 0x00000001, /* Write log into a file. */\n     DLT_UDP    = 0x00000002  /* Send out log via UDP. */\n} DirectLogType;\n\ntypedef DirectResult (*DirectLogWriteFunc)( DirectLog *log, const char *buffer, size_t bytes );\ntypedef DirectResult (*DirectLogFlushFunc)( DirectLog *log );\n\nstruct __D_DirectLog {\n     int                     magic;\n\n     DirectLogType           type;\n\n     DirectMutex             lock;\n\n     void                   *data;\n\n     DirectLogWriteFunc      write;\n     DirectLogFlushFunc      flush;\n};\n\n/**********************************************************************************************************************/\n\n/*\n * Initializes a logging facility.\n *\n * For each 'log->type' the 'param' has a different meaning:\n *   DLT_STDERR     ignored (leave NULL)\n *   DLT_FILE       file name\n *   DLT_UDP        <ip>:<port>\n */\nDirectResult DIRECT_API direct_log_init  ( DirectLog  *log,\n                                           const char *param );\n\n/*\n * Destroys a logging facility.\n */\nDirectResult DIRECT_API direct_log_deinit( DirectLog  *log );\n\n#endif\n"
  },
  {
    "path": "lib/direct/os/mem.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__MEM_H__\n#define __DIRECT__OS__MEM_H__\n\n#include <direct/os/types.h>\n\n/**********************************************************************************************************************/\n\nvoid DIRECT_API *direct_malloc ( size_t      bytes );\n\nvoid DIRECT_API *direct_calloc ( size_t      count,\n                                 size_t      bytes );\n\nvoid DIRECT_API *direct_realloc( void       *mem,\n                                 size_t      bytes );\n\nchar DIRECT_API *direct_strdup ( const char *string );\n\nvoid DIRECT_API  direct_free   ( void       *mem );\n\n#endif\n"
  },
  {
    "path": "lib/direct/os/mutex.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__MUTEX_H__\n#define __DIRECT__OS__MUTEX_H__\n\n#include <direct/os/types.h>\n\n/**********************************************************************************************************************/\n\nDirectResult DIRECT_API direct_mutex_init          ( DirectMutex *mutex );\n\nDirectResult DIRECT_API direct_recursive_mutex_init( DirectMutex *mutex );\n\nDirectResult DIRECT_API direct_mutex_lock          ( DirectMutex *mutex );\n\nDirectResult DIRECT_API direct_mutex_unlock        ( DirectMutex *mutex );\n\nDirectResult DIRECT_API direct_mutex_trylock       ( DirectMutex *mutex );\n\nDirectResult DIRECT_API direct_mutex_deinit        ( DirectMutex *mutex );\n\nDirectResult DIRECT_API direct_rwlock_init         ( DirectRWLock *rwlock );\n\nDirectResult DIRECT_API direct_rwlock_rdlock       ( DirectRWLock *rwlock );\n\nDirectResult DIRECT_API direct_rwlock_wrlock       ( DirectRWLock *rwlock );\n\nDirectResult DIRECT_API direct_rwlock_unlock       ( DirectRWLock *rwlock );\n\nDirectResult DIRECT_API direct_rwlock_trywrlock    ( DirectRWLock *rwlock );\n\nDirectResult DIRECT_API direct_rwlock_deinit       ( DirectRWLock *rwlock );\n\n#endif\n"
  },
  {
    "path": "lib/direct/os/nuttx/clock.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/os/clock.h>\n#include <direct/messages.h>\n#include <direct/util.h>\n\n/**********************************************************************************************************************/\n\nstatic long long session_clock_offset;\n\n/**********************************************************************************************************************/\n\n__attribute__((no_instrument_function))\nlong long\ndirect_clock_get_time( DirectClockType type )\n{\n     long long       micros;\n     struct timespec spec;\n     clockid_t       clock_id;\n\n     switch (type) {\n          case DIRECT_CLOCK_REALTIME:\n               clock_id = CLOCK_REALTIME;\n               break;\n\n          case DIRECT_CLOCK_SESSION:\n          case DIRECT_CLOCK_MONOTONIC:\n               clock_id = CLOCK_MONOTONIC;\n               break;\n\n          case DIRECT_CLOCK_PROCESS_CPUTIME_ID:\n               clock_id = CLOCK_PROCESS_CPUTIME_ID;\n               break;\n\n          case DIRECT_CLOCK_THREAD_CPUTIME_ID:\n               clock_id = CLOCK_THREAD_CPUTIME_ID;\n               break;\n\n          default:\n               D_BUG( \"invalid clock type %u\", type );\n               return DR_INVARG;\n     }\n\n     if (clock_gettime( clock_id, &spec ) < 0) {\n          if (clock_id != CLOCK_REALTIME) {\n               D_WARN( \"clock with id %d not supported by system\", clock_id );\n               return direct_clock_get_time( DIRECT_CLOCK_REALTIME );\n          }\n\n          D_PERROR( \"Direct/Clock: Could not get real time clock!\\n\" );\n          return 0;\n     }\n\n     micros = spec.tv_sec * 1000000LL + spec.tv_nsec / 1000LL;\n\n     if (type == DIRECT_CLOCK_SESSION)\n          micros -= session_clock_offset;\n\n     usleep( 1 );\n\n     return micros;\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_clock_set_time( DirectClockType type,\n                       long long       micros )\n{\n     DirectResult    ret;\n     clockid_t       clock_id;\n     struct timespec spec;\n\n     switch (type) {\n          case DIRECT_CLOCK_SESSION:\n               session_clock_offset = micros;\n               return DR_OK;\n\n          case DIRECT_CLOCK_REALTIME:\n               clock_id = CLOCK_REALTIME;\n               break;\n\n          case DIRECT_CLOCK_MONOTONIC:\n               clock_id = CLOCK_MONOTONIC;\n               break;\n\n          case DIRECT_CLOCK_PROCESS_CPUTIME_ID:\n               clock_id = CLOCK_PROCESS_CPUTIME_ID;\n               break;\n\n          case DIRECT_CLOCK_THREAD_CPUTIME_ID:\n               clock_id = CLOCK_THREAD_CPUTIME_ID;\n               break;\n\n          default:\n               D_BUG( \"invalid clock type %u\", type );\n               return DR_INVARG;\n     }\n\n     spec.tv_sec  = micros / 1000000LL;\n     spec.tv_nsec = micros % 1000000LL * 1000LL;\n\n     if (clock_settime( clock_id, &spec ) < 0) {\n          ret = errno2result( errno );\n          D_PERROR( \"Direct/Clock: Could not set clock with id %d!\\n\", clock_id );\n          return ret;\n     }\n\n     return DR_OK;\n}\n\n__attribute__((no_instrument_function))\nlong long\ndirect_clock_resolution( DirectClockType type )\n{\n     struct timespec spec;\n     clockid_t       clock_id;\n\n     switch (type) {\n          case DIRECT_CLOCK_SESSION:\n          case DIRECT_CLOCK_REALTIME:\n               clock_id = CLOCK_REALTIME;\n               break;\n\n          case DIRECT_CLOCK_MONOTONIC:\n               clock_id = CLOCK_MONOTONIC;\n               break;\n\n          case DIRECT_CLOCK_PROCESS_CPUTIME_ID:\n               clock_id = CLOCK_PROCESS_CPUTIME_ID;\n               break;\n\n          case DIRECT_CLOCK_THREAD_CPUTIME_ID:\n               clock_id = CLOCK_THREAD_CPUTIME_ID;\n               break;\n\n          default:\n               D_BUG( \"invalid clock type %u\", type );\n               return DR_INVARG;\n     }\n\n     if (clock_getres( clock_id, &spec ) < 0) {\n          if (clock_id != CLOCK_REALTIME) {\n               D_WARN( \"clock with id %d not supported by system\", clock_id );\n               return direct_clock_resolution( DIRECT_CLOCK_REALTIME );\n          }\n\n          D_PERROR( \"Direct/Clock: Could not get real time clock resolution!\\n\" );\n          return 0;\n     }\n\n     return spec.tv_sec * 1000000LL + spec.tv_nsec / 1000LL;\n}\n"
  },
  {
    "path": "lib/direct/os/nuttx/configs/sim/defconfig",
    "content": "CONFIG_ARCH=\"sim\"\nCONFIG_ARCH_BOARD=\"sim\"\nCONFIG_ARCH_BOARD_SIM=y\nCONFIG_ARCH_CHIP=\"sim\"\nCONFIG_ARCH_SIM=y\nCONFIG_BOARD_LATE_INITIALIZE=y\nCONFIG_DRIVERS_VIDEO=y\nCONFIG_EXAMPLES_DIRECTFB=y\nCONFIG_GRAPHICS_DIRECTFB2=y\nCONFIG_INIT_ENTRYPOINT=\"directfb_main\"\nCONFIG_INPUT=y\nCONFIG_PIPES=y\nCONFIG_PTHREAD_CLEANUP_STACKSIZE=1\nCONFIG_PTHREAD_MUTEX_TYPES=y\nCONFIG_SIM_FBHEIGHT=480\nCONFIG_SIM_FBWIDTH=640\nCONFIG_SIM_KEYBOARD=y\nCONFIG_SIM_TOUCHSCREEN=y\nCONFIG_SIM_X11FB=y\nCONFIG_VIDEO_FB=y\n"
  },
  {
    "path": "lib/direct/os/nuttx/configs/stm32f429i-disco/defconfig",
    "content": "# CONFIG_STM32_FB_CMAP is not set\nCONFIG_ARCH=\"arm\"\nCONFIG_ARCH_BOARD=\"stm32f429i-disco\"\nCONFIG_ARCH_BOARD_STM32F429I_DISCO=y\nCONFIG_ARCH_BUTTONS=y\nCONFIG_ARCH_CHIP=\"stm32\"\nCONFIG_ARCH_CHIP_STM32F429Z=y\nCONFIG_ARCH_IRQBUTTONS=y\nCONFIG_BUILTIN=y\nCONFIG_DRIVERS_VIDEO=y\nCONFIG_EXAMPLES_DIRECTFB=y\nCONFIG_EXAMPLES_DIRECTFB_FONT_EXTENSION=\"ttf\"\nCONFIG_EXAMPLES_DIRECTFB_FONT_PROVIDER=\"STB\"\nCONFIG_EXAMPLES_DIRECTFB_IMAGE_EXTENSION=\"png\"\nCONFIG_EXAMPLES_DIRECTFB_IMAGE_PROVIDER=\"STB\"\nCONFIG_EXAMPLES_DIRECTFB_VIDEO_EXTENSION=\"mpg\"\nCONFIG_EXAMPLES_DIRECTFB_VIDEO_PROVIDER=\"PLM\"\nCONFIG_GRAPHICS_DIRECTFB2=y\nCONFIG_GRAPHICS_DIRECTFB2_MEDIA_PL_MPEG=y\nCONFIG_GRAPHICS_DIRECTFB2_MEDIA_STB=y\nCONFIG_HEAP2_BASE=0xD0000000\nCONFIG_HEAP2_SIZE=7774208\nCONFIG_INIT_ENTRYPOINT=\"nsh_main\"\nCONFIG_INPUT=y\nCONFIG_INPUT_BUTTONS=y\nCONFIG_INPUT_BUTTONS_LOWER=y\nCONFIG_INPUT_STMPE811=y\nCONFIG_MM_REGIONS=2\nCONFIG_NSH_ARCHINIT=y\nCONFIG_NSH_BUILTIN_APPS=y\nCONFIG_PIPES=y\nCONFIG_PTHREAD_CLEANUP_STACKSIZE=1\nCONFIG_PTHREAD_MUTEX_TYPES=y\nCONFIG_RAW_BINARY=y\nCONFIG_SCHED_HPWORK=y\nCONFIG_STM32F429I_DISCO_ILI9341=y\nCONFIG_STM32_CCMEXCLUDE=y\nCONFIG_STM32_EXTERNAL_RAM=y\nCONFIG_STM32_FMC=y\nCONFIG_STM32_I2C3=y\nCONFIG_STM32_LTDC=y\nCONFIG_STM32_LTDC_FB_BASE=0xD076A000\nCONFIG_STM32_LTDC_FB_SIZE=307200\nCONFIG_STM32_USART1=y\nCONFIG_STMPE811_ACTIVELOW=y\nCONFIG_STMPE811_EDGE=y\nCONFIG_STMPE811_OFFSETX=300\nCONFIG_STMPE811_OFFSETY=242\nCONFIG_STMPE811_THRESHX=15\nCONFIG_STMPE811_THRESHY=11\nCONFIG_STMPE811_SWAPXY=y\nCONFIG_SYSTEM_NSH=y\nCONFIG_USART1_SERIAL_CONSOLE=y\nCONFIG_VIDEO_FB=y\n"
  },
  {
    "path": "lib/direct/os/nuttx/filesystem.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/debug.h>\n#include <direct/os/filesystem.h>\n#include <direct/messages.h>\n#include <direct/util.h>\n\n/**********************************************************************************************************************/\n\nDirectResult\ndirect_dir_get_current( char   *buf,\n                        size_t  length )\n{\n     D_ASSERT( buf != NULL );\n\n     if (!getcwd( buf, length ))\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_dir_change( const char *name )\n{\n     D_ASSERT( name != NULL );\n\n     if (chdir( name ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_dir_create( const char *name,\n                   mode_t      mode )\n{\n     D_ASSERT( name != NULL );\n\n     if (mkdir( name, mode ) < 0) {\n          if (errno == EEXIST)\n               return DR_BUSY;\n          else\n               return errno2result( errno );\n     }\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_dir_open( DirectDir  *dir,\n                 const char *name )\n{\n     D_ASSERT( dir != NULL );\n     D_ASSERT( name != NULL );\n\n     dir->dir = opendir( name );\n     if (!dir->dir)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_dir_read( DirectDir   *dir,\n                 DirectEntry *entry )\n{\n     struct dirent *ent;\n\n     D_ASSERT( dir != NULL );\n     D_ASSERT( entry != NULL );\n\n     ent = readdir( dir->dir );\n     if (!ent)\n          return errno ? errno2result( errno ) : DR_ITEMNOTFOUND;\n     else\n          strcpy( entry->name, ent->d_name );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_dir_rewind( DirectDir *dir )\n{\n     D_ASSERT( dir != NULL );\n\n     rewinddir( dir->dir );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_dir_close( DirectDir *dir )\n{\n     int err;\n\n     D_ASSERT( dir != NULL );\n\n     err = closedir( dir->dir );\n\n     dir->dir = NULL;\n\n     if (err < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_dir_remove( const char *name )\n{\n     D_ASSERT( name != NULL );\n\n     if (rmdir( name ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_open( DirectFile *file,\n                  const char *name,\n                  int         flags,\n                  mode_t      mode )\n{\n     D_ASSERT( file != NULL );\n     D_ASSERT( name != NULL );\n\n     file->file = NULL;\n\n     file->fd = open( name, flags, mode );\n     if (file->fd < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_read( DirectFile *file,\n                  void       *buffer,\n                  size_t      bytes,\n                  size_t     *ret_bytes )\n{\n     ssize_t num;\n\n     D_ASSERT( file != NULL );\n     D_ASSERT( buffer != NULL );\n\n     num = read( file->fd, buffer, bytes );\n     if (num < 0)\n          return errno2result( errno );\n\n     if (ret_bytes)\n          *ret_bytes = num;\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_write( DirectFile *file,\n                   const void *buffer,\n                   size_t      bytes,\n                   size_t     *ret_bytes )\n{\n     ssize_t num;\n\n     D_ASSERT( file != NULL );\n     D_ASSERT( buffer != NULL );\n\n     num = write( file->fd, buffer, bytes );\n     if (num < 0)\n          return errno2result( errno );\n\n     if (ret_bytes)\n          *ret_bytes = num;\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_seek( DirectFile *file,\n                  off_t       offset )\n{\n     D_ASSERT( file != NULL );\n\n     if (lseek( file->fd, offset, SEEK_CUR ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_seek_to( DirectFile *file,\n                     off_t       offset )\n{\n     D_ASSERT( file != NULL );\n\n     if (lseek( file->fd, offset, SEEK_SET ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_close( DirectFile *file )\n{\n     int err;\n\n     D_ASSERT( file != NULL );\n\n     if (file->file) {\n          err = fclose( file->file );\n\n          file->file = NULL;\n     }\n     else\n          err = close( file->fd );\n\n     file->fd = -1;\n\n     if (err < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_map( DirectFile            *file,\n                 void                  *addr,\n                 size_t                 offset,\n                 size_t                 bytes,\n                 DirectFilePermission   perms,\n                 void                 **ret_addr )\n{\n     void *map;\n     int   prot = 0;\n     int   flags = MAP_SHARED;\n\n     D_ASSERT( file != NULL );\n     D_ASSERT( ret_addr != NULL );\n\n     if (perms & DFP_READ)\n          prot |= PROT_READ;\n\n     if (perms & DFP_WRITE)\n          prot |= PROT_WRITE;\n\n     if (addr)\n          flags |= MAP_FIXED;\n\n     map = mmap( addr, bytes, prot, flags, file->fd, offset );\n     if (map == MAP_FAILED)\n          return errno2result( errno );\n\n     *ret_addr = map;\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_unmap( void   *addr,\n                   size_t  bytes )\n{\n     if (munmap( addr, bytes ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_get_info( DirectFile     *file,\n                      DirectFileInfo *ret_info )\n{\n     struct stat st;\n\n     D_ASSERT( file != NULL );\n     D_ASSERT( ret_info != NULL );\n\n     if (fstat( file->fd, &st ) < 0)\n          return errno2result( errno );\n\n     ret_info->flags = DFIF_SIZE;\n     ret_info->size  = st.st_size;\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_chmod( DirectFile *file,\n                   mode_t      mode )\n{\n     D_ASSERT( file != NULL );\n\n     if (fchmod( file->fd, mode ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_chown( DirectFile *file,\n                   uid_t       owner,\n                   gid_t       group )\n{\n     D_ASSERT( file != NULL );\n\n     if (fchown( file->fd, owner, group ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_truncate( DirectFile *file,\n                      off_t       length )\n{\n     D_ASSERT( file != NULL );\n\n     if (ftruncate( file->fd, length ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_file_get_string( DirectFile *file,\n                        char       *buf,\n                        size_t      length )\n{\n     D_ASSERT( file != NULL );\n     D_ASSERT( buf != NULL );\n\n     if (!file->file) {\n          file->file = fdopen( file->fd, \"r\" );\n          if (!file->file)\n               return errno2result( errno );\n     }\n\n     if (!fgets( buf, length, file->file )) {\n          if (feof( file->file ))\n               return DR_EOF;\n\n          return DR_FAILURE;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_popen( DirectFile *file,\n              const char *name,\n              int         flags )\n{\n     D_ASSERT( file != NULL );\n     D_ASSERT( name != NULL );\n\n     file->file = popen( name, (flags & O_WRONLY) ? \"w\" : (flags & O_RDWR) ? \"rw\" : \"r\" );\n     if (!file->file)\n          return errno2result( errno );\n\n     file->fd = fileno( file->file );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_pclose( DirectFile *file )\n{\n     D_ASSERT( file != NULL );\n     D_ASSERT( file->file != NULL );\n\n     if (pclose( file->file ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_access( const char *name,\n               int         flags )\n{\n     D_ASSERT( name != NULL );\n\n     if (access( name, flags ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_chmod( const char *name,\n              mode_t      mode )\n{\n     D_ASSERT( name != NULL );\n\n     if (chmod( name, mode ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_chown( const char *name,\n              uid_t       owner,\n              gid_t       group )\n{\n     D_ASSERT( name != NULL );\n\n     if (chown( name, owner, group ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_readlink( const char *name,\n                 char       *buf,\n                 size_t      length,\n                 ssize_t    *ret_length )\n{\n     ssize_t len;\n\n     D_ASSERT( name != NULL );\n\n     len = readlink( name, buf, length );\n     if (len < 0)\n          return errno2result( errno );\n\n     if (ret_length)\n          *ret_length = len;\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_unlink( const char *name )\n{\n     D_ASSERT( name != NULL );\n\n     if (unlink( name ) < 0)\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_filesystem_size( const char *name,\n                        size_t     *size )\n{\n     struct statfs stat;\n\n     D_ASSERT( name != NULL );\n\n     if (statfs( name, &stat ) < 0)\n          return errno2result( errno );\n\n     *size = stat.f_blocks * stat.f_bsize;\n\n     return DR_OK;\n}\n"
  },
  {
    "path": "lib/direct/os/nuttx/filesystem.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__NUTTX__FILESYSTEM_H__\n#define __DIRECT__OS__NUTTX__FILESYSTEM_H__\n\n#include <direct/os/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     DIR *dir;\n} DirectDir;\n\ntypedef struct {\n     int   fd;\n\n     FILE *file;\n} DirectFile;\n\n#endif\n"
  },
  {
    "path": "lib/direct/os/nuttx/log.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/os/log.h>\n#include <direct/messages.h>\n#include <direct/util.h>\n\n/**********************************************************************************************************************/\n\nstatic DirectResult init_stderr( DirectLog *log );\n\nstatic DirectResult init_file  ( DirectLog  *log, const char *filename );\n\n/**********************************************************************************************************************/\n\nDirectResult\ndirect_log_init( DirectLog  *log,\n                 const char *param )\n{\n     switch (log->type) {\n          case DLT_STDERR:\n               return init_stderr( log );\n\n          case DLT_FILE:\n               return init_file( log, param );\n\n          case DLT_UDP:\n          default:\n               break;\n     }\n\n     return DR_UNSUPPORTED;\n}\n\nDirectResult\ndirect_log_deinit( DirectLog *log )\n{\n     close( (long) log->data );\n\n     return DR_OK;\n}\n\n/**********************************************************************************************************************/\n\n__attribute__((no_instrument_function))\nstatic DirectResult\ncommon_log_write( DirectLog  *log,\n                  const char *buffer,\n                  size_t      bytes )\n{\n     ssize_t sz;\n\n     sz = write( (long) log->data, buffer, bytes );\n     if (sz < 0)\n          D_PERROR( \"Direct/Log: Could not write to log!\\n\" );\n\n     return DR_OK;\n}\n\n__attribute__((no_instrument_function))\nstatic DirectResult\ncommon_log_flush( DirectLog *log )\n{\n     if (log->type == DLT_STDERR && fflush( stderr ))\n          return errno2result( errno );\n\n     return DR_OK;\n}\n\n__attribute__((no_instrument_function))\nstatic DirectResult\nstderr_log_write( DirectLog  *log,\n                  const char *buffer,\n                  size_t      bytes )\n{\n     fwrite( buffer, bytes, 1, stderr );\n\n     return DR_OK;\n}\n\nstatic DirectResult\ninit_stderr( DirectLog *log )\n{\n     log->data = (void*)(long) dup( fileno( stderr ) );\n\n     log->write      = stderr_log_write;\n     log->flush      = common_log_flush;\n\n     return DR_OK;\n}\n\nstatic DirectResult\ninit_file( DirectLog  *log,\n           const char *filename )\n{\n     DirectResult ret;\n     int          fd;\n\n     fd = open( filename, O_WRONLY | O_CREAT | O_APPEND, 0664 );\n     if (fd < 0) {\n          ret = errno2result( errno );\n          D_PERROR( \"Direct/Log: Could not open '%s' for writing!\\n\", filename );\n          return ret;\n     }\n\n     log->data = (void*)(long) fd;\n\n     log->write = common_log_write;\n     log->flush = common_log_flush;\n\n     return DR_OK;\n}\n"
  },
  {
    "path": "lib/direct/os/nuttx/mem.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/os/mem.h>\n\n#if DIRECT_BUILD_SENTINELS\n\n#include <direct/debug.h>\n\nD_DEBUG_DOMAIN( Direct_Sentinels, \"Direct/Sentinels\", \"Direct Sentinels\" );\n\n#endif /* DIRECT_BUILD_SENTINELS */\n\n/**********************************************************************************************************************/\n\n#if DIRECT_BUILD_SENTINELS\n\n#define PREFIX_SENTINEL 8\n#define SUFFIX_SENTINEL 8\n\n#define TOTAL_SENTINEL  ((PREFIX_SENTINEL) + (SUFFIX_SENTINEL))\n\n__attribute__((no_instrument_function))\nstatic inline void\ninstall_sentinels( void *p, size_t size )\n{\n     size_t  i;\n     size_t *ps     = p;\n     u8     *prefix = p;\n     u8     *suffix = p + PREFIX_SENTINEL + size;\n\n     D_DEBUG_AT( Direct_Sentinels, \"%s( %p, \"_ZU\" )\\n\", __FUNCTION__, p, size );\n\n     *ps = size;\n\n     for (i = sizeof(size_t); i < PREFIX_SENTINEL; i++)\n          prefix[i] = i;\n\n     for (i = 0; i < SUFFIX_SENTINEL; i++)\n          suffix[i] = i;\n}\n\n__attribute__((no_instrument_function))\nstatic inline void\nremove_sentinels( void *p )\n{\n     size_t  i;\n     size_t *ps     = p;\n     u8     *prefix = p;\n     u8     *suffix = p + PREFIX_SENTINEL + *ps;\n\n     D_DEBUG_AT( Direct_Sentinels, \"%s( %p )\\n\", __FUNCTION__, p );\n\n     for (i = sizeof(size_t); i < PREFIX_SENTINEL; i++)\n          prefix[i] = 0;\n\n     for (i = 0; i < SUFFIX_SENTINEL; i++)\n          suffix[i] = 0;\n}\n\n__attribute__((no_instrument_function))\nstatic inline void\ncheck_sentinels( void *p )\n{\n     size_t  i;\n     size_t *ps     = p;\n     u8     *prefix = p;\n     u8     *suffix = p + PREFIX_SENTINEL + *ps;\n\n     for (i = sizeof(size_t); i < PREFIX_SENTINEL; i++) {\n          if (prefix[i] != i)\n               D_DEBUG_AT( Direct_Sentinels, \"Sentinel error at prefix[\"_ZU\"] (%u) of \"_ZU\" bytes allocation!\\n\",\n                           i, prefix[i], *ps );\n     }\n\n     for (i = 0; i < SUFFIX_SENTINEL; i++) {\n          if (suffix[i] != i)\n               D_DEBUG_AT( Direct_Sentinels, \"Sentinel error at suffix[\"_ZU\"] (%u) of \"_ZU\" bytes allocation!\\n\",\n                           i, suffix[i], *ps );\n     }\n}\n\n__attribute__((no_instrument_function))\nvoid *\ndirect_malloc( size_t bytes )\n{\n     void *p = bytes ? malloc( bytes + TOTAL_SENTINEL ) : NULL;\n\n     if (!p)\n          return NULL;\n\n     install_sentinels( p, bytes );\n\n     return p + PREFIX_SENTINEL;\n}\n\n__attribute__((no_instrument_function))\nvoid *\ndirect_calloc( size_t count, size_t bytes)\n{\n     void *p = (count && bytes) ? calloc( 1, count * bytes + TOTAL_SENTINEL ) : NULL;\n\n     if (!p)\n          return NULL;\n\n     install_sentinels( p, count * bytes );\n\n     return p + PREFIX_SENTINEL;\n}\n\n__attribute__((no_instrument_function))\nvoid *\ndirect_realloc( void *mem, size_t bytes )\n{\n     void *p = mem ? mem - PREFIX_SENTINEL : NULL;\n\n     if (!mem)\n          return direct_malloc( bytes );\n\n     check_sentinels( p );\n\n     if (!bytes) {\n          direct_free( mem );\n          return NULL;\n     }\n\n     p = realloc( p, bytes + TOTAL_SENTINEL );\n\n     if (!p)\n          return NULL;\n\n     install_sentinels( p, bytes );\n\n     return p + PREFIX_SENTINEL;\n}\n\n__attribute__((no_instrument_function))\nchar *\ndirect_strdup( const char *str )\n{\n     int   n = strlen( str );\n     void *p = malloc( n+1 + TOTAL_SENTINEL );\n\n     if (!p)\n          return NULL;\n\n     memcpy( p + PREFIX_SENTINEL, str, n + 1 );\n\n     install_sentinels( p, n + 1 );\n\n     return p + PREFIX_SENTINEL;\n}\n\n__attribute__((no_instrument_function))\nvoid\ndirect_free( void *mem )\n{\n     void *p = mem ? mem - PREFIX_SENTINEL : NULL;\n\n     if (p) {\n          check_sentinels( p );\n\n          remove_sentinels( p );\n\n          free( p );\n     }\n}\n\n#else /* DIRECT_BUILD_SENTINELS */\n\n__attribute__((no_instrument_function))\nvoid *\ndirect_malloc( size_t bytes )\n{\n     return malloc( bytes );\n}\n\n__attribute__((no_instrument_function))\nvoid *\ndirect_calloc( size_t count, size_t bytes)\n{\n     return calloc( count, bytes );\n}\n\n__attribute__((no_instrument_function))\nvoid *\ndirect_realloc( void *mem, size_t bytes )\n{\n     return realloc( mem, bytes );\n}\n\n__attribute__((no_instrument_function))\nchar *\ndirect_strdup( const char *str )\n{\n     return strdup( str );\n}\n\n__attribute__((no_instrument_function))\nvoid\ndirect_free( void *mem )\n{\n     free( mem );\n}\n\n#endif /* DIRECT_BUILD_SENTINELS */\n"
  },
  {
    "path": "lib/direct/os/nuttx/mutex.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/messages.h>\n#include <direct/os/mutex.h>\n#include <direct/util.h>\n\n/**********************************************************************************************************************/\n\nDirectResult\ndirect_mutex_init( DirectMutex *mutex )\n{\n     int erno = pthread_mutex_init( &mutex->lock, NULL );\n\n     return errno2result( erno );\n}\n\nDirectResult\ndirect_recursive_mutex_init( DirectMutex *mutex )\n{\n     DirectResult        ret = DR_OK;\n     int                 erno;\n     pthread_mutexattr_t attr;\n\n     pthread_mutexattr_init( &attr );\n     pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );\n     erno = pthread_mutex_init( &mutex->lock, &attr );\n     if (erno) {\n          ret = errno2result( erno );\n          D_PERROR( \"Direct/Mutex: Could not initialize recursive mutex!\\n\" );\n     }\n\n     pthread_mutexattr_destroy( &attr );\n\n     return ret;\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_mutex_lock( DirectMutex *mutex )\n{\n     int erno = pthread_mutex_lock( &mutex->lock );\n\n     return errno2result( erno );\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_mutex_unlock( DirectMutex *mutex )\n{\n     int erno = pthread_mutex_unlock( &mutex->lock );\n\n     return errno2result( erno );\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_mutex_trylock( DirectMutex *mutex )\n{\n     int erno = pthread_mutex_trylock( &mutex->lock );\n\n     return errno2result( erno );\n}\n\nDirectResult\ndirect_mutex_deinit( DirectMutex *mutex )\n{\n     int erno = pthread_mutex_destroy( &mutex->lock );\n\n     return errno2result( erno );\n}\n\nDirectResult\ndirect_rwlock_init( DirectRWLock *rwlock )\n{\n     int erno = pthread_rwlock_init( &rwlock->lock, NULL );\n\n     return errno2result( erno );\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_rwlock_rdlock( DirectRWLock *rwlock )\n{\n     int erno = pthread_rwlock_rdlock( &rwlock->lock );\n\n     return errno2result( erno );\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_rwlock_wrlock( DirectRWLock *rwlock )\n{\n     int erno = pthread_rwlock_wrlock( &rwlock->lock );\n\n     return errno2result( erno );\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_rwlock_unlock( DirectRWLock *rwlock )\n{\n     int erno = pthread_rwlock_unlock( &rwlock->lock );\n\n     return errno2result( erno );\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_rwlock_trywrlock( DirectRWLock *rwlock )\n{\n     int erno = pthread_rwlock_trywrlock( &rwlock->lock );\n\n     return errno2result( erno );\n}\n\nDirectResult\ndirect_rwlock_deinit( DirectRWLock *rwlock )\n{\n     int erno = pthread_rwlock_destroy( &rwlock->lock );\n\n     return errno2result( erno );\n}\n"
  },
  {
    "path": "lib/direct/os/nuttx/mutex.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__NUTTX__MUTEX_H__\n#define __DIRECT__OS__NUTTX__MUTEX_H__\n\n#include <direct/os/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     pthread_mutex_t lock;\n} DirectMutex;\n\n#define DIRECT_MUTEX_INITIALIZER() { PTHREAD_MUTEX_INITIALIZER }\n\ntypedef struct {\n     pthread_rwlock_t lock;\n} DirectRWLock;\n\n#endif\n"
  },
  {
    "path": "lib/direct/os/nuttx/signals.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/conf.h>\n#include <direct/list.h>\n#include <direct/mem.h>\n#include <direct/messages.h>\n#include <direct/os/mutex.h>\n#include <direct/os/signals.h>\n#include <direct/trace.h>\n#include <direct/util.h>\n\nD_DEBUG_DOMAIN( Direct_Signals, \"Direct/Signals\", \"Direct Signals handling\" );\n\n/**********************************************************************************************************************/\n\nstruct __D_DirectSignalHandler {\n     DirectLink               link;\n\n     int                      magic;\n\n     int                      num;\n     DirectSignalHandlerFunc  func;\n     void                    *ctx;\n\n     bool                     removed;\n};\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int              signum;\n     struct sigaction old_action;\n     struct sigaction new_action;\n} SigHandled;\n\nstatic int sigs_to_handle[] = {\n     SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGSEGV, SIGPIPE, SIGTERM, SIGXCPU, SIGXFSZ,\n     SIGSYS\n};\n\n#define NUM_SIGS_TO_HANDLE (D_ARRAY_SIZE(sigs_to_handle))\n\nstatic SigHandled   sigs_handled[NUM_SIGS_TO_HANDLE];\n\nstatic DirectLink  *handlers = NULL;\nstatic DirectMutex  handlers_lock;\n\nstatic void install_handlers( void );\nstatic void remove_handlers ( void );\n\n/**********************************************************************************************************************/\n\nDirectResult\ndirect_signals_initialize()\n{\n     D_DEBUG_AT( Direct_Signals, \"%s() initializing...\\n\", __FUNCTION__ );\n\n     direct_recursive_mutex_init( &handlers_lock );\n\n     install_handlers();\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_signals_shutdown()\n{\n     D_DEBUG_AT( Direct_Signals, \"%s() shutting down...\\n\", __FUNCTION__ );\n\n     remove_handlers();\n\n     direct_mutex_deinit( &handlers_lock );\n\n     return DR_OK;\n}\n\nvoid\ndirect_signals_block_all()\n{\n     sigset_t signals;\n\n     D_DEBUG_AT( Direct_Signals, \"Blocking all signals from now on\\n\" );\n\n     sigfillset( &signals );\n\n     sigprocmask( SIG_BLOCK, &signals, NULL );\n}\n\nDirectResult\ndirect_signal_handler_add( int                       num,\n                           DirectSignalHandlerFunc   func,\n                           void                     *ctx,\n                           DirectSignalHandler     **ret_handler )\n{\n     DirectSignalHandler *handler;\n\n     D_ASSERT( func != NULL );\n     D_ASSERT( ret_handler != NULL );\n\n     D_DEBUG_AT( Direct_Signals, \"Adding handler %p for signal %d with context %p...\\n\", func, num, ctx );\n\n     handler = D_CALLOC( 1, sizeof(DirectSignalHandler) );\n     if (!handler) {\n          return DR_NOLOCALMEMORY;\n     }\n\n     handler->num  = num;\n     handler->func = func;\n     handler->ctx  = ctx;\n\n     D_MAGIC_SET( handler, DirectSignalHandler );\n\n     direct_mutex_lock( &handlers_lock );\n     direct_list_append( &handlers, &handler->link );\n     direct_mutex_unlock( &handlers_lock );\n\n     *ret_handler = handler;\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_signal_handler_remove( DirectSignalHandler *handler )\n{\n     D_MAGIC_ASSERT( handler, DirectSignalHandler );\n\n     D_DEBUG_AT( Direct_Signals, \"Removing handler %p for signal %d with context %p...\\n\",\n                 handler->func, handler->num, handler->ctx );\n\n     /* Mark the handler for removal, freeing will actually come later. */\n     handler->removed = true;\n\n     return DR_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic void\ncall_handlers( int   num,\n               void *addr )\n{\n     DirectSignalHandler *handler, *temp;\n     DirectLink          *garbage = NULL;\n\n     if (num == SIGPIPE)\n          num = DIRECT_SIGNAL_DUMP_STACK;\n\n     /* Loop through all handlers. */\n     direct_mutex_lock( &handlers_lock );\n\n     direct_list_foreach_safe (handler, temp, handlers) {\n          if (handler->removed) {\n               direct_list_remove( &handlers, &handler->link );\n               direct_list_append( &garbage, &handler->link );\n               continue;\n          }\n\n          D_LOG( Direct_Signals, FATAL, \"  --> %d\\n\", handler->num );\n\n          if (handler->num != num && handler->num != DIRECT_SIGNAL_ANY)\n               continue;\n\n          if (handler->num == DIRECT_SIGNAL_ANY && num == DIRECT_SIGNAL_DUMP_STACK)\n               continue;\n\n          switch (handler->func( num, addr, handler->ctx )) {\n               case DSHR_OK:\n                    break;\n\n               case DSHR_REMOVE:\n                    direct_list_remove( &handlers, &handler->link );\n                    direct_list_append( &garbage, &handler->link );\n                    break;\n\n               case DSHR_RESUME:\n                    D_LOG( Direct_Signals, FATAL, \"    '-> cured!\\n\" );\n                    direct_mutex_unlock( &handlers_lock );\n                    return;\n\n               default:\n                    D_BUG( \"unknown result\" );\n                    break;\n          }\n     }\n\n     direct_list_foreach_safe (handler, temp, handlers) {\n          D_MAGIC_CLEAR( handler );\n          D_FREE( handler );\n     }\n\n     direct_mutex_unlock( &handlers_lock );\n}\n\nstatic void\nsignal_handler( int        num,\n                siginfo_t *info,\n                void      *uctx )\n{\n     if (info && info > (siginfo_t*) 0x100)\n          D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d <--\\n\", info->si_signo );\n     else\n          D_LOG( Direct_Signals, FATAL, \"  --> Caught signal %d, no siginfo available <--\\n\", num );\n\n     direct_trace_print_stacks();\n\n     call_handlers( num, NULL );\n\n     remove_handlers();\n\n     exit( -num );\n}\n\n/**********************************************************************************************************************/\n\nstatic void\ninstall_handlers()\n{\n     int i;\n\n     D_DEBUG_AT( Direct_Signals, \"%s()\\n\", __FUNCTION__ );\n\n     for (i = 0; i < NUM_SIGS_TO_HANDLE; i++) {\n          sigs_handled[i].signum = -1;\n\n          if (direct_config->sighandler && !sigismember( &direct_config->dont_catch, sigs_to_handle[i] )) {\n               struct sigaction action;\n               int              signum = sigs_to_handle[i];\n\n               action.sa_sigaction = signal_handler;\n               action.sa_flags     = SA_SIGINFO;\n\n               if (signum != SIGSEGV)\n                    action.sa_flags |= SA_NODEFER;\n\n               sigemptyset( &action.sa_mask );\n\n               if (sigaction( signum, &action, &sigs_handled[i].old_action )) {\n                    D_PERROR( \"Direct/Signals: Unable to install signal handler for signal %d!\\n\", signum );\n                    continue;\n               }\n\n               sigs_handled[i].signum = signum;\n          }\n     }\n}\n\nstatic void\nremove_handlers()\n{\n     int i;\n\n     D_DEBUG_AT( Direct_Signals, \"%s()\\n\", __FUNCTION__ );\n\n     for (i = 0; i < NUM_SIGS_TO_HANDLE; i++) {\n          if (sigs_handled[i].signum != -1) {\n               int signum = sigs_handled[i].signum;\n\n               if (sigaction( signum, &sigs_handled[i].old_action, NULL )) {\n                    D_PERROR( \"Direct/Signals: Unable to restore previous handler for signal %d!\\n\", signum );\n               }\n\n               sigs_handled[i].signum = -1;\n          }\n     }\n}\n"
  },
  {
    "path": "lib/direct/os/nuttx/system.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/os/system.h>\n#include <direct/util.h>\n\n/**********************************************************************************************************************/\n\n__attribute__((no_instrument_function))\nvoid\ndirect_sched_yield()\n{\n     sched_yield();\n}\n\nlong\ndirect_pagesize()\n{\n     return sysconf( _SC_PAGESIZE );\n}\n\nunsigned long\ndirect_page_align( unsigned long value )\n{\n     unsigned long mask = sysconf( _SC_PAGESIZE ) - 1;\n\n     return (value + mask) & ~mask;\n}\n\n__attribute__((no_instrument_function))\npid_t\ndirect_getpid()\n{\n     return getpid();\n}\n\n__attribute__((no_instrument_function))\npid_t\ndirect_gettid()\n{\n     return gettid();\n}\n\nvoid\ndirect_trap( const char *domain,\n             int         sig )\n{\n     exit(0);\n}\n\nDirectResult\ndirect_kill( pid_t pid,\n             int   sig )\n{\n     if (kill( pid, sig ) < 0) {\n          if (errno == ESRCH)\n               return DR_NOSUCHINSTANCE;\n          else\n               return errno2result( errno );\n     }\n\n     return DR_OK;\n}\n\nvoid\ndirect_sync()\n{\n}\n\nuid_t\ndirect_geteuid()\n{\n     return geteuid();\n}\n\nchar *\ndirect_getenv( const char *name )\n{\n     return getenv( name );\n}\n\nDirectResult\ndirect_futex( int                   *uaddr,\n              int                    op,\n              int                    val,\n              const struct timespec *timeout,\n              int                   *uaddr2,\n              int                    val3 )\n{\n     return DR_UNIMPLEMENTED;\n}\n\nbool\ndirect_madvise()\n{\n     return false;\n}\n"
  },
  {
    "path": "lib/direct/os/nuttx/thread.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/conf.h>\n#include <direct/debug.h>\n#include <direct/messages.h>\n#include <direct/os/mem.h>\n#include <direct/os/system.h>\n#include <direct/os/thread.h>\n#include <direct/trace.h>\n\nD_DEBUG_DOMAIN( Direct_Thread,     \"Direct/Thread\",      \"Direct Thread Management\" );\nD_DEBUG_DOMAIN( Direct_ThreadInit, \"Direct/Thread/Init\", \"Direct Thread Init\" );\n\n/**********************************************************************************************************************/\n\nstatic pthread_key_t thread_key;\nstatic DirectOnce    thread_init_once = DIRECT_ONCE_INIT();\n\n/*\n * Wrapper around pthread's main routine to pass additional arguments\n * and setup things like signal masks and scheduling priorities.\n */\n__attribute__((no_instrument_function))\nstatic void *direct_thread_main( void *arg );\n\n/**********************************************************************************************************************/\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_once( DirectOnce            *once,\n             DirectOnceInitHandler  handler )\n{\n     int erno = pthread_once( &once->once, handler );\n\n     return errno2result( erno );\n}\n\n__attribute__((no_instrument_function))\nstatic void\ninit_once( void )\n{\n     /* Create the key for the TSD (thread specific data). */\n     pthread_key_create( &thread_key, NULL );\n}\n\nDirectResult\ndirect_thread_init( DirectThread *thread )\n{\n     int                erno;\n     pthread_attr_t     attr;\n     struct sched_param param;\n     int                policy;\n     int                priority;\n\n     D_DEBUG_AT( Direct_ThreadInit, \"%s( %p, '%s' )\\n\", __FUNCTION__, thread->main, thread->name );\n\n     direct_once( &thread_init_once, init_once );\n\n     /* Initialize scheduling and other parameters. */\n     pthread_attr_init( &attr );\n\n     pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED );\n\n     /* Select scheduler. */\n     switch (direct_config->thread_scheduler) {\n          case DCTS_FIFO:\n               policy = SCHED_FIFO;\n               break;\n\n          case DCTS_RR:\n               policy = SCHED_RR;\n               break;\n\n          case DCTS_SPORADIC:\n               policy = SCHED_SPORADIC;\n               break;\n\n          default:\n               policy = SCHED_OTHER;\n               break;\n     }\n\n     if (pthread_attr_setschedpolicy( &attr, policy ))\n          D_PERROR( \"Direct/Thread/Init: Could not set scheduling policy to %s!\\n\", direct_thread_policy_name( policy ) );\n\n     /* Read (back) value. */\n     pthread_attr_getschedpolicy( &attr, &policy );\n     thread->policy = policy;\n\n     /* Select priority. */\n     switch (thread->type) {\n          case DTT_CLEANUP:\n          case DTT_INPUT:\n          case DTT_OUTPUT:\n          case DTT_MESSAGING:\n          case DTT_CRITICAL:\n               priority = thread->type * direct_config->thread_priority_scale / 100;\n               break;\n\n          default:\n               priority = direct_config->thread_priority;\n               break;\n     }\n\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> priority %d [%d;%d]\\n\", priority,\n                 sched_get_priority_min( policy ), sched_get_priority_max( policy ) );\n\n     if (priority < sched_get_priority_min( policy ))\n          priority = sched_get_priority_min( policy );\n\n     if (priority > sched_get_priority_max( policy ))\n          priority = sched_get_priority_max( policy );\n\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> policy %s with priority set to %d\\n\", direct_thread_policy_name( policy ),\n                 priority );\n\n     param.sched_priority = priority;\n\n     if (pthread_attr_setschedparam( &attr, &param ))\n          D_PERROR( \"Direct/Thread/Init: Could not set scheduling priority to %d!\\n\", priority );\n\n     /* Select stack size. */\n     if (direct_config->thread_stack_size > 0) {\n          if (pthread_attr_setstacksize( &attr, direct_config->thread_stack_size ))\n               D_PERROR( \"Direct/Thread/Init: Could not set stack size to %d!\\n\", direct_config->thread_stack_size );\n     }\n\n     erno = pthread_create( &thread->handle, &attr, direct_thread_main, thread );\n     if (erno)\n          return errno2result( erno );\n\n     /* Read (back) value. */\n     pthread_attr_getstacksize( &attr, &thread->stack_size );\n     pthread_attr_getschedparam( &attr, &param );\n     thread->priority = param.sched_priority;\n\n     pthread_attr_destroy( &attr );\n\n     return DR_OK;\n}\n\nvoid\ndirect_thread_deinit( DirectThread *thread )\n{\n     D_MAGIC_ASSERT( thread, DirectThread );\n\n     D_ASSUME( !pthread_equal( thread->handle, pthread_self() ) );\n     D_ASSUME( !thread->detached );\n\n     D_DEBUG_AT( Direct_ThreadInit, \"%s( %p, '%s' %d )\\n\", __FUNCTION__, thread->main, thread->name, thread->tid );\n\n     if (!thread->joined && !pthread_equal( thread->handle, pthread_self() )) {\n          if (thread->canceled)\n               D_DEBUG_AT( Direct_ThreadInit, \"  -> canceled but not joined!\\n\" );\n          else {\n               D_DEBUG_AT( Direct_ThreadInit, \"  -> still running!\\n\" );\n\n               if (thread->name)\n                    D_ERROR( \"Direct/Thread/Init: Canceling '%s' (%d)!\\n\", thread->name, thread->tid );\n               else\n                    D_ERROR( \"Direct/Thread/Init: Canceling %d!\\n\", thread->tid );\n\n               pthread_cancel( thread->handle );\n          }\n\n          pthread_join( thread->handle, NULL );\n     }\n}\n\n__attribute__((no_instrument_function))\nvoid\ndirect_thread_setcancelstate( DirectThreadCancelState state )\n{\n     switch (state) {\n          case DIRECT_THREAD_CANCEL_ENABLE:\n               pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL );\n\n          case DIRECT_THREAD_CANCEL_DISABLE:\n               pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, NULL );\n     }\n}\n\n__attribute__((no_instrument_function))\nDirectThread *\ndirect_thread_self()\n{\n     DirectThread *thread;\n\n     direct_once( &thread_init_once, init_once );\n\n     thread = pthread_getspecific( thread_key );\n\n     /* Support this function for non-direct threads. */\n     if (!thread) {\n          thread = calloc( 1, sizeof(DirectThread) );\n          if (!thread) {\n               D_OOM();\n               return NULL;\n          }\n\n          thread->handle = pthread_self();\n          thread->tid    = direct_gettid();\n\n          D_MAGIC_SET( thread, DirectThread );\n\n          pthread_setspecific( thread_key, thread );\n     }\n\n     return thread;\n}\n\n#if defined(__GNUC__) && __GNUC__ >= 10\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wanalyzer-malloc-leak\"\n#endif\n__attribute__((no_instrument_function))\nconst char *\ndirect_thread_self_name()\n{\n     DirectThread *thread = direct_thread_self();\n     char name[CONFIG_TASK_NAME_SIZE];\n\n     /* This function is called by debugging functions, e.g. debug messages, assertions etc.\n        Therefore no assertions are made here, because they would loop forever if they fail. */\n\n     if (!thread)\n          return NULL;\n\n     if (!thread->name) {\n          prctl( PR_GET_NAME, name, 0, 0, 0 );\n          thread->name = strdup( name );\n     }\n\n     return thread->name;\n}\n\nvoid\ndirect_thread_set_name( const char *name )\n{\n     char         *copy;\n     DirectThread *thread;\n\n     D_DEBUG_AT( Direct_Thread, \"%s( '%s' )\\n\", __FUNCTION__, name );\n\n     thread = direct_thread_self();\n     if (!thread)\n          return;\n\n     /* Duplicate string. */\n     copy = strdup( name );\n     if (!copy) {\n          D_OOM();\n          return;\n     }\n\n     /* Free old string. */\n     if (thread->name)\n          free( thread->name );\n\n     /* Keep the copy. */\n     thread->name = copy;\n}\n#if defined(__GNUC__) && __GNUC__ >= 10\n#pragma GCC diagnostic pop\n#endif\n\nvoid\ndirect_thread_cancel( DirectThread *thread )\n{\n     D_MAGIC_ASSERT( thread, DirectThread );\n     D_ASSERT( thread->handle != -1 );\n     D_ASSERT( !pthread_equal( thread->handle, pthread_self() ) );\n\n     D_ASSUME( !thread->canceled );\n\n     D_DEBUG_AT( Direct_Thread, \"%s( %p, '%s' %d )\\n\", __FUNCTION__, thread->main, thread->name, thread->tid );\n\n     thread->canceled = true;\n\n     pthread_cancel( thread->handle );\n}\n\nvoid\ndirect_thread_detach( DirectThread *thread )\n{\n     D_MAGIC_ASSERT( thread, DirectThread );\n     D_ASSERT( thread->handle != -1 );\n     D_ASSERT( !pthread_equal( thread->handle, pthread_self() ) );\n\n     D_ASSUME( !thread->canceled );\n\n     D_DEBUG_AT( Direct_Thread, \"%s( %p, '%s' %d )\\n\", __FUNCTION__, thread->main, thread->name, thread->tid );\n\n     thread->detached = true;\n\n     pthread_detach( thread->handle );\n}\n\nvoid\ndirect_thread_testcancel( DirectThread *thread )\n{\n     D_MAGIC_ASSERT( thread, DirectThread );\n     D_ASSERT( thread->handle != -1 );\n     D_ASSERT( pthread_equal( thread->handle, pthread_self() ) );\n\n     /* Quick check before calling the pthread function. */\n     if (thread->canceled)\n          pthread_testcancel();\n}\n\nvoid\ndirect_thread_join( DirectThread *thread )\n{\n     D_MAGIC_ASSERT( thread, DirectThread );\n     D_ASSERT( thread->handle != -1 );\n\n     D_ASSUME( !pthread_equal( thread->handle, pthread_self() ) );\n     D_ASSUME( !thread->joining );\n     D_ASSUME( !thread->joined );\n     D_ASSUME( !thread->detached );\n\n     D_DEBUG_AT( Direct_Thread, \"%s( %p, '%s' %d )\\n\", __FUNCTION__, thread->main, thread->name, thread->tid );\n\n     if (thread->detached) {\n          D_DEBUG_AT( Direct_Thread, \"  -> detached\\n\" );\n          return;\n     }\n\n     if (!thread->joining && !pthread_equal( thread->handle, pthread_self() )) {\n          thread->joining = true;\n\n          D_DEBUG_AT( Direct_Thread, \"  -> joining...\\n\" );\n\n          pthread_join( thread->handle, NULL );\n\n          thread->joined = true;\n\n          D_DEBUG_AT( Direct_Thread, \"  -> joined\\n\" );\n     }\n}\n\nvoid\ndirect_thread_kill( DirectThread *thread,\n                    int           signal )\n{\n     D_MAGIC_ASSERT( thread, DirectThread );\n     D_ASSERT( thread->handle != -1 );\n\n     D_DEBUG_AT( Direct_Thread, \"%s( %p, '%s' %d, signal %d )\\n\", __FUNCTION__,\n                 thread->main, thread->name, thread->tid, signal );\n\n     pthread_kill( thread->handle, signal );\n}\n\nvoid\ndirect_thread_sleep( long long micros )\n{\n     usleep( micros );\n}\n\nvoid\ndirect_thread_atfork( DirectThreadPrepareHandler prepare,\n                      DirectThreadParentHandler  parent,\n                      DirectThreadChildHandler   child )\n{\n     pthread_atfork( prepare, parent, child );\n}\n\n/**********************************************************************************************************************/\n\nconst char *\ndirect_thread_type_name( DirectThreadType type )\n{\n     switch (type) {\n          case DTT_DEFAULT:\n               return \"DEFAULT\";\n\n          case DTT_CLEANUP:\n               return \"CLEANUP\";\n\n          case DTT_INPUT:\n               return \"INPUT\";\n\n          case DTT_OUTPUT:\n               return \"OUTPUT\";\n\n          case DTT_MESSAGING:\n               return \"MESSAGING\";\n\n          case DTT_CRITICAL:\n               return \"CRITICAL\";\n     }\n\n     return \"<unknown>\";\n}\n\nconst char *\ndirect_thread_policy_name( int policy )\n{\n     switch (policy) {\n          case SCHED_OTHER:\n               return \"OTHER\";\n\n          case SCHED_FIFO:\n               return \"FIFO\";\n\n          case SCHED_RR:\n               return \"RR\";\n\n          case SCHED_SPORADIC:\n               return \"SPORADIC\";\n     }\n\n     return \"<unknown>\";\n}\n\n/**********************************************************************************************************************/\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_tls_register( DirectTLS *tls,\n                     DirectTLSDestructor  destructor )\n{\n     int erno = pthread_key_create( &tls->key, destructor );\n\n     return errno2result( erno );\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_tls_unregister( DirectTLS *tls )\n{\n     int erno;\n\n     erno = pthread_key_delete( tls->key );\n     if (erno)\n          return errno2result( erno );\n\n     tls->key = (pthread_key_t) -1;\n\n     return DR_OK;\n}\n\n__attribute__((no_instrument_function))\nvoid *\ndirect_tls_get( DirectTLS *tls )\n{\n     void *value;\n\n     value = pthread_getspecific( tls->key );\n\n     return value;\n}\n\n__attribute__((no_instrument_function))\nDirectResult\ndirect_tls_set( DirectTLS *tls,\n                void      *value )\n{\n     int erno = pthread_setspecific( tls->key, value );\n\n     return errno2result( erno );\n}\n\n/**********************************************************************************************************************/\n\nstatic void\ndirect_thread_cleanup( void *arg )\n{\n     DirectThread *thread = arg;\n\n     D_MAGIC_ASSERT( thread, DirectThread );\n\n     D_DEBUG_AT( Direct_Thread, \"%s( %p, '%s' %d )\\n\", __FUNCTION__, thread->main, thread->name, thread->tid );\n\n     if (thread->trace_buffer)\n          direct_trace_free_buffer( thread->trace_buffer );\n\n     if (thread->detached) {\n          D_MAGIC_CLEAR( thread );\n\n          if (thread->name)\n               free( thread->name );\n\n          free( thread );\n     }\n}\n\n__attribute__((no_instrument_function))\nstatic void *\ndirect_thread_main( void *arg )\n{\n     void         *res;\n     DirectThread *thread = arg;\n\n     prctl( PR_SET_NAME, thread->name, 0, 0, 0 );\n\n     pthread_setspecific( thread_key, thread );\n\n     D_DEBUG_AT( Direct_ThreadInit, \"%s( %p )\\n\", __FUNCTION__, arg );\n\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> starting...\\n\" );\n\n     D_MAGIC_ASSERT( thread, DirectThread );\n\n     pthread_cleanup_push( direct_thread_cleanup, thread );\n\n     thread->tid = direct_gettid();\n\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> tid %d\\n\", thread->tid );\n\n     _direct_thread_call_init_handlers( thread );\n\n     /* Have all signals handled by the main thread. */\n     if (direct_config->thread_block_signals) {\n          sigset_t signals;\n          sigfillset( &signals );\n          sigprocmask( SIG_BLOCK, &signals, NULL );\n     }\n\n     /* Lock the thread mutex. */\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> locking...\\n\" );\n     direct_mutex_lock( &thread->lock );\n\n     /* Indicate that our initialization has completed. */\n     thread->init = true;\n\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> signalling...\\n\" );\n     direct_waitqueue_signal( &thread->cond );\n\n     /* Unlock the thread mutex. */\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> unlocking...\\n\" );\n     direct_mutex_unlock( &thread->lock );\n\n     if (thread->joining) {\n          D_DEBUG_AT( Direct_ThreadInit, \"  -> being joined before entering main routine!\\n\" );\n          return NULL;\n     }\n\n     /* Call main routine. */\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> running...\\n\" );\n     res = thread->main( thread, thread->arg );\n\n     D_DEBUG_AT( Direct_Thread, \"  -> returning %p from '%s' (%s, %d)...\\n\",\n                 res, thread->name, direct_thread_type_name( thread->type ), thread->tid );\n\n     pthread_cleanup_pop( 1 );\n\n     return res;\n}\n"
  },
  {
    "path": "lib/direct/os/nuttx/thread.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__NUTTX__THREAD_H__\n#define __DIRECT__OS__NUTTX__THREAD_H__\n\n#include <direct/os/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef pthread_t DirectThreadHandle;\n\ntypedef struct {\n     pthread_once_t once;\n} DirectOnce;\n\n#define DIRECT_ONCE_INIT() { PTHREAD_ONCE_INIT }\n\ntypedef struct {\n     pthread_key_t key;\n} DirectTLS;\n\n#endif\n"
  },
  {
    "path": "lib/direct/os/nuttx/types.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__NUTTX__TYPES_H__\n#define __DIRECT__OS__NUTTX__TYPES_H__\n\n#include <alloca.h>\n#include <fcntl.h>\n#include <grp.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/ioctl.h>\n#include <sys/mman.h>\n#include <sys/prctl.h>\n#include <sys/stat.h>\n#include <sys/statfs.h>\n#include <sys/time.h>\n\ntypedef unsigned int unichar;\n\ntypedef unsigned char          u8;\ntypedef unsigned short         u16;\ntypedef unsigned int           u32;\ntypedef unsigned long long int u64;\n\ntypedef signed char            s8;\ntypedef short int              s16;\ntypedef int                    s32;\ntypedef long long int          s64;\n\n#define _ZD \"%zd\"\n#define _ZU \"%zu\"\n#define _ZUn(x) \"%\" #x \"zu\"\n\n#endif\n"
  },
  {
    "path": "lib/direct/os/nuttx/waitqueue.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__NUTTX__WAITQUEUE_H__\n#define __DIRECT__OS__NUTTX__WAITQUEUE_H__\n\n#include <direct/os/mutex.h>\n#include <direct/util.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     pthread_cond_t cond;\n} DirectWaitQueue;\n\nstatic inline DirectResult\ndirect_waitqueue_init( DirectWaitQueue *queue )\n{\n     int erno = pthread_cond_init( &queue->cond, NULL );\n\n     return errno2result( erno );\n}\n\nstatic inline DirectResult\ndirect_waitqueue_wait( DirectWaitQueue *queue,\n                       DirectMutex     *mutex )\n{\n     int erno = pthread_cond_wait( &queue->cond, &mutex->lock );\n\n     return errno2result( erno );\n}\n\nstatic inline DirectResult\ndirect_waitqueue_wait_timeout( DirectWaitQueue *queue,\n                               DirectMutex     *mutex,\n                               unsigned long    micros )\n{\n     struct timeval  now;\n     struct timespec timeout;\n     long            seconds      = micros / 1000000;\n     long            nano_seconds = (micros % 1000000) * 1000;\n\n     gettimeofday( &now, NULL );\n\n     timeout.tv_sec  = now.tv_sec + seconds;\n     timeout.tv_nsec = (now.tv_usec * 1000) + nano_seconds;\n\n     timeout.tv_sec  += timeout.tv_nsec / 1000000000;\n     timeout.tv_nsec %= 1000000000;\n\n     if (pthread_cond_timedwait( &queue->cond, &mutex->lock, &timeout ) == ETIMEDOUT)\n          return DR_TIMEOUT;\n\n     return DR_OK;\n}\n\nstatic inline DirectResult\ndirect_waitqueue_signal( DirectWaitQueue *queue )\n{\n     int erno = pthread_cond_signal( &queue->cond );\n\n     return errno2result( erno );\n}\n\nstatic inline DirectResult\ndirect_waitqueue_broadcast( DirectWaitQueue *queue )\n{\n     int erno = pthread_cond_broadcast( &queue->cond );\n\n     return errno2result( erno );\n}\n\nstatic inline DirectResult\ndirect_waitqueue_deinit( DirectWaitQueue *queue )\n{\n     int erno = pthread_cond_destroy( &queue->cond );\n\n     return errno2result( erno );\n}\n\n#endif\n"
  },
  {
    "path": "lib/direct/os/signals.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__SIGNALS_H__\n#define __DIRECT__OS__SIGNALS_H__\n\n#include <direct/os/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     DSHR_OK     = 0x00000000,\n     DSHR_REMOVE = 0x00000001,\n     DSHR_RESUME = 0x00000002\n} DirectSignalHandlerResult;\n\ntypedef DirectSignalHandlerResult (*DirectSignalHandlerFunc)( int num, void *addr, void *ctx );\n\n/*\n * Signal number to use when registering a handler for any interrupt.\n */\n#define DIRECT_SIGNAL_ANY        -1\n#define DIRECT_SIGNAL_DUMP_STACK -2\n\n/**********************************************************************************************************************/\n\nDirectResult DIRECT_API direct_signals_initialize   ( void );\n\nDirectResult DIRECT_API direct_signals_shutdown     ( void );\n\n/*\n * Modifies the current thread's signal mask to block everything.\n */\nvoid         DIRECT_API direct_signals_block_all    ( void );\n\nDirectResult DIRECT_API direct_signal_handler_add   ( int                       num,\n                                                      DirectSignalHandlerFunc   func,\n                                                      void                     *ctx,\n                                                      DirectSignalHandler     **ret_handler );\n\nDirectResult DIRECT_API direct_signal_handler_remove( DirectSignalHandler      *handler );\n\n#endif\n"
  },
  {
    "path": "lib/direct/os/system.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__SYSTEM_H__\n#define __DIRECT__OS__SYSTEM_H__\n\n#include <direct/os/types.h>\n\n/**********************************************************************************************************************/\n\nvoid          DIRECT_API  direct_sched_yield( void );\n\nlong          DIRECT_API  direct_pagesize   ( void );\n\nunsigned long DIRECT_API  direct_page_align ( unsigned long          value );\n\npid_t         DIRECT_API  direct_getpid     ( void );\n\npid_t         DIRECT_API  direct_gettid     ( void );\n\nvoid          DIRECT_API  direct_trap       ( const char            *domain,\n                                              int                    sig );\n\nDirectResult  DIRECT_API  direct_kill       ( pid_t                  pid,\n                                              int                    sig );\n\nvoid          DIRECT_API  direct_sync       ( void );\n\nuid_t         DIRECT_API  direct_geteuid    ( void );\n\nchar          DIRECT_API *direct_getenv     ( const char            *name );\n\nDirectResult  DIRECT_API  direct_futex      ( int                   *uaddr,\n                                              int                    op,\n                                              int                    val,\n                                              const struct timespec *timeout,\n                                              int                   *uaddr2,\n                                              int                    val3 );\n\nbool          DIRECT_API  direct_madvise    ( void );\n\n/**********************************************************************************************************************/\n\n#define FUTEX_WAIT 0\n#define FUTEX_WAKE 1\n\nextern unsigned int DIRECT_API __Direct_Futex_Wait_Count;\nextern unsigned int DIRECT_API __Direct_Futex_Wake_Count;\n\n#endif\n"
  },
  {
    "path": "lib/direct/os/thread.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__THREAD_H__\n#define __DIRECT__OS__THREAD_H__\n\n#include <direct/os/types.h>\n#include <direct/os/waitqueue.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     DTT_DEFAULT   =   0,\n     DTT_CLEANUP   =  -5,\n     DTT_INPUT     = -10,\n     DTT_OUTPUT    = -12,\n     DTT_MESSAGING = -15,\n     DTT_CRITICAL  = -20\n} DirectThreadType;\n\ntypedef void *(*DirectThreadMainFunc)( DirectThread *thread, void *arg );\n\nstruct __D_DirectThread {\n     int                   magic;\n\n     char                 *name;\n\n     DirectThreadType      type;         /* The thread's type. */\n     DirectThreadMainFunc  main;         /* The thread's main routine (or entry point). */\n     void                 *arg;          /* Custom argument passed to the main routine. */\n\n     DirectThreadHandle    handle;       /* The thread's handle. */\n     pid_t                 tid;          /* The thread's ID. */\n\n     bool                  canceled;     /* Set when direct_thread_cancel() is called. */\n     bool                  joining;      /* Set when direct_thread_join() is called. */\n     bool                  joined;       /* Set when direct_thread_join() has finished. */\n     bool                  detached;     /* Set when direct_thread_detach() is called. */\n     bool                  terminated;   /* Set when direct_thread_terminate() is called. */\n\n     bool                  init;         /* Set to true before the main routine is called. */\n\n     DirectMutex           lock;\n     DirectWaitQueue       cond;\n\n     unsigned int          counter;\n\n     int                   policy;\n     int                   priority;\n     size_t                stack_size;\n\n     void                 *trace_buffer;\n};\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     DIRECT_THREAD_CANCEL_ENABLE  = 0x00000000,\n     DIRECT_THREAD_CANCEL_DISABLE = 0x00000001\n} DirectThreadCancelState;\n\ntypedef void (*DirectOnceInitHandler)( void );\n\ntypedef void (*DirectThreadPrepareHandler)( void );\ntypedef void (*DirectThreadParentHandler) ( void );\ntypedef void (*DirectThreadChildHandler)  ( void );\n\ntypedef void (*DirectTLSDestructor)( void *arg );\n\n/**********************************************************************************************************************/\n\n/*\n * Thread initialization/deinitialization.\n */\n\nDirectResult DIRECT_API  direct_once                     ( DirectOnce                 *once,\n                                                           DirectOnceInitHandler       handler );\n\nDirectResult DIRECT_API  direct_thread_init              ( DirectThread               *thread );\n\nvoid         DIRECT_API  direct_thread_deinit            ( DirectThread               *thread );\n\n/*\n * Sets the cancelability state of the calling thread.\n */\nvoid         DIRECT_API  direct_thread_setcancelstate    ( DirectThreadCancelState     state );\n\n/*\n * Returns the thread of the caller.\n */\nDirectThread DIRECT_API *direct_thread_self              ( void );\n\n/*\n * Returns the name of the calling thread.\n */\nconst char   DIRECT_API *direct_thread_self_name         ( void );\n\n/*\n * Changes the name of the calling thread.\n */\nvoid         DIRECT_API  direct_thread_set_name          ( const char                 *name );\n\n/*\n * Cancel a running thread.\n */\nvoid         DIRECT_API  direct_thread_cancel            ( DirectThread               *thread );\n\n/*\n * Detach a thread.\n */\nvoid         DIRECT_API  direct_thread_detach            ( DirectThread               *thread );\n\n/*\n * Check if the calling thread is canceled.\n */\nvoid         DIRECT_API  direct_thread_testcancel        ( DirectThread               *thread );\n\n/*\n * Wait until a running thread is terminated.\n */\nvoid         DIRECT_API  direct_thread_join              ( DirectThread               *thread );\n\n/*\n * Send a signal to a thread.\n */\nvoid         DIRECT_API  direct_thread_kill              ( DirectThread               *thread,\n                                                           int                         signal );\n\n/*\n * Sleep a thread.\n */\nvoid         DIRECT_API  direct_thread_sleep             ( long long                   micros );\n\n/*\n * Register fork handlers.\n */\nvoid         DIRECT_API  direct_thread_atfork            ( DirectThreadPrepareHandler  prepare,\n                                                           DirectThreadParentHandler   parent,\n                                                           DirectThreadChildHandler    child );\n\n/*\n * Utilities for stringification.\n */\n\nconst char   DIRECT_API *direct_thread_type_name         ( DirectThreadType            type );\n\nconst char   DIRECT_API *direct_thread_policy_name       ( int                         policy );\n\n/*\n * Thread-specific data.\n */\n\nDirectResult DIRECT_API  direct_tls_register             ( DirectTLS                  *tls,\n                                                           DirectTLSDestructor         destructor );\n\nDirectResult DIRECT_API  direct_tls_unregister           ( DirectTLS                  *tls );\n\nvoid         DIRECT_API *direct_tls_get                  ( DirectTLS                  *tls );\n\nDirectResult DIRECT_API  direct_tls_set                  ( DirectTLS                  *tls,\n                                                           void                       *value);\n\n/*\n * Call all init handlers.\n */\nvoid         DIRECT_API _direct_thread_call_init_handlers( DirectThread               *thread );\n\n#endif\n"
  },
  {
    "path": "lib/direct/os/types.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__TYPES_H__\n#define __DIRECT__OS__TYPES_H__\n\n#include <direct/build.h>\n\n#endif\n\n#if defined(DIRECT_BUILD_OS_LINUX)\n\n#include <direct/os/linux/types.h>\n\n#ifdef __DIRECT__OS__FILESYSTEM_H__\n#include <direct/os/linux/filesystem.h>\n#endif\n\n#ifdef __DIRECT__OS__MUTEX_H__\n#include <direct/os/linux/mutex.h>\n#endif\n\n#ifdef __DIRECT__OS__THREAD_H__\n#include <direct/os/linux/thread.h>\n#endif\n\n#ifdef __DIRECT__OS__WAITQUEUE_H__\n#include <direct/os/linux/waitqueue.h>\n#endif\n\n#elif defined(DIRECT_BUILD_OS_NUTTX)\n\n#include <direct/os/nuttx/types.h>\n\n#ifdef __DIRECT__OS__FILESYSTEM_H__\n#include <direct/os/nuttx/filesystem.h>\n#endif\n\n#ifdef __DIRECT__OS__MUTEX_H__\n#include <direct/os/nuttx/mutex.h>\n#endif\n\n#ifdef __DIRECT__OS__THREAD_H__\n#include <direct/os/nuttx/thread.h>\n#endif\n\n#ifdef __DIRECT__OS__WAITQUEUE_H__\n#include <direct/os/nuttx/waitqueue.h>\n#endif\n\n#else\n#error Unsupported OS!\n#endif\n\n#ifndef __DIRECT__TYPES_H__\n#include <direct/types.h>\n#endif\n"
  },
  {
    "path": "lib/direct/os/waitqueue.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__OS__WAITQUEUE_H__\n#define __DIRECT__OS__WAITQUEUE_H__\n\n#include <direct/os/types.h>\n\n/**********************************************************************************************************************/\n\nDirectResult DIRECT_API direct_waitqueue_init        ( DirectWaitQueue *queue );\n\nDirectResult DIRECT_API direct_waitqueue_wait        ( DirectWaitQueue *queue,\n                                                       DirectMutex     *mutex );\n\nDirectResult DIRECT_API direct_waitqueue_wait_timeout( DirectWaitQueue *queue,\n                                                       DirectMutex     *mutex,\n                                                       unsigned long    micros );\n\nDirectResult DIRECT_API direct_waitqueue_signal      ( DirectWaitQueue *queue );\n\nDirectResult DIRECT_API direct_waitqueue_broadcast   ( DirectWaitQueue *queue );\n\nDirectResult DIRECT_API direct_waitqueue_deinit      ( DirectWaitQueue *queue );\n\n#endif\n"
  },
  {
    "path": "lib/direct/result.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/debug.h>\n#include <direct/hash.h>\n#include <direct/mutex.h>\n#include <direct/result.h>\n\nD_DEBUG_DOMAIN( Direct_Result, \"Direct/Result\", \"Direct Result types\" );\n\n/**********************************************************************************************************************/\n\nstatic DirectHash  result_types = DIRECT_HASH_INIT( 7, false );\nstatic DirectMutex result_mutex;\n\n/**********************************************************************************************************************/\n\nvoid\n__D_result_init()\n{\n     direct_mutex_init( &result_mutex );\n}\n\nvoid\n__D_result_deinit()\n{\n     direct_mutex_deinit( &result_mutex );\n}\n\n/**********************************************************************************************************************/\n\nDirectResult\nDirectResultTypeRegister( DirectResultType *type )\n{\n     DirectResult ret;\n\n     D_DEBUG_AT( Direct_Result, \"%s( %p )\\n\", __FUNCTION__, type );\n\n     D_ASSERT( type != NULL );\n\n     D_DEBUG_AT( Direct_Result, \"  -> refs    %d\\n\",     type->refs );\n     D_DEBUG_AT( Direct_Result, \"  -> base    0x%08x\\n\", type->base );\n     D_DEBUG_AT( Direct_Result, \"  -> strings %p\\n\",     type->result_strings );\n     D_DEBUG_AT( Direct_Result, \"  -> count   %u\\n\",     type->result_count );\n\n     D_ASSERT( type->result_count > 0 );\n     D_ASSERT( type->result_count <= D_RESULT_TYPE_SPACE );\n\n     D_DEBUG_AT( Direct_Result, \"  => %s\\n\", type->result_strings[0] );\n\n     ret = direct_mutex_lock( &result_mutex );\n     if (ret)\n          return ret;\n\n     if (direct_hash_lookup( &result_types, type->base )) {\n          D_ASSERT( direct_hash_lookup( &result_types, type->base ) == type );\n\n          D_MAGIC_ASSERT( type, DirectResultType );\n\n          D_ASSERT( type->refs > 0 );\n\n          type->refs++;\n     }\n     else {\n          D_ASSERT( type->refs == 0 );\n\n          D_MAGIC_SET( type, DirectResultType );\n\n          ret = direct_hash_insert( &result_types, type->base, type );\n          if (ret)\n               D_MAGIC_CLEAR( type );\n          else\n               type->refs = 1;\n     }\n\n     direct_mutex_unlock( &result_mutex );\n\n     return ret;\n}\n\nDirectResult\nDirectResultTypeUnregister( DirectResultType *type )\n{\n     DirectResult ret;\n\n     D_DEBUG_AT( Direct_Result, \"%s( %p )\\n\", __FUNCTION__, type );\n\n     D_MAGIC_ASSERT( type, DirectResultType );\n\n     D_DEBUG_AT( Direct_Result, \"  -> refs    %d\\n\",     type->refs );\n     D_DEBUG_AT( Direct_Result, \"  -> base    0x%08x\\n\", type->base );\n     D_DEBUG_AT( Direct_Result, \"  -> strings %p\\n\",     type->result_strings );\n     D_DEBUG_AT( Direct_Result, \"  -> count   %u\\n\",     type->result_count );\n\n     D_ASSERT( type->result_count > 0 );\n     D_ASSERT( type->result_count <= D_RESULT_TYPE_SPACE );\n\n     D_DEBUG_AT( Direct_Result, \"  => %s\\n\", type->result_strings[0] );\n\n     ret = direct_mutex_lock( &result_mutex );\n     if (ret)\n          return ret;\n\n     D_ASSERT( type->refs > 0 );\n\n     D_ASSERT( direct_hash_lookup( &result_types, type->base ) == type );\n\n     if (!--type->refs) {\n          D_MAGIC_CLEAR( type );\n\n          ret = direct_hash_remove( &result_types, type->base );\n     }\n\n     direct_mutex_unlock( &result_mutex );\n\n     return ret;\n}\n\nconst char *\nDirectResultString( DirectResult result )\n{\n     DirectResult      ret;\n     DirectResultType *type;\n\n     if (result) {\n          ret = direct_mutex_lock( &result_mutex );\n          if (ret)\n               return NULL;\n\n          type = direct_hash_lookup( &result_types, D_RESULT_TYPE( result ) );\n\n          direct_mutex_unlock( &result_mutex );\n\n          if (type) {\n               unsigned int index = D_RESULT_INDEX( result );\n\n               D_MAGIC_ASSERT( type, DirectResultType );\n\n               D_ASSERT( type->refs > 0 );\n\n               if (index < type->result_count)\n                    return type->result_strings[index];\n\n               return type->result_strings[0];\n          }\n\n          return \"UNKNOWN RESULT TYPE\";\n     }\n\n     return \"OK\";\n}\n"
  },
  {
    "path": "lib/direct/result.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__RESULT_H__\n#define __DIRECT__RESULT_H__\n\n#include <direct/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int            magic;\n     int            refs;\n\n     unsigned int   base;\n\n     const char   **result_strings;\n     unsigned int   result_count;\n} DirectResultType;\n\n/**********************************************************************************************************************/\n\nDirectResult DIRECT_API  DirectResultTypeRegister  ( DirectResultType *type );\n\nDirectResult DIRECT_API  DirectResultTypeUnregister( DirectResultType *type );\n\nconst char   DIRECT_API *DirectResultString        ( DirectResult      result );\n\n/**********************************************************************************************************************/\n\nvoid __D_result_init  ( void );\nvoid __D_result_deinit( void );\n\n#endif\n"
  },
  {
    "path": "lib/direct/serial.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__SERIAL_H__\n#define __DIRECT__SERIAL_H__\n\n#include <direct/debug.h>\n\nD_DEBUG_DOMAIN( Direct_Serial, \"Direct/Serial\", \"Direct Serial\" );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int           magic;\n\n     u32           overflow;\n\n     unsigned long value;\n\n     int           waiting;\n     int           wakeup;\n} DirectSerial;\n\n/**********************************************************************************************************************/\n\nstatic __inline__ void\ndirect_serial_init( DirectSerial *serial )\n{\n     D_DEBUG_AT( Direct_Serial, \"%s( %p )\\n\", __FUNCTION__, serial );\n\n     D_ASSERT( serial != NULL );\n\n     serial->value    = 0;\n     serial->overflow = 0;\n     serial->waiting  = 0;\n\n     D_MAGIC_SET( serial, DirectSerial );\n}\n\nstatic __inline__ void\ndirect_serial_deinit( DirectSerial *serial )\n{\n     D_MAGIC_ASSERT( serial, DirectSerial );\n\n     D_DEBUG_AT( Direct_Serial, \"%s( %p ) <- %lu\\n\", __FUNCTION__, serial, serial->value );\n\n     D_ASSUME( serial->waiting == 0 );\n\n     D_MAGIC_CLEAR( serial );\n}\n\nstatic __inline__ void\ndirect_serial_increase( DirectSerial *serial )\n{\n     D_MAGIC_ASSERT( serial, DirectSerial );\n\n     D_DEBUG_AT( Direct_Serial, \"%s( %p ) <- %lu ++\\n\", __FUNCTION__, serial, serial->value );\n\n     if (!++serial->value)\n          serial->overflow++;\n\n     D_DEBUG_AT( Direct_Serial, \"  -> %lu\\n\", serial->value );\n}\n\nstatic __inline__ void\ndirect_serial_copy( DirectSerial       *serial,\n                    const DirectSerial *source )\n{\n     D_MAGIC_ASSERT( serial, DirectSerial );\n     D_MAGIC_ASSERT( source, DirectSerial );\n\n     D_DEBUG_AT( Direct_Serial, \"%s( %p, %p ) <- %lu = %lu\\n\", __FUNCTION__,\n                 serial, source, source->value, serial->value );\n\n     serial->value    = source->value;\n     serial->overflow = source->overflow;\n}\n\nstatic __inline__ bool\ndirect_serial_check( const DirectSerial *serial,\n                     const DirectSerial *source )\n{\n     D_MAGIC_ASSERT( serial, DirectSerial );\n     D_MAGIC_ASSERT( source, DirectSerial );\n\n     D_DEBUG_AT( Direct_Serial, \"%s( %p, %p ) <- %lu == %lu\\n\", __FUNCTION__,\n                 serial, source, serial->value, source->value );\n\n     if (serial->overflow < source->overflow)\n          return false;\n     else if (serial->overflow == source->overflow && serial->value < source->value)\n          return false;\n\n     return true;\n}\n\nstatic __inline__ bool\ndirect_serial_update( DirectSerial       *serial,\n                      const DirectSerial *source )\n{\n     D_MAGIC_ASSERT( serial, DirectSerial );\n     D_MAGIC_ASSERT( source, DirectSerial );\n\n     D_DEBUG_AT( Direct_Serial, \"%s( %p, %p ) <- %lu <-= %lu\\n\", __FUNCTION__,\n                 serial, source, serial->value, source->value );\n\n     if (serial->overflow < source->overflow) {\n          serial->overflow = source->overflow;\n          serial->value    = source->value;\n\n          return true;\n     }\n     else if (serial->overflow == source->overflow && serial->value < source->value) {\n          serial->value = source->value;\n\n          return true;\n     }\n\n     return false;\n}\n\n#endif\n"
  },
  {
    "path": "lib/direct/signals.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__SIGNALS_H__\n#define __DIRECT__SIGNALS_H__\n\n#include <direct/os/signals.h>\n\n/**********************************************************************************************************************/\n\n#endif\n"
  },
  {
    "path": "lib/direct/stream.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/debug.h>\n#include <direct/filesystem.h>\n#include <direct/mem.h>\n#include <direct/memcpy.h>\n#include <direct/messages.h>\n#include <direct/stream.h>\n#include <direct/system.h>\n#include <direct/util.h>\n\nD_DEBUG_DOMAIN( Direct_Stream, \"Direct/Stream\", \"Direct Stream wrapper\" );\n\n/**********************************************************************************************************************/\n\nstruct __D_DirectStream {\n     int                   magic;\n     int                   ref;\n\n     int                   fd;\n     DirectFile            file;\n\n     off_t                 offset;\n     ssize_t               length;\n\n     char                 *mime;\n\n#if DIRECT_BUILD_PIPED_STREAM\n     /* Cache for piped streams. */\n     void                 *cache;\n     unsigned int          cache_size;\n#endif /* DIRECT_BUILD_PIPED_STREAM */\n\n#if DIRECT_BUILD_NETWORK\n     /* Remote streams data. */\n     struct {\n          int              sd;\n\n          char            *host;\n          int              port;\n          struct addrinfo *addr;\n\n          char            *user;\n          char            *pass;\n          char            *auth;\n\n          char            *path;\n\n          int              redirects;\n\n          void            *data;\n     } remote;\n#endif /* DIRECT_BUILD_NETWORK */\n\n     DirectResult (*wait)( DirectStream *stream, unsigned int length, struct timeval *timeout );\n     DirectResult (*peek)( DirectStream *stream, unsigned int length, int offset, void *buf, unsigned int *read_out );\n     DirectResult (*read)( DirectStream *stream, unsigned int length, void *buf, unsigned int *read_out );\n     DirectResult (*seek)( DirectStream *stream, unsigned int offset );\n};\n\n/**********************************************************************************************************************/\n\nstatic void\ndirect_stream_close( DirectStream *stream )\n{\n#if DIRECT_BUILD_NETWORK\n     if (stream->remote.host) {\n          D_FREE( stream->remote.host );\n          stream->remote.host = NULL;\n     }\n\n     if (stream->remote.user) {\n          D_FREE( stream->remote.user );\n          stream->remote.user = NULL;\n     }\n\n     if (stream->remote.pass) {\n          D_FREE( stream->remote.pass );\n          stream->remote.pass = NULL;\n     }\n\n     if (stream->remote.auth) {\n          D_FREE( stream->remote.auth );\n          stream->remote.auth = NULL;\n     }\n\n     if (stream->remote.path) {\n          D_FREE( stream->remote.path );\n          stream->remote.path = NULL;\n     }\n\n     if (stream->remote.addr) {\n          freeaddrinfo( stream->remote.addr );\n          stream->remote.addr = NULL;\n     }\n\n     if (stream->remote.data) {\n          D_FREE( stream->remote.data );\n          stream->remote.data = NULL;\n     }\n\n     if (stream->remote.sd > 0) {\n          close( stream->remote.sd );\n          stream->remote.sd = -1;\n     }\n#endif /* DIRECT_BUILD_NETWORK */\n\n#if DIRECT_BUILD_PIPED_STREAM\n     if (stream->cache) {\n          D_FREE( stream->cache );\n          stream->cache = NULL;\n          stream->cache_size = 0;\n     }\n#endif /* DIRECT_BUILD_PIPED_STREAM */\n\n#if DIRECT_BUILD_NETWORK || DIRECT_BUILD_PIPED_STREAM\n     if (stream->fd >= 0) {\n          fcntl( stream->fd, F_SETFL, fcntl( stream->fd, F_GETFL ) & ~O_NONBLOCK );\n          close( stream->fd );\n          stream->fd = -1;\n     } else\n#endif /* DIRECT_BUILD_NETWORK || DIRECT_BUILD_PIPED_STREAM */\n     direct_file_close( &stream->file );\n\n     if (stream->mime) {\n          D_FREE( stream->mime );\n          stream->mime = NULL;\n     }\n}\n\n/**********************************************************************************************************************/\n\n#if DIRECT_BUILD_NETWORK\n\nstatic __inline__ char *\ntrim( char *s )\n{\n     char *e;\n\n#define space(c) ((c) == ' ' || (c) == '\\t' || (c) == '\\r' || (c) == '\\n' || (c) == '\"' || (c) == '\\'')\n\n     for (; space(*s); s++);\n\n     e = s + strlen( s ) - 1;\n     for (; e > s && space(*e); *e-- = '\\0');\n\n#undef space\n\n     return s;\n}\n\nstatic void\nparse_url( const char  *url,\n           char       **ret_host,\n           int         *ret_port,\n           char       **ret_user,\n           char       **ret_pass,\n           char       **ret_path )\n{\n     char *path;\n     char *tmp;\n     char *host;\n     char *user = NULL;\n     char *pass = NULL;\n     int   port = 0;\n\n     tmp = strchr( url, '/' );\n     if (tmp) {\n          host = alloca( tmp - url + 1 );\n          direct_memcpy( host, url, tmp - url );\n          host[tmp-url] = '\\0';\n          path = tmp;\n     }\n     else {\n          host = alloca( strlen( url ) + 1 );\n          direct_memcpy( host, url, strlen( url ) + 1 );\n          path = \"/\";\n     }\n\n     tmp = strrchr( host, '@' );\n     if (tmp) {\n          *tmp = '\\0';\n          pass = strchr( host, ':' );\n          if (pass) {\n               *pass = '\\0';\n               pass++;\n          }\n          user = host;\n          host = tmp + 1;\n     }\n\n     tmp = strchr( host, ':' );\n     if (tmp) {\n          port = strtol( tmp + 1, NULL, 10 );\n          *tmp = '\\0';\n     }\n\n     /* Host within brackets. */\n     if (*host == '[') {\n          host++;\n          tmp = strchr( host, ']' );\n          if (tmp)\n               *tmp = '\\0';\n     }\n\n     if (ret_host)\n          *ret_host = D_STRDUP( host );\n\n     if (ret_port && port)\n          *ret_port = port;\n\n     if (ret_user && user)\n          *ret_user = D_STRDUP( user );\n\n     if (ret_pass && pass)\n          *ret_pass = D_STRDUP( pass );\n\n     if (ret_path)\n          *ret_path = D_STRDUP( path );\n}\n\n/**********************************************************************************************************************/\n\n#define NET_TIMEOUT 15\n\nstatic int\nnet_response( DirectStream *stream,\n              char         *buf,\n              size_t        size )\n{\n     int            i;\n     fd_set         set;\n     struct timeval timeout;\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     FD_ZERO( &set );\n     FD_SET( stream->remote.sd, &set );\n\n     for (i = 0; i < size - 1; i++) {\n          timeout.tv_sec  = NET_TIMEOUT;\n          timeout.tv_usec = 0;\n\n          select( stream->remote.sd + 1, &set, NULL, NULL, &timeout );\n\n          if (recv( stream->remote.sd, buf + i, 1, 0 ) != 1)\n               break;\n\n          if (buf[i] == '\\n') {\n               if (i > 0 && buf[i-1] == '\\r')\n                    i--;\n               break;\n          }\n     }\n\n     buf[i] = '\\0';\n\n     D_DEBUG_AT( Direct_Stream, \"  -> got [%s]\\n\", buf );\n\n     return i;\n}\n\nstatic int\nnet_command( DirectStream *stream,\n             char         *buf,\n             size_t        size )\n{\n     fd_set         set;\n     struct timeval timeout;\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     FD_ZERO( &set );\n     FD_SET( stream->remote.sd, &set );\n\n     timeout.tv_sec  = NET_TIMEOUT;\n     timeout.tv_usec = 0;\n\n     switch (select( stream->remote.sd + 1, NULL, &set, NULL, &timeout )) {\n          case 0:\n               D_DEBUG_AT( Direct_Stream, \"  -> timeout\\n\" );\n          case -1:\n               return -1;\n     }\n\n     send( stream->remote.sd, buf, strlen( buf ), 0 );\n     send( stream->remote.sd, \"\\r\\n\", 2, 0 );\n\n     D_DEBUG_AT( Direct_Stream, \"  -> sent [%s]\\n\", buf );\n\n     while (net_response( stream, buf, size ) > 0) {\n          int  status;\n          int  version;\n          char space;\n\n          if (sscanf( buf, \"HTTP/1.%d %3d\", &version, &status ) == 2 ||\n              sscanf( buf, \"RTSP/1.%d %3d\", &version, &status ) == 2 ||\n              sscanf( buf, \"%3d%[ ]\", &status, &space )         == 2)\n               return status;\n     }\n\n     return 0;\n}\n\nstatic DirectResult\nnet_connect( struct addrinfo *addr,\n             int              sock,\n             int              proto,\n             int             *ret_fd )\n{\n     DirectResult     ret = DR_OK;\n     int              fd  = -1;\n     struct addrinfo *tmp;\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( addr != NULL );\n     D_ASSERT( ret_fd != NULL );\n\n     for (tmp = addr; tmp; tmp = tmp->ai_next) {\n          int err;\n\n          fd = socket( tmp->ai_family, sock, proto );\n          if (fd < 0) {\n               ret = errno2result( errno );\n               D_DEBUG_AT( Direct_Stream, \"  -> failed to create socket!\\n\" );\n               continue;\n          }\n\n          fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK );\n\n          D_DEBUG_AT( Direct_Stream, \"  -> connecting to %s...\\n\", tmp->ai_canonname );\n\n          if (proto == IPPROTO_UDP)\n               err = bind( fd, tmp->ai_addr, tmp->ai_addrlen );\n          else\n               err = connect( fd, tmp->ai_addr, tmp->ai_addrlen );\n\n          if (err == 0 || errno == EINPROGRESS) {\n               fd_set         set;\n               struct timeval timeout = { NET_TIMEOUT, 0 };\n\n               /* Join multicast group. */\n               if (tmp->ai_addr->sa_family == AF_INET) {\n                    struct sockaddr_in *saddr = (struct sockaddr_in*) tmp->ai_addr;\n\n                    if (IN_MULTICAST( ntohl(saddr->sin_addr.s_addr) )) {\n                         struct ip_mreq req;\n\n                         D_DEBUG_AT( Direct_Stream, \"  -> joining multicast group (%d.%d.%d.%d)...\\n\",\n                                     tmp->ai_addr->sa_data[2], tmp->ai_addr->sa_data[3],\n                                     tmp->ai_addr->sa_data[4], tmp->ai_addr->sa_data[5] );\n\n                         req.imr_multiaddr.s_addr = saddr->sin_addr.s_addr;\n                         req.imr_interface.s_addr = 0;\n\n                         err = setsockopt( fd, SOL_IP, IP_ADD_MEMBERSHIP, &req, sizeof(req) );\n                         if (err < 0) {\n                              ret = errno2result( errno );\n                              D_DEBUG_AT( Direct_Stream, \"  -> could not join multicast group (%d.%d.%d.%d)\\n\",\n                                          tmp->ai_addr->sa_data[2], tmp->ai_addr->sa_data[3],\n                                          tmp->ai_addr->sa_data[4], tmp->ai_addr->sa_data[5] );\n                              close( fd );\n                              continue;\n                         }\n\n                         setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, saddr, sizeof(*saddr) );\n                    }\n               }\n\n               FD_ZERO( &set );\n               FD_SET( fd, &set );\n\n               err = select( fd + 1, NULL, &set, NULL, &timeout );\n               if (err < 1) {\n                    D_DEBUG_AT( Direct_Stream, \"  -> ...connection failed\\n\" );\n\n                    close( fd );\n                    fd = -1;\n\n                    if (err == 0) {\n                         ret = DR_TIMEOUT;\n                         continue;\n                    }\n                    else {\n                         ret = errno2result( errno );\n                         break;\n                    }\n               }\n\n               D_DEBUG_AT( Direct_Stream, \"  -> ...connected\\n\" );\n\n               ret = DR_OK;\n               break;\n          }\n     }\n\n     *ret_fd = fd;\n\n     return ret;\n}\n\nstatic DirectResult\nnet_stream_wait( DirectStream   *stream,\n                 unsigned int    length,\n                 struct timeval *timeout )\n{\n     fd_set set;\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     if (stream->fd == -1)\n          return DR_EOF;\n\n     FD_ZERO( &set );\n     FD_SET( stream->fd, &set );\n\n     switch (select( stream->fd + 1, &set, NULL, NULL, timeout )) {\n          case 0:\n               if (!timeout)\n                    return DR_EOF;\n               return DR_TIMEOUT;\n          case -1:\n               return errno2result( errno );\n     }\n\n     return DR_OK;\n}\n\nstatic DirectResult\nnet_stream_peek( DirectStream *stream,\n                 unsigned int  length,\n                 int           offset,\n                 void         *buf,\n                 unsigned int *read_out )\n{\n     ssize_t  size;\n     char    *tmp;\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     if (offset < 0)\n          return DR_UNSUPPORTED;\n\n     tmp = alloca( length + offset );\n\n     size = recv( stream->fd, tmp, length + offset, MSG_PEEK );\n     switch (size) {\n          case 0:\n               return DR_EOF;\n          case -1:\n               if (errno == EAGAIN || errno == EWOULDBLOCK)\n                    return DR_BUFFEREMPTY;\n               return errno2result( errno );\n          default:\n               if (size < offset)\n                    return DR_BUFFEREMPTY;\n               size -= offset;\n               break;\n     }\n\n     direct_memcpy( buf, tmp + offset, size );\n\n     if (read_out)\n          *read_out = size;\n\n     return DR_OK;\n}\n\nstatic DirectResult\nnet_stream_read( DirectStream *stream,\n                 unsigned int  length,\n                 void         *buf,\n                 unsigned int *read_out )\n{\n     ssize_t size;\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     size = recv( stream->fd, buf, length, 0 );\n     switch (size) {\n          case 0:\n               return DR_EOF;\n          case -1:\n               if (errno == EAGAIN || errno == EWOULDBLOCK)\n                    return DR_BUFFEREMPTY;\n               return errno2result( errno );\n     }\n\n     stream->offset += size;\n\n     if (read_out)\n          *read_out = size;\n\n     return DR_OK;\n}\n\nstatic DirectResult\nnet_stream_open( DirectStream *stream,\n                 const char   *filename,\n                 int           proto )\n{\n     DirectResult    ret;\n     struct addrinfo hints;\n     char            port[16];\n     int             sock = (proto == IPPROTO_TCP) ? SOCK_STREAM : SOCK_DGRAM;\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     parse_url( filename,\n                &stream->remote.host,\n                &stream->remote.port,\n                &stream->remote.user,\n                &stream->remote.pass,\n                &stream->remote.path );\n\n     snprintf( port, sizeof(port), \"%d\", stream->remote.port );\n\n     memset( &hints, 0, sizeof(hints) );\n     hints.ai_flags    = AI_CANONNAME;\n     hints.ai_socktype = sock;\n     hints.ai_family   = PF_UNSPEC;\n\n     if (getaddrinfo( stream->remote.host, port, &hints, &stream->remote.addr )) {\n          D_ERROR( \"Direct/Stream: Failed to resolve host '%s'\\n\", stream->remote.host );\n          return DR_FAILURE;\n     }\n\n     ret = net_connect( stream->remote.addr, sock, proto, &stream->remote.sd );\n     if (ret)\n          return ret;\n\n     stream->fd     = stream->remote.sd;\n     stream->length = -1;\n     stream->wait   = net_stream_wait;\n     stream->peek   = net_stream_peek;\n     stream->read   = net_stream_read;\n\n     return DR_OK;\n}\n\n/**********************************************************************************************************************/\n\n#define FTP_PORT 21\n\nstatic DirectResult\nftp_open_pasv( DirectStream *stream,\n               char         *buf,\n               size_t        size )\n{\n     DirectResult ret;\n     int          i;\n     int          len;\n\n     snprintf( buf, size, \"PASV\" );\n     if (net_command( stream, buf, size ) != 227)\n          return DR_FAILURE;\n\n     for (i = 4; buf[i]; i++) {\n          unsigned int d[6];\n\n          if (sscanf( &buf[i], \"%u,%u,%u,%u,%u,%u\", &d[0], &d[1], &d[2], &d[3], &d[4], &d[5] ) == 6) {\n               struct addrinfo hints, *addr;\n\n               /* Address */\n               len = snprintf( buf, size, \"%u.%u.%u.%u\", d[0], d[1], d[2], d[3] );\n               /* Port */\n               snprintf( buf + len + 1, size - len - 1, \"%u\", ((d[4] & 0xff) << 8) | (d[5] & 0xff) );\n\n               memset( &hints, 0, sizeof(hints) );\n               hints.ai_flags    = AI_CANONNAME;\n               hints.ai_socktype = SOCK_STREAM;\n               hints.ai_family   = PF_UNSPEC;\n\n               if (getaddrinfo( buf, buf + len + 1, &hints, &addr )) {\n                    D_ERROR( \"Direct/Stream: Failed to resolve host '%s'\\n\", buf );\n                    return DR_FAILURE;\n               }\n\n               ret = net_connect( addr, SOCK_STREAM, IPPROTO_TCP, &stream->fd );\n\n               freeaddrinfo( addr );\n\n               return ret;\n          }\n     }\n\n     return DR_FAILURE;\n}\n\nstatic DirectResult\nftp_stream_seek( DirectStream *stream,\n                 unsigned int  offset )\n{\n     DirectResult ret;\n     char         buf[512];\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     if (stream->fd > 0) {\n          close( stream->fd );\n          stream->fd = -1;\n\n          /* Ignore response. */\n          while (net_response( stream, buf, sizeof(buf) ) > 0) {\n               int status;\n\n               if (sscanf( buf, \"%3d%[ ]\", &status, buf ) == 2)\n                    break;\n          }\n     }\n\n     ret = ftp_open_pasv( stream, buf, sizeof(buf) );\n     if (ret)\n          return ret;\n\n     snprintf( buf, sizeof(buf), \"REST %u\", offset );\n     if (net_command( stream, buf, sizeof(buf) ) != 350)\n          goto error;\n\n     snprintf( buf, sizeof(buf), \"RETR %s\", stream->remote.path );\n     switch (net_command( stream, buf, sizeof(buf) )) {\n          case 150:\n          case 125:\n               break;\n          default:\n               goto error;\n     }\n\n     stream->offset = offset;\n\n     return DR_OK;\n\nerror:\n     close( stream->fd );\n     stream->fd = -1;\n\n     return DR_FAILURE;\n}\n\nstatic DirectResult\nftp_stream_open( DirectStream *stream,\n                 const char   *filename )\n{\n     DirectResult ret;\n     int          status = 0;\n     char         buf[512];\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     stream->remote.port = FTP_PORT;\n\n     ret = net_stream_open( stream, filename, IPPROTO_TCP );\n     if (ret)\n          return ret;\n\n     while (net_response( stream, buf, sizeof(buf) ) > 0) {\n          if (sscanf( buf, \"%3d%[ ]\", &status, buf ) == 2)\n               break;\n     }\n\n     if (status != 220)\n          return DR_FAILURE;\n\n     /* Login. */\n     snprintf( buf, sizeof(buf), \"USER %s\", stream->remote.user ?: \"anonymous\" );\n     switch (net_command( stream, buf, sizeof(buf) )) {\n          case 230:\n          case 331:\n               break;\n          default:\n               return DR_FAILURE;\n     }\n\n     if (stream->remote.pass) {\n          snprintf( buf, sizeof(buf), \"PASS %s\", stream->remote.pass );\n          if (net_command( stream, buf, sizeof(buf) ) != 230)\n               return DR_FAILURE;\n     }\n\n     /* Enter binary mode. */\n     snprintf( buf, sizeof(buf), \"TYPE I\" );\n     if (net_command( stream, buf, sizeof(buf) ) != 200)\n          return DR_FAILURE;\n\n     /* Get file size. */\n     snprintf( buf, sizeof(buf), \"SIZE %s\", stream->remote.path );\n     if (net_command( stream, buf, sizeof(buf) ) == 213)\n          stream->length = strtol( buf + 4, NULL, 10 );\n\n     /* Enter passive mode by default. */\n     ret = ftp_open_pasv( stream, buf, sizeof(buf) );\n     if (ret)\n          return ret;\n\n     /* Retrieve file. */\n     snprintf( buf, sizeof(buf), \"RETR %s\", stream->remote.path );\n     switch (net_command( stream, buf, sizeof(buf) )) {\n          case 125:\n          case 150:\n               break;\n          default:\n               return DR_FAILURE;\n     }\n\n     stream->seek = ftp_stream_seek;\n\n     return DR_OK;\n}\n\n/**********************************************************************************************************************/\n\n#define RTSP_PORT 554\n\ntypedef struct {\n     s8          pt;\n     const char *mime;\n} RTPPayload;\n\nstatic const RTPPayload payloads[] = {\n     { 32, \"video/mpeg\",  },\n     { 33, \"video/mpegts\" },\n     { 34, \"video/h263\",  },\n};\n\n#define NUM_PAYLOADS D_ARRAY_SIZE(payloads)\n\ntypedef struct {\n     s8   pt;\n     char control[128];\n} SDPMedia;\n\nstatic DirectResult\nsdp_parse( DirectStream *stream,\n           int           length,\n           SDPMedia     *media )\n{\n     fd_set          set;\n     struct timeval  timeout;\n     char           *buf, *tmp;\n\n     buf = D_CALLOC( 1, length + 1 );\n     if (!buf)\n          return D_OOM();\n\n     FD_ZERO( &set );\n     FD_SET( stream->remote.sd, &set );\n\n     timeout.tv_sec  = NET_TIMEOUT;\n     timeout.tv_usec = 0;\n\n     select( stream->remote.sd + 1, &set, NULL, NULL, &timeout );\n\n     if (recv( stream->remote.sd, buf, length, MSG_WAITALL ) < 1)\n          return DR_EOF;\n\n     for (tmp = buf; tmp && *tmp;) {\n          char *end;\n\n          end = strchr( tmp, '\\n' );\n          if (end) {\n               if (end > tmp && *(end - 1) == '\\r')\n                    *(end - 1) = '\\0';\n               *end = '\\0';\n          }\n\n          switch (*tmp) {\n               case 'm':\n                    if (*(tmp + 1) == '=') {\n                         int i, pt;\n\n                         tmp += 2;\n\n                         if (sscanf( tmp, \"video %d RTP/AVP %d\", &i, &pt ) == 2) {\n                              for (i = 0; i < NUM_PAYLOADS; i++) {\n                                   if (pt == payloads[i].pt) {\n                                        media->pt = pt;\n                                        if (stream->mime)\n                                             D_FREE( stream->mime );\n                                        stream->mime = D_STRDUP( payloads[i].mime );\n                                        break;\n                                   }\n                              }\n                         }\n                    }\n                    break;\n               case 'a':\n                    if (*(tmp + 1) == '=' && media->pt) {\n                         tmp += 2;\n\n                         if (!strncmp( tmp, \"control:\", 8 ))\n                              snprintf( media->control, sizeof(media->control), \"%s\", trim( tmp + 8 ) );\n                    }\n                    break;\n               default:\n                    break;\n          }\n\n          tmp = end;\n          if (tmp)\n               tmp++;\n     }\n\n     D_FREE( buf );\n\n     return media->pt ? DR_OK : DR_FAILURE;\n}\n\nstatic DirectResult\nrtp_read_packet( DirectStream *stream )\n{\n     int           len;\n     unsigned char buf[12];\n     s8            pt   = *(s8*) stream->remote.data;\n     int           skip = 0;\n\n     do {\n          if (recv( stream->fd, buf, 1, MSG_WAITALL ) < 1)\n               return DR_EOF;\n     } while (buf[0] != '$');\n\n     if (recv( stream->fd, buf, 3, MSG_WAITALL ) < 3)\n          return DR_EOF;\n\n     len = (buf[1] << 8) | buf[2];\n     if (len < 12)\n          return DR_FAILURE;\n\n     if (recv( stream->fd, buf, 12, MSG_WAITALL ) < 12)\n          return DR_EOF;\n\n     len -= 12;\n\n     if ((buf[0] & 0xc0) != (2 << 6)) {\n          D_ERROR( \"Direct/Stream: Bad RTP version %d!\\n\", buf[0] );\n          return DR_FAILURE;\n     }\n\n     if ((buf[1] & 0x7f) == 72) {\n          while (len) {\n               ssize_t size;\n\n               size = recv( stream->fd, buf, MIN( len, 12 ), MSG_WAITALL );\n               if (size < 1)\n                    return DR_EOF;\n\n               len -= size;\n          }\n\n          return DR_OK;\n     }\n     else if ((buf[1] & 0x7f) != pt) {\n          D_ERROR( \"Direct/Stream: Bad Payload type %d!\\n\", buf[1] & 0x7f );\n          return DR_FAILURE;\n     }\n\n     switch (pt) {\n          case 32: /* MPEG Video */\n               if (recv( stream->fd, buf, 1, MSG_WAITALL ) < 1)\n                    return DR_EOF;\n               len--;\n               skip = 3;\n               if (buf[0] & (1 << 2))\n                    skip += 4;\n               break;\n          case 34: /* H263 */\n               if ( recv( stream->fd, buf, 1, MSG_WAITALL ) < 1)\n                    return DR_EOF;\n               len--;\n               skip = 3;\n               if (buf[0] & (1 << 7))\n                    skip += 4;\n               if (buf[0] & (1 << 6))\n                    skip += 4;\n               break;\n          case 33: /* MPEG Transport stream */\n          default:\n               break;\n     }\n\n     if (skip) {\n          if (recv( stream->fd, buf, skip, MSG_WAITALL ) < 1)\n               return DR_EOF;\n\n          len -= skip;\n     }\n\n     if (len > 0) {\n          stream->cache = D_REALLOC( stream->cache, stream->cache_size + len );\n          if (!stream->cache)\n               return D_OOM();\n\n          if (recv( stream->fd, stream->cache + stream->cache_size, len, MSG_WAITALL ) < 1)\n               return DR_EOF;\n\n          stream->cache_size += len;\n     }\n\n     return DR_OK;\n}\n\nstatic DirectResult\nrtsp_peek( DirectStream *stream,\n           unsigned int  length,\n           int           offset,\n           void         *buf,\n           unsigned int *read_out )\n{\n     DirectResult ret;\n     unsigned int len;\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     if (offset < 0)\n          return DR_UNSUPPORTED;\n\n     len = length + offset;\n     while (len > stream->cache_size) {\n          ret = rtp_read_packet( stream );\n          if (ret) {\n               if (stream->cache_size < offset)\n                    return ret;\n               break;\n          }\n     }\n\n     len = MIN( stream->cache_size - offset, length );\n\n     direct_memcpy( buf, stream->cache + offset, len );\n\n     if (read_out)\n          *read_out = len;\n\n     return DR_OK;\n}\n\nstatic DirectResult\nrtsp_read( DirectStream *stream,\n           unsigned int  length,\n           void         *buf,\n           unsigned int *read_out )\n{\n     DirectResult ret;\n     unsigned int size = 0;\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     while (size < length || stream->cache_size < length) {\n          if (stream->cache_size && length - size) {\n               unsigned int len = MIN( stream->cache_size, length - size );\n\n               direct_memcpy( buf + size, stream->cache, len );\n\n               size               += len;\n               stream->cache_size -= len;\n\n               direct_memcpy( stream->cache, stream->cache + len, stream->cache_size );\n          }\n\n          if (size < length || stream->cache_size < length) {\n               ret = rtp_read_packet( stream );\n               if (ret) {\n                    if (!size)\n                         return ret;\n                    break;\n               }\n          }\n     }\n\n     stream->offset += size;\n\n     if (read_out)\n          *read_out = size;\n\n     return DR_OK;\n}\n\nstatic DirectResult\nrtsp_stream_open( DirectStream *stream,\n                  const char   *filename )\n{\n     DirectResult ret;\n     SDPMedia     media;\n     int          len;\n     char         buf[1280];\n     int          cseq        = 0;\n     char         session[32] = { 0 };\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     stream->remote.port = RTSP_PORT;\n\n     ret = net_stream_open( stream, filename, IPPROTO_TCP );\n     if (ret)\n          return ret;\n\n     snprintf( buf, sizeof(buf),\n               \"OPTIONS rtsp://%s:%d RTSP/1.0\\r\\n\"\n               \"CSeq: %d\\r\\n\"\n               \"User-Agent: DirectFB\\r\\n\",\n               stream->remote.host,\n               stream->remote.port,\n               ++cseq );\n\n     if (net_command( stream, buf, sizeof(buf) ) != 200)\n          return DR_FAILURE;\n\n     /* Discard remaining response. */\n     while (net_response( stream, buf, sizeof(buf) ) > 0);\n\n     snprintf( buf, sizeof(buf),\n               \"DESCRIBE rtsp://%s:%d%s RTSP/1.0\\r\\n\"\n               \"CSeq: %d\\r\\n\"\n               \"User-Agent: DirectFB\\r\\n\"\n               \"Accept: application/sdp\\r\\n\",\n               stream->remote.host,\n               stream->remote.port,\n               stream->remote.path,\n               ++cseq );\n\n     if (net_command( stream, buf, sizeof(buf) ) != 200)\n          return DR_FAILURE;\n\n     len = 0;\n\n     while (net_response( stream, buf, sizeof(buf) ) > 0) {\n          if (!strncasecmp( buf, \"Content-Length:\", 15 )) {\n               char *tmp = trim( buf + 15 );\n               if (sscanf( tmp, \"%d\", &len ) != 1)\n                    sscanf( tmp, \"bytes=%d\", &len );\n          }\n     }\n\n     if (!len) {\n          D_ERROR( \"Direct/Stream: Couldn't get SDP length!\\n\" );\n          return DR_FAILURE;\n     }\n\n     memset( &media, 0, sizeof(SDPMedia) );\n\n     ret = sdp_parse( stream, len, &media );\n     if (ret)\n          return ret;\n\n     snprintf( buf, sizeof(buf),\n               \"SETUP rtsp://%s:%d%s/%s RTSP/1.0\\r\\n\"\n               \"CSeq: %d\\r\\n\"\n               \"User-Agent: DirectFB\\r\\n\"\n               \"Transport: RTP/AVP/TCP;unicast\\r\\n\",\n               stream->remote.host,\n               stream->remote.port,\n               stream->remote.path,\n               media.control, ++cseq );\n\n     if (net_command( stream, buf, sizeof(buf) ) != 200)\n          return DR_FAILURE;\n\n     while (net_response( stream, buf, sizeof(buf) ) > 0) {\n          if (!*session && !strncmp( buf, \"Session:\", 8 ))\n               snprintf( session, sizeof(session), \"%s\", trim( buf + 8 ) );\n     }\n\n     len = snprintf( buf, sizeof(buf),\n                     \"PLAY rtsp://%s:%d%s RTSP/1.0\\r\\n\"\n                     \"CSeq: %d\\r\\n\"\n                     \"User-Agent: DirectFB\\r\\n\"\n                     \"Range: npt=0-\\r\\n\",\n                     stream->remote.host,\n                     stream->remote.port,\n                     stream->remote.path,\n                     ++cseq );\n     if (*session) {\n          snprintf( buf + len, sizeof(buf) - len,\n                    \"Session: %s\\r\\n\", session );\n     }\n\n     if (net_command( stream, buf, sizeof(buf) ) != 200)\n          return DR_FAILURE;\n\n     /* Discard remaining response. */\n     while (net_response( stream, buf, sizeof(buf) ) > 0);\n\n     /* Payload type data. */\n     stream->remote.data = D_CALLOC( 1, sizeof(s8) );\n     if (!stream->remote.data)\n          return D_OOM();\n\n     *(s8*) stream->remote.data = media.pt;\n\n     stream->peek = rtsp_peek;\n     stream->read = rtsp_read;\n\n     return DR_OK;\n}\n\n/**********************************************************************************************************************/\n\n#define HTTP_PORT          80\n#define HTTP_MAX_REDIRECTS 15\n\nstatic DirectResult\nhttp_stream_seek( DirectStream *stream,\n                  unsigned int  offset )\n{\n     DirectResult ret;\n     int          status;\n     int          len;\n     char         buf[1280];\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     close( stream->remote.sd );\n     stream->remote.sd = -1;\n\n     ret = net_connect( stream->remote.addr, SOCK_STREAM, IPPROTO_TCP, &stream->remote.sd );\n     if (ret)\n          return ret;\n\n     stream->fd = stream->remote.sd;\n\n     len = snprintf( buf, sizeof(buf),\n                     \"GET %s HTTP/1.0\\r\\n\"\n                     \"Host: %s:%d\\r\\n\",\n                     stream->remote.path, stream->remote.host, stream->remote.port );\n\n     if (stream->remote.auth) {\n          len += snprintf( buf + len, sizeof(buf) - len,\n                           \"Authorization: Basic %s\\r\\n\",\n                           stream->remote.auth );\n     }\n\n     snprintf( buf + len, sizeof(buf) - len,\n               \"User-Agent: DirectFB\\r\\n\"\n               \"Accept: */*\\r\\n\"\n               \"Range: bytes=%u-\\r\\n\"\n               \"Connection: Close\\r\\n\",\n               offset );\n\n     status = net_command( stream, buf, sizeof(buf) );\n     switch (status) {\n          case 200 ... 299:\n               stream->offset = offset;\n               break;\n          default:\n               if (status)\n                    D_ERROR( \"Direct/Stream: Server returned status %d\\n\", status );\n               return DR_FAILURE;\n     }\n\n     /* Discard remaining response. */\n     while (net_response( stream, buf, sizeof(buf) ) > 0);\n\n     return DR_OK;\n}\n\nstatic DirectResult\nhttp_stream_open( DirectStream *stream,\n                  const char   *filename )\n{\n     DirectResult ret;\n     int          status;\n     int          len;\n     char         buf[1280];\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     stream->remote.port = HTTP_PORT;\n\n     ret = net_stream_open( stream, filename, IPPROTO_TCP );\n     if (ret)\n          return ret;\n\n     if (stream->remote.user) {\n          char *tmp;\n\n          if (stream->remote.pass) {\n               tmp = alloca( strlen( stream->remote.user ) + strlen( stream->remote.pass ) + 2 );\n               len = sprintf( tmp, \"%s:%s\", stream->remote.user, stream->remote.pass );\n          }\n          else {\n               tmp = alloca( strlen( stream->remote.user ) + 2 );\n               len = sprintf( tmp, \"%s:\", stream->remote.user );\n          }\n\n          stream->remote.auth = direct_base64_encode( tmp, len );\n     }\n\n     len = snprintf( buf, sizeof(buf),\n                     \"GET %s HTTP/1.0\\r\\n\"\n                     \"Host: %s:%d\\r\\n\",\n                     stream->remote.path, stream->remote.host, stream->remote.port );\n\n     if (stream->remote.auth) {\n          len += snprintf( buf + len, sizeof(buf) - len,\n                           \"Authorization: Basic %s\\r\\n\",\n                           stream->remote.auth );\n     }\n\n     snprintf( buf + len, sizeof(buf) - len,\n               \"User-Agent: DirectFB\\r\\n\"\n               \"Accept: */*\\r\\n\"\n               \"Connection: Close\\r\\n\" );\n\n     status = net_command( stream, buf, sizeof(buf) );\n\n     while (net_response( stream, buf, sizeof(buf) ) > 0) {\n          if (!strncasecmp( buf, \"Accept-Ranges:\", 14 )) {\n               if (strcmp( trim( buf + 14 ), \"none\" ))\n                    stream->seek = http_stream_seek;\n          }\n          else if (!strncasecmp( buf, \"Content-Type:\", 13 )) {\n               char *mime = trim( buf + 13 );\n               char *tmp  = strchr( mime, ';' );\n               if (tmp)\n                    *tmp = '\\0';\n               if (stream->mime)\n                    D_FREE( stream->mime );\n               stream->mime = D_STRDUP( mime );\n          }\n          else if (!strncasecmp( buf, \"Content-Length:\", 15 )) {\n               char *tmp = trim( buf + 15 );\n               if (sscanf( tmp, \"\"_ZD\"\", &stream->length ) < 1)\n                    sscanf( tmp, \"bytes=\"_ZD\"\", &stream->length );\n          }\n          else if (!strncasecmp( buf, \"Location:\", 9 )) {\n               direct_stream_close( stream );\n               stream->seek = NULL;\n\n               if (++stream->remote.redirects > HTTP_MAX_REDIRECTS) {\n                    D_ERROR( \"Direct/Stream: Reached maximum number of redirects (%d)\\n\", HTTP_MAX_REDIRECTS );\n                    return DR_LIMITEXCEEDED;\n               }\n\n               filename = trim( buf + 9 );\n               if (!strncmp( filename, \"ftp://\", 6 ))\n                    return ftp_stream_open( stream, filename + 6 );\n               if (!strncmp( filename, \"http://\", 7 ))\n                    return http_stream_open( stream, filename + 7 );\n               if (!strncmp( filename, \"rtsp://\", 7 ))\n                    return rtsp_stream_open( stream, filename+7 );\n\n               return DR_UNSUPPORTED;\n          }\n     }\n\n     switch (status) {\n          case 200 ... 299:\n               break;\n          default:\n               if (status)\n                    D_ERROR( \"Direct/Stream: Server returned status %d\\n\", status );\n               return (status == 404) ? DR_FILENOTFOUND : DR_FAILURE;\n     }\n\n     return DR_OK;\n}\n\n#endif /* DIRECT_BUILD_NETWORK */\n\n/**********************************************************************************************************************/\n\n#if DIRECT_BUILD_PIPED_STREAM\nstatic DirectResult\npipe_stream_wait( DirectStream   *stream,\n                  unsigned int    length,\n                  struct timeval *timeout )\n{\n     fd_set set;\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     if (stream->cache_size >= length)\n          return DR_OK;\n\n     FD_ZERO( &set );\n     FD_SET( stream->fd, &set );\n\n     switch (select( stream->fd + 1, &set, NULL, NULL, timeout )) {\n          case 0:\n               if (!timeout && !stream->cache_size)\n                    return DR_EOF;\n               return DR_TIMEOUT;\n          case -1:\n               return errno2result( errno );\n     }\n\n     return DR_OK;\n}\n\nstatic DirectResult\npipe_stream_peek( DirectStream *stream,\n                  unsigned int  length,\n                  int           offset,\n                  void         *buf,\n                  unsigned int *read_out )\n{\n     int          len;\n     unsigned int size = length;\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     if (offset < 0)\n          return DR_UNSUPPORTED;\n\n     len = length + offset;\n     if (len > stream->cache_size) {\n          ssize_t sz;\n\n          stream->cache = D_REALLOC( stream->cache, len );\n          if (!stream->cache) {\n               stream->cache_size = 0;\n               return D_OOM();\n          }\n\n          sz = read( stream->fd, stream->cache + stream->cache_size, len - stream->cache_size );\n          if (sz < 0) {\n               if (errno != EAGAIN || stream->cache_size == 0)\n                    return errno2result( errno );\n               sz = 0;\n          }\n\n          stream->cache_size += sz;\n          if (stream->cache_size <= offset)\n               return DR_BUFFEREMPTY;\n\n          size = stream->cache_size - offset;\n     }\n\n     direct_memcpy( buf, stream->cache + offset, size );\n\n     if (read_out)\n          *read_out = size;\n\n     return DR_OK;\n}\n\nstatic DirectResult\npipe_stream_read( DirectStream *stream,\n                  unsigned int  length,\n                  void         *buf,\n                  unsigned int *read_out )\n{\n     unsigned int size = 0;\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     if (stream->cache_size) {\n          size = MIN( stream->cache_size, length );\n\n          direct_memcpy( buf, stream->cache, size );\n\n          length -= size;\n          stream->cache_size -= size;\n\n          if (stream->cache_size) {\n               direct_memcpy( stream->cache, stream->cache + size, stream->cache_size );\n          }\n          else {\n               D_FREE( stream->cache );\n               stream->cache = NULL;\n          }\n     }\n\n     if (length) {\n          ssize_t sz;\n\n          sz = read( stream->fd, buf + size, length - size );\n          switch (sz) {\n               case 0:\n                    if (!size)\n                         return DR_EOF;\n                    break;\n               case -1:\n                    if (!size) {\n                         return (errno == EAGAIN) ? DR_BUFFEREMPTY : errno2result( errno );\n                    }\n                    break;\n               default:\n                    size += sz;\n                    break;\n          }\n     }\n\n     stream->offset += size;\n\n     if (read_out)\n          *read_out = size;\n\n     return DR_OK;\n}\n#endif /* DIRECT_BUILD_PIPED_STREAM */\n\nstatic DirectResult\nfile_stream_wait( DirectStream   *stream,\n                  unsigned int    length,\n                  struct timeval *timeout )\n{\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     if (stream->offset >= stream->length)\n          return DR_EOF;\n\n     return DR_OK;\n}\n\nstatic DirectResult\nfile_stream_peek( DirectStream *stream,\n                  unsigned int  length,\n                  int           offset,\n                  void         *buf,\n                  unsigned int *read_out )\n{\n     DirectResult ret;\n     size_t       size;\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     ret = direct_file_seek( &stream->file, offset );\n     if (ret)\n          return ret;\n\n     ret = direct_file_read( &stream->file, buf, length, &size );\n     if (ret)\n          return ret;\n\n     ret = direct_file_seek( &stream->file, -offset - (off_t) size );\n     if (ret)\n          return ret;\n\n     if (read_out)\n          *read_out = size;\n\n     return DR_OK;\n}\n\nstatic DirectResult\nfile_stream_read( DirectStream *stream,\n                  unsigned int  length,\n                  void         *buf,\n                  unsigned int *read_out )\n{\n     DirectResult ret;\n     size_t       size;\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     ret = direct_file_read( &stream->file, buf, length, &size );\n     if (ret)\n          return ret;\n\n     stream->offset += size;\n\n     if (read_out)\n          *read_out = size;\n\n     return DR_OK;\n}\n\nstatic DirectResult\nfile_stream_seek( DirectStream *stream,\n                  unsigned int  offset )\n{\n     DirectResult ret;\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     ret = direct_file_seek_to( &stream->file, offset );\n     if (ret)\n          return ret;\n\n     stream->offset = offset;\n\n     return DR_OK;\n}\n\nstatic DirectResult\nfile_stream_open( DirectStream *stream,\n                  const char   *filename )\n{\n     DirectResult   ret;\n     DirectFileInfo info;\n\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     ret = direct_file_open( &stream->file, filename, O_RDONLY | O_NONBLOCK, 0644 );\n     if (ret)\n          return ret;\n\n#if DIRECT_BUILD_PIPED_STREAM\n     stream->fd = stream->file.fd;\n\n     if (lseek( stream->fd, 0, SEEK_CUR ) < 0 && errno == ESPIPE) {\n          stream->length = -1;\n          stream->wait   = pipe_stream_wait;\n          stream->peek   = pipe_stream_peek;\n          stream->read   = pipe_stream_read;\n\n          return DR_OK;\n     }\n#endif /* DIRECT_BUILD_PIPED_STREAM */\n\n     ret = direct_file_get_info( &stream->file, &info );\n     if (ret) {\n          direct_file_close( &stream->file );\n          return ret;\n     }\n\n     stream->length = info.size;\n     stream->wait   = file_stream_wait;\n     stream->peek   = file_stream_peek;\n     stream->read   = file_stream_read;\n     stream->seek   = file_stream_seek;\n\n     return DR_OK;\n}\n\n/**********************************************************************************************************************/\n\nDirectResult\ndirect_stream_create( const char    *filename,\n                      DirectStream **ret_stream )\n{\n     DirectResult  ret;\n     DirectStream *stream;\n\n     D_ASSERT( filename != NULL );\n     D_ASSERT( ret_stream != NULL );\n\n     D_DEBUG_AT( Direct_Stream, \"%s( '%s' )\\n\", __FUNCTION__, filename );\n\n     stream = D_CALLOC( 1, sizeof(DirectStream) );\n     if (!stream)\n          return D_OOM();\n\n     D_MAGIC_SET( stream, DirectStream );\n\n     stream->ref =  1;\n     stream->fd  = -1;\n\n     if (direct_getenv( \"D_STREAM_BYPASS\" )) {\n          ret = DR_OK;\n     }\n     else if (!strncmp( filename, \"file://\", 7 )) {\n          ret = file_stream_open( stream, filename + 7 );\n     }\n#if DIRECT_BUILD_NETWORK\n     else if (!strncmp( filename, \"ftp://\", 6 )) {\n          ret = ftp_stream_open( stream, filename + 6 );\n     }\n     else if (!strncmp( filename, \"http://\", 7 )) {\n          ret = http_stream_open( stream, filename + 7 );\n     }\n     else if (!strncmp( filename, \"rtsp://\", 7 )) {\n          ret = rtsp_stream_open( stream, filename + 7 );\n     }\n     else if (!strncmp( filename, \"tcp://\", 6 )) {\n          ret = net_stream_open( stream, filename + 6, IPPROTO_TCP );\n     }\n     else if (!strncmp( filename, \"udp://\", 6 )) {\n          ret = net_stream_open( stream, filename + 6, IPPROTO_UDP );\n     }\n#endif /* DIRECT_BUILD_NETWORK */\n     else {\n          ret = file_stream_open( stream, filename );\n     }\n\n     if (ret) {\n          direct_stream_close( stream );\n          D_FREE( stream );\n          return ret;\n     }\n\n     *ret_stream = stream;\n\n     return DR_OK;\n}\n\nDirectStream *\ndirect_stream_dup( DirectStream *stream )\n{\n     D_MAGIC_ASSERT( stream, DirectStream );\n\n     stream->ref++;\n\n     return stream;\n}\n\nint\ndirect_stream_fileno( DirectStream  *stream )\n{\n     D_MAGIC_ASSERT( stream, DirectStream );\n\n     return stream->fd;\n}\n\nbool\ndirect_stream_seekable( DirectStream *stream )\n{\n     D_MAGIC_ASSERT( stream, DirectStream );\n\n     return stream->seek ? true : false;\n}\n\nbool\ndirect_stream_remote( DirectStream *stream )\n{\n     D_MAGIC_ASSERT( stream, DirectStream );\n\n#if DIRECT_BUILD_NETWORK\n     if (stream->remote.host)\n          return true;\n#endif /* DIRECT_BUILD_NETWORK */\n\n     return false;\n}\n\nconst char *\ndirect_stream_mime( DirectStream *stream )\n{\n     D_MAGIC_ASSERT( stream, DirectStream );\n\n     return stream->mime;\n}\n\nunsigned int\ndirect_stream_offset( DirectStream *stream )\n{\n     D_MAGIC_ASSERT( stream, DirectStream );\n\n     return stream->offset;\n}\n\nunsigned int\ndirect_stream_length( DirectStream *stream )\n{\n     D_MAGIC_ASSERT( stream, DirectStream );\n\n     return (unsigned int) ((stream->length >= 0) ? stream->length : stream->offset);\n}\n\nDirectResult\ndirect_stream_wait( DirectStream   *stream,\n                    unsigned int    length,\n                    struct timeval *timeout )\n{\n     D_MAGIC_ASSERT( stream, DirectStream );\n\n     if (length && stream->wait)\n          return stream->wait( stream, length, timeout );\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_stream_peek( DirectStream *stream,\n                    unsigned int  length,\n                    int           offset,\n                    void         *buf,\n                    unsigned int *read_out )\n{\n     D_MAGIC_ASSERT( stream, DirectStream );\n     D_ASSERT( length != 0 );\n     D_ASSERT( buf != NULL );\n\n     if (stream->length >= 0 && (stream->offset + offset) >= stream->length)\n          return DR_EOF;\n\n     if (stream->peek)\n          return stream->peek( stream, length, offset, buf, read_out );\n\n     return DR_UNSUPPORTED;\n}\n\nDirectResult\ndirect_stream_read( DirectStream *stream,\n                    unsigned int  length,\n                    void         *buf,\n                    unsigned int *read_out )\n{\n     D_MAGIC_ASSERT( stream, DirectStream );\n     D_ASSERT( length != 0 );\n     D_ASSERT( buf != NULL );\n\n     if (stream->length >= 0 && stream->offset >= stream->length)\n          return DR_EOF;\n\n     if (stream->read)\n          return stream->read( stream, length, buf, read_out );\n\n     return DR_UNSUPPORTED;\n}\n\nDirectResult\ndirect_stream_seek( DirectStream *stream,\n                    unsigned int  offset )\n{\n     D_MAGIC_ASSERT( stream, DirectStream );\n\n     if (stream->offset == offset)\n          return DR_OK;\n\n     if (stream->length >= 0 && offset > stream->length)\n          offset = (unsigned int) stream->length;\n\n     if (stream->seek)\n          return stream->seek( stream, offset );\n\n     return DR_UNSUPPORTED;\n}\n\nvoid\ndirect_stream_destroy( DirectStream *stream )\n{\n     D_DEBUG_AT( Direct_Stream, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( stream, DirectStream );\n\n     if (--stream->ref == 0) {\n          direct_stream_close( stream );\n\n          D_MAGIC_CLEAR( stream );\n\n          D_FREE( stream );\n     }\n}\n"
  },
  {
    "path": "lib/direct/stream.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__STREAM_H__\n#define __DIRECT__STREAM_H__\n\n#include <direct/types.h>\n\n/**********************************************************************************************************************/\n\n/*\n * Create a stream wrapper.\n *\n * 'filename' can be a plain file name or one of the following:\n *   file://<path>\n *   http://<host>[:<port>]/<path>\n *   ftp://<host>[:<port>]/<path>\n *   tcp://<host>:<port>\n *   udp://<host>:<port>\n */\nDirectResult DIRECT_API  direct_stream_create  ( const char      *filename,\n                                                 DirectStream   **ret_stream );\n\n/*\n * Duplicate the stream.\n */\nDirectStream DIRECT_API *direct_stream_dup     ( DirectStream    *stream );\n\n/*\n * Return the file descriptor associated to the stream.\n */\nint          DIRECT_API  direct_stream_filenoi ( DirectStream    *stream );\n\n/*\n * True if stream is seekable.\n */\nbool         DIRECT_API  direct_stream_seekable( DirectStream    *stream );\n\n/*\n * True if stream originates from a remote host.\n */\nbool         DIRECT_API  direct_stream_remote  ( DirectStream    *stream );\n\n/*\n * Get the mime description of the stream.\n */\nconst char   DIRECT_API *direct_stream_mime    ( DirectStream    *stream );\n\n/*\n * Get stream position.\n */\nunsigned int DIRECT_API  direct_stream_offset  ( DirectStream    *stream );\n\n/*\n * Get stream length.\n */\nunsigned int DIRECT_API  direct_stream_length  ( DirectStream    *stream );\n\n/*\n * Wait for data to be available.\n * If 'timeout' is NULL, the function blocks indefinitely.\n * Set the 'timeout' value to 0 to make the function return immediatly.\n */\nDirectResult DIRECT_API  direct_stream_wait    ( DirectStream    *stream,\n                                                 unsigned int     length,\n                                                 struct timeval  *timeout );\n\n/*\n * Peek 'length' bytes of data at offset 'offset' from the stream.\n */\nDirectResult DIRECT_API  direct_stream_peek    ( DirectStream    *stream,\n                                                 unsigned int     length,\n                                                 int              offset,\n                                                 void            *buf,\n                                                 unsigned int    *read_out );\n\n/*\n * Fetch 'length' bytes of data from the stream.\n */\nDirectResult DIRECT_API  direct_stream_read    ( DirectStream    *stream,\n                                                 unsigned int     length,\n                                                 void            *buf,\n                                                 unsigned int    *read_out );\n\n/*\n * Seek to the specified absolute offset within the stream.\n */\nDirectResult DIRECT_API  direct_stream_seek    ( DirectStream    *stream,\n                                                 unsigned int     offset );\n\n/*\n * Destroy the stream wrapper.\n */\nvoid         DIRECT_API  direct_stream_destroy ( DirectStream    *stream );\n\n#endif\n"
  },
  {
    "path": "lib/direct/system.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/debug.h>\n#include <direct/messages.h>\n#include <direct/system.h>\n\nD_DEBUG_DOMAIN( Direct_Futex, \"Direct/Futex\", \"Direct Futex\" );\n\n/**********************************************************************************************************************/\n\nDirectResult\ndirect_futex_wait( int *uaddr,\n                   int  val )\n{\n     DirectResult ret;\n\n     D_ASSERT( uaddr != NULL );\n\n     D_DEBUG_AT( Direct_Futex, \"%s( %p, %d ) <- %d\\n\", __FUNCTION__, uaddr, val, *uaddr );\n\n     if (*uaddr != val) {\n          D_DEBUG_AT( Direct_Futex, \"  -> value changed!\\n\" );\n          return DR_OK;\n     }\n\n     while ((ret = direct_futex( uaddr, FUTEX_WAIT, val, NULL, NULL, 0 ))) {\n          switch (ret) {\n               case DR_SIGNALLED:\n                    continue;\n\n               case DR_BUSY:\n                    return DR_OK;\n\n               default:\n                    D_DERROR( ret, \"Direct/Futex: FUTEX_WAIT( %p, %d ) failed!\\n\", uaddr, val );\n                    return ret;\n          }\n     }\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_futex_wait_timed( int *uaddr,\n                         int  val,\n                         int  ms )\n{\n     DirectResult    ret;\n     struct timespec timeout;\n\n     D_ASSERT( uaddr != NULL );\n\n     D_DEBUG_AT( Direct_Futex, \"%s( %p, %d, %d ) <- %d\\n\", __FUNCTION__, uaddr, val, ms, *uaddr );\n\n     if (*uaddr != val) {\n          D_DEBUG_AT( Direct_Futex, \"  -> value changed!\\n\" );\n          return DR_OK;\n     }\n\n     timeout.tv_sec  =  ms / 1000;\n     timeout.tv_nsec = (ms % 1000) * 1000000;\n\n     while ((ret = direct_futex( uaddr, FUTEX_WAIT, val, &timeout, NULL, 0 ))) {\n          switch (ret) {\n               case DR_SIGNALLED:\n                    continue;\n\n               case DR_BUSY:\n                    return DR_OK;\n\n               default:\n                    D_DERROR( ret, \"Direct/Futex: FUTEX_WAIT( %p, %d ) failed!\\n\", uaddr, val );\n\n               case DR_TIMEOUT:\n                    return ret;\n          }\n     }\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_futex_wake( int *uaddr,\n                   int  num )\n{\n     DirectResult ret;\n\n     D_ASSERT( uaddr != NULL );\n     D_ASSERT( num > 0 );\n\n     D_DEBUG_AT( Direct_Futex, \"%s( %p, %d ) <- %d\\n\", __FUNCTION__, uaddr, num, *uaddr );\n\n     while ((ret = direct_futex( uaddr, FUTEX_WAKE, num, NULL, NULL, 0 ))) {\n          switch (ret) {\n               case DR_BUSY:\n                    continue;\n\n               default:\n                    D_DERROR( ret, \"Direct/Futex: FUTEX_WAKE( %p, %d ) failed!\\n\", uaddr, num );\n                    return ret;\n          }\n     }\n\n     return DR_OK;\n}\n\nunsigned int __Direct_Futex_Wait_Count = 0;\nunsigned int __Direct_Futex_Wake_Count = 0;\n"
  },
  {
    "path": "lib/direct/system.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__SYSTEM_H__\n#define __DIRECT__SYSTEM_H__\n\n#include <direct/os/system.h>\n\n/**********************************************************************************************************************/\n\nDirectResult DIRECT_API direct_futex_wait      ( int *uaddr,\n                                                 int  val );\n\nDirectResult DIRECT_API direct_futex_wait_timed( int *uaddr,\n                                                 int  val,\n                                                 int  ms );\n\nDirectResult DIRECT_API direct_futex_wake      ( int *uaddr,\n                                                 int  num );\n\n#endif\n"
  },
  {
    "path": "lib/direct/thread.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/list.h>\n#include <direct/mem.h>\n#include <direct/messages.h>\n#if D_DEBUG_ENABLED\n#include <direct/system.h>\n#endif\n#include <direct/thread.h>\n\nD_DEBUG_DOMAIN( Direct_Thread,     \"Direct/Thread\",      \"Direct Thread Management\" );\nD_DEBUG_DOMAIN( Direct_ThreadInit, \"Direct/Thread/Init\", \"Direct Thread Init\" );\n\n/**********************************************************************************************************************/\n\nstruct __D_DirectThreadInitHandler {\n     DirectLink            link;\n\n     int                   magic;\n\n     DirectThreadInitFunc  func;\n     void                 *arg;\n};\n\n/**********************************************************************************************************************/\n\nstatic DirectMutex  handler_lock;\nstatic DirectLink  *handlers;\n\n/**********************************************************************************************************************/\n\nvoid\n__D_thread_init()\n{\n     direct_mutex_init( &handler_lock );\n}\n\nvoid\n__D_thread_deinit()\n{\n     direct_mutex_deinit( &handler_lock );\n}\n\n/**********************************************************************************************************************/\n\nDirectThreadInitHandler *\ndirect_thread_add_init_handler( DirectThreadInitFunc  func,\n                                void                 *arg )\n{\n     DirectThreadInitHandler *handler;\n\n     D_DEBUG_AT( Direct_Thread, \"Adding thread init handler %p...\\n\", func );\n\n     handler = D_CALLOC( 1, sizeof(DirectThreadInitHandler) );\n     if (!handler) {\n          return NULL;\n     }\n\n     handler->func = func;\n     handler->arg  = arg;\n\n     D_MAGIC_SET( handler, DirectThreadInitHandler );\n\n     direct_mutex_lock( &handler_lock );\n\n     direct_list_append( &handlers, &handler->link );\n\n     direct_mutex_unlock( &handler_lock );\n\n     return handler;\n}\n\nvoid\ndirect_thread_remove_init_handler( DirectThreadInitHandler *handler )\n{\n     D_MAGIC_ASSERT( handler, DirectThreadInitHandler );\n\n     D_DEBUG_AT( Direct_Thread, \"Removing thread init handler %p...\\n\", handler->func );\n\n     direct_mutex_lock( &handler_lock );\n\n     direct_list_remove( &handlers, &handler->link );\n\n     direct_mutex_unlock( &handler_lock );\n\n     D_MAGIC_CLEAR( handler );\n\n     D_FREE( handler );\n}\n\nDirectThread *\ndirect_thread_create( DirectThreadType      thread_type,\n                      DirectThreadMainFunc  thread_main,\n                      void                 *arg,\n                      const char           *name )\n{\n     DirectThread *thread;\n\n     D_ASSERT( thread_main != NULL );\n     D_ASSERT( name != NULL );\n\n     D_DEBUG_AT( Direct_ThreadInit, \"%s( %s, %p( %p ), '%s' )\\n\", __FUNCTION__,\n                 direct_thread_type_name( thread_type ), thread_main, arg, name );\n\n     /* Allocate thread structure. */\n     thread = D_CALLOC( 1, sizeof(DirectThread) );\n     if (!thread) {\n          D_OOM();\n          return NULL;\n     }\n\n     /* Write thread information to structure. */\n     thread->name = D_STRDUP( name );\n     thread->type = thread_type;\n     thread->main = thread_main;\n     thread->arg  = arg;\n\n     /* Initialize to -1 for synchronization. */\n     thread->tid  = (pid_t) -1;\n\n     /* Initialize mutex and condition. */\n     direct_recursive_mutex_init( &thread->lock );\n     direct_waitqueue_init( &thread->cond );\n\n     D_MAGIC_SET( thread, DirectThread );\n\n     /* Lock the thread mutex. */\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> locking...\\n\" );\n     direct_mutex_lock( &thread->lock );\n\n     /* Create and run the thread. */\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> creating handle...\\n\" );\n     direct_thread_init( thread );\n\n     /* Wait for completion of the thread's initialization. */\n     while (!thread->init) {\n          D_DEBUG_AT( Direct_ThreadInit, \"  -> waiting...\\n\" );\n          direct_waitqueue_wait( &thread->cond, &thread->lock );\n     }\n\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> started '%s' (%d) [%s - %s/%d] <\"_ZU\">...\\n\",\n                 thread->name, thread->tid, direct_thread_type_name( thread->type ),\n                 direct_thread_policy_name( thread->policy ), thread->priority, thread->stack_size );\n\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> ...thread is running\\n\" );\n\n     /* Unlock the thread mutex. */\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> unlocking...\\n\" );\n     direct_mutex_unlock( &thread->lock );\n\n     D_DEBUG_AT( Direct_ThreadInit, \"  -> returning %p\\n\", thread );\n\n     return thread;\n}\n\nDirectResult\ndirect_thread_wait( DirectThread *thread,\n                   int            timeout_ms )\n{\n     DirectResult ret;\n     unsigned int old_counter = thread->counter;\n\n     D_MAGIC_ASSERT( thread, DirectThread );\n     D_ASSERT( thread->tid != -1 );\n\n     D_ASSUME( !thread->canceled );\n\n     D_DEBUG_AT( Direct_Thread, \"%s( %p, '%s' %d, %dms )\\n\", __FUNCTION__,\n                 thread->main, thread->name, thread->tid, timeout_ms );\n\n     while (old_counter == thread->counter && !thread->terminated) {\n          if (timeout_ms <= 0)\n               ret = direct_waitqueue_wait( &thread->cond, &thread->lock );\n          else\n               ret = direct_waitqueue_wait_timeout( &thread->cond, &thread->lock, timeout_ms * 1000 );\n\n          if (ret)\n               return ret;\n     }\n\n     if (thread->terminated)\n          return DR_DEAD;\n\n     return DR_OK;\n}\n\nDirectResult\ndirect_thread_notify( DirectThread *thread )\n{\n     DirectResult ret;\n\n     D_MAGIC_ASSERT( thread, DirectThread );\n     D_ASSERT( thread->tid != -1 );\n\n     D_ASSUME( !thread->canceled );\n\n     D_DEBUG_AT( Direct_Thread, \"%s( %p, '%s' %d )\\n\", __FUNCTION__, thread->main, thread->name, thread->tid );\n\n     ret = direct_mutex_lock( &thread->lock );\n     if (ret)\n          return ret;\n\n     thread->counter++;\n\n     direct_mutex_unlock( &thread->lock );\n\n     return direct_waitqueue_broadcast( &thread->cond );\n}\n\nDirectResult\ndirect_thread_lock( DirectThread *thread )\n{\n     D_MAGIC_ASSERT( thread, DirectThread );\n     D_ASSERT( thread->tid != -1 );\n\n     D_ASSUME( !thread->canceled );\n\n     D_DEBUG_AT( Direct_Thread, \"%s( %p, '%s' %d )\\n\", __FUNCTION__, thread->main, thread->name, thread->tid );\n\n     return direct_mutex_lock( &thread->lock );\n}\n\nDirectResult\ndirect_thread_unlock( DirectThread *thread )\n{\n     D_MAGIC_ASSERT( thread, DirectThread );\n     D_ASSERT( thread->tid != -1 );\n\n     D_ASSUME( !thread->canceled );\n\n     D_DEBUG_AT( Direct_Thread, \"%s( %p, '%s' %d )\\n\", __FUNCTION__, thread->main, thread->name, thread->tid );\n\n     return direct_mutex_unlock( &thread->lock );\n}\n\nDirectResult\ndirect_thread_terminate( DirectThread *thread )\n{\n     D_MAGIC_ASSERT( thread, DirectThread );\n     D_ASSERT( thread->tid != -1 );\n\n     D_ASSUME( thread->tid != direct_gettid() );\n     D_ASSUME( !thread->canceled );\n\n     D_DEBUG_AT( Direct_Thread, \"%s( %p, '%s' %d )\\n\", __FUNCTION__, thread->main, thread->name, thread->tid );\n\n     thread->terminated = true;\n\n     return direct_thread_notify( thread );\n}\n\nvoid\ndirect_thread_destroy( DirectThread *thread )\n{\n     D_MAGIC_ASSERT( thread, DirectThread );\n\n     D_ASSUME( thread->tid != direct_gettid() );\n     D_ASSUME( !thread->detached );\n\n     D_DEBUG_AT( Direct_ThreadInit, \"%s( %p, '%s' %d )\\n\", __FUNCTION__, thread->main, thread->name, thread->tid );\n\n     if (thread->detached) {\n          D_DEBUG_AT( Direct_ThreadInit, \"  -> detached\\n\" );\n          return;\n     }\n\n     direct_thread_deinit( thread );\n\n     D_MAGIC_CLEAR( thread );\n\n     D_FREE( thread->name );\n     D_FREE( thread );\n}\n\npid_t\ndirect_thread_get_tid( const DirectThread *thread )\n{\n     return thread->tid;\n}\n\nbool\ndirect_thread_is_canceled( const DirectThread *thread )\n{\n     return thread->canceled;\n}\n\nbool\ndirect_thread_is_joined( const DirectThread *thread )\n{\n     return thread->joined;\n}\n\n/**********************************************************************************************************************/\n\nvoid\n_direct_thread_call_init_handlers( DirectThread *thread )\n{\n     DirectThreadInitHandler *handler;\n\n     direct_mutex_lock( &handler_lock );\n\n     direct_list_foreach (handler, handlers) {\n          handler->func( thread, handler->arg );\n     }\n\n     direct_mutex_unlock( &handler_lock );\n}\n"
  },
  {
    "path": "lib/direct/thread.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__THREAD_H__\n#define __DIRECT__THREAD_H__\n\n#include <direct/os/thread.h>\n\n/**********************************************************************************************************************/\n\ntypedef void (*DirectThreadInitFunc)( DirectThread *thread, void *arg );\n\n/**********************************************************************************************************************/\n\n/*\n * Add a handler being called at the beginning of new threads.\n */\nDirectThreadInitHandler DIRECT_API *direct_thread_add_init_handler   ( DirectThreadInitFunc  func,\n                                                                       void                 *arg );\n\n/*\n * Remove the specified handler.\n */\nvoid                    DIRECT_API  direct_thread_remove_init_handler( DirectThreadInitHandler *handler );\n\n/*\n * Create a new thread and start it. The thread type is relevant for the scheduling priority.\n */\nDirectThread            DIRECT_API *direct_thread_create             ( DirectThreadType      thread_type,\n                                                                       DirectThreadMainFunc  thread_main,\n                                                                       void                 *arg,\n                                                                       const char           *name );\n\n/*\n * Wait on the thread object to be notified via direct_thread_notify().\n */\nDirectResult            DIRECT_API  direct_thread_wait               ( DirectThread         *thread,\n                                                                       int                   timeout_ms );\n\n/*\n * Notify the thread object waking up callers of direct_thread_wait().\n */\nDirectResult            DIRECT_API  direct_thread_notify             ( DirectThread         *thread );\n\n/*\n * The thread acquires the lock.\n */\nDirectResult            DIRECT_API  direct_thread_lock               ( DirectThread         *thread );\n\n/*\n * The thread releases the lock.\n */\nDirectResult            DIRECT_API  direct_thread_unlock             ( DirectThread         *thread );\n\n/*\n * Kindly ask the thread to terminate (for joining without thread cancellation).\n */\nDirectResult            DIRECT_API  direct_thread_terminate          ( DirectThread         *thread );\n\n/*\n * Free resources allocated by direct_thread_create. If the thread is still running it will be killed.\n */\nvoid                    DIRECT_API  direct_thread_destroy            ( DirectThread         *thread );\n\n/*\n * Return the thread's ID.\n */\npid_t                   DIRECT_API  direct_thread_get_tid            ( const DirectThread   *thread );\n\n/*\n * True if the thread is canceled.\n */\nbool                    DIRECT_API  direct_thread_is_canceled        ( const DirectThread   *thread );\n\n/*\n * True if the thread is joined.\n */\nbool                    DIRECT_API  direct_thread_is_joined          ( const DirectThread   *thread );\n\n/**********************************************************************************************************************/\n\nvoid __D_thread_init  ( void );\nvoid __D_thread_deinit( void );\n\n#endif\n"
  },
  {
    "path": "lib/direct/trace.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/trace.h>\n\n#if DIRECT_BUILD_TRACE\n\n#include <direct/filesystem.h>\n#include <direct/list.h>\n#include <direct/log.h>\n#include <direct/mem.h>\n#include <direct/memcpy.h>\n#include <direct/messages.h>\n#include <direct/system.h>\n#include <direct/thread.h>\n\nD_DEBUG_DOMAIN( Direct_Trace, \"Direct/Trace\", \"Direct Trace support\" );\n\n#endif /* DIRECT_BUILD_TRACE */\n\n/**********************************************************************************************************************/\n\n#if DIRECT_BUILD_TRACE\n\n#define MAX_LEVEL 200\n\ntypedef enum {\n     TF_NONE  = 0x00000000,\n     TF_DEBUG = 0x00000001\n} TraceFlags;\n\ntypedef struct {\n     void       *addr;\n     TraceFlags  flags;\n} Trace;\n\nstruct __D_DirectTraceBuffer {\n     DirectLink    link;\n     int           magic;\n     pid_t         tid;\n     char         *name;\n     DirectThread *thread;\n     int           level;\n     bool          in_trace;\n     Trace         trace[MAX_LEVEL];\n};\n\n/**********************************************************************************************************************/\n\nstatic DirectLink  *buffers;\nstatic DirectMutex  buffers_lock = DIRECT_MUTEX_INITIALIZER();\n\n__dfb_no_instrument_function__\nstatic __inline__ DirectTraceBuffer *\nget_trace_buffer()\n{\n     DirectTraceBuffer *buffer;\n     DirectThread      *self = direct_thread_self();\n\n     buffer = self->trace_buffer;\n     if (!buffer) {\n          buffer = direct_calloc( 1, sizeof(DirectTraceBuffer) );\n          if (!buffer)\n               return NULL;\n\n          buffer->tid    = direct_gettid();\n          buffer->thread = direct_thread_self();\n\n          D_MAGIC_SET( buffer, DirectTraceBuffer );\n\n          self->trace_buffer = buffer;\n\n          direct_mutex_lock( &buffers_lock );\n          direct_list_append( &buffers, &buffer->link );\n          direct_mutex_unlock( &buffers_lock );\n     }\n\n     return buffer;\n}\n\n#define NAME_LEN 92\n\ntypedef struct {\n     long offset;\n     char name[NAME_LEN];\n} Symbol;\n\ntypedef struct {\n     DirectLink  link;\n\n     char       *filename;\n     Symbol     *symbols;\n     int         capacity;\n     int         num_symbols;\n} SymbolTable;\n\nstatic DirectLink  *tables      = NULL;\nstatic DirectMutex  tables_lock = DIRECT_MUTEX_INITIALIZER();\n\n__dfb_no_instrument_function__\nstatic void\nadd_symbol( SymbolTable *table,\n            long         offset,\n            const char  *name )\n{\n     Symbol *symbol;\n\n     if (table->num_symbols == table->capacity) {\n          Symbol *symbols;\n          int     capacity = table->capacity * 2;\n\n          if (!capacity)\n               capacity = 256;\n\n          symbols = direct_malloc( capacity * sizeof(Symbol) );\n          if (!symbols) {\n               D_WARN( \"out of memory\" );\n               return;\n          }\n\n          direct_memcpy( symbols, table->symbols, table->num_symbols * sizeof(Symbol) );\n\n          direct_free( table->symbols );\n\n          table->symbols  = symbols;\n          table->capacity = capacity;\n     }\n\n     symbol = &table->symbols[table->num_symbols++];\n\n     symbol->offset = offset;\n\n     direct_snputs( symbol->name, name, NAME_LEN );\n}\n\n__dfb_no_instrument_function__\nstatic SymbolTable *\nload_symbols( const char *filename )\n{\n     DirectResult  ret;\n     SymbolTable  *table;\n     DirectFile    f;\n     bool          is_pipe = false;\n     char          file[1024];\n     char          line[1024];\n     int           command_len;\n     const char   *full_path = filename;\n     char         *tmp;\n\n     D_DEBUG_AT( Direct_Trace, \"%s( %s )\\n\", __FUNCTION__, filename );\n\n     if (filename) {\n          ret = direct_access( filename, R_OK );\n          if (ret && ret == DR_FILENOTFOUND) {\n               ssize_t len = 0;\n\n               ret = direct_readlink( \"/proc/self/exe\", file, sizeof(file) - 1, &len );\n               if (ret) {\n                    D_DERROR( ret, \"Direct/Trace: direct_readlink( '/proc/self/exe' ) failed!\\n\" );\n                    return NULL;\n               }\n\n               file[len] = 0;\n\n               tmp = strrchr( file, '/' );\n               if (!tmp)\n                    return NULL;\n\n               if (strcmp( filename, tmp + 1 ))\n                    return NULL;\n\n               full_path = file;\n          }\n     }\n     else {\n          ssize_t len = 0;\n\n          ret = direct_readlink( \"/proc/self/exe\", file, sizeof(file) - 1, &len );\n          if (ret) {\n               D_DERROR( ret, \"Direct/Trace: direct_readlink( '/proc/self/exe' ) failed!\\n\" );\n               return NULL;\n          }\n\n          file[len] = 0;\n\n          full_path = file;\n     }\n\n     command_len = strlen( full_path ) + 32;\n     char command[command_len+1];\n\n     /* First check if there's a \"nm-n\" file. */\n     tmp = strrchr( full_path, '/' );\n     if (!tmp)\n          return NULL;\n\n     *tmp = 0;\n     snprintf( command, command_len, \"%s/nm-n.%s\", full_path, tmp + 1 );\n     *tmp = '/';\n\n     ret = direct_access( command, R_OK );\n     if (ret == DR_OK) {\n          ret = direct_file_open( &f, command, O_RDONLY, 0 );\n          if (ret)\n               D_DERROR( ret, \"Direct/Trace: direct_file_open( '%s' ) failed!\\n\", command );\n     }\n     else {\n          snprintf( command, command_len, \"%s.nm\", full_path );\n\n          ret = direct_access( command, R_OK );\n          if (ret == DR_OK) {\n               ret = direct_file_open( &f, command, O_RDONLY, 0 );\n               if (ret)\n                    D_DERROR( ret, \"Direct/Trace: direct_file_open( '%s' ) failed!\\n\", command );\n          }\n     }\n\n     /* Fallback to live mode. */\n     if (ret) {\n          snprintf( command, command_len, \"nm -nC %s\", full_path );\n\n          if (!direct_config->nm_for_trace) {\n               D_DEBUG_AT( Direct_Trace, \"  -> not running '%s', enable via 'nm-for-trace' option\\n\", command );\n               return NULL;\n          }\n\n          D_DEBUG_AT( Direct_Trace, \"  -> running '%s'...\\n\", command );\n\n          ret = direct_popen( &f, command, O_RDONLY );\n          if (ret) {\n               D_DERROR( ret, \"Direct/Trace: direct_popen( '%s' ) failed!\\n\", command );\n               return NULL;\n          }\n\n          is_pipe = true;\n     }\n\n     table = direct_calloc( 1, sizeof(SymbolTable) );\n     if (!table) {\n          D_OOM();\n          goto out;\n     }\n\n     if (filename)\n          table->filename = direct_strdup( filename );\n\n     while (direct_file_get_string( &f, line, sizeof(line) ) == DR_OK) {\n          int  n;\n          int  digits = sizeof(long) * 2;\n          long offset = 0;\n          int  length = strlen( line );\n\n          if (line[0] == ' ' || length < (digits + 5) || line[length-1] != '\\n')\n               continue;\n\n          if (line[digits+1] != 't' && line[digits+1] != 'T' && line[digits+1] != 'W')\n               continue;\n\n          if (line[digits] != ' ' || line[digits+2] != ' ' || line[digits+3] == '.')\n               continue;\n\n          for (n = 0; n < digits; n++) {\n               char c = line[n];\n\n               offset <<= 4;\n\n               if (c >= '0' && c <= '9')\n                    offset |= c - '0';\n               else\n                    offset |= c - 'a' + 10;\n          }\n\n          line[length-1] = 0;\n\n          add_symbol( table, offset, line + digits + 3 );\n     }\n\nout:\n     if (is_pipe)\n          direct_pclose( &f );\n     else\n          direct_file_close( &f );\n\n     return table;\n}\n\n__dfb_no_instrument_function__\nstatic int\ncompare_symbols( const void *x,\n                 const void *y )\n{\n     return  *((const long*) x)  -  *((const long*) y);\n}\n\n__dfb_no_instrument_function__\nstatic SymbolTable *\nfind_table( const char *filename )\n{\n     SymbolTable *table;\n\n     if (filename) {\n          direct_list_foreach (table, tables) {\n               if (table->filename && !strcmp( filename, table->filename ))\n                    return table;\n          }\n     }\n     else {\n          direct_list_foreach (table, tables) {\n               if (!table->filename)\n                    return table;\n          }\n     }\n\n     return NULL;\n}\n\n/**********************************************************************************************************************/\n\n__dfb_no_instrument_function__\nconst char *\ndirect_trace_lookup_symbol( const char *filename,\n                            long        offset )\n{\n     Symbol      *symbol;\n     SymbolTable *table;\n\n     direct_mutex_lock( &tables_lock );\n\n     table = find_table( filename );\n     if (!table) {\n          table = load_symbols( filename );\n          if (!table) {\n               direct_mutex_unlock( &tables_lock );\n               return false;\n          }\n\n          direct_list_prepend( &tables, &table->link );\n     }\n\n     direct_mutex_unlock( &tables_lock );\n\n     symbol = direct_bsearch( &offset, table->symbols, table->num_symbols, sizeof(Symbol), compare_symbols );\n\n     return symbol ? symbol->name : NULL;\n}\n\n__dfb_no_instrument_function__\nconst char *\ndirect_trace_lookup_file( void  *address,\n                          void **ret_base )\n{\n     Dl_info info;\n\n     if (dladdr( address, &info )) {\n          if (ret_base)\n               *ret_base = info.dli_fbase;\n\n          return info.dli_fname;\n     }\n     else\n     {\n          if (ret_base)\n               *ret_base = NULL;\n     }\n\n     return NULL;\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_trace_print_stack( DirectTraceBuffer *buffer )\n{\n     Dl_info info;\n     int     i;\n     int     level;\n\n     if (!direct_config->trace)\n          return;\n\n     if (!buffer) {\n          buffer = get_trace_buffer();\n          if (!buffer)\n               return;\n     }\n\n     if (buffer->in_trace)\n          return;\n\n     buffer->in_trace = true;\n\n     level = buffer->level;\n     if (level > MAX_LEVEL) {\n          D_WARN( \"only showing %d of %d items\", MAX_LEVEL, level );\n          level = MAX_LEVEL;\n     }\n     else if (level == 0) {\n          buffer->in_trace = false;\n          return;\n     }\n\n     direct_log_printf( NULL, \"(-) [%5d: -STACK- '%s']\\n\",\n                        buffer->tid, buffer->thread ? buffer->thread->name : buffer->name );\n\n     for (i = level - 1; i >= 0; i--) {\n          void *fn = buffer->trace[i].addr;\n\n          if (dladdr( fn, &info )) {\n               if (info.dli_fname) {\n                    const char *symbol = direct_trace_lookup_symbol( info.dli_fname, (long) (fn - info.dli_fbase) );\n                    if (!symbol) {\n                         symbol = direct_trace_lookup_symbol( info.dli_fname, (long) fn );\n                         if (!symbol) {\n                              if (info.dli_sname)\n                                   symbol = info.dli_sname;\n                              else\n                                   symbol = \"??\";\n                         }\n                    }\n\n                    direct_log_printf( NULL, \"  #%-2d 0x%08lx in %s () from %s [%p]\\n\",\n                                       level - i - 1, (unsigned long) fn, symbol, info.dli_fname, info.dli_fbase );\n               }\n               else if (info.dli_sname) {\n                    direct_log_printf( NULL, \"  #%-2d 0x%08lx in %s ()\\n\",\n                                       level - i - 1, (unsigned long) fn, info.dli_sname );\n               }\n               else\n                    direct_log_printf( NULL, \"  #%-2d 0x%08lx in ?? ()\\n\",\n                                       level - i - 1, (unsigned long) fn );\n          }\n          else\n          {\n               const char *symbol = direct_trace_lookup_symbol( NULL, (long) fn );\n               direct_log_printf( NULL, \"  #%-2d 0x%08lx in %s ()\\n\",\n                                  level - i - 1, (unsigned long) fn, symbol ?: \"??\" );\n          }\n     }\n\n     direct_log_printf( NULL, \"\\n\" );\n\n     buffer->in_trace = false;\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_trace_print_stacks()\n{\n     DirectTraceBuffer *b;\n     DirectTraceBuffer *buffer = get_trace_buffer();\n\n     direct_mutex_lock( &buffers_lock );\n\n     if (buffer && buffer->level)\n          direct_trace_print_stack( buffer );\n\n     direct_list_foreach (b, buffers) {\n          if (b != buffer && b->level)\n               direct_trace_print_stack( b );\n     }\n\n     direct_mutex_unlock( &buffers_lock );\n}\n\n__dfb_no_instrument_function__\nint\ndirect_trace_debug_indent()\n{\n     int                in     = 0;\n     DirectTraceBuffer *buffer = get_trace_buffer();\n\n     if (buffer) {\n          int level = buffer->level - 1;\n\n          if (level < 0)\n               return 0;\n\n          buffer->trace[level--].flags |= TF_DEBUG;\n\n          for (in = 0; level >= 0; level--) {\n               if (buffer->trace[level].flags & TF_DEBUG)\n                    in++;\n          }\n     }\n\n     return in;\n}\n\n__dfb_no_instrument_function__\nvoid *\ndirect_trace_get_caller()\n{\n     void              *caller = NULL;\n     DirectTraceBuffer *buffer = get_trace_buffer();\n\n     if (buffer) {\n          int level = buffer->level - 2;\n\n          if (level >= 0)\n               caller = buffer->trace[level].addr;\n     }\n\n     return caller;\n}\n\n__dfb_no_instrument_function__\nDirectTraceBuffer *\ndirect_trace_copy_buffer( DirectTraceBuffer *buffer )\n{\n     int                level;\n     DirectTraceBuffer *copy;\n\n     if (!buffer) {\n          buffer = get_trace_buffer();\n          if (!buffer)\n               return NULL;\n     }\n\n     level = buffer->level;\n     if (level > MAX_LEVEL) {\n          D_WARN( \"only copying %d of %d items\", MAX_LEVEL, level );\n          level = MAX_LEVEL;\n     }\n\n     copy = direct_calloc( 1, sizeof(DirectTraceBuffer) - sizeof(Trace) * (MAX_LEVEL - level) );\n     if (!copy)\n          return NULL;\n\n     if (buffer->thread && buffer->thread->name)\n          copy->name = direct_strdup( buffer->thread->name );\n\n     copy->tid   = buffer->tid;\n     copy->level = buffer->level;\n\n     direct_memcpy( &copy->trace[0], &buffer->trace[0], level * sizeof(Trace) );\n\n     D_MAGIC_SET( copy, DirectTraceBuffer );\n\n     return copy;\n}\n\n__dfb_no_instrument_function__\nvoid\ndirect_trace_free_buffer( DirectTraceBuffer *buffer )\n{\n     D_MAGIC_ASSERT( buffer, DirectTraceBuffer );\n\n     if (buffer->thread) {\n          direct_mutex_lock( &buffers_lock );\n          direct_list_remove( &buffers, &buffer->link );\n          direct_mutex_unlock( &buffers_lock );\n\n          buffer->thread = NULL;\n     }\n\n     if (buffer->name)\n          direct_free( buffer->name );\n\n     D_MAGIC_CLEAR( buffer );\n\n     direct_free( buffer );\n}\n\n/**********************************************************************************************************************/\n\n__dfb_no_instrument_function__\nvoid\n__cyg_profile_func_enter( void *this_fn,\n                          void *call_site )\n{\n     if (direct_config->trace) {\n          DirectTraceBuffer *buffer = get_trace_buffer();\n\n          if (buffer) {\n               int    level = buffer->level++;\n               Trace *trace = &buffer->trace[level];\n\n               if (level < MAX_LEVEL) {\n                    trace->addr  = this_fn;\n                    trace->flags = TF_NONE;\n               }\n          }\n     }\n}\n\n__dfb_no_instrument_function__\nvoid\n__cyg_profile_func_exit( void *this_fn,\n                         void *call_site )\n{\n     if (direct_config->trace) {\n          DirectTraceBuffer *buffer = get_trace_buffer();\n\n          if (buffer) {\n               if (buffer->level > 0)\n                    buffer->level--;\n          }\n     }\n}\n\n#else /* DIRECT_BUILD_TRACE */\n\nconst char *\ndirect_trace_lookup_symbol( const char *filename,\n                            long        offset )\n{\n     return NULL;\n}\n\nconst char *\ndirect_trace_lookup_file( void  *address,\n                          void **ret_base )\n{\n     if (ret_base)\n          *ret_base = NULL;\n\n     return NULL;\n}\n\nvoid\ndirect_trace_print_stack( DirectTraceBuffer *buffer )\n{\n}\n\nvoid\ndirect_trace_print_stacks()\n{\n}\n\nint\ndirect_trace_debug_indent()\n{\n     return 0;\n}\n\nvoid *\ndirect_trace_get_caller()\n{\n     return NULL;\n}\n\nDirectTraceBuffer *\ndirect_trace_copy_buffer( DirectTraceBuffer *buffer )\n{\n     return NULL;\n}\n\nvoid\ndirect_trace_free_buffer( DirectTraceBuffer *buffer )\n{\n}\n\n#endif /* DIRECT_BUILD_TRACE */\n"
  },
  {
    "path": "lib/direct/trace.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__TRACE_H__\n#define __DIRECT__TRACE_H__\n\n#include <direct/types.h>\n\n/**********************************************************************************************************************/\n\n/*\n * Look up a symbol by filename and offset.\n *\n * Returns symbol name on success or NULL.\n */\nconst char        DIRECT_API *direct_trace_lookup_symbol( const char         *filename,\n                                                          long                offset );\n\n/*\n * Returns filename on success or NULL.\n *\n * Stores load address of object in 'ret_base' on success.\n */\nconst char        DIRECT_API *direct_trace_lookup_file  ( void               *address,\n                                                          void              **ret_base );\n\n/*\n * Print stack in 'buffer' or current if NULL.\n */\nvoid              DIRECT_API  direct_trace_print_stack  ( DirectTraceBuffer  *buffer );\n\n/*\n * Print stack of each known thread.\n */\nvoid              DIRECT_API  direct_trace_print_stacks ( void );\n\n/*\n * Returns indent level for debug output.\n */\nint               DIRECT_API  direct_trace_debug_indent ( void );\n\n/*\n * Retrieve pointer to calling function if present, otherwise NULL.\n */\nvoid              DIRECT_API *direct_trace_get_caller   ( void );\n\n/*\n * Create a copy of a stack in 'buffer' or of current if NULL.\n */\nDirectTraceBuffer DIRECT_API *direct_trace_copy_buffer  ( DirectTraceBuffer  *buffer );\n\n/*\n * Free a (copied) stack buffer.\n */\nvoid              DIRECT_API  direct_trace_free_buffer  ( DirectTraceBuffer  *buffer );\n\n/**********************************************************************************************************************/\n\n/*\n * Convenience function combining direct_trace_lookup_file() and direct_trace_lookup_symbol().\n */\nstatic __inline__ const char *\ndirect_trace_lookup_symbol_at( void *address )\n{\n     void       *base;\n     const char *filename;\n\n     filename = direct_trace_lookup_file( address, &base );\n\n     return direct_trace_lookup_symbol( filename, (unsigned long) address - (unsigned long) base );\n}\n\n#endif\n"
  },
  {
    "path": "lib/direct/types.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__TYPES_H__\n#define __DIRECT__TYPES_H__\n\n#ifndef __DIRECT__OS__TYPES_H__\n#include <direct/os/types.h>\n#endif\n\n/**********************************************************************************************************************/\n\n#define DIRECT_API\n\n#define D_RESULT_TYPE_CHAR_MASK  ((unsigned int) 0x2F)\n#define D_RESULT_TYPE_CHAR_MIN   ((unsigned int) 0x30)\n#define D_RESULT_TYPE_CHAR_MAX   (D_RESULT_TYPE_CHAR_MIN + D_RESULT_TYPE_CHAR_MASK)\n#define D_RESULT_TYPE_CHAR_MUL_0 ((unsigned int) 1)\n#define D_RESULT_TYPE_CHAR_MUL_1 ((unsigned int) (D_RESULT_TYPE_CHAR_MASK + 1))\n#define D_RESULT_TYPE_CHAR_MUL_2 (D_RESULT_TYPE_CHAR_MUL_1 * D_RESULT_TYPE_CHAR_MUL_1)\n#define D_RESULT_TYPE_CHAR_MUL_3 (D_RESULT_TYPE_CHAR_MUL_1 * D_RESULT_TYPE_CHAR_MUL_2)\n#define D_RESULT_TYPE_CHAR(C)    (((unsigned int) (C) - D_RESULT_TYPE_CHAR_MIN) & D_RESULT_TYPE_CHAR_MASK)\n#define D_RESULT_TYPE_SPACE      ((unsigned int) (0xFFFFFFFF / (D_RESULT_TYPE_CHAR_MASK * D_RESULT_TYPE_CHAR_MUL_3 + \\\n                                                                D_RESULT_TYPE_CHAR_MASK * D_RESULT_TYPE_CHAR_MUL_2 + \\\n                                                                D_RESULT_TYPE_CHAR_MASK * D_RESULT_TYPE_CHAR_MUL_1 + \\\n                                                                D_RESULT_TYPE_CHAR_MASK * D_RESULT_TYPE_CHAR_MUL_0)  \\\n                                                  - 1))\n\n/**********************************************************************************************************************/\n\n/*\n * Generate result code base for API\n *\n * Allowed are ASCII values between (inclusive) D_RESULT_TYPE_CHAR_MIN (0x30) and D_RESULT_TYPE_CHAR_MAX (0x5F)\n *\n *  0  1  2  3  4  5  6  7  8  9  :  ;  <  =  >  ?\n *\n *  @  A  B  C  D  E  F  G  H  I  J  K  L  M  N  O\n *\n *  P  Q  R  S  T  U  V  W  X  Y  Z  [  \\  ]  ^  _\n *\n */\n#define D_RESULT_TYPE_CODE_BASE(a,b,c,d) ((D_RESULT_TYPE_CHAR( a ) * (D_RESULT_TYPE_CHAR_MUL_3) +  \\\n                                           D_RESULT_TYPE_CHAR( b ) * (D_RESULT_TYPE_CHAR_MUL_2) +  \\\n                                           D_RESULT_TYPE_CHAR( c ) * (D_RESULT_TYPE_CHAR_MUL_1) +  \\\n                                           D_RESULT_TYPE_CHAR( d ) * (D_RESULT_TYPE_CHAR_MUL_0)) * D_RESULT_TYPE_SPACE)\n\n#define D_RESULT_TYPE(code)              ((code) - ((code) % D_RESULT_TYPE_SPACE))\n#define D_RESULT_INDEX(code)             ((code) % D_RESULT_TYPE_SPACE)\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     DR_OK,              /* No error occurred */\n\n     DR__RESULT_BASE = D_RESULT_TYPE_CODE_BASE( 'D','R','_', '1' ),\n\n     DR_FAILURE,         /* A general or unknown error occurred */\n     DR_INIT,            /* A general initialization error occurred */\n     DR_BUG,             /* Internal bug or inconsistency has been detected */\n     DR_DEAD,            /* Interface has a zero reference counter (available in debug mode) */\n     DR_UNSUPPORTED,     /* The requested operation or an argument is (currently) not supported */\n     DR_UNIMPLEMENTED,   /* The requested operation is not implemented, yet */\n     DR_ACCESSDENIED,    /* Access to the resource is denied */\n     DR_INVAREA,         /* An invalid area has been specified or detected */\n     DR_INVARG,          /* An invalid argument has been specified */\n     DR_NOLOCALMEMORY,   /* There's not enough local system memory */\n     DR_NOSHAREDMEMORY,  /* There's not enough shared system memory */\n     DR_LOCKED,          /* The resource is (already) locked */\n     DR_BUFFEREMPTY,     /* The buffer is empty */\n     DR_FILENOTFOUND,    /* The specified file has not been found */\n     DR_IO,              /* A general I/O error occurred */\n     DR_BUSY,            /* The resource or device is busy */\n     DR_NOIMPL,          /* No implementation for this interface or content type has been found */\n     DR_TIMEOUT,         /* The operation timed out */\n     DR_THIZNULL,        /* 'thiz' pointer is NULL */\n     DR_IDNOTFOUND,      /* No resource has been found by the specified id */\n     DR_DESTROYED,       /* The requested object has been destroyed */\n     DR_FUSION,          /* Internal fusion error detected, most likely related to IPC resources */\n     DR_BUFFERTOOLARGE,  /* Buffer is too large */\n     DR_INTERRUPTED,     /* The operation has been interrupted */\n     DR_NOCONTEXT,       /* No context available */\n     DR_TEMPUNAVAIL,     /* Temporarily unavailable */\n     DR_LIMITEXCEEDED,   /* Attempted to exceed limit, i.e. any kind of maximum size, count etc */\n     DR_NOSUCHMETHOD,    /* Requested method is not known */\n     DR_NOSUCHINSTANCE,  /* Requested instance is not known */\n     DR_ITEMNOTFOUND,    /* No such item found */\n     DR_VERSIONMISMATCH, /* Some versions didn't match */\n     DR_EOF,             /* Reached end of file */\n     DR_SUSPENDED,       /* The requested object is suspended */\n     DR_INCOMPLETE,      /* The operation has been executed, but not completely */\n     DR_NOCORE,          /* Core part not available */\n     DR_SIGNALLED,       /* Received a signal, e.g. while waiting */\n     DR_TASK_NOT_FOUND,  /* The corresponding task has not been found */\n\n     DR__RESULT_END\n} DirectResult;\n\ntypedef enum {\n     DENUM_OK     = 0,   /* Proceed with enumeration */\n     DENUM_CANCEL = 1,   /* Cancel enumeration */\n     DENUM_REMOVE = 2    /* Remove item */\n} DirectEnumerationResult;\n\n/**********************************************************************************************************************/\n\ntypedef struct __D_DirectCleanupHandler    DirectCleanupHandler;\ntypedef struct __D_DirectHash              DirectHash;\ntypedef struct __D_DirectLink              DirectLink;\ntypedef struct __D_DirectLog               DirectLog;\ntypedef struct __D_DirectMap               DirectMap;\ntypedef struct __D_DirectModuleDir         DirectModuleDir;\ntypedef struct __D_DirectModuleEntry       DirectModuleEntry;\ntypedef struct __D_DirectSignalHandler     DirectSignalHandler;\ntypedef struct __D_DirectStream            DirectStream;\ntypedef struct __D_DirectTraceBuffer       DirectTraceBuffer;\ntypedef struct __D_DirectThread            DirectThread;\ntypedef struct __D_DirectThreadInitHandler DirectThreadInitHandler;\n\n#endif\n"
  },
  {
    "path": "lib/direct/utf8.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__UTF8_H__\n#define __DIRECT__UTF8_H__\n\n#include <direct/types.h>\n\n/**********************************************************************************************************************/\n\n#define DIRECT_UTF8_SKIP(c)     (((u8) (c) < 0xc0) ? 1 : __direct_utf8_skip[(u8) (c) & 0x3f])\n\n#define DIRECT_UTF8_GET_CHAR(p) (*(const u8*) (p) < 0xc0 ? *(const u8*) (p) : __direct_utf8_get_char((const u8*) (p)))\n\n/*\n *  Actually the last two fields used to be zero since they indicate an invalid UTF-8 string.\n *  Changed it to 1 to avoid endless looping on invalid input.\n */\nstatic const char __direct_utf8_skip[64] = {\n     2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,\n     3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1\n};\n\nstatic __inline__ unichar\n__direct_utf8_get_char( const u8 *p )\n{\n     int     len;\n     unichar result = p[0];\n\n     if (result < 0xc0)\n          return result;\n\n     if (result > 0xfd)\n          return (unichar) -1;\n\n     len = __direct_utf8_skip[result & 0x3f];\n\n     result &= 0x7c >> len;\n\n     while (--len) {\n          int c = *(++p);\n\n          if ((c & 0xc0) != 0x80)\n               return (unichar) -1;\n\n          result = (result << 6) | (c & 0x3f);\n     }\n\n     return result;\n}\n\n#endif\n"
  },
  {
    "path": "lib/direct/util.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <config.h>\n#include <direct/debug.h>\n#include <direct/mem.h>\n#include <direct/util.h>\n\nD_DEBUG_DOMAIN( Direct_Util, \"Direct/Util\", \"Direct Util\" );\n\n/**********************************************************************************************************************/\n\nstatic const char *strings_base[150];\n\n#define STRINGS_ADD(index,string)                         \\\n     do {                                                 \\\n          D_ASSERT( index < D_ARRAY_SIZE(strings_base) ); \\\n          strings_base[index] = string;                   \\\n     } while (0)\n\n/**********************************************************************************************************************/\n\nvoid\n__D_util_init()\n{\n     STRINGS_ADD( EPERM,     \"Operation not permitted\" );\n     STRINGS_ADD( ENOENT,    \"No such file or directory\" );\n     STRINGS_ADD( ESRCH,     \"No such process\" );\n     STRINGS_ADD( EINTR,     \"Interrupted system call\" );\n     STRINGS_ADD( EIO,       \"I/O error\" );\n     STRINGS_ADD( ENXIO,     \"No such device or address\" );\n     STRINGS_ADD( E2BIG,     \"Argument list too long\" );\n     STRINGS_ADD( ENOEXEC,   \"Exec format error\" );\n     STRINGS_ADD( EBADF,     \"Bad file number\" );\n     STRINGS_ADD( ECHILD,    \"No child processes\" );\n     STRINGS_ADD( EAGAIN,    \"Try again\" );\n     STRINGS_ADD( ENOMEM,    \"Out of memory\" );\n     STRINGS_ADD( EACCES,    \"Permission denied\" );\n     STRINGS_ADD( EFAULT,    \"Bad address\" );\n     STRINGS_ADD( ENOTBLK,   \"Block device required\" );\n     STRINGS_ADD( EBUSY,     \"Device or resource busy\" );\n     STRINGS_ADD( EEXIST,    \"File exists\" );\n     STRINGS_ADD( EXDEV,     \"Cross-device link\" );\n     STRINGS_ADD( ENODEV,    \"No such device\" );\n     STRINGS_ADD( ENOTDIR,   \"Not a directory\" );\n     STRINGS_ADD( EISDIR,    \"Is a directory\" );\n     STRINGS_ADD( EINVAL,    \"Invalid argument\" );\n     STRINGS_ADD( ENFILE,    \"File table overflow\" );\n     STRINGS_ADD( EMFILE,    \"Too many open files\" );\n     STRINGS_ADD( ENOTTY,    \"Not a typewriter\" );\n     STRINGS_ADD( ETXTBSY,   \"Text file busy\" );\n     STRINGS_ADD( EFBIG,     \"File too large\" );\n     STRINGS_ADD( ENOSPC,    \"No space left on device\" );\n     STRINGS_ADD( ESPIPE,    \"Illegal seek\" );\n     STRINGS_ADD( EROFS,     \"Read-only file system\" );\n     STRINGS_ADD( EMLINK,    \"Too many links\" );\n     STRINGS_ADD( EPIPE,     \"Broken pipe\" );\n     STRINGS_ADD( EDOM,      \"Math argument out of domain of func\" );\n     STRINGS_ADD( ERANGE,    \"Math result not representable\" );\n     STRINGS_ADD( ETIMEDOUT, \"Timed out\" );\n}\n\nvoid\n__D_util_deinit()\n{\n}\n\n/**********************************************************************************************************************/\n\nconst char *\ndirect_strerror( int erno )\n{\n     if (erno < 0)\n          return \"negative errno\";\n\n     if (erno >= D_ARRAY_SIZE(strings_base))\n          return \"too high errno\";\n\n     return strings_base[erno];\n}\n\n__dfb_no_instrument_function__\nDirectResult\nerrno2result( int erno )\n{\n     switch (erno) {\n          case 0:\n               return DR_OK;\n          case ENOENT:\n               return DR_FILENOTFOUND;\n          case EACCES:\n          case EPERM:\n               return DR_ACCESSDENIED;\n          case EBUSY:\n          case EAGAIN:\n               return DR_BUSY;\n          case ETIMEDOUT:\n               return DR_TIMEOUT;\n          case ECONNREFUSED:\n               return DR_ACCESSDENIED;\n          case EINTR:\n               return DR_SIGNALLED;\n          case ENOSYS:\n               return DR_NOSUCHMETHOD;\n          case EINVAL:\n               return DR_INVARG;\n          case ENODEV:\n          case ENXIO:\n          case ENOTSUP:\n               return DR_UNSUPPORTED;\n     }\n\n     return DR_FAILURE;\n}\n\nvoid\ndirect_trim( char **s )\n{\n     int i;\n     int len = strlen( *s );\n\n     for (i = len - 1; i >= 0; i--)\n          if ((*s)[i] <= ' ')\n               (*s)[i] = 0;\n          else\n               break;\n\n     while (**s)\n          if (**s <= ' ')\n               (*s)++;\n          else\n               return;\n}\n\nstatic __inline__ char *\n__D_strtok_r( char        *s,\n              const char  *delim,\n              char       **save_ptr )\n{\n     char *token;\n     if (s == NULL)\n          s = *save_ptr;\n     /* Scan leading delimiters. */\n     s += strspn( s, delim );\n     if (*s == '\\0') {\n          *save_ptr = s;\n          return NULL;\n     }\n     /* Find the end of the token. */\n     token = s;\n     s = strpbrk( token, delim );\n     if (s == NULL) {\n          /* This token finishes the string. */\n          *save_ptr = strchr( token, '\\0' );\n     }\n     else {\n          /* Terminate the token and make *save_ptr point past it. */\n          *s = '\\0';\n          *save_ptr = s + 1;\n     }\n     return token;\n}\n\nstatic __inline__ char *\n__D_strtok_r_1c( char  *__s,\n                 char   __sep,\n                 char **__nextp )\n{\n     char *__result;\n     if (__s == NULL)\n          __s = *__nextp;\n     while (*__s == __sep)\n          ++__s;\n     __result = NULL;\n     if (*__s != '\\0') {\n          __result = __s++;\n          while (*__s != '\\0')\n               if (*__s++ == __sep) {\n                    __s[-1] = '\\0';\n                    break;\n               }\n          *__nextp = __s;\n     }\n     return __result;\n}\n\n#define __D_string2_1bptr_p(__x)                                                      \\\n     ((size_t)(const void*) ((__x) + 1) - (size_t)(const void*) (__x) == 1)\n\n#define __D_strtok_r(s,sep,nextp)                                                     \\\n     __builtin_constant_p( sep ) && __D_string2_1bptr_p( sep ) ?                      \\\n          (((__const char*) (sep))[0] != '\\0' && ((__const char*) (sep))[1] == '\\0' ? \\\n               __D_strtok_r_1c( s, ((__const char*) (sep))[0], nextp ) :              \\\n               __D_strtok_r( s, sep, nextp )) :                                       \\\n          __D_strtok_r( s, sep, nextp )\n\nchar *\ndirect_strtok_r( char        *str,\n                 const char  *delim,\n                 char       **saveptr )\n{\n     return __D_strtok_r( str, delim, saveptr );\n}\n\nchar *\ndirect_snputs( char       *dest,\n               const char *src,\n               size_t      n )\n{\n     char *start = dest;\n\n     D_ASSERT( dest != NULL );\n     D_ASSERT( src != NULL );\n\n     if (!n)\n          return NULL;\n\n     for (; n > 1 && *src; n--)\n          *dest++ = *src++;\n\n     *dest = 0;\n\n     return start;\n}\n\nchar *\ndirect_base64_encode( const void *data,\n                      int         size )\n{\n     static const char   *enc = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n                                \"abcdefghijklmnopqrstuvwxyz\"\n                                \"0123456789+/=\";\n     const unsigned char *src = (const unsigned char*) data;\n     char                *res;\n     char                *buf;\n\n     D_ASSERT( data != NULL );\n\n     buf = res = D_MALLOC( (size + 2) / 3 * 4 + 1 );\n     if (!res)\n          return NULL;\n\n     for (; size >= 3; size -= 3) {\n          buf[0] = enc[((src[0] & 0xfc) >> 2)];\n          buf[1] = enc[((src[0] & 0x03) << 4) | ((src[1] & 0xf0) >> 4)];\n          buf[2] = enc[((src[1] & 0x0f) << 2) | ((src[2] & 0xc0) >> 6)];\n          buf[3] = enc[((src[2] & 0x3f))];\n          buf += 4;\n          src += 3;\n     }\n\n     if (size > 0) {\n          buf[0] = enc[(src[0] & 0xfc) >> 2];\n\n          if (size > 1) {\n               buf[1] = enc[((src[0] & 0x03) << 4) | ((src[1] & 0xf0) >> 4)];\n               buf[2] = enc[((src[1] & 0x0f) << 2)];\n          }\n          else {\n               buf[1] = enc[(src[0] & 0x03) << 4];\n               buf[2] = '=';\n          }\n\n          buf[3] = '=';\n          buf += 4;\n     }\n\n     *buf = '\\0';\n\n     return res;\n}\n\nvoid *\ndirect_base64_decode( const char *string,\n                      int        *ret_size )\n{\n     unsigned char  dec[256];\n     unsigned char *res;\n     unsigned char *buf;\n     int            len;\n     int            i, j;\n\n     D_ASSERT( string != NULL );\n\n     len = strlen( string );\n     buf = res = D_MALLOC( len * 3 / 4 + 3 );\n     if (!res)\n          return NULL;\n\n     /* Generate decode table. */\n     for (i = 0; i < 255; i++)\n          dec[i] = 0x80;\n     for (i = 'A'; i <= 'Z'; i++)\n          dec[i] = 0  + (i - 'A');\n     for (i = 'a'; i <= 'z'; i++)\n          dec[i] = 26 + (i - 'a');\n     for (i = '0'; i <= '9'; i++)\n          dec[i] = 52 + (i - '0');\n     dec['+'] = 62;\n     dec['/'] = 63;\n     dec['='] = 0;\n\n     /* Decode. */\n     for (j = 0; j < len; j += 4) {\n          unsigned char a[4], b[4];\n\n          for (i = 0; i < 4; i++) {\n               int c = string[i+j];\n               a[i] = c;\n               b[i] = dec[c];\n          }\n\n          *buf++ = (b[0] << 2) | (b[1] >> 4);\n          *buf++ = (b[1] << 4) | (b[2] >> 2);\n          *buf++ = (b[2] << 6) | (b[3]     );\n          if (a[2] == '=' || a[3] == '=')\n               break;\n     }\n\n     *buf = '\\0';\n\n     if (ret_size)\n          *ret_size = buf - res;\n\n     return res;\n}\n\nstatic const u8 S[4][4] = {\n     { 7, 12, 17, 22}, /* Round 1 */\n     { 5,  9, 14, 20}, /* Round 2 */\n     { 4, 11, 16, 23}, /* Round 3 */\n     { 6, 10, 15, 21}  /* Round 4 */\n};\n\nstatic const u32 T[64] = {\n     0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, /* Round 1 */\n     0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,\n     0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,\n     0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,\n\n     0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, /* Round 2 */\n     0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,\n     0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,\n     0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,\n\n     0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, /* Round 3 */\n     0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,\n     0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,\n     0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,\n\n     0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, /* Round 4 */\n     0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,\n     0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,\n     0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,\n};\n\nstatic void\nmd5_hash( u32 ABCD[4],\n          u32 X[16] )\n{\n     u32 a = ABCD[3];\n     u32 b = ABCD[2];\n     u32 c = ABCD[1];\n     u32 d = ABCD[0];\n     int t;\n     int i;\n\n#ifdef WORDS_BIGENDIAN\n     for (i = 0; i < 16; i++)\n          X[i] = BSWAP32(X[i]);\n#endif\n\n     for (i = 0; i < 64; i++) {\n          t = S[i>>4][i&3];\n          a += T[i];\n          switch (i>>4) {\n               case 0: a += (d ^ (b&(c^d))) + X[(        i) & 15]; break;\n               case 1: a += (c ^ (d&(c^b))) + X[(1 + 5 * i) & 15]; break;\n               case 2: a += (b^c^d)         + X[(5 + 3 * i) & 15]; break;\n               case 3: a += (c ^ (b | ~d))  + X[(    7 * i) & 15]; break;\n          }\n          a = b + ((a << t) | (a >> (32 - t)));\n          t = d; d = c; c = b; b = a; a = t;\n     }\n\n     ABCD[0] += d;\n     ABCD[1] += c;\n     ABCD[2] += b;\n     ABCD[3] += a;\n}\n\nvoid\ndirect_md5_sum( void       *dst,\n                const void *src,\n                const int   len )\n{\n     u8  block[64];\n     u32 ABCD[4];\n     int i, j;\n\n     D_ASSERT( dst != NULL );\n     D_ASSERT( src != NULL );\n\n     ABCD[0] = 0x10325476;\n     ABCD[1] = 0x98badcfe;\n     ABCD[2] = 0xefcdab89;\n     ABCD[3] = 0x67452301;\n\n     for (i = 0, j = 0; i < len; i++) {\n          block[j++] = ((const u8*) src)[i];\n          if (j == 64) {\n               md5_hash( ABCD, (u32*) block );\n               j = 0;\n          }\n     }\n\n     block[j++] = 0x80;\n     memset( &block[j], 0, 64 - j );\n\n     if (j > 56) {\n          md5_hash( ABCD, (u32*) block );\n          memset( block, 0, 64 );\n     }\n\n     for (i = 0; i < 8; i++)\n          block[56+i] = (u8) (((u64) len << 3) >> (i << 3));\n\n     md5_hash( ABCD, (u32*) block );\n\n     for (i = 0; i < 4; i++)\n#ifdef WORDS_BIGENDIAN\n          ((u32*) dst)[i] = BSWAP32(ABCD[3-i]);\n#else\n          ((u32*) dst)[i] = ABCD[3-i];\n#endif\n}\n\nvoid *\ndirect_bsearch( const void *key,\n                const void *base,\n                size_t      nmemb,\n                size_t      size,\n                void       *func )\n{\n     return bsearch( key, base, nmemb, size, func );\n}\n"
  },
  {
    "path": "lib/direct/util.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__UTIL_H__\n#define __DIRECT__UTIL_H__\n\n#include <direct/clock.h>\n\n/**********************************************************************************************************************/\n\n#ifndef MIN\n#define MIN(a,b) ((a) < (b) ? (a) : (b))\n#endif\n#ifndef MAX\n#define MAX(a,b) ((a) > (b) ? (a) : (b))\n#endif\n\n#ifndef SIGN\n#define SIGN(x) (((x) < 0) ? -1 : (((x) > 0) ? 1 : 0))\n#endif\n\n#ifndef ABS\n#define ABS(x) ((x) > 0 ? (x) : -(x))\n#endif\n\n#ifndef CLAMP\n#define CLAMP(x,min,max) ((x) < (min) ? (min) : (x) > (max) ? (max) : (x))\n#endif\n\n#ifndef BSWAP16\n#define BSWAP16(x) (((u16) (x)>>8) | ((u16) (x)<<8))\n#endif\n\n#ifndef BSWAP32\n#define BSWAP32(x) ((((u32) (x)>>24) & 0x000000ff) | (((u32) (x)>> 8) & 0x0000ff00) | \\\n                    (((u32) (x)<< 8) & 0x00ff0000) | (((u32) (x)<<24) & 0xff000000))\n#endif\n\n#define D_FLAGS_SET(flags,f)     do { (flags) = (__typeof__(flags))((flags) |  (f)); } while (0)\n#define D_FLAGS_CLEAR(flags,f)   do { (flags) = (__typeof__(flags))((flags) & ~(f)); } while (0)\n#define D_FLAGS_IS_SET(flags,f)  (((flags) & (f)) != 0)\n#define D_FLAGS_ARE_SET(flags,f) (((flags) & (f)) == (f))\n#define D_FLAGS_ARE_IN(flags,f)  (((flags) & ~(f)) == 0)\n#define D_FLAGS_INVALID(flags,f) (((flags) & ~(f)) != 0)\n\n#define D_ARRAY_SIZE(array) ((int) (sizeof(array) / sizeof((array)[0])))\n\n#define D_UTIL_SWAP(a,b)                                                 \\\n     do {                                                                \\\n          const __typeof__(a) __swap_x = (a); (a) = (b); (b) = __swap_x; \\\n     } while (0)\n\n#define D_BITn32(f)  (((f) & 0x00000001) ?  0 : \\\n                      ((f) & 0x00000002) ?  1 : \\\n                      ((f) & 0x00000004) ?  2 : \\\n                      ((f) & 0x00000008) ?  3 : \\\n                      ((f) & 0x00000010) ?  4 : \\\n                      ((f) & 0x00000020) ?  5 : \\\n                      ((f) & 0x00000040) ?  6 : \\\n                      ((f) & 0x00000080) ?  7 : \\\n                      ((f) & 0x00000100) ?  8 : \\\n                      ((f) & 0x00000200) ?  9 : \\\n                      ((f) & 0x00000400) ? 10 : \\\n                      ((f) & 0x00000800) ? 11 : \\\n                      ((f) & 0x00001000) ? 12 : \\\n                      ((f) & 0x00002000) ? 13 : \\\n                      ((f) & 0x00004000) ? 14 : \\\n                      ((f) & 0x00008000) ? 15 : \\\n                      ((f) & 0x00010000) ? 16 : \\\n                      ((f) & 0x00020000) ? 17 : \\\n                      ((f) & 0x00040000) ? 18 : \\\n                      ((f) & 0x00080000) ? 19 : \\\n                      ((f) & 0x00100000) ? 20 : \\\n                      ((f) & 0x00200000) ? 21 : \\\n                      ((f) & 0x00400000) ? 22 : \\\n                      ((f) & 0x00800000) ? 23 : \\\n                      ((f) & 0x01000000) ? 24 : \\\n                      ((f) & 0x02000000) ? 25 : \\\n                      ((f) & 0x04000000) ? 26 : \\\n                      ((f) & 0x08000000) ? 27 : \\\n                      ((f) & 0x10000000) ? 28 : \\\n                      ((f) & 0x20000000) ? 29 : \\\n                      ((f) & 0x40000000) ? 30 : \\\n                      ((f) & 0x80000000) ? 31 : -1)\n\n#define D_UNUSED_P(x) (void) x\n\n/**********************************************************************************************************************/\n\n/*\n * Return a string describing errno.\n */\nconst char        DIRECT_API *direct_strerror     ( int          erno );\n\n/*\n * Translate errno to DirectResult.\n */\nDirectResult      DIRECT_API  errno2result        ( int          erno );\n\n/*\n * Remove whitespace from both sides of a string.\n */\nvoid              DIRECT_API  direct_trim         ( char       **s );\n\n/*\n * Extract tokens from a string.\n */\nchar              DIRECT_API *direct_strtok_r     ( char        *str,\n                                                    const char  *delim,\n                                                    char       **saveptr );\n\n/*\n * Set a string with a maximum size including the zero termination.\n * This acts like a strncpy( d, s, n ), but always terminates the string like direct_snprintf( d, n, \"%s\", s ).\n * Returns dest or NULL if n is zero.\n */\nchar              DIRECT_API *direct_snputs       ( char        *dest,\n                                                    const char  *src,\n                                                    size_t       n );\n\n/*\n * Encode Base-64 strings.\n */\nchar              DIRECT_API *direct_base64_encode( const void  *data,\n                                                    int          size );\n\n/*\n * Decode Base-64 strings.\n */\nvoid              DIRECT_API *direct_base64_decode( const char  *string,\n                                                    int         *ret_size );\n\n/*\n * Compute MD5 sum (store 16-bytes long result in 'dst').\n */\nvoid              DIRECT_API  direct_md5_sum      ( void        *dst,\n                                                    const void  *src,\n                                                    const int    len );\n\n/*\n * Search 'key' in 'base' and return a pointer to a matching element if found.\n */\nvoid              DIRECT_API *direct_bsearch      ( const void  *key,\n                                                    const void  *base,\n                                                    size_t       nmemb,\n                                                    size_t       size,\n                                                    void        *func );\n\n/**********************************************************************************************************************/\n\n/*\n * Slow implementation, but quite fast if only low bits are set.\n */\nstatic __inline__ int\ndirect_util_count_bits( unsigned int mask )\n{\n     int res = 0;\n\n     while (mask) {\n          res += mask & 1;\n          mask >>= 1;\n     }\n\n     return res;\n}\n\n/*\n * Generic alignment routine.\n */\nstatic __inline__ int\ndirect_util_align( int value,\n                   int alignment )\n{\n     if (alignment > 1) {\n          int tail = value % alignment;\n\n          if (tail)\n               value += alignment - tail;\n     }\n\n     return value;\n}\n\n/*\n * This floor operation is done by \"(iround(f + .5) + iround(f - .5)) >> 1\",\n * but uses some IEEE specific tricks for better speed.\n * 'f' must be between -4194304 and 4194303.\n */\nstatic __inline__ int\nD_IFLOOR( float f )\n{\n     int ai, bi;\n     double af, bf;\n\n     af = (3 << 22) + 0.5 + (double) f;\n     bf = (3 << 22) + 0.5 - (double) f;\n\n     union { int i; float f; } u;\n     u.f = (float) af; ai = u.i;\n     u.f = (float) bf; bi = u.i;\n\n     return (ai - bi) >> 1;\n}\n\n/*\n * This ceil operation is done by \"(iround(f + .5) + iround(f - .5) + 1) >> 1\",\n * but uses some IEEE specific tricks for better speed.\n * 'f' must be between -4194304 and 4194303.\n */\nstatic __inline__ int\nD_ICEIL( float f )\n{\n     int ai, bi;\n     double af, bf;\n\n     af = (3 << 22) + 0.5 + (double) f;\n     bf = (3 << 22) + 0.5 - (double) f;\n\n     union { int i; float f; } u;\n     u.f = (float) af; ai = u.i;\n     u.f = (float) bf; bi = u.i;\n\n     return (ai - bi + 1) >> 1;\n}\n\nstatic __inline__ int\ndirect_log2( int val )\n{\n     int res = 0;\n\n     while (val >> ++res);\n\n     if ((1 << --res) < val)\n          res++;\n\n     return res;\n}\n\ntypedef struct {\n     long long start;\n     long long stop;\n} DirectClock;\n\nstatic __inline__ void\ndirect_clock_start( DirectClock *clock )\n{\n     clock->start = direct_clock_get_micros();\n}\n\nstatic __inline__ void\ndirect_clock_stop( DirectClock *clock )\n{\n     clock->stop = direct_clock_get_micros();\n}\n\nstatic __inline__ long long\ndirect_clock_diff( DirectClock *clock )\n{\n     return clock->stop - clock->start;\n}\n\n#define DIRECT_CLOCK_DIFF_SEC_MS(clock) \\\n     (direct_clock_diff( clock ) / 1000000), (direct_clock_diff( clock ) / 1000 % 1000)\n\n/**********************************************************************************************************************/\n\nvoid __D_util_init  ( void );\nvoid __D_util_deinit( void );\n\n#endif\n"
  },
  {
    "path": "lib/direct/waitqueue.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECT__WAITQUEUE_H__\n#define __DIRECT__WAITQUEUE_H__\n\n#include <direct/os/waitqueue.h>\n\n/**********************************************************************************************************************/\n\n#endif\n"
  },
  {
    "path": "lib/fusion/arena.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <fusion/arena.h>\n#include <fusion/fusion_internal.h>\n#include <fusion/hash.h>\n#include <fusion/shmalloc.h>\n\nD_DEBUG_DOMAIN( Fusion_Arena, \"Fusion/Arena\", \"Fusion Arena\" );\n\n/**********************************************************************************************************************/\n\nstruct __Fusion_FusionArena {\n     DirectLink         link;\n\n     int                magic;\n\n     FusionWorldShared *shared;\n\n     FusionSkirmish     lock;\n     FusionRef          ref;\n\n     char              *name;\n\n     FusionHash        *field_hash;\n};\n\n/**********************************************************************************************************************/\n\nstatic FusionArena *lock_arena  ( FusionWorld *world, const char  *name, bool add );\n\nstatic void         unlock_arena( FusionArena *arena );\n\n/**********************************************************************************************************************/\n\nDirectResult\nfusion_arena_enter( FusionWorld     *world,\n                    const char      *name,\n                    ArenaEnterFunc   initialize,\n                    ArenaEnterFunc   join,\n                    void            *ctx,\n                    FusionArena    **ret_arena,\n                    int             *ret_error )\n{\n     FusionArena    *arena;\n     ArenaEnterFunc  func;\n     int             error = 0;\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n     D_ASSERT( name != NULL );\n     D_ASSERT( ret_arena != NULL );\n\n     D_DEBUG_AT( Fusion_Arena, \"%s( '%s' )\\n\", __FUNCTION__, name );\n\n     /* Lookup arena and lock it. If it doesn't exist create it. */\n     arena = lock_arena( world, name, true );\n     if (!arena)\n          return DR_FAILURE;\n\n     /* Check if we are the first. */\n     if (fusion_ref_zero_trylock( &arena->ref ) == DR_OK) {\n          D_DEBUG_AT( Fusion_Arena, \"  -> entering arena '%s' (establishing)\\n\", name );\n\n          /* Call 'initialize' later. */\n          func = initialize;\n\n          /* Unlock the reference counter. */\n          fusion_ref_unlock( &arena->ref );\n     }\n     else {\n          D_DEBUG_AT( Fusion_Arena, \"  -> entering arena '%s' (joining)\\n\", name );\n\n          /* Call 'join' later. */\n          func = join;\n     }\n\n     /* Increase reference counter. */\n     fusion_ref_up( &arena->ref, false );\n\n     /* Return the arena. */\n     *ret_arena = arena;\n\n     /* Call 'initialize' or 'join'. */\n     if (func)\n          error = func( arena, ctx );\n\n     /* Return the return value of the callback. */\n     if (ret_error)\n          *ret_error = error;\n\n     if (error) {\n          fusion_ref_down( &arena->ref, false );\n\n          if (func == initialize) {\n               /* Destroy fields. */\n               fusion_hash_destroy( arena->field_hash );\n\n               /* Destroy reference counter. */\n               fusion_ref_destroy( &arena->ref );\n\n               /* Destroy the arena lock. This has to happen before locking the list.\n                  Otherwise a dead lock with lock_arena() below could occur. */\n               fusion_skirmish_destroy( &arena->lock );\n\n               /* Lock the list and remove the arena. */\n               fusion_skirmish_prevail( &world->shared->arenas_lock );\n               direct_list_remove( &world->shared->arenas, &arena->link );\n               fusion_skirmish_dismiss( &world->shared->arenas_lock );\n\n               D_MAGIC_CLEAR( arena );\n\n               /* Free allocated memory. */\n               SHFREE( world->shared->main_pool, arena->name );\n               SHFREE( world->shared->main_pool, arena );\n\n               return DR_OK;\n          }\n     }\n\n     /* Unlock the arena. */\n     unlock_arena( arena );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_arena_add_shared_field( FusionArena *arena,\n                               const char  *name,\n                               void        *data )\n{\n     DirectResult  ret;\n     char         *shname;\n\n     D_MAGIC_ASSERT( arena, FusionArena );\n     D_MAGIC_ASSERT( arena->shared, FusionWorldShared );\n     D_ASSERT( data != NULL );\n     D_ASSERT( name != NULL );\n\n     D_DEBUG_AT( Fusion_Arena, \"%s( '%s', '%s' -> %p )\\n\", __FUNCTION__, arena->name, name, data );\n\n     /* Lock the arena. */\n     ret = fusion_skirmish_prevail( &arena->lock );\n     if (ret)\n          return ret;\n\n     /* Give it the requested name. */\n     shname = SHSTRDUP( arena->shared->main_pool, name );\n     if (shname)\n          ret = fusion_hash_replace( arena->field_hash, shname, data, NULL, NULL );\n     else\n          ret = D_OOSHM();\n\n     /* Unlock the arena. */\n     fusion_skirmish_dismiss( &arena->lock );\n\n     return ret;\n}\n\nDirectResult\nfusion_arena_get_shared_field( FusionArena  *arena,\n                               const char   *name,\n                               void        **data )\n{\n     void *ptr;\n\n     D_ASSERT( arena != NULL );\n     D_ASSERT( name != NULL );\n     D_ASSERT( data != NULL );\n\n     D_MAGIC_ASSERT( arena, FusionArena );\n\n     D_DEBUG_AT( Fusion_Arena, \"%s( '%s', '%s' )\\n\", __FUNCTION__, arena->name, name );\n\n     /* Lock the arena. */\n     if (fusion_skirmish_prevail( &arena->lock ))\n          return DR_FAILURE;\n\n     /* Lookup entry. */\n     ptr = fusion_hash_lookup( arena->field_hash, name );\n\n     D_DEBUG_AT( Fusion_Arena, \"  -> %p\\n\", ptr );\n\n     /* Unlock the arena. */\n     fusion_skirmish_dismiss( &arena->lock );\n\n     if (!ptr)\n          return DR_ITEMNOTFOUND;\n\n     *data = ptr;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_arena_exit( FusionArena   *arena,\n                   ArenaExitFunc  shutdown,\n                   ArenaExitFunc  leave,\n                   void          *ctx,\n                   bool           emergency,\n                   int           *ret_error )\n{\n     int error = 0;\n\n     D_MAGIC_ASSERT( arena, FusionArena );\n     D_MAGIC_ASSERT( arena->shared, FusionWorldShared );\n     D_ASSERT( shutdown != NULL );\n\n     D_DEBUG_AT( Fusion_Arena, \"%s( '%s' )\\n\", __FUNCTION__, arena->name );\n\n     /* Lock the arena. */\n     if (fusion_skirmish_prevail( &arena->lock ))\n          return DR_FAILURE;\n\n     /* Decrease reference counter. */\n     fusion_ref_down( &arena->ref, false );\n\n     /* If we are the last... */\n     if (fusion_ref_zero_trylock( &arena->ref ) == DR_OK) {\n          /* Deinitialize everything. */\n          error = shutdown( arena, ctx, emergency );\n\n          /* Destroy fields. */\n          fusion_hash_destroy( arena->field_hash );\n\n          /* Destroy reference counter. */\n          fusion_ref_destroy( &arena->ref );\n\n          /* Destroy the arena lock. This has to happen before locking the list.\n             Otherwise a dead lock with lock_arena() below could occur. */\n          fusion_skirmish_destroy( &arena->lock );\n\n          /* Lock the list and remove the arena. */\n          fusion_skirmish_prevail( &arena->shared->arenas_lock );\n          direct_list_remove( &arena->shared->arenas, &arena->link );\n          fusion_skirmish_dismiss( &arena->shared->arenas_lock );\n\n          D_MAGIC_CLEAR( arena );\n\n          /* Free allocated memory. */\n          SHFREE( arena->shared->main_pool, arena->name );\n          SHFREE( arena->shared->main_pool, arena );\n     }\n     else {\n          if (!leave) {\n               fusion_ref_up( &arena->ref, false );\n               fusion_skirmish_dismiss( &arena->lock );\n               return DR_BUSY;\n          }\n\n          /* Simply leave the arena. */\n          error = leave( arena, ctx, emergency );\n\n          /* Unlock the arena. */\n          fusion_skirmish_dismiss( &arena->lock );\n     }\n\n     /* Return the return value of the callback. */\n     if (ret_error)\n          *ret_error = error;\n\n     return DR_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic FusionArena *\ncreate_arena( FusionWorld *world,\n              const char  *name )\n{\n     DirectResult  ret;\n     char          buf[64];\n     FusionArena  *arena;\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n     D_ASSERT( name != NULL );\n\n     arena = SHCALLOC( world->shared->main_pool, 1, sizeof(FusionArena) );\n     if (!arena) {\n          D_OOSHM();\n          return NULL;\n     }\n\n     arena->shared = world->shared;\n\n     snprintf( buf, sizeof(buf), \"Arena '%s'\", name );\n\n     /* Initialize lock and reference counter. */\n     ret = fusion_skirmish_init( &arena->lock, buf, world );\n     if (ret)\n          goto error;\n\n     fusion_skirmish_add_permissions( &arena->lock, 0,\n                                      FUSION_SKIRMISH_PERMIT_PREVAIL | FUSION_SKIRMISH_PERMIT_DISMISS );\n\n     ret = fusion_ref_init( &arena->ref, buf, world );\n     if (ret)\n          goto error_ref;\n\n     fusion_ref_add_permissions( &arena->ref, 0,\n                                 FUSION_REF_PERMIT_REF_UNREF_LOCAL | FUSION_REF_PERMIT_ZERO_LOCK_UNLOCK );\n\n     /* Give it the requested name. */\n     arena->name = SHSTRDUP( world->shared->main_pool, name );\n     if (!arena->name) {\n          D_OOSHM();\n          goto error_prevail;\n     }\n\n     ret = fusion_hash_create( world->shared->main_pool, HASH_STRING, HASH_PTR, 7, &arena->field_hash );\n     if (ret)\n          goto error_hash;\n\n     fusion_hash_set_autofree( arena->field_hash, true, false );\n\n     /* Add it to the list. */\n     direct_list_prepend( &world->shared->arenas, &arena->link );\n\n     /* Lock the newly created arena. */\n     ret = fusion_skirmish_prevail( &arena->lock );\n     if (ret)\n          goto error_prevail;\n\n     D_MAGIC_SET( arena, FusionArena );\n\n     /* Returned locked new arena. */\n     return arena;\n\nerror_prevail:\n     fusion_hash_destroy( arena->field_hash );\n\nerror_hash:\n     if (arena->name)\n          SHFREE( world->shared->main_pool, arena->name );\n\n     fusion_ref_destroy( &arena->ref );\n\nerror_ref:\n     fusion_skirmish_destroy( &arena->lock );\n\nerror:\n     SHFREE( world->shared->main_pool, arena );\n\n     return NULL;\n}\n\nstatic FusionArena *\nlock_arena( FusionWorld *world,\n            const char  *name,\n            bool         add )\n{\n     FusionArena *arena;\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n     D_ASSERT( name != NULL );\n\n     /* Lock the list. */\n     if (fusion_skirmish_prevail( &world->shared->arenas_lock ))\n          return NULL;\n\n     /* For each existing arena... */\n     direct_list_foreach (arena, world->shared->arenas) {\n          /* Lock the arena. */\n          if (fusion_skirmish_prevail( &arena->lock ))\n               continue;\n\n          D_MAGIC_ASSERT( arena, FusionArena );\n\n          /* Check if the name matches. */\n          if (!strcmp( arena->name, name )) {\n               /* Check for an orphaned arena. */\n               if (fusion_ref_zero_trylock( &arena->ref ) == DR_OK) {\n                    D_ERROR( \"Fusion/Arena: Orphaned arena '%s'!\\n\", name );\n\n                    fusion_ref_unlock( &arena->ref );\n               }\n\n               /* Unlock the list. */\n               fusion_skirmish_dismiss( &world->shared->arenas_lock );\n\n               /* Return locked arena. */\n               return arena;\n          }\n\n          /* Unlock mismatched arena. */\n          fusion_skirmish_dismiss( &arena->lock );\n     }\n\n     /* If no arena name matched, create a new arena before unlocking the list again. */\n     arena = add ? create_arena( world, name ) : NULL;\n\n     /* Unlock the list. */\n     fusion_skirmish_dismiss( &world->shared->arenas_lock );\n\n     return arena;\n}\n\nstatic void\nunlock_arena( FusionArena *arena )\n{\n     D_MAGIC_ASSERT( arena, FusionArena );\n\n     /* Unlock the arena. */\n     fusion_skirmish_dismiss( &arena->lock );\n}\n"
  },
  {
    "path": "lib/fusion/arena.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FUSION__ARENA_H__\n#define __FUSION__ARENA_H__\n\n#include <fusion/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef int (*ArenaEnterFunc)( FusionArena *arena, void *ctx );\ntypedef int (*ArenaExitFunc) ( FusionArena *arena, void *ctx, bool emergency );\n\n/**********************************************************************************************************************/\n\nDirectResult FUSION_API fusion_arena_enter           ( FusionWorld     *world,\n                                                       const char      *name,\n                                                       ArenaEnterFunc   initialize,\n                                                       ArenaEnterFunc   join,\n                                                       void            *ctx,\n                                                       FusionArena    **ret_arena,\n                                                       int             *ret_error );\n\nDirectResult FUSION_API fusion_arena_add_shared_field( FusionArena     *arena,\n                                                       const char      *name,\n                                                       void            *data );\n\nDirectResult FUSION_API fusion_arena_get_shared_field( FusionArena     *arena,\n                                                       const char      *name,\n                                                       void           **data );\n\nDirectResult FUSION_API fusion_arena_exit            ( FusionArena     *arena,\n                                                       ArenaExitFunc    shutdown,\n                                                       ArenaExitFunc    leave,\n                                                       void            *ctx,\n                                                       bool             emergency,\n                                                       int             *ret_error );\n\n#endif\n"
  },
  {
    "path": "lib/fusion/call.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/thread.h>\n#include <fusion/call.h>\n#include <fusion/fusion_internal.h>\n\n#if FUSION_BUILD_MULTI\n\n#include <direct/memcpy.h>\n#include <fusion/conf.h>\n\n#if FUSION_BUILD_KERNEL\n#include <direct/mem.h>\n#if D_DEBUG_ENABLED\n#include <direct/trace.h>\n#endif\n#else /* FUSION_BUILD_KERNEL */\n#include <direct/filesystem.h>\n#include <fusion/hash.h>\n#include <fusion/shmalloc.h>\n#endif /* FUSION_BUILD_KERNEL */\n\n#endif /* FUSION_BUILD_MULTI */\n\nD_DEBUG_DOMAIN( Fusion_Call, \"Fusion/Call\", \"Fusion Call\" );\n\n/**********************************************************************************************************************/\n\n#if FUSION_BUILD_MULTI\n\n#if FUSION_BUILD_KERNEL\n\n#define FUSION_CALL_RETURN_DATA_MAX          32*1024*1024\n#define FUSION_CALL_RETURN_DATA_MAX_ON_STACK 1024\n\ntypedef struct {\n     int                 magic;\n\n     DirectThread       *thread;\n     bool                dispatcher;\n\n     FusionWorld        *world;\n\n     FusionCallExecute3 *bins;\n     int                 bins_num;\n     char               *bins_data;\n     int                 bins_data_len;\n     long long           bins_create_ts;\n} CallTLS;\n\nstatic DirectTLS call_tls_key;\n\n#else /* FUSION_BUILD_KERNEL */\n\ntypedef struct {\n     int       call_id;\n     FusionID  fusion_id;\n\n     void     *handler;\n     void     *handler3;\n     void     *ctx;\n} CallInfo;\n\n#endif /* FUSION_BUILD_KERNEL */\n\n#endif /* FUSION_BUILD_MULTI */\n\n/**********************************************************************************************************************/\n\n#if FUSION_BUILD_MULTI && FUSION_BUILD_KERNEL\n\nstatic void\ncall_tls_destroy( void *arg )\n{\n     CallTLS *call_tls = arg;\n\n     D_MAGIC_ASSERT( call_tls, CallTLS );\n\n     fusion_world_flush_calls( call_tls->world, 0 );\n\n     D_ASSUME( call_tls->bins_num == 0 );\n\n     D_MAGIC_CLEAR( call_tls );\n\n     D_FREE( call_tls );\n}\n\nvoid\n__Fusion_call_init()\n{\n     direct_tls_register( &call_tls_key, call_tls_destroy );\n}\n\nvoid\n__Fusion_call_deinit()\n{\n     direct_tls_unregister( &call_tls_key );\n}\n\n#else /* FUSION_BUILD_MULTI && FUSION_BUILD_KERNEL */\n\nvoid\n__Fusion_call_init()\n{\n}\n\nvoid\n__Fusion_call_deinit()\n{\n}\n\n#endif /* FUSION_BUILD_MULTI && FUSION_BUILD_KERNEL */\n\n/**********************************************************************************************************************/\n\n#if FUSION_BUILD_MULTI\n\n#if FUSION_BUILD_KERNEL\n\nstatic CallTLS *\nCall_GetTLS( FusionWorld *world )\n{\n     CallTLS *call_tls;\n\n     call_tls = direct_tls_get( &call_tls_key );\n     if (!call_tls) {\n          call_tls = D_CALLOC( 1, sizeof(CallTLS) + sizeof(FusionCallExecute3) * fusion_config->call_bin_max_num\n                                                  + fusion_config->call_bin_max_data );\n          if (!call_tls) {\n               D_OOM();\n               return NULL;\n          }\n\n          DirectThread *self = direct_thread_self();\n\n          if (self)\n               call_tls->dispatcher = fusion_dispatcher_tid( world ) == direct_thread_get_tid( self );\n\n          call_tls->thread    = self;\n          call_tls->world     = world;\n          call_tls->bins      = (FusionCallExecute3*) (call_tls + 1);\n          call_tls->bins_data = (char*) (call_tls->bins + fusion_config->call_bin_max_num);\n\n          D_MAGIC_SET( call_tls, CallTLS );\n\n          direct_tls_set( &call_tls_key, call_tls );\n     }\n\n     D_MAGIC_ASSERT( call_tls, CallTLS );\n\n     return call_tls;\n}\n\nDirectResult\nfusion_call_init( FusionCall        *call,\n                  FusionCallHandler  handler,\n                  void              *ctx,\n                  const FusionWorld *world )\n{\n     FusionCallNew call_new;\n\n     if (direct_log_domain_check( &Fusion_Call ))\n          D_DEBUG_AT( Fusion_Call, \"%s( %p, %p <%s>, %p, %p )\\n\", __FUNCTION__,\n                      call, handler, direct_trace_lookup_symbol_at( handler ), ctx, world );\n\n     D_ASSERT( call != NULL );\n     D_ASSERT( handler != NULL );\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     /* Called from others. */\n     call_new.handler = handler;\n     call_new.ctx     = ctx;\n\n     while (ioctl( world->fusion_fd, FUSION_CALL_NEW, &call_new )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n               default:\n                    break;\n          }\n\n          D_PERROR( \"Fusion/Call: FUSION_CALL_NEW\" );\n\n          return DR_FAILURE;\n     }\n\n     memset( call, 0, sizeof(FusionCall) );\n\n     /* Store handler, called directly when called by ourself. */\n     call->handler = handler;\n     call->ctx     = ctx;\n\n     /* Store call and own fusion id. */\n     call->call_id   = call_new.call_id;\n     call->fusion_id = fusion_id( world );\n\n     /* Keep back pointer to shared world data. */\n     call->shared = world->shared;\n\n     D_DEBUG_AT( Fusion_Call, \"  -> call id %d\\n\", call->call_id );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_init3( FusionCall         *call,\n                   FusionCallHandler3  handler3,\n                   void               *ctx,\n                   const FusionWorld  *world )\n{\n     FusionCallNew call_new;\n\n     if (direct_log_domain_check( &Fusion_Call ))\n          D_DEBUG_AT( Fusion_Call, \"%s( %p, %p <%s>, %p, %p )\\n\", __FUNCTION__,\n                      call, handler3, direct_trace_lookup_symbol_at( handler3 ), ctx, world );\n\n     D_ASSERT( call != NULL );\n     D_ASSERT( handler3 != NULL );\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     /* Called from others. */\n     call_new.handler = handler3;\n     call_new.ctx     = ctx;\n\n     while (ioctl( world->fusion_fd, FUSION_CALL_NEW, &call_new )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n               default:\n                    break;\n          }\n\n          D_PERROR( \"Fusion/Call: FUSION_CALL_NEW\" );\n\n          return DR_FAILURE;\n     }\n\n     memset( call, 0, sizeof(FusionCall) );\n\n     /* Store handler, called directly when called by ourself. */\n     call->handler3 = handler3;\n     call->ctx      = ctx;\n\n     /* Store call and own fusion id. */\n     call->call_id   = call_new.call_id;\n     call->fusion_id = fusion_id( world );\n\n     /* Keep back pointer to shared world data. */\n     call->shared = world->shared;\n\n     D_DEBUG_AT( Fusion_Call, \"  -> call id %d\\n\", call->call_id );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_init_from( FusionCall        *call,\n                       int                call_id,\n                       const FusionWorld *world )\n{\n     D_DEBUG_AT( Fusion_Call, \"%s( %p, %d, %p )\\n\", __FUNCTION__, call, call_id, world );\n\n     D_ASSERT( call != NULL );\n     D_ASSERT( call_id != 0 );\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     memset( call, 0, sizeof(FusionCall) );\n\n     /* Store call id. */\n     call->call_id = call_id;\n\n     /* Keep back pointer to shared world data. */\n     call->shared = world->shared;\n\n     D_DEBUG_AT( Fusion_Call, \"  -> call id %d\\n\", call->call_id );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_set_name( FusionCall *call,\n                      const char *name )\n{\n     FusionEntryInfo info;\n\n     D_ASSERT( call != NULL );\n     D_ASSERT( name != NULL );\n\n     info.type = FT_CALL;\n     info.id   = call->call_id;\n\n     direct_snputs( info.name, name, sizeof(info.name) );\n\n     while (ioctl( _fusion_fd( call->shared ), FUSION_ENTRY_SET_INFO, &info )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n               case EAGAIN:\n                    return DR_LOCKED;\n               case EINVAL:\n                    D_ERROR( \"Fusion/Call: Invalid call (id %d)!\\n\", call->call_id );\n                    return DR_DESTROYED;\n               default:\n                    break;\n          }\n\n          D_PERROR( \"Fusion/Call: FUSION_ENTRY_SET_INFO\" );\n\n          return DR_FAILURE;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_execute( FusionCall          *call,\n                     FusionCallExecFlags  flags,\n                     int                  call_arg,\n                     void                *call_ptr,\n                     int                 *ret_val )\n{\n     FusionWorld *world;\n     CallTLS     *call_tls;\n\n     D_DEBUG_AT( Fusion_Call, \"%s( %p, flags 0x%x, arg %d, ptr %p )\\n\", __FUNCTION__, call, flags, call_arg, call_ptr );\n\n     D_ASSERT( call != NULL );\n\n     if (!call->handler)\n          return DR_DESTROYED;\n\n     world = _fusion_world( call->shared );\n\n     if (call->fusion_id == _fusion_id( call->shared ) && direct_log_domain_check( &Fusion_Call ))\n          D_DEBUG_AT( Fusion_Call, \"  -> %s\\n\", direct_trace_lookup_symbol_at( call->handler ) );\n\n     call_tls = Call_GetTLS( world );\n\n     if (call->fusion_id == fusion_id( world ) && (!(flags & FCEF_NODIRECT) || (call_tls->dispatcher))) {\n          int                     res;\n          FusionCallHandlerResult result;\n\n          result = call->handler( call->fusion_id, call_arg, call_ptr, call->ctx, 0, &res );\n\n          if (result != FCHR_RETURN)\n               D_WARN( \"local call handler returned FCHR_RETAIN, need FCEF_NODIRECT\" );\n\n          if (ret_val)\n               *ret_val = res;\n     }\n     else {\n          FusionCallExecute execute;\n\n          execute.call_id  = call->call_id;\n          execute.call_arg = call_arg;\n          execute.call_ptr = call_ptr;\n          execute.flags    = flags | FCEF_RESUMABLE;\n          execute.serial   = 0;\n\n          fusion_world_flush_calls( world, 1 );\n\n          while (ioctl( world->fusion_fd, FUSION_CALL_EXECUTE, &execute )) {\n               switch (errno) {\n                    case EINTR:\n                         continue;\n                    case EINVAL:\n                         D_ERROR( \"Fusion/Call: Invalid call (id %d)!\\n\", call->call_id );\n                         return DR_INVARG;\n                    case EIDRM:\n                         D_ERROR( \"Fusion/Call: Call got destroyed (id %d)!\\n\", call->call_id );\n                         return DR_DESTROYED;\n                    default:\n                         break;\n               }\n\n               D_PERROR( \"Fusion/Call: FUSION_CALL_EXECUTE( id %d, creator %lu )\", call->call_id, call->fusion_id );\n\n               return DR_FAILURE;\n          }\n\n          if (ret_val)\n               *ret_val = execute.ret_val;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_execute2( FusionCall          *call,\n                      FusionCallExecFlags  flags,\n                      int                  call_arg,\n                      void                *ptr,\n                      unsigned int         length,\n                      int                 *ret_val )\n{\n     D_DEBUG_AT( Fusion_Call, \"%s( %p, flags 0x%x, arg %d, ptr %p, length %u )\\n\", __FUNCTION__,\n                 call, flags, call_arg, ptr, length );\n\n     D_ASSERT( call != NULL );\n\n     if (call->fusion_id == _fusion_id( call->shared ) && direct_log_domain_check( &Fusion_Call ))\n          D_DEBUG_AT( Fusion_Call, \"  -> %s\\n\", direct_trace_lookup_symbol_at( call->handler ) );\n\n     if (!(flags & FCEF_NODIRECT) && call->fusion_id == _fusion_id( call->shared )) {\n          int                     res;\n          FusionCallHandlerResult result;\n\n          result = call->handler( call->fusion_id, call_arg, ptr, call->ctx, 0, &res );\n\n          if (result != FCHR_RETURN)\n               D_WARN( \"local call handler returned FCHR_RETAIN, need FCEF_NODIRECT\" );\n\n          if (ret_val)\n               *ret_val = res;\n     }\n     else {\n          FusionCallExecute2 execute;\n\n          execute.call_id  = call->call_id;\n          execute.call_arg = call_arg;\n          execute.ptr      = ptr;\n          execute.length   = length;\n          execute.flags    = flags | FCEF_RESUMABLE;\n          execute.serial   = 0;\n\n          fusion_world_flush_calls( _fusion_world( call->shared ), 1 );\n\n          while (ioctl( _fusion_fd( call->shared ), FUSION_CALL_EXECUTE2, &execute )) {\n               switch (errno) {\n                    case EINTR:\n                         continue;\n                    case EINVAL:\n                         D_ERROR( \"Fusion/Call: Invalid call (id %d)!\\n\", call->call_id );\n                         return DR_INVARG;\n                    case EIDRM:\n                         D_ERROR( \"Fusion/Call: Call got destroyed (id %d)!\\n\", call->call_id );\n                         return DR_DESTROYED;\n                    default:\n                         break;\n               }\n\n               D_PERROR( \"Fusion/Call: FUSION_CALL_EXECUTE2( id %d, creator %lu )\", call->call_id, call->fusion_id );\n\n               return DR_FAILURE;\n          }\n\n          if (ret_val)\n               *ret_val = execute.ret_val;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_execute3( FusionCall          *call,\n                      FusionCallExecFlags  flags,\n                      int                  call_arg,\n                      void                *ptr,\n                      unsigned int         length,\n                      void                *ret_ptr,\n                      unsigned int         ret_size,\n                      unsigned int        *ret_length )\n{\n     FusionWorld *world;\n     CallTLS     *call_tls;\n\n     D_DEBUG_AT( Fusion_Call, \"%s( %p, flags 0x%x, arg %d, ptr %p, length %u, ret_ptr %p, ret_size %u )\\n\",\n                 __FUNCTION__, call, flags, call_arg, ptr, length, ret_ptr, ret_size );\n\n     if (ret_size > FUSION_CALL_RETURN_DATA_MAX)\n          return DR_LIMITEXCEEDED;\n\n     D_ASSERT( call != NULL );\n\n     world = _fusion_world( call->shared );\n\n     if (call->fusion_id == fusion_id( world ) && direct_log_domain_check( &Fusion_Call ))\n          D_DEBUG_AT( Fusion_Call, \"  -> handler is %s()\\n\", direct_trace_lookup_symbol_at( call->handler3 ) );\n\n     call_tls = Call_GetTLS( world );\n\n     if (call->fusion_id == fusion_id( world ) && (!(flags & FCEF_NODIRECT) || (call_tls->dispatcher))) {\n          FusionCallHandlerResult result;\n          unsigned int            execute_length;\n\n          result = call->handler3( call->fusion_id, call_arg, ptr, length, call->ctx, 0, ret_ptr, ret_size,\n                                   &execute_length );\n\n          if (result != FCHR_RETURN)\n               D_WARN( \"local call handler returned FCHR_RETAIN, need FCEF_NODIRECT\" );\n\n          if (ret_length)\n               *ret_length = execute_length;\n     }\n     else {\n          FusionCallExecute3  execute;\n          DirectResult        ret = DR_OK;\n\n          /* Check whether we can cache this call. */\n          if (flags & FCEF_QUEUE && fusion_config->call_bin_max_num > 0 && length < 10000) {\n               if (call_tls->bins_data_len + length > fusion_config->call_bin_max_data) {\n                    ret = fusion_world_flush_calls( world, 0 );\n                    if (ret)\n                         return ret;\n               }\n\n               call_tls->bins[call_tls->bins_num].call_id    = call->call_id;\n               call_tls->bins[call_tls->bins_num].call_arg   = call_arg;\n               call_tls->bins[call_tls->bins_num].ptr        = NULL;\n               call_tls->bins[call_tls->bins_num].length     = length;\n               call_tls->bins[call_tls->bins_num].ret_ptr    = ret_ptr;\n               call_tls->bins[call_tls->bins_num].ret_length = ret_size;\n               call_tls->bins[call_tls->bins_num].flags      = flags | FCEF_FOLLOW | FCEF_RESUMABLE;\n               call_tls->bins[call_tls->bins_num].serial     = 0;\n\n               D_DEBUG_AT( Fusion_Call, \"  -> buffered length %u, flags 0x%x\\n\",\n                           length, call_tls->bins[call_tls->bins_num].flags );\n\n               if (length > 0) {\n                    call_tls->bins[call_tls->bins_num].ptr = &call_tls->bins_data[call_tls->bins_data_len];\n                    direct_memcpy( &call_tls->bins_data[call_tls->bins_data_len], ptr, length );\n                    call_tls->bins_data_len += length;\n               }\n\n               call_tls->bins_num++;\n\n               if (call_tls->bins_num == 1) {\n                    call_tls->bins_create_ts = direct_clock_get_millis();\n               }\n               else if (call_tls->bins_num >= fusion_config->call_bin_max_num ||\n                        direct_clock_get_millis() - call_tls->bins_create_ts >= EXECUTE3_BIN_FLUSH_MILLIS) {\n                    ret = fusion_world_flush_calls( world, 0 );\n               }\n\n               return ret;\n          }\n\n          ret = fusion_world_flush_calls( world, 1 );\n\n          execute.call_id    = call->call_id;\n          execute.call_arg   = call_arg;\n          execute.ptr        = ptr;\n          execute.length     = length;\n          execute.ret_ptr    = ret_ptr;\n          execute.ret_length = ret_size;\n          execute.flags      = flags | FCEF_RESUMABLE;\n          execute.serial     = 0;\n\n          D_DEBUG_AT( Fusion_Call, \"  -> ptr %p, length %u, flags 0x%x\\n\", ptr, length, execute.flags );\n\n          while (ioctl( world->fusion_fd, FUSION_CALL_EXECUTE3, &execute )) {\n               switch (errno) {\n                    case EINTR:\n                         D_DEBUG_AT( Fusion_Call, \"  -> EINTR (flags 0x%x, serial %u)\\n\",\n                                     execute.flags, execute.serial );\n                         continue;\n                    case EINVAL:\n                         D_ERROR( \"Fusion/Call: Invalid call (id %d)!\\n\", call->call_id );\n                         return DR_INVARG;\n                    case EIDRM:\n                         D_ERROR( \"Fusion/Call: Call got destroyed (id %d)!\\n\", call->call_id );\n                         return DR_DESTROYED;\n                    default:\n                         D_DEBUG_AT( Fusion_Call, \"  -> OK (flags 0x%x)\\n\", execute.flags );\n                         break;\n               }\n\n               D_PERROR( \"Fusion/Call: FUSION_CALL_EXECUTE3( id %d, creator %lu )\", call->call_id, call->fusion_id );\n\n               return DR_FAILURE;\n          }\n\n          if (ret_length)\n               *ret_length = execute.ret_length;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_world_flush_calls( FusionWorld *world,\n                          int          lock )\n{\n     DirectResult  ret = DR_OK;\n     CallTLS      *call_tls;\n\n     call_tls = Call_GetTLS( world );\n\n     D_DEBUG_AT( Fusion_Call, \"%s( %p, lock %d )\\n\", __FUNCTION__, world, lock );\n\n     if (call_tls->bins_num > 0) {\n          D_DEBUG_AT( Fusion_Call, \"  -> num %d, length %d\\n\", call_tls->bins_num, call_tls->bins_data_len );\n\n          if (direct_log_domain_check( &Fusion_Call )) {\n               int i;\n\n               for (i = 0; i < call_tls->bins_num; i++) {\n                    D_DEBUG_AT( Fusion_Call, \"  -> [%2d] id %d, flags 0x%x, arg %d, length %u\\n\",\n                                i, call_tls->bins[i].call_id,\n                                call_tls->bins[i].flags, call_tls->bins[i].call_arg, call_tls->bins[i].length );\n               }\n          }\n\n          if (call_tls->dispatcher) {\n               D_DEBUG_AT( Fusion_Call, \"  -> dispatcher, not flushing\\n\" );\n               return DR_OK;\n          }\n\n          call_tls->bins[call_tls->bins_num-1].flags &= ~(FCEF_FOLLOW | FCEF_QUEUE);\n\n          while (ioctl( world->fusion_fd, FUSION_CALL_EXECUTE3, call_tls->bins )) {\n               switch (errno) {\n                    case EINTR:\n                         continue;\n                    case EINVAL:\n                         D_ERROR( \"Fusion/Call: Invalid call (id %d)!\\n\", call_tls->bins[0].call_id );\n                         ret = DR_INVARG;\n                         break;\n                    case EIDRM:\n                         D_ERROR( \"Fusion/Call: Call got destroyed (id %d)!\\n\", call_tls->bins[0].call_id );\n                         ret = DR_DESTROYED;\n                         break;\n                    default:\n                         break;\n               }\n\n               D_PERROR( \"Fusion/Call: FUSION_CALL_EXECUTE3( num %d, len %d )\",\n                         call_tls->bins_num, call_tls->bins_data_len );\n\n               ret = DR_FAILURE;\n               break;\n          }\n\n          call_tls->bins_num      = 0;\n          call_tls->bins_data_len = 0;\n     }\n\n     return ret;\n}\n\nDirectResult\nfusion_call_return( FusionCall   *call,\n                    unsigned int  serial,\n                    int           val )\n{\n     FusionCallReturn call_ret;\n\n     D_DEBUG_AT( Fusion_Call, \"%s( %p, %u, %d )\\n\", __FUNCTION__, call, serial, val );\n\n     D_ASSERT( call != NULL );\n\n     D_ASSUME( serial != 0 );\n\n     if (direct_log_domain_check( &Fusion_Call ))\n          D_DEBUG_AT( Fusion_Call, \"  -> %s\\n\", direct_trace_lookup_symbol_at( call->handler ) );\n\n     if (!serial)\n          return DR_UNSUPPORTED;\n\n     call_ret.call_id = call->call_id;\n     call_ret.val     = val;\n     call_ret.serial  = serial;\n\n     fusion_world_flush_calls( _fusion_world( call->shared ), 1 );\n\n     while (ioctl( _fusion_fd( call->shared ), FUSION_CALL_RETURN, &call_ret )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n               case EIDRM:\n                    D_WARN( \"caller withdrawn\" );\n                    return DR_NOCONTEXT;\n               case EINVAL:\n                    D_ERROR( \"Fusion/Call: Invalid call (id %d)!\\n\", call->call_id );\n                    return DR_DESTROYED;\n               default:\n                    break;\n          }\n\n          D_PERROR( \"Fusion/Call: FUSION_CALL_RETURN\" );\n\n          return DR_FAILURE;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_return3( FusionCall   *call,\n                     unsigned int  serial,\n                     void         *ptr,\n                     unsigned int  length )\n{\n     FusionCallReturn3 call_ret;\n\n     D_DEBUG_AT( Fusion_Call, \"%s( %p, serial %u, ptr %p, length %u )\\n\", __FUNCTION__, call, serial, ptr, length );\n\n     D_ASSERT( call != NULL );\n\n     D_ASSUME( serial != 0 );\n\n     if (direct_log_domain_check( &Fusion_Call ))\n          D_DEBUG_AT( Fusion_Call, \"  -> %s\\n\", direct_trace_lookup_symbol_at( call->handler ) );\n\n     if (!serial)\n          return DR_UNSUPPORTED;\n\n     call_ret.call_id = call->call_id;\n     call_ret.serial  = serial;\n     call_ret.ptr     = ptr;\n     call_ret.length  = length;\n\n     fusion_world_flush_calls( _fusion_world( call->shared ), 1 );\n\n     while (ioctl( _fusion_fd( call->shared ), FUSION_CALL_RETURN3, &call_ret )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n               case EIDRM:\n                    D_WARN( \"caller withdrawn\" );\n                    return DR_NOCONTEXT;\n               case EINVAL:\n                    D_ERROR( \"Fusion/Call: Invalid call (id %d)!\\n\", call->call_id );\n                    return DR_DESTROYED;\n               default:\n                    break;\n          }\n\n          D_PERROR( \"Fusion/Call: FUSION_CALL_RETURN3\" );\n\n          return DR_FAILURE;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_get_owner( FusionCall *call,\n                       FusionID   *ret_fusion_id )\n{\n     FusionCallGetOwner get_owner;\n\n     D_DEBUG_AT( Fusion_Call, \"%s( %p )\\n\", __FUNCTION__, call );\n\n     D_ASSERT( call != NULL );\n     D_ASSERT( ret_fusion_id != NULL );\n\n     get_owner.call_id = call->call_id;\n\n     while (ioctl( _fusion_fd( call->shared ), FUSION_CALL_GET_OWNER, &get_owner )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n               default:\n                    break;\n          }\n\n          D_PERROR( \"Fusion/Call: FUSION_CALL_GET_OWNER\" );\n\n          return DR_FAILURE;\n     }\n\n     *ret_fusion_id = get_owner.fusion_id;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_set_quota( FusionCall   *call,\n                       FusionID      fusion_id,\n                       unsigned int  limit )\n{\n     FusionCallSetQuota set_quota;\n\n     D_DEBUG_AT( Fusion_Call, \"%s( %p, fusion_id %lu, limit %u )\\n\", __FUNCTION__, call, fusion_id, limit );\n\n     D_ASSERT( call != NULL );\n\n     set_quota.call_id   = call->call_id;\n     set_quota.fusion_id = fusion_id;\n     set_quota.limit     = limit;\n\n     while (ioctl( _fusion_fd( call->shared ), FUSION_CALL_SET_QUOTA, &set_quota )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n               default:\n                    break;\n          }\n\n          D_PERROR( \"Fusion/Call: FUSION_CALL_SET_QUOTA\" );\n\n          return DR_FAILURE;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_destroy( FusionCall *call )\n{\n     D_DEBUG_AT( Fusion_Call, \"%s( %p )\\n\", __FUNCTION__, call );\n\n     D_ASSERT( call != NULL );\n     D_ASSERT( call->handler != NULL || call->handler3 != NULL );\n\n     D_DEBUG_AT( Fusion_Call, \"  -> call_id %d\\n\", call->call_id );\n\n     if (direct_log_domain_check( &Fusion_Call ))\n          D_DEBUG_AT( Fusion_Call, \"  -> %s\\n\", direct_trace_lookup_symbol_at( call->handler ?:\n                                                                               (FusionCallHandler) call->handler3 ) );\n\n     while (ioctl( _fusion_fd( call->shared ), FUSION_CALL_DESTROY, &call->call_id )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n               case EINVAL:\n                    return DR_DESTROYED;\n               default:\n                    break;\n          }\n\n          D_PERROR( \"Fusion/Call: FUSION_CALL_DESTROY\" );\n\n          return DR_FAILURE;\n     }\n\n     call->handler = NULL;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_add_permissions( FusionCall            *call,\n                             FusionID               fusion_id,\n                             FusionCallPermissions  call_permissions )\n{\n     FusionEntryPermissions permissions;\n\n     permissions.type        = FT_CALL;\n     permissions.id          = call->call_id;\n     permissions.fusion_id   = fusion_id;\n     permissions.permissions = 0;\n\n     if (call_permissions & FUSION_CALL_PERMIT_EXECUTE) {\n          FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_CALL_EXECUTE );\n          FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_CALL_EXECUTE2 );\n          FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_CALL_EXECUTE3 );\n     }\n\n     while (ioctl( _fusion_fd( call->shared ), FUSION_ENTRY_ADD_PERMISSIONS, &permissions ) < 0) {\n          if (errno != EINTR) {\n               D_PERROR( \"Fusion/Call: FUSION_ENTRY_ADD_PERMISSIONS( id %d )\\n\", call->call_id );\n               return DR_FAILURE;\n          }\n     }\n\n     return DR_OK;\n}\n\nvoid\n_fusion_call_process( FusionWorld       *world,\n                      int                call_id,\n                      FusionCallMessage *msg,\n                      void              *ptr )\n{\n     FusionCallHandlerResult result = FCHR_RETURN;\n     FusionCallHandler       call_handler;\n     FusionCallReturn        call_ret = { .val = 0 };\n\n     D_DEBUG_AT( Fusion_Call, \"%s( call_id %d, msg %p, ptr %p)\\n\", __FUNCTION__, call_id, msg, ptr );\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_ASSERT( msg != NULL );\n     D_ASSERT( msg->handler != NULL );\n\n     call_handler = msg->handler;\n\n     if (direct_log_domain_check( &Fusion_Call ))\n          D_DEBUG_AT( Fusion_Call, \"  -> %s\\n\", direct_trace_lookup_symbol_at( call_handler ) );\n\n     result = call_handler( msg->caller, msg->call_arg, ptr ?: msg->call_ptr, msg->ctx, msg->serial, &call_ret.val );\n\n     switch (result) {\n          case FCHR_RETURN:\n               if (msg->serial) {\n                    call_ret.serial  = msg->serial;\n                    call_ret.call_id = call_id;\n\n                    while (ioctl( world->fusion_fd, FUSION_CALL_RETURN, &call_ret )) {\n                         switch (errno) {\n                              case EINTR:\n                                   continue;\n                              case EIDRM:\n                                   D_WARN( \"caller withdrawn\" );\n                                   return;\n                              case EINVAL:\n                                   D_ERROR( \"Fusion/Call: Invalid call (id %d)!\\n\", call_id );\n                                   return;\n                              default:\n                                   D_PERROR( \"Fusion/Call: FUSION_CALL_RETURN\" );\n                                   return;\n                         }\n                    }\n               }\n               break;\n\n          case FCHR_RETAIN:\n               break;\n\n          default:\n               D_BUG( \"unknown result %u from call handler\", result );\n     }\n}\n\nvoid\n_fusion_call_process3( FusionWorld        *world,\n                       int                 call_id,\n                       FusionCallMessage3 *msg,\n                       void               *ptr )\n{\n     FusionCallHandlerResult  result = FCHR_RETURN;\n     FusionCallHandler3       call_handler;\n     FusionCallReturn3        call_ret;\n     char                    *ret_ptr    = NULL;\n     unsigned int             ret_length = 0;\n\n     D_DEBUG_AT( Fusion_Call, \"%s( call_id %d, msg %p, ptr %p)\\n\", __FUNCTION__, call_id, msg, ptr );\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_ASSERT( msg != NULL );\n     D_ASSERT( msg->handler != NULL );\n\n     call_handler = msg->handler;\n\n     if (direct_log_domain_check( &Fusion_Call ))\n          D_DEBUG_AT( Fusion_Call, \"  -> %s\\n\", direct_trace_lookup_symbol_at( call_handler ) );\n\n     if (msg->ret_length > FUSION_CALL_RETURN_DATA_MAX) {\n          D_ERROR( \"Fusion/Call: Maximum return data length (%d) exceeded (%u)!\\n\",\n                   FUSION_CALL_RETURN_DATA_MAX, msg->ret_length );\n     }\n     else {\n          if (msg->ret_length > FUSION_CALL_RETURN_DATA_MAX_ON_STACK) {\n               ret_ptr = D_MALLOC( msg->ret_length );\n               if (!ret_ptr)\n                    D_OOM();\n          }\n          else\n               ret_ptr = alloca( msg->ret_length );\n     }\n\n     if (ret_ptr)\n          result = call_handler( msg->caller, msg->call_arg, ptr ?: msg->call_ptr, msg->call_length, msg->ctx,\n                                 msg->serial, ret_ptr, msg->ret_length, &ret_length );\n\n     switch (result) {\n          case FCHR_RETURN:\n               if (msg->serial) {\n                    call_ret.call_id = call_id;\n                    call_ret.serial  = msg->serial;\n                    call_ret.ptr     = ret_ptr;\n                    call_ret.length  = ret_length;\n\n                    while (ioctl( world->fusion_fd, FUSION_CALL_RETURN3, &call_ret )) {\n                         switch (errno) {\n                              case EINTR:\n                                   continue;\n                              case EIDRM:\n                                   D_DEBUG_AT( Fusion_Call, \"  -> caller withdrawn\\n\" );\n                                   goto out;\n                              case EINVAL:\n                                   D_ERROR( \"Fusion/Call: Invalid call (id %d)!\\n\", call_id );\n                                   goto out;\n                              default:\n                                   D_PERROR( \"Fusion/Call: FUSION_CALL_RETURN3\" );\n                                   goto out;\n                         }\n                    }\n               }\n               break;\n\n          case FCHR_RETAIN:\n               break;\n\n          default:\n               D_BUG( \"unknown result %u from call handler\", result );\n     }\n\nout:\n     if (msg->ret_length > FUSION_CALL_RETURN_DATA_MAX_ON_STACK)\n          D_FREE( ret_ptr );\n}\n\n#else /* FUSION_BUILD_KERNEL */\n\nDirectResult\nfusion_call_init( FusionCall        *call,\n                  FusionCallHandler  handler,\n                  void              *ctx,\n                  const FusionWorld *world )\n{\n     D_ASSERT( call != NULL );\n     D_ASSERT( handler != NULL );\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     memset( call, 0, sizeof(FusionCall) );\n\n     call->call_id = ++world->shared->call_ids;\n\n     /* Store handler, called directly when called by ourself. */\n     call->handler = handler;\n     call->ctx     = ctx;\n\n     /* Store own fusion id. */\n     call->fusion_id = fusion_id( world );\n\n     /* Keep back pointer to shared world data. */\n     call->shared = world->shared;\n\n     CallInfo *info = SHCALLOC( world->shared->main_pool, 1, sizeof(CallInfo) );\n     if (!info)\n          return D_OOSHM();\n\n     info->call_id   = call->call_id;\n     info->fusion_id = call->fusion_id;\n     info->handler   = call->handler;\n     info->handler3  = call->handler3;\n     info->ctx       = call->ctx;\n\n     fusion_hash_insert( world->shared->call_hash, (void*)(long) call->call_id, info );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_init3( FusionCall         *call,\n                   FusionCallHandler3  handler3,\n                   void               *ctx,\n                   const FusionWorld  *world )\n{\n     D_ASSERT( call != NULL );\n     D_ASSERT( handler3 != NULL );\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     memset( call, 0, sizeof(FusionCall) );\n\n     call->call_id = ++world->shared->call_ids;\n\n     /* Store handler, called directly when called by ourself. */\n     call->handler3 = handler3;\n     call->ctx      = ctx;\n\n     /* Store own fusion id. */\n     call->fusion_id = fusion_id( world );\n\n     /* Keep back pointer to shared world data. */\n     call->shared = world->shared;\n\n     CallInfo *info = SHCALLOC( world->shared->main_pool, 1, sizeof(CallInfo) );\n     if (!info)\n          return D_OOSHM();\n\n     info->call_id   = call->call_id;\n     info->fusion_id = call->fusion_id;\n     info->handler   = call->handler;\n     info->handler3  = call->handler3;\n     info->ctx       = call->ctx;\n\n     fusion_hash_insert( world->shared->call_hash, (void*)(long) call->call_id, info );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_init_from( FusionCall        *call,\n                       int                call_id,\n                       const FusionWorld *world )\n{\n     D_DEBUG_AT( Fusion_Call, \"%s( %p, %d, %p )\\n\", __FUNCTION__, call, call_id, world );\n\n     D_ASSERT( call != NULL );\n     D_ASSERT( call_id != 0 );\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     CallInfo *info = fusion_hash_lookup( world->shared->call_hash, (void*)(long) call_id );\n\n     D_ASSERT( info != NULL );\n     D_ASSERT( info->call_id == call_id );\n\n     memset( call, 0, sizeof(FusionCall) );\n\n     /* Store call id. */\n     call->call_id = call_id;\n\n     /* Store handlers, called directly when called by ourself. */\n     call->handler  = info->handler;\n     call->handler3 = info->handler3;\n     call->ctx      = info->ctx;\n\n     /* Store own fusion id. */\n     call->fusion_id = info->fusion_id;\n\n     /* Keep back pointer to shared world data. */\n     call->shared = world->shared;\n\n     D_DEBUG_AT( Fusion_Call, \"  -> call id %d\\n\", call->call_id );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_set_name( FusionCall *call,\n                      const char *name )\n{\n     D_ASSERT( call != NULL );\n     D_ASSERT( name != NULL );\n\n     return DR_OK;\n}\n\nstatic DirectResult\nfusion_call_execute_internal( FusionCall          *call,\n                              FusionCallExecFlags  flags,\n                              int                  call_arg,\n                              void                *call_ptr,\n                              unsigned int         length,\n                              void                *ret_ptr,\n                              unsigned int         ret_size,\n                              unsigned int        *ret_length )\n{\n     DirectResult        ret = DR_OK;\n     FusionWorld        *world;\n     struct sockaddr_un  addr;\n     char                msg_buf[sizeof(FusionCallMessage) + length];\n     FusionCallMessage  *msg = (FusionCallMessage*) msg_buf;\n\n     D_ASSERT( call != NULL );\n\n     if (!call->handler && !call->handler3)\n          return DR_DESTROYED;\n\n     world = _fusion_world( call->shared );\n\n     if (call->fusion_id == fusion_id( world ) &&\n         (!(flags & FCEF_NODIRECT) || (call->handler3 && (direct_thread_self() == world->dispatch_loop)))) {\n          FusionCallHandlerResult result;\n\n          if (call->handler) {\n               D_ASSERT( length == sizeof(void*) );\n               result = call->handler( _fusion_id( call->shared ), call_arg, *(void**) call_ptr, call->ctx, 0, ret_ptr );\n          }\n          else {\n               D_ASSERT( call->handler3 != NULL );\n               result = call->handler3( _fusion_id( call->shared ), call_arg, call_ptr, length, call->ctx, 0, ret_ptr,\n                                        ret_size, ret_length );\n          }\n\n          if (result != FCHR_RETURN)\n               D_WARN( \"local call handler returned FCHR_RETAIN, need FCEF_NODIRECT\" );\n\n          return DR_OK;\n     }\n\n     msg->type        = FMT_CALL;\n     msg->caller      = world->fusion_id;\n     msg->call_id     = call->call_id;\n     msg->call_arg    = call_arg;\n     msg->call_length = length;\n     msg->ret_length  = ret_size;\n     msg->handler     = call->handler;\n     msg->handler3    = call->handler3;\n     msg->ctx         = call->ctx;\n     msg->flags       = flags;\n\n     direct_memcpy( msg + 1, call_ptr, length );\n\n     if (flags & FCEF_ONEWAY) {\n          /* Invalidate serial. */\n          msg->serial = -1;\n\n          /* Send message. */\n          addr.sun_family = AF_UNIX;\n          snprintf( addr.sun_path, sizeof(addr.sun_path), \"/tmp/.fusion-%d/%lx\",\n                    call->shared->world_index, call->fusion_id );\n\n          ret = _fusion_send_message( world->fusion_fd, msg, sizeof(FusionCallMessage) + length, &addr );\n     }\n     else {\n          int fd;\n          int err;\n          int len;\n\n          fd = socket( PF_LOCAL, SOCK_RAW, 0 );\n          if (fd < 0) {\n               D_PERROR( \"Fusion/Call: Error creating local socket!\\n\" ) ;\n               return DR_IO;\n          }\n\n          /* Set close-on-exec flag. */\n          fcntl( fd, F_SETFD, FD_CLOEXEC );\n\n          addr.sun_family = AF_UNIX;\n          len = snprintf( addr.sun_path, sizeof(addr.sun_path), \"/tmp/.fusion-%d/call.%x.\",\n                          fusion_world_index( world ), (unsigned int) call->call_id );\n\n          /* Generate call serial (socket address is based on it). */\n          for (msg->serial = 0; msg->serial <= 0xffffff; msg->serial++) {\n               snprintf( addr.sun_path + len, sizeof(addr.sun_path) - len, \"%x\", msg->serial );\n               err = bind( fd, (struct sockaddr*) &addr, sizeof(addr) );\n               if (err == 0) {\n                    direct_chmod( addr.sun_path, 0660 );\n                    /* Change group, if requested. */\n                    if (fusion_config->shmfile_gid != -1)\n                         direct_chown( addr.sun_path, -1, fusion_config->shmfile_gid );\n                    break;\n               }\n          }\n\n          if (err < 0) {\n               D_PERROR( \"Fusion/Call: Error binding local socket!\\n\" );\n               close( fd );\n               return DR_IO;\n          }\n\n          /* Send message. */\n          snprintf( addr.sun_path, sizeof(addr.sun_path), \"/tmp/.fusion-%d/%lx\",\n                    call->shared->world_index, call->fusion_id );\n\n          ret = _fusion_send_message( fd, msg, sizeof(FusionCallMessage) + length, &addr );\n          if (ret == DR_OK) {\n               char              buf[sizeof(FusionCallReturn) + ret_size];\n               FusionCallReturn *callret = (FusionCallReturn*) buf;\n\n               /* Wait for reply. */\n               ret = _fusion_recv_message( fd, buf, sizeof(FusionCallReturn) + ret_size, NULL );\n               if (ret == DR_OK) {\n                    D_ASSERT( callret->length <= ret_size );\n\n                    if (callret->length) {\n                         D_ASSERT( ret_ptr != NULL );\n\n                         direct_memcpy( ret_ptr, callret + 1, callret->length );\n                    }\n\n                    if (ret_length)\n                         *ret_length = callret->length;\n               }\n          }\n\n          socklen_t addrlen = sizeof(addr);\n          if (getsockname( fd, (struct sockaddr*) &addr, &addrlen ) == 0)\n               direct_unlink( addr.sun_path );\n\n          close( fd );\n     }\n\n     return ret;\n}\n\nDirectResult\nfusion_call_execute( FusionCall          *call,\n                     FusionCallExecFlags  flags,\n                     int                  call_arg,\n                     void                *call_ptr,\n                     int                 *ret_val )\n{\n     return fusion_call_execute_internal( call, flags, call_arg, &call_ptr, sizeof(call_ptr), ret_val, sizeof(*ret_val),\n                                          NULL );\n}\n\nDirectResult\nfusion_call_execute2( FusionCall          *call,\n                      FusionCallExecFlags  flags,\n                      int                  call_arg,\n                      void                *call_ptr,\n                      unsigned int         length,\n                      int                 *ret_val )\n{\n     return fusion_call_execute_internal( call, flags, call_arg, call_ptr, length, ret_val, 4, NULL );\n}\n\nDirectResult\nfusion_call_execute3( FusionCall          *call,\n                      FusionCallExecFlags  flags,\n                      int                  call_arg,\n                      void                *call_ptr,\n                      unsigned int         length,\n                      void                *ret_ptr,\n                      unsigned int         ret_size,\n                      unsigned int        *ret_length )\n{\n     return fusion_call_execute_internal( call, flags, call_arg, call_ptr, length, ret_ptr, ret_size, ret_length );\n}\n\nDirectResult\nfusion_world_flush_calls( FusionWorld *world,\n                          int          lock )\n{\n     return DR_OK;\n}\n\nstatic DirectResult\nfusion_call_return_internal( FusionCall   *call,\n                             unsigned int  serial,\n                             const void   *ptr,\n                             unsigned int  length )\n{\n     struct sockaddr_un  addr;\n     char                buf[sizeof(FusionCallReturn) + length];\n     FusionCallReturn   *callret = (FusionCallReturn*) buf;\n\n     D_ASSERT( call != NULL );\n\n     addr.sun_family = AF_UNIX;\n     snprintf( addr.sun_path, sizeof(addr.sun_path), \"/tmp/.fusion-%d/call.%x.%x\",\n               call->shared->world_index, (unsigned int) call->call_id, serial );\n\n     callret->type   = FMT_CALLRET;\n     callret->length = length;\n\n     if (length) {\n          D_ASSERT( ptr != NULL );\n\n          direct_memcpy( callret + 1, ptr, length );\n     }\n\n     return _fusion_send_message( _fusion_fd( call->shared ), callret, sizeof(FusionCallReturn) + length, &addr );\n}\n\nDirectResult\nfusion_call_return( FusionCall   *call,\n                    unsigned int  serial,\n                    int           val )\n{\n     return fusion_call_return_internal( call, serial, &val, sizeof(int) );\n}\n\nDirectResult\nfusion_call_return3( FusionCall   *call,\n                     unsigned int  serial,\n                     void         *ptr,\n                     unsigned int  length )\n{\n     return fusion_call_return_internal( call, serial, ptr, length );\n}\n\nDirectResult\nfusion_call_get_owner( FusionCall *call,\n                       FusionID   *ret_fusion_id )\n{\n     D_DEBUG_AT( Fusion_Call, \"%s( %p )\\n\", __FUNCTION__, call );\n\n     D_ASSERT( call != NULL );\n     D_ASSERT( ret_fusion_id != NULL );\n\n     *ret_fusion_id = call->fusion_id;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_set_quota( FusionCall   *call,\n                       FusionID      fusion_id,\n                       unsigned int  limit )\n{\n     D_DEBUG_AT( Fusion_Call, \"%s( %p, fusion_id %lu, limit %u )\\n\", __FUNCTION__, call, fusion_id, limit );\n\n     D_ASSERT( call != NULL );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_destroy( FusionCall *call )\n{\n     D_ASSERT( call != NULL );\n     D_ASSERT( call->handler != NULL || call->handler3 != NULL );\n\n     CallInfo *info = fusion_hash_lookup( call->shared->call_hash, (void*)(long) call->call_id );\n\n     D_ASSERT( info != NULL );\n     D_ASSERT( info->call_id == call->call_id );\n\n     fusion_hash_remove( call->shared->call_hash, (void*)(long) call->call_id, NULL, NULL );\n\n     SHFREE( call->shared->main_pool, info );\n\n     call->handler  = NULL;\n     call->handler3 = NULL;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_add_permissions( FusionCall            *call,\n                             FusionID               fusion_id,\n                             FusionCallPermissions  call_permissions )\n{\n     return DR_OK;\n}\n\nvoid\n_fusion_call_process( FusionWorld       *world,\n                      int                call_id,\n                      FusionCallMessage *msg,\n                      void              *ptr )\n{\n     FusionCallHandlerResult  result;\n     char                     buf[sizeof(FusionCallReturn) + msg->ret_length];\n     FusionCallReturn        *callret = (FusionCallReturn*) buf;\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_ASSERT( msg != NULL );\n\n     if (msg->handler) {\n          FusionCallHandler call_handler = msg->handler;\n\n          D_ASSERT( call_handler != NULL );\n\n          callret->type   = FMT_CALLRET;\n          callret->length = sizeof(int);\n\n          D_ASSERT( msg->call_length == sizeof(void*) );\n\n          result = call_handler( msg->caller, msg->call_arg, ptr, msg->ctx, msg->serial, (int*) (callret + 1) );\n          switch (result) {\n               case FCHR_RETURN:\n                    if (!(msg->flags & FCEF_ONEWAY)) {\n                         struct sockaddr_un addr;\n\n                         addr.sun_family = AF_UNIX;\n                         snprintf( addr.sun_path, sizeof(addr.sun_path), \"/tmp/.fusion-%d/call.%x.%x\",\n                                   fusion_world_index( world ), (unsigned int) call_id, msg->serial );\n\n                         if (_fusion_send_message( world->fusion_fd, callret,\n                                                   sizeof(FusionCallMessage) + callret->length, &addr ))\n                              D_ERROR( \"Fusion/Call: Could not send call return (serial %u)!\\n\", msg->serial );\n                    }\n                    break;\n\n               case FCHR_RETAIN:\n                    break;\n\n               default:\n                    D_BUG( \"unknown result %u from call handler\", result );\n                    break;\n          }\n     }\n     else {\n          FusionCallHandler3 call_handler3 = msg->handler3;\n\n          D_ASSERT( call_handler3 != NULL );\n\n          callret->type   = FMT_CALLRET;\n          callret->length = 0;\n\n          result = call_handler3( msg->caller, msg->call_arg, ptr, msg->call_length, msg->ctx, msg->serial, callret + 1,\n                                  msg->ret_length, &callret->length );\n          switch (result) {\n               case FCHR_RETURN:\n                    if (!(msg->flags & FCEF_ONEWAY)) {\n                         struct sockaddr_un addr;\n\n                         addr.sun_family = AF_UNIX;\n                         snprintf( addr.sun_path, sizeof(addr.sun_path), \"/tmp/.fusion-%d/call.%x.%x\",\n                                   fusion_world_index( world ), (unsigned int) call_id, msg->serial );\n\n                         if (_fusion_send_message( world->fusion_fd, callret,\n                                                   sizeof(FusionCallMessage) + callret->length, &addr ))\n                              D_ERROR( \"Fusion/Call: Could not send call return (serial %u)!\\n\", msg->serial );\n                    }\n                    break;\n\n               case FCHR_RETAIN:\n                    break;\n\n               default:\n                    D_BUG( \"unknown result %u from call handler\", result );\n                    break;\n          }\n     }\n}\n\n#endif /* FUSION_BUILD_KERNEL */\n\n#else /* FUSION_BUILD_MULTI */\n\nDirectResult\nfusion_call_init( FusionCall        *call,\n                  FusionCallHandler  handler,\n                  void              *ctx,\n                  const FusionWorld *world )\n{\n     D_ASSERT( call != NULL );\n     D_ASSERT( handler != NULL );\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     /* Called locally. */\n     call->handler = handler;\n     call->ctx     = ctx;\n\n     call->shared = world->shared;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_init3( FusionCall         *call,\n                   FusionCallHandler3  handler3,\n                   void               *ctx,\n                   const FusionWorld  *world )\n{\n     D_ASSERT( call != NULL );\n     D_ASSERT( handler3 != NULL );\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     /* Called locally. */\n     call->handler3 = handler3;\n     call->ctx      = ctx;\n\n     call->shared = world->shared;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_init_from( FusionCall        *call,\n                       int                call_id,\n                       const FusionWorld *world )\n{\n     D_DEBUG_AT( Fusion_Call, \"%s( %p, %d, %p )\\n\", __FUNCTION__, call, call_id, world );\n\n     D_ASSERT( call != NULL );\n     D_ASSERT( call_id != 0 );\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     memset( call, 0, sizeof(FusionCall) );\n\n     /* Store call id. */\n     call->call_id = call_id;\n\n     /* Keep back pointer to shared world data. */\n     call->shared = world->shared;\n\n     D_DEBUG_AT( Fusion_Call, \"  -> call id %d\\n\", call->call_id );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_set_name( FusionCall *call,\n                      const char *name )\n{\n     D_ASSERT( call != NULL );\n     D_ASSERT( name != NULL );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_execute( FusionCall          *call,\n                     FusionCallExecFlags  flags,\n                     int                  call_arg,\n                     void                *call_ptr,\n                     int                 *ret_val )\n{\n     DirectResult               ret;\n     FusionEventDispatcherCall  msg;\n     FusionEventDispatcherCall *ret_msg = &msg;\n\n     D_ASSERT( call != NULL );\n\n     if (!call->handler)\n          return DR_DESTROYED;\n\n     if (!(flags & FCEF_NODIRECT) || direct_thread_self() == call->shared->world->event_dispatcher_thread)\n          return call->handler( 1, call_arg, call_ptr, call->ctx, 0, ret_val );\n\n     msg.processed = 0;\n     msg.reaction = 0;\n     msg.call_handler = call->handler;\n     msg.call_handler3 = 0;\n     msg.call_ctx = call->ctx;\n     msg.flags = flags;\n     msg.call_arg = call_arg;\n     msg.ptr = call_ptr;\n     msg.length = 0;\n     msg.ret_val = 0;\n     msg.ret_ptr = 0;\n     msg.ret_size = 0;\n     msg.ret_length = 0;\n\n     ret = _fusion_event_dispatcher_process( call->shared->world, &msg, &ret_msg );\n\n     if (!(flags & FCEF_ONEWAY) && ret_val)\n          *ret_val = ret_msg->ret_val;\n\n     return ret;\n}\n\nDirectResult\nfusion_call_execute2( FusionCall          *call,\n                      FusionCallExecFlags  flags,\n                      int                  call_arg,\n                      void                *ptr,\n                      unsigned int         length,\n                      int                 *ret_val )\n{\n     DirectResult               ret;\n     FusionEventDispatcherCall  msg;\n     FusionEventDispatcherCall *ret_msg = &msg;\n\n     D_ASSERT( call != NULL );\n\n     if (!call->handler)\n          return DR_DESTROYED;\n\n     if (!(flags & FCEF_NODIRECT) || direct_thread_self() == call->shared->world->event_dispatcher_thread)\n          return call->handler( 1, call_arg, ptr, call->ctx, 0, ret_val );\n\n     msg.processed = 0;\n     msg.reaction = 0;\n     msg.call_handler = call->handler;\n     msg.call_handler3 = 0;\n     msg.call_ctx = call->ctx;\n     msg.flags = flags;\n     msg.call_arg = call_arg;\n     msg.ptr = ptr;\n     msg.length = length;\n     msg.ret_val = 0;\n     msg.ret_ptr = 0;\n     msg.ret_size = 0;\n     msg.ret_length = 0;\n\n     ret = _fusion_event_dispatcher_process( call->shared->world, &msg, &ret_msg );\n     if (!(flags & FCEF_ONEWAY) && ret_val)\n         *ret_val = ret_msg->ret_val;\n\n     return ret;\n}\n\nDirectResult\nfusion_call_execute3( FusionCall          *call,\n                      FusionCallExecFlags  flags,\n                      int                  call_arg,\n                      void                *ptr,\n                      unsigned int         length,\n                      void                *ret_ptr,\n                      unsigned int         ret_size,\n                      unsigned int        *ret_length )\n{\n     DirectResult               ret;\n     FusionEventDispatcherCall  msg;\n     FusionEventDispatcherCall *ret_msg = &msg;\n\n     D_ASSERT( call != NULL );\n\n     if (!call->handler3)\n          return DR_DESTROYED;\n\n     if (!(flags & FCEF_NODIRECT) || direct_thread_self() == call->shared->world->event_dispatcher_thread) {\n          unsigned int ret_len;\n\n          ret = call->handler3( 1, call_arg, ptr, length, call->ctx, 0, ret_ptr, ret_size, &ret_len );\n\n          if (ret_length)\n               *ret_length = ret_len;\n\n          return ret;\n     }\n\n     msg.processed = 0;\n     msg.reaction = 0;\n     msg.call_handler = 0;\n     msg.call_handler3 = call->handler3;\n     msg.call_ctx = call->ctx;\n     msg.flags = flags;\n     msg.call_arg = call_arg;\n     msg.ptr = ptr;\n     msg.length = length;\n     msg.ret_val = 0;\n     msg.ret_ptr = ret_ptr;\n     msg.ret_size = ret_size;\n     msg.ret_length = 0;\n\n     ret = _fusion_event_dispatcher_process( call->shared->world, &msg, &ret_msg );\n\n     if (!(flags & FCEF_ONEWAY) && ret_length)\n          *ret_length = ret_msg->ret_length;\n\n     return ret;\n}\n\nDirectResult\nfusion_world_flush_calls( FusionWorld *world,\n                          int          lock )\n{\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_return( FusionCall   *call,\n                    unsigned int  serial,\n                    int           val )\n{\n     return DR_UNIMPLEMENTED;\n}\n\nDirectResult\nfusion_call_return3( FusionCall   *call,\n                     unsigned int  serial,\n                     void         *ptr,\n                     unsigned int  length )\n{\n     return DR_UNIMPLEMENTED;\n}\n\nDirectResult\nfusion_call_get_owner( FusionCall *call,\n                       FusionID   *ret_fusion_id )\n{\n     *ret_fusion_id = FUSION_ID_MASTER;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_set_quota( FusionCall   *call,\n                       FusionID      fusion_id,\n                       unsigned int  limit )\n{\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_destroy( FusionCall *call )\n{\n     D_ASSERT( call != NULL );\n     D_ASSERT( call->handler != NULL || call->handler3 != NULL );\n\n     call->handler  = NULL;\n     call->handler3 = NULL;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_call_add_permissions( FusionCall            *call,\n                             FusionID               fusion_id,\n                             FusionCallPermissions  call_permissions )\n{\n     return DR_OK;\n}\n\n#endif /* FUSION_BUILD_MULTI */\n"
  },
  {
    "path": "lib/fusion/call.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FUSION__CALL_H__\n#define __FUSION__CALL_H__\n\n#include <fusion/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     FCHR_RETURN = 0x00000000,\n     FCHR_RETAIN = 0x00000001\n} FusionCallHandlerResult;\n\ntypedef FusionCallHandlerResult (*FusionCallHandler) ( int           caller,    /* Fusion id of the caller. */\n                                                       int           call_arg,  /* Optional call parameter. */\n                                                       void         *call_ptr,  /* Optional call parameter. */\n                                                       void         *ctx,       /* Optional handler context. */\n                                                       unsigned int  serial,\n                                                       int          *ret_val );\n\ntypedef FusionCallHandlerResult (*FusionCallHandler3)( int           caller,    /* Fusion id of the caller. */\n                                                       int           call_arg,  /* Optional call parameter. */\n                                                       void         *ptr,       /* Optional call parameter. */\n                                                       unsigned int  length,    /* Length. */\n                                                       void         *ctx,       /* Optional handler context. */\n                                                       unsigned int  serial,\n                                                       void         *ret_ptr,\n                                                       unsigned int  ret_size,\n                                                       unsigned int *ret_length );\n\nstruct __Fusion_FusionCall {\n     FusionWorldShared  *shared;\n     int                 call_id;\n     FusionID            fusion_id;\n     FusionCallHandler   handler;\n     FusionCallHandler3  handler3;\n     void               *ctx;\n};\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     FUSION_CALL_PERMIT_NONE    = 0x00000000,\n\n     FUSION_CALL_PERMIT_EXECUTE = 0x00000001,\n\n     FUSION_CALL_PERMIT_ALL     = 0x00000001\n} FusionCallPermissions;\n\n/**********************************************************************************************************************/\n\nDirectResult FUSION_API fusion_call_init           ( FusionCall            *call,\n                                                     FusionCallHandler      handler,\n                                                     void                  *ctx,\n                                                     const FusionWorld     *world );\n\nDirectResult FUSION_API fusion_call_init3          ( FusionCall            *call,\n                                                     FusionCallHandler3     handler3,\n                                                     void                  *ctx,\n                                                     const FusionWorld     *world );\n\nDirectResult FUSION_API fusion_call_init_from      ( FusionCall            *call,\n                                                     int                    call_id,\n                                                     const FusionWorld     *world );\n\nDirectResult FUSION_API fusion_call_set_name       ( FusionCall            *call,\n                                                     const char            *name );\n\nDirectResult FUSION_API fusion_call_execute        ( FusionCall            *call,\n                                                     FusionCallExecFlags    flags,\n                                                     int                    call_arg,\n                                                     void                  *call_ptr,\n                                                     int                   *ret_val );\n\nDirectResult FUSION_API fusion_call_execute2       ( FusionCall            *call,\n                                                     FusionCallExecFlags    flags,\n                                                     int                    call_arg,\n                                                     void                  *ptr,\n                                                     unsigned int           length,\n                                                     int                   *ret_val );\n\nDirectResult FUSION_API fusion_call_execute3       ( FusionCall            *call,\n                                                     FusionCallExecFlags    flags,\n                                                     int                    call_arg,\n                                                     void                  *ptr,\n                                                     unsigned int           length,\n                                                     void                  *ret_ptr,\n                                                     unsigned int           ret_size,\n                                                     unsigned int          *ret_length );\n\nDirectResult FUSION_API fusion_world_flush_calls   ( FusionWorld           *world,\n                                                     int                    lock );\n\nDirectResult FUSION_API fusion_call_return         ( FusionCall            *call,\n                                                     unsigned int           serial,\n                                                     int                    val );\n\nDirectResult FUSION_API fusion_call_return3        ( FusionCall            *call,\n                                                     unsigned int           serial,\n                                                     void                  *ptr,\n                                                     unsigned int           length );\n\nDirectResult FUSION_API fusion_call_get_owner      ( FusionCall            *call,\n                                                     FusionID              *ret_fusion_id );\n\nDirectResult FUSION_API fusion_call_set_quota      ( FusionCall            *call,\n                                                     FusionID               fusion_id,\n                                                     unsigned int           limit );\n\nDirectResult FUSION_API fusion_call_destroy        ( FusionCall            *call );\n\n/*\n * Give permissions to another fusionee to use the call.\n */\nDirectResult FUSION_API fusion_call_add_permissions( FusionCall            *call,\n                                                     FusionID               fusion_id,\n                                                     FusionCallPermissions  permissions );\n\n/**********************************************************************************************************************/\n\nvoid __Fusion_call_init  ( void );\nvoid __Fusion_call_deinit( void );\n\n#endif\n"
  },
  {
    "path": "lib/fusion/conf.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/debug.h>\n#include <direct/mem.h>\n#include <fusion/conf.h>\n\nD_DEBUG_DOMAIN( Fusion_Config, \"Fusion/Config\", \"Fusion Runtime Configuration options\" );\n\n/**********************************************************************************************************************/\n\nstatic FusionConfig conf = { 0 };\n\nFusionConfig *fusion_config = &conf;\nconst char   *fusion_config_usage =\n     \"libfusion options:\\n\"\n     \"  tmpfs=<directory>              Location of the shared memory file in multi application mode (default = auto)\\n\"\n     \"  shmfile-group=<groupname>      Group that owns shared memory files\\n\"\n     \"  [no-]force-slave               Always enter as a slave, waiting for the master, if not there\\n\"\n     \"  [no-]fork-handler              Register fork handlers\\n\"\n     \"  [no-]debugshm                  Enable shared memory allocation tracking\\n\"\n     \"  [no-]madv-remove               Enable usage of MADV_REMOVE (default = auto)\\n\"\n     \"  [no-]secure-fusion             Use secure fusion, e.g. read-only shm (default enabled)\\n\"\n     \"  [no-]defer-destructors         Handle destructor calls in separate thread\\n\"\n     \"  trace-ref=<hexid>              Trace FusionRef up/down ('all' traces all)\\n\"\n     \"  call-bin-max-num=<n>           Set maximum call number for async call buffer (default = 512, 0 = disable)\\n\"\n     \"  call-bin-max-data=<n>          Set maximum call data size for async call buffer (default = 65536)\\n\"\n     \"  [no-]shutdown-info             Dump objects from all pools if some objects remain alive\\n\"\n     \"\\n\";\n\n/**********************************************************************************************************************/\n\nvoid\n__Fusion_conf_init()\n{\n     fusion_config->shmfile_gid       = -1;\n     fusion_config->secure_fusion     = true;\n     fusion_config->call_bin_max_num  = 512;\n     fusion_config->call_bin_max_data = 65536;\n}\n\nvoid\n__Fusion_conf_deinit()\n{\n}\n\n/**********************************************************************************************************************/\n\nDirectResult\nfusion_config_set( const char *name,\n                   const char *value )\n{\n     if (strcmp( name, \"tmpfs\" ) == 0) {\n          if (value) {\n               if (fusion_config->tmpfs)\n                    D_FREE( fusion_config->tmpfs );\n               fusion_config->tmpfs = D_STRDUP( value );\n          }\n          else {\n               D_ERROR( \"Fusion/Config: '%s': No directory name specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"shmfile-group\" ) == 0) {\n          if (value) {\n               struct group *group_info;\n\n               group_info = getgrnam( value );\n               if (group_info)\n                    fusion_config->shmfile_gid = group_info->gr_gid;\n               else\n                    D_PERROR( \"Fusion/Config: 'shmfile-group': Group '%s' not found!\\n\", value );\n          }\n          else {\n               D_ERROR( \"Fusion/Config: '%s': No file group name specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"force-slave\" ) == 0) {\n          fusion_config->force_slave = true;\n     } else\n     if (strcmp( name, \"no-force-slave\" ) == 0) {\n          fusion_config->force_slave = false;\n     } else\n     if (strcmp( name, \"fork-handler\" ) == 0) {\n          fusion_config->fork_handler = true;\n     } else\n     if (strcmp( name, \"no-fork-handler\" ) == 0) {\n          fusion_config->fork_handler = false;\n     } else\n     if (strcmp( name, \"debugshm\" ) == 0) {\n          fusion_config->debugshm = true;\n     } else\n     if (strcmp( name, \"no-debugshm\" ) == 0) {\n          fusion_config->debugshm = false;\n     } else\n     if (strcmp( name, \"madv-remove\" ) == 0) {\n          fusion_config->madv_remove       = true;\n          fusion_config->madv_remove_force = true;\n     } else\n     if (strcmp( name, \"no-madv-remove\" ) == 0) {\n          fusion_config->madv_remove       = false;\n          fusion_config->madv_remove_force = true;\n     } else\n     if (strcmp( name, \"secure-fusion\" ) == 0) {\n          fusion_config->secure_fusion = true;\n     } else\n     if (strcmp( name, \"no-secure-fusion\" ) == 0) {\n          fusion_config->secure_fusion = false;\n     } else\n     if (strcmp( name, \"defer-destructors\" ) == 0) {\n          fusion_config->defer_destructors = true;\n     } else\n     if (strcmp( name, \"no-defer-destructors\" ) == 0) {\n          fusion_config->defer_destructors = false;\n     } else\n     if (strcmp( name, \"trace-ref\" ) == 0) {\n          if (value) {\n               if (!strcmp( value, \"all\" )) {\n                    fusion_config->trace_ref = -1;\n               }\n               else if (sscanf( value, \"%x\", (unsigned int *) &fusion_config->trace_ref ) != 1) {\n                    D_ERROR( \"Fusion/Config: '%s': Invalid value!\\n\", name );\n                    return DR_INVARG;\n               }\n          }\n          else {\n               D_ERROR( \"Fusion/Config: '%s': No ID specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"call-bin-max-num\" ) == 0) {\n          if (value) {\n               unsigned int max;\n\n               if (sscanf( value, \"%u\", &max ) < 1) {\n                    D_ERROR( \"Fusion/Config: '%s': Could not parse value!\\n\", name );\n                    return DR_INVARG;\n               }\n\n               if (max < 1) {\n                    D_ERROR( \"Fusion/Config: '%s': Error in value '%s' (min 1)!\\n\", name, value );\n                    return DR_INVARG;\n               }\n\n               if (max > 16384) {\n                    D_ERROR( \"Fusion/Config: '%s': Error in value '%s' (max 16384)!\\n\", name, value );\n                    return DR_INVARG;\n               }\n\n               fusion_config->call_bin_max_num = max;\n          }\n          else {\n               D_ERROR( \"Fusion/Config: '%s': No value specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"call-bin-max-data\" ) == 0) {\n          if (value) {\n               unsigned int max;\n\n               if (sscanf( value, \"%u\", &max ) < 1) {\n                    D_ERROR( \"Fusion/Config: '%s': Could not parse value!\\n\", name );\n                    return DR_INVARG;\n               }\n\n               if (max < 4096) {\n                    D_ERROR( \"Fusion/Config: '%s': Error in value '%s' (min 4096)!\\n\", name, value );\n                    return DR_INVARG;\n               }\n\n               if (max > 16777216) {\n                    D_ERROR( \"Fusion/Config: '%s': Error in value '%s' (max 16777216)!\\n\", name, value );\n                    return DR_INVARG;\n               }\n\n               fusion_config->call_bin_max_data = max;\n          }\n          else {\n               D_ERROR( \"Fusion/Config: '%s': No value specified!\\n\", name );\n               return DR_INVARG;\n          }\n     } else\n     if (strcmp( name, \"shutdown-info\" ) == 0) {\n          fusion_config->shutdown_info = true;\n     } else\n     if (strcmp( name, \"no-shutdown-info\" ) == 0) {\n          fusion_config->shutdown_info = false;\n     }\n     else\n          return DR_INVARG;\n\n     D_DEBUG_AT( Fusion_Config, \"Set %s '%s'\\n\", name, value ?: \"\" );\n\n     return DR_OK;\n}\n"
  },
  {
    "path": "lib/fusion/conf.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FUSION__CONF_H__\n#define __FUSION__CONF_H__\n\n#include <fusion/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     char         *tmpfs;\n     gid_t         shmfile_gid;\n     bool          force_slave;\n     bool          fork_handler;\n     bool          debugshm;\n     bool          madv_remove;\n     bool          madv_remove_force;\n     bool          secure_fusion;\n     bool          defer_destructors;\n     int           trace_ref;\n     unsigned int  call_bin_max_num;\n     unsigned int  call_bin_max_data;\n     bool          shutdown_info;\n} FusionConfig;\n\n/**********************************************************************************************************************/\n\nextern FusionConfig FUSION_API *fusion_config;\n\nextern const char   FUSION_API *fusion_config_usage;\n\n/*\n * Set indiviual option.\n */\nDirectResult        FUSION_API  fusion_config_set( const char *name,\n                                                   const char *value );\n\n/**********************************************************************************************************************/\n\nvoid __Fusion_conf_init  ( void );\nvoid __Fusion_conf_deinit( void );\n\n#endif\n"
  },
  {
    "path": "lib/fusion/fusion.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/direct.h>\n#include <direct/mem.h>\n#include <direct/thread.h>\n#include <fusion/conf.h>\n#include <fusion/fusion_internal.h>\n#include <fusion/shm/pool.h>\n\n#if FUSION_BUILD_MULTI\n\n#include <direct/filesystem.h>\n#include <direct/map.h>\n#include <direct/system.h>\n#if D_DEBUG_ENABLED\n#include <direct/trace.h>\n#endif\n#include <fusion/shmalloc.h>\n#include <fusion/shm/shm.h>\n\n#if FUSION_BUILD_KERNEL\n#include <direct/memcpy.h>\n#else /* FUSION_BUILD_KERNEL */\n#include <fusion/hash.h>\n#endif /* FUSION_BUILD_KERNEL */\n\n#else /* FUSION_BUILD_MULTI */\n\n#include <direct/memcpy.h>\n#include <fusion/reactor.h>\n\n#endif /* FUSION_BUILD_MULTI */\n\nD_DEBUG_DOMAIN( Fusion_Main,          \"Fusion/Main\",          \"Fusion High level IPC\" );\nD_DEBUG_DOMAIN( Fusion_Main_Dispatch, \"Fusion/Main/Dispatch\", \"Fusion High level IPC Dispatch\" );\n\n/**********************************************************************************************************************/\n\n#if FUSION_BUILD_MULTI\n\nstatic FusionWorld *fusion_worlds[FUSION_MAX_WORLDS];\nstatic DirectMutex  fusion_worlds_lock = DIRECT_MUTEX_INITIALIZER();\n\nint\n_fusion_fd( const FusionWorldShared *shared )\n{\n     int          index;\n     FusionWorld *world;\n\n     D_MAGIC_ASSERT( shared, FusionWorldShared );\n\n     index = shared->world_index;\n\n     D_ASSERT( index >= 0 );\n     D_ASSERT( index < FUSION_MAX_WORLDS );\n\n     world = fusion_worlds[index];\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     return world->fusion_fd;\n}\n\nFusionID\n_fusion_id( const FusionWorldShared *shared )\n{\n     int          index;\n     FusionWorld *world;\n\n     D_MAGIC_ASSERT( shared, FusionWorldShared );\n\n     index = shared->world_index;\n\n     D_ASSERT( index >= 0 );\n     D_ASSERT( index < FUSION_MAX_WORLDS );\n\n     world = fusion_worlds[index];\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     return world->fusion_id;\n}\n\nFusionWorld *\n_fusion_world( const FusionWorldShared *shared )\n{\n     int          index;\n     FusionWorld *world;\n\n     D_MAGIC_ASSERT( shared, FusionWorldShared );\n\n     index = shared->world_index;\n\n     D_ASSERT( index >= 0 );\n     D_ASSERT( index < FUSION_MAX_WORLDS );\n\n     world = fusion_worlds[index];\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     return world;\n}\n\nstatic void fusion_fork_handler_prepare( void );\nstatic void fusion_fork_handler_parent ( void );\nstatic void fusion_fork_handler_child  ( void );\n\nstatic void\ninit_once( void )\n{\n     if (fusion_config->fork_handler)\n          direct_thread_atfork( fusion_fork_handler_prepare, fusion_fork_handler_parent, fusion_fork_handler_child );\n\n     fusion_print_madvise();\n}\n\nstatic bool\nrefs_map_compare( DirectMap  *map,\n                  const void *key,\n                  void       *object,\n                  void       *ctx )\n{\n     const FusionRefSlaveKey *map_key   = key;\n     FusionRefSlaveEntry     *map_entry = object;\n\n     return map_key->fusion_id == map_entry->key.fusion_id && map_key->ref_id == map_entry->key.ref_id;\n}\n\nstatic unsigned int\nrefs_map_hash( DirectMap  *map,\n               const void *key,\n               void       *ctx )\n{\n     const FusionRefSlaveKey *map_key = key;\n\n     return map_key->ref_id * 131 + map_key->fusion_id;\n}\n\nstatic bool\nrefs_map_slave_compare( DirectMap  *map,\n                        const void *key,\n                        void       *object,\n                        void       *ctx )\n{\n     const int *map_key   = key;\n     FusionRef *map_entry = object;\n\n     return *map_key == map_entry->multi.id;\n}\n\nstatic unsigned int\nrefs_map_slave_hash( DirectMap  *map,\n                     const void *key,\n                     void       *ctx )\n{\n     const int *map_key = key;\n\n     return *map_key;\n}\n\nstatic FusionCallHandlerResult\nworld_refs_call( int           caller,   /* Fusion id of the caller. */\n                 int           call_arg, /* Optional call parameter. */\n                 void         *call_ptr, /* Optional call parameter. */\n                 void         *ctx,      /* Optional handler context. */\n                 unsigned int  serial,\n                 int          *ret_val )\n{\n     FusionWorld         *world = ctx;\n     FusionRefSlaveKey    key;\n     FusionRefSlaveEntry *slave;\n\n     key.fusion_id = caller;\n     key.ref_id    = call_arg;\n\n     direct_mutex_lock( &world->refs_lock );\n     slave = direct_map_lookup( world->refs_map, &key );\n     direct_mutex_unlock( &world->refs_lock );\n\n     if (!slave) {\n          D_WARN( \"slave (%d) ref (%d) not found\", caller, call_arg );\n          return FCHR_RETURN;\n     }\n\n     fusion_ref_down( slave->ref, false );\n\n     direct_mutex_lock( &world->refs_lock );\n\n     if (!--slave->refs) {\n          direct_map_remove( world->refs_map, &key );\n\n          D_FREE( slave );\n     }\n\n     direct_mutex_unlock( &world->refs_lock );\n\n     return FCHR_RETURN;\n}\n\nstatic void *fusion_dispatch_loop( DirectThread *thread, void *arg );\n\nstatic DirectOnce fusion_init_once = DIRECT_ONCE_INIT();\n\n#if FUSION_BUILD_KERNEL\n\nstatic int\nfusion_try_open( const char *name1,\n                 const char *name2,\n                 int         flags,\n                 bool        error_msg )\n{\n     int fd;\n\n     fd = open( name1, flags, 660 );\n     if (fd < 0) {\n          if (errno != ENOENT) {\n               if (error_msg)\n                    D_PERROR( \"Fusion/Main: Opening '%s' failed!\\n\", name1 );\n               return -1;\n          }\n\n          fd = open( name2, flags, 660 );\n          if (fd < 0 && error_msg) {\n               if (errno == ENOENT)\n                    D_PERROR( \"Fusion/Main: Opening '%s' and '%s' failed!\\n\", name1, name2 );\n               else\n                    D_PERROR( \"Fusion/Main: Opening '%s' failed!\\n\", name2 );\n          }\n     }\n\n     return (fd < 0) ? -1 : fd;\n}\n\nstatic void\nfusion_world_fork( FusionWorld *world )\n{\n     int         fd;\n     char        buf1[20];\n     char        buf2[20];\n     FusionEnter enter;\n     FusionFork  fork;\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     snprintf( buf1, sizeof(buf1), \"/dev/fusion%d\", world->shared->world_index );\n     snprintf( buf2, sizeof(buf2), \"/dev/fusion/%d\", world->shared->world_index );\n\n     /* Open Fusion Kernel Device. */\n     fd = fusion_try_open( buf1, buf2, O_RDWR, true );\n     if (fd < 0) {\n          D_ERROR( \"Fusion/Main: Reopening fusion device (world %d) failed!\\n\", world->shared->world_index );\n          raise( SIGTRAP );\n     }\n\n     /* Drop \"identity\" when running another program. */\n     if (fcntl( fd, F_SETFD, FD_CLOEXEC ) < 0)\n          D_PERROR( \"Fusion/Main: Setting FD_CLOEXEC flag failed!\\n\" );\n\n     /* Fill enter information. */\n     enter.api.major = 9;\n     enter.api.minor = 0;\n     enter.fusion_id = 0;\n\n     /* Enter the fusion world. */\n     while (ioctl( fd, FUSION_ENTER, &enter )) {\n          if (errno != EINTR) {\n               D_PERROR( \"Fusion/Main: Could not reenter world '%d'!\\n\", world->shared->world_index );\n               raise( SIGTRAP );\n          }\n     }\n\n     /* Check for valid Fusion ID. */\n     if (!enter.fusion_id) {\n          D_ERROR( \"Fusion/Main: Got no ID from FUSION_ENTER!\\n\" );\n          raise( SIGTRAP );\n     }\n\n     D_DEBUG_AT( Fusion_Main, \"  -> Fusion ID 0x%08lx\\n\", enter.fusion_id );\n\n     /* Fill fork information. */\n     fork.fusion_id = world->fusion_id;\n\n     fusion_world_flush_calls( world, 1 );\n\n     /* Fork within the fusion world. */\n     while (ioctl( fd, FUSION_FORK, &fork )) {\n          if (errno != EINTR) {\n               D_PERROR( \"Fusion/Main: Could not fork in world '%d'!\\n\", world->shared->world_index );\n               raise( SIGTRAP );\n          }\n     }\n\n     D_DEBUG_AT( Fusion_Main, \"  -> Fusion ID 0x%08lx\\n\", fork.fusion_id );\n\n     /* Get new fusion id back. */\n     world->fusion_id = fork.fusion_id;\n\n     /* Close old file descriptor. */\n     close( world->fusion_fd );\n\n     /* Write back new file descriptor. */\n     world->fusion_fd = fd;\n\n     D_DEBUG_AT( Fusion_Main, \"  -> restarting dispatcher loop...\\n\" );\n\n     /* Restart the dispatcher thread. */\n     world->dispatch_loop = direct_thread_create( DTT_MESSAGING, fusion_dispatch_loop, world, \"Fusion Dispatch\" );\n     if (!world->dispatch_loop)\n          raise( SIGTRAP );\n}\n\nstatic void\nfusion_fork_handler_prepare()\n{\n     int i;\n\n     D_DEBUG_AT( Fusion_Main, \"%s()\\n\", __FUNCTION__ );\n\n     for (i = 0; i < FUSION_MAX_WORLDS; i++) {\n          FusionWorld *world = fusion_worlds[i];\n\n          if (!world)\n               continue;\n\n          D_MAGIC_ASSERT( world, FusionWorld );\n\n          if (world->fork_callback)\n               world->fork_callback( world->fork_action, FFS_PREPARE );\n     }\n}\n\nstatic void\nfusion_fork_handler_parent()\n{\n     int i;\n\n     D_DEBUG_AT( Fusion_Main, \"%s()\\n\", __FUNCTION__ );\n\n     for (i = 0; i < FUSION_MAX_WORLDS; i++) {\n          FusionWorld *world = fusion_worlds[i];\n\n          if (!world)\n               continue;\n\n          D_MAGIC_ASSERT( world, FusionWorld );\n          D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n          if (world->fork_callback)\n               world->fork_callback( world->fork_action, FFS_PARENT );\n\n          if (world->fork_action == FFA_FORK) {\n               /* Increase the shared reference counter. */\n               if (fusion_master( world ))\n                    world->shared->refs++;\n          }\n     }\n}\n\nstatic void\nfusion_fork_handler_child()\n{\n     int i;\n\n     D_DEBUG_AT( Fusion_Main, \"%s()\\n\", __FUNCTION__ );\n\n     for (i = 0; i < FUSION_MAX_WORLDS; i++) {\n          FusionWorld *world = fusion_worlds[i];\n\n          if (!world)\n               continue;\n\n          D_MAGIC_ASSERT( world, FusionWorld );\n\n          if (world->fork_callback)\n               world->fork_callback( world->fork_action, FFS_CHILD );\n\n          switch (world->fork_action) {\n               default:\n                    D_BUG( \"unknown fork action %u\", world->fork_action );\n\n               case FFA_CLOSE:\n                    D_DEBUG_AT( Fusion_Main, \"  -> closing world %d\\n\", i );\n\n                    /* Remove world from global list. */\n                    fusion_worlds[i] = NULL;\n\n                    /* Unmap shared area. */\n                    direct_file_unmap( world->shared, sizeof(FusionWorldShared) );\n\n                    /* Close Fusion Kernel Device. */\n                    close( world->fusion_fd );\n\n                    /* Free local world data. */\n                    D_MAGIC_CLEAR( world );\n                    D_FREE( world );\n\n                    break;\n\n               case FFA_FORK:\n                    D_DEBUG_AT( Fusion_Main, \"  -> forking in world %d\\n\", i );\n\n                    fusion_world_fork( world );\n\n                    break;\n          }\n     }\n}\n\nstatic DirectResult\nmap_shared_root( void               *shm_base,\n                 int                 world_index,\n                 bool                master,\n                 FusionWorldShared **ret_shared )\n{\n     DirectResult   ret = DR_OK;\n     DirectFile     fd;\n     void          *map;\n     char           tmpfs[FUSION_SHM_TMPFS_PATH_NAME_LEN];\n     char           root_file[FUSION_SHM_TMPFS_PATH_NAME_LEN+32];\n     int            flags = O_RDONLY;\n     int            perms = DFP_READ;\n     unsigned long  size = direct_page_align( sizeof(FusionWorldShared) );\n     unsigned long  base = (unsigned long) shm_base + (size + direct_pagesize()) * world_index;\n\n     if (master || !fusion_config->secure_fusion) {\n          perms  |= DFP_WRITE;\n          flags  = O_RDWR;\n     }\n\n     if (master)\n          flags |= O_CREAT | O_TRUNC;\n\n     if (fusion_config->tmpfs) {\n          direct_snputs( tmpfs, fusion_config->tmpfs, FUSION_SHM_TMPFS_PATH_NAME_LEN );\n     }\n     else if (!fusion_find_tmpfs( tmpfs, FUSION_SHM_TMPFS_PATH_NAME_LEN )) {\n          D_ERROR( \"Fusion/Main: Could not find tmpfs mount point, falling back to /dev/shm!\\n\" );\n          snprintf( tmpfs, FUSION_SHM_TMPFS_PATH_NAME_LEN, \"/dev/shm\" );\n     }\n\n     snprintf( root_file, sizeof(root_file), \"%s/fusion.%d\", tmpfs, world_index );\n\n     /* Open the virtual file. */\n     ret = direct_file_open( &fd, root_file, flags, 0660 );\n     if (ret) {\n          D_DERROR( ret, \"Fusion/Main: Could not open virtual file '%s'!\\n\", root_file );\n          return ret;\n     }\n\n     if (fusion_config->shmfile_gid != -1) {\n          if (direct_file_chown( &fd, -1, fusion_config->shmfile_gid ))\n               D_WARN( \"changing owner on %s failed\", root_file );\n     }\n\n     if (master) {\n          direct_file_chmod( &fd, fusion_config->secure_fusion ? 0640 : 0660 );\n          if (direct_file_truncate( &fd, size )) {\n               D_DERROR( ret, \"Fusion/Main: Could not truncate shared memory file '%s'!\\n\", root_file );\n               goto out;\n          }\n     }\n\n     D_DEBUG_AT( Fusion_Main, \"  -> mapping shared memory file (\"_ZU\" bytes)\\n\", sizeof(FusionWorldShared) );\n\n     /* Map shared area. */\n     D_INFO( \"Fusion/Main: Shared root (%d) is \"_ZU\" bytes, 0x%lx at 0x%lx\\n\",\n             world_index, sizeof(FusionWorldShared), size, base );\n\n     ret = direct_file_map( &fd, (void*) base, 0, size, perms, &map );\n     if (ret) {\n          D_DERROR( ret, \"Fusion/Main: Mapping shared area failed!\\n\" );\n          goto out;\n     }\n\n     *ret_shared = map;\n\nout:\n     direct_file_close( &fd );\n\n     return ret;\n}\n\nstatic void *\nfusion_deferred_loop( DirectThread *thread,\n                      void         *arg )\n{\n     FusionWorld *world = arg;\n\n     D_DEBUG_AT( Fusion_Main_Dispatch, \"%s() running...\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     direct_mutex_lock( &world->deferred.lock );\n\n     while (world->refs) {\n          DeferredCall *deferred;\n\n          deferred = (DeferredCall*) world->deferred.list;\n          if (!deferred) {\n               direct_waitqueue_wait( &world->deferred.queue, &world->deferred.lock );\n               continue;\n          }\n\n          direct_list_remove( &world->deferred.list, &deferred->link );\n\n          direct_mutex_unlock( &world->deferred.lock );\n\n          FusionReadMessage *header = &deferred->header;\n          void              *data   = header + 1;\n\n          switch (header->msg_type) {\n               case FMT_SEND:\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_SEND!\\n\" );\n                    break;\n               case FMT_CALL:\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_CALL...\\n\" );\n                    _fusion_call_process( world, header->msg_id, data,\n                                          (header->msg_size != sizeof(FusionCallMessage)) ?\n                                          data + sizeof(FusionCallMessage) : NULL );\n                    break;\n               case FMT_REACTOR:\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_REACTOR...\\n\" );\n                    _fusion_reactor_process_message( world, header->msg_id, header->msg_channel, data );\n                    break;\n               case FMT_SHMPOOL:\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_SHMPOOL...\\n\" );\n                    _fusion_shmpool_process( world, header->msg_id, data );\n                    break;\n               case FMT_CALL3:\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_CALL3...\\n\" );\n                    _fusion_call_process3( world, header->msg_id, data,\n                                           (header->msg_size != sizeof(FusionCallMessage3)) ?\n                                           data + sizeof(FusionCallMessage3) : NULL );\n                    break;\n               default:\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> discarding message of unknown type '%u'\\n\",\n                                header->msg_type );\n                    break;\n          }\n\n          D_FREE( deferred );\n\n          direct_mutex_lock( &world->deferred.lock );\n     }\n\n     direct_mutex_unlock( &world->deferred.lock );\n\n     return NULL;\n}\n\nDirectResult\nfusion_enter( int               world_index,\n              int               abi_version,\n              FusionEnterRole   role,\n              FusionWorld     **ret_world )\n{\n     DirectResult       ret    = DR_OK;\n     int                fd     = -1;\n     FusionWorld       *world  = NULL;\n     FusionWorldShared *shared = NULL;\n     FusionEnter        enter;\n     char               buf1[20];\n     char               buf2[20];\n     unsigned long      shm_base;\n\n     D_DEBUG_AT( Fusion_Main, \"%s( %d, %d, %p )\\n\", __FUNCTION__, world_index, abi_version, ret_world );\n\n     D_ASSERT( ret_world != NULL );\n\n     if (world_index >= FUSION_MAX_WORLDS) {\n          D_ERROR( \"Fusion/Main: World index %d exceeds maximum index %d!\\n\", world_index, FUSION_MAX_WORLDS - 1 );\n          return DR_INVARG;\n     }\n\n     direct_once( &fusion_init_once, init_once );\n\n     if (fusion_config->force_slave)\n          role = FER_SLAVE;\n\n     direct_initialize();\n\n     direct_mutex_lock( &fusion_worlds_lock );\n\n     if (world_index < 0) {\n          if (role == FER_SLAVE) {\n               D_ERROR( \"Fusion/Main: Slave role and a new world (index -1) was requested!\\n\" );\n               direct_mutex_unlock( &fusion_worlds_lock );\n               return DR_INVARG;\n          }\n\n          for (world_index = 0; world_index < FUSION_MAX_WORLDS; world_index++) {\n               world = fusion_worlds[world_index];\n               if (world)\n                    break;\n\n               snprintf( buf1, sizeof(buf1), \"/dev/fusion%d\", world_index );\n               snprintf( buf2, sizeof(buf2), \"/dev/fusion/%d\", world_index );\n\n               /* Open Fusion Kernel Device. */\n               fd = fusion_try_open( buf1, buf2, O_RDWR | O_EXCL, false );\n               if (fd < 0) {\n                    if (errno != EBUSY)\n                         D_ERROR( \"Fusion/Main: Error opening '%s' and/or '%s'!\\n\", buf1, buf2 );\n               }\n               else\n                    break;\n          }\n     }\n     else {\n          world = fusion_worlds[world_index];\n          if (!world) {\n               int flags = O_RDWR;\n\n               snprintf( buf1, sizeof(buf1), \"/dev/fusion%d\", world_index );\n               snprintf( buf2, sizeof(buf2), \"/dev/fusion/%d\", world_index );\n\n               if (role == FER_MASTER)\n                    flags |= O_EXCL;\n               else if (role == FER_SLAVE)\n                    flags |= O_APPEND;\n\n               /* Open Fusion Kernel Device. */\n               fd = fusion_try_open( buf1, buf2, flags, true );\n          }\n     }\n\n     /* Enter a world again. */\n     if (world) {\n          D_MAGIC_ASSERT( world, FusionWorld );\n          D_ASSERT( world->refs > 0 );\n\n          /* Check the role again. */\n          switch (role) {\n               case FER_MASTER:\n                    if (world->fusion_id != FUSION_ID_MASTER) {\n                         D_ERROR( \"Fusion/Main: Master role requested for a world (%d), but we are already slave in!\\n\",\n                                  world_index );\n                         ret = DR_UNSUPPORTED;\n                         goto error;\n                    }\n                    break;\n\n               case FER_SLAVE:\n                    if (world->fusion_id == FUSION_ID_MASTER) {\n                         D_ERROR( \"Fusion/Main: Slave role requested for a world (%d), but we are already master in!\\n\",\n                                  world_index );\n                         ret = DR_UNSUPPORTED;\n                         goto error;\n                    }\n                    break;\n\n               case FER_ANY:\n                    break;\n          }\n\n          shared = world->shared;\n\n          D_MAGIC_ASSERT( shared, FusionWorldShared );\n\n          if (shared->world_abi != abi_version) {\n               D_ERROR( \"Fusion/Main: World ABI (%d) of world '%d' doesn't match own (%d)!\\n\",\n                        shared->world_abi, world_index, abi_version );\n               ret = DR_VERSIONMISMATCH;\n               goto error;\n          }\n\n          world->refs++;\n\n          direct_mutex_unlock( &fusion_worlds_lock );\n\n          D_DEBUG_AT( Fusion_Main, \"  -> using existing world %p [%d]\\n\", world, world_index );\n\n          /* Return the world. */\n          *ret_world = world;\n\n          return DR_OK;\n     }\n\n     if (fd < 0) {\n          D_ERROR( \"Fusion/Main: Opening fusion device (world %d) as '%s' failed!\\n\",\n                   world_index, role == FER_ANY ? \"any\" : (role == FER_MASTER ? \"master\" : \"slave\") );\n          ret = DR_INIT;\n          goto error;\n     }\n\n     /* Drop \"identity\" when running another program. */\n     if (fcntl( fd, F_SETFD, FD_CLOEXEC ) < 0)\n          D_PERROR( \"Fusion/Main: Setting FD_CLOEXEC flag failed!\\n\" );\n\n     /* Fill enter information. */\n     enter.api.major = 9;\n     enter.api.minor = 0;\n     enter.fusion_id = 0;\n     enter.secure    = fusion_config->secure_fusion;\n\n     /* Enter the fusion world. */\n     while (ioctl( fd, FUSION_ENTER, &enter )) {\n          if (errno != EINTR) {\n               D_PERROR( \"Fusion/Main: Could not enter world '%d'!\\n\", world_index );\n               ret = DR_INIT;\n               goto error;\n          }\n     }\n\n     /* Check for valid Fusion ID. */\n     if (!enter.fusion_id) {\n          D_ERROR( \"Fusion/Main: Got no ID from FUSION_ENTER!\\n\" );\n          ret = DR_INIT;\n          goto error;\n     }\n\n     D_DEBUG_AT( Fusion_Main, \"  -> Fusion ID 0x%08lx\\n\", enter.fusion_id );\n\n     /* Check slave role only, master is handled by O_EXCL earlier. */\n     if (role == FER_SLAVE && enter.fusion_id == FUSION_ID_MASTER) {\n          D_ERROR( \"Fusion/Main: Entering world '%d' as a slave failed!\\n\", world_index );\n          ret = DR_UNSUPPORTED;\n          goto error;\n     }\n\n     if (ioctl( fd, FUSION_SHM_GET_BASE, &shm_base )) {\n          ret = errno2result( errno );\n          D_PERROR( \"Fusion/Main: FUSION_SHM_GET_BASE\" );\n          goto error;\n     }\n\n     /* Map shared area. */\n     ret = map_shared_root( (void*) shm_base, world_index, enter.fusion_id == FUSION_ID_MASTER, &shared );\n     if (ret)\n          goto error;\n\n     D_DEBUG_AT( Fusion_Main, \"  -> shared area at %p, size \"_ZU\"\\n\", shared, sizeof(FusionWorldShared) );\n\n     /* Initialize shared data. */\n     if (enter.fusion_id == FUSION_ID_MASTER) {\n          /* Initialize reference counter. */\n          shared->refs = 1;\n\n          /* Set ABI version. */\n          shared->world_abi = abi_version;\n\n          /* Set the world index. */\n          shared->world_index = world_index;\n\n          /* Set start time of world clock. */\n          shared->start_time = direct_clock_get_time( DIRECT_CLOCK_SESSION );\n\n          D_MAGIC_SET( shared, FusionWorldShared );\n     }\n     else {\n          D_MAGIC_ASSERT( shared, FusionWorldShared );\n\n          /* Check ABI version. */\n          if (shared->world_abi != abi_version) {\n               D_ERROR( \"Fusion/Main: World ABI (%d) doesn't match own (%d)!\\n\",\n                        shared->world_abi, abi_version );\n               ret = DR_VERSIONMISMATCH;\n               goto error;\n          }\n     }\n\n     /* Synchronize to world clock. */\n     direct_clock_set_time( DIRECT_CLOCK_SESSION, shared->start_time );\n\n     /* Allocate local data. */\n     world = D_CALLOC( 1, sizeof(FusionWorld) );\n     if (!world) {\n          ret = D_OOM();\n          goto error;\n     }\n\n     /* Initialize local data. */\n     world->refs      = 1;\n     world->shared    = shared;\n     world->fusion_fd = fd;\n     world->fusion_id = enter.fusion_id;\n\n     direct_mutex_init( &world->reactor_nodes_lock );\n\n     D_MAGIC_SET( world, FusionWorld );\n\n     fusion_worlds[world_index] = world;\n\n     /* Initialize shared memory part. */\n     ret = fusion_shm_init( world );\n     if (ret)\n          goto error2;\n\n     D_DEBUG_AT( Fusion_Main, \"  -> initializing other parts...\\n\" );\n\n     direct_mutex_init( &world->refs_lock );\n\n     /* Initialize other parts. */\n     if (enter.fusion_id == FUSION_ID_MASTER) {\n          fusion_skirmish_init2( &shared->reactor_globals, \"Fusion Reactor Globals\",\n                                 world,fusion_config->secure_fusion );\n          fusion_skirmish_init2( &shared->arenas_lock, \"Fusion Arenas\",\n                                 world, fusion_config->secure_fusion );\n\n          if (!fusion_config->secure_fusion) {\n               fusion_skirmish_add_permissions( &shared->reactor_globals, 0,\n                                                FUSION_SKIRMISH_PERMIT_PREVAIL | FUSION_SKIRMISH_PERMIT_DISMISS );\n               fusion_skirmish_add_permissions( &shared->arenas_lock, 0,\n                                                FUSION_SKIRMISH_PERMIT_PREVAIL | FUSION_SKIRMISH_PERMIT_DISMISS );\n          }\n\n          /* Create the main pool. */\n          ret = fusion_shm_pool_create( world, \"Fusion Main Pool\", 0x1000000,\n                                        fusion_config->debugshm, &shared->main_pool );\n          if (ret)\n               goto error3;\n\n          fusion_call_init( &shared->refs_call, world_refs_call, world, world );\n          fusion_call_set_name( &shared->refs_call, \"world_refs\" );\n          fusion_call_add_permissions( &shared->refs_call, 0, FUSION_CALL_PERMIT_EXECUTE );\n\n          direct_map_create( 37, refs_map_compare, refs_map_hash, world, &world->refs_map );\n     }\n     else\n          direct_map_create( 37, refs_map_slave_compare, refs_map_slave_hash, world, &world->refs_map );\n\n     D_DEBUG_AT( Fusion_Main, \"  -> starting dispatcher loop...\\n\" );\n\n     /* Start the dispatcher thread. */\n     world->dispatch_loop = direct_thread_create( DTT_MESSAGING, fusion_dispatch_loop, world, \"Fusion Dispatch\" );\n     if (!world->dispatch_loop) {\n          ret = DR_FAILURE;\n          goto error4;\n     }\n\n     direct_waitqueue_init( &world->deferred.queue );\n     direct_mutex_init( &world->deferred.lock );\n\n     /* Start the deferred thread. */\n     world->deferred.thread = direct_thread_create( DTT_MESSAGING, fusion_deferred_loop, world, \"Fusion Deferred\" );\n     if (!world->deferred.thread) {\n          ret = DR_FAILURE;\n          goto error4;\n     }\n\n     D_DEBUG_AT( Fusion_Main, \"  -> done (%p)\\n\", world );\n\n     direct_mutex_unlock( &fusion_worlds_lock );\n\n     /* Return the fusion world. */\n     *ret_world = world;\n\n     return DR_OK;\n\nerror4:\n     if (world->deferred.thread)\n          direct_thread_destroy( world->deferred.thread );\n\n     if (world->dispatch_loop)\n          direct_thread_destroy( world->dispatch_loop );\n\n     if (enter.fusion_id == FUSION_ID_MASTER)\n          fusion_shm_pool_destroy( world, shared->main_pool );\n\nerror3:\n     if (enter.fusion_id == FUSION_ID_MASTER) {\n          fusion_skirmish_destroy( &shared->arenas_lock );\n          fusion_skirmish_destroy( &shared->reactor_globals );\n     }\n\n     fusion_shm_deinit( world );\n\nerror2:\n     fusion_worlds[world_index] = world;\n\n     D_MAGIC_CLEAR( world );\n\n     D_FREE( world );\n\nerror:\n     if (shared && shared != MAP_FAILED) {\n          if (enter.fusion_id == FUSION_ID_MASTER)\n               D_MAGIC_CLEAR( shared );\n\n          direct_file_unmap( shared, sizeof(FusionWorldShared) );\n     }\n\n     if (fd != -1)\n          close( fd );\n\n     direct_mutex_unlock( &fusion_worlds_lock );\n\n     direct_shutdown();\n\n     return ret;\n}\n\nDirectResult\nfusion_world_activate( FusionWorld *world )\n{\n     D_DEBUG_AT( Fusion_Main, \"  -> unblocking world...\\n\" );\n\n     while (ioctl( world->fusion_fd, FUSION_UNBLOCK )) {\n          if (errno != EINTR) {\n               D_PERROR( \"Fusion/Main: Could not unblock world!\\n\" );\n               return DR_FUSION;\n          }\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_stop_dispatcher( FusionWorld *world,\n                        bool         emergency )\n{\n     D_DEBUG_AT( Fusion_Main_Dispatch, \"%s( %semergency )\\n\", __FUNCTION__, emergency ? \"\" : \"no \" );\n\n     if (!world->dispatch_loop)\n          return DR_OK;\n\n     if (!emergency) {\n          fusion_sync( world );\n\n          D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> locking thread...\\n\" );\n\n          direct_thread_lock( world->dispatch_loop );\n     }\n\n     D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> locked\\n\" );\n\n     world->dispatch_stop = true;\n\n     if (!emergency) {\n          D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> unlocking thread...\\n\" );\n\n          direct_thread_unlock( world->dispatch_loop );\n\n          fusion_sync( world );\n     }\n\n     fcntl( world->fusion_fd, F_SETFL, O_NONBLOCK );\n\n     D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> finished stopping\\n\" );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_exit( FusionWorld *world,\n             bool         emergency )\n{\n     DirectResult ret;\n\n     D_DEBUG_AT( Fusion_Main, \"%s( %p, %semergency )\\n\", __FUNCTION__, world, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n     D_ASSERT( world->refs > 0 );\n\n     direct_mutex_lock( &fusion_worlds_lock );\n\n     if (--world->refs) {\n          direct_mutex_unlock( &fusion_worlds_lock );\n          return DR_OK;\n     }\n\n     D_ASSUME( direct_thread_self() != world->dispatch_loop );\n\n     if (direct_thread_self() != world->dispatch_loop) {\n          int               foo;\n          FusionSendMessage msg;\n\n          /* Wake up the read loop thread. */\n          msg.fusion_id = world->fusion_id;\n          msg.msg_id    = 0;\n          msg.msg_data  = &foo;\n          msg.msg_size  = sizeof(foo);\n\n          fusion_world_flush_calls( world, 1 );\n\n          while (ioctl( world->fusion_fd, FUSION_SEND_MESSAGE, &msg ) < 0) {\n               if (errno != EINTR) {\n                    D_PERROR( \"Fusion/Main: FUSION_SEND_MESSAGE\" );\n                    direct_thread_cancel( world->dispatch_loop );\n                    break;\n               }\n          }\n\n          /* Wait for its termination. */\n          direct_thread_join( world->dispatch_loop );\n     }\n\n     D_ASSUME( direct_thread_self() != world->deferred.thread );\n\n     /* Wake up the deferred call thread. */\n     direct_waitqueue_signal( &world->deferred.queue );\n\n     /* Wait for its termination. */\n     direct_thread_join( world->deferred.thread );\n\n     direct_thread_destroy( world->dispatch_loop );\n     direct_thread_destroy( world->deferred.thread );\n\n     direct_mutex_deinit( &world->deferred.lock );\n     direct_waitqueue_deinit( &world->deferred.queue );\n\n     direct_mutex_deinit( &world->refs_lock );\n     direct_map_destroy( world->refs_map );\n\n     /* Master has to deinitialize shared data. */\n     if (fusion_master( world )) {\n          fusion_call_destroy( &world->shared->refs_call );\n\n          world->shared->refs--;\n          if (world->shared->refs == 0) {\n               fusion_skirmish_destroy( &world->shared->reactor_globals );\n               fusion_skirmish_destroy( &world->shared->arenas_lock );\n\n               fusion_shm_pool_destroy( world, world->shared->main_pool );\n\n               /* Deinitialize shared memory. */\n               fusion_shm_deinit( world );\n          }\n     }\n     else {\n          /* Leave shared memory. */\n          fusion_shm_deinit( world );\n     }\n\n     /* Reset local dispatch nodes. */\n     _fusion_reactor_free_all( world );\n\n     /* Remove world from global list. */\n     fusion_worlds[world->shared->world_index] = NULL;\n\n     /* Unmap shared area. */\n     if (fusion_master( world ) && world->shared->refs == 0) {\n          char         tmpfs[FUSION_SHM_TMPFS_PATH_NAME_LEN];\n          char         root_file[FUSION_SHM_TMPFS_PATH_NAME_LEN+32];\n\n          if (fusion_config->tmpfs)\n               direct_snputs( tmpfs, fusion_config->tmpfs, FUSION_SHM_TMPFS_PATH_NAME_LEN );\n          else if (!fusion_find_tmpfs( tmpfs, FUSION_SHM_TMPFS_PATH_NAME_LEN ))\n               snprintf( tmpfs, FUSION_SHM_TMPFS_PATH_NAME_LEN, \"/dev/shm\" );\n\n          snprintf( root_file, sizeof(root_file), \"%s/fusion.%d\", tmpfs, world->shared->world_index );\n\n          ret = direct_unlink( root_file );\n          if (ret)\n               D_DERROR( ret, \"Fusion/Main: Could not unlink shared memory file '%s'!\\n\", root_file );\n\n          D_MAGIC_CLEAR( world->shared );\n     }\n\n     direct_file_unmap( world->shared, sizeof(FusionWorldShared) );\n\n     /* Close Fusion Kernel Device. */\n     close( world->fusion_fd );\n\n     /* Free local world data. */\n     D_MAGIC_CLEAR( world );\n\n     D_FREE( world );\n\n     direct_mutex_unlock( &fusion_worlds_lock );\n\n     direct_shutdown();\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_kill( FusionWorld *world,\n             FusionID     fusion_id,\n             int          signal,\n             int          timeout_ms )\n{\n     FusionKill param;\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     param.fusion_id  = fusion_id;\n     param.signal     = signal;\n     param.timeout_ms = timeout_ms;\n\n     fusion_world_flush_calls( world, 1 );\n\n     while (ioctl( world->fusion_fd, FUSION_KILL, &param )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n               case ETIMEDOUT:\n                    return DR_TIMEOUT;\n               default:\n                    break;\n          }\n\n          D_PERROR( \"Fusion/Main: FUSION_KILL\" );\n\n          return DR_FAILURE;\n     }\n\n     return DR_OK;\n}\n\nconst char *\nfusion_get_tmpfs( FusionWorld *world )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     return world->shared->shm.tmpfs;\n}\n\nstatic DirectResult\ndefer_message( FusionWorld       *world,\n               FusionReadMessage *header,\n               void              *data )\n{\n     DeferredCall *deferred;\n\n     deferred = D_CALLOC( 1, sizeof(DeferredCall) + header->msg_size );\n     if (!deferred)\n          return D_OOM();\n\n     deferred->header = *header;\n\n     direct_memcpy( deferred + 1, data, header->msg_size );\n\n     direct_mutex_lock( &world->deferred.lock );\n\n     direct_list_append( &world->deferred.list, &deferred->link );\n\n     direct_mutex_unlock( &world->deferred.lock );\n\n     direct_waitqueue_signal( &world->deferred.queue );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_dispatch_cleanup_add( FusionWorld                *world,\n                             FusionDispatchCleanupFunc   func,\n                             void                       *ctx,\n                             FusionDispatchCleanup     **ret_cleanup )\n{\n     FusionDispatchCleanup *cleanup;\n\n     cleanup = D_CALLOC( 1, sizeof(FusionDispatchCleanup) );\n     if (!cleanup)\n          return D_OOM();\n\n     cleanup->func = func;\n     cleanup->ctx  = ctx;\n\n     direct_list_append( &world->dispatch_cleanups, &cleanup->link );\n\n     *ret_cleanup = cleanup;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_dispatch_cleanup_remove( FusionWorld           *world,\n                                FusionDispatchCleanup *cleanup )\n{\n     direct_list_remove( &world->dispatch_cleanups, &cleanup->link );\n\n     D_FREE( cleanup );\n\n     return DR_OK;\n}\n\nstatic void\nhandle_dispatch_cleanups( FusionWorld *world )\n{\n     FusionDispatchCleanup *cleanup, *next;\n\n     D_DEBUG_AT( Fusion_Main_Dispatch, \"%s( %p )\\n\", __FUNCTION__, world );\n\n     direct_list_foreach_safe (cleanup, next, world->dispatch_cleanups) {\n          if (direct_log_domain_check( &Fusion_Main_Dispatch ))\n               D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> %s (%p)\\n\",\n                           direct_trace_lookup_symbol_at( cleanup->func ), cleanup->ctx );\n\n          cleanup->func( cleanup->ctx );\n\n          D_FREE( cleanup );\n     }\n\n     D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> cleanups done\\n\" );\n\n     world->dispatch_cleanups = NULL;\n}\n\nstatic DirectEnumerationResult\nrefs_iterate( DirectMap *map,\n              void      *object,\n              void      *ctx )\n{\n     FusionRefSlaveEntry *entry = object;\n\n     if (entry->key.fusion_id == *((FusionID*) ctx)) {\n          int i;\n\n          for (i = 0; i < entry->refs; i++)\n               fusion_ref_down( entry->ref, false );\n\n          D_FREE( entry );\n\n          return DENUM_REMOVE;\n     }\n\n     return DENUM_OK;\n}\n\nstatic void *\nfusion_dispatch_loop( DirectThread *thread,\n                      void         *arg )\n{\n     ssize_t      len      = 0;\n     size_t       buf_size = FUSION_MESSAGE_SIZE * 4;\n     char        *buf      = D_MALLOC( buf_size );\n     FusionWorld *world    = arg;\n\n     D_DEBUG_AT( Fusion_Main_Dispatch, \"%s() running...\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     direct_thread_lock( thread );\n\n     while (true) {\n          char *buf_p = buf;\n\n          if (world->dispatch_stop) {\n               D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> ignoring (dispatch_stop)\\n\" );\n\n               goto out;\n          }\n          else {\n               D_DEBUG_AT( Fusion_Main_Dispatch, \"%s( world %p ) => read( \"_ZU\" )...\\n\", __FUNCTION__,\n                           world, buf_size );\n\n               direct_thread_unlock( thread );\n\n               len = read( world->fusion_fd, buf, buf_size );\n\n               direct_thread_lock( thread );\n\n               if (len < 0) {\n                    if (errno == EINTR)\n                         continue;\n\n                    break;\n               }\n\n               D_DEBUG_AT( Fusion_Main_Dispatch, \"%s( world %p ) => got \"_ZD\" (of up to \"_ZU\")\\n\", __FUNCTION__,\n                           world, len, buf_size );\n\n               while (buf_p < buf + len) {\n                    FusionReadMessage *header = (FusionReadMessage*) buf_p;\n                    void              *data   = buf_p + sizeof(FusionReadMessage);\n\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"%s( world %p ) => %p [%ld]\\n\", __FUNCTION__,\n                                world, header, (long) buf_p - (long) buf );\n\n                    D_ASSERT( (buf + len - buf_p) >= sizeof(FusionReadMessage) );\n\n                    switch (header->msg_type) {\n                         case FMT_SEND:\n                              D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_SEND!\\n\" );\n                              break;\n                         case FMT_CALL:\n                              D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_CALL...\\n\" );\n                              if (((FusionCallMessage*) data)->caller == 0)\n                                   handle_dispatch_cleanups( world );\n\n                              /* If the call comes from kernel space it is most likely a destructor call, defer it. */\n                              if (fusion_config->defer_destructors && ((FusionCallMessage*) data)->caller == 0) {\n                                   defer_message( world, header, data );\n                              }\n                              else {\n                                   _fusion_call_process( world, header->msg_id, data,\n                                                         (header->msg_size != sizeof(FusionCallMessage)) ?\n                                                         data + sizeof(FusionCallMessage) : NULL );\n                              }\n                              break;\n                         case FMT_REACTOR:\n                              D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_REACTOR...\\n\" );\n                              _fusion_reactor_process_message( world, header->msg_id, header->msg_channel, data );\n                              break;\n                         case FMT_SHMPOOL:\n                              D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_SHMPOOL...\\n\" );\n                              _fusion_shmpool_process( world, header->msg_id, data );\n                              break;\n                         case FMT_CALL3:\n                              D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_CALL3...\\n\" );\n                              _fusion_call_process3( world, header->msg_id, data,\n                                                     (header->msg_size != sizeof(FusionCallMessage3)) ?\n                                                     data + sizeof(FusionCallMessage3) : NULL );\n                              break;\n                         case FMT_LEAVE:\n                              D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_LEAVE...\\n\" );\n                              if (world->fusion_id == FUSION_ID_MASTER) {\n                                   direct_mutex_lock( &world->refs_lock );\n                                   direct_map_iterate( world->refs_map, refs_iterate, data );\n                                   direct_mutex_unlock( &world->refs_lock );\n                              }\n\n                              if (world->leave_callback)\n                                   world->leave_callback( world, *((FusionID*) data), world->leave_ctx );\n                              break;\n                         default:\n                              D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> discarding message of unknown type %u\\n\",\n                                          header->msg_type );\n                              break;\n                    }\n\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> done\\n\" );\n\n                    buf_p = data + ((header->msg_size + 3) & ~3);\n               }\n          }\n\n          handle_dispatch_cleanups( world );\n\n          if (!world->refs) {\n               D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> good bye!\\n\" );\n               goto out;\n          }\n     }\n\n     D_PERROR( \"Fusion/Main: Reading from fusion device failed!\\n\" );\n\nout:\n     direct_thread_unlock( thread );\n     D_FREE( buf );\n     return NULL;\n}\n\nDirectResult\nfusion_dispatch( FusionWorld *world,\n                 size_t       buf_size )\n{\n     ssize_t  len = 0;\n     char    *buf;\n     char    *buf_p;\n\n     D_DEBUG_AT( Fusion_Main_Dispatch, \"%s( world %p, buf_size \"_ZU\" )\\n\", __FUNCTION__, world, buf_size );\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     if (buf_size == 0)\n          buf_size = FUSION_MESSAGE_SIZE * 4;\n     else\n          D_ASSUME( buf_size >= FUSION_MESSAGE_SIZE );\n\n     buf = buf_p = D_MALLOC( buf_size );\n\n     D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> dispatch => reading up to \"_ZU\" bytes...\\n\", buf_size );\n\n     while (true) {\n          len = read( world->fusion_fd, buf, buf_size );\n          if (len < 0) {\n               if (errno == EINTR)\n                    continue;\n\n               if (errno != EAGAIN)\n                    D_PERROR( \"Fusion/Main: Reading from fusion device failed!\\n\" );\n\n               D_FREE( buf );\n               return DR_IO;\n          }\n\n          break;\n     }\n\n     D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> dispatch => got \"_ZD\" bytes (of up to \"_ZU\")\\n\", len, buf_size );\n\n     if (world->dispatch_loop)\n          direct_thread_lock( world->dispatch_loop );\n\n     while (buf_p < buf + len) {\n          FusionReadMessage *header = (FusionReadMessage*) buf_p;\n          void              *data   = buf_p + sizeof(FusionReadMessage);\n\n          D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> dispatch => %p [%ld]\\n\", header, (long) buf_p - (long) buf );\n\n          D_ASSERT( (buf + len - buf_p) >= sizeof(FusionReadMessage) );\n\n          switch (header->msg_type) {\n               case FMT_SEND:\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_SEND!\\n\" );\n                    break;\n               case FMT_CALL:\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_CALL...\\n\" );\n                    if (((FusionCallMessage*) data)->caller == 0)\n                         handle_dispatch_cleanups( world );\n\n                    /* If the call comes from kernel space it is most likely a destructor call, defer it. */\n                    if (fusion_config->defer_destructors && ((FusionCallMessage*) data)->caller == 0) {\n                         defer_message( world, header, data );\n                    }\n                    else\n                         _fusion_call_process( world, header->msg_id, data,\n                                               (header->msg_size != sizeof(FusionCallMessage)) ?\n                                               data + sizeof(FusionCallMessage) : NULL );\n                    break;\n               case FMT_REACTOR:\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_REACTOR...\\n\" );\n                    _fusion_reactor_process_message( world, header->msg_id, header->msg_channel, data );\n                    break;\n               case FMT_SHMPOOL:\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_SHMPOOL...\\n\" );\n                    _fusion_shmpool_process( world, header->msg_id, data );\n                    break;\n               case FMT_CALL3:\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_CALL3...\\n\" );\n                    _fusion_call_process3( world, header->msg_id, data,\n                                           (header->msg_size != sizeof(FusionCallMessage3)) ?\n                                           data + sizeof(FusionCallMessage3) : NULL );\n                    break;\n               case FMT_LEAVE:\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_LEAVE...\\n\" );\n                    if (world->fusion_id == FUSION_ID_MASTER) {\n                         direct_mutex_lock( &world->refs_lock );\n                         direct_map_iterate( world->refs_map, refs_iterate, data );\n                         direct_mutex_unlock( &world->refs_lock );\n                    }\n\n                    if (world->leave_callback)\n                         world->leave_callback( world, *((FusionID*) data), world->leave_ctx );\n                    break;\n               default:\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> discarding message of unknown type '%u'\\n\",\n                                header->msg_type );\n                    break;\n          }\n\n          D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> done\\n\" );\n\n          buf_p = data + ((header->msg_size + 3) & ~3);\n     }\n\n     handle_dispatch_cleanups( world );\n\n     if (world->dispatch_loop)\n          direct_thread_unlock( world->dispatch_loop );\n\n     D_FREE( buf );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_get_fusionee_path( const FusionWorld *world,\n                          FusionID           fusion_id,\n                          char              *buf,\n                          size_t             buf_size,\n                          size_t            *ret_size )\n{\n     FusionGetFusioneeInfo info;\n     size_t                len;\n\n     D_ASSERT( world != NULL );\n     D_ASSERT( buf != NULL );\n     D_ASSERT( ret_size != NULL );\n\n     info.fusion_id = fusion_id;\n\n     while (ioctl( world->fusion_fd, FUSION_GET_FUSIONEE_INFO, &info ) < 0) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n\n               default:\n                    break;\n          }\n\n          D_PERROR( \"Fusion/Main: FUSION_GET_FUSIONEE_INFO\" );\n\n          return DR_FUSION;\n     }\n\n     len = strlen( info.exe_file ) + 1;\n\n     if (len > buf_size) {\n          *ret_size = len;\n          return DR_LIMITEXCEEDED;\n     }\n\n     direct_memcpy( buf, info.exe_file, len );\n\n     *ret_size = len;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_get_fusionee_pid( const FusionWorld *world,\n                         FusionID           fusion_id,\n                         pid_t             *ret_pid )\n{\n     FusionGetFusioneeInfo info;\n\n     D_ASSERT( world != NULL );\n     D_ASSERT( ret_pid != NULL );\n\n     info.fusion_id = fusion_id;\n\n     while (ioctl( world->fusion_fd, FUSION_GET_FUSIONEE_INFO, &info ) < 0) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n\n               default:\n                    break;\n          }\n\n          D_PERROR( \"Fusion/main: FUSION_GET_FUSIONEE_INFO\" );\n\n          return DR_FUSION;\n     }\n\n     *ret_pid = info.pid;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_world_set_root( FusionWorld *world,\n                       void        *root )\n{\n     D_ASSERT( world != NULL );\n     D_ASSERT( world->shared != NULL );\n\n     if (world->fusion_id != FUSION_ID_MASTER)\n          return DR_ACCESSDENIED;\n\n     world->shared->world_root = root;\n\n     return DR_OK;\n}\n\nvoid *\nfusion_world_get_root( FusionWorld *world )\n{\n     D_ASSERT( world != NULL );\n     D_ASSERT( world->shared != NULL );\n\n     return world->shared->world_root;\n}\n\nDirectResult\nfusion_sync( const FusionWorld *world )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     D_DEBUG_AT( Fusion_Main, \"%s( %p )\\n\", __FUNCTION__, world );\n\n     D_DEBUG_AT( Fusion_Main, \"  -> syncing with fusion device...\\n\" );\n\n     while (ioctl( world->fusion_fd, FUSION_SYNC )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n               default:\n                    break;\n          }\n\n          D_PERROR( \"Fusion/Main: FUSION_SYNC\" );\n\n          return DR_FAILURE;\n     }\n\n     D_DEBUG_AT( Fusion_Main, \"  -> synced\\n\" );\n\n     return DR_OK;\n}\n\n#else /* FUSION_BUILD_KERNEL */\n\ntypedef struct {\n     DirectLink  link;\n\n     FusionRef  *ref;\n\n     int         count;\n} FusioneeRef;\n\ntypedef struct {\n     DirectLink  link;\n\n     FusionID    id;\n     pid_t       pid;\n\n     DirectLink *refs;\n} Fusionee;\n\nstatic DirectResult\n_fusion_add_fusionee( FusionWorld *world,\n                      FusionID     fusion_id )\n{\n     DirectResult  ret;\n     Fusionee     *fusionee;\n\n     D_DEBUG_AT( Fusion_Main, \"%s( %p, %lu )\\n\", __FUNCTION__, world, fusion_id );\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     fusionee = SHCALLOC( world->shared->main_pool, 1, sizeof(Fusionee) );\n     if (!fusionee)\n          return D_OOSHM();\n\n     fusionee->id  = fusion_id;\n     fusionee->pid = direct_gettid();\n\n     ret = fusion_skirmish_prevail( &world->shared->fusionees_lock );\n     if (ret) {\n          SHFREE( world->shared->main_pool, fusionee );\n          return ret;\n     }\n\n     direct_list_append( &world->shared->fusionees, &fusionee->link );\n\n     fusion_skirmish_dismiss( &world->shared->fusionees_lock );\n\n     /* Set local pointer. */\n     world->fusionee = fusionee;\n\n     return DR_OK;\n}\n\nvoid\n_fusion_add_local( FusionWorld *world,\n                   FusionRef   *ref,\n                   int          add )\n{\n     Fusionee    *fusionee;\n     FusioneeRef *fusionee_ref;\n\n     D_DEBUG_AT( Fusion_Main, \"%s( %p, %p, %d )\\n\", __FUNCTION__, world, ref, add );\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n     D_ASSERT( world->fusionee != NULL );\n     D_ASSERT( ref != NULL );\n\n     fusionee = world->fusionee;\n\n     direct_list_foreach (fusionee_ref, fusionee->refs) {\n          if (fusionee_ref->ref == ref)\n               break;\n     }\n\n     if (fusionee_ref) {\n          fusionee_ref->count += add;\n\n          D_DEBUG_AT( Fusion_Main, \"  -> refs = %d\\n\", fusionee_ref->count );\n\n          if (fusionee_ref->count == 0) {\n               direct_list_remove( &fusionee->refs, &fusionee_ref->link );\n\n               SHFREE( world->shared->main_pool, fusionee_ref );\n          }\n     }\n     else {\n          /* Check whether we are called from _fusion_remove_fusionee(). */\n          if (add <= 0)\n               return;\n\n          D_DEBUG_AT( Fusion_Main, \"  -> new ref\\n\" );\n\n          fusionee_ref = SHCALLOC( world->shared->main_pool, 1, sizeof(FusioneeRef) );\n          if (!fusionee_ref) {\n               D_OOSHM();\n               return;\n          }\n\n          fusionee_ref->ref   = ref;\n          fusionee_ref->count = add;\n\n          direct_list_prepend( &fusionee->refs, &fusionee_ref->link );\n     }\n}\n\nvoid\n_fusion_check_locals( FusionWorld *world,\n                      FusionRef   *ref )\n{\n     DirectResult  ret;\n     Fusionee     *fusionee;\n     FusioneeRef  *fusionee_ref, *next;\n     DirectLink   *list = NULL;\n\n     D_DEBUG_AT( Fusion_Main, \"%s( %p, %p )\\n\", __FUNCTION__, world, ref );\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n     D_ASSERT( ref != NULL );\n\n     if (fusion_skirmish_prevail( &world->shared->fusionees_lock ))\n          return;\n\n     direct_list_foreach (fusionee, world->shared->fusionees) {\n          if (fusionee->id == world->fusion_id)\n               continue;\n\n          direct_list_foreach (fusionee_ref, fusionee->refs) {\n               if (fusionee_ref->ref == ref) {\n                    ret = direct_kill( fusionee->pid, 0 );\n                    if (ret == DR_NOSUCHINSTANCE) {\n                         direct_list_remove( &fusionee->refs, &fusionee_ref->link );\n                         direct_list_append( &list, &fusionee_ref->link );\n                    }\n                    break;\n               }\n          }\n     }\n\n     fusion_skirmish_dismiss( &world->shared->fusionees_lock );\n\n     direct_list_foreach_safe (fusionee_ref, next, list) {\n          _fusion_ref_change( ref, -fusionee_ref->count, false );\n\n          SHFREE( world->shared->main_pool, fusionee_ref );\n     }\n}\n\nvoid\n_fusion_remove_all_locals( FusionWorld     *world,\n                           const FusionRef *ref )\n{\n     Fusionee    *fusionee;\n     FusioneeRef *fusionee_ref, *next;\n\n     D_DEBUG_AT( Fusion_Main, \"%s( %p, %p )\\n\", __FUNCTION__, world, ref );\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n     D_ASSERT( ref != NULL );\n\n     if (fusion_skirmish_prevail( &world->shared->fusionees_lock ))\n          return;\n\n     direct_list_foreach (fusionee, world->shared->fusionees) {\n          direct_list_foreach_safe (fusionee_ref, next, fusionee->refs) {\n               if (fusionee_ref->ref == ref) {\n                    direct_list_remove( &fusionee->refs, &fusionee_ref->link );\n\n                    SHFREE( world->shared->main_pool, fusionee_ref );\n               }\n          }\n     }\n\n     fusion_skirmish_dismiss( &world->shared->fusionees_lock );\n}\n\nstatic void\n_fusion_remove_fusionee( FusionWorld *world,\n                         FusionID fusion_id )\n{\n     Fusionee    *fusionee;\n     FusioneeRef *fusionee_ref, *next;\n\n     D_DEBUG_AT( Fusion_Main, \"%s( %p, %lu )\\n\", __FUNCTION__, world, fusion_id );\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     fusion_skirmish_prevail( &world->shared->fusionees_lock );\n\n     if (fusion_id == world->fusion_id) {\n          fusionee = world->fusionee;\n     }\n     else {\n          direct_list_foreach (fusionee, world->shared->fusionees) {\n               if (fusionee->id == fusion_id)\n                    break;\n          }\n     }\n\n     if (!fusionee) {\n          D_DEBUG_AT( Fusion_Main, \"  -> fusionee %lu not found!\\n\", fusion_id );\n          fusion_skirmish_dismiss( &world->shared->fusionees_lock );\n          return;\n     }\n\n     direct_list_remove( &world->shared->fusionees, &fusionee->link );\n\n     fusion_skirmish_dismiss( &world->shared->fusionees_lock );\n\n     direct_list_foreach_safe (fusionee_ref, next, fusionee->refs) {\n          direct_list_remove( &fusionee->refs, &fusionee_ref->link );\n\n          _fusion_ref_change( fusionee_ref->ref, -fusionee_ref->count, false );\n\n          SHFREE( world->shared->main_pool, fusionee_ref );\n     }\n\n     SHFREE( world->shared->main_pool, fusionee );\n}\n\nDirectResult\n_fusion_send_message( int                 fd,\n                      const void         *msg,\n                      size_t              msg_size,\n                      struct sockaddr_un *addr )\n{\n     socklen_t addrlen = sizeof(struct sockaddr_un);\n\n     D_ASSERT( msg != NULL );\n\n     if (!addr) {\n          addr = alloca( sizeof(struct sockaddr_un) );\n          getsockname( fd, (struct sockaddr*) addr, &addrlen );\n     }\n\n     while (sendto( fd, msg, msg_size, 0, (struct sockaddr*) addr, addrlen ) < 0) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n               case ECONNREFUSED:\n                    return DR_DESTROYED;\n               default:\n                    break;\n          }\n\n          D_PERROR( \"Fusion/Main: sendto() failed!\\n\" );\n\n          return DR_IO;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\n_fusion_recv_message( int                 fd,\n                      void               *msg,\n                      size_t              msg_size,\n                      struct sockaddr_un *addr )\n{\n     socklen_t addrlen = addr ? sizeof(struct sockaddr_un) : 0;\n\n     D_ASSERT( msg != NULL );\n\n     while (recvfrom( fd, msg, msg_size, 0, (struct sockaddr*) addr, &addrlen ) < 0) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n               case ECONNREFUSED:\n                    return DR_DESTROYED;\n               default:\n                    break;\n          }\n\n          D_PERROR( \"Fusion/Main: recvfrom() failed!\\n\" );\n\n          return DR_IO;\n     }\n\n     return DR_OK;\n}\n\nstatic void\nfusion_fork_handler_prepare()\n{\n     int i;\n\n     D_DEBUG_AT( Fusion_Main, \"%s()\\n\", __FUNCTION__ );\n\n     for (i = 0; i < FUSION_MAX_WORLDS; i++) {\n          FusionWorld *world = fusion_worlds[i];\n\n          if (!world)\n               continue;\n\n          D_MAGIC_ASSERT( world, FusionWorld );\n\n          if (world->fork_callback)\n               world->fork_callback( world->fork_action, FFS_PREPARE );\n     }\n}\n\nstatic void\nfusion_fork_handler_parent()\n{\n     int i;\n\n     D_DEBUG_AT( Fusion_Main, \"%s()\\n\", __FUNCTION__ );\n\n     for (i = 0; i < FUSION_MAX_WORLDS; i++) {\n          FusionWorld *world = fusion_worlds[i];\n\n          if (!world)\n               continue;\n\n          D_MAGIC_ASSERT( world, FusionWorld );\n          D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n          if (world->fork_callback)\n               world->fork_callback( world->fork_action, FFS_PARENT );\n\n          if (world->fork_action == FFA_FORK) {\n               /* Increase the shared reference counter. */\n               if (fusion_master( world ))\n                    world->shared->refs++;\n\n               /* Cancel the dispatcher to prevent conflicts. */\n               direct_thread_cancel( world->dispatch_loop );\n          }\n     }\n}\n\nstatic void\nfusion_fork_handler_child()\n{\n     int i;\n\n     D_DEBUG_AT( Fusion_Main, \"%s()\\n\", __FUNCTION__ );\n\n     for (i = 0; i < FUSION_MAX_WORLDS; i++) {\n          FusionWorld *world = fusion_worlds[i];\n\n          if (!world)\n               continue;\n\n          D_MAGIC_ASSERT( world, FusionWorld );\n          D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n          if (world->fork_callback)\n               world->fork_callback( world->fork_action, FFS_CHILD );\n\n          switch (world->fork_action) {\n               default:\n                    D_BUG( \"unknown fork action %u\", world->fork_action );\n\n               case FFA_CLOSE:\n                    D_DEBUG_AT( Fusion_Main, \"  -> closing world %d\\n\", i );\n\n                    /* Remove world from global list. */\n                    fusion_worlds[i] = NULL;\n\n                    /* Unmap shared area. */\n                    direct_file_unmap( world->shared, sizeof(FusionWorldShared) );\n\n                    /* Close socket. */\n                    close( world->fusion_fd );\n\n                    /* Free local world data. */\n                    D_MAGIC_CLEAR( world );\n                    D_FREE( world );\n\n                    break;\n\n               case FFA_FORK: {\n                    Fusionee    *fusionee;\n                    FusioneeRef *fusionee_ref;\n\n                    D_DEBUG_AT( Fusion_Main, \"  -> forking in world %d\\n\", i );\n\n                    fusionee = world->fusionee;\n\n                    D_DEBUG_AT( Fusion_Main, \"  -> duplicating fusion id %lu\\n\", world->fusion_id );\n\n                    fusion_skirmish_prevail( &world->shared->fusionees_lock );\n\n                    if (_fusion_add_fusionee( world, world->fusion_id )) {\n                         fusion_skirmish_dismiss( &world->shared->fusionees_lock );\n                         raise( SIGTRAP );\n                    }\n\n                    D_DEBUG_AT( Fusion_Main, \"  -> duplicating local refs...\\n\" );\n\n                    direct_list_foreach (fusionee_ref, fusionee->refs) {\n                         FusioneeRef *new_ref;\n\n                         new_ref = SHCALLOC( world->shared->main_pool, 1, sizeof(FusioneeRef) );\n                         if (!new_ref) {\n                              D_OOSHM();\n                              fusion_skirmish_dismiss( &world->shared->fusionees_lock );\n                              raise( SIGTRAP );\n                         }\n\n                         new_ref->ref   = fusionee_ref->ref;\n                         new_ref->count = fusionee_ref->count;\n                         /* Avoid locking. */\n                         new_ref->ref->multi.builtin.local += new_ref->count;\n\n                         direct_list_append( &((Fusionee*) world->fusionee)->refs, &new_ref->link );\n                    }\n\n                    fusion_skirmish_dismiss( &world->shared->fusionees_lock );\n\n                    D_DEBUG_AT( Fusion_Main, \"  -> restarting dispatcher loop...\\n\" );\n\n                    /* Restart the dispatcher thread. */\n                    world->dispatch_loop = direct_thread_create( DTT_MESSAGING, fusion_dispatch_loop, world,\n                                                                 \"Fusion Dispatch\" );\n                    if (!world->dispatch_loop)\n                         raise( SIGTRAP );\n\n                    break;\n               }\n          }\n     }\n}\n\nDirectResult\nfusion_enter( int               world_index,\n              int               abi_version,\n              FusionEnterRole   role,\n              FusionWorld     **ret_world )\n{\n     DirectResult        ret        = DR_OK;\n     int                 orig_index = world_index;\n     int                 fd         = -1;\n     FusionID            id         = -1;\n     FusionWorld        *world      = NULL;\n     FusionWorldShared  *shared     = MAP_FAILED;\n     struct sockaddr_un  addr;\n     char                buf[128];\n     int                 err;\n     int                 len;\n\n     D_DEBUG_AT( Fusion_Main, \"%s( %d, %d, %p )\\n\", __FUNCTION__, world_index, abi_version, ret_world );\n\n     D_ASSERT( ret_world != NULL );\n\n     if (world_index >= FUSION_MAX_WORLDS) {\n          D_ERROR( \"Fusion/Main: World index %d exceeds maximum index %d!\\n\", world_index, FUSION_MAX_WORLDS - 1 );\n          return DR_INVARG;\n     }\n\n     if (fusion_config->force_slave)\n          role = FER_SLAVE;\n\n     direct_once( &fusion_init_once, init_once );\n\n     direct_initialize();\n\n     direct_mutex_lock( &fusion_worlds_lock );\n\nretry:\n     world_index = orig_index;\n     fd          = -1;\n     id          = -1;\n     world       = NULL;\n     shared      = MAP_FAILED;\n\n     fd = socket( PF_LOCAL, SOCK_RAW, 0 );\n     if (fd < 0) {\n          D_PERROR( \"Fusion/Main: Error creating local socket!\\n\" );\n          direct_mutex_unlock( &fusion_worlds_lock );\n          return DR_IO;\n     }\n\n     /* Set close-on-exec flag. */\n     if (fcntl( fd, F_SETFD, FD_CLOEXEC ) < 0)\n          D_PERROR( \"Fusion/Main: Setting FD_CLOEXEC flag failed!\\n\" );\n\n     addr.sun_family = AF_UNIX;\n\n     if (world_index < 0) {\n          if (role == FER_SLAVE) {\n               D_ERROR( \"Fusion/Main: Slave role and a new world (index -1) was requested!\\n\" );\n               direct_mutex_unlock( &fusion_worlds_lock );\n               close( fd );\n               return DR_INVARG;\n          }\n\n          for (world_index = 0; world_index < FUSION_MAX_WORLDS; world_index++) {\n               if (fusion_worlds[world_index])\n                    continue;\n\n               len = snprintf( addr.sun_path, sizeof(addr.sun_path), \"/tmp/.fusion-%d/\", world_index );\n\n               /* Make socket directory if it doesn't exits. */\n               ret = direct_dir_create( addr.sun_path, 0775 );\n               if (ret == DR_OK) {\n                    if (fusion_config->shmfile_gid != -1)\n                         direct_chown( addr.sun_path, -1, fusion_config->shmfile_gid );\n               }\n\n               snprintf( addr.sun_path + len, sizeof(addr.sun_path) - len, \"%lx\", (unsigned long) FUSION_ID_MASTER );\n\n               /* Bind to address. */\n               err = bind( fd, (struct sockaddr*) &addr, sizeof(addr) );\n               if (err == 0) {\n                    direct_chmod( addr.sun_path, 0660 );\n\n                    /* Change group, if requested. */\n                    if (fusion_config->shmfile_gid != -1)\n                         direct_chown( addr.sun_path, -1, fusion_config->shmfile_gid );\n                    id = FUSION_ID_MASTER;\n                    break;\n               }\n          }\n     }\n     else {\n          world = fusion_worlds[world_index];\n          if (!world) {\n               len = snprintf( addr.sun_path, sizeof(addr.sun_path), \"/tmp/.fusion-%d/\", world_index );\n\n               /* Make socket directory if it doesn't exits. */\n               ret = direct_dir_create( addr.sun_path, 0775 );\n               if (ret == DR_OK) {\n                    if (fusion_config->shmfile_gid != -1)\n                         direct_chown( addr.sun_path, -1, fusion_config->shmfile_gid );\n               }\n\n               /* Check wether we are master. */\n               snprintf( addr.sun_path + len, sizeof(addr.sun_path) - len, \"%lx\", (unsigned long) FUSION_ID_MASTER );\n\n               err = bind( fd, (struct sockaddr*) &addr, sizeof(addr) );\n               if (err < 0) {\n                    if (role == FER_MASTER) {\n                         D_ERROR( \"Fusion/Main: Could not start session as master -> remove %s!\\n\", addr.sun_path );\n                         ret = DR_INIT;\n                         goto error;\n                    }\n\n                    /* Auto generate slave id. */\n                    for (id = FUSION_ID_MASTER + 1; id < (FusionID) -1; id++) {\n                         snprintf( addr.sun_path + len, sizeof(addr.sun_path) - len, \"%lx\", id );\n                         err = bind( fd, (struct sockaddr*) &addr, sizeof(addr) );\n                         if (err == 0) {\n                              direct_chmod( addr.sun_path, 0660 );\n\n                               /* Change group, if requested. */\n                              if (fusion_config->shmfile_gid != -1)\n                                   direct_chown( addr.sun_path, -1, fusion_config->shmfile_gid );\n                              break;\n                         }\n                    }\n               }\n               else if (err == 0 && role != FER_SLAVE) {\n                    direct_chmod( addr.sun_path, 0660 );\n\n                    /* Change group, if requested. */\n                    if (fusion_config->shmfile_gid != -1)\n                         direct_chown( addr.sun_path, -1, fusion_config->shmfile_gid );\n                    id = FUSION_ID_MASTER;\n               }\n          }\n     }\n\n     /* Enter a world again. */\n     if (world) {\n          D_MAGIC_ASSERT( world, FusionWorld );\n          D_ASSERT( world->refs > 0 );\n\n          /* Check the role again. */\n          switch (role) {\n               case FER_MASTER:\n                    if (world->fusion_id != FUSION_ID_MASTER) {\n                         D_ERROR( \"Fusion/Main: Master role requested for a world (%d), but we are already slave in!\\n\",\n                                  world_index );\n                         ret = DR_UNSUPPORTED;\n                         goto error;\n                    }\n                    break;\n\n               case FER_SLAVE:\n                    if (world->fusion_id == FUSION_ID_MASTER) {\n                         D_ERROR( \"Fusion/Main: Slave role requested for a world (%d), but we are already master in!\\n\",\n                                  world_index );\n                         ret = DR_UNSUPPORTED;\n                         goto error;\n                    }\n                    break;\n\n               case FER_ANY:\n                    break;\n          }\n\n          shared = world->shared;\n\n          D_MAGIC_ASSERT( shared, FusionWorldShared );\n\n          if (shared->world_abi != abi_version) {\n               D_ERROR( \"Fusion/Main: World ABI (%d) of world '%d' doesn't match own (%d)!\\n\",\n                        shared->world_abi, world_index, abi_version );\n               ret = DR_VERSIONMISMATCH;\n               goto error;\n          }\n\n          world->refs++;\n\n          direct_mutex_unlock( &fusion_worlds_lock );\n\n          D_DEBUG_AT( Fusion_Main, \"  -> using existing world %p [%d]\\n\", world, world_index );\n\n          close( fd );\n\n          /* Return the world. */\n          *ret_world = world;\n\n          return DR_OK;\n     }\n\n     if (id == (FusionID) -1) {\n          D_ERROR( \"Fusion/Main: Opening fusion socket (world %d) as '%s' failed!\\n\",\n                   world_index, role == FER_ANY ? \"any\" : (role == FER_MASTER ? \"master\" : \"slave\") );\n          ret = DR_INIT;\n          goto error;\n     }\n\n     D_DEBUG_AT( Fusion_Main, \"  -> Fusion ID 0x%08lx\\n\", id );\n\n     if (id == FUSION_ID_MASTER) {\n          DirectFile shared_fd;\n\n          snprintf( buf, sizeof(buf), \"%s/fusion.%d.core\", fusion_config->tmpfs ?: \"/dev/shm\", world_index );\n\n          /* Open shared memory file. */\n          ret = direct_file_open( &shared_fd, buf, O_RDWR | O_CREAT | O_TRUNC, 0660 );\n          if (ret) {\n               D_DERROR( ret, \"Fusion/Main: Could not open shared memory file '%s'!\\n\", buf );\n               ret = DR_INIT;\n               goto error;\n          }\n\n          if (fusion_config->shmfile_gid != -1) {\n               if (direct_file_chown( &shared_fd, -1, fusion_config->shmfile_gid ))\n                    D_INFO( \"Fusion/Main: Changing owner on '%s' failed... continuing on\\n\", buf );\n          }\n\n          direct_file_chmod( &shared_fd, 0660 );\n          direct_file_truncate( &shared_fd, sizeof(FusionWorldShared) );\n\n          unsigned long size = direct_page_align( sizeof(FusionWorldShared) );\n          unsigned long base = (unsigned long) 0x20000000 + (size + direct_pagesize()) * world_index;\n\n          /* Map shared area. */\n          ret = direct_file_map( &shared_fd, (void*) base, 0, size, DFP_READ | DFP_WRITE, (void**) &shared );\n          if (ret) {\n               D_DERROR( ret, \"Fusion/Main: Mapping shared area failed!\\n\" );\n               direct_file_close( &shared_fd );\n               ret = DR_INIT;\n               goto error;\n          }\n\n          direct_file_close( &shared_fd );\n\n          D_DEBUG_AT( Fusion_Main, \"  -> shared area at %p, size \"_ZU\"\\n\", shared, sizeof(FusionWorldShared) );\n\n          /* Initialize reference counter. */\n          shared->refs = 1;\n\n          /* Set ABI version. */\n          shared->world_abi = abi_version;\n\n          /* Set the world index. */\n          shared->world_index = world_index;\n\n          /* Set pool allocation base/max. */\n          shared->pool_base = (void*) 0x20000000 + (size + direct_pagesize())*FUSION_MAX_WORLDS + 0x8000000*world_index;\n          shared->pool_max  = shared->pool_base + 0x8000000 - 1;\n\n          /* Set start time of world clock. */\n          shared->start_time = direct_clock_get_time( DIRECT_CLOCK_SESSION );\n\n          D_MAGIC_SET( shared, FusionWorldShared );\n     }\n     else {\n          FusionEnter enter;\n          DirectFile  shared_fd;\n\n          /* Fill enter information. */\n          enter.type      = FMT_ENTER;\n          enter.fusion_id = id;\n\n          snprintf( addr.sun_path, sizeof(addr.sun_path), \"/tmp/.fusion-%d/%lx\",\n                    world_index, (unsigned long) FUSION_ID_MASTER );\n\n          /* Send enter message (used to sync with the master). */\n          ret = _fusion_send_message( fd, &enter, sizeof(FusionEnter), &addr );\n          if (ret == DR_DESTROYED) {\n               DirectDir   dir;\n               DirectEntry entry;\n\n               D_DEBUG_AT( Fusion_Main, \"  -> master seems dead, cleaning up...\\n\" );\n\n               snprintf( addr.sun_path, sizeof(addr.sun_path), \"/tmp/.fusion-%d\", world_index );\n\n               ret = direct_dir_open( &dir, addr.sun_path );\n               if (ret) {\n                    D_DERROR( ret, \"Fusion/Main: Error opening directory '%s' for cleanup!\\n\", addr.sun_path );\n\n                    /* Unbind. */\n                    socklen_t addrlen = sizeof(addr);\n                    if (getsockname( fd, (struct sockaddr*) &addr, &addrlen ) == 0)\n                         direct_unlink( addr.sun_path );\n\n                    close( fd );\n\n                    ret = DR_INIT;\n                    goto error;\n               }\n\n               while (direct_dir_read( &dir, &entry ) == DR_OK) {\n                    if (!strcmp( entry.name, \".\" ) || !strcmp( entry.name, \"..\" ))\n                         continue;\n\n                    /* sizeof(addr.sun_path) = 108 */\n                    snprintf( addr.sun_path, sizeof(addr.sun_path), \"/tmp/.fusion-%d/%.83s\", world_index, entry.name );\n\n                    D_DEBUG_AT( Fusion_Main, \"  -> removing '%s'\\n\", addr.sun_path );\n\n                    ret = direct_unlink( addr.sun_path );\n                    if (ret) {\n                         D_DERROR( ret, \"Fusion/Main: Error deleting '%s' for cleanup!\\n\", addr.sun_path );\n                         direct_dir_close( &dir );\n\n                         /* Unbind. */\n                         socklen_t addrlen = sizeof(addr);\n                         if (getsockname( fd, (struct sockaddr*) &addr, &addrlen ) == 0)\n                              direct_unlink( addr.sun_path );\n\n                         close( fd );\n\n                         ret = DR_ACCESSDENIED;\n                         goto error;\n                    }\n               }\n\n               direct_dir_close( &dir );\n\n               /* Unbind. */\n               socklen_t addrlen = sizeof(addr);\n               if (getsockname( fd, (struct sockaddr*) &addr, &addrlen ) == 0)\n                    direct_unlink( addr.sun_path );\n\n               close( fd );\n\n               D_DEBUG_AT( Fusion_Main, \"  -> retrying...\\n\" );\n               goto retry;\n          }\n\n          if (ret)\n               D_DERROR( ret, \"Fusion/Main: Send message failed!\\n\" );\n\n          if (ret == DR_OK) {\n               ret = _fusion_recv_message( fd, &enter, sizeof(FusionEnter), NULL );\n               if (ret)\n                    D_DERROR( ret, \"Fusion/Main: Receive message failed!\\n\" );\n               if (ret == DR_OK && enter.type != FMT_ENTER) {\n                    D_ERROR( \"Fusion/Main: Expected message ENTER, got '%u'!\\n\", enter.type );\n                    ret = DR_FUSION;\n               }\n          }\n\n          if (ret) {\n               D_ERROR( \"Fusion/Main: Could not enter world '%d'!\\n\", world_index );\n               goto error;\n          }\n\n          snprintf( buf, sizeof(buf), \"%s/fusion.%d.core\", fusion_config->tmpfs ?: \"/dev/shm\", world_index );\n\n          /* Open shared memory file. */\n          ret = direct_file_open( &shared_fd, buf, O_RDWR, 0 );\n          if (ret) {\n               D_DERROR( ret, \"Fusion/Main: Could not open shared memory file '%s'!\\n\", buf );\n               ret = DR_INIT;\n               goto error;\n          }\n\n          unsigned long size = direct_page_align( sizeof(FusionWorldShared) );\n          unsigned long base = (unsigned long) 0x20000000 + (size + direct_pagesize()) * world_index;\n\n          /* Map shared area. */\n          ret = direct_file_map( &shared_fd, (void*) base, 0, size, DFP_READ | DFP_WRITE, (void**) &shared );\n          if (ret) {\n               D_DERROR( ret, \"Fusion/Main: Mapping shared area failed!\\n\" );\n               direct_file_close( &shared_fd );\n               ret = DR_INIT;\n               goto error;\n          }\n\n          direct_file_close( &shared_fd );\n\n          D_DEBUG_AT( Fusion_Main, \"  -> shared area at %p, size \"_ZU\"\\n\", shared, sizeof(FusionWorldShared) );\n\n          D_MAGIC_ASSERT( shared, FusionWorldShared );\n\n          /* Check ABI version. */\n          if (shared->world_abi != abi_version) {\n               D_ERROR( \"Fusion/Main: World ABI (%d) doesn't match own (%d)!\\n\",\n                        shared->world_abi, abi_version );\n               ret = DR_VERSIONMISMATCH;\n               goto error;\n          }\n     }\n\n     /* Synchronize to world clock. */\n     direct_clock_set_time( DIRECT_CLOCK_SESSION, shared->start_time );\n\n     /* Allocate local data. */\n     world = D_CALLOC( 1, sizeof(FusionWorld) );\n     if (!world) {\n          ret = D_OOM();\n          goto error;\n     }\n\n     /* Initialize local data. */\n     world->refs      = 1;\n     world->shared    = shared;\n     world->fusion_fd = fd;\n     world->fusion_id = id;\n\n     D_MAGIC_SET( world, FusionWorld );\n\n     fusion_worlds[world_index] = world;\n\n     /* Initialize shared memory part. */\n     ret = fusion_shm_init( world );\n     if (ret)\n          goto error2;\n\n     D_DEBUG_AT( Fusion_Main, \"  -> initializing other parts...\\n\" );\n\n     direct_mutex_init( &world->refs_lock );\n\n     /* Initialize other parts. */\n     if (world->fusion_id == FUSION_ID_MASTER) {\n          fusion_skirmish_init( &shared->arenas_lock, \"Fusion Arenas\", world );\n          fusion_skirmish_init( &shared->reactor_globals, \"Fusion Reactor Globals\", world );\n          fusion_skirmish_init( &shared->fusionees_lock, \"Fusionees\", world );\n\n          /* Create the main pool. */\n          ret = fusion_shm_pool_create( world, \"Fusion Main Pool\", 0x100000,\n                                        fusion_config->debugshm, &shared->main_pool );\n          if (ret)\n               goto error3;\n\n          fusion_hash_create( shared->main_pool, HASH_INT, HASH_PTR, 109, &shared->call_hash );\n\n          fusion_call_init( &shared->refs_call, world_refs_call, world, world );\n          fusion_call_set_name( &shared->refs_call, \"world_refs\" );\n          fusion_call_add_permissions( &shared->refs_call, 0, FUSION_CALL_PERMIT_EXECUTE );\n\n          direct_map_create( 37, refs_map_compare, refs_map_hash, world, &world->refs_map );\n     }\n     else {\n          direct_map_create( 37, refs_map_slave_compare, refs_map_slave_hash, world, &world->refs_map );\n     }\n\n     /* Add ourselves to the list of fusionees. */\n     ret = _fusion_add_fusionee( world, id );\n     if (ret)\n          goto error4;\n\n     D_DEBUG_AT( Fusion_Main, \"  -> starting dispatcher loop...\\n\" );\n\n     /* Start the dispatcher thread. */\n     world->dispatch_loop = direct_thread_create( DTT_MESSAGING, fusion_dispatch_loop, world, \"Fusion Dispatch\" );\n     if (!world->dispatch_loop) {\n          ret = DR_FAILURE;\n          goto error5;\n     }\n\n     D_DEBUG_AT( Fusion_Main, \"  -> done (%p)\\n\", world );\n\n     direct_mutex_unlock( &fusion_worlds_lock );\n\n     /* Return the fusion world. */\n     *ret_world = world;\n\n     return DR_OK;\n\nerror5:\n     if (world->dispatch_loop)\n          direct_thread_destroy( world->dispatch_loop );\n\n     _fusion_remove_fusionee( world, id );\n\nerror4:\n     if (world->fusion_id == FUSION_ID_MASTER)\n          fusion_shm_pool_destroy( world, shared->main_pool );\n\nerror3:\n     if (world->fusion_id == FUSION_ID_MASTER) {\n          fusion_skirmish_destroy( &shared->arenas_lock );\n          fusion_skirmish_destroy( &shared->reactor_globals );\n          fusion_skirmish_destroy( &shared->fusionees_lock );\n     }\n\n     fusion_shm_deinit( world );\n\nerror2:\n     fusion_worlds[world_index] = world;\n\n     D_MAGIC_CLEAR( world );\n\n     D_FREE( world );\n\nerror:\n     if (shared != MAP_FAILED) {\n          if (id == FUSION_ID_MASTER)\n               D_MAGIC_CLEAR( shared );\n\n          direct_file_unmap( shared, sizeof(FusionWorldShared) );\n     }\n\n     if (fd != -1) {\n          /* Unbind. */\n          socklen_t addrlen = sizeof(addr);\n          if (getsockname( fd, (struct sockaddr*) &addr, &addrlen ) == 0)\n               direct_unlink( addr.sun_path );\n\n          close( fd );\n     }\n\n     direct_mutex_unlock( &fusion_worlds_lock );\n\n     direct_shutdown();\n\n     return ret;\n}\n\nDirectResult\nfusion_world_activate( FusionWorld *world )\n{\n     return DR_OK;\n}\n\nDirectResult\nfusion_stop_dispatcher( FusionWorld *world,\n                        bool         emergency )\n{\n     if (!world->dispatch_loop)\n          return DR_OK;\n\n     if (!emergency) {\n          fusion_sync( world );\n\n          direct_thread_lock( world->dispatch_loop );\n     }\n\n     world->dispatch_stop = true;\n\n     if (!emergency) {\n          direct_thread_unlock( world->dispatch_loop );\n\n          fusion_sync( world );\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_exit( FusionWorld *world,\n             bool         emergency )\n{\n     DirectResult ret;\n     int          world_index;\n     bool         clear = false;\n\n     D_DEBUG_AT( Fusion_Main, \"%s( %p, %semergency )\\n\", __FUNCTION__, world, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n     D_ASSERT( world->refs > 0 );\n\n     world_index = world->shared->world_index;\n\n     direct_mutex_lock( &fusion_worlds_lock );\n\n     if (--world->refs) {\n          direct_mutex_unlock( &fusion_worlds_lock );\n          return DR_OK;\n     }\n\n     if (!emergency) {\n          FusionMessageType msg = FMT_SEND;\n\n          /* Wakeup dispatcher. */\n          if (_fusion_send_message( world->fusion_fd, &msg, sizeof(msg), NULL ))\n               direct_thread_cancel( world->dispatch_loop );\n\n          /* Wait for its termination. */\n          direct_thread_join( world->dispatch_loop );\n     }\n\n     direct_thread_destroy( world->dispatch_loop );\n\n     /* Remove ourselves from list. */\n     if (!emergency || fusion_master( world )) {\n          _fusion_remove_fusionee( world, world->fusion_id );\n     }\n     else {\n          struct sockaddr_un addr;\n          FusionLeave        leave;\n\n          addr.sun_family = AF_UNIX;\n          snprintf( addr.sun_path, sizeof(addr.sun_path), \"/tmp/.fusion-%d/%lx\",\n                    world_index, (unsigned long) FUSION_ID_MASTER );\n\n          leave.type      = FMT_LEAVE;\n          leave.fusion_id = world->fusion_id;\n\n          _fusion_send_message( world->fusion_fd, &leave, sizeof(FusionLeave), &addr );\n     }\n\n     direct_mutex_deinit( &world->refs_lock );\n     direct_map_destroy( world->refs_map );\n\n     /* Master has to deinitialize shared data. */\n     if (fusion_master( world )) {\n          fusion_call_destroy( &world->shared->refs_call );\n\n          fusion_hash_destroy( world->shared->call_hash );\n\n          world->shared->refs--;\n          if (world->shared->refs == 0) {\n               fusion_skirmish_destroy( &world->shared->reactor_globals );\n               fusion_skirmish_destroy( &world->shared->arenas_lock );\n               fusion_skirmish_destroy( &world->shared->fusionees_lock );\n\n               fusion_shm_pool_destroy( world, world->shared->main_pool );\n\n               /* Deinitialize shared memory. */\n               fusion_shm_deinit( world );\n\n               clear = true;\n          }\n     }\n     else {\n          /* Leave shared memory. */\n          fusion_shm_deinit( world );\n     }\n\n     /* Reset local dispatch nodes. */\n     _fusion_reactor_free_all( world );\n\n     /* Remove world from global list. */\n     fusion_worlds[world->shared->world_index] = NULL;\n\n     /* Unmap shared area. */\n     if (clear)\n          D_MAGIC_CLEAR( world->shared );\n\n     direct_file_unmap( world->shared, sizeof(FusionWorldShared) );\n\n     /* Close socket. */\n     close( world->fusion_fd );\n\n     if (clear) {\n          DirectDir dir;\n          char      buf[128];\n          int       len;\n\n          /* Remove core shmfile. */\n          snprintf( buf, sizeof(buf), \"%s/fusion.%d.core\", fusion_config->tmpfs ?: \"/dev/shm\", world_index );\n          D_DEBUG_AT( Fusion_Main, \"  -> removing shmfile %s\\n\", buf );\n          direct_unlink( buf );\n\n          /* Cleanup socket directory. */\n          len = snprintf( buf, sizeof(buf), \"/tmp/.fusion-%d/\", world_index );\n          ret = direct_dir_open( &dir, buf );\n          if (ret == DR_OK) {\n               DirectEntry entry;\n\n               while (direct_dir_read( &dir, &entry ) == DR_OK) {\n                    if (entry.name[0] != '.') {\n                         struct stat st;\n\n                         direct_snputs( buf + len, entry.name, sizeof(buf) - len );\n                         if (stat( buf, &st ) == 0 && S_ISSOCK(st.st_mode)) {\n                              D_DEBUG_AT( Fusion_Main, \"  -> removing socket %s\\n\", buf );\n                              direct_unlink( buf );\n                         }\n                    }\n               }\n\n               direct_dir_close( &dir );\n          }\n          else {\n               D_DERROR( ret, \"Fusion/Main: Could not open socket directory %s\", buf );\n          }\n     }\n\n     /* Free local world data. */\n     D_MAGIC_CLEAR( world );\n     D_FREE( world );\n\n     D_DEBUG_AT( Fusion_Main, \"%s( %p ) done\\n\", __FUNCTION__, world );\n\n     direct_mutex_unlock( &fusion_worlds_lock );\n\n     direct_shutdown();\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_kill( FusionWorld *world,\n             FusionID     fusion_id,\n             int          signal,\n             int          timeout_ms )\n{\n     DirectResult  ret;\n     Fusionee     *fusionee, *next;\n\n     D_DEBUG_AT( Fusion_Main, \"%s( %p, %lu, %d, %d )\\n\", __FUNCTION__, world, fusion_id, signal, timeout_ms );\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     fusion_skirmish_prevail( &world->shared->fusionees_lock );\n\n     direct_list_foreach_safe (fusionee, next, world->shared->fusionees) {\n          if (fusion_id == 0 && fusionee->id == world->fusion_id)\n               continue;\n\n          if (fusion_id != 0 && fusionee->id != fusion_id)\n               continue;\n\n          D_DEBUG_AT( Fusion_Main, \"  -> killing fusionee %lu (%d)...\\n\", fusionee->id, fusionee->pid );\n\n          ret = direct_kill( fusionee->pid, signal );\n          if (ret == DR_OK && timeout_ms >= 0) {\n               pid_t     pid  = fusionee->pid;\n               long long stop = timeout_ms ? (direct_clock_get_micros() + timeout_ms*1000) : 0;\n\n               fusion_skirmish_dismiss( &world->shared->fusionees_lock );\n\n               while (direct_kill( pid, 0 ) == 0) {\n                    usleep( 1000 );\n\n                    if (timeout_ms && direct_clock_get_micros() >= stop)\n                         break;\n               };\n\n               fusion_skirmish_prevail( &world->shared->fusionees_lock );\n          }\n          else {\n               if (ret == DR_NOSUCHINSTANCE) {\n                    D_DEBUG_AT( Fusion_Main, \" ... fusionee %lu exited without removing itself\\n\", fusionee->id );\n\n                    _fusion_remove_fusionee( world, fusionee->id );\n               }\n               else {\n                    D_DERROR( ret, \"Fusion/Main: direct_kill( %d, %d ) failed!\\n\", fusionee->pid, signal );\n               }\n          }\n     }\n\n     fusion_skirmish_dismiss( &world->shared->fusionees_lock );\n\n     return DR_OK;\n}\n\nconst char *\nfusion_get_tmpfs( FusionWorld *world )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     return \"/tmp\";\n}\n\nDirectResult\nfusion_dispatch_cleanup_add( FusionWorld                *world,\n                             FusionDispatchCleanupFunc   func,\n                             void                       *ctx,\n                             FusionDispatchCleanup     **ret_cleanup )\n{\n     FusionDispatchCleanup *cleanup;\n\n     cleanup = D_CALLOC( 1, sizeof(FusionDispatchCleanup) );\n     if (!cleanup)\n          return D_OOM();\n\n     cleanup->func = func;\n     cleanup->ctx  = ctx;\n\n     direct_list_append( &world->dispatch_cleanups, &cleanup->link );\n\n     *ret_cleanup = cleanup;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_dispatch_cleanup_remove( FusionWorld           *world,\n                                FusionDispatchCleanup *cleanup )\n{\n     direct_list_remove( &world->dispatch_cleanups, &cleanup->link );\n\n     D_FREE( cleanup );\n\n     return DR_OK;\n}\n\nstatic void\nhandle_dispatch_cleanups( FusionWorld *world )\n{\n     FusionDispatchCleanup *cleanup, *next;\n\n     D_DEBUG_AT( Fusion_Main_Dispatch, \"%s( %p )\\n\", __FUNCTION__, world );\n\n     direct_list_foreach_safe (cleanup, next, world->dispatch_cleanups) {\n          if (direct_log_domain_check( &Fusion_Main_Dispatch ))\n               D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> %s (%p)\\n\",\n                           direct_trace_lookup_symbol_at( cleanup->func ), cleanup->ctx );\n\n          cleanup->func( cleanup->ctx );\n\n          D_FREE( cleanup );\n     }\n\n     D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> cleanups done\\n\" );\n\n     world->dispatch_cleanups = NULL;\n}\n\nstatic DirectEnumerationResult\nrefs_iterate( DirectMap *map,\n              void      *object,\n              void      *ctx )\n{\n     FusionRefSlaveEntry *entry = object;\n\n     if (entry->key.fusion_id == *((FusionID*) ctx)) {\n          int i;\n\n          for (i = 0; i < entry->refs; i++)\n               fusion_ref_down( entry->ref, false );\n\n          D_FREE( entry );\n\n          return DENUM_REMOVE;\n     }\n\n     return DENUM_OK;\n}\n\nstatic void *\nfusion_dispatch_loop( DirectThread *self,\n                      void         *arg )\n{\n     FusionWorld        *world = arg;\n     struct sockaddr_un  addr;\n     socklen_t           addrlen = sizeof(addr);\n     fd_set              set;\n     char                buf[FUSION_MESSAGE_SIZE];\n\n     D_DEBUG_AT( Fusion_Main_Dispatch, \"%s() running...\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     while (true) {\n          int     err;\n          ssize_t msg_size;\n\n          FD_ZERO( &set );\n          FD_SET( world->fusion_fd, &set );\n\n          err = select( world->fusion_fd + 1, &set, NULL, NULL, NULL );\n          if (err < 0) {\n               switch (errno) {\n                    case EINTR:\n                         continue;\n\n                    default:\n                         D_PERROR( \"Fusion/Main: select() failed!\\n\" );\n                         return NULL;\n               }\n          }\n\n          if (FD_ISSET( world->fusion_fd, &set ) &&\n              (msg_size = recvfrom( world->fusion_fd, buf, sizeof(buf), 0, (struct sockaddr*) &addr, &addrlen )) > 0) {\n               FusionMessage *msg = (FusionMessage*) buf;\n\n               direct_thread_setcancelstate( DIRECT_THREAD_CANCEL_DISABLE );\n\n               D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> message from '%s'...\\n\", addr.sun_path );\n\n               direct_thread_lock( self );\n\n               if (world->dispatch_stop) {\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> ignoring (dispatch_stop)\\n\" );\n               }\n               else {\n                    switch (msg->type) {\n                         case FMT_SEND:\n                              D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_SEND!\\n\" );\n                              break;\n\n                         case FMT_ENTER:\n                              D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_ENTER...\\n\" );\n\n                              if (!fusion_master( world )) {\n                                   D_ERROR( \"Fusion/Main/Dispatch: Got ENTER request, but we are not master!\\n\" );\n                                   break;\n                              }\n\n                              if (msg->enter.fusion_id == world->fusion_id) {\n                                   D_ERROR( \"Fusion/Main/Dispatch: ENTER request received from ourselves!\\n\" );\n                                   break;\n                              }\n\n                              _fusion_send_message( world->fusion_fd, msg, sizeof(FusionEnter), &addr );\n                              break;\n\n                         case FMT_LEAVE:\n                              D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_LEAVE...\\n\" );\n\n                              if (!fusion_master( world )) {\n                                   D_ERROR( \"Fusion/Main/Dispatch: Got LEAVE request, but we are not master!\\n\" );\n                                   break;\n                              }\n\n                              if (world->fusion_id == FUSION_ID_MASTER) {\n                                   direct_mutex_lock( &world->refs_lock );\n                                   direct_map_iterate( world->refs_map, refs_iterate, &msg->leave.fusion_id );\n                                   direct_mutex_unlock( &world->refs_lock );\n                              }\n\n                              if (msg->leave.fusion_id == world->fusion_id) {\n                                   D_ERROR( \"Fusion/Main/Dispatch: LEAVE request received from ourselves!\\n\" );\n                                   break;\n                              }\n\n                              _fusion_remove_fusionee( world, msg->leave.fusion_id );\n                              break;\n\n                         case FMT_CALL:\n                              D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_CALL...\\n\" );\n\n                              if (((FusionCallMessage*) msg)->caller == 0)\n                                   handle_dispatch_cleanups( world );\n\n                              _fusion_call_process( world, msg->call.call_id, &msg->call,\n                                                    (msg_size != sizeof(FusionCallMessage)) ?\n                                                    (((FusionCallMessage*) msg) + 1) : NULL );\n                              break;\n\n                         case FMT_REACTOR:\n                              D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> FMT_REACTOR...\\n\" );\n\n                              _fusion_reactor_process_message( world, msg->reactor.id, msg->reactor.channel,\n                                                               &buf[sizeof(FusionReactorMessage)] );\n\n                              if (msg->reactor.ref) {\n                                   fusion_ref_down( msg->reactor.ref, true );\n                                   if (fusion_ref_zero_trylock( msg->reactor.ref ) == DR_OK) {\n                                        fusion_ref_destroy( msg->reactor.ref );\n                                        SHFREE( world->shared->main_pool, msg->reactor.ref );\n                                   }\n                              }\n                              break;\n\n                         default:\n                              D_BUG( \"unexpected message type %u\", msg->type );\n                              break;\n                    }\n               }\n\n               handle_dispatch_cleanups( world );\n\n               direct_thread_unlock( self );\n\n               if (!world->refs) {\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> good bye!\\n\" );\n                    return NULL;\n               }\n\n               D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> done\\n\" );\n\n               direct_thread_setcancelstate( DIRECT_THREAD_CANCEL_ENABLE );\n          }\n     }\n\n     return NULL;\n}\n\nDirectResult\nfusion_dispatch( FusionWorld *world,\n                 size_t       buf_size )\n{\n     return DR_OK;\n}\n\nDirectResult\nfusion_get_fusionee_path( const FusionWorld *world,\n                          FusionID           fusion_id,\n                          char              *buf,\n                          size_t             buf_size,\n                          size_t            *ret_size )\n{\n     D_ASSERT( world != NULL );\n     D_ASSERT( buf != NULL );\n     D_ASSERT( ret_size != NULL );\n\n     *buf = '\\0';\n     *ret_size = 0;\n\n     return DR_UNIMPLEMENTED;\n}\n\nDirectResult\nfusion_get_fusionee_pid( const FusionWorld *world,\n                         FusionID           fusion_id,\n                         pid_t             *ret_pid )\n{\n     D_ASSERT( world != NULL );\n\n     return DR_UNIMPLEMENTED;\n}\n\nDirectResult\nfusion_world_set_root( FusionWorld *world,\n                       void        *root )\n{\n     D_ASSERT( world != NULL );\n     D_ASSERT( world->shared != NULL );\n\n     if (world->fusion_id != FUSION_ID_MASTER)\n          return DR_ACCESSDENIED;\n\n     world->shared->world_root = root;\n\n     return DR_OK;\n}\n\nvoid *\nfusion_world_get_root( FusionWorld *world )\n{\n     D_ASSERT( world != NULL );\n     D_ASSERT( world->shared != NULL );\n\n     return world->shared->world_root;\n}\n\nDirectResult\nfusion_sync( const FusionWorld *world )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     D_DEBUG_AT( Fusion_Main, \"%s( %p )\\n\", __FUNCTION__, world );\n\n     D_DEBUG_AT( Fusion_Main, \"  -> syncing with fusion device...\\n\" );\n\n     D_DEBUG_AT( Fusion_Main, \"  -> synced\\n\" );\n\n     return DR_OK;\n}\n\n#endif /* FUSION_BUILD_KERNEL */\n\nvoid\nfusion_world_set_fork_action( FusionWorld      *world,\n                              FusionForkAction  action )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     world->fork_action = action;\n}\n\nFusionForkAction\nfusion_world_get_fork_action( FusionWorld *world )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     return world->fork_action;\n}\n\nvoid\nfusion_world_set_fork_callback( FusionWorld        *world,\n                                FusionForkCallback  callback )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     world->fork_callback = callback;\n}\n\nvoid\nfusion_world_set_leave_callback( FusionWorld         *world,\n                                 FusionLeaveCallback  callback,\n                                 void                *ctx )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     world->leave_callback = callback;\n     world->leave_ctx      = ctx;\n}\n\nint\nfusion_world_index( const FusionWorld *world )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     return world->shared->world_index;\n}\n\nFusionID\nfusion_id( const FusionWorld *world )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     return world->fusion_id;\n}\n\nbool\nfusion_is_multi( const FusionWorld *world )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     return true;\n}\n\npid_t\nfusion_dispatcher_tid( const FusionWorld *world )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     if (world->dispatch_loop)\n          return direct_thread_get_tid( world->dispatch_loop );\n\n     return 0;\n}\n\nbool\nfusion_master( const FusionWorld *world )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     return world->fusion_id == FUSION_ID_MASTER;\n}\n\nbool\nfusion_is_shared( FusionWorld *world,\n                  const void  *ptr )\n{\n     int           i;\n     DirectResult  ret;\n     FusionSHM    *shm;\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     shm = &world->shm;\n\n     D_MAGIC_ASSERT( shm, FusionSHM );\n     D_MAGIC_ASSERT( shm->shared, FusionSHMShared );\n\n     if (ptr >= (void*) world->shared && ptr < (void*) world->shared + sizeof(FusionWorldShared))\n          return true;\n\n     ret = fusion_skirmish_prevail( &shm->shared->lock );\n     if (ret)\n          return false;\n\n     for (i = 0; i < FUSION_SHM_MAX_POOLS; i++) {\n          if (shm->shared->pools[i].active) {\n               FusionSHMPoolShared *pool = &shm->shared->pools[i];\n               shmalloc_heap       *heap;\n\n               D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n               D_MAGIC_ASSERT( pool->heap, shmalloc_heap );\n\n               heap = pool->heap;\n\n               if (ptr >= pool->addr_base && ptr < pool->addr_base + heap->size) {\n                    fusion_skirmish_dismiss( &shm->shared->lock );\n                    return true;\n               }\n          }\n     }\n\n     fusion_skirmish_dismiss( &shm->shared->lock );\n\n     return false;\n}\n\n#else /* FUSION_BUILD_MULTI */\n\nstatic void *\nevent_dispatcher_loop( DirectThread *thread,\n                       void         *arg )\n{\n     const int    call_size = sizeof(FusionEventDispatcherCall);\n     FusionWorld *world     = arg;\n\n     D_DEBUG_AT( Fusion_Main_Dispatch, \"%s() running...\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     while (1) {\n          FusionEventDispatcherBuffer *buf;\n\n          direct_mutex_lock( &world->event_dispatcher_mutex );\n\n          while (1) {\n               if (!world->event_dispatcher_buffers)\n                    direct_waitqueue_wait( &world->event_dispatcher_cond, &world->event_dispatcher_mutex );\n\n               buf = (FusionEventDispatcherBuffer*) world->event_dispatcher_buffers;\n\n               D_MAGIC_ASSERT( buf, FusionEventDispatcherBuffer );\n\n               if (buf->can_free && buf->read_pos == buf->write_pos) {\n                    direct_list_remove( &world->event_dispatcher_buffers, &buf->link );\n                    direct_list_append( &world->event_dispatcher_buffers_remove, &buf->link );\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"Remove buffer %p free %d read %d write %d sync %d pending %d\\n\",\n                                buf, buf->can_free, buf->read_pos, buf->write_pos, buf->sync_calls, buf->pending );\n                    continue;\n               }\n\n               if (buf->read_pos >= buf->write_pos) {\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"Waiting buffer %p free %d read %d write %d sync %d pending %d\\n\",\n                                buf, buf->can_free, buf->read_pos, buf->write_pos, buf->sync_calls, buf->pending );\n                    direct_waitqueue_wait( &world->event_dispatcher_cond, &world->event_dispatcher_mutex );\n               }\n\n               buf = (FusionEventDispatcherBuffer*) world->event_dispatcher_buffers;\n\n               D_MAGIC_ASSERT( buf, FusionEventDispatcherBuffer );\n\n               if (buf->can_free && buf->read_pos == buf->write_pos) {\n                    direct_list_remove( &world->event_dispatcher_buffers, &buf->link );\n                    direct_list_append( &world->event_dispatcher_buffers_remove, &buf->link );\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"Remove buffer %p free %d read %d write %d sync %d pending %d\\n\",\n                                buf, buf->can_free, buf->read_pos, buf->write_pos, buf->sync_calls, buf->pending );\n                    continue;\n               }\n               break;\n          }\n\n          FusionEventDispatcherCall *msg = (FusionEventDispatcherCall*) &buf->buffer[buf->read_pos];\n\n          D_DEBUG_AT( Fusion_Main_Dispatch, \"%s() got msg %p <- arg %d, reaction %d\\n\", __FUNCTION__,\n                      msg, msg->call_arg, msg->reaction );\n          D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> processing buffer %p free %d read %d write %d sync %d pending %d\\n\",\n                      buf, buf->can_free, buf->read_pos, buf->write_pos, buf->sync_calls, buf->pending );\n\n          buf->read_pos += call_size;\n          if (msg->flags & FCEF_ONEWAY)\n               buf->read_pos += msg->length;\n\n          /* Align on 4-byte boundaries. */\n          buf->read_pos = (buf->read_pos + 3) & ~3;\n\n          if (world->dispatch_stop) {\n               D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> ignoring (dispatch_stop)\\n\" );\n\n               FusionEventDispatcherBuffer *next;\n\n               direct_list_foreach_safe (buf, next, world->event_dispatcher_buffers) {\n                    D_MAGIC_CLEAR( buf );\n                    D_FREE( buf );\n               }\n\n               direct_mutex_unlock( &world->event_dispatcher_mutex );\n               break;\n          }\n          else {\n               direct_mutex_unlock( &world->event_dispatcher_mutex );\n\n               if (msg->call_handler3) {\n                    if (FCHR_RETAIN == msg->call_handler3( 1, msg->call_arg, msg->ptr, msg->length, msg->call_ctx, 0,\n                                                           msg->ret_ptr, msg->ret_size, &msg->ret_length ))\n                         D_WARN( \"fusion dispatch => FCHR_RETAIN\\n\" );\n               }\n               else if (msg->call_handler) {\n                    if (FCHR_RETAIN == msg->call_handler( 1, msg->call_arg, msg->ptr, msg->call_ctx, 0, &msg->ret_val ))\n                         D_WARN( \"fusion dispatch => FCHR_RETAIN\\n\" );\n               }\n               else if (msg->reaction == 1) {\n                    FusionReactor *reactor = msg->call_ctx;\n                    Reaction      *reaction, *next;\n\n                    D_MAGIC_ASSERT( reactor, FusionReactor );\n\n                    direct_mutex_lock( &reactor->reactions_lock );\n\n                    direct_list_foreach_safe (reaction, next, reactor->reactions) {\n                         if ((long) reaction->node_link == msg->call_arg) {\n                              if (RS_REMOVE == reaction->func( msg->ptr, reaction->ctx ))\n                                   direct_list_remove( &reactor->reactions, &reaction->link );\n                         }\n                    }\n\n                    direct_mutex_unlock( &reactor->reactions_lock );\n               }\n               else if (msg->reaction == 2) {\n                    FusionReactor *reactor = msg->call_ctx;\n\n                    fusion_reactor_free( reactor );\n               }\n               else {\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> good bye!\\n\" );\n                    return NULL;\n               }\n\n               if (!(msg->flags & FCEF_ONEWAY)) {\n                    direct_mutex_lock( &world->event_dispatcher_call_mutex );\n\n                    msg->processed = 1;\n\n                    direct_waitqueue_broadcast( &world->event_dispatcher_call_cond );\n\n                    direct_mutex_unlock( &world->event_dispatcher_call_mutex );\n               }\n\n               direct_mutex_lock( &world->event_dispatcher_mutex );\n\n               buf->pending--;\n          }\n\n          direct_waitqueue_signal( &world->event_dispatcher_process_cond );\n\n          if (world->event_dispatcher_buffers_remove) {\n               buf = (FusionEventDispatcherBuffer*) world->event_dispatcher_buffers_remove;\n\n               D_MAGIC_ASSERT( buf, FusionEventDispatcherBuffer );\n\n               if (!buf->sync_calls && !buf->pending) {\n                    D_DEBUG_AT( Fusion_Main_Dispatch, \"Free buffer %p free %d read %d write %d sync %d pending %d\\n\\n\",\n                                buf, buf->can_free, buf->read_pos, buf->write_pos, buf->sync_calls, buf->pending );\n                    direct_list_remove( &world->event_dispatcher_buffers_remove, &buf->link );\n                    D_MAGIC_CLEAR( buf );\n                    D_FREE( buf );\n               }\n          }\n\n          direct_mutex_unlock( &world->event_dispatcher_mutex );\n\n          if (!world->refs) {\n               D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> good bye!\\n\" );\n               return NULL;\n          }\n     }\n\n     D_DEBUG_AT( Fusion_Main_Dispatch, \"  -> good bye!\\n\" );\n\n     return NULL;\n}\n\nDirectResult\n_fusion_event_dispatcher_process( FusionWorld                      *world,\n                                  const FusionEventDispatcherCall  *call,\n                                  FusionEventDispatcherCall       **ret )\n{\n     const int call_size = sizeof(FusionEventDispatcherCall);\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     direct_mutex_lock( &world->event_dispatcher_mutex );\n\n     if (world->dispatch_stop) {\n          direct_mutex_unlock( &world->event_dispatcher_mutex );\n          return DR_DESTROYED;\n     }\n\n     while (call->call_handler3 && (call->flags & FCEF_ONEWAY) &&\n            direct_list_count_elements_EXPENSIVE( world->event_dispatcher_buffers ) > 4) {\n          direct_waitqueue_wait( &world->event_dispatcher_process_cond, &world->event_dispatcher_mutex );\n     }\n\n     if (!world->event_dispatcher_buffers) {\n          FusionEventDispatcherBuffer *new_buf = D_CALLOC( 1, sizeof(FusionEventDispatcherBuffer) );\n          D_MAGIC_SET( new_buf, FusionEventDispatcherBuffer );\n          direct_list_append( &world->event_dispatcher_buffers, &new_buf->link );\n     }\n\n     FusionEventDispatcherBuffer *buf = direct_list_get_last( world->event_dispatcher_buffers );\n     if (!buf)\n          return DR_FAILURE;\n\n     D_MAGIC_ASSERT( buf, FusionEventDispatcherBuffer );\n\n     if (buf->write_pos + call_size + call->length > EVENT_DISPATCHER_BUFFER_LENGTH) {\n          buf->can_free = 1;\n          FusionEventDispatcherBuffer *new_buf = D_CALLOC( 1, sizeof(FusionEventDispatcherBuffer) );\n          D_MAGIC_SET( new_buf, FusionEventDispatcherBuffer );\n          direct_list_append( &world->event_dispatcher_buffers, &new_buf->link );\n          buf = new_buf;\n     }\n\n     *ret = (FusionEventDispatcherCall*) &buf->buffer[buf->write_pos];\n\n     /* Copy data and signal dispatcher. */\n     direct_memcpy( *ret, call, call_size );\n\n     buf->write_pos += call_size;\n\n     buf->pending++;\n\n     if (!(call->flags & FCEF_ONEWAY))\n          buf->sync_calls++;\n\n     /* Copy extra data to buffer. */\n     if (call->flags & FCEF_ONEWAY && call->length) {\n          (*ret)->ptr = &buf->buffer[buf->write_pos];\n          direct_memcpy( (*ret)->ptr, call->ptr, call->length );\n          buf->write_pos += call->length;\n     }\n\n     /* Align on 4-byte boundaries. */\n     buf->write_pos = (buf->write_pos + 3) & ~3;\n\n     direct_waitqueue_signal( &world->event_dispatcher_cond );\n\n     direct_mutex_unlock( &world->event_dispatcher_mutex );\n\n     if (!(call->flags & FCEF_ONEWAY)) {\n          direct_mutex_lock( &world->event_dispatcher_call_mutex );\n\n          while (!(*ret)->processed)\n               direct_waitqueue_wait( &world->event_dispatcher_call_cond, &world->event_dispatcher_call_mutex );\n\n          direct_mutex_unlock( &world->event_dispatcher_call_mutex );\n\n          direct_mutex_lock( &world->event_dispatcher_mutex );\n          buf->sync_calls--;\n          direct_mutex_unlock( &world->event_dispatcher_mutex );\n     }\n\n     return DR_OK;\n}\n\nDirectResult\n_fusion_event_dispatcher_process_reactions( FusionWorld   *world,\n                                            FusionReactor *reactor,\n                                            int            channel,\n                                            void          *msg_data,\n                                            int            msg_size )\n{\n     const int                  call_size = sizeof(FusionEventDispatcherCall);\n     FusionEventDispatcherCall  msg;\n     FusionEventDispatcherCall *res;\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     msg.processed = 0;\n     msg.reaction = 1;\n     msg.call_handler = 0;\n     msg.call_handler3 = 0;\n     msg.call_ctx = reactor;\n     msg.flags = FCEF_ONEWAY;\n     msg.call_arg = channel;\n     msg.ptr = msg_data;\n     msg.length = msg_size;\n     msg.ret_val = 0;\n     msg.ret_ptr = 0;\n     msg.ret_size = 0;\n     msg.ret_length = 0;\n\n     direct_mutex_lock( &world->event_dispatcher_mutex );\n\n     if (world->dispatch_stop) {\n          direct_mutex_unlock( &world->event_dispatcher_mutex );\n          return DR_DESTROYED;\n     }\n\n     if (!world->event_dispatcher_buffers) {\n          FusionEventDispatcherBuffer *new_buf = D_CALLOC( 1, sizeof(FusionEventDispatcherBuffer) );\n          D_MAGIC_SET( new_buf, FusionEventDispatcherBuffer );\n          direct_list_append( &world->event_dispatcher_buffers, &new_buf->link );\n     }\n\n     FusionEventDispatcherBuffer *buf = direct_list_get_last( world->event_dispatcher_buffers );\n     if (!buf)\n          return DR_FAILURE;\n\n     D_MAGIC_ASSERT( buf, FusionEventDispatcherBuffer );\n\n     if (buf->write_pos + call_size + msg_size > EVENT_DISPATCHER_BUFFER_LENGTH) {\n          buf->can_free = 1;\n          FusionEventDispatcherBuffer *new_buf = D_CALLOC( 1, sizeof(FusionEventDispatcherBuffer) );\n          D_MAGIC_SET( new_buf, FusionEventDispatcherBuffer );\n          direct_list_append( &world->event_dispatcher_buffers, &new_buf->link );\n          buf = new_buf;\n     }\n\n     res = (FusionEventDispatcherCall*) &buf->buffer[buf->write_pos];\n\n     /* Copy data and signal dispatcher. */\n     direct_memcpy( res, &msg, call_size );\n\n     buf->write_pos += call_size;\n\n     buf->pending++;\n\n     /* Copy extra data to buffer. */\n     if (msg.length) {\n          res->ptr = &buf->buffer[buf->write_pos];\n          direct_memcpy( res->ptr, msg.ptr, msg.length );\n          buf->write_pos += msg.length;\n     }\n\n     /* Align on 4-byte boundaries. */\n     buf->write_pos = (buf->write_pos + 3) & ~3;\n\n     direct_waitqueue_signal( &world->event_dispatcher_cond );\n\n     direct_mutex_unlock( &world->event_dispatcher_mutex );\n\n     return DR_OK;\n}\n\nDirectResult\n_fusion_event_dispatcher_process_reactor_free( FusionWorld   *world,\n                                               FusionReactor *reactor )\n{\n     const int                  call_size = sizeof(FusionEventDispatcherCall);\n     FusionEventDispatcherCall  msg;\n     FusionEventDispatcherCall *res;\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     if (reactor->free)\n          return DR_OK;\n\n     reactor->free = 1;\n\n     msg.processed = 0;\n     msg.reaction = 2;\n     msg.call_handler = 0;\n     msg.call_handler3 = 0;\n     msg.call_ctx = reactor;\n     msg.flags = FCEF_ONEWAY;\n     msg.call_arg = 0;\n     msg.ptr = 0;\n     msg.length = 0;\n     msg.ret_val = 0;\n     msg.ret_ptr = 0;\n     msg.ret_size = 0;\n     msg.ret_length = 0;\n\n     direct_mutex_lock( &world->event_dispatcher_mutex );\n\n     if (world->dispatch_stop) {\n          direct_mutex_unlock( &world->event_dispatcher_mutex );\n          return DR_DESTROYED;\n     }\n\n     if (!world->event_dispatcher_buffers) {\n          FusionEventDispatcherBuffer *new_buf = D_CALLOC( 1, sizeof(FusionEventDispatcherBuffer) );\n          D_MAGIC_SET( new_buf, FusionEventDispatcherBuffer );\n          direct_list_append( &world->event_dispatcher_buffers, &new_buf->link );\n     }\n\n     FusionEventDispatcherBuffer *buf = direct_list_get_last( world->event_dispatcher_buffers );\n     if (!buf)\n          return DR_FAILURE;\n\n     D_MAGIC_ASSERT( buf, FusionEventDispatcherBuffer );\n\n     if (buf->write_pos + call_size > EVENT_DISPATCHER_BUFFER_LENGTH) {\n          buf->can_free = 1;\n          FusionEventDispatcherBuffer *new_buf = D_CALLOC( 1, sizeof(FusionEventDispatcherBuffer) );\n          D_MAGIC_SET( new_buf, FusionEventDispatcherBuffer );\n          direct_list_append( &world->event_dispatcher_buffers, &new_buf->link );\n          buf = new_buf;\n     }\n\n     res = (FusionEventDispatcherCall*) &buf->buffer[buf->write_pos];\n\n     /* Copy data and signal dispatcher. */\n     direct_memcpy( res, &msg, call_size );\n\n     buf->write_pos += call_size;\n\n     buf->pending++;\n\n     /* Align on 4-byte boundaries. */\n     buf->write_pos = (buf->write_pos + 3) & ~3;\n\n     direct_waitqueue_signal( &world->event_dispatcher_cond );\n\n     direct_mutex_unlock( &world->event_dispatcher_mutex );\n\n     return DR_INCOMPLETE;\n}\n\nDirectResult\nfusion_enter( int               world_index,\n              int               abi_version,\n              FusionEnterRole   role,\n              FusionWorld     **ret_world )\n{\n     DirectResult       ret;\n     FusionWorld       *world  = NULL;\n     FusionWorldShared *shared = NULL;\n\n     D_ASSERT( ret_world != NULL );\n\n     ret = direct_initialize();\n     if (ret)\n          return ret;\n\n     world = D_CALLOC( 1, sizeof(FusionWorld) );\n     if (!world) {\n          ret = D_OOM();\n          goto error;\n     }\n\n     shared = D_CALLOC( 1, sizeof(FusionWorldShared) );\n     if (!shared) {\n          ret = D_OOM();\n          goto error;\n     }\n\n     world->shared = shared;\n\n     world->fusion_id = FUSION_ID_MASTER;\n\n     /* Create the main pool. */\n     ret = fusion_shm_pool_create( world, \"Fusion Main Pool\", 0x100000,\n                                   fusion_config->debugshm, &shared->main_pool );\n     if (ret)\n          goto error;\n\n     D_MAGIC_SET( world, FusionWorld );\n     D_MAGIC_SET( world->shared, FusionWorldShared );\n\n     fusion_skirmish_init( &shared->arenas_lock, \"Fusion Arenas\", world );\n\n     shared->world = world;\n\n     direct_mutex_init( &world->event_dispatcher_mutex );\n     direct_waitqueue_init( &world->event_dispatcher_cond );\n     direct_waitqueue_init( &world->event_dispatcher_process_cond );\n     direct_mutex_init( &world->event_dispatcher_call_mutex );\n     direct_waitqueue_init( &world->event_dispatcher_call_cond );\n     world->event_dispatcher_thread = direct_thread_create( DTT_MESSAGING, event_dispatcher_loop, world,\n                                                            \"Fusion Dispatch\" );\n\n     world->refs = 1;\n\n     *ret_world = world;\n\n     return DR_OK;\n\nerror:\n     if (world) {\n          if (world->shared)\n               D_FREE( world->shared );\n\n          D_FREE( world );\n     }\n\n     direct_shutdown();\n\n     return ret;\n}\n\nDirectResult\nfusion_world_activate( FusionWorld *world )\n{\n     return DR_OK;\n}\n\nDirectResult\nfusion_stop_dispatcher( FusionWorld *world,\n                        bool         emergency )\n{\n     return DR_OK;\n}\n\nDirectResult\nfusion_exit( FusionWorld *world,\n             bool         emergency )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     fusion_shm_pool_destroy( world, world->shared->main_pool );\n\n     direct_mutex_lock( &world->event_dispatcher_mutex );\n     world->dispatch_stop = 1;\n     direct_mutex_unlock( &world->event_dispatcher_mutex );\n\n     direct_waitqueue_signal( &world->event_dispatcher_call_cond );\n     direct_waitqueue_signal( &world->event_dispatcher_cond );\n\n     direct_thread_join( world->event_dispatcher_thread );\n\n     direct_thread_destroy( world->event_dispatcher_thread );\n\n     direct_mutex_deinit( &world->event_dispatcher_mutex );\n     direct_waitqueue_deinit( &world->event_dispatcher_cond );\n     direct_mutex_deinit( &world->event_dispatcher_call_mutex );\n     direct_waitqueue_deinit( &world->event_dispatcher_call_cond );\n\n     fusion_skirmish_destroy( &world->shared->arenas_lock );\n\n     D_MAGIC_CLEAR( world->shared );\n\n     D_FREE( world->shared );\n\n     D_MAGIC_CLEAR( world );\n\n     D_FREE( world );\n\n     direct_shutdown();\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_kill( FusionWorld *world,\n             FusionID     fusion_id,\n             int          signal,\n             int          timeout_ms )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     world->dispatch_stop = 1;\n\n     return DR_OK;\n}\n\nconst char *\nfusion_get_tmpfs( FusionWorld *world )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     return \"/tmp\";\n}\n\nDirectResult\nfusion_dispatch_cleanup_add( FusionWorld                *world,\n                             FusionDispatchCleanupFunc   func,\n                             void                       *ctx,\n                             FusionDispatchCleanup     **ret_cleanup )\n{\n     func( ctx );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_dispatch_cleanup_remove( FusionWorld           *world,\n                                FusionDispatchCleanup *cleanup )\n{\n     return DR_OK;\n}\n\nDirectResult\nfusion_dispatch( FusionWorld *world,\n                 size_t       buf_size )\n{\n     return DR_OK;\n}\n\nDirectResult\nfusion_get_fusionee_path( const FusionWorld *world,\n                          FusionID           fusion_id,\n                          char              *buf,\n                          size_t             buf_size,\n                          size_t            *ret_size )\n{\n     D_ASSERT( world != NULL );\n     D_ASSERT( buf != NULL );\n     D_ASSERT( ret_size != NULL );\n\n     *buf = '\\0';\n     *ret_size = 0;\n\n     return DR_UNIMPLEMENTED;\n}\n\nDirectResult\nfusion_get_fusionee_pid( const FusionWorld *world,\n                         FusionID           fusion_id,\n                         pid_t             *ret_pid )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     return DR_UNIMPLEMENTED;\n}\n\nDirectResult\nfusion_world_set_root( FusionWorld *world,\n                       void        *root )\n{\n     D_ASSERT( world != NULL );\n     D_ASSERT( world->shared != NULL );\n\n     if (world->fusion_id != FUSION_ID_MASTER)\n          return DR_ACCESSDENIED;\n\n     world->shared->world_root = root;\n\n     return DR_OK;\n}\n\nvoid *\nfusion_world_get_root( FusionWorld *world )\n{\n     D_ASSERT( world != NULL );\n     D_ASSERT( world->shared != NULL );\n\n     return world->shared->world_root;\n}\n\nDirectResult\nfusion_sync( const FusionWorld *world )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     return DR_OK;\n}\n\nvoid\nfusion_world_set_fork_action( FusionWorld      *world,\n                              FusionForkAction  action )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n}\n\nFusionForkAction\nfusion_world_get_fork_action( FusionWorld *world )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     return world->fork_action;\n}\n\nvoid\nfusion_world_set_fork_callback( FusionWorld        *world,\n                                FusionForkCallback  callback )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n}\n\nvoid\nfusion_world_set_leave_callback( FusionWorld         *world,\n                                 FusionLeaveCallback  callback,\n                                 void                *ctx )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n}\n\nint\nfusion_world_index( const FusionWorld *world )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     return 0;\n}\n\nFusionID\nfusion_id( const FusionWorld *world )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     return world->fusion_id;\n}\n\nbool\nfusion_is_multi( const FusionWorld *world )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     return false;\n}\n\npid_t\nfusion_dispatcher_tid( const FusionWorld *world )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     return direct_thread_get_tid( world->event_dispatcher_thread );\n}\n\nbool\nfusion_master( const FusionWorld *world )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     return true;\n}\n\nbool\nfusion_is_shared( FusionWorld *world,\n                  const void  *ptr )\n{\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     return true;\n}\n\n#endif /* FUSION_BUILD_MULTI */\n"
  },
  {
    "path": "lib/fusion/fusion.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FUSION__FUSION_H__\n#define __FUSION__FUSION_H__\n\n#include <direct/list.h>\n#include <fusion/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     FER_ANY    = 0x00000000,\n     FER_MASTER = 0x00000001,\n     FER_SLAVE  = 0x00000002\n} FusionEnterRole;\n\ntypedef enum {\n     FFA_CLOSE = 0x00000000,\n     FFA_FORK  = 0x00000001\n} FusionForkAction;\n\ntypedef enum {\n     FFS_PREPARE = 0x00000000,\n     FFS_PARENT  = 0x00000001,\n     FFS_CHILD   = 0x00000002\n} FusionForkState;\n\ntypedef void (*FusionForkCallback) ( FusionForkAction action, FusionForkState state );\n\ntypedef void (*FusionLeaveCallback)( FusionWorld *world, FusionID fusion_id, void *ctx );\n\ntypedef void (*FusionDispatchCleanupFunc)( void *ctx );\n\ntypedef struct {\n     DirectLink                    link;\n\n     FusionDispatchCleanupFunc     func;\n     void                         *ctx;\n} FusionDispatchCleanup;\n\n/**********************************************************************************************************************/\n\n/*\n * Enters a fusion world by joining or creating it.\n * If 'world_index' is negative, the next free index is used to create a new world.\n * Otherwise the world with the specified index is joined or created.\n */\nDirectResult     FUSION_API  fusion_enter                   ( int                         world_index,\n                                                              int                         abi_version,\n                                                              FusionEnterRole             role,\n                                                              FusionWorld               **ret_world );\n\n/*\n * Unblock slaves from entering.\n */\nDirectResult     FUSION_API  fusion_world_activate          ( FusionWorld                *world );\n\n/*\n * Stop the dispatcher thread.\n */\nDirectResult     FUSION_API  fusion_stop_dispatcher         ( FusionWorld                *world,\n                                                              bool                        emergency );\n\n/*\n * Exits the fusion world.\n * If 'emergency' is true the function won't join but kill the dispatcher thread.\n */\nDirectResult     FUSION_API  fusion_exit                    ( FusionWorld                *world,\n                                                              bool                        emergency );\n\n/*\n * Sends a signal to one or more fusionees and optionally waits for their processes to terminate.\n * A fusion_id of zero means all fusionees.\n * A timeout of zero means infinite waiting while a negative value means no waiting at all.\n */\nDirectResult     FUSION_API  fusion_kill                    ( FusionWorld                *world,\n                                                              FusionID                    fusion_id,\n                                                              int                         signal,\n                                                              int                         timeout_ms );\n\n/*\n * Return the location of shared memory file.\n */\nconst char       FUSION_API *fusion_get_tmpfs               ( FusionWorld                *world );\n\n/*\n * Add dispatch cleanup handler.\n */\nDirectResult     FUSION_API  fusion_dispatch_cleanup_add    ( FusionWorld                *world,\n                                                              FusionDispatchCleanupFunc   func,\n                                                              void                       *ctx,\n                                                              FusionDispatchCleanup     **ret_cleanup );\n\n/*\n * Remove dispatch cleanup handler.\n */\nDirectResult     FUSION_API  fusion_dispatch_cleanup_remove ( FusionWorld                *world,\n                                                              FusionDispatchCleanup      *cleanup );\n\n/*\n * Dispatch.\n */\nDirectResult     FUSION_API  fusion_dispatch                ( FusionWorld                *world,\n                                                              size_t                      buf_size );\n\n/*\n * Get the executable path of the fusionee.\n */\nDirectResult     FUSION_API  fusion_get_fusionee_path       ( const FusionWorld          *world,\n                                                              FusionID                    fusion_id,\n                                                              char                       *buf,\n                                                              size_t                      buf_size,\n                                                              size_t                     *ret_size );\n\n/*\n * Get the PID of the fusionee.\n */\nDirectResult     FUSION_API  fusion_get_fusionee_pid        ( const FusionWorld          *world,\n                                                              FusionID                    fusion_id,\n                                                              pid_t                      *ret_pid );\n\n/*\n * Set the world root, i.e. the shared core.\n */\nDirectResult     FUSION_API  fusion_world_set_root          ( FusionWorld                *world,\n                                                              void                       *root );\n\n/*\n * Get the world root.\n */\nvoid             FUSION_API *fusion_world_get_root          ( FusionWorld                *world );\n\n/*\n * Wait until all pending messages are processed.\n */\nDirectResult     FUSION_API  fusion_sync                    ( const FusionWorld          *world );\n\n/*\n * Sets the fork() action of the calling fusionee within the world.\n */\nvoid             FUSION_API  fusion_world_set_fork_action   ( FusionWorld                *world,\n                                                              FusionForkAction            action );\n\n/*\n * Gets the current fork() action.\n */\nFusionForkAction FUSION_API  fusion_world_get_fork_action   ( FusionWorld                *world );\n\n/*\n * Registers a callback called upon fork().\n */\nvoid             FUSION_API  fusion_world_set_fork_callback ( FusionWorld                *world,\n                                                              FusionForkCallback          callback );\n\n/*\n * Registers a callback called when a slave exits.\n */\nvoid             FUSION_API  fusion_world_set_leave_callback( FusionWorld                *world,\n                                                              FusionLeaveCallback         callback,\n                                                              void                       *ctx );\n\n/*\n * Returns the index of the specified world.\n */\nint              FUSION_API  fusion_world_index             ( const FusionWorld          *world );\n\n/*\n * Returns the own Fusion ID within the specified world.\n */\nFusionID         FUSION_API  fusion_id                      ( const FusionWorld          *world );\n\n/*\n * Returns if the world is a multi application world.\n */\nbool             FUSION_API  fusion_is_multi                ( const FusionWorld          *world );\n\n/*\n * Returns the thread ID of the Fusion Dispatcher within the specified world.\n */\npid_t            FUSION_API  fusion_dispatcher_tid          ( const FusionWorld          *world );\n\n/*\n * Returns true if this process is the master.\n */\nbool             FUSION_API  fusion_master                  ( const FusionWorld          *world );\n\n/*\n * Check if a pointer points to the shared memory.\n */\nbool             FUSION_API  fusion_is_shared               ( FusionWorld                *world,\n                                                              const void                 *ptr );\n\n#endif\n"
  },
  {
    "path": "lib/fusion/fusion_internal.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FUSION__FUSION_INTERNAL_H__\n#define __FUSION__FUSION_INTERNAL_H__\n\n#include <fusion/call.h>\n#include <fusion/fusion.h>\n#include <fusion/ref.h>\n#include <fusion/shm/shm_internal.h>\n\n/**********************************************************************************************************************/\n\nstruct __Fusion_FusionWorldShared {\n     int                  magic;\n\n     int                  refs;            /* Increased by the master on fork(). */\n\n     int                  world_index;\n\n     int                  world_abi;\n\n     long long            start_time;\n\n     DirectLink          *arenas;\n     FusionSkirmish       arenas_lock;\n\n     FusionSkirmish       reactor_globals;\n\n     FusionSHMShared      shm;\n\n     FusionSHMPoolShared *main_pool;\n\n     DirectLink          *fusionees;       /* Connected fusionees. */\n     FusionSkirmish       fusionees_lock;  /* Lock for fusionees. */\n\n     unsigned int         call_ids;        /* Generates call ids. */\n     unsigned int         lock_ids;        /* Generates locks ids. */\n     unsigned int         ref_ids;         /* Generates refs ids. */\n     unsigned int         reactor_ids;     /* Generates reactors ids. */\n     unsigned int         pool_ids;        /* Generates pools ids. */\n\n     void                *pool_base;       /* SHM pool allocation base. */\n     void                *pool_max;        /* SHM pool max address. */\n\n     void                *world_root;\n\n     FusionWorld         *world;\n\n     FusionCall           refs_call;\n\n     FusionHash          *call_hash;\n};\n\nstruct __Fusion_FusionWorld {\n     int                   magic;\n\n     int                   refs;\n\n     FusionWorldShared    *shared;\n\n     int                   fusion_fd;\n     FusionID              fusion_id;\n\n     DirectThread         *dispatch_loop;\n     bool                  dispatch_stop;\n\n     DirectLink           *reactor_nodes;\n     DirectMutex           reactor_nodes_lock;\n\n     FusionSHM             shm;\n\n     FusionForkAction      fork_action;\n     FusionForkCallback    fork_callback;\n\n     void                 *fusionee;\n\n     struct {\n          DirectThread    *thread;\n          DirectWaitQueue  queue;\n          DirectMutex      lock;\n          DirectLink      *list;\n     } deferred;\n\n     FusionLeaveCallback   leave_callback;\n     void                 *leave_ctx;\n\n     DirectLink           *dispatch_cleanups;\n\n     DirectMutex           refs_lock;\n     DirectMap            *refs_map;\n\n     DirectThread         *event_dispatcher_thread;\n     DirectMutex           event_dispatcher_mutex;\n     DirectWaitQueue       event_dispatcher_cond;\n     DirectWaitQueue       event_dispatcher_process_cond;\n     DirectLink           *event_dispatcher_buffers;\n     DirectLink           *event_dispatcher_buffers_remove;\n     DirectMutex           event_dispatcher_call_mutex;\n     DirectWaitQueue       event_dispatcher_call_cond;\n};\n\n/**********************************************************************************************************************/\n\n#if FUSION_BUILD_MULTI\n\n#define FUSION_MAX_WORLDS 32\n\ntypedef struct {\n     FusionID fusion_id;\n     int      ref_id;\n} FusionRefSlaveKey;\n\ntypedef struct {\n     FusionRefSlaveKey  key;\n\n     int                refs;\n\n     FusionRef         *ref;\n} FusionRefSlaveEntry;\n\ntypedef struct {\n     int ref_id;\n\n     int refs_catch;\n     int refs_local;\n} FusionRefSlaveSlaveEntry;\n\n/*\n * from call.c\n */\nvoid         _fusion_call_process                         ( FusionWorld                      *world,\n                                                            int                               call_id,\n                                                            FusionCallMessage                *call,\n                                                            void                             *ptr );\n\n/*\n * from fusion.c\n */\nint          _fusion_fd                                   ( const FusionWorldShared          *shared );\n\nFusionID     _fusion_id                                   ( const FusionWorldShared          *shared );\n\nFusionWorld *_fusion_world                                ( const FusionWorldShared          *shared );\n\n/*\n * from reactor.c\n */\nvoid         _fusion_reactor_free_all                     ( FusionWorld                      *world );\n\nvoid         _fusion_reactor_process_message              ( FusionWorld                      *world,\n                                                            int                               reactor_id,\n                                                            int                               channel,\n                                                            const void                       *msg_data );\n\n#if FUSION_BUILD_KERNEL\n\nstatic __inline__ void\nfusion_entry_add_permissions( const FusionWorld *world,\n                              FusionType         type,\n                              int                entry_id,\n                              FusionID           fusion_id, ... )\n{\n     FusionEntryPermissions permissions;\n     va_list                args;\n     int                    arg;\n\n     permissions.type        = type;\n     permissions.id          = entry_id;\n     permissions.fusion_id   = fusion_id;\n     permissions.permissions = 0;\n\n     va_start( args, fusion_id );\n\n     while ((arg = va_arg( args, int )) != 0)\n          FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, arg );\n\n     va_end( args );\n\n     while (ioctl( world->fusion_fd, FUSION_ENTRY_ADD_PERMISSIONS, &permissions ) < 0) {\n          if (errno != EINTR) {\n               D_PERROR( \"Fusion: FUSION_ENTRY_ADD_PERMISSIONS( type %u, id %d )\\n\", type, entry_id );\n               break;\n          }\n     }\n}\n\ntypedef struct {\n     DirectLink        link;\n\n     FusionReadMessage header;\n} DeferredCall;\n\n#define EXECUTE3_BIN_FLUSH_MILLIS 16\n\n/*\n * from call.c\n */\nvoid         _fusion_call_process3                        ( FusionWorld                      *world,\n                                                            int                               call_id,\n                                                            FusionCallMessage3               *msg,\n                                                            void                             *ptr );\n\n/*\n * from shm/pool.c\n */\nvoid         _fusion_shmpool_process                      ( FusionWorld                      *world,\n                                                            int                               pool_id,\n                                                            FusionSHMPoolMessage             *msg );\n\n#else /* FUSION_BUILD_KERNEL */\n\n/*\n * from fusion.c\n */\nvoid         _fusion_add_local                            ( FusionWorld                      *world,\n                                                            FusionRef                        *ref,\n                                                            int                               add );\n\nvoid         _fusion_check_locals                         ( FusionWorld                      *world,\n                                                            FusionRef                        *ref );\n\nvoid         _fusion_remove_all_locals                    ( FusionWorld                      *world,\n                                                            const FusionRef                  *ref );\n\nDirectResult _fusion_send_message                         ( int                               fd,\n                                                            const void                       *msg,\n                                                            size_t                            msg_size,\n                                                            struct sockaddr_un               *addr );\n\nDirectResult _fusion_recv_message                         ( int                               fd,\n                                                            void                             *msg,\n                                                            size_t                            msg_size,\n                                                            struct sockaddr_un               *addr );\n\n/*\n * from ref.c\n */\nDirectResult _fusion_ref_change                           ( FusionRef                        *ref,\n                                                            int                               add,\n                                                            bool                              global );\n\n#endif /* FUSION_BUILD_KERNEL */\n\n#else /* FUSION_BUILD_MULTI */\n\n#define EVENT_DISPATCHER_BUFFER_LENGTH (FUSION_CALL_MAX_LENGTH)\n\ntypedef struct {\n     DirectLink link;\n\n     int        magic;\n\n     char       buffer[FUSION_CALL_MAX_LENGTH];\n     int        read_pos;\n     int        write_pos;\n     int        can_free;\n     int        sync_calls;\n     int        pending;\n} FusionEventDispatcherBuffer;\n\ntypedef struct\n{\n     int                  reaction;\n     FusionCallHandler    call_handler;\n     FusionCallHandler3   call_handler3;\n     void                *call_ctx;\n     FusionCallExecFlags  flags;\n     int                  call_arg;\n     void                *ptr;\n     unsigned int         length;\n     int                  ret_val;\n     void                *ret_ptr;\n     unsigned int         ret_size;\n     unsigned int         ret_length;\n     int                  processed;\n} FusionEventDispatcherCall;\n\n/*\n * from fusion.c\n */\nDirectResult _fusion_event_dispatcher_process             ( FusionWorld                      *world,\n                                                            const FusionEventDispatcherCall  *call,\n                                                            FusionEventDispatcherCall       **ret );\n\nDirectResult _fusion_event_dispatcher_process_reactions   ( FusionWorld                      *world,\n                                                            FusionReactor                    *reactor,\n                                                            int                               channel,\n                                                            void                             *msg_data,\n                                                            int                               msg_size );\n\nDirectResult _fusion_event_dispatcher_process_reactor_free( FusionWorld                      *world,\n                                                            FusionReactor                    *reactor );\n\n#endif /* FUSION_BUILD_MULTI */\n\n#endif\n"
  },
  {
    "path": "lib/fusion/hash.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/mem.h>\n#include <direct/util.h>\n#include <fusion/hash.h>\n#include <fusion/shmalloc.h>\n\nD_DEBUG_DOMAIN( Fusion_Hash, \"Fusion/Hash\", \"Fusion Hash table\" );\n\n/**********************************************************************************************************************/\n\n#define HASH_STR(h,p)                   \\\n{                                       \\\n     h = *p;                            \\\n     if (h)                             \\\n          for (p += 1; *p != '\\0'; p++) \\\n               h = (h << 5) - h + *p;   \\\n}\n\nstatic const unsigned int primes[] =\n{\n     11,\n     19,\n     37,\n     73,\n     109,\n     163,\n     251,\n     367,\n     557,\n     823,\n     1237,\n     1861,\n     2777,\n     4177,\n     6247,\n     9371,\n     14057,\n     21089,\n     31627,\n     47431,\n     71143,\n     106721,\n     160073,\n     240101,\n     360163,\n     540217,\n     810343,\n     1215497,\n     1823231,\n     2734867,\n     4102283,\n     6153409,\n     9230113,\n     13845163,\n};\n\nstatic const unsigned int nprimes = D_ARRAY_SIZE(primes);\n\nstatic unsigned int\nspaced_primes_closest( unsigned int num )\n{\n     unsigned int i;\n\n     for (i = 0; i < nprimes; i++)\n          if (primes[i] > num)\n               return primes[i];\n\n     return primes[nprimes-1];\n}\n\nstatic __inline__ FusionHashNode **\nfusion_hash_lookup_node( FusionHash *hash,\n                         const void *key )\n{\n     FusionHashNode **node;\n\n     if (hash->key_type == HASH_STRING) {\n          unsigned int  h;\n          const char   *p = key;\n          HASH_STR(h,p)\n          node = &hash->nodes[h % hash->size];\n     }\n     else\n          node = &hash->nodes[((unsigned long) key) % hash->size];\n\n     if (hash->key_type == HASH_STRING) {\n          while (*node && strcmp( (*node)->key, key ))\n               node = &(*node)->next;\n     }\n     else\n          while (*node && (*node)->key != key)\n               node = &(*node)->next;\n\n     return node;\n}\n\n/**********************************************************************************************************************/\n\nstatic DirectResult\nfusion_hash_create_internal( bool                  local,\n                             FusionSHMPoolShared  *pool,\n                             FusionHashType        key_type,\n                             FusionHashType        value_type,\n                             int                   size,\n                             FusionHash          **ret_hash )\n{\n     FusionHash *hash;\n\n     if (!ret_hash)\n          return DR_BUG;\n     if (!local && !pool)\n          return DR_BUG;\n\n     if (size < FUSION_HASH_MIN_SIZE)\n          size = FUSION_HASH_MIN_SIZE;\n\n     if (local)\n          hash = D_CALLOC( 1, sizeof(FusionHash) );\n     else\n          hash = SHCALLOC( pool, 1, sizeof(FusionHash) );\n\n     if (!hash)\n          return local ? DR_NOLOCALMEMORY : DR_NOSHAREDMEMORY;\n\n     hash->local      = local;\n     hash->pool       = pool;\n     hash->key_type   = key_type;\n     hash->value_type = value_type;\n     hash->size       = size;\n     hash->nnodes     = 0;\n     if (local)\n          hash->nodes = D_CALLOC( size, sizeof(FusionHashNode*) );\n     else\n          hash->nodes = SHCALLOC( pool, size, sizeof(FusionHashNode*) );\n\n     if (!hash->nodes) {\n          if (local)\n               D_FREE( hash );\n          else\n               SHFREE( pool, hash );\n          return local ? DR_NOLOCALMEMORY : DR_NOSHAREDMEMORY;\n     }\n\n     D_MAGIC_SET( hash, FusionHash );\n\n     *ret_hash = hash;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_hash_create_local( FusionHashType   key_type,\n                          FusionHashType   value_type,\n                          int              size,\n                          FusionHash     **ret_hash )\n{\n     D_DEBUG_AT( Fusion_Hash, \"Creating local hash table with initial capacity of %d...\\n\", size );\n\n     return fusion_hash_create_internal( true, NULL, key_type, value_type, size, ret_hash );\n}\n\nDirectResult\nfusion_hash_create( FusionSHMPoolShared  *pool,\n                    FusionHashType        key_type,\n                    FusionHashType        value_type,\n                    int                   size,\n                    FusionHash          **ret_hash )\n{\n     D_DEBUG_AT( Fusion_Hash, \"Creating shared hash table with initial capacity of %d...\\n\", size );\n\n     return fusion_hash_create_internal( false, pool, key_type, value_type, size, ret_hash );\n}\n\nstatic void\nfusion_hash_node_destroy( FusionHash      *hash,\n                          FusionHashNode  *node,\n                          void           **old_key,\n                          void           **old_value )\n{\n     if (!node)\n          return;\n\n     if (old_key)\n          *old_key = node->key;\n     else if (hash->key_type != HASH_INT) {\n          if (hash->free_keys) {\n               if (hash->local)\n                    D_FREE( node->key );\n               else\n                    SHFREE( hash->pool, node->key );\n          }\n     }\n\n     if (old_value)\n          *old_value = node->value;\n     else if (hash->value_type != HASH_INT) {\n          if (hash->free_values) {\n               if (hash->local)\n                    D_FREE( node->value );\n               else\n                    SHFREE( hash->pool, node->value );\n          }\n     }\n\n     if (hash->local)\n          D_FREE( node );\n     else\n          SHFREE( hash->pool, node );\n}\n\nvoid\nfusion_hash_destroy( FusionHash *hash )\n{\n     FusionHashNode *node;\n     FusionHashNode *next;\n     int             i;\n\n     D_MAGIC_ASSERT( hash, FusionHash );\n\n     for (i = 0; i < hash->size; i++) {\n          for (node = hash->nodes[i]; node; node = next) {\n               next = node->next;\n               fusion_hash_node_destroy( hash, node, NULL, NULL );\n          }\n     }\n\n     if (hash->local)\n          D_FREE( hash->nodes );\n     else\n          SHFREE( hash->pool, hash->nodes );\n\n     D_MAGIC_CLEAR( hash );\n\n     if (hash->local)\n          D_FREE( hash );\n     else\n          SHFREE( hash->pool, hash );\n}\n\nvoid\nfusion_hash_set_autofree( FusionHash *hash,\n                          bool        free_keys,\n                          bool        free_values )\n{\n     D_MAGIC_ASSERT( hash, FusionHash );\n\n     hash->free_keys   = free_keys;\n     hash->free_values = free_values;\n}\n\nvoid *\nfusion_hash_lookup( FusionHash *hash,\n                    const void *key )\n{\n     FusionHashNode *node;\n\n     D_MAGIC_ASSERT( hash, FusionHash );\n\n     node = *fusion_hash_lookup_node( hash, key );\n\n     return node ? node->value : NULL;\n}\n\nDirectResult\nfusion_hash_insert( FusionHash *hash,\n                    void       *key,\n                    void       *value )\n{\n     FusionHashNode **node;\n\n     D_MAGIC_ASSERT( hash, FusionHash );\n\n     node = fusion_hash_lookup_node( hash, key );\n\n     if (*node) {\n          D_BUG( \"key already exists\" );\n          return DR_BUG;\n     }\n     else {\n          if (hash->local)\n               (*node) = D_CALLOC( 1, sizeof(FusionHashNode) );\n          else\n               (*node) = SHCALLOC( hash->pool, 1, sizeof(FusionHashNode) );\n\n          if (!(*node))\n               return hash->local ? DR_NOLOCALMEMORY : DR_NOSHAREDMEMORY;\n\n          (*node)->key = key;\n          (*node)->value = value;\n\n          hash->nnodes++;\n\n          if (fusion_hash_should_resize( hash ))\n               fusion_hash_resize( hash );\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_hash_replace( FusionHash  *hash,\n                     void        *key,\n                     void        *value,\n                     void       **old_key,\n                     void       **old_value )\n{\n     FusionHashNode **node;\n\n     D_MAGIC_ASSERT( hash, FusionHash );\n\n     node = fusion_hash_lookup_node( hash, key );\n\n     if (*node) {\n          if (old_key)\n               *old_key = (*node)->key;\n          else if (hash->key_type != HASH_INT) {\n               if (hash->free_keys) {\n                    if (hash->local)\n                         D_FREE( (*node)->key );\n                    else\n                         SHFREE( hash->pool, (*node)->key );\n               }\n          }\n\n          if (old_value)\n               *old_value = (*node)->value;\n          else if (hash->value_type != HASH_INT) {\n               if (hash->free_values) {\n                    if (hash->local)\n                         D_FREE( (*node)->value );\n                    else\n                         SHFREE( hash->pool, (*node)->value );\n               }\n          }\n\n          (*node)->key = key;\n          (*node)->value = value;\n     }\n     else {\n          if (hash->local)\n               *node = D_CALLOC( 1, sizeof(FusionHashNode) );\n          else\n               *node = SHCALLOC( hash->pool, 1, sizeof(FusionHashNode) );\n\n          if (!(*node))\n               return hash->local ? DR_NOLOCALMEMORY : DR_NOSHAREDMEMORY;\n\n          (*node)->key = key;\n          (*node)->value = value;\n\n          hash->nnodes++;\n\n          if (fusion_hash_should_resize( hash ))\n               fusion_hash_resize( hash );\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_hash_remove( FusionHash *hash,\n                    const void *key,\n                    void       **old_key,\n                    void       **old_value )\n{\n     FusionHashNode **node;\n     FusionHashNode  *dest;\n\n     D_MAGIC_ASSERT( hash, FusionHash );\n\n     node = fusion_hash_lookup_node( hash, key );\n     if (*node) {\n          dest = *node;\n\n          (*node) = dest->next;\n\n          fusion_hash_node_destroy( hash, dest, old_key, old_value );\n\n          hash->nnodes--;\n\n          return DR_OK;\n     }\n\n     return DR_OK;\n}\n\nvoid\nfusion_hash_iterate( FusionHash             *hash,\n                     FusionHashIteratorFunc  func,\n                     void                   *ctx )\n{\n     FusionHashNode *node;\n     FusionHashNode *next;\n     int             i;\n\n     D_MAGIC_ASSERT( hash, FusionHash );\n\n     for (i = 0; i < hash->size; i++) {\n          for (node = hash->nodes[i]; node; node = next) {\n               next = node->next;\n\n               if (func( hash, node->key, node->value, ctx) )\n                    return;\n          }\n     }\n}\n\nunsigned int\nfusion_hash_size( FusionHash *hash )\n{\n     D_MAGIC_ASSERT( hash, FusionHash );\n\n     return hash->nnodes;\n}\n\nbool fusion_hash_should_resize( FusionHash *hash )\n{\n     D_MAGIC_ASSERT( hash, FusionHash );\n\n     if ((hash->size >= 3 * hash->nnodes && hash->size > FUSION_HASH_MIN_SIZE) ||\n         (3 * hash->size <= hash->nnodes && hash->size < FUSION_HASH_MAX_SIZE))\n          return true;\n\n     return false;\n}\n\nDirectResult\nfusion_hash_resize( FusionHash *hash )\n{\n     FusionHashNode **new_nodes;\n     FusionHashNode *node;\n     FusionHashNode *next;\n     unsigned int    hash_val;\n     int             new_size;\n     int             i;\n\n     D_MAGIC_ASSERT( hash, FusionHash );\n\n     new_size = spaced_primes_closest( hash->nnodes );\n     if (new_size > FUSION_HASH_MAX_SIZE )\n          new_size = FUSION_HASH_MAX_SIZE;\n     if (new_size <  FUSION_HASH_MIN_SIZE)\n          new_size = FUSION_HASH_MIN_SIZE;\n\n     if (hash->local)\n          new_nodes = D_CALLOC( new_size, sizeof(FusionHashNode*) );\n     else\n          new_nodes = SHCALLOC( hash->pool, new_size, sizeof(FusionHashNode*) );\n\n     if (!new_nodes)\n          return hash->local?DR_NOLOCALMEMORY:DR_NOSHAREDMEMORY;\n\n     for (i = 0; i < hash->size; i++) {\n          for (node = hash->nodes[i]; node; node = next) {\n               next = node->next;\n               if (hash->key_type == HASH_STRING) {\n                    unsigned int  h;\n                    const char   *p = node->key;\n                    HASH_STR(h, p)\n                    hash_val = h % new_size;\n               }\n               else\n                    hash_val = ((unsigned long) node->key) % new_size;\n\n               node->next = new_nodes[hash_val];\n               new_nodes[hash_val] = node;\n          }\n     }\n\n     if (hash->local)\n          D_FREE( hash->nodes );\n     else\n          SHFREE( hash->pool, hash->nodes );\n\n     hash->nodes = new_nodes;\n     hash->size = new_size;\n\n     return true;\n}\n"
  },
  {
    "path": "lib/fusion/hash.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FUSION_HASH_H__\n#define __FUSION_HASH_H__\n\n#include <direct/debug.h>\n#include <fusion/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     HASH_PTR    = 0x00000000,\n     HASH_STRING = 0x00000001,\n     HASH_INT    = 0x00000002\n} FusionHashType;\n\ntypedef struct _FusionHashNode {\n    void                   *key;\n    void                   *value;\n    struct _FusionHashNode *next;\n} FusionHashNode;\n\nstruct __Fusion_FusionHash {\n    int                   magic;\n    bool                  local;\n    FusionHashType        key_type;\n    FusionHashType        value_type;\n    int                   size;\n    int                   nnodes;\n    FusionHashNode      **nodes;\n    FusionSHMPoolShared  *pool;\n\n    bool                  free_keys;\n    bool                  free_values;\n};\n\n/**********************************************************************************************************************/\n\n#define FUSION_HASH_MIN_SIZE 11\n#define FUSION_HASH_MAX_SIZE 13845163\n\ntypedef bool (*FusionHashIteratorFunc)( FusionHash *hash, void *key, void *value, void *ctx );\n\n/**********************************************************************************************************************/\n\n/*\n * Creates a new hash that uses local memory.\n */\nDirectResult FUSION_API  fusion_hash_create_local ( FusionHashType           key_type,\n                                                    FusionHashType           value_type,\n                                                    int                      size,\n                                                    FusionHash             **ret_hash );\n\n/*\n * Creates a new hash.\n */\nDirectResult FUSION_API  fusion_hash_create       ( FusionSHMPoolShared     *pool,\n                                                    FusionHashType           key_type,\n                                                    FusionHashType           value_type,\n                                                    int                      size,\n                                                    FusionHash             **ret_hash );\n\n/*\n * Destroys a hash.\n */\nvoid         FUSION_API  fusion_hash_destroy      ( FusionHash              *hash );\n\n/*\n * Frees keys or values when calling fusion_hash_replace(), fusion_hash_remove(), fusion_hash_destroy().\n */\nvoid         FUSION_API  fusion_hash_set_autofree ( FusionHash               *hash,\n                                                    bool                      free_keys,\n                                                    bool                      free_values );\n\n/*\n * Looks up a key in a hash.\n */\nvoid         FUSION_API *fusion_hash_lookup       ( FusionHash              *hash,\n                                                    const void              *key );\n\n/*\n * Inserts a new key and value into a hash.\n * If you think a key may exist you should call fusion_hash_replace().\n */\nDirectResult FUSION_API  fusion_hash_insert       ( FusionHash              *hash,\n                                                    void                    *key,\n                                                    void                    *value );\n\n/*\n * Inserts a new key and value into a hash similar to hash_insert().\n * The difference is that if the key already exists in the hash, it gets replaced by the new key.\n */\nDirectResult FUSION_API  fusion_hash_replace      ( FusionHash              *hash,\n                                                    void                    *key,\n                                                    void                    *value,\n                                                    void                   **old_key,\n                                                    void                   **old_value );\n\n/*\n * Removes a key and its associated value from a hash.\n */\nDirectResult FUSION_API  fusion_hash_remove       ( FusionHash              *hash,\n                                                    const void              *key,\n                                                    void                   **old_key,\n                                                    void                   **old_value );\n\n/*\n * Calls the given function for each of the key/value pairs in a hash.\n * The hash table can't be modified while iterating over it.\n */\nvoid         FUSION_API  fusion_hash_iterate      ( FusionHash              *hash,\n                                                    FusionHashIteratorFunc   func,\n                                                    void                    *ctx );\n\n/*\n * Returns the number of key/value pairs contained in a hash.\n */\nunsigned int FUSION_API  fusion_hash_size         ( FusionHash              *hash );\n\n/*\n * Determines if the hash has grown to large.\n */\nbool         FUSION_API  fusion_hash_should_resize( FusionHash              *hash );\n\n/*\n * Resizes the hash to minimum.\n */\nDirectResult FUSION_API  fusion_hash_resize       ( FusionHash              *hash );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     FusionHash     *hash;\n     int             index;\n     FusionHashNode *next;\n} FusionHashIterator;\n\nstatic __inline__ void *\nfusion_hash_iterator_next( FusionHashIterator *iterator )\n{\n     FusionHashNode *node = NULL;\n\n     if (iterator->next) {\n          node           = iterator->next;\n          iterator->next = node->next;\n     }\n     else {\n          FusionHash *hash = iterator->hash;\n\n          D_MAGIC_ASSERT( hash, FusionHash );\n\n          for (iterator->index++; iterator->index < hash->size; iterator->index++) {\n               node = hash->nodes[iterator->index];\n               if (node) {\n                    iterator->next = node->next;\n\n                    break;\n               }\n          }\n     }\n\n     return node ? node->value : NULL;\n}\n\nstatic __inline__ void *\nfusion_hash_iterator_init( FusionHashIterator *iterator,\n                           FusionHash         *hash )\n{\n     D_MAGIC_ASSERT( hash, FusionHash );\n\n     iterator->hash  = hash;\n     iterator->index = -1;\n     iterator->next  = NULL;\n\n     return fusion_hash_iterator_next( iterator );\n}\n\n#define fusion_hash_foreach(elem,iterator,hash)                                     \\\n     for ((elem) = (__typeof__(elem)) fusion_hash_iterator_init( &iterator, hash ); \\\n          (elem) != NULL;                                                           \\\n          (elem) = (__typeof__(elem)) fusion_hash_iterator_next( &iterator ))\n\n#endif\n"
  },
  {
    "path": "lib/fusion/init.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/debug.h>\n#include <direct/util.h>\n#include <fusion/call.h>\n#include <fusion/conf.h>\n\n/**********************************************************************************************************************/\n\ntypedef void (*Func)( void );\n\n\nstatic Func init_funcs[] = {\n     __Fusion_conf_init,\n     __Fusion_call_init,\n};\n\nstatic Func deinit_funcs[] = {\n     __Fusion_call_deinit,\n     __Fusion_conf_deinit,\n};\n\n/**********************************************************************************************************************/\n\n__dfb_constructor__\nvoid\n__Fusion_init_all( void )\n{\n     size_t i;\n\n     for (i = 0; i < D_ARRAY_SIZE(init_funcs); i++)\n          init_funcs[i]();\n}\n\n__dfb_destructor__\nvoid\n__Fusion_deinit_all( void )\n{\n     size_t i;\n\n     for (i = 0; i < D_ARRAY_SIZE(deinit_funcs); i++)\n          deinit_funcs[i]();\n}\n"
  },
  {
    "path": "lib/fusion/lock.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/mem.h>\n#include <direct/memcpy.h>\n#include <fusion/lock.h>\n\n#if FUSION_BUILD_MULTI\n\n#include <direct/thread.h>\n#include <fusion/conf.h>\n#include <fusion/fusion_internal.h>\n\n#if !FUSION_BUILD_KERNEL\n#include <direct/system.h>\n#include <fusion/shmalloc.h>\n#endif /* FUSION_BUILD_KERNEL */\n\n#endif /* FUSION_BUILD_MULTI */\n\nD_DEBUG_DOMAIN( Fusion_Skirmish, \"Fusion/Skirmish\", \"Fusion's Skirmish (Mutex)\" );\n\n/**********************************************************************************************************************/\n\n#if FUSION_BUILD_MULTI\n\n#if FUSION_BUILD_KERNEL\n\nDirectResult\nfusion_skirmish_init( FusionSkirmish    *skirmish,\n                      const char        *name,\n                      const FusionWorld *world )\n{\n     FusionEntryInfo info;\n\n     D_ASSERT( skirmish != NULL );\n     D_ASSERT( name != NULL );\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s' )\\n\", __FUNCTION__, skirmish, name ?: \"\" );\n\n     while (ioctl( world->fusion_fd, FUSION_SKIRMISH_NEW, &skirmish->multi.id )) {\n          if (errno == EINTR)\n               continue;\n\n          D_PERROR( \"Fusion/Skirmish: FUSION_SKIRMISH_NEW\" );\n          return DR_FUSION;\n     }\n\n     D_DEBUG_AT( Fusion_Skirmish, \"  -> new skirmish %p [%d]\\n\", skirmish, skirmish->multi.id );\n\n     info.type = FT_SKIRMISH;\n     info.id   = skirmish->multi.id;\n\n     direct_snputs( info.name, name, sizeof(info.name) );\n\n     ioctl( world->fusion_fd, FUSION_ENTRY_SET_INFO, &info );\n\n     fusion_entry_add_permissions( world, FT_SKIRMISH, skirmish->multi.id, 0, FUSION_SKIRMISH_LOCK_COUNT, 0 );\n\n     /* Keep back pointer to shared world data. */\n     skirmish->multi.shared = world->shared;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_init2( FusionSkirmish    *skirmish,\n                       const char        *name,\n                       const FusionWorld *world,\n                       bool               local )\n{\n     D_ASSERT( skirmish != NULL );\n     D_ASSERT( name != NULL );\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s', %s )\\n\", __FUNCTION__, skirmish, name ?: \"\",\n                 local ? \"local\" : \"shared\" );\n\n     if (!local)\n          return fusion_skirmish_init( skirmish, name, world );\n\n     skirmish->single = D_CALLOC( 1, sizeof(FusionSkirmishSingle) + strlen( name ) + 1 );\n     if (skirmish->single == 0)\n          return DR_NOLOCALMEMORY;\n\n     skirmish->single->name = (char*) (skirmish->single + 1);\n     strcpy( skirmish->single->name, name );\n\n     direct_recursive_mutex_init( &skirmish->single->lock );\n     direct_waitqueue_init( &skirmish->single->cond );\n\n     D_MAGIC_SET( skirmish->single, FusionSkirmishSingle );\n\n     /* Keep back pointer to shared world data. */\n     skirmish->multi.shared = world->shared;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_prevail( FusionSkirmish *skirmish )\n{\n     DirectResult ret;\n\n     D_ASSERT( skirmish != NULL );\n\n     if (skirmish->single) {\n          D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s' )\\n\", __FUNCTION__, skirmish, skirmish->single->name );\n\n          D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n          ret= direct_mutex_lock( &skirmish->single->lock );\n          if (ret)\n               return ret;\n\n          skirmish->single->count++;\n\n          return DR_OK;\n     }\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p [%d] )\\n\", __FUNCTION__, skirmish, skirmish->multi.id );\n\n     while (ioctl( _fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_PREVAIL, &skirmish->multi.id )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n\n               case EINVAL:\n                    D_ERROR( \"Fusion/Skirmish: Invalid skirmish!\\n\" );\n                    return DR_DESTROYED;\n          }\n\n          D_PERROR( \"Fusion/Skirmish: FUSION_SKIRMISH_PREVAIL\" );\n          return DR_FUSION;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_swoop( FusionSkirmish *skirmish )\n{\n     DirectResult ret;\n\n     D_ASSERT( skirmish != NULL );\n\n     if (skirmish->single) {\n          D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s' )\\n\", __FUNCTION__, skirmish, skirmish->single->name );\n\n          D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n          ret = direct_mutex_trylock( &skirmish->single->lock );\n          if (ret)\n               return ret;\n\n          skirmish->single->count++;\n\n          return DR_OK;\n     }\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p [%d] )\\n\", __FUNCTION__, skirmish, skirmish->multi.id );\n\n     while (ioctl( _fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_SWOOP, &skirmish->multi.id )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n\n               case EAGAIN:\n                    return DR_BUSY;\n\n               case EINVAL:\n                    D_ERROR( \"Fusion/Skirmish: Invalid skirmish!\\n\" );\n                    return DR_DESTROYED;\n          }\n\n          D_PERROR( \"Fusion/Skirmish: FUSION_SKIRMISH_SWOOP\" );\n          return DR_FUSION;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_lock_count( FusionSkirmish *skirmish,\n                            int            *lock_count )\n{\n     DirectResult ret;\n     int          data[2];\n\n     D_ASSERT( skirmish != NULL );\n\n     if (skirmish->single) {\n          D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s' )\\n\", __FUNCTION__, skirmish, skirmish->single->name );\n\n          D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n          ret = direct_mutex_trylock( &skirmish->single->lock );\n          if (ret) {\n               *lock_count = 0;\n               return ret;\n          }\n\n          *lock_count = skirmish->single->count;\n\n          direct_mutex_unlock( &skirmish->single->lock );\n\n          return DR_OK;\n     }\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p [%d] )\\n\", __FUNCTION__, skirmish, skirmish->multi.id );\n\n     data[0] = skirmish->multi.id;\n     data[1] = 0;\n\n     while (ioctl( _fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_LOCK_COUNT, data )) {\n           switch (errno) {\n               case EINTR:\n                    continue;\n\n               case EINVAL:\n                    D_ERROR( \"Fusion/Skirmish: Invalid skirmish!\\n\" );\n                    return DR_DESTROYED;\n           }\n\n          D_PERROR( \"Fusion/Skirmish: FUSION_SKIRMISH_LOCK_COUNT\" );\n          return DR_FUSION;\n     }\n\n     *lock_count = data[1];\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_dismiss( FusionSkirmish *skirmish )\n{\n     D_ASSERT( skirmish != NULL );\n\n     if (skirmish->single) {\n          D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s' )\\n\", __FUNCTION__, skirmish, skirmish->single->name );\n\n          D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n          skirmish->single->count--;\n\n          return direct_mutex_unlock( &skirmish->single->lock );\n     }\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p [%d] )\\n\", __FUNCTION__, skirmish, skirmish->multi.id );\n\n     while (ioctl( _fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_DISMISS, &skirmish->multi.id )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n\n               case EINVAL:\n                    D_ERROR( \"Fusion/Skirmish: Invalid skirmish!\\n\" );\n                    return DR_DESTROYED;\n          }\n\n          D_PERROR( \"Fusion/Skirmish: FUSION_SKIRMISH_DISMISS\" );\n          return DR_FUSION;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_destroy( FusionSkirmish *skirmish )\n{\n     DirectResult ret;\n\n     D_ASSERT( skirmish != NULL );\n\n     if (skirmish->single) {\n          D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s' )\\n\", __FUNCTION__, skirmish, skirmish->single->name );\n\n          D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n          direct_waitqueue_broadcast( &skirmish->single->cond );\n          direct_waitqueue_deinit( &skirmish->single->cond );\n\n          ret = direct_mutex_deinit( &skirmish->single->lock );\n\n          D_MAGIC_CLEAR( skirmish->single );\n\n          D_FREE( skirmish->single );\n\n          return ret;\n     }\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p [%d] )\\n\", __FUNCTION__, skirmish, skirmish->multi.id );\n\n     while (ioctl( _fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_DESTROY, &skirmish->multi.id )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n\n               case EINVAL:\n                    D_ERROR( \"Fusion/Skirmish: Invalid skirmish!\\n\" );\n                    return DR_DESTROYED;\n          }\n\n          D_PERROR( \"Fusion/Skirmish: FUSION_SKIRMISH_DESTROY\" );\n          return DR_FUSION;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_wait( FusionSkirmish *skirmish,\n                      unsigned int    timeout )\n{\n     FusionSkirmishWait wait;\n\n     D_ASSERT( skirmish != NULL );\n\n     if (skirmish->single) {\n          D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s' )\\n\", __FUNCTION__, skirmish, skirmish->single->name );\n\n          D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n          if (timeout)\n               return direct_waitqueue_wait_timeout( &skirmish->single->cond,\n                                                     &skirmish->single->lock, timeout * 1000 );\n\n          return direct_waitqueue_wait( &skirmish->single->cond, &skirmish->single->lock );\n     }\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p [%d] )\\n\", __FUNCTION__, skirmish, skirmish->multi.id );\n\n     wait.id         = skirmish->multi.id;\n     wait.timeout    = timeout;\n     wait.lock_count = 0;\n\n     while (ioctl( _fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_WAIT, &wait )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n\n               case ETIMEDOUT:\n                    return DR_TIMEOUT;\n\n               case EINVAL:\n                    D_ERROR( \"Fusion/Skirmish: Invalid skirmish!\\n\" );\n                    return DR_DESTROYED;\n          }\n\n          D_PERROR( \"Fusion/Skirmish: FUSION_SKIRMISH_WAIT\" );\n          return DR_FUSION;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_notify( FusionSkirmish *skirmish )\n{\n     D_ASSERT( skirmish != NULL );\n\n     if (skirmish->single) {\n          D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s' )\\n\", __FUNCTION__, skirmish, skirmish->single->name );\n\n          D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n          direct_waitqueue_broadcast( &skirmish->single->cond );\n\n          return DR_OK;\n     }\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p [%d] )\\n\", __FUNCTION__, skirmish, skirmish->multi.id );\n\n     while (ioctl( _fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_NOTIFY, &skirmish->multi.id )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n\n               case EINVAL:\n                    D_ERROR( \"Fusion/Skirmish: Invalid skirmish!\\n\" );\n                    return DR_DESTROYED;\n          }\n\n          D_PERROR( \"Fusion/Skirmish: FUSION_SKIRMISH_NOTIFY\" );\n          return DR_FUSION;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_add_permissions( FusionSkirmish            *skirmish,\n                                 FusionID                   fusion_id,\n                                 FusionSkirmishPermissions  skirmish_permissions )\n{\n     FusionEntryPermissions permissions;\n\n     D_ASSERT( skirmish != NULL );\n\n     if (skirmish->single) {\n          D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s' )\\n\", __FUNCTION__, skirmish, skirmish->single->name );\n\n          D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n          return DR_OK;\n     }\n\n     permissions.type        = FT_SKIRMISH;\n     permissions.id          = skirmish->multi.id;\n     permissions.fusion_id   = fusion_id;\n     permissions.permissions = 0;\n\n     if (skirmish_permissions & FUSION_SKIRMISH_PERMIT_PREVAIL)\n          FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_SKIRMISH_PREVAIL );\n\n     if (skirmish_permissions & FUSION_SKIRMISH_PERMIT_SWOOP)\n          FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_SKIRMISH_SWOOP );\n\n     if (skirmish_permissions & FUSION_SKIRMISH_PERMIT_DISMISS)\n          FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_SKIRMISH_DISMISS );\n\n     if (skirmish_permissions & FUSION_SKIRMISH_PERMIT_LOCK_COUNT)\n          FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_SKIRMISH_LOCK_COUNT );\n\n     if (skirmish_permissions & FUSION_SKIRMISH_PERMIT_WAIT)\n          FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_SKIRMISH_WAIT );\n\n     if (skirmish_permissions & FUSION_SKIRMISH_PERMIT_NOTIFY)\n          FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_SKIRMISH_NOTIFY );\n\n     if (skirmish_permissions & FUSION_SKIRMISH_PERMIT_DESTROY)\n          FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_SKIRMISH_DESTROY );\n\n     while (ioctl( _fusion_fd( skirmish->multi.shared ), FUSION_ENTRY_ADD_PERMISSIONS, &permissions ) < 0) {\n          if (errno != EINTR) {\n               D_PERROR( \"Fusion/Skirmish: FUSION_ENTRY_ADD_PERMISSIONS( id %d )\\n\", skirmish->multi.id );\n               return DR_FAILURE;\n          }\n     }\n\n     return DR_OK;\n}\n\n#else /* FUSION_BUILD_KERNEL */\n\ntypedef struct {\n     DirectLink link;\n\n     pid_t      pid;\n     bool       notified;\n} WaitNode;\n\nDirectResult\nfusion_skirmish_init( FusionSkirmish    *skirmish,\n                      const char        *name,\n                      const FusionWorld *world )\n{\n     D_ASSERT( skirmish != NULL );\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s' )\\n\", __FUNCTION__, skirmish, name ?: \"\" );\n\n     skirmish->multi.id = ++world->shared->lock_ids;\n\n     /* Set state to unlocked. */\n     skirmish->multi.builtin.locked = 0;\n     skirmish->multi.builtin.owner  = 0;\n\n     skirmish->multi.builtin.waiting = NULL;\n\n     skirmish->multi.builtin.requested = false;\n     skirmish->multi.builtin.destroyed = false;\n\n     /* Keep back pointer to shared world data. */\n     skirmish->multi.shared = world->shared;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_init2( FusionSkirmish    *skirmish,\n                       const char        *name,\n                       const FusionWorld *world,\n                       bool               local )\n{\n     D_ASSERT( skirmish != NULL );\n     D_ASSERT( name != NULL );\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s', %s )\\n\", __FUNCTION__, skirmish, name ?: \"\",\n                 local ? \"local\" : \"shared\" );\n\n     if (!local)\n          return fusion_skirmish_init( skirmish, name, world );\n\n\n     skirmish->single = D_CALLOC( 1, sizeof(FusionSkirmishSingle) + strlen( name ) + 1 );\n     if (skirmish->single == 0)\n          return DR_NOLOCALMEMORY;\n\n     skirmish->single->name = (char*) (skirmish->single + 1);\n     strcpy( skirmish->single->name, name );\n\n     direct_recursive_mutex_init( &skirmish->single->lock );\n     direct_waitqueue_init( &skirmish->single->cond );\n\n     D_MAGIC_SET( skirmish->single, FusionSkirmishSingle );\n\n     /* Keep back pointer to shared world data. */\n     skirmish->multi.shared = world->shared;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_prevail( FusionSkirmish *skirmish )\n{\n     DirectResult ret;\n\n     D_ASSERT( skirmish != NULL );\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p )\\n\", __FUNCTION__, skirmish );\n\n     if (skirmish->single) {\n          D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n          ret = direct_mutex_lock( &skirmish->single->lock );\n          if (ret)\n               return ret;\n\n          skirmish->single->count++;\n\n          return DR_OK;\n     }\n\n     if (skirmish->multi.builtin.destroyed)\n          return DR_DESTROYED;\n\n     asm( \"\" ::: \"memory\" );\n\n     if (skirmish->multi.builtin.locked && skirmish->multi.builtin.owner != direct_gettid()) {\n          int count = 0;\n\n          while (skirmish->multi.builtin.locked) {\n               /* Check whether owner exited without unlocking. */\n               ret = direct_kill( skirmish->multi.builtin.owner, 0 );\n               if (ret == DR_NOSUCHINSTANCE) {\n                    skirmish->multi.builtin.locked = 0;\n                    skirmish->multi.builtin.requested = false;\n                    break;\n               }\n\n               skirmish->multi.builtin.requested = true;\n\n               asm( \"\" ::: \"memory\" );\n\n               if (++count > 1000) {\n                    usleep( 10000 );\n                    count = 0;\n               }\n               else {\n                    direct_sched_yield();\n               }\n\n               if (skirmish->multi.builtin.destroyed)\n                    return DR_DESTROYED;\n          }\n     }\n\n     skirmish->multi.builtin.locked++;\n     skirmish->multi.builtin.owner = direct_gettid();\n\n     asm( \"\" ::: \"memory\" );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_swoop( FusionSkirmish *skirmish )\n{\n     DirectResult ret;\n\n     D_ASSERT( skirmish != NULL );\n\n     if (skirmish->single) {\n          D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n          ret = direct_mutex_trylock( &skirmish->single->lock );\n          if (ret)\n               return ret;\n\n          skirmish->single->count++;\n\n          return DR_OK;\n     }\n\n     if (skirmish->multi.builtin.destroyed)\n          return DR_DESTROYED;\n\n     asm( \"\" ::: \"memory\" );\n\n     if (skirmish->multi.builtin.locked && skirmish->multi.builtin.owner != direct_gettid()) {\n          /* Check whether owner exited without unlocking. */\n          ret = direct_kill( skirmish->multi.builtin.owner, 0 );\n          if (ret == DR_NOSUCHINSTANCE) {\n               skirmish->multi.builtin.locked = 0;\n               skirmish->multi.builtin.requested = false;\n          }\n          else\n               return DR_BUSY;\n     }\n\n     skirmish->multi.builtin.locked++;\n     skirmish->multi.builtin.owner = direct_gettid();\n\n     asm( \"\" ::: \"memory\" );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_lock_count( FusionSkirmish *skirmish,\n                            int            *lock_count )\n{\n     DirectResult ret;\n\n     D_ASSERT( skirmish != NULL );\n\n     if (skirmish->single) {\n          D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n          ret = direct_mutex_trylock( &skirmish->single->lock );\n          if (ret) {\n               *lock_count = 0;\n               return ret;\n          }\n\n          *lock_count = skirmish->single->count;\n\n          direct_mutex_unlock( &skirmish->single->lock );\n\n          return DR_OK;\n     }\n\n     if (skirmish->multi.builtin.destroyed) {\n          *lock_count = 0;\n          return DR_DESTROYED;\n     }\n\n     *lock_count = skirmish->multi.builtin.locked;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_dismiss( FusionSkirmish *skirmish )\n{\n     D_ASSERT( skirmish != NULL );\n\n     if (skirmish->single) {\n          D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n          skirmish->single->count--;\n\n          return direct_mutex_unlock( &skirmish->single->lock );\n     }\n\n     if (skirmish->multi.builtin.destroyed)\n          return DR_DESTROYED;\n\n     asm( \"\" ::: \"memory\" );\n\n     if (skirmish->multi.builtin.locked) {\n          if (skirmish->multi.builtin.owner != direct_gettid()) {\n               D_ERROR( \"Fusion/Skirmish: Tried to dismiss a skirmish not owned by the current process!\\n\" );\n               return DR_ACCESSDENIED;\n          }\n\n          if (--skirmish->multi.builtin.locked == 0) {\n               skirmish->multi.builtin.owner = 0;\n\n               if (skirmish->multi.builtin.requested) {\n                    skirmish->multi.builtin.requested = false;\n                    direct_sched_yield();\n               }\n          }\n     }\n\n     asm( \"\" ::: \"memory\" );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_destroy( FusionSkirmish *skirmish )\n{\n     DirectResult ret;\n\n     D_ASSERT( skirmish != NULL );\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p )\\n\", __FUNCTION__, skirmish );\n\n     if (skirmish->single) {\n          D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n          direct_waitqueue_broadcast( &skirmish->single->cond );\n          direct_waitqueue_deinit( &skirmish->single->cond );\n\n          ret = direct_mutex_deinit( &skirmish->single->lock );\n\n          D_MAGIC_CLEAR( skirmish->single );\n\n          D_FREE( skirmish->single );\n\n          return ret;\n     }\n\n     if (skirmish->multi.builtin.destroyed)\n          return DR_DESTROYED;\n\n     if (skirmish->multi.builtin.waiting)\n          fusion_skirmish_notify( skirmish );\n\n     skirmish->multi.builtin.destroyed = true;\n\n     return DR_OK;\n}\n\nstatic void restart_handler( int s ) {}\n\nDirectResult\nfusion_skirmish_wait( FusionSkirmish *skirmish,\n                      unsigned int    timeout )\n{\n     WaitNode         *node;\n     long long         stop;\n     struct sigaction  act, oldact;\n     sigset_t          mask, set;\n     DirectResult      ret = DR_OK;\n\n     D_ASSERT( skirmish != NULL );\n\n     if (skirmish->single) {\n          D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n          if (timeout)\n               return direct_waitqueue_wait_timeout( &skirmish->single->cond,\n                                                     &skirmish->single->lock, timeout * 1000 );\n\n          return direct_waitqueue_wait( &skirmish->single->cond, &skirmish->single->lock );\n     }\n\n     if (skirmish->multi.builtin.destroyed)\n          return DR_DESTROYED;\n\n     /* Set timeout. */\n     stop = direct_clock_get_micros() + timeout * 1000ll;\n\n     /* Add ourself to the list of waiting processes. */\n     node = SHMALLOC( skirmish->multi.shared->main_pool, sizeof(WaitNode) );\n     if (!node)\n          return D_OOSHM();\n\n     node->pid      = direct_gettid();\n     node->notified = false;\n\n     direct_list_append( &skirmish->multi.builtin.waiting, &node->link );\n\n     /* Install a (fake) signal handler for SIGRTMAX. */\n     act.sa_handler = restart_handler;\n     act.sa_flags   = SA_RESETHAND | SA_RESTART | SA_NODEFER;\n\n     sigaction( SIGRTMAX, &act, &oldact );\n\n     /* Unblock SIGRTMAX. */\n     sigprocmask( SIG_SETMASK, NULL, &mask );\n     sigdelset( &mask, SIGRTMAX );\n\n     fusion_skirmish_dismiss( skirmish );\n\n     while (!node->notified) {\n          if (timeout) {\n               long long now = direct_clock_get_micros();\n\n               if (now >= stop) {\n                    /* Stop notifying us. */\n                    node->notified = true;\n                    ret = DR_TIMEOUT;\n                    break;\n               }\n\n               sigprocmask( SIG_SETMASK, &mask, &set );\n               usleep( stop - now );\n               sigprocmask( SIG_SETMASK, &set, NULL );\n          }\n          else {\n               sigsuspend( &mask );\n          }\n     }\n\n     /* Flush pending signals. */\n     if (!sigpending( &set ) && sigismember( &set, SIGRTMAX ) > 0)\n          sigsuspend( &mask );\n\n     if (fusion_skirmish_prevail( skirmish ))\n          ret = DR_DESTROYED;\n\n     direct_list_remove( &skirmish->multi.builtin.waiting, &node->link );\n\n     SHFREE( skirmish->multi.shared->main_pool, node );\n\n     sigaction( SIGRTMAX, &oldact, NULL );\n\n     return ret;\n}\n\nDirectResult\nfusion_skirmish_notify( FusionSkirmish *skirmish )\n{\n     DirectResult  ret;\n     WaitNode     *node, *next;\n\n     D_ASSERT( skirmish != NULL );\n\n     if (skirmish->single) {\n          D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n          direct_waitqueue_broadcast( &skirmish->single->cond );\n\n          return DR_OK;\n     }\n\n     if (skirmish->multi.builtin.destroyed)\n          return DR_DESTROYED;\n\n     direct_list_foreach_safe (node, next, skirmish->multi.builtin.waiting) {\n          if (node->notified)\n               continue;\n\n          node->notified = true;\n\n          ret = direct_kill( node->pid, SIGRTMAX );\n          if (ret) {\n               if (ret == DR_NOSUCHINSTANCE) {\n                    /* Remove dead process. */\n                    direct_list_remove( &skirmish->multi.builtin.waiting, &node->link );\n                    SHFREE( skirmish->multi.shared->main_pool, node );\n               }\n               else {\n                    D_DERROR( ret, \"Fusion/Skirmish: Could not send notification signal!\\n\" );\n               }\n          }\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_add_permissions( FusionSkirmish            *skirmish,\n                                 FusionID                   fusion_id,\n                                 FusionSkirmishPermissions  skirmish_permissions )\n{\n     return DR_OK;\n}\n\n#endif /* FUSION_BUILD_KERNEL */\n\n#else /* FUSION_BUILD_MULTI */\n\nDirectResult\nfusion_skirmish_init( FusionSkirmish    *skirmish,\n                      const char        *name,\n                      const FusionWorld *world )\n{\n     D_ASSERT( skirmish != NULL );\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s' )\\n\", __FUNCTION__, skirmish, name ?: \"\" );\n\n     skirmish->single = D_CALLOC( 1, sizeof(FusionSkirmishSingle) + strlen( name ) + 1 );\n     if (skirmish->single == 0)\n          return DR_NOLOCALMEMORY;\n\n     skirmish->single->name = (char*) (skirmish->single + 1);\n     strcpy( skirmish->single->name, name );\n\n     direct_recursive_mutex_init( &skirmish->single->lock );\n     direct_waitqueue_init( &skirmish->single->cond );\n\n     D_MAGIC_SET( skirmish->single, FusionSkirmishSingle );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_init2( FusionSkirmish    *skirmish,\n                       const char        *name,\n                       const FusionWorld *world,\n                       bool               local )\n{\n     return fusion_skirmish_init( skirmish, name, world );\n}\n\nDirectResult\nfusion_skirmish_prevail( FusionSkirmish *skirmish )\n{\n     DirectResult ret;\n\n     D_ASSERT( skirmish != NULL );\n     D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s' )\\n\", __FUNCTION__, skirmish, skirmish->single->name );\n\n     ret = direct_mutex_lock( &skirmish->single->lock );\n     if (ret)\n          return ret;\n\n     skirmish->single->count++;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_swoop( FusionSkirmish *skirmish )\n{\n     DirectResult ret;\n\n     D_ASSERT( skirmish != NULL );\n     D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s' )\\n\", __FUNCTION__, skirmish, skirmish->single->name );\n\n     ret = direct_mutex_trylock( &skirmish->single->lock );\n     if (ret)\n          return ret;\n\n     skirmish->single->count++;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_lock_count( FusionSkirmish *skirmish,\n                            int            *lock_count )\n{\n     DirectResult ret;\n\n     D_ASSERT( skirmish != NULL );\n     D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n     D_ASSERT( lock_count != NULL );\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s' )\\n\", __FUNCTION__, skirmish, skirmish->single->name );\n\n     ret = direct_mutex_trylock( &skirmish->single->lock );\n     if (ret) {\n          *lock_count = 0;\n          return ret;\n     }\n\n     *lock_count = skirmish->single->count;\n\n     direct_mutex_unlock( &skirmish->single->lock );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_dismiss( FusionSkirmish *skirmish )\n{\n     D_ASSERT( skirmish != NULL );\n     D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s' )\\n\", __FUNCTION__, skirmish, skirmish->single->name );\n\n     skirmish->single->count--;\n\n     return direct_mutex_unlock( &skirmish->single->lock );\n}\n\nDirectResult\nfusion_skirmish_destroy( FusionSkirmish *skirmish )\n{\n     DirectResult ret;\n\n     D_ASSERT( skirmish != NULL );\n     D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s' )\\n\", __FUNCTION__, skirmish, skirmish->single->name );\n\n     direct_waitqueue_broadcast( &skirmish->single->cond );\n     direct_waitqueue_deinit( &skirmish->single->cond );\n\n     ret = direct_mutex_deinit( &skirmish->single->lock );\n\n     D_MAGIC_CLEAR( skirmish->single );\n\n     D_FREE( skirmish->single );\n\n     return ret;\n}\n\nDirectResult\nfusion_skirmish_wait( FusionSkirmish *skirmish,\n                      unsigned int    timeout )\n{\n     D_ASSERT( skirmish != NULL );\n     D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s' )\\n\", __FUNCTION__, skirmish, skirmish->single->name );\n\n     if (timeout)\n          return direct_waitqueue_wait_timeout( &skirmish->single->cond,\n                                                &skirmish->single->lock, timeout * 1000 );\n\n     return direct_waitqueue_wait( &skirmish->single->cond, &skirmish->single->lock );\n}\n\nDirectResult\nfusion_skirmish_notify( FusionSkirmish *skirmish )\n{\n     D_ASSERT( skirmish != NULL );\n     D_MAGIC_ASSERT( skirmish->single, FusionSkirmishSingle );\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, '%s' )\\n\", __FUNCTION__, skirmish, skirmish->single->name );\n\n     direct_waitqueue_broadcast( &skirmish->single->cond );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_skirmish_add_permissions( FusionSkirmish            *skirmish,\n                                 FusionID                   fusion_id,\n                                 FusionSkirmishPermissions  skirmish_permissions )\n{\n     return DR_OK;\n}\n\n#endif /* FUSION_BUILD_MULTI */\n\nstatic int\nptr_compare( const void *p1,\n             const void *p2 )\n{\n     return *(u32*) p1 - *(u32*) p2;\n}\n\nDirectResult\nfusion_skirmish_prevail_multi( FusionSkirmish **skirmishs,\n                               unsigned int     num )\n{\n     DirectResult    ret = DR_OK;\n     unsigned int    i;\n     FusionSkirmish *skirmishs_sorted[num];\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, %u )\\n\", __FUNCTION__, skirmishs, num );\n\n     direct_memcpy( skirmishs_sorted, skirmishs, num * sizeof(FusionSkirmish*) );\n\n     qsort( skirmishs_sorted, num, sizeof(FusionSkirmish*), ptr_compare );\n\n     for (i = 0; i < num; i++) {\n          ret = fusion_skirmish_prevail( skirmishs_sorted[i] );\n          if (ret) {\n               D_DERROR( ret, \"Fusion/Skirmish: Failed at index %u, skirmish_id [0x%08x]\\n\",\n                         i, (unsigned int) skirmishs_sorted[i]->multi.id );\n               break;\n          }\n     }\n\n     if (ret) {\n          for (--i; i >= 0; i--)\n               fusion_skirmish_dismiss( skirmishs_sorted[i] );\n     }\n\n     return ret;\n}\n\nDirectResult\nfusion_skirmish_dismiss_multi( FusionSkirmish **skirmishs,\n                               unsigned int     num )\n{\n     DirectResult    ret = DR_OK, ret2;\n     unsigned int    i;\n     FusionSkirmish *skirmishs_sorted[num];\n\n     D_DEBUG_AT( Fusion_Skirmish, \"%s( %p, %u )\\n\", __FUNCTION__, skirmishs, num );\n\n     direct_memcpy( skirmishs_sorted, skirmishs, num * sizeof(FusionSkirmish*) );\n\n     qsort( skirmishs_sorted, num, sizeof(FusionSkirmish*), ptr_compare );\n\n     for (i = 0; i < num; i++) {\n          ret2 = fusion_skirmish_dismiss( skirmishs_sorted[i] );\n          if (ret2) {\n               D_DERROR( ret, \"Fusion/Skirmish: Failed at index %u, skirmish_id [0x%08x]\\n\",\n                         i, (unsigned int) skirmishs_sorted[i]->multi.id );\n               ret = ret2;\n          }\n     }\n\n     return ret;\n}\n"
  },
  {
    "path": "lib/fusion/lock.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FUSION__LOCK_H__\n#define __FUSION__LOCK_H__\n\n#include <direct/debug.h>\n#include <direct/waitqueue.h>\n#include <fusion/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int              magic;\n     DirectMutex      lock;\n     DirectWaitQueue  cond;\n     int              count;\n     char            *name;\n} FusionSkirmishSingle;\n\ntypedef struct {\n     /* multi app */\n     struct {\n          int                      id;\n          const FusionWorldShared *shared;\n          /* builtin impl */\n          struct {\n               unsigned int        locked;\n               pid_t               owner;\n               DirectLink         *waiting;\n               bool                requested;\n               bool                destroyed;\n          } builtin;\n     } multi;\n\n     /* single app */\n     FusionSkirmishSingle         *single;\n} FusionSkirmish;\n\ntypedef enum {\n     FUSION_SKIRMISH_PERMIT_NONE       = 0x00000000,\n\n     FUSION_SKIRMISH_PERMIT_PREVAIL    = 0x00000001,\n     FUSION_SKIRMISH_PERMIT_SWOOP      = 0x00000002,\n     FUSION_SKIRMISH_PERMIT_DISMISS    = 0x00000004,\n     FUSION_SKIRMISH_PERMIT_LOCK_COUNT = 0x00000008,\n     FUSION_SKIRMISH_PERMIT_WAIT       = 0x00000010,\n     FUSION_SKIRMISH_PERMIT_NOTIFY     = 0x00000020,\n     FUSION_SKIRMISH_PERMIT_DESTROY    = 0x00000040,\n\n     FUSION_SKIRMISH_PERMIT_ALL        = 0x0000007F\n} FusionSkirmishPermissions;\n\n#if D_DEBUG_ENABLED\n#define FUSION_SKIRMISH_ASSERT(skirmish)                                            \\\n     do {                                                                           \\\n          int lock_count;                                                           \\\n                                                                                    \\\n          D_ASSERT( skirmish != NULL );                                             \\\n          D_ASSERT( fusion_skirmish_lock_count( skirmish, &lock_count ) == DR_OK ); \\\n          D_ASSERT( lock_count > 0 );                                               \\\n     } while (0)\n#else\n#define FUSION_SKIRMISH_ASSERT(skirmish)                                            \\\n     do {                                                                           \\\n     } while (0)\n#endif\n\n/**********************************************************************************************************************/\n\n/*\n * Initialize.\n */\nDirectResult FUSION_API fusion_skirmish_init           ( FusionSkirmish             *skirmish,\n                                                         const char                 *name,\n                                                         const FusionWorld          *world );\n\n/*\n * Initialize with 'local' to create a fake skirmish (simple mutex).\n * This can be used by secure fusion mode when skirmishs are no longer locked by slaves at all.\n */\nDirectResult FUSION_API fusion_skirmish_init2          ( FusionSkirmish             *skirmish,\n                                                         const char                 *name,\n                                                         const FusionWorld          *world,\n                                                         bool                        local );\n\n/*\n * Lock.\n */\nDirectResult FUSION_API fusion_skirmish_prevail        ( FusionSkirmish             *skirmish );\n\n/*\n * Try lock.\n */\nDirectResult FUSION_API fusion_skirmish_swoop          ( FusionSkirmish             *skirmish );\n\n/*\n * Find out how many times current thread has acquired lock.\n */\nDirectResult FUSION_API fusion_skirmish_lock_count     ( FusionSkirmish             *skirmish,\n                                                         int                        *lock_count );\n\n/*\n * Unlock.\n */\nDirectResult FUSION_API fusion_skirmish_dismiss        ( FusionSkirmish             *skirmish );\n\n/*\n * Deinitialize.\n */\nDirectResult FUSION_API fusion_skirmish_destroy        ( FusionSkirmish             *skirmish );\n\n/*\n * Wait.\n */\nDirectResult FUSION_API fusion_skirmish_wait           ( FusionSkirmish             *skirmish,\n                                                         unsigned int                timeout );\n\n/*\n * Notify.\n */\nDirectResult FUSION_API fusion_skirmish_notify         ( FusionSkirmish             *skirmish );\n\n/*\n * Give permissions to another fusionee to use the skirmish.\n */\nDirectResult FUSION_API fusion_skirmish_add_permissions( FusionSkirmish             *skimrish,\n                                                         FusionID                    fusion_id,\n                                                         FusionSkirmishPermissions   permissions );\n\n/*\n * Lock by sorting by pointer first, so locks are always taken in same order.\n */\nDirectResult FUSION_API fusion_skirmish_prevail_multi  ( FusionSkirmish            **skirmishs,\n                                                         unsigned int                num );\n\n/*\n * Unlock by sorting by pointer first.\n */\nDirectResult FUSION_API fusion_skirmish_dismiss_multi  ( FusionSkirmish            **skirmishs,\n                                                         unsigned int                num );\n\n#endif\n"
  },
  {
    "path": "lib/fusion/meson.build",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\nfusion_sources = [\n  'arena.c',\n  'call.c',\n  'conf.c',\n  'fusion.c',\n  'hash.c',\n  'init.c',\n  'lock.c',\n  'object.c',\n  'reactor.c',\n  'ref.c',\n  'shmalloc.c',\n  'vector.c'\n]\n\nfusion_headers = [\n  'arena.h',\n  'call.h',\n  'conf.h',\n  'fusion.h',\n  'hash.h',\n  'lock.h',\n  'object.h',\n  'protocol.h',\n  'reactor.h',\n  'ref.h',\n  'shmalloc.h',\n  'types.h',\n  'vector.h',\n]\n\nif get_option('multi')\n  shm_sources = [\n    'shm/heap.c',\n    'shm/pool.c',\n    'shm/shm.c'\n  ]\nelse\n  shm_sources = 'shm/fake.c'\nendif\n\nshm_headers = [\n  'shm/pool.h'\n]\n\nbuild_conf = configuration_data()\n\nif get_option('multi')\n  if get_option('os') == 'linux'\n    if get_option('multi-kernel') and cc.has_header('linux/fusion.h')\n        build_conf.set('FUSION_BUILD_KERNEL', 1)\n    else\n        build_conf.set('FUSION_BUILD_KERNEL', 0)\n    endif\n  endif\n  build_conf.set('FUSION_MESSAGE_SIZE', get_option('message-size'))\nendif\n\nbuild_conf.set10('FUSION_BUILD_MULTI', get_option('multi'))\n\nconfigure_file(configuration: build_conf,\n               output: 'build.h',\n               install: true,\n               install_dir: get_option('includedir') / 'directfb/fusion')\n\nfusion_private = []\nif get_option('default_library') == 'static'\n  fusion_private = 'direct'\nendif\n\nlibfusion_private = []\nif get_option('default_library') == 'static' and get_option('constructors')\n  libfusion_private = '-Wl,-u,__Fusion_init_all'\nendif\n\nlibfusion = library('fusion-@0@.@1@'.format(directfb_major_version, directfb_minor_version),\n                    fusion_sources, shm_sources,\n                    include_directories: [config_inc, lib_inc],\n                    build_rpath: get_option('prefix') / get_option('libdir'),\n                    dependencies: direct_dep,\n                    version: '0.@0@.0'.format(directfb_micro_version),\n                    install: true,\n                    install_rpath: get_option('prefix') / get_option('libdir'))\n\ninstall_symlink('libfusion' + libsuffix,\n                pointing_to: 'libfusion-@0@.@1@'.format(directfb_major_version, directfb_minor_version) + libsuffix,\n                install_dir: get_option('prefix') / get_option('libdir'))\n\ninstall_headers(fusion_headers, subdir: 'directfb/fusion')\ninstall_headers(shm_headers,    subdir: 'directfb/fusion/shm')\n\npkgconfig.generate(filebase: 'fusion',\n                   name: 'Fusion',\n                   description: 'DirectFB IPC library',\n                   requires_private: fusion_private,\n                   libraries: '-L${libdir} -lfusion',\n                   libraries_private: libfusion_private,\n                   subdirs: 'directfb')\n\nfusion_dep = declare_dependency(include_directories: lib_inc, link_with: libfusion)\n"
  },
  {
    "path": "lib/fusion/object.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/trace.h>\n#include <fusion/conf.h>\n#include <fusion/fusion_internal.h>\n#include <fusion/hash.h>\n#include <fusion/object.h>\n#include <fusion/shmalloc.h>\n\nD_DEBUG_DOMAIN( Fusion_Object,       \"Fusion/Object\",       \"Fusion Objects and Pools\" );\nD_DEBUG_DOMAIN( Fusion_Object_Owner, \"Fusion/Object/Owner\", \"Fusion Objects and Pools Owner\" );\n\n/**********************************************************************************************************************/\n\nstatic FusionCallHandlerResult\nobject_reference_watcher( int           caller,\n                          int           call_arg,\n                          void         *call_ptr,\n                          void         *ctx,\n                          unsigned int  serial,\n                          int          *ret_val )\n{\n     FusionObject     *object;\n     FusionObjectPool *pool = ctx;\n\n     D_DEBUG_AT( Fusion_Object, \"%s( %d, %d, %p, %p, %u, %p )\\n\", __FUNCTION__,\n                 caller, call_arg, call_ptr, ctx, serial, ret_val );\n\n#if FUSION_BUILD_MULTI && FUSION_BUILD_KERNEL\n     if (caller && !pool->secure) {\n          D_BUG( \"call not coming from fusion device (caller %d)\", caller );\n          return FCHR_RETURN;\n     }\n#endif /* FUSION_BUILD_MULTI && FUSION_BUILD_KERNEL */\n\n     D_MAGIC_ASSERT( pool, FusionObjectPool );\n\n     /* Lock the pool. */\n     if (fusion_skirmish_prevail( &pool->lock ))\n          return FCHR_RETURN;\n\n     /* Lookup the object. */\n     object = fusion_hash_lookup( pool->objects, (void*)(long) call_arg );\n\n     D_DEBUG_AT( Fusion_Object, \"  -> lookup %p\\n\", object );\n\n     if (object) {\n          D_MAGIC_ASSERT( object, FusionObject );\n\n          D_DEBUG_AT( Fusion_Object, \"  -> %p [id %u] ref [%d] | [0x%08x] (single %d) identity %lu\\n\",\n                      object, object->id, object->ref.multi.id, (unsigned int) object->ref.multi.id,\n                      object->ref.single.refs, object->identity );\n\n          if (object->ref.single.dead) {\n               object->ref.single.dead--;\n\n               if (object->ref.single.dead) {\n                    D_DEBUG_AT( Fusion_Object, \"  -> died multiple times (%d more), skipping...\\n\",\n                                object->ref.single.dead );\n\n                    fusion_skirmish_dismiss( &pool->lock );\n                    return FCHR_RETURN;\n               }\n          }\n\n          switch (fusion_ref_zero_trylock( &object->ref )) {\n               case DR_OK:\n                    break;\n\n               case DR_DESTROYED:\n                    D_BUG( \"%p [%u] in '%s' already destroyed\", object, object->id, pool->name );\n\n                    fusion_hash_remove( pool->objects, (void*)(long) object->id, NULL, NULL );\n                    fusion_skirmish_dismiss( &pool->lock );\n                    return FCHR_RETURN;\n\n               default:\n                    D_ERROR( \"Fusion/Object: Error locking ref of %p [%u] in '%s'!\\n\", object, object->id, pool->name );\n                    /* fall through */\n\n               case DR_BUSY:\n                    fusion_skirmish_dismiss( &pool->lock );\n                    return FCHR_RETURN;\n          }\n\n          D_DEBUG_AT( Fusion_Object, \"  -> dead object %p [%u] (ref [%d] | [0x%08x])\\n\", object, object->id,\n                      object->ref.multi.id, (unsigned int) object->ref.multi.id );\n\n          if (object->state == FOS_INIT) {\n               D_WARN( \"won't destroy incomplete object, leaking some memory\" );\n               fusion_hash_remove( pool->objects, (void*)(long) object->id, NULL, NULL );\n               fusion_skirmish_dismiss( &pool->lock );\n               return FCHR_RETURN;\n          }\n\n          /* Set \"deinitializing\" state. */\n          object->state = FOS_DEINIT;\n\n          /* Remove the object from the pool. */\n          object->pool = NULL;\n          fusion_hash_remove( pool->objects, (void*)(long) object->id, NULL, NULL );\n\n          /* Unlock the pool. */\n          fusion_skirmish_dismiss( &pool->lock );\n\n          D_DEBUG_AT( Fusion_Object, \"  -> calling destructor...\\n\" );\n\n          /* Call the destructor. */\n          pool->destructor( object, false, pool->ctx );\n\n          D_DEBUG_AT( Fusion_Object, \"  -> destructor done\\n\" );\n\n          return FCHR_RETURN;\n     }\n\n     D_BUG( \"unknown object [%d] in '%s'\", call_arg, pool->name );\n\n     /* Unlock the pool. */\n     fusion_skirmish_dismiss( &pool->lock );\n\n     return FCHR_RETURN;\n}\n\nFusionObjectPool *\nfusion_object_pool_create( const char             *name,\n                           int                     object_size,\n                           int                     message_size,\n                           FusionObjectDestructor  destructor,\n                           void                   *ctx,\n                           const FusionWorld      *world )\n{\n     FusionObjectPool *pool;\n\n     D_ASSERT( name != NULL );\n     D_ASSERT( object_size >= sizeof(FusionObject) );\n     D_ASSERT( destructor != NULL );\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     D_DEBUG_AT( Fusion_Object, \"%s( '%s' )\\n\", __FUNCTION__, name );\n\n     /* Allocate shared memory for the pool. */\n     pool = SHCALLOC( world->shared->main_pool, 1, sizeof(FusionObjectPool) );\n     if (!pool) {\n          D_OOSHM();\n          return NULL;\n     }\n\n     /* Initialize the pool lock. */\n     if (fusion_config->secure_fusion)\n          fusion_skirmish_init2( &pool->lock, name, world, true );\n     else {\n          fusion_skirmish_init2( &pool->lock, name, world, false );\n\n          fusion_skirmish_add_permissions( &pool->lock, 0,\n                                           FUSION_SKIRMISH_PERMIT_PREVAIL | FUSION_SKIRMISH_PERMIT_DISMISS );\n     }\n\n     /* Fill information. */\n     pool->shared       = world->shared;\n     pool->name         = SHSTRDUP( world->shared->main_pool, name );\n     pool->object_size  = object_size;\n     pool->message_size = message_size;\n     pool->destructor   = destructor;\n     pool->ctx          = ctx;\n     pool->secure       = fusion_config->secure_fusion;\n\n     fusion_hash_create( world->shared->main_pool, HASH_INT, HASH_PTR, 17, &pool->objects );\n\n     /* Destruction call from Fusion. */\n     fusion_call_init( &pool->call, object_reference_watcher, pool, world );\n     fusion_call_set_name( &pool->call, \"object_reference_watcher\" );\n\n     D_MAGIC_SET( pool, FusionObjectPool );\n\n     return pool;\n}\n\nDirectResult\nfusion_object_pool_destroy( FusionObjectPool *pool,\n                            FusionWorld      *world,\n                            bool              shutdown_info )\n{\n     DirectResult        ret;\n     FusionObject       *object;\n     FusionHashIterator  it;\n\n     D_MAGIC_ASSERT( pool, FusionObjectPool );\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n     D_ASSERT( world->shared == pool->shared );\n\n     D_DEBUG_AT( Fusion_Object, \"%s( %p '%s' )\\n\", __FUNCTION__, pool, pool->name );\n\n     D_DEBUG_AT( Fusion_Object, \"  -> destroying pool...\\n\" );\n\n     fusion_world_flush_calls( world, 1 );\n\n     D_DEBUG_AT( Fusion_Object, \"  -> locking...\\n\" );\n\n     /* Lock the pool. */\n     ret = fusion_skirmish_prevail( &pool->lock );\n     if (ret)\n          return ret;\n\n     /* Destroy the call. */\n     fusion_call_destroy( &pool->call );\n\n     /* Destroy zombies. */\n     fusion_hash_foreach (object, it, pool->objects) {\n          int refs;\n\n          fusion_ref_stat( &object->ref, &refs );\n\n          if (refs > 0) {\n               if (shutdown_info) {\n                    D_WARN( \"zombie %p [%u], refs %d (in %s) => ref [%d] | [0x%08x]\", object, object->id,\n                            refs, pool->name, object->ref.multi.id, (unsigned int) object->ref.multi.id );\n\n                    direct_trace_print_stack( object->create_stack );\n               }\n          }\n\n          D_DEBUG_AT( Fusion_Object, \"  -> %p [%u], refs %d\\n\", object, object->id, refs );\n\n          /* Set \"deinitializing\" state. */\n          object->state = FOS_DEINIT;\n\n          D_DEBUG_AT( Fusion_Object, \"  -> calling destructor...\\n\" );\n\n          /* Call the destructor. */\n          pool->destructor( object, refs > 0, pool->ctx );\n\n          D_DEBUG_AT( Fusion_Object, \"  -> destructor done\\n\" );\n     }\n\n     fusion_hash_destroy( pool->objects );\n\n     D_MAGIC_CLEAR( pool );\n\n     D_DEBUG_AT( Fusion_Object, \"  -> pool destroyed (%s)\\n\", pool->name );\n\n     /* Destroy the pool lock. */\n     fusion_skirmish_dismiss( &pool->lock );\n     fusion_skirmish_destroy( &pool->lock );\n\n     /* Deallocate shared memory. */\n     SHFREE( world->shared->main_pool, pool->name );\n     SHFREE( world->shared->main_pool, pool );\n\n     return DR_OK;\n}\n\ntypedef struct {\n     FusionObjectPool     *pool;\n     FusionObjectCallback  callback;\n     void                 *ctx;\n} ObjectIteratorContext;\n\nstatic bool\nobject_iterator( FusionHash *hash,\n                 void       *key,\n                 void       *value,\n                 void       *ctx )\n{\n     ObjectIteratorContext *context = ctx;\n     FusionObject          *object  = value;\n\n     D_MAGIC_ASSERT( object, FusionObject );\n\n     return !context->callback( context->pool, object, context->ctx );\n}\n\nDirectResult\nfusion_object_pool_enum( FusionObjectPool     *pool,\n                         FusionObjectCallback  callback,\n                         void                 *ctx )\n{\n     ObjectIteratorContext iterator_context;\n\n     D_MAGIC_ASSERT( pool, FusionObjectPool );\n     D_ASSERT( callback != NULL );\n\n     D_DEBUG_AT( Fusion_Object, \"%s( %p '%s' )\\n\", __FUNCTION__, pool, pool->name );\n\n     /* Lock the pool. */\n     if (fusion_skirmish_prevail( &pool->lock ))\n          return DR_FUSION;\n\n     iterator_context.pool     = pool;\n     iterator_context.callback = callback;\n     iterator_context.ctx      = ctx;\n\n     fusion_hash_iterate( pool->objects, object_iterator, &iterator_context );\n\n     /* Unlock the pool. */\n     fusion_skirmish_dismiss( &pool->lock );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_object_pool_size( FusionObjectPool *pool,\n                         size_t           *ret_size )\n{\n     D_MAGIC_ASSERT( pool, FusionObjectPool );\n\n     if (!ret_size)\n          return DR_INVARG;\n\n     *ret_size = fusion_hash_size( pool->objects );\n\n     return DR_OK;\n}\n\nFusionObject *\nfusion_object_create( FusionObjectPool  *pool,\n                      const FusionWorld *world,\n                      FusionID           identity )\n{\n     FusionObject *object;\n\n     D_MAGIC_ASSERT( pool, FusionObjectPool );\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n     D_ASSERT( world->shared == pool->shared );\n\n     D_DEBUG_AT( Fusion_Object, \"%s( %p '%s', identity %lu )\\n\", __FUNCTION__, pool, pool->name, identity );\n\n     /* Lock the pool. */\n     if (fusion_skirmish_prevail( &pool->lock ))\n          return NULL;\n\n     /* Allocate shared memory for the object. */\n     object = SHCALLOC( world->shared->main_pool, 1, pool->object_size );\n     if (!object) {\n          D_OOSHM();\n          fusion_skirmish_dismiss( &pool->lock );\n          return NULL;\n     }\n\n     /* Set \"initializing\" state. */\n     object->state = FOS_INIT;\n\n     /* Set object id. */\n     object->id = ++pool->id_pool;\n\n     object->identity = identity;\n\n     if (pool->secure || world->fusion_id == FUSION_ID_MASTER)\n          object->create_stack = direct_trace_copy_buffer( NULL );\n\n     /* Initialize the reference counter. */\n     if (fusion_ref_init2( &object->ref, pool->name, pool->secure, world )) {\n          SHFREE( world->shared->main_pool, object );\n          fusion_skirmish_dismiss( &pool->lock );\n          return NULL;\n     }\n\n     /* Increase the object's reference counter. */\n     fusion_ref_up( &object->ref, false );\n\n     /* Install handler for automatic destruction. */\n     if (fusion_ref_watch( &object->ref, &pool->call, object->id )) {\n          fusion_ref_destroy( &object->ref );\n          SHFREE( world->shared->main_pool, object );\n          fusion_skirmish_dismiss( &pool->lock );\n          return NULL;\n     }\n\n     /* Create a reactor for message dispatching. */\n     object->reactor = fusion_reactor_new( pool->message_size, pool->name, world );\n     if (!object->reactor) {\n          fusion_ref_destroy( &object->ref );\n          SHFREE( world->shared->main_pool, object );\n          fusion_skirmish_dismiss( &pool->lock );\n          return NULL;\n     }\n\n     fusion_reactor_set_lock( object->reactor, &pool->lock );\n\n     fusion_vector_init( &object->access, 1, world->shared->main_pool );\n     fusion_vector_init( &object->owners, 1, world->shared->main_pool );\n\n     /* Set pool/world back pointer. */\n     object->pool   = pool;\n     object->shared = world->shared;\n\n     /* Add the object to the pool. */\n     fusion_hash_insert( pool->objects, (void*)(long) object->id, object );\n\n     D_DEBUG_AT( Fusion_Object, \"  -> added object %p [%u] (ref [%d] | [0x%08x])\\n\", object, object->id,\n                 object->ref.multi.id, (unsigned int) object->ref.multi.id );\n\n     D_MAGIC_SET( object, FusionObject );\n\n     /* Unlock the pool. */\n     fusion_skirmish_dismiss( &pool->lock );\n\n     return object;\n}\n\nDirectResult\nfusion_object_get( FusionObjectPool  *pool,\n                   FusionObjectID     object_id,\n                   FusionObject     **ret_object )\n{\n     DirectResult  ret;\n     FusionObject *object = NULL;\n\n     D_MAGIC_ASSERT( pool, FusionObjectPool );\n     D_ASSERT( ret_object != NULL );\n\n     D_DEBUG_AT( Fusion_Object, \"%s( %p '%s', object_id %u )\\n\", __FUNCTION__, pool, pool->name, object_id );\n\n     /* Lock the pool. */\n     ret = fusion_skirmish_prevail( &pool->lock );\n     if (ret == DR_OK) {\n          object = fusion_hash_lookup( pool->objects, (void*)(long) object_id );\n          if (object) {\n               int refs;\n\n               ret = fusion_ref_stat( &object->ref, &refs );\n               if (ret == DR_OK) {\n                    D_DEBUG_AT( Fusion_Object, \"  -> refs %d\\n\", refs );\n\n                    if (refs > 0)\n                         ret = fusion_object_ref( object );\n                    else\n                         ret = DR_DEAD;\n               }\n          }\n          else {\n               D_DEBUG_AT( Fusion_Object, \"  -> not found\\n\" );\n               ret = DR_IDNOTFOUND;\n          }\n     }\n\n     if (ret == DR_OK)\n          *ret_object = object;\n\n     /* Unlock the pool. */\n     fusion_skirmish_dismiss( &pool->lock );\n\n     return ret;\n}\n\nDirectResult\nfusion_object_lookup( FusionObjectPool  *pool,\n                      FusionObjectID     object_id,\n                      FusionObject     **ret_object )\n{\n     DirectResult  ret    = DR_IDNOTFOUND;\n     FusionObject *object = NULL;\n\n     D_MAGIC_ASSERT( pool, FusionObjectPool );\n     D_ASSERT( ret_object != NULL );\n\n     D_DEBUG_AT( Fusion_Object, \"%s( %p '%s', object_id %u )\\n\", __FUNCTION__, pool, pool->name, object_id );\n\n     /* Lock the pool. */\n     if (fusion_skirmish_prevail( &pool->lock ))\n          return DR_FUSION;\n\n     object = fusion_hash_lookup( pool->objects, (void*)(long) object_id );\n     if (object) {\n          ret = DR_OK;\n     }\n     else\n          D_DEBUG_AT( Fusion_Object, \"  -> not found\\n\" );\n\n     *ret_object = object;\n\n     /* Unlock the pool. */\n     fusion_skirmish_dismiss( &pool->lock );\n\n     return ret;\n}\n\nDirectResult\nfusion_object_set_lock( FusionObject   *object,\n                        FusionSkirmish *lock )\n{\n     D_MAGIC_ASSERT( object, FusionObject );\n     D_ASSERT( lock != NULL );\n\n     D_ASSUME( object->state == FOS_INIT );\n\n     return fusion_reactor_set_lock_only( object->reactor, lock );\n}\n\nDirectResult\nfusion_object_activate( FusionObject *object )\n{\n     D_MAGIC_ASSERT( object, FusionObject );\n\n     /* Set active state. */\n     object->state = FOS_ACTIVE;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_object_destroy( FusionObject *object )\n{\n     FusionObjectPool *pool;\n     char             *access;\n     int               index;\n\n     D_MAGIC_ASSERT( object, FusionObject );\n     D_MAGIC_ASSERT( object->shared, FusionWorldShared );\n     D_ASSERT( object->state != FOS_ACTIVE );\n\n     pool = object->pool;\n\n     /* Set \"deinitializing\" state. */\n     object->state = FOS_DEINIT;\n\n     /* Remove the object from the pool. */\n     if (pool) {\n          D_MAGIC_ASSERT( pool, FusionObjectPool );\n\n          /* Lock the pool. */\n          if (fusion_skirmish_prevail( &pool->lock ))\n               return DR_FAILURE;\n\n          /* Remove the object from the pool. */\n          if (object->pool) {\n               D_ASSERT( object->pool == pool );\n\n               object->pool = NULL;\n\n               fusion_hash_remove( pool->objects, (void*)(long) object->id, NULL, NULL );\n          }\n\n          /* Unlock the pool. */\n          fusion_skirmish_dismiss( &pool->lock );\n     }\n\n     fusion_vector_foreach (access, index, object->access) {\n          SHFREE( object->shared->main_pool, access );\n     }\n\n     fusion_vector_destroy( &object->access );\n     fusion_vector_destroy( &object->owners );\n\n     fusion_ref_destroy( &object->ref );\n\n     fusion_reactor_free( object->reactor );\n\n     if (object->properties)\n          fusion_hash_destroy( object->properties );\n\n     if (object->create_stack)\n          direct_trace_free_buffer( object->create_stack );\n\n     D_MAGIC_CLEAR( object );\n     SHFREE( object->shared->main_pool, object );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_object_set_property( FusionObject  *object,\n                            const char    *key,\n                            void          *value,\n                            void         **old_value )\n{\n     DirectResult  ret;\n     char         *sharedkey;\n\n     D_MAGIC_ASSERT( object, FusionObject );\n     D_ASSERT( object->shared != NULL );\n     D_ASSERT( key != NULL );\n     D_ASSERT( value != NULL );\n\n     /* Create property hash on demand. */\n     if (!object->properties) {\n          ret = fusion_hash_create( object->shared->main_pool, HASH_STRING, HASH_PTR, FUSION_HASH_MIN_SIZE,\n                                    &object->properties );\n          if (ret)\n               return ret;\n     }\n\n     /* Create a shared copy of the key. */\n     sharedkey = SHSTRDUP( object->shared->main_pool, key );\n     if (!sharedkey)\n          return D_OOSHM();\n\n     /* Put it into the hash. */\n     ret = fusion_hash_replace( object->properties, sharedkey, value, NULL, old_value );\n     if (ret)\n          SHFREE( object->shared->main_pool, sharedkey );\n\n     return ret;\n}\n\nvoid *\nfusion_object_get_property( FusionObject *object,\n                            const char   *key )\n{\n     D_MAGIC_ASSERT( object, FusionObject );\n     D_ASSERT( key != NULL );\n\n     if (!object->properties)\n          return NULL;\n\n     return fusion_hash_lookup( object->properties, key );\n}\n\nvoid\nfusion_object_remove_property( FusionObject  *object,\n                               const char    *key,\n                               void         **old_value )\n{\n     D_MAGIC_ASSERT( object, FusionObject );\n     D_ASSERT( key != NULL );\n\n     if (!object->properties)\n          return;\n\n     fusion_hash_remove( object->properties, key, NULL, old_value );\n\n     if (fusion_hash_should_resize( object->properties ))\n          fusion_hash_resize( object->properties );\n}\n\nDirectResult\nfusion_object_add_access( FusionObject *object,\n                          const char   *executable )\n{\n     DirectResult  ret;\n     char         *copy;\n\n     D_DEBUG_AT( Fusion_Object, \"%s( %p, '%s' )\\n\", __FUNCTION__, object, executable );\n\n     D_MAGIC_ASSERT( object, FusionObject );\n     D_ASSERT( executable != NULL );\n\n     copy = SHSTRDUP( object->shared->main_pool, executable );\n     if (!copy)\n          return D_OOM();\n\n     ret = fusion_vector_add( &object->access, copy );\n     if (ret) {\n          SHFREE( object->shared->main_pool, copy );\n          return ret;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_object_has_access( FusionObject *object,\n                          const char   *executable )\n{\n     char *access;\n     int   index;\n\n     D_DEBUG_AT( Fusion_Object, \"%s( %p, '%s' )\\n\", __FUNCTION__, object, executable );\n\n     D_MAGIC_ASSERT( object, FusionObject );\n     D_ASSERT( executable != NULL );\n\n     fusion_vector_foreach (access, index, object->access) {\n          int len = strlen( access );\n\n          if (access[len-1] == '*') {\n               if (!strncmp( access, executable, len - 1 ))\n                    return DR_OK;\n          }\n          else\n               if (!strcmp( access, executable ))\n                    return DR_OK;\n     }\n\n     return DR_ACCESSDENIED;\n}\n\nDirectResult\nfusion_object_add_owner( FusionObject *object,\n                         FusionID      owner )\n{\n     FusionID id;\n     int      i;\n\n     D_DEBUG_AT( Fusion_Object, \"%s( %p, %lu )\\n\", __FUNCTION__, object, owner );\n\n     D_MAGIC_ASSERT( object, FusionObject );\n\n     fusion_vector_foreach (id, i, object->owners) {\n          if (id == owner)\n               return DR_OK;\n     }\n\n     D_DEBUG_AT( Fusion_Object_Owner, \"  -> add %lu (object %p id %u)\\n\", owner, object, object->id );\n\n     return fusion_vector_add( &object->owners, (void*) owner );\n}\n\nDirectResult\nfusion_object_check_owner( FusionObject *object,\n                           FusionID      owner,\n                           bool          succeed_if_not_owned )\n{\n     FusionID id;\n     int      i;\n\n     D_DEBUG_AT( Fusion_Object, \"%s( %p, %lu )\\n\", __FUNCTION__, object, owner );\n\n     D_MAGIC_ASSERT( object, FusionObject );\n\n     D_DEBUG_AT( Fusion_Object_Owner, \"  -> check %lu and %ssucceed if not owned (object %p id %u)\\n\",\n                 owner, succeed_if_not_owned ? \"\" : \"don't \", object, object->id );\n\n     if (succeed_if_not_owned && object->owners.count == 0) {\n          D_DEBUG_AT( Fusion_Object_Owner, \"    => SUCCESS (no owner)\\n\" );\n          return DR_OK;\n     }\n\n     fusion_vector_foreach (id, i, object->owners) {\n          if (id == owner) {\n               D_DEBUG_AT( Fusion_Object_Owner, \"    => SUCCESS (found as owner with index %d)\\n\", i );\n               return DR_OK;\n          }\n     }\n\n     D_DEBUG_AT( Fusion_Object_Owner, \"    => FAIL (not found)\\n\" );\n\n     return DR_IDNOTFOUND;\n}\n\nDirectResult\nfusion_object_catch( FusionObject *object )\n{\n     DirectResult ret;\n\n     D_MAGIC_ASSERT( object, FusionObject );\n\n     ret = fusion_ref_up( &object->ref, false );\n     if (ret)\n          return ret;\n\n     ret = fusion_ref_catch( &object->ref );\n     if (ret) {\n          D_DERROR( ret, \"Fusion/Object: Failed to catch reference [%d] | [0x%08x]!\\n\",\n                    object->ref.multi.id, (unsigned int) object->ref.multi.id );\n          fusion_ref_down( &object->ref, false );\n          return ret;\n     }\n\n     return DR_OK;\n}\n"
  },
  {
    "path": "lib/fusion/object.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FUSION__OBJECT_H__\n#define __FUSION__OBJECT_H__\n\n#include <fusion/call.h>\n#include <fusion/reactor.h>\n#include <fusion/ref.h>\n#include <fusion/vector.h>\n\n/**********************************************************************************************************************/\n\ntypedef u32 FusionObjectID;\n\ntypedef enum {\n     FOS_INIT   = 0x00000000,\n     FOS_ACTIVE = 0x00000001,\n     FOS_DEINIT = 0x00000002\n} FusionObjectState;\n\nstruct __Fusion_FusionObject {\n     DirectLink         link;\n     FusionObjectPool  *pool;\n\n     int                magic;\n\n     FusionObjectID     id;\n     FusionID           identity;\n\n     FusionObjectState  state;\n\n     FusionRef          ref;\n     FusionReactor     *reactor;\n\n     FusionWorldShared *shared;\n     FusionHash        *properties;\n\n     FusionVector       owners;\n\n     FusionVector       access;\n\n     DirectTraceBuffer *create_stack;\n\n     void              *type_instance;\n};\n\ntypedef void (*FusionObjectDestructor)( FusionObject *object, bool zombie, void *ctx );\n\nstruct __Fusion_FusionObjectPool {\n     int                     magic;\n\n     FusionWorldShared      *shared;\n\n     FusionSkirmish          lock;\n     FusionHash             *objects;\n     FusionObjectID          id_pool;\n\n     char                   *name;\n     int                     object_size;\n     int                     message_size;\n     FusionObjectDestructor  destructor;\n     void                   *ctx;\n\n     FusionCall              call;\n\n     bool                    secure;\n};\n\n/**********************************************************************************************************************/\n\ntypedef bool (*FusionObjectCallback)( FusionObjectPool *pool, FusionObject *object, void *ctx );\n\n/**********************************************************************************************************************/\n\nFusionObjectPool FUSION_API *fusion_object_pool_create    ( const char              *name,\n                                                            int                      object_size,\n                                                            int                      message_size,\n                                                            FusionObjectDestructor   destructor,\n                                                            void                    *ctx,\n                                                            const FusionWorld       *world );\n\nDirectResult     FUSION_API  fusion_object_pool_destroy   ( FusionObjectPool        *pool,\n                                                            FusionWorld             *world,\n                                                            bool                     shutdown_info );\n\nDirectResult     FUSION_API  fusion_object_pool_enum      ( FusionObjectPool        *pool,\n                                                            FusionObjectCallback     callback,\n                                                            void                    *ctx );\n\nDirectResult     FUSION_API  fusion_object_pool_size      ( FusionObjectPool        *pool,\n                                                            size_t                  *ret_size );\n\nFusionObject     FUSION_API *fusion_object_create         ( FusionObjectPool        *pool,\n                                                            const FusionWorld       *world,\n                                                            FusionID                 identity );\n\nDirectResult     FUSION_API  fusion_object_get            ( FusionObjectPool        *pool,\n                                                            FusionObjectID           object_id,\n                                                            FusionObject           **ret_object );\n\nDirectResult     FUSION_API  fusion_object_lookup         ( FusionObjectPool        *pool,\n                                                            FusionObjectID           object_id,\n                                                            FusionObject           **ret_object );\n\nDirectResult     FUSION_API  fusion_object_set_lock       ( FusionObject            *object,\n                                                            FusionSkirmish          *lock );\n\nDirectResult     FUSION_API  fusion_object_activate       ( FusionObject            *object );\n\nDirectResult     FUSION_API  fusion_object_destroy        ( FusionObject            *object );\n\nDirectResult     FUSION_API  fusion_object_set_property   ( FusionObject            *object,\n                                                            const char              *key,\n                                                            void                    *value,\n                                                            void                   **old_value );\n\nvoid             FUSION_API *fusion_object_get_property   ( FusionObject            *object,\n                                                            const char              *key );\n\nvoid             FUSION_API  fusion_object_remove_property( FusionObject            *object,\n                                                            const char              *key,\n                                                            void                   **ret_val );\n\nDirectResult     FUSION_API  fusion_object_add_access     ( FusionObject            *object,\n                                                            const char              *exectuable );\n\nDirectResult     FUSION_API  fusion_object_has_access     ( FusionObject            *object,\n                                                            const char              *executable );\n\nDirectResult     FUSION_API  fusion_object_add_owner      ( FusionObject            *object,\n                                                            FusionID                 owner );\n\nDirectResult     FUSION_API  fusion_object_check_owner    ( FusionObject            *object,\n                                                            FusionID                 owner,\n                                                            bool                     succeed_if_not_owned );\n\nDirectResult     FUSION_API  fusion_object_catch          ( FusionObject            *object );\n\n/**********************************************************************************************************************/\n\n#define FUSION_OBJECT_METHODS(type,prefix)                                                                        \\\n                                                                                                                  \\\nstatic __inline__ DirectResult                                                                                    \\\nprefix##_attach( type         *object,                                                                            \\\n                 ReactionFunc  func,                                                                              \\\n                 void         *ctx,                                                                               \\\n                 Reaction     *ret_reaction )                                                                     \\\n{                                                                                                                 \\\n     D_MAGIC_ASSERT( (FusionObject*) object, FusionObject );                                                      \\\n     return fusion_reactor_attach( ((FusionObject*) object)->reactor, func, ctx, ret_reaction );                  \\\n}                                                                                                                 \\\n                                                                                                                  \\\nstatic __inline__ DirectResult                                                                                    \\\nprefix##_attach_channel( type         *object,                                                                    \\\n                         int           channel,                                                                   \\\n                         ReactionFunc  func,                                                                      \\\n                         void         *ctx,                                                                       \\\n                         Reaction     *ret_reaction )                                                             \\\n{                                                                                                                 \\\n     D_MAGIC_ASSERT( (FusionObject*) object, FusionObject );                                                      \\\n     return fusion_reactor_attach_channel( ((FusionObject*) object)->reactor, channel, func, ctx, ret_reaction ); \\\n}                                                                                                                 \\\n                                                                                                                  \\\nstatic __inline__ DirectResult                                                                                    \\\nprefix##_detach( type     *object,                                                                                \\\n                 Reaction *reaction )                                                                             \\\n{                                                                                                                 \\\n     D_MAGIC_ASSERT( (FusionObject*) object, FusionObject );                                                      \\\n     return fusion_reactor_detach( ((FusionObject*) object)->reactor, reaction );                                 \\\n}                                                                                                                 \\\n                                                                                                                  \\\nstatic __inline__ DirectResult                                                                                    \\\nprefix##_attach_global( type           *object,                                                                   \\\n                        int             index,                                                                    \\\n                        void           *ctx,                                                                      \\\n                        GlobalReaction *reaction )                                                                \\\n{                                                                                                                 \\\n     D_MAGIC_ASSERT( (FusionObject*) object, FusionObject );                                                      \\\n     return fusion_reactor_attach_global( ((FusionObject*) object)->reactor, index, ctx, reaction );              \\\n}                                                                                                                 \\\n                                                                                                                  \\\nstatic __inline__ DirectResult                                                                                    \\\nprefix##_detach_global( type           *object,                                                                   \\\n                        GlobalReaction *reaction )                                                                \\\n{                                                                                                                 \\\n     D_MAGIC_ASSERT( (FusionObject*) object, FusionObject );                                                      \\\n     return fusion_reactor_detach_global( ((FusionObject*) object)->reactor, reaction );                          \\\n}                                                                                                                 \\\n                                                                                                                  \\\nstatic __inline__ DirectResult                                                                                    \\\nprefix##_dispatch( type               *object,                                                                    \\\n                   void               *message,                                                                   \\\n                   const ReactionFunc *globals )                                                                  \\\n{                                                                                                                 \\\n     D_MAGIC_ASSERT( (FusionObject*) object, FusionObject );                                                      \\\n     return fusion_reactor_dispatch( ((FusionObject*) object)->reactor, message, true, globals );                 \\\n}                                                                                                                 \\\n                                                                                                                  \\\nstatic __inline__ DirectResult                                                                                    \\\nprefix##_dispatch_channel( type               *object,                                                            \\\n                           int                 channel,                                                           \\\n                           void               *message,                                                           \\\n                           int                 size,                                                              \\\n                           const ReactionFunc *globals )                                                          \\\n{                                                                                                                 \\\n     D_MAGIC_ASSERT( (FusionObject*) object, FusionObject );                                                      \\\n     return fusion_reactor_dispatch_channel( ((FusionObject*) object)->reactor,                                   \\\n                                             channel, message, size, true, globals );                             \\\n}                                                                                                                 \\\n                                                                                                                  \\\nstatic __inline__ DirectResult                                                                                    \\\nprefix##_ref( type *object )                                                                                      \\\n{                                                                                                                 \\\n     D_MAGIC_ASSERT( (FusionObject*) object, FusionObject );                                                      \\\n     return fusion_ref_up( &((FusionObject*) object)->ref, false );                                               \\\n}                                                                                                                 \\\n                                                                                                                  \\\nstatic __inline__ DirectResult                                                                                    \\\nprefix##_unref( type *object )                                                                                    \\\n{                                                                                                                 \\\n     D_MAGIC_ASSERT( (FusionObject*) object, FusionObject );                                                      \\\n     return fusion_ref_down( &((FusionObject*) object)->ref, false );                                             \\\n}                                                                                                                 \\\n                                                                                                                  \\\nstatic __inline__ DirectResult                                                                                    \\\nprefix##_ref_stat( type *object, int *refs )                                                                      \\\n{                                                                                                                 \\\n     D_MAGIC_ASSERT( (FusionObject*) object, FusionObject );                                                      \\\n     return fusion_ref_stat ( &((FusionObject*) object)->ref, refs );                                             \\\n}                                                                                                                 \\\n                                                                                                                  \\\nstatic __inline__ DirectResult                                                                                    \\\nprefix##_link( type **link,                                                                                       \\\n               type  *object )                                                                                    \\\n{                                                                                                                 \\\n     DirectResult ret;                                                                                            \\\n                                                                                                                  \\\n     D_MAGIC_ASSERT( (FusionObject*) object, FusionObject );                                                      \\\n                                                                                                                  \\\n     ret = fusion_ref_up( &((FusionObject*) object)->ref, true );                                                 \\\n     if (ret)                                                                                                     \\\n          return ret;                                                                                             \\\n                                                                                                                  \\\n     *link = object;                                                                                              \\\n                                                                                                                  \\\n     return DR_OK;                                                                                                \\\n}                                                                                                                 \\\n                                                                                                                  \\\nstatic __inline__ DirectResult                                                                                    \\\nprefix##_unlink( type **link )                                                                                    \\\n{                                                                                                                 \\\n     type *object = *link;                                                                                        \\\n                                                                                                                  \\\n     D_MAGIC_ASSERT( (FusionObject*) object, FusionObject );                                                      \\\n                                                                                                                  \\\n     *link = NULL;                                                                                                \\\n                                                                                                                  \\\n     return fusion_ref_down( &((FusionObject*) object)->ref, true );                                              \\\n}                                                                                                                 \\\n                                                                                                                  \\\nstatic __inline__ DirectResult                                                                                    \\\nprefix##_inherit( type *object,                                                                                   \\\n                  void *from )                                                                                    \\\n{                                                                                                                 \\\n     D_MAGIC_ASSERT( (FusionObject*) object, FusionObject );                                                      \\\n     D_MAGIC_ASSERT( (FusionObject*) from, FusionObject );                                                        \\\n                                                                                                                  \\\n     return fusion_ref_inherit( &((FusionObject*) object)->ref, &((FusionObject*) from)->ref );                   \\\n}                                                                                                                 \\\n                                                                                                                  \\\nstatic __inline__ DirectResult                                                                                    \\\nprefix##_globalize( type *object )                                                                                \\\n{                                                                                                                 \\\n     DirectResult ret;                                                                                            \\\n                                                                                                                  \\\n     D_MAGIC_ASSERT( (FusionObject*) object, FusionObject );                                                      \\\n                                                                                                                  \\\n     ret = fusion_ref_up( &((FusionObject*) object)->ref, true );                                                 \\\n     if (ret)                                                                                                     \\\n          return ret;                                                                                             \\\n                                                                                                                  \\\n     ret = fusion_ref_down( &((FusionObject*) object)->ref, false );                                              \\\n     if (ret)                                                                                                     \\\n          fusion_ref_down( &((FusionObject*) object)->ref, true );                                                \\\n                                                                                                                  \\\n     return ret;                                                                                                  \\\n}\n\nFUSION_OBJECT_METHODS( void, fusion_object )\n\n#endif\n"
  },
  {
    "path": "lib/fusion/protocol.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FUSION_PROTOCOL_H__\n#define __FUSION_PROTOCOL_H__\n\n#include <fusion/call.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     FMT_SEND    = 0x00000000,\n     FMT_ENTER   = 0x00000001,\n     FMT_LEAVE   = 0x00000002,\n     FMT_CALL    = 0x00000003,\n     FMT_CALLRET = 0x00000004,\n     FMT_REACTOR = 0x00000005\n} FusionMessageType;\n\n/*\n * Enter world (slave).\n */\ntypedef struct {\n     FusionMessageType type;\n\n     FusionID          fusion_id;\n} FusionEnter;\n\n/*\n * Leave the world (slave).\n */\ntypedef struct {\n     FusionMessageType type;\n\n     FusionID          fusion_id;\n} FusionLeave;\n\n/*\n * Execute a call.\n */\ntypedef struct {\n     FusionMessageType    type;\n\n     unsigned int         serial;\n\n     FusionID             caller;\n     int                  call_id;\n     int                  call_arg;\n     unsigned int         call_length; /* Length of data. */\n     unsigned int         ret_length;  /* Maximum length of return data. */\n\n     void                *handler;\n     void                *handler3;\n     void                *ctx;\n\n     FusionCallExecFlags  flags;\n} FusionCallMessage;\n\n/*\n * Send call return.\n */\ntypedef struct {\n     FusionMessageType type;\n\n     unsigned int      length;\n} FusionCallReturn;\n\n/*\n * Send reactor message.\n */\ntypedef struct {\n     FusionMessageType  type;\n\n     int                id;\n     int                channel;\n\n     FusionRef         *ref;\n} FusionReactorMessage;\n\ntypedef union {\n     FusionMessageType    type;\n\n     FusionEnter          enter;\n     FusionLeave          leave;\n     FusionCallMessage    call;\n     FusionCallReturn     callret;\n     FusionReactorMessage reactor;\n} FusionMessage;\n\n#endif\n"
  },
  {
    "path": "lib/fusion/reactor.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/mem.h>\n#include <fusion/fusion_internal.h>\n#include <fusion/reactor.h>\n\n#if FUSION_BUILD_MULTI\n\n#include <fusion/shmalloc.h>\n\n#if FUSION_BUILD_KERNEL\n#include <fusion/conf.h>\n#if D_DEBUG_ENABLED\n#include <direct/trace.h>\n#endif\n#else /* FUSION_BUILD_KERNEL */\n#include <direct/memcpy.h>\n#endif /* FUSION_BUILD_KERNEL */\n\n#endif /* FUSION_BUILD_MULTI */\n\nD_DEBUG_DOMAIN( Fusion_Reactor, \"Fusion/Reactor\", \"Fusion's Reactor\" );\n\n/**********************************************************************************************************************/\n\nstatic void process_globals( FusionReactor *reactor, const void *msg_data, const ReactionFunc *globals );\n\n#if FUSION_BUILD_MULTI\n\ntypedef struct {\n     DirectLink     link;\n\n     int            magic;\n\n     DirectRWLock   lock;\n\n     int            reactor_id;\n     FusionReactor *reactor;\n\n     DirectLink    *links;      /* Reactor listeners attached to node. */\n} ReactorNode;\n\ntypedef struct {\n     DirectLink         link;\n\n     int                magic;\n\n     Reaction          *reaction;\n     int                channel;\n} NodeLink;\n\nstatic void\nremove_node_link( ReactorNode *node,\n                  NodeLink    *link )\n{\n     D_MAGIC_ASSERT( node, ReactorNode );\n     D_MAGIC_ASSERT( link, NodeLink );\n\n     D_ASSUME( link->reaction == NULL );\n\n     direct_list_remove( &node->links, &link->link );\n\n     D_MAGIC_CLEAR( link );\n\n     D_FREE( link );\n}\n\nstatic ReactorNode *lock_node  ( int reactor_id, bool add_it, bool wlock, FusionReactor *reactor, FusionWorld *world );\nstatic void         unlock_node( ReactorNode *node );\n\n#if FUSION_BUILD_KERNEL\n\nFusionReactor *\nfusion_reactor_new( int                msg_size,\n                    const char        *name,\n                    const FusionWorld *world )\n{\n     FusionEntryInfo  info;\n     FusionReactor   *reactor;\n\n     D_ASSERT( name != NULL );\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( '%s', size %d )\\n\", __FUNCTION__, name, msg_size );\n\n     /* Allocate shared reactor data. */\n     reactor = SHCALLOC( world->shared->main_pool, 1, sizeof(FusionReactor) );\n     if (!reactor) {\n          D_OOSHM();\n          return NULL;\n     }\n\n     /* Create a new reactor. */\n     while (ioctl( world->fusion_fd, FUSION_REACTOR_NEW, &reactor->id )) {\n          if (errno == EINTR)\n              continue;\n\n          D_PERROR( \"Fusion/Reactor: FUSION_REACTOR_NEW\" );\n          SHFREE( world->shared->main_pool, reactor );\n          return NULL;\n     }\n\n     /* Set the static message size. */\n     reactor->msg_size = msg_size;\n\n     /* Set default lock for global reactions. */\n     reactor->globals_lock = &world->shared->reactor_globals;\n\n     D_DEBUG_AT( Fusion_Reactor, \"  -> new reactor %p [%d] with lock %p [%d]\\n\",\n                 reactor, reactor->id, reactor->globals_lock, reactor->globals_lock->multi.id );\n\n     reactor->shared = world->shared;\n     reactor->direct = true;\n\n     D_MAGIC_SET( reactor, FusionReactor );\n\n     info.type = FT_REACTOR;\n     info.id   = reactor->id;\n\n     direct_snputs( info.name, name, sizeof(info.name) );\n\n     ioctl( world->fusion_fd, FUSION_ENTRY_SET_INFO, &info );\n\n     return reactor;\n}\n\nDirectResult\nfusion_reactor_destroy( FusionReactor *reactor )\n{\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_MAGIC_ASSERT( reactor->shared, FusionWorldShared );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p [%d] )\\n\", __FUNCTION__, reactor, reactor->id );\n\n     D_ASSUME( !reactor->destroyed );\n\n     if (reactor->destroyed)\n          return DR_DESTROYED;\n\n     while (ioctl( _fusion_fd( reactor->shared ), FUSION_REACTOR_DESTROY, &reactor->id )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n\n               case EINVAL:\n                    D_ERROR( \"Fusion/Reactor: Invalid reactor!\\n\" );\n                    return DR_DESTROYED;\n          }\n\n          D_PERROR( \"Fusion/Reactor: FUSION_REACTOR_DESTROY\" );\n          return DR_FUSION;\n     }\n\n     reactor->destroyed = true;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_free( FusionReactor *reactor )\n{\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_MAGIC_ASSERT( reactor->shared, FusionWorldShared );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p [%d] )\\n\", __FUNCTION__, reactor, reactor->id );\n\n     D_MAGIC_CLEAR( reactor );\n\n     if (!reactor->destroyed)\n          while (ioctl( _fusion_fd( reactor->shared ), FUSION_REACTOR_DESTROY, &reactor->id ) && errno == EINTR);\n\n     /* Free shared reactor data. */\n     SHFREE( reactor->shared->main_pool, reactor );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_attach_channel( FusionReactor *reactor,\n                               int            channel,\n                               ReactionFunc   func,\n                               void          *ctx,\n                               Reaction      *reaction )\n{\n     ReactorNode         *node;\n     NodeLink            *link;\n     FusionReactorAttach  attach;\n\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( func != NULL );\n     D_ASSERT( reaction != NULL );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p [%d], func %p, ctx %p, reaction %p )\\n\", __FUNCTION__,\n                 reactor, reactor->id, func, ctx, reaction );\n\n     link = D_CALLOC( 1, sizeof(NodeLink) );\n     if (!link)\n          return D_OOM();\n\n     node = lock_node( reactor->id, true, true, reactor, NULL );\n     if (!node) {\n          D_FREE( link );\n          return DR_FUSION;\n     }\n\n     attach.reactor_id = reactor->id;\n     attach.channel    = channel;\n\n     while (ioctl( _fusion_fd( reactor->shared ), FUSION_REACTOR_ATTACH, &attach )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n\n               case EINVAL:\n                    D_ERROR( \"Fusion/Reactor: Invalid reactor!\\n\" );\n                    unlock_node( node );\n                    D_FREE( link );\n                    return DR_DESTROYED;\n          }\n\n          D_PERROR( \"Fusion/Reactor: FUSION_REACTOR_ATTACH\" );\n          unlock_node( node );\n          D_FREE( link );\n          return DR_FUSION;\n     }\n\n     /* Fill out callback information. */\n     reaction->func      = func;\n     reaction->ctx       = ctx;\n     reaction->node_link = link;\n\n     link->reaction = reaction;\n     link->channel  = channel;\n\n     D_MAGIC_SET( link, NodeLink );\n\n     /* Prepend the reaction to the local reaction list. */\n     direct_list_prepend( &node->links, &link->link );\n\n     unlock_node( node );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_detach( FusionReactor *reactor,\n                       Reaction      *reaction )\n{\n     ReactorNode *node;\n     NodeLink    *link;\n\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( reaction != NULL );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p [%d], reaction %p ) <- func %p, ctx %p\\n\", __FUNCTION__,\n                 reactor, reactor->id, reaction, reaction->func, reaction->ctx );\n\n     node = lock_node( reactor->id, false, true, reactor, NULL );\n     if (!node) {\n          return DR_BUG;\n     }\n\n     link = reaction->node_link;\n\n     D_ASSUME( link != NULL );\n\n     if (link) {\n          FusionReactorDetach detach;\n\n          D_ASSERT( link->reaction == reaction );\n\n          detach.reactor_id = reactor->id;\n          detach.channel    = link->channel;\n\n          reaction->node_link = NULL;\n\n          link->reaction = NULL;\n\n          remove_node_link( node, link );\n\n          while (ioctl( _fusion_fd( reactor->shared ), FUSION_REACTOR_DETACH, &detach )) {\n               switch (errno) {\n                    case EINTR:\n                         continue;\n\n                    case EINVAL:\n                         D_ERROR( \"Fusion/Reactor: Invalid reactor!\\n\" );\n                         unlock_node( node );\n                         return DR_DESTROYED;\n               }\n\n               D_PERROR( \"Fusion/Reactor: FUSION_REACTOR_DETACH\" );\n               unlock_node( node );\n               return DR_FUSION;\n          }\n     }\n\n     unlock_node( node );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_dispatch_channel( FusionReactor      *reactor,\n                                 int                 channel,\n                                 const void         *msg_data,\n                                 int                 msg_size,\n                                 bool                self,\n                                 const ReactionFunc *globals )\n{\n     FusionWorld           *world;\n     FusionReactorDispatch  dispatch;\n\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( msg_data != NULL );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p [%d], msg_data %p, self %s, globals %p)\\n\", __FUNCTION__,\n                 reactor, reactor->id, msg_data, self ? \"true\" : \"false\", globals );\n\n     world = _fusion_world( reactor->shared );\n\n     fusion_world_flush_calls( world, 1 );\n\n     /* Handle global reactions first. */\n     if (channel == 0 && reactor->globals) {\n          if (fusion_config->secure_fusion && !fusion_master(world)) {\n               D_BUG( \"global reactions on channel 0, cannot dispatch from secure slave\" );\n               return DR_BUG;\n          }\n\n          if (globals)\n               process_globals( reactor, msg_data, globals );\n          else\n               D_ERROR( \"Fusion/Reactor: There are global reactions but no globals have been passed to dispatch()!\\n\" );\n     }\n\n     /* Handle local reactions. */\n     if (self && reactor->direct) {\n          _fusion_reactor_process_message( world, reactor->id, channel, msg_data );\n          self = false;\n     }\n\n     /* Initialize dispatch data. */\n     dispatch.reactor_id = reactor->id;\n     dispatch.channel    = channel;\n     dispatch.self       = self;\n     dispatch.msg_size   = msg_size;\n     dispatch.msg_data   = msg_data;\n\n     /* Dispatch the message to handle foreign reactions. */\n     while (ioctl( _fusion_fd( reactor->shared ), FUSION_REACTOR_DISPATCH, &dispatch )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n\n               case EINVAL:\n                    D_ERROR( \"Fusion/Reactor: Invalid reactor!\\n\" );\n                    return DR_DESTROYED;\n          }\n\n          D_PERROR( \"Fusion/Reactor: FUSION_REACTOR_DISPATCH\" );\n          return DR_FUSION;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_set_dispatch_callback( FusionReactor *reactor,\n                                      FusionCall    *call,\n                                      void          *call_ptr )\n{\n     FusionReactorSetCallback callback;\n\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( call != NULL );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p [%d], call %p [%d], ptr %p)\\n\", __FUNCTION__,\n                 reactor, reactor->id, call, call->call_id, call_ptr );\n\n     /* Fill callback info. */\n     callback.reactor_id = reactor->id;\n     callback.call_id    = call->call_id;\n     callback.call_ptr   = call_ptr;\n\n     /* Set the dispatch callback. */\n     while (ioctl( _fusion_fd( reactor->shared ), FUSION_REACTOR_SET_DISPATCH_CALLBACK, &callback )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n\n               case EINVAL:\n                    D_ERROR( \"Fusion/Reactor: Invalid reactor!\\n\" );\n                    return DR_DESTROYED;\n          }\n\n          D_PERROR( \"Fusion/Reactor: FUSION_REACTOR_SET_DISPATCH_CALLBACK\" );\n          return DR_FUSION;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_set_name( FusionReactor *reactor,\n                         const char    *name )\n{\n     FusionEntryInfo info;\n\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( name != NULL );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p, '%s' )\\n\", __FUNCTION__, reactor, name );\n\n     /* Initialize reactor info. */\n     info.type = FT_REACTOR;\n     info.id   = reactor->id;\n\n     /* Put reactor name into info. */\n     direct_snputs( info.name, name, sizeof(info.name) );\n\n     /* Set the reactor info. */\n     while (ioctl( _fusion_fd( reactor->shared ), FUSION_ENTRY_SET_INFO, &info )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n\n               case EINVAL:\n                    D_ERROR( \"Fusion/Reactor: Invalid reactor!\\n\" );\n                    return DR_IDNOTFOUND;\n          }\n\n          D_PERROR( \"Fusion/Reactor: FUSION_ENTRY_SET_INFO( reactor %d, '%s' )\\n\", reactor->id, name );\n          return DR_FUSION;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_add_permissions( FusionReactor            *reactor,\n                                FusionID                  fusion_id,\n                                FusionReactorPermissions  reactor_permissions )\n{\n     FusionEntryPermissions permissions;\n\n     permissions.type        = FT_REACTOR;\n     permissions.id          = reactor->id;\n     permissions.fusion_id   = fusion_id;\n     permissions.permissions = 0;\n\n     if (reactor_permissions & FUSION_REACTOR_PERMIT_ATTACH_DETACH) {\n          FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REACTOR_ATTACH );\n          FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REACTOR_DETACH );\n     }\n\n     if (reactor_permissions & FUSION_REACTOR_PERMIT_DISPATCH)\n          FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REACTOR_DISPATCH );\n\n     while (ioctl( _fusion_fd( reactor->shared ), FUSION_ENTRY_ADD_PERMISSIONS, &permissions ) < 0) {\n          if (errno != EINTR) {\n               D_PERROR( \"Fusion/Reactor: FUSION_ENTRY_ADD_PERMISSIONS( id %d )\", reactor->id );\n               return DR_FAILURE;\n          }\n     }\n\n     return DR_OK;\n}\n\nvoid\n_fusion_reactor_process_message( FusionWorld *world,\n                                 int          reactor_id,\n                                 int          channel,\n                                 const void  *msg_data )\n{\n     ReactorNode *node;\n     NodeLink    *link;\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_ASSERT( msg_data != NULL );\n\n     D_DEBUG_AT( Fusion_Reactor, \"  _fusion_reactor_process_message( [%d], msg_data %p )\\n\", reactor_id, msg_data );\n\n     /* Find the local counter part of the reactor. */\n     node = lock_node( reactor_id, false, false, NULL, world );\n     if (!node)\n          return;\n\n     D_DEBUG_AT( Fusion_Reactor, \"    -> node %p, reactor %p\\n\", node, node->reactor );\n\n     D_ASSUME( node->links != NULL );\n\n     if (!node->links) {\n          D_DEBUG_AT( Fusion_Reactor, \"    -> no local reactions!\\n\" );\n          unlock_node( node );\n          return;\n     }\n\n     direct_list_foreach (link, node->links) {\n          Reaction *reaction;\n\n          D_MAGIC_ASSERT( link, NodeLink );\n\n          if (link->channel != channel)\n               continue;\n\n          reaction = link->reaction;\n          if (!reaction)\n               continue;\n\n          if (direct_log_domain_check( &Fusion_Reactor ))\n               D_DEBUG_AT( Fusion_Reactor, \"    -> %s (%p)\\n\",\n                           direct_trace_lookup_symbol_at( reaction->func ), reaction->func );\n\n          if (reaction->func( msg_data, reaction->ctx ) == RS_REMOVE) {\n               FusionReactorDetach detach;\n\n               detach.reactor_id = reactor_id;\n               detach.channel    = channel;\n\n               D_DEBUG_AT( Fusion_Reactor, \"    -> removing %p, func %p, ctx %p\\n\",\n                           reaction, reaction->func, reaction->ctx );\n\n               link->reaction = NULL;\n\n               /* We can't remove the link as we only have read lock, to avoid dead locks. */\n\n               while (ioctl( world->fusion_fd, FUSION_REACTOR_DETACH, &detach )) {\n                    switch (errno) {\n                         case EINTR:\n                              continue;\n\n                         case EINVAL:\n                              D_ERROR( \"Fusion/Reactor: Invalid reactor!\\n\" );\n                              break;\n\n                         default:\n                              D_PERROR( \"Fusion/Reactor: FUSION_REACTOR_DETACH\" );\n                              break;\n                    }\n\n                    break;\n               }\n          }\n     }\n\n     unlock_node( node );\n}\n\n#else /* FUSION_BUILD_KERNEL */\n\ntypedef struct {\n     DirectLink   link;\n\n     unsigned int refs;\n\n     FusionID     fusion_id;\n     int          channel;\n} Listener;\n\nFusionReactor *\nfusion_reactor_new( int                msg_size,\n                    const char        *name,\n                    const FusionWorld *world )\n{\n     FusionReactor *reactor;\n\n     D_ASSERT( name != NULL );\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( '%s', size %d )\\n\", __FUNCTION__, name, msg_size );\n\n     /* Allocate shared reactor data. */\n     reactor = SHCALLOC( world->shared->main_pool, 1, sizeof(FusionReactor) );\n     if (!reactor) {\n          D_OOSHM();\n          return NULL;\n     }\n\n     /* Generate the reactor id. */\n     reactor->id = ++world->shared->reactor_ids;\n\n     /* Set the static message size. */\n     reactor->msg_size = msg_size;\n\n     /* Set default lock for global reactions. */\n     reactor->globals_lock = &world->shared->reactor_globals;\n\n     fusion_skirmish_init( &reactor->listeners_lock, \"Reactor Listeners\", world );\n\n     D_DEBUG_AT( Fusion_Reactor, \"  -> new reactor %p [%d] with lock %p [%d]\\n\",\n                 reactor, reactor->id, reactor->globals_lock, reactor->globals_lock->multi.id );\n\n     reactor->shared = world->shared;\n     reactor->direct = true;\n\n     D_MAGIC_SET( reactor, FusionReactor );\n\n     return reactor;\n}\n\nDirectResult\nfusion_reactor_destroy( FusionReactor *reactor )\n{\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_MAGIC_ASSERT( reactor->shared, FusionWorldShared );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p [%d] )\\n\", __FUNCTION__, reactor, reactor->id );\n\n     D_ASSUME( !reactor->destroyed );\n\n     if (reactor->destroyed)\n          return DR_DESTROYED;\n\n     fusion_skirmish_destroy( &reactor->listeners_lock );\n\n     reactor->destroyed = true;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_free( FusionReactor *reactor )\n{\n     Listener *listener, *next;\n\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_MAGIC_ASSERT( reactor->shared, FusionWorldShared );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p [%d] )\\n\", __FUNCTION__, reactor, reactor->id );\n\n     D_MAGIC_CLEAR( reactor );\n\n     direct_list_foreach_safe (listener, next, reactor->listeners) {\n          direct_list_remove( &reactor->listeners, &listener->link );\n          SHFREE( reactor->shared->main_pool, listener );\n     }\n\n     /* Free shared reactor data. */\n     SHFREE( reactor->shared->main_pool, reactor );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_attach_channel( FusionReactor *reactor,\n                               int            channel,\n                               ReactionFunc   func,\n                               void          *ctx,\n                               Reaction      *reaction )\n{\n     DirectResult  ret;\n     ReactorNode  *node;\n     NodeLink     *link;\n     FusionID      fusion_id;\n     Listener     *listener;\n\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( func != NULL );\n     D_ASSERT( reaction != NULL );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p [%d], func %p, ctx %p, reaction %p )\\n\", __FUNCTION__,\n                 reactor, reactor->id, func, ctx, reaction );\n\n     if (reactor->destroyed)\n          return DR_DESTROYED;\n\n     link = D_CALLOC( 1, sizeof(NodeLink) );\n     if (!link)\n          return D_OOM();\n\n     node = lock_node( reactor->id, true, true, reactor, NULL );\n     if (!node) {\n          D_FREE( link );\n          return DR_FUSION;\n     }\n\n     fusion_id = _fusion_id( reactor->shared );\n\n     fusion_skirmish_prevail( &reactor->listeners_lock );\n\n     direct_list_foreach (listener, reactor->listeners) {\n          if (listener->fusion_id == fusion_id && listener->channel == channel) {\n               listener->refs++;\n               break;\n          }\n     }\n\n     if (!listener) {\n          listener = SHCALLOC( reactor->shared->main_pool, 1, sizeof(Listener) );\n          if (!listener) {\n               ret = D_OOSHM();\n               fusion_skirmish_dismiss( &reactor->listeners_lock );\n               unlock_node( node );\n               D_FREE( link );\n               return ret;\n          }\n\n          listener->refs      = 1;\n          listener->fusion_id = fusion_id;\n          listener->channel   = channel;\n\n          direct_list_append( &reactor->listeners, &listener->link );\n     }\n\n     fusion_skirmish_dismiss( &reactor->listeners_lock );\n\n     /* Fill out callback information. */\n     reaction->func      = func;\n     reaction->ctx       = ctx;\n     reaction->node_link = link;\n\n     link->reaction = reaction;\n     link->channel  = channel;\n\n     D_MAGIC_SET( link, NodeLink );\n\n     /* Prepend the reaction to the local reaction list. */\n     direct_list_prepend( &node->links, &link->link );\n\n     unlock_node( node );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_detach( FusionReactor *reactor,\n                       Reaction      *reaction )\n{\n     ReactorNode *node;\n     NodeLink    *link;\n\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( reaction != NULL );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p [%d], reaction %p ) <- func %p, ctx %p\\n\", __FUNCTION__,\n                 reactor, reactor->id, reaction, reaction->func, reaction->ctx );\n\n     if (reactor->destroyed)\n          return DR_DESTROYED;\n\n     node = lock_node( reactor->id, false, true, reactor, NULL );\n     if (!node) {\n          return DR_BUG;\n     }\n\n     link = reaction->node_link;\n\n     D_ASSUME( link != NULL );\n\n     if (link) {\n          Listener *listener;\n          FusionID  fusion_id = _fusion_id( reactor->shared );\n\n          D_ASSERT( link->reaction == reaction );\n\n          reaction->node_link = NULL;\n\n          link->reaction = NULL;\n\n          remove_node_link( node, link );\n\n          fusion_skirmish_prevail( &reactor->listeners_lock );\n\n          direct_list_foreach (listener, reactor->listeners) {\n               if (listener->fusion_id == fusion_id && listener->channel == link->channel) {\n                    if (--listener->refs == 0) {\n                         direct_list_remove( &reactor->listeners, &listener->link );\n                         SHFREE( reactor->shared->main_pool, listener );\n                    }\n                    break;\n               }\n          }\n\n          fusion_skirmish_dismiss( &reactor->listeners_lock );\n     }\n\n     unlock_node( node );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_dispatch_channel( FusionReactor      *reactor,\n                                 int                 channel,\n                                 const void         *msg_data,\n                                 int                 msg_size,\n                                 bool                self,\n                                 const ReactionFunc *globals )\n{\n     FusionWorld          *world;\n     Listener             *listener, *next;\n     FusionRef            *ref = NULL;\n     FusionReactorMessage *msg;\n     struct sockaddr_un    addr;\n     int                   len;\n\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( msg_data != NULL );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p [%d], msg_data %p, self %s, globals %p)\\n\", __FUNCTION__,\n                 reactor, reactor->id, msg_data, self ? \"true\" : \"false\", globals );\n\n     if (reactor->destroyed)\n          return DR_DESTROYED;\n\n     if (msg_size > FUSION_MESSAGE_SIZE-sizeof(FusionReactorMessage)) {\n          D_ERROR( \"Fusion/Reactor: Message too large (%d)!\\n\", msg_size );\n          return DR_UNSUPPORTED;\n     }\n\n     world = _fusion_world( reactor->shared );\n\n     if (reactor->call) {\n          ref = SHMALLOC( world->shared->main_pool, sizeof(FusionRef) );\n          if (!ref)\n               return D_OOSHM();\n\n          fusion_ref_init( ref, \"Dispatch Ref\", world );\n          fusion_ref_up( ref, true );\n          fusion_ref_watch( ref, reactor->call, 0 );\n     }\n\n     /* Handle global reactions first. */\n     if (channel == 0 && reactor->globals) {\n          if (globals)\n               process_globals( reactor, msg_data, globals );\n          else\n               D_ERROR( \"Fusion/Reactor: There are global reactions but no globals have been passed to dispatch()!\\n\" );\n     }\n\n     /* Handle local reactions. */\n     if (self && reactor->direct) {\n          _fusion_reactor_process_message( _fusion_world(reactor->shared), reactor->id, channel, msg_data );\n          self = false;\n     }\n\n     msg = alloca( sizeof(FusionReactorMessage) + msg_size );\n\n     msg->type    = FMT_REACTOR;\n     msg->id      = reactor->id;\n     msg->channel = channel;\n     msg->ref     = ref;\n\n     direct_memcpy( (void*) msg + sizeof(FusionReactorMessage), msg_data, msg_size );\n\n     addr.sun_family = AF_UNIX;\n     len = snprintf( addr.sun_path, sizeof(addr.sun_path), \"/tmp/.fusion-%d/\", fusion_world_index( world ) );\n\n     fusion_skirmish_prevail( &reactor->listeners_lock );\n\n     direct_list_foreach_safe (listener, next, reactor->listeners) {\n          if (listener->channel == channel) {\n               DirectResult ret;\n\n               if (!self && listener->fusion_id == world->fusion_id)\n                    continue;\n\n               if (ref)\n                    fusion_ref_up( ref, true );\n\n               snprintf( addr.sun_path + len, sizeof(addr.sun_path) - len, \"%lx\", listener->fusion_id );\n\n               D_DEBUG_AT( Fusion_Reactor, \"  -> sending to '%s'\\n\", addr.sun_path );\n\n               ret = _fusion_send_message( world->fusion_fd, msg, sizeof(FusionReactorMessage) + msg_size, &addr );\n               if (ret == DR_FUSION) {\n                    D_DEBUG_AT( Fusion_Reactor, \"  -> removing dead listener %lu\\n\", listener->fusion_id );\n\n                    if (ref)\n                         fusion_ref_down( ref, true );\n\n                    direct_list_remove( &reactor->listeners, &listener->link );\n\n                    SHFREE( reactor->shared->main_pool, listener );\n               }\n          }\n     }\n\n     fusion_skirmish_dismiss( &reactor->listeners_lock );\n\n     if (ref) {\n          fusion_ref_down( ref, true );\n          if (fusion_ref_zero_trylock( ref ) == DR_OK) {\n               fusion_ref_destroy( ref );\n               SHFREE( world->shared->main_pool, ref );\n          }\n     }\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p ) done\\n\", __FUNCTION__, reactor );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_set_dispatch_callback( FusionReactor *reactor,\n                                      FusionCall    *call,\n                                      void          *call_ptr )\n{\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( call != NULL );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p [%d], call %p [%d], ptr %p)\\n\", __FUNCTION__,\n                 reactor, reactor->id, call, call->call_id, call_ptr );\n\n     if (reactor->destroyed)\n          return DR_DESTROYED;\n\n     if (call_ptr)\n          return DR_UNIMPLEMENTED;\n\n     reactor->call = call;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_set_name( FusionReactor *reactor,\n                         const char    *name )\n{\n     return DR_UNIMPLEMENTED;\n}\n\nDirectResult\nfusion_reactor_add_permissions( FusionReactor            *reactor,\n                                FusionID                  fusion_id,\n                                FusionReactorPermissions  permissions )\n{\n     return DR_UNIMPLEMENTED;\n}\n\nvoid\n_fusion_reactor_process_message( FusionWorld *world,\n                                 int          reactor_id,\n                                 int          channel,\n                                 const void  *msg_data )\n{\n     ReactorNode *node;\n     NodeLink    *link;\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_ASSERT( msg_data != NULL );\n\n     D_DEBUG_AT( Fusion_Reactor, \"  _fusion_reactor_process_message( [%d], msg_data %p )\\n\", reactor_id, msg_data );\n\n     /* Find the local counter part of the reactor. */\n     node = lock_node( reactor_id, false, false, NULL, world );\n     if (!node)\n          return;\n\n     D_DEBUG_AT( Fusion_Reactor, \"    -> node %p, reactor %p\\n\", node, node->reactor );\n\n     D_ASSUME( node->links != NULL );\n\n     if (!node->links) {\n          D_DEBUG_AT( Fusion_Reactor, \"    -> no local reactions!\\n\" );\n          unlock_node( node );\n          return;\n     }\n\n     direct_list_foreach (link, node->links) {\n          Reaction *reaction;\n\n          D_MAGIC_ASSERT( link, NodeLink );\n\n          if (link->channel != channel)\n               continue;\n\n          reaction = link->reaction;\n          if (!reaction)\n               continue;\n\n          if (reaction->func( msg_data, reaction->ctx ) == RS_REMOVE) {\n               FusionReactor *reactor = node->reactor;\n               Listener      *listener;\n\n               D_DEBUG_AT( Fusion_Reactor, \"    -> removing %p, func %p, ctx %p\\n\",\n                           reaction, reaction->func, reaction->ctx );\n\n               fusion_skirmish_prevail( &reactor->listeners_lock );\n\n               direct_list_foreach (listener, reactor->listeners) {\n                    if (listener->fusion_id == world->fusion_id && listener->channel == channel) {\n                         if (--listener->refs == 0) {\n                              direct_list_remove( &reactor->listeners, &listener->link );\n                              SHFREE( world->shared->main_pool, listener );\n                         }\n                         break;\n                    }\n               }\n\n               fusion_skirmish_dismiss( &reactor->listeners_lock );\n          }\n     }\n\n     unlock_node( node );\n}\n\n#endif /* FUSION_BUILD_KERNEL */\n\nDirectResult\nfusion_reactor_set_lock( FusionReactor  *reactor,\n                         FusionSkirmish *lock )\n{\n     DirectResult    ret;\n     FusionSkirmish *old;\n\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( lock != NULL );\n\n     old = reactor->globals_lock;\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p [%d], lock %p [%d] ) <- old %p [%d]\\n\", __FUNCTION__,\n                 reactor, reactor->id, lock, lock->multi.id, old, old->multi.id );\n\n     /* Acquire the old lock to make sure that changing the lock doesn't result in mismatching lock/unlock pairs. */\n     ret = fusion_skirmish_prevail( old );\n     if (ret)\n          return ret;\n\n     D_ASSUME( reactor->globals_lock != lock );\n\n     /* Set the lock replacement. */\n     reactor->globals_lock = lock;\n\n     /* Release the old lock which is obsolete now. */\n     fusion_skirmish_dismiss( old );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_set_lock_only( FusionReactor  *reactor,\n                              FusionSkirmish *lock )\n{\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( lock != NULL );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p [%d], lock %p [%d] ) <- old %p [%d]\\n\", __FUNCTION__,\n                 reactor, reactor->id, lock, lock->multi.id, reactor->globals_lock, reactor->globals_lock->multi.id );\n\n     D_ASSUME( reactor->globals_lock != lock );\n\n     /* Set the lock replacement. */\n     reactor->globals_lock = lock;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_attach( FusionReactor *reactor,\n                       ReactionFunc   func,\n                       void          *ctx,\n                       Reaction      *reaction )\n{\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( func != NULL );\n     D_ASSERT( reaction != NULL );\n\n     return fusion_reactor_attach_channel( reactor, 0, func, ctx, reaction );\n}\n\nDirectResult\nfusion_reactor_attach_global( FusionReactor  *reactor,\n                              int             index,\n                              void           *ctx,\n                              GlobalReaction *reaction )\n{\n     DirectResult    ret;\n     FusionSkirmish *lock;\n\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( index >= 0 );\n     D_ASSERT( reaction != NULL );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p [%d], index %d, ctx %p, reaction %p )\\n\", __FUNCTION__,\n                 reactor, reactor->id, index, ctx, reaction );\n\n     /* Initialize reaction data. */\n     reaction->index    = index;\n     reaction->ctx      = ctx;\n     reaction->attached = true;\n\n     /* Remember for safety. */\n     lock = reactor->globals_lock;\n\n     /* Lock the list of global reactions. */\n     ret = fusion_skirmish_prevail( lock );\n     if (ret)\n          return ret;\n\n     if (lock != reactor->globals_lock)\n          D_WARN( \"using old lock once more\" );\n\n     /* Prepend the reaction to the list. */\n     direct_list_prepend( &reactor->globals, &reaction->link );\n\n     /* Unlock the list of global reactions. */\n     fusion_skirmish_dismiss( lock );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_detach_global( FusionReactor  *reactor,\n                              GlobalReaction *reaction )\n{\n     DirectResult    ret;\n     FusionSkirmish *lock;\n\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( reaction != NULL );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p [%d], reaction %p ) <- index %d, ctx %p\\n\", __FUNCTION__,\n                 reactor, reactor->id, reaction, reaction->index, reaction->ctx );\n\n     /* Remember for safety. */\n     lock = reactor->globals_lock;\n\n     /* Lock the list of global reactions. */\n     ret = fusion_skirmish_prevail( lock );\n     if (ret)\n          return ret;\n\n     if (lock != reactor->globals_lock)\n          D_WARN( \"using old lock once more\" );\n\n     /* Check against multiple detach. */\n     if (reaction->attached) {\n          /* Mark as detached. */\n          reaction->attached = false;\n\n          /* Remove the reaction from the list. */\n          direct_list_remove( &reactor->globals, &reaction->link );\n     }\n\n     /* Unlock the list of global reactions. */\n     fusion_skirmish_dismiss( lock );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_dispatch( FusionReactor      *reactor,\n                         const void         *msg_data,\n                         bool                self,\n                         const ReactionFunc *globals )\n{\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n\n     return fusion_reactor_dispatch_channel( reactor, 0, msg_data, reactor->msg_size, self, globals );\n}\n\nDirectResult\nfusion_reactor_direct( FusionReactor *reactor,\n                       bool           direct )\n{\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n\n     reactor->direct = direct;\n\n     return DR_OK;\n}\n\nvoid\n_fusion_reactor_free_all( FusionWorld *world )\n{\n     ReactorNode *node, *node_next;\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s() <- nodes %p\\n\", __FUNCTION__, world->reactor_nodes );\n\n     direct_mutex_lock( &world->reactor_nodes_lock );\n\n     direct_list_foreach_safe (node, node_next, world->reactor_nodes) {\n          NodeLink *link, *link_next;\n\n          D_MAGIC_ASSERT( node, ReactorNode );\n\n          direct_rwlock_wrlock( &node->lock );\n\n          direct_list_foreach_safe (link, link_next, node->links) {\n               D_MAGIC_ASSERT( link, NodeLink );\n\n               D_MAGIC_CLEAR( link );\n\n               D_FREE( link );\n          }\n\n          direct_rwlock_unlock( &node->lock );\n          direct_rwlock_deinit( &node->lock );\n\n          D_MAGIC_CLEAR( node );\n\n          D_FREE( node );\n     }\n\n     world->reactor_nodes = NULL;\n\n     direct_mutex_unlock( &world->reactor_nodes_lock );\n}\n\nstatic void\nprocess_globals( FusionReactor      *reactor,\n                 const void         *msg_data,\n                 const ReactionFunc *globals )\n{\n     GlobalReaction *global, *next;\n     FusionSkirmish *lock;\n     int             max_index = -1;\n\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( msg_data != NULL );\n     D_ASSERT( globals != NULL );\n\n     D_DEBUG_AT( Fusion_Reactor, \"  process_globals( %p [%d], msg_data %p, globals %p )\\n\",\n                 reactor, reactor->id, msg_data, globals );\n\n     /* Find maximum reaction index. */\n     while (globals[max_index+1])\n          max_index++;\n\n     if (max_index < 0)\n          return;\n\n     /* Remember for safety. */\n     lock = reactor->globals_lock;\n\n     /* Lock the list of global reactions. */\n     if (fusion_skirmish_prevail( lock ))\n          return;\n\n     if (lock != reactor->globals_lock)\n          D_WARN( \"using old lock once more\" );\n\n     /* Loop through all global reactions. */\n     direct_list_foreach_safe (global, next, reactor->globals) {\n          int index = global->index;\n\n          /* Check if the index is valid. */\n          if (index < 0 || index > max_index) {\n               D_WARN( \"global reaction index out of bounds (%d/%d)\", global->index, max_index );\n               continue;\n          }\n\n          /* Remove the reaction if requested. */\n          if (globals[global->index]( msg_data, global->ctx ) == RS_REMOVE) {\n               D_DEBUG_AT( Fusion_Reactor, \"    -> removing %p, index %d, ctx %p\\n\",\n                           global, global->index, global->ctx );\n\n               /* Mark as detached, since the global reaction is being removed from the global reaction list. */\n               global->attached = false;\n\n               direct_list_remove( &reactor->globals, &global->link );\n          }\n     }\n\n     /* Unlock the list of global reactions. */\n     fusion_skirmish_dismiss( lock );\n}\n\nstatic ReactorNode *\nlock_node( int            reactor_id,\n           bool           add_it,\n           bool           wlock,\n           FusionReactor *reactor,\n           FusionWorld   *world )\n{\n     ReactorNode       *node, *node_next;\n     FusionWorldShared *shared;\n\n     D_DEBUG_AT( Fusion_Reactor, \"    lock_node( [%d], add %s, reactor %p )\\n\",\n                 reactor_id, add_it ? \"true\" : \"false\", reactor );\n\n     D_ASSERT( reactor != NULL || (!add_it && world != NULL) );\n\n     if (reactor) {\n          D_MAGIC_ASSERT( reactor, FusionReactor );\n          D_MAGIC_ASSERT( reactor->shared, FusionWorldShared );\n\n          shared = reactor->shared;\n\n          world = _fusion_world( shared );\n     }\n     else {\n          D_MAGIC_ASSERT( world, FusionWorld );\n          D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n          shared = world->shared;\n     }\n\n     direct_mutex_lock( &world->reactor_nodes_lock );\n\n     direct_list_foreach_safe (node, node_next, world->reactor_nodes) {\n          D_MAGIC_ASSERT( node, ReactorNode );\n\n          if (node->reactor_id == reactor_id) {\n               if (wlock) {\n                    NodeLink *link, *link_next;\n\n                    direct_rwlock_wrlock( &node->lock );\n\n                    direct_list_foreach_safe (link, link_next, node->links) {\n                         D_MAGIC_ASSERT( link, NodeLink );\n\n                         if (!link->reaction) {\n                              D_DEBUG_AT( Fusion_Reactor, \"    -> cleaning up %p\\n\", link );\n\n                              remove_node_link( node, link );\n                         }\n                         else\n                              D_ASSERT( link->reaction->node_link == link );\n                    }\n               }\n               else\n                    direct_rwlock_rdlock( &node->lock );\n\n               if (!node->links && !add_it) {\n                    direct_list_remove( &world->reactor_nodes, &node->link );\n\n                    direct_rwlock_unlock( &node->lock );\n                    direct_rwlock_deinit( &node->lock );\n\n                    D_MAGIC_CLEAR( node );\n\n                    D_FREE( node );\n\n                    node = NULL;\n               }\n               else {\n                    D_ASSERT( node->reactor == reactor || reactor == NULL );\n\n                    direct_list_move_to_front( &world->reactor_nodes, &node->link );\n               }\n\n               direct_mutex_unlock( &world->reactor_nodes_lock );\n\n               return node;\n          }\n\n          if (!direct_rwlock_trywrlock( &node->lock )) {\n               if (!node->links) {\n                    direct_list_remove( &world->reactor_nodes, &node->link );\n\n                    direct_rwlock_unlock( &node->lock );\n                    direct_rwlock_deinit( &node->lock );\n\n                    D_MAGIC_CLEAR( node );\n\n                    D_FREE( node );\n               }\n               else {\n                    direct_rwlock_unlock( &node->lock );\n               }\n          }\n     }\n\n     if (add_it) {\n          D_MAGIC_ASSERT( reactor, FusionReactor );\n\n          node = D_CALLOC( 1, sizeof(ReactorNode) );\n          if (!node) {\n               D_OOM();\n               return NULL;\n          }\n\n          direct_rwlock_init( &node->lock );\n\n          if (wlock)\n               direct_rwlock_wrlock( &node->lock );\n          else\n               direct_rwlock_rdlock( &node->lock );\n\n          node->reactor_id = reactor_id;\n          node->reactor    = reactor;\n\n          D_MAGIC_SET( node, ReactorNode );\n\n          direct_list_prepend( &world->reactor_nodes, &node->link );\n\n          direct_mutex_unlock( &world->reactor_nodes_lock );\n\n          return node;\n     }\n\n     direct_mutex_unlock( &world->reactor_nodes_lock );\n\n     return NULL;\n}\n\nstatic void\nunlock_node( ReactorNode *node )\n{\n     D_ASSERT( node != NULL );\n\n     direct_rwlock_unlock( &node->lock );\n}\n\n#else /* FUSION_BUILD_MULTI */\n\nFusionReactor *\nfusion_reactor_new( int                msg_size,\n                    const char        *name,\n                    const FusionWorld *world )\n{\n     FusionReactor *reactor;\n\n     D_ASSERT( name != NULL );\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( '%s', size %d )\\n\", __FUNCTION__, name, msg_size );\n\n     reactor = D_CALLOC( 1, sizeof(FusionReactor) );\n     if (!reactor)\n          return NULL;\n\n     reactor->msg_size = msg_size;\n     reactor->world    = (FusionWorld*) world;\n\n     direct_recursive_mutex_init( &reactor->reactions_lock );\n     direct_recursive_mutex_init( &reactor->globals_mutex );\n\n     D_MAGIC_SET( reactor, FusionReactor );\n\n     return reactor;\n}\n\nDirectResult\nfusion_reactor_destroy( FusionReactor *reactor )\n{\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p )\\n\", __FUNCTION__, reactor );\n\n     D_ASSUME( !reactor->destroyed );\n\n     reactor->destroyed = true;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_free( FusionReactor *reactor )\n{\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p )\\n\", __FUNCTION__, reactor );\n\n     if (_fusion_event_dispatcher_process_reactor_free( reactor->world, reactor ))\n          return DR_OK;\n\n     reactor->reactions = NULL;\n     direct_mutex_deinit( &reactor->reactions_lock );\n\n     reactor->globals = NULL;\n     direct_mutex_deinit( &reactor->globals_mutex );\n\n     D_MAGIC_CLEAR( reactor );\n\n     D_FREE( reactor );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_attach_channel( FusionReactor *reactor,\n                               int            channel,\n                               ReactionFunc   func,\n                               void          *ctx,\n                               Reaction      *reaction )\n{\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( func != NULL );\n     D_ASSERT( reaction != NULL );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p, func %p, ctx %p, reaction %p )\\n\", __FUNCTION__,\n                 reactor, func, ctx, reaction );\n\n     reaction->func      = func;\n     reaction->ctx       = ctx;\n     reaction->node_link = (void*)(long) channel;\n\n     direct_mutex_lock( &reactor->reactions_lock );\n\n     direct_list_prepend( &reactor->reactions, &reaction->link );\n\n     direct_mutex_unlock( &reactor->reactions_lock );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_detach( FusionReactor *reactor,\n                       Reaction      *reaction )\n{\n     D_ASSERT( reactor != NULL );\n     D_ASSERT( reaction != NULL );\n\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p, reaction %p ) <- func %p, ctx %p\\n\", __FUNCTION__,\n                 reactor, reaction, reaction->func, reaction->ctx );\n\n     direct_mutex_lock( &reactor->reactions_lock );\n\n     direct_list_remove( &reactor->reactions, &reaction->link );\n\n     direct_mutex_unlock( &reactor->reactions_lock );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_dispatch_channel( FusionReactor      *reactor,\n                                 int                 channel,\n                                 const void         *msg_data,\n                                 int                 msg_size,\n                                 bool                self,\n                                 const ReactionFunc *globals )\n{\n     D_ASSERT( reactor != NULL );\n     D_ASSERT( msg_data != NULL );\n\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p, msg_data %p, self %s, globals %p)\\n\", __FUNCTION__,\n                 reactor, msg_data, self ? \"true\" : \"false\", globals );\n\n     if (channel == 0 && reactor->globals) {\n          if (globals)\n               process_globals( reactor, msg_data, globals );\n          else\n               D_ERROR( \"Fusion/Reactor: There are global reactions but no globals have been passed to dispatch()!\\n\" );\n     }\n\n     if (!self)\n          return DR_OK;\n\n     _fusion_event_dispatcher_process_reactions( reactor->world, reactor, channel, (void*) msg_data, msg_size );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_set_dispatch_callback( FusionReactor  *reactor,\n                                      FusionCall     *call,\n                                      void           *call_ptr )\n{\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n\n     D_UNIMPLEMENTED();\n\n     return DR_UNIMPLEMENTED;\n}\n\nDirectResult\nfusion_reactor_set_name( FusionReactor *reactor,\n                         const char    *name )\n{\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n\n     D_UNIMPLEMENTED();\n\n     return DR_UNIMPLEMENTED;\n}\n\nDirectResult\nfusion_reactor_add_permissions( FusionReactor            *reactor,\n                                FusionID                  fusion_id,\n                                FusionReactorPermissions  permissions )\n{\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_set_lock( FusionReactor  *reactor,\n                         FusionSkirmish *lock )\n\n{\n     D_ASSERT( reactor != NULL );\n     D_ASSERT( lock != NULL );\n\n     return DR_UNIMPLEMENTED;\n}\n\nDirectResult\nfusion_reactor_set_lock_only( FusionReactor  *reactor,\n                              FusionSkirmish *lock )\n{\n     D_ASSERT( reactor != NULL );\n     D_ASSERT( lock != NULL );\n\n     return DR_UNIMPLEMENTED;\n}\n\nDirectResult\nfusion_reactor_attach( FusionReactor *reactor,\n                       ReactionFunc   func,\n                       void          *ctx,\n                       Reaction      *reaction )\n{\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( func != NULL );\n     D_ASSERT( reaction != NULL );\n\n     return fusion_reactor_attach_channel( reactor, 0, func, ctx, reaction );\n}\n\nDirectResult\nfusion_reactor_attach_global( FusionReactor  *reactor,\n                              int             index,\n                              void           *ctx,\n                              GlobalReaction *reaction )\n{\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( index >= 0 );\n     D_ASSERT( reaction != NULL );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p, index %d, ctx %p, reaction %p )\\n\", __FUNCTION__,\n                 reactor, index, ctx, reaction );\n\n     reaction->index = index;\n     reaction->ctx   = ctx;\n\n     /* Mark the reaction as attached now. */\n     reaction->attached = true;\n\n     direct_mutex_lock( &reactor->globals_mutex );\n\n     direct_list_prepend( &reactor->globals, &reaction->link );\n\n     direct_mutex_unlock( &reactor->globals_mutex );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_detach_global( FusionReactor  *reactor,\n                              GlobalReaction *reaction )\n{\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( reaction != NULL );\n\n     D_DEBUG_AT( Fusion_Reactor, \"%s( %p, reaction %p ) <- index %d, ctx %p\\n\", __FUNCTION__,\n                 reactor, reaction, reaction->index, reaction->ctx );\n\n     direct_mutex_lock( &reactor->globals_mutex );\n\n     /* Check to prevent multiple detaches from being performed. */\n     if (reaction->attached) {\n          /* Mark as detached, since the global reaction is being removed from the global reaction list. */\n          reaction->attached = false;\n\n          /* Remove the reaction from the list. */\n          direct_list_remove( &reactor->globals, &reaction->link );\n     }\n\n     direct_mutex_unlock( &reactor->globals_mutex );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_reactor_dispatch( FusionReactor      *reactor,\n                         const void         *msg_data,\n                         bool                self,\n                         const ReactionFunc *globals )\n{\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n\n     return fusion_reactor_dispatch_channel( reactor, 0, msg_data, reactor->msg_size, self, globals );\n}\n\nDirectResult\nfusion_reactor_direct( FusionReactor *reactor,\n                       bool           direct )\n{\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n\n     return DR_OK;\n}\n\nstatic void\nprocess_globals( FusionReactor      *reactor,\n                 const void         *msg_data,\n                 const ReactionFunc *globals )\n{\n     GlobalReaction *global, *next;\n     int             max_index = -1;\n\n     D_MAGIC_ASSERT( reactor, FusionReactor );\n     D_ASSERT( msg_data != NULL );\n     D_ASSERT( globals != NULL );\n\n     D_DEBUG_AT( Fusion_Reactor, \"  process_globals( %p [%d], msg_data %p, globals %p )\\n\",\n                 reactor, reactor->id, msg_data, globals );\n\n     /* Find maximum reaction index. */\n     while (globals[max_index+1])\n          max_index++;\n\n     if (max_index < 0)\n          return;\n\n     direct_mutex_lock( &reactor->globals_mutex );\n\n     /* Loop through all global reactions. */\n     direct_list_foreach_safe (global, next, reactor->globals) {\n          if (global->index < 0 || global->index > max_index) {\n               D_WARN( \"global reaction index out of bounds (%d/%d)\", global->index, max_index );\n          }\n          else {\n               /* Remove the reaction if requested. */\n               if (globals[global->index]( msg_data, global->ctx ) == RS_REMOVE) {\n                    D_DEBUG_AT( Fusion_Reactor, \"    -> removing %p, index %d, ctx %p\\n\",\n                                global, global->index, global->ctx );\n\n                    /* Mark as detached, since the global reaction is being removed from the global reaction list. */\n                    global->attached = false;\n\n                    direct_list_remove( &reactor->globals, &global->link );\n               }\n          }\n     }\n\n     direct_mutex_unlock( &reactor->globals_mutex );\n}\n\n#endif /* FUSION_BUILD_MULTI */\n"
  },
  {
    "path": "lib/fusion/reactor.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FUSION__REACTOR_H__\n#define __FUSION__REACTOR_H__\n\n#include <direct/list.h>\n#include <fusion/lock.h>\n\n/**********************************************************************************************************************/\n\nstruct __Fusion_FusionReactor {\n     int                magic;\n\n     int                id;\n     int                msg_size;\n     bool               direct;\n     bool               destroyed;\n     bool               free;\n\n     DirectLink        *globals;\n     FusionSkirmish    *globals_lock;\n     DirectMutex        globals_mutex;\n\n     FusionWorldShared *shared;\n     FusionWorld       *world;\n\n     DirectLink        *listeners;\n     FusionSkirmish     listeners_lock;\n     FusionCall        *call;\n\n     DirectLink        *reactions;\n     DirectMutex        reactions_lock;\n};\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     RS_OK     = 0x00000000,\n     RS_REMOVE = 0x00000001,\n     RS_DROP   = 0x00000002\n} ReactionResult;\n\ntypedef enum {\n     FUSION_REACTOR_PERMIT_NONE          = 0x00000000,\n\n     FUSION_REACTOR_PERMIT_ATTACH_DETACH = 0x00000001,\n     FUSION_REACTOR_PERMIT_DISPATCH      = 0x00000002,\n\n     FUSION_REACTOR_PERMIT_ALL           = 0x00000003\n} FusionReactorPermissions;\n\ntypedef ReactionResult (*ReactionFunc)( const void *msg_data, void *ctx );\n\ntypedef struct {\n     DirectLink    link;\n     ReactionFunc  func;\n     void         *ctx;\n     void         *node_link;\n} Reaction;\n\ntypedef struct {\n     DirectLink  link;\n     int         index;\n     void       *ctx;\n     bool        attached;\n} GlobalReaction;\n\n/**********************************************************************************************************************/\n\n/*\n * Create a new reactor configured for the specified message data size.\n */\nFusionReactor FUSION_API *fusion_reactor_new                  ( int                       msg_size,\n                                                                const char               *name,\n                                                                const FusionWorld        *world );\n\n/*\n * Destroy the reactor.\n */\nDirectResult  FUSION_API  fusion_reactor_destroy              ( FusionReactor            *reactor );\n\n/*\n * Free the reactor.\n */\nDirectResult  FUSION_API  fusion_reactor_free                 ( FusionReactor            *reactor );\n\n/*\n * Attach a local reaction to a specific reactor channel (0-1023).\n */\nDirectResult  FUSION_API  fusion_reactor_attach_channel       ( FusionReactor            *reactor,\n                                                                int                       channel,\n                                                                ReactionFunc              func,\n                                                                void                     *ctx,\n                                                                Reaction                 *reaction );\n\n/*\n * Detach an attached local reaction from the reactor.\n */\nDirectResult  FUSION_API  fusion_reactor_detach               ( FusionReactor            *reactor,\n                                                                Reaction                 *reaction );\n\n/*\n * Dispatch a message via a specific channel (0-1023).\n * Setting 'self' to false excludes the caller's local reactions.\n */\nDirectResult  FUSION_API  fusion_reactor_dispatch_channel     ( FusionReactor            *reactor,\n                                                                int                       channel,\n                                                                const void               *msg_data,\n                                                                int                       msg_size,\n                                                                bool                      self,\n                                                                const ReactionFunc       *globals );\n\n/*\n * Have the call executed when a dispatched message has been processed by all recipients.\n */\nDirectResult  FUSION_API  fusion_reactor_set_dispatch_callback( FusionReactor            *reactor,\n                                                                FusionCall               *call,\n                                                                void                     *call_ptr );\n\n/*\n * Change the name of the reactor.\n */\nDirectResult  FUSION_API  fusion_reactor_set_name             ( FusionReactor            *reactor,\n                                                                const char               *name );\n\n/*\n * Give permissions to another fusionee to use the reactor.\n */\nDirectResult  FUSION_API  fusion_reactor_add_permissions      ( FusionReactor            *reactor,\n                                                                FusionID                  fusion_id,\n                                                                FusionReactorPermissions  permissions );\n\n/*\n * Make the reactor use the specified lock for managing global reactions.\n */\nDirectResult  FUSION_API  fusion_reactor_set_lock             ( FusionReactor            *reactor,\n                                                                FusionSkirmish           *lock );\n\n/*\n * Don't lock, i.e. use this function in fusion_object_set_lock() as this is called during object initialization.\n */\nDirectResult  FUSION_API  fusion_reactor_set_lock_only        ( FusionReactor            *reactor,\n                                                                FusionSkirmish           *lock );\n\n/*\n * Attach a local reaction to the reactor (channel 0).\n */\nDirectResult  FUSION_API  fusion_reactor_attach               ( FusionReactor            *reactor,\n                                                                ReactionFunc              func,\n                                                                void                     *ctx,\n                                                                Reaction                 *reaction );\n\n/*\n * Attach a global reaction to the reactor.\n * It's always called directly, no matter which fusionee calls fusion_reactor_dispatch().\n */\nDirectResult  FUSION_API  fusion_reactor_attach_global        ( FusionReactor            *reactor,\n                                                                int                       index,\n                                                                void                     *ctx,\n                                                                GlobalReaction           *reaction );\n\n/*\n * Detach an attached global reaction from the reactor.\n */\nDirectResult  FUSION_API  fusion_reactor_detach_global        ( FusionReactor            *reactor,\n                                                                GlobalReaction           *reaction );\n\n/*\n * Dispatch a message to any attached reaction (channel 0).\n * Setting 'self' to false excludes the caller's local reactions.\n */\nDirectResult  FUSION_API  fusion_reactor_dispatch             ( FusionReactor            *reactor,\n                                                                const void               *msg_data,\n                                                                bool                      self,\n                                                                const ReactionFunc       *globals );\n\n/*\n * Specify whether local message handlers (reactions) should be called directly.\n */\nDirectResult  FUSION_API  fusion_reactor_direct               ( FusionReactor            *reactor,\n                                                                bool                      direct );\n\n#endif\n"
  },
  {
    "path": "lib/fusion/ref.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/system.h>\n#include <direct/trace.h>\n#include <fusion/conf.h>\n#include <fusion/ref.h>\n\n#if FUSION_BUILD_MULTI\n\n#include <direct/map.h>\n#include <direct/mem.h>\n#include <fusion/fusion_internal.h>\n\n#else /* FUSION_BUILD_MULTI */\n\n#include <fusion/call.h>\n\n#endif /* FUSION_BUILD_MULTI */\n\nD_DEBUG_DOMAIN( Fusion_Ref, \"Fusion/Ref\", \"Fusion's Reference Counter\" );\n\n/**********************************************************************************************************************/\n\n#if FUSION_BUILD_MULTI\n\n#if FUSION_BUILD_KERNEL\n\nDirectResult\nfusion_ref_init( FusionRef         *ref,\n                 const char        *name,\n                 const FusionWorld *world )\n{\n     return fusion_ref_init2( ref, name, false, world );\n}\n\nDirectResult\nfusion_ref_init2( FusionRef         *ref,\n                  const char        *name,\n                  bool               user,\n                  const FusionWorld *world )\n{\n     FusionEntryInfo info;\n\n     D_ASSERT( ref != NULL );\n     D_ASSERT( name != NULL );\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p, '%s' )\\n\", __FUNCTION__, ref, name ?: \"\" );\n\n     if (user) {\n          ref->multi.id   = (long) ref;\n          ref->multi.user = true;\n\n          direct_recursive_mutex_init( &ref->single.lock );\n          direct_waitqueue_init( &ref->single.cond );\n\n          ref->single.refs      = 0;\n          ref->single.destroyed = false;\n          ref->single.locked    = 0;\n     }\n     else {\n          while (ioctl( world->fusion_fd, FUSION_REF_NEW, &ref->multi.id )) {\n               if (errno == EINTR)\n                    continue;\n\n               D_PERROR( \"Fusion/Ref: FUSION_REF_NEW\" );\n               return DR_FUSION;\n          }\n\n          D_DEBUG_AT( Fusion_Ref, \"  -> new ref %p [%d]\\n\", ref, ref->multi.id );\n\n          info.type = FT_REF;\n          info.id   = ref->multi.id;\n\n          direct_snputs( info.name, name, sizeof(info.name) );\n\n          ioctl( world->fusion_fd, FUSION_ENTRY_SET_INFO, &info );\n     }\n\n     /* Keep back pointer to shared world data. */\n     ref->multi.shared  = world->shared;\n     ref->multi.creator = fusion_id( world );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_set_name( FusionRef  *ref,\n                     const char *name )\n{\n     FusionEntryInfo info;\n\n     D_ASSERT( ref != NULL );\n     D_ASSERT( name != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p, '%s' )\\n\", __FUNCTION__, ref, name );\n\n     if (ref->multi.user)\n          return DR_OK;\n\n     info.type = FT_REF;\n     info.id   = ref->multi.id;\n\n     direct_snputs( info.name, name, sizeof(info.name) );\n\n     while (ioctl( _fusion_fd( ref->multi.shared ), FUSION_ENTRY_SET_INFO, &info )) {\n          switch (errno) {\n               case EINTR:\n                    continue;\n               case EAGAIN:\n                    return DR_LOCKED;\n               case EINVAL:\n                    D_ERROR( \"Fusion/Ref: Invalid reference!\\n\" );\n                    return DR_DESTROYED;\n               default:\n                    break;\n          }\n\n          D_PERROR( \"Fusion/Ref: FUSION_ENTRY_SET_INFO\" );\n\n          return DR_FAILURE;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_up( FusionRef *ref,\n               bool       global )\n{\n     DirectResult ret = DR_OK;\n\n     D_ASSERT( ref != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p [%d]%s )\\n\", __FUNCTION__, ref, ref->multi.id, global ? \" GLOBAL\" : \"\" );\n\n     if (fusion_config->trace_ref == -1 || ref->multi.id == fusion_config->trace_ref) {\n          D_INFO( \"Fusion/Ref: [%d] up (%s), single refs %d\\n\",\n                  ref->multi.id, global ? \"global\" : \"local\", ref->single.refs );\n          direct_trace_print_stack( NULL );\n     }\n\n     if (ref->multi.user) {\n          FusionWorld *world = _fusion_world( ref->multi.shared );\n\n          if (world->fusion_id == FUSION_ID_MASTER) {\n               direct_mutex_lock( &ref->single.lock );\n\n               if (ref->single.destroyed)\n                    ret = DR_DESTROYED;\n               else if (ref->single.locked)\n                    ret = DR_LOCKED;\n               else\n                    ref->single.refs++;\n\n               direct_mutex_unlock( &ref->single.lock );\n          }\n          else {\n               FusionRefSlaveSlaveEntry *entry;\n\n               direct_mutex_lock( &world->refs_lock );\n\n               entry = direct_map_lookup( world->refs_map, &ref->multi.id );\n               if (!entry) {\n                    entry = D_CALLOC( 1, sizeof(FusionRefSlaveSlaveEntry) );\n                    if (!entry) {\n                         direct_mutex_unlock( &world->refs_lock );\n                         return D_OOM();\n                    }\n\n                    entry->ref_id = ref->multi.id;\n\n                    direct_map_insert( world->refs_map, &ref->multi.id, entry );\n               }\n\n               entry->refs_local++;\n\n               direct_mutex_unlock( &world->refs_lock );\n          }\n     }\n     else {\n          while (ioctl( _fusion_fd( ref->multi.shared ), global ?  FUSION_REF_UP_GLOBAL : FUSION_REF_UP,\n                        &ref->multi.id )) {\n               switch (errno) {\n                    case EINTR:\n                         continue;\n                    case EAGAIN:\n                         return DR_LOCKED;\n                    case EINVAL:\n                         D_ERROR( \"Fusion/Ref: Invalid reference!\\n\" );\n                         return DR_DESTROYED;\n                    default:\n                         break;\n               }\n\n               if (global)\n                    D_PERROR( \"Fusion/Ref: FUSION_REF_UP_GLOBAL\" );\n               else\n                    D_PERROR( \"Fusion/Ref: FUSION_REF_UP\" );\n\n               return DR_FAILURE;\n          }\n\n          D_DEBUG_AT( Fusion_Ref, \"  -> %d references now\\n\",\n                      ioctl( _fusion_fd( ref->multi.shared ), FUSION_REF_STAT, &ref->multi.id ) );\n     }\n\n     return ret;\n}\n\nDirectResult\nfusion_ref_down( FusionRef *ref,\n                 bool       global )\n{\n     D_ASSERT( ref != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p [%d]%s )\\n\", __FUNCTION__, ref, ref->multi.id, global ? \" GLOBAL\" : \"\" );\n\n     if (fusion_config->trace_ref == -1 || ref->multi.id == fusion_config->trace_ref) {\n          D_INFO( \"Fusion/Ref: [%d] down (%s), single refs %d\\n\",\n                  ref->multi.id, global ? \"global\" : \"local\", ref->single.refs );\n          direct_trace_print_stack( NULL );\n     }\n\n     if (ref->multi.user) {\n          FusionWorld *world = _fusion_world( ref->multi.shared );\n\n          if (world->fusion_id == FUSION_ID_MASTER) {\n               direct_mutex_lock( &ref->single.lock );\n\n               if (!ref->single.refs) {\n                    D_BUG( \"no more references\" );\n                    direct_mutex_unlock( &ref->single.lock );\n                    return DR_BUG;\n               }\n\n               if (ref->single.destroyed) {\n                    direct_mutex_unlock( &ref->single.lock );\n                    return DR_DESTROYED;\n               }\n\n               if (!--ref->single.refs) {\n                    ref->single.dead++;\n\n                    if (fusion_config->trace_ref == -1 || ref->multi.id == fusion_config->trace_ref) {\n                         D_INFO( \"Fusion/Ref: [%d] down (%s), single refs got %d -> call %p\\n\",\n                                 ref->multi.id, global ? \"global\" : \"local\", ref->single.refs, ref->single.call );\n                    }\n\n                    if (ref->single.call) {\n                         FusionCall *call = ref->single.call;\n\n                         if (fusion_config->trace_ref == -1 || ref->multi.id == fusion_config->trace_ref) {\n                              D_INFO( \"Fusion/Ref: [%d] down (%s), call_id %d, handler %p/%p\\n\",\n                                      ref->multi.id, global ? \"global\" : \"local\",\n                                      call->call_id, call->handler, call->handler3 );\n                         }\n\n                         if (call->handler) {\n                              FusionCall copy_call = *call;\n                              int        copy_arg  = ref->single.call_arg;\n\n                              direct_mutex_unlock( &ref->single.lock );\n\n                              fusion_call_execute( &copy_call, FCEF_NODIRECT | FCEF_ONEWAY, copy_arg, NULL, NULL );\n\n                              return DR_OK;\n                         }\n                         else if (call->handler3) {\n                              fusion_call_execute3( call, FCEF_NODIRECT | FCEF_ONEWAY | FCEF_QUEUE,\n                                                    ref->single.call_arg, NULL, 0, NULL, 0, NULL );\n\n                              direct_mutex_unlock( &ref->single.lock );\n\n                              fusion_world_flush_calls( world, 1 );\n\n                              return DR_OK;\n                         }\n                    }\n                    else\n                         direct_waitqueue_broadcast( &ref->single.cond );\n               }\n\n               direct_mutex_unlock( &ref->single.lock );\n          }\n          else {\n               FusionRefSlaveSlaveEntry *entry;\n\n               direct_mutex_lock( &world->refs_lock );\n\n               entry = direct_map_lookup( world->refs_map, &ref->multi.id );\n               if (!entry) {\n                    direct_mutex_unlock( &world->refs_lock );\n                    D_WARN( \"[%d] not found\", ref->multi.id );\n                    return DR_ITEMNOTFOUND;\n               }\n\n               if (!--entry->refs_local) {\n                    int i;\n\n                    for (i = 0; i < entry->refs_catch; i++)\n                         fusion_call_execute( &ref->multi.shared->refs_call, FCEF_ONEWAY, ref->multi.id, NULL, NULL );\n\n                    entry->refs_catch = 0;\n               }\n\n               direct_mutex_unlock( &world->refs_lock );\n          }\n     }\n     else {\n          fusion_world_flush_calls( _fusion_world( ref->multi.shared ), 1 );\n\n          while (ioctl( _fusion_fd( ref->multi.shared ), global ? FUSION_REF_DOWN_GLOBAL : FUSION_REF_DOWN,\n                        &ref->multi.id )) {\n               switch (errno) {\n                    case EINTR:\n                         continue;\n                    case EINVAL:\n                         D_ERROR( \"Fusion/Ref: Invalid reference!\\n\" );\n                         return DR_DESTROYED;\n                    default:\n                         break;\n               }\n\n               return DR_FAILURE;\n          }\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_catch( FusionRef *ref )\n{\n     D_ASSERT( ref != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p [%d] )\\n\", __FUNCTION__, ref, ref->multi.id );\n\n     if (fusion_config->trace_ref == -1 || ref->multi.id == fusion_config->trace_ref) {\n          D_INFO( \"Fusion/Ref: [%d] catch, single refs %d\\n\", ref->multi.id, ref->single.refs );\n          direct_trace_print_stack( NULL );\n     }\n\n     if (ref->multi.user) {\n          FusionWorld *world = _fusion_world( ref->multi.shared );\n\n          if (world->fusion_id == FUSION_ID_MASTER) {\n               /* If catcher is master, then we are most likely running in always-indirect mode. */\n               direct_mutex_lock( &ref->single.lock );\n\n               if (ref->single.refs < 2) {\n                    D_BUG( \"master catch with less than two refs\" );\n                    direct_mutex_unlock( &ref->single.lock );\n                    return DR_BUG;\n               }\n\n               ref->single.refs--;\n\n               direct_mutex_unlock( &ref->single.lock );\n          }\n          else {\n               FusionRefSlaveSlaveEntry *entry;\n\n               direct_mutex_lock( &world->refs_lock );\n\n               entry = direct_map_lookup( world->refs_map, &ref->multi.id );\n               if (!entry) {\n                    entry = D_CALLOC( 1, sizeof(FusionRefSlaveSlaveEntry) );\n                    if (!entry) {\n                         direct_mutex_unlock( &world->refs_lock );\n                         return D_OOM();\n                    }\n\n                    entry->ref_id = ref->multi.id;\n\n                    direct_map_insert( world->refs_map, &ref->multi.id, entry );\n               }\n\n               entry->refs_catch++;\n\n               direct_mutex_unlock( &world->refs_lock );\n          }\n     }\n     else {\n          while (ioctl( _fusion_fd( ref->multi.shared ), FUSION_REF_CATCH, &ref->multi.id )) {\n               switch (errno) {\n                    case EINTR:\n                         continue;\n                    case EINVAL:\n                         D_ERROR( \"Fusion/Ref: Invalid reference!\\n\" );\n                         return DR_DESTROYED;\n                    default:\n                         break;\n               }\n\n               D_PERROR( \"Fusion/Ref: FUSION_REF_CATCH\" );\n\n               return DR_FAILURE;\n          }\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_throw( FusionRef *ref,\n                  FusionID   catcher )\n{\n     D_ASSERT( ref != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p [%d] )\\n\", __FUNCTION__, ref, ref->multi.id );\n\n     if (fusion_config->trace_ref == -1 || ref->multi.id == fusion_config->trace_ref) {\n          D_INFO( \"Fusion/Ref: [%d] throw, single refs %d\\n\", ref->multi.id, ref->single.refs );\n          direct_trace_print_stack( NULL );\n     }\n\n     if (ref->multi.user) {\n          FusionWorld *world = _fusion_world( ref->multi.shared );\n\n          if (world->fusion_id == FUSION_ID_MASTER) {\n               /* If catcher is master, then we are most likely running in always-indirect mode. */\n               if (catcher != FUSION_ID_MASTER) {\n                    FusionRefSlaveKey    key;\n                    FusionRefSlaveEntry *slave;\n\n                    key.fusion_id = catcher;\n                    key.ref_id    = ref->multi.id;\n\n                    direct_mutex_lock( &world->refs_lock );\n\n                    slave = direct_map_lookup( world->refs_map, &key );\n                    if (!slave) {\n                         slave = D_CALLOC( 1, sizeof(FusionRefSlaveEntry) );\n                         if (!slave) {\n                              direct_mutex_unlock( &world->refs_lock );\n                              return D_OOM();\n                         }\n\n                         slave->key = key;\n                         slave->ref = ref;\n\n                         direct_map_insert( world->refs_map, &key, slave );\n                    }\n\n                    slave->refs++;\n\n                    direct_mutex_unlock( &world->refs_lock );\n               }\n          }\n          else {\n               D_UNIMPLEMENTED();\n          }\n     }\n     else {\n          FusionRefThrow throw_;\n\n          throw_.id      = ref->multi.id;\n          throw_.catcher = catcher;\n\n          while (ioctl( _fusion_fd( ref->multi.shared ), FUSION_REF_THROW, &throw_ )) {\n               switch (errno) {\n                    case EINTR:\n                         continue;\n                    case EINVAL:\n                         D_ERROR( \"Fusion/Ref: Invalid reference!\\n\" );\n                         return DR_DESTROYED;\n                    default:\n                         break;\n               }\n\n               D_PERROR( \"Fusion/Ref: FUSION_REF_THROW\" );\n\n               return DR_FAILURE;\n          }\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_stat( FusionRef *ref,\n                 int       *refs )\n{\n     int val;\n\n     D_ASSERT( ref != NULL );\n     D_ASSERT( refs != NULL );\n\n     if (ref->multi.user) {\n          if (ref->single.destroyed)\n               return DR_DESTROYED;\n\n          val = ref->single.refs;\n     }\n     else {\n          while ((val = ioctl( _fusion_fd( ref->multi.shared ), FUSION_REF_STAT, &ref->multi.id )) < 0) {\n               switch (errno) {\n                    case EINTR:\n                         continue;\n                    case EINVAL:\n                         D_ERROR( \"Fusion/Ref: Invalid reference!\\n\" );\n                         return DR_DESTROYED;\n                    default:\n                         break;\n               }\n\n               D_PERROR( \"Fusion/Ref: FUSION_REF_STAT\" );\n\n               return DR_FAILURE;\n          }\n     }\n\n     *refs = val;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_zero_trylock( FusionRef *ref )\n{\n     DirectResult ret = DR_OK;\n\n     D_ASSERT( ref != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p )\\n\", __FUNCTION__, ref );\n\n     if (ref->multi.user) {\n          FusionWorld *world = _fusion_world( ref->multi.shared );\n\n          if (world->fusion_id == FUSION_ID_MASTER) {\n               direct_mutex_lock( &ref->single.lock );\n\n               if (ref->single.destroyed)\n                    ret = DR_DESTROYED;\n               else if (ref->single.locked)\n                    ret = DR_LOCKED;\n               else if (ref->single.refs)\n                    ret = DR_BUSY;\n               else\n                    ref->single.locked = direct_gettid();\n\n               direct_mutex_unlock( &ref->single.lock );\n          }\n          else {\n               D_UNIMPLEMENTED();\n\n               return DR_UNIMPLEMENTED;\n          }\n     }\n     else {\n          while (ioctl( _fusion_fd( ref->multi.shared ), FUSION_REF_ZERO_TRYLOCK, &ref->multi.id )) {\n               switch (errno) {\n                    case EINTR:\n                         continue;\n                    case ETOOMANYREFS:\n                         return DR_BUSY;\n                    case EINVAL:\n                         D_ERROR( \"Fusion/Ref: Invalid reference!\\n\" );\n                         return DR_DESTROYED;\n                    default:\n                         break;\n               }\n\n               D_PERROR( \"Fusion/Ref: FUSION_REF_ZERO_TRYLOCK\" );\n\n               return DR_FAILURE;\n          }\n     }\n\n     return ret;\n}\n\nDirectResult\nfusion_ref_unlock( FusionRef *ref )\n{\n     DirectResult ret = DR_OK;\n\n     D_ASSERT( ref != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p )\\n\", __FUNCTION__, ref );\n\n     if (ref->multi.user) {\n          FusionWorld *world = _fusion_world( ref->multi.shared );\n\n          if (world->fusion_id == FUSION_ID_MASTER) {\n               direct_mutex_lock( &ref->single.lock );\n\n               if (ref->single.locked == direct_gettid()) {\n                    ref->single.locked = 0;\n\n                    direct_waitqueue_broadcast( &ref->single.cond );\n               }\n               else\n                    ret = DR_ACCESSDENIED;\n\n               direct_mutex_unlock( &ref->single.lock );\n          }\n          else {\n               D_UNIMPLEMENTED();\n\n               return DR_UNIMPLEMENTED;\n          }\n     }\n     else {\n          while (ioctl( _fusion_fd( ref->multi.shared ), FUSION_REF_UNLOCK, &ref->multi.id )) {\n               switch (errno) {\n                    case EINTR:\n                         continue;\n                    case EINVAL:\n                         D_ERROR( \"Fusion/Ref: Invalid reference!\\n\" );\n                         return DR_DESTROYED;\n                    default:\n                         break;\n               }\n\n               D_PERROR( \"Fusion/Ref: FUSION_REF_UNLOCK\" );\n\n               return DR_FAILURE;\n          }\n     }\n\n     return ret;\n}\n\nDirectResult\nfusion_ref_watch( FusionRef  *ref,\n                  FusionCall *call,\n                  int         call_arg )\n{\n     DirectResult ret = DR_OK;\n\n     D_ASSERT( ref != NULL );\n     D_ASSERT( call != NULL );\n\n     if (ref->multi.user) {\n          FusionWorld *world = _fusion_world( ref->multi.shared );\n\n          if (world->fusion_id == FUSION_ID_MASTER) {\n               direct_mutex_lock( &ref->single.lock );\n\n               if (ref->single.destroyed)\n                    ret = DR_DESTROYED;\n               else if (!ref->single.refs)\n                    ret = DR_BUG;\n               else if (ref->single.call)\n                    ret = DR_BUSY;\n               else {\n                    ref->single.call     = call;\n                    ref->single.call_arg = call_arg;\n               }\n\n               direct_mutex_unlock( &ref->single.lock );\n          }\n          else {\n               D_UNIMPLEMENTED();\n\n               return DR_UNIMPLEMENTED;\n          }\n     }\n     else {\n          FusionRefWatch watch;\n\n          watch.id       = ref->multi.id;\n          watch.call_id  = call->call_id;\n          watch.call_arg = call_arg;\n\n          while (ioctl( _fusion_fd( ref->multi.shared ), FUSION_REF_WATCH, &watch )) {\n               switch (errno) {\n                    case EINTR:\n                         continue;\n                    case EINVAL:\n                         D_ERROR( \"Fusion/Ref: Invalid reference!\\n\" );\n                         return DR_DESTROYED;\n                    default:\n                         break;\n               }\n\n               D_PERROR( \"Fusion/Ref: FUSION_REF_WATCH\" );\n\n               return DR_FAILURE;\n          }\n     }\n\n     return ret;\n}\n\nDirectResult\nfusion_ref_inherit( FusionRef *ref,\n                    FusionRef *from )\n{\n     D_ASSERT( ref != NULL );\n     D_ASSERT( from != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p, %p )\\n\", __FUNCTION__, ref, from );\n\n     if (ref->multi.user) {\n          D_UNIMPLEMENTED();\n\n          return DR_UNIMPLEMENTED;\n     }\n     else {\n          FusionRefInherit inherit;\n\n          inherit.id   = ref->multi.id;\n          inherit.from = from->multi.id;\n\n          while (ioctl( _fusion_fd( ref->multi.shared ), FUSION_REF_INHERIT, &inherit )) {\n               switch (errno) {\n                    case EINTR:\n                         continue;\n                    case EINVAL:\n                         D_ERROR( \"Fusion/Ref: Invalid reference!\\n\" );\n                         return DR_DESTROYED;\n                    default:\n                         break;\n               }\n\n               D_PERROR( \"Fusion/Ref: FUSION_REF_INHERIT\" );\n\n               return DR_FAILURE;\n          }\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_destroy( FusionRef *ref )\n{\n     D_ASSERT( ref != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p [%d] )\\n\", __FUNCTION__, ref, ref->multi.id );\n\n     if (ref->multi.user) {\n          FusionWorld *world = _fusion_world( ref->multi.shared );\n\n          if (world->fusion_id == FUSION_ID_MASTER) {\n               ref->single.destroyed = true;\n\n               direct_waitqueue_broadcast( &ref->single.cond );\n\n               direct_mutex_deinit( &ref->single.lock );\n               direct_waitqueue_deinit( &ref->single.cond );\n          }\n          else {\n               D_UNIMPLEMENTED();\n\n               return DR_UNIMPLEMENTED;\n          }\n     }\n     else {\n          fusion_world_flush_calls( _fusion_world( ref->multi.shared ), 1 );\n\n          while (ioctl( _fusion_fd( ref->multi.shared ), FUSION_REF_DESTROY, &ref->multi.id )) {\n               switch (errno) {\n                    case EINTR:\n                         continue;\n                    case EINVAL:\n                         D_ERROR( \"Fusion/Ref: Invalid reference!\\n\" );\n                         return DR_DESTROYED;\n                    default:\n                         break;\n               }\n\n               D_PERROR( \"Fusion/Ref: FUSION_REF_DESTROY\" );\n\n               return DR_FAILURE;\n          }\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_add_permissions( FusionRef            *ref,\n                            FusionID              fusion_id,\n                            FusionRefPermissions  ref_permissions )\n{\n     if (!ref->multi.user) {\n          FusionEntryPermissions permissions;\n\n          permissions.type        = FT_REF;\n          permissions.id          = ref->multi.id;\n          permissions.fusion_id   = fusion_id;\n          permissions.permissions = 0;\n\n          if (ref_permissions & FUSION_REF_PERMIT_REF_UNREF_LOCAL) {\n               FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_UP );\n               FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_DOWN );\n          }\n\n          if (ref_permissions & FUSION_REF_PERMIT_REF_UNREF_GLOBAL) {\n               FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_UP_GLOBAL );\n               FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_DOWN_GLOBAL );\n          }\n\n          if (ref_permissions & FUSION_REF_PERMIT_ZERO_LOCK_UNLOCK) {\n               FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_ZERO_LOCK );\n               FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_ZERO_TRYLOCK );\n               FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_UNLOCK );\n          }\n\n          if (ref_permissions & FUSION_REF_PERMIT_WATCH)\n               FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_WATCH );\n\n          if (ref_permissions & FUSION_REF_PERMIT_INHERIT)\n               FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_INHERIT );\n\n          if (ref_permissions & FUSION_REF_PERMIT_DESTROY)\n               FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_DESTROY );\n\n          if (ref_permissions & FUSION_REF_PERMIT_CATCH)\n               FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_CATCH );\n\n          if (ref_permissions & FUSION_REF_PERMIT_THROW)\n               FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_THROW );\n\n          while (ioctl( _fusion_fd( ref->multi.shared ), FUSION_ENTRY_ADD_PERMISSIONS, &permissions ) < 0) {\n               if (errno != EINTR) {\n                    D_PERROR( \"Fusion/Ref: FUSION_ENTRY_ADD_PERMISSIONS( id %d )\\n\", ref->multi.id );\n                    return DR_FAILURE;\n               }\n          }\n     }\n\n     return DR_OK;\n}\n\n#else /* FUSION_BUILD_KERNEL */\n\nDirectResult\nfusion_ref_init( FusionRef         *ref,\n                 const char        *name,\n                 const FusionWorld *world )\n{\n     return fusion_ref_init2( ref, name, false, world );\n}\n\nDirectResult\nfusion_ref_init2( FusionRef         *ref,\n                  const char        *name,\n                  bool               user,\n                  const FusionWorld *world )\n{\n     D_ASSERT( ref != NULL );\n     D_ASSERT( name != NULL );\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p, '%s' )\\n\", __FUNCTION__, ref, name ?: \"\" );\n\n     ref->multi.id      = ++world->shared->ref_ids;\n     ref->multi.shared  = world->shared;\n     ref->multi.creator = fusion_id( world );\n     ref->multi.user    = user;\n\n     if (user) {\n          direct_recursive_mutex_init( &ref->single.lock );\n          direct_waitqueue_init( &ref->single.cond );\n\n          ref->single.refs      = 0;\n          ref->single.destroyed = false;\n          ref->single.locked    = 0;\n     }\n     else {\n          ref->multi.builtin.local  = 0;\n          ref->multi.builtin.global = 0;\n\n          fusion_skirmish_init( &ref->multi.builtin.lock, name, world );\n\n          ref->multi.builtin.call = NULL;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_set_name( FusionRef  *ref,\n                     const char *name )\n{\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p, '%s' )\\n\", __FUNCTION__, ref, name );\n\n     return DR_OK;\n}\n\nDirectResult\n_fusion_ref_change( FusionRef *ref,\n                    int        add,\n                    bool       global )\n{\n     DirectResult ret;\n\n     D_ASSERT( ref != NULL );\n     D_ASSERT( add != 0 );\n\n     ret = fusion_skirmish_prevail( &ref->multi.builtin.lock );\n     if (ret)\n          return ret;\n\n     if (global) {\n          if (ref->multi.builtin.global + add < 0) {\n               D_BUG( \"ref has no global references\" );\n               fusion_skirmish_dismiss( &ref->multi.builtin.lock );\n               return DR_BUG;\n          }\n\n          ref->multi.builtin.global += add;\n     }\n     else {\n          if (ref->multi.builtin.local + add < 0) {\n               D_BUG( \"ref has no local references\" );\n               fusion_skirmish_dismiss( &ref->multi.builtin.lock );\n               return DR_BUG;\n          }\n\n          ref->multi.builtin.local += add;\n\n          _fusion_add_local( _fusion_world(ref->multi.shared), ref, add );\n     }\n\n     if (ref->multi.builtin.local + ref->multi.builtin.global == 0) {\n          fusion_skirmish_notify( &ref->multi.builtin.lock );\n\n          if (ref->multi.builtin.call) {\n               fusion_skirmish_dismiss( &ref->multi.builtin.lock );\n               return fusion_call_execute( ref->multi.builtin.call, FCEF_ONEWAY,\n                                           ref->multi.builtin.call_arg, NULL, NULL );\n          }\n     }\n\n     fusion_skirmish_dismiss( &ref->multi.builtin.lock );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_up( FusionRef *ref,\n               bool       global )\n{\n     DirectResult ret = DR_OK;\n\n     D_ASSERT( ref != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p [%d]%s )\\n\", __FUNCTION__, ref, ref->multi.id, global ? \" GLOBAL\" : \"\" );\n\n     if (fusion_config->trace_ref == -1 || ref->multi.id == fusion_config->trace_ref) {\n          D_INFO( \"Fusion/Ref: [%d] up (%s), single refs %d\\n\",\n                  ref->multi.id, global ? \"global\" : \"local\", ref->single.refs );\n          direct_trace_print_stack( NULL );\n     }\n\n     if (ref->multi.user) {\n          FusionWorld *world = _fusion_world( ref->multi.shared );\n\n          if (world->fusion_id == FUSION_ID_MASTER) {\n               direct_mutex_lock( &ref->single.lock );\n\n               if (ref->single.destroyed)\n                    ret = DR_DESTROYED;\n               else if (ref->single.locked)\n                    ret = DR_LOCKED;\n               else\n                    ref->single.refs++;\n\n               direct_mutex_unlock( &ref->single.lock );\n          }\n          else {\n               FusionRefSlaveSlaveEntry *entry;\n\n               direct_mutex_lock( &world->refs_lock );\n\n               entry = direct_map_lookup( world->refs_map, &ref->multi.id );\n               if (!entry) {\n                    entry = D_CALLOC( 1, sizeof(FusionRefSlaveSlaveEntry) );\n                    if (!entry) {\n                         direct_mutex_unlock( &world->refs_lock );\n                         return D_OOM();\n                    }\n\n                    entry->ref_id = ref->multi.id;\n\n                    direct_map_insert( world->refs_map, &ref->multi.id, entry );\n               }\n\n               entry->refs_local++;\n\n               direct_mutex_unlock( &world->refs_lock );\n          }\n     }\n     else\n          return _fusion_ref_change( ref, +1, global );\n\n     return ret;\n}\n\nDirectResult\nfusion_ref_down( FusionRef *ref,\n                 bool       global )\n{\n     D_ASSERT( ref != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p [%d]%s )\\n\", __FUNCTION__, ref, ref->multi.id, global ? \" GLOBAL\" : \"\" );\n\n     if (fusion_config->trace_ref == -1 || ref->multi.id == fusion_config->trace_ref) {\n          D_INFO( \"Fusion/Ref: [%d] down (%s), single refs %d\\n\",\n                  ref->multi.id, global ? \"global\" : \"local\", ref->single.refs );\n          direct_trace_print_stack( NULL );\n     }\n\n     if (ref->multi.user) {\n          FusionWorld *world = _fusion_world( ref->multi.shared );\n\n          if (world->fusion_id == FUSION_ID_MASTER) {\n               direct_mutex_lock( &ref->single.lock );\n\n               if (!ref->single.refs) {\n                    D_BUG( \"no more references\" );\n                    direct_mutex_unlock( &ref->single.lock );\n                    return DR_BUG;\n               }\n\n               if (ref->single.destroyed) {\n                    direct_mutex_unlock( &ref->single.lock );\n                    return DR_DESTROYED;\n               }\n\n               if (!--ref->single.refs) {\n                    ref->single.dead++;\n\n                    if (fusion_config->trace_ref == -1 || ref->multi.id == fusion_config->trace_ref) {\n                         D_INFO( \"Fusion/Ref: [%d] down (%s), single refs got %d -> call %p\\n\",\n                                 ref->multi.id, global ? \"global\" : \"local\", ref->single.refs, ref->single.call );\n                    }\n\n                    if (ref->single.call) {\n                         FusionCall *call = ref->single.call;\n\n                         if (fusion_config->trace_ref == -1 || ref->multi.id == fusion_config->trace_ref) {\n                              D_INFO( \"Fusion/Ref: [%d] down (%s), call_id %d, handler %p/%p\\n\",\n                                      ref->multi.id, global ? \"global\" : \"local\",\n                                      call->call_id, call->handler, call->handler3 );\n                         }\n\n                         if (call->handler) {\n                              FusionCall copy_call = *call;\n                              int        copy_arg  = ref->single.call_arg;\n\n                              direct_mutex_unlock( &ref->single.lock );\n\n                              fusion_call_execute( &copy_call, FCEF_NODIRECT | FCEF_ONEWAY, copy_arg, NULL, NULL );\n\n                              return DR_OK;\n                         }\n                         else if (call->handler3) {\n                              fusion_call_execute3( call, FCEF_NODIRECT | FCEF_ONEWAY | FCEF_QUEUE,\n                                                    ref->single.call_arg, NULL, 0, NULL, 0, NULL );\n\n                              direct_mutex_unlock( &ref->single.lock );\n\n                              fusion_world_flush_calls( world, 1 );\n\n                              return DR_OK;\n                         }\n                    }\n                    else\n                         direct_waitqueue_broadcast( &ref->single.cond );\n               }\n\n               direct_mutex_unlock( &ref->single.lock );\n          }\n          else {\n               FusionRefSlaveSlaveEntry *entry;\n\n               direct_mutex_lock( &world->refs_lock );\n\n               entry = direct_map_lookup( world->refs_map, &ref->multi.id );\n               if (!entry) {\n                    direct_mutex_unlock( &world->refs_lock );\n                    D_WARN( \"[%d] not found\", ref->multi.id );\n                    return DR_ITEMNOTFOUND;\n               }\n\n               if (!--entry->refs_local) {\n                    int i;\n\n                    for (i = 0; i < entry->refs_catch; i++)\n                         fusion_call_execute( &ref->multi.shared->refs_call, FCEF_ONEWAY, ref->multi.id, NULL, NULL );\n\n                    entry->refs_catch = 0;\n               }\n\n               direct_mutex_unlock( &world->refs_lock );\n          }\n     }\n     else\n          return _fusion_ref_change( ref, -1, global );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_catch( FusionRef *ref )\n{\n     D_ASSERT( ref != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p [%d] )\\n\", __FUNCTION__, ref, ref->multi.id );\n\n     if (fusion_config->trace_ref == -1 || ref->multi.id == fusion_config->trace_ref) {\n          D_INFO( \"Fusion/Ref: [%d] catch, single refs %d\\n\", ref->multi.id, ref->single.refs );\n          direct_trace_print_stack( NULL );\n     }\n\n     if (ref->multi.user) {\n          FusionWorld *world = _fusion_world( ref->multi.shared );\n\n          if (world->fusion_id == FUSION_ID_MASTER) {\n               /* If catcher is master, then we are most likely running in always-indirect mode. */\n               direct_mutex_lock( &ref->single.lock );\n\n               if (ref->single.refs < 2) {\n                    D_BUG( \"master catch with less than two refs\" );\n                    direct_mutex_unlock( &ref->single.lock );\n                    return DR_BUG;\n               }\n\n               ref->single.refs--;\n\n               direct_mutex_unlock( &ref->single.lock );\n          }\n          else {\n               FusionRefSlaveSlaveEntry *entry;\n\n               direct_mutex_lock( &world->refs_lock );\n\n               entry = direct_map_lookup( world->refs_map, &ref->multi.id );\n               if (!entry) {\n                    entry = D_CALLOC( 1, sizeof(FusionRefSlaveSlaveEntry) );\n                    if (!entry) {\n                         direct_mutex_unlock( &world->refs_lock );\n                         return D_OOM();\n                    }\n\n                    entry->ref_id = ref->multi.id;\n\n                    direct_map_insert( world->refs_map, &ref->multi.id, entry );\n               }\n\n               entry->refs_catch++;\n\n               direct_mutex_unlock( &world->refs_lock );\n          }\n     }\n     else\n          return fusion_ref_down( ref, false );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_throw( FusionRef *ref,\n                  FusionID   catcher )\n{\n     D_ASSERT( ref != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p [%d] )\\n\", __FUNCTION__, ref, ref->multi.id );\n\n     if (fusion_config->trace_ref == -1 || ref->multi.id == fusion_config->trace_ref) {\n          D_INFO( \"Fusion/Ref: [%d] throw, single refs %d\\n\", ref->multi.id, ref->single.refs );\n          direct_trace_print_stack( NULL );\n     }\n\n     if (ref->multi.user) {\n          FusionWorld *world = _fusion_world( ref->multi.shared );\n\n          if (world->fusion_id == FUSION_ID_MASTER) {\n               /* If catcher is master, then we are most likely running in always-indirect mode. */\n               if (catcher != FUSION_ID_MASTER) {\n                    FusionRefSlaveKey    key;\n                    FusionRefSlaveEntry *slave;\n\n                    key.fusion_id = catcher;\n                    key.ref_id    = ref->multi.id;\n\n                    direct_mutex_lock( &world->refs_lock );\n\n                    slave = direct_map_lookup( world->refs_map, &key );\n                    if (!slave) {\n                         slave = D_CALLOC( 1, sizeof(FusionRefSlaveEntry) );\n                         if (!slave) {\n                              direct_mutex_unlock( &world->refs_lock );\n                              return D_OOM();\n                         }\n\n                         slave->key = key;\n                         slave->ref = ref;\n\n                         direct_map_insert( world->refs_map, &key, slave );\n                    }\n\n                    slave->refs++;\n\n                    direct_mutex_unlock( &world->refs_lock );\n               }\n          }\n          else {\n               D_UNIMPLEMENTED();\n          }\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_stat( FusionRef *ref,\n                 int       *refs )\n{\n     int val;\n\n     D_ASSERT( ref != NULL );\n     D_ASSERT( refs != NULL );\n\n     if (ref->multi.user) {\n          if (ref->single.destroyed)\n               return DR_DESTROYED;\n\n          val = ref->single.refs;\n     }\n     else\n          val = ref->multi.builtin.local + ref->multi.builtin.global;\n\n     *refs = val;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_zero_trylock( FusionRef *ref )\n{\n     DirectResult ret = DR_OK;\n\n     D_ASSERT( ref != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p )\\n\", __FUNCTION__, ref );\n\n     if (ref->multi.user) {\n          FusionWorld *world = _fusion_world( ref->multi.shared );\n\n          if (world->fusion_id == FUSION_ID_MASTER) {\n               direct_mutex_lock( &ref->single.lock );\n\n               if (ref->single.destroyed)\n                    ret = DR_DESTROYED;\n               else if (ref->single.locked)\n                    ret = DR_LOCKED;\n               else if (ref->single.refs)\n                    ret = DR_BUSY;\n               else\n                    ref->single.locked = direct_gettid();\n\n               direct_mutex_unlock( &ref->single.lock );\n          }\n          else {\n               D_UNIMPLEMENTED();\n\n               return DR_UNIMPLEMENTED;\n          }\n     }\n     else {\n          ret = fusion_skirmish_prevail( &ref->multi.builtin.lock );\n          if (ret)\n               return ret;\n\n          if (ref->multi.builtin.local)\n               _fusion_check_locals( _fusion_world(ref->multi.shared), ref );\n\n          if (ref->multi.builtin.local + ref->multi.builtin.global)\n               ret = DR_BUSY;\n\n          if (ret)\n               fusion_skirmish_dismiss( &ref->multi.builtin.lock );\n     }\n\n     return ret;\n}\n\nDirectResult\nfusion_ref_unlock( FusionRef *ref )\n{\n     DirectResult ret = DR_OK;\n\n     D_ASSERT( ref != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p )\\n\", __FUNCTION__, ref );\n\n     if (ref->multi.user) {\n          FusionWorld *world = _fusion_world( ref->multi.shared );\n\n          if (world->fusion_id == FUSION_ID_MASTER) {\n               direct_mutex_lock( &ref->single.lock );\n\n               if (ref->single.locked == direct_gettid()) {\n                    ref->single.locked = 0;\n\n                    direct_waitqueue_broadcast( &ref->single.cond );\n               }\n               else\n                    ret = DR_ACCESSDENIED;\n\n               direct_mutex_unlock( &ref->single.lock );\n          }\n          else {\n               D_UNIMPLEMENTED();\n\n               return DR_UNIMPLEMENTED;\n          }\n     }\n     else\n          fusion_skirmish_dismiss( &ref->multi.builtin.lock );\n\n     return ret;\n}\n\nDirectResult\nfusion_ref_watch( FusionRef  *ref,\n                  FusionCall *call,\n                  int         call_arg )\n{\n     DirectResult ret = DR_OK;\n\n     D_ASSERT( ref != NULL );\n     D_ASSERT( call != NULL );\n\n     if (ref->multi.user) {\n          FusionWorld *world = _fusion_world( ref->multi.shared );\n\n          if (world->fusion_id == FUSION_ID_MASTER) {\n               direct_mutex_lock( &ref->single.lock );\n\n               if (ref->single.destroyed)\n                    ret = DR_DESTROYED;\n               else if (!ref->single.refs)\n                    ret = DR_BUG;\n               else if (ref->single.call)\n                    ret = DR_BUSY;\n               else {\n                    ref->single.call     = call;\n                    ref->single.call_arg = call_arg;\n               }\n\n               direct_mutex_unlock( &ref->single.lock );\n          }\n          else {\n               D_UNIMPLEMENTED();\n\n               return DR_UNIMPLEMENTED;\n          }\n     }\n     else {\n          ret = fusion_skirmish_prevail( &ref->multi.builtin.lock );\n          if (ret)\n               return ret;\n\n          if (ref->multi.builtin.local + ref->multi.builtin.global == 0) {\n               D_BUG( \"ref has no references\" );\n               ret = DR_BUG;\n          }\n          else if (ref->multi.builtin.call) {\n               ret = DR_BUSY;\n          }\n          else {\n               ref->multi.builtin.call     = call;\n               ref->multi.builtin.call_arg = call_arg;\n               fusion_skirmish_notify( &ref->multi.builtin.lock );\n          }\n\n          fusion_skirmish_dismiss( &ref->multi.builtin.lock );\n     }\n\n     return ret;\n}\n\nDirectResult\nfusion_ref_inherit( FusionRef *ref,\n                    FusionRef *from )\n{\n     D_ASSERT( ref != NULL );\n     D_ASSERT( from != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p, %p )\\n\", __FUNCTION__, ref, from );\n\n     D_UNIMPLEMENTED();\n\n     return fusion_ref_up( ref, true );\n}\n\nDirectResult\nfusion_ref_destroy( FusionRef *ref )\n{\n     FusionSkirmish *skirmish;\n\n     D_ASSERT( ref != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p )\\n\", __FUNCTION__, ref );\n\n     skirmish = &ref->multi.builtin.lock;\n     if (skirmish->multi.builtin.destroyed)\n          return DR_DESTROYED;\n\n     _fusion_remove_all_locals( _fusion_world(ref->multi.shared), ref );\n\n     fusion_skirmish_destroy( skirmish );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_add_permissions( FusionRef            *ref,\n                            FusionID              fusion_id,\n                            FusionRefPermissions  ref_permissions )\n{\n     return DR_UNIMPLEMENTED;\n}\n\n#endif /* FUSION_BUILD_KERNEL */\n\n#else /* FUSION_BUILD_MULTI */\n\nDirectResult\nfusion_ref_init( FusionRef         *ref,\n                 const char        *name,\n                 const FusionWorld *world )\n{\n     D_ASSERT( ref != NULL );\n     D_ASSERT( name != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p )\\n\", __FUNCTION__, ref );\n\n     direct_recursive_mutex_init( &ref->single.lock );\n     direct_waitqueue_init( &ref->single.cond );\n\n     ref->single.refs      = 0;\n     ref->single.destroyed = false;\n     ref->single.locked    = 0;\n     ref->multi.id         = (long) ref;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_init2( FusionRef         *ref,\n                  const char        *name,\n                  bool               user,\n                  const FusionWorld *world )\n{\n     return fusion_ref_init( ref, name, world );\n}\n\nDirectResult\nfusion_ref_set_name( FusionRef  *ref,\n                     const char *name )\n{\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p, '%s' )\\n\", __FUNCTION__, ref, name );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_up( FusionRef *ref,\n               bool       global )\n{\n     DirectResult ret = DR_OK;\n\n     D_ASSERT( ref != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p [0x%08x]%s )\\n\", __FUNCTION__,\n                 ref, (unsigned int) ref->multi.id, global ? \" GLOBAL\" : \"\" );\n\n     if (fusion_config->trace_ref == -1 || ref->multi.id == fusion_config->trace_ref) {\n          D_INFO( \"Fusion/Ref: [0x%08x] up (%s), single refs %d\\n\",\n                  (unsigned int) ref->multi.id, global ? \"global\" : \"local\", ref->single.refs );\n          direct_trace_print_stack( NULL );\n     }\n\n     direct_mutex_lock( &ref->single.lock );\n\n     if (ref->single.destroyed)\n          ret = DR_DESTROYED;\n     else if (ref->single.locked)\n          ret = DR_LOCKED;\n     else\n          ref->single.refs++;\n\n     direct_mutex_unlock( &ref->single.lock );\n\n     return ret;\n}\n\nDirectResult\nfusion_ref_down( FusionRef *ref,\n                 bool       global )\n{\n     D_ASSERT( ref != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p [0x%08x]%s )\\n\", __FUNCTION__,\n                 ref, (unsigned int) ref->multi.id, global ? \" GLOBAL\" : \"\" );\n\n     if (fusion_config->trace_ref == -1 || ref->multi.id == fusion_config->trace_ref) {\n          D_INFO( \"Fusion/Ref: [0x%08x] down (%s), single refs %d\\n\",\n                  (unsigned int) ref->multi.id, global ? \"global\" : \"local\", ref->single.refs );\n          direct_trace_print_stack( NULL );\n     }\n\n     direct_mutex_lock( &ref->single.lock );\n\n     if (!ref->single.refs) {\n          D_BUG( \"no more references\" );\n          direct_mutex_unlock( &ref->single.lock );\n          return DR_BUG;\n     }\n\n     if (ref->single.destroyed) {\n          direct_mutex_unlock( &ref->single.lock );\n          return DR_DESTROYED;\n     }\n\n     if (!--ref->single.refs) {\n          if (ref->single.call) {\n               FusionCall *call = ref->single.call;\n\n               if (call->handler) {\n                    FusionCall copy_call = *call;\n                    int        copy_arg  = ref->single.call_arg;\n\n                    direct_mutex_unlock( &ref->single.lock );\n\n                    fusion_call_execute( &copy_call, FCEF_NODIRECT | FCEF_ONEWAY, copy_arg, NULL, NULL );\n\n                    return DR_OK;\n               }\n          }\n          else\n               direct_waitqueue_broadcast( &ref->single.cond );\n     }\n\n     direct_mutex_unlock( &ref->single.lock );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_catch( FusionRef *ref )\n{\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p [0x%08x] )\\n\", __FUNCTION__, ref, (unsigned int) ref->multi.id );\n\n     if (fusion_config->trace_ref == -1 || ref->multi.id == fusion_config->trace_ref) {\n          D_INFO( \"Fusion/Ref: [0x%08x] catch, single refs %d\\n\", (unsigned int) ref->multi.id, ref->single.refs );\n          direct_trace_print_stack( NULL );\n     }\n\n     return fusion_ref_down( ref, false );\n}\n\nDirectResult\nfusion_ref_throw( FusionRef *ref,\n                  FusionID   catcher )\n{\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p [0x%08x] )\\n\", __FUNCTION__, ref, (unsigned int) ref->multi.id );\n\n     if (fusion_config->trace_ref == -1 || ref->multi.id == fusion_config->trace_ref) {\n          D_INFO( \"Fusion/Ref: [0x%08x] throw, single refs %d\\n\", (unsigned int) ref->multi.id, ref->single.refs );\n          direct_trace_print_stack( NULL );\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_stat( FusionRef *ref,\n                 int       *refs )\n{\n     D_ASSERT( ref != NULL );\n     D_ASSERT( refs != NULL );\n\n     if (ref->single.destroyed)\n          return DR_DESTROYED;\n\n     *refs = ref->single.refs;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_zero_trylock( FusionRef *ref )\n{\n     DirectResult ret = DR_OK;\n\n     D_ASSERT( ref != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p )\\n\", __FUNCTION__, ref );\n\n     direct_mutex_lock( &ref->single.lock );\n\n     if (ref->single.destroyed)\n          ret = DR_DESTROYED;\n     else if (ref->single.locked)\n          ret = DR_LOCKED;\n     else if (ref->single.refs)\n          ret = DR_BUSY;\n     else\n          ref->single.locked = direct_gettid();\n\n     direct_mutex_unlock( &ref->single.lock );\n\n     return ret;\n}\n\nDirectResult\nfusion_ref_unlock( FusionRef *ref )\n{\n     DirectResult ret = DR_OK;\n\n     D_ASSERT( ref != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p )\\n\", __FUNCTION__, ref );\n\n     direct_mutex_lock( &ref->single.lock );\n\n     if (ref->single.locked == direct_gettid()) {\n          ref->single.locked = 0;\n\n          direct_waitqueue_broadcast( &ref->single.cond );\n     }\n     else\n          ret = DR_ACCESSDENIED;\n\n     direct_mutex_unlock( &ref->single.lock );\n\n     return ret;\n}\n\nDirectResult\nfusion_ref_watch( FusionRef  *ref,\n                  FusionCall *call,\n                  int         call_arg )\n{\n     DirectResult ret = DR_OK;\n\n     D_ASSERT( ref != NULL );\n     D_ASSERT( call != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p )\\n\", __FUNCTION__, ref );\n\n     direct_mutex_lock( &ref->single.lock );\n\n     if (ref->single.destroyed)\n          ret = DR_DESTROYED;\n     else if (!ref->single.refs)\n          ret = DR_BUG;\n     else if (ref->single.call)\n          ret = DR_BUSY;\n     else {\n          ref->single.call     = call;\n          ref->single.call_arg = call_arg;\n     }\n\n     direct_mutex_unlock( &ref->single.lock );\n\n     return ret;\n}\n\nDirectResult\nfusion_ref_inherit( FusionRef *ref,\n                    FusionRef *from )\n{\n     D_ASSERT( ref != NULL );\n     D_ASSERT( from != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p, %p )\\n\", __FUNCTION__, ref, from );\n\n     D_UNIMPLEMENTED();\n\n     return fusion_ref_up( ref, true );\n}\n\nDirectResult\nfusion_ref_destroy( FusionRef *ref )\n{\n     D_ASSERT( ref != NULL );\n\n     D_DEBUG_AT( Fusion_Ref, \"%s( %p )\\n\", __FUNCTION__, ref );\n\n     ref->single.destroyed = true;\n\n     direct_waitqueue_broadcast( &ref->single.cond );\n\n     direct_mutex_deinit( &ref->single.lock );\n     direct_waitqueue_deinit( &ref->single.cond );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_ref_add_permissions( FusionRef            *ref,\n                            FusionID              fusion_id,\n                            FusionRefPermissions  ref_permissions )\n{\n     return DR_OK;\n}\n\n#endif /* FUSION_BUILD_MULTI */\n"
  },
  {
    "path": "lib/fusion/ref.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FUSION__REF_H__\n#define __FUSION__REF_H__\n\n#include <fusion/lock.h>\n\n/**********************************************************************************************************************/\n\nstruct __Fusion_FusionRef {\n     /* multi app */\n     struct {\n          int                  id;\n          FusionWorldShared   *shared;\n          FusionID             creator;\n          /* builtin impl */\n          struct {\n               int             local;\n               int             global;\n               FusionSkirmish  lock;\n\n               FusionCall     *call;\n               int             call_arg;\n          } builtin;\n          bool                 user;\n     } multi;\n\n     /* single app */\n     struct {\n          int                  refs;\n          DirectWaitQueue      cond;\n          DirectMutex          lock;\n          int                  dead;\n          bool                 destroyed;\n          int                  locked;\n\n          FusionCall          *call;\n          int                  call_arg;\n     } single;\n};\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     FUSION_REF_PERMIT_NONE             = 0x00000000,\n\n     FUSION_REF_PERMIT_REF_UNREF_LOCAL  = 0x00000001,\n     FUSION_REF_PERMIT_REF_UNREF_GLOBAL = 0x00000002,\n     FUSION_REF_PERMIT_ZERO_LOCK_UNLOCK = 0x00000004,\n     FUSION_REF_PERMIT_WATCH            = 0x00000008,\n     FUSION_REF_PERMIT_INHERIT          = 0x00000010,\n     FUSION_REF_PERMIT_DESTROY          = 0x00000020,\n     FUSION_REF_PERMIT_CATCH            = 0x00000040,\n     FUSION_REF_PERMIT_THROW            = 0x00000080,\n\n     FUSION_REF_PERMIT_ALL              = 0x000000FF\n} FusionRefPermissions;\n\n/**********************************************************************************************************************/\n\n/*\n * Initialize.\n */\nDirectResult FUSION_API fusion_ref_init           ( FusionRef            *ref,\n                                                    const char           *name,\n                                                    const FusionWorld    *world );\n\n/*\n * Initialize with 'user' set to true for secure fusion.\n */\nDirectResult FUSION_API fusion_ref_init2          ( FusionRef            *ref,\n                                                    const char           *name,\n                                                    bool                  user,\n                                                    const FusionWorld    *world );\n\n/*\n * Change name.\n */\nDirectResult FUSION_API fusion_ref_set_name       ( FusionRef            *ref,\n                                                    const char           *name );\n\n/*\n * Lock, increase, unlock.\n */\nDirectResult FUSION_API fusion_ref_up             ( FusionRef            *ref,\n                                                    bool                  global );\n\n/*\n * Lock, decrease, unlock.\n */\nDirectResult FUSION_API fusion_ref_down           ( FusionRef            *ref,\n                                                    bool                  global );\n\n/*\n * Catch reference\n */\nDirectResult FUSION_API fusion_ref_catch          ( FusionRef            *ref );\n\n/*\n * Throw reference\n */\nDirectResult FUSION_API fusion_ref_throw          ( FusionRef            *ref,\n                                                    FusionID              catcher );\n\n/*\n * Get the current reference count. This value is not reliable, because no locking will be performed.\n */\nDirectResult FUSION_API fusion_ref_stat           ( FusionRef            *ref,\n                                                    int                  *refs );\n\n/*\n * Check for zero and lock if true.\n */\nDirectResult FUSION_API fusion_ref_zero_trylock   ( FusionRef            *ref );\n\n/*\n * Unlock the counter.\n */\nDirectResult FUSION_API fusion_ref_unlock         ( FusionRef            *ref );\n\n/*\n * Have the call executed when reference counter reaches zero.\n */\nDirectResult FUSION_API fusion_ref_watch          ( FusionRef            *ref,\n                                                    FusionCall           *call,\n                                                    int                   call_arg );\n\n/*\n * Inherit local reference count from another reference.\n */\nDirectResult FUSION_API fusion_ref_inherit        ( FusionRef            *ref,\n                                                    FusionRef            *from );\n\n/*\n * Deinitialize.\n */\nDirectResult FUSION_API fusion_ref_destroy        ( FusionRef            *ref );\n\n/*\n * Give permissions to another fusionee to use the reference.\n */\nDirectResult FUSION_API fusion_ref_add_permissions( FusionRef            *ref,\n                                                    FusionID              fusion_id,\n                                                    FusionRefPermissions  permissions );\n\n#endif\n"
  },
  {
    "path": "lib/fusion/shm/fake.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/mem.h>\n#include <fusion/fusion_internal.h>\n#include <fusion/shm/pool.h>\n\nD_DEBUG_DOMAIN( Fusion_FakeSHMPool, \"Fusion/FakeSHMPool\", \"Fusion Fake Shared Memory Pool\" );\n\n/**********************************************************************************************************************/\n\nDirectResult\nfusion_shm_pool_create( FusionWorld          *world,\n                        const char           *name,\n                        unsigned int          max_size,\n                        bool                  debug,\n                        FusionSHMPoolShared **ret_pool )\n{\n     FusionSHMPoolShared *pool;\n\n     D_DEBUG_AT( Fusion_FakeSHMPool, \"%s( %p [%d], '%s', %u, %p, %sdebug )\\n\", __FUNCTION__,\n                 world, world->shared->world_index, name, max_size, ret_pool, debug ? \"\" : \"no-\" );\n\n     pool = D_CALLOC( 1, sizeof(FusionSHMPoolShared) );\n     if (!pool)\n          return D_OOM();\n\n     pool->debug = debug;\n\n     D_MAGIC_SET( pool, FusionSHMPoolShared );\n\n     *ret_pool = pool;\n\n     D_DEBUG_AT( Fusion_FakeSHMPool, \"  -> %p\\n\", *ret_pool );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_shm_pool_destroy( FusionWorld         *world,\n                         FusionSHMPoolShared *pool )\n{\n     D_DEBUG_AT( Fusion_FakeSHMPool, \"%s( %p, %p )\\n\", __FUNCTION__, world, pool );\n\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n\n     D_MAGIC_CLEAR( pool );\n\n     D_FREE( pool );\n\n     return DR_OK;\n}\n"
  },
  {
    "path": "lib/fusion/shm/heap.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/filesystem.h>\n#include <direct/memcpy.h>\n#include <fusion/conf.h>\n#include <fusion/shmalloc.h>\n#include <fusion/shm/shm_internal.h>\n\nD_DEBUG_DOMAIN( Fusion_SHMHeap, \"Fusion/SHMHeap\", \"Fusion Shared Memory Heap\" );\n\n/**********************************************************************************************************************/\n\n/* Number of contiguous free blocks allowed to build up at the end of memory before being returned to the system. */\n#define FINAL_FREE_BLOCKS 8\n\n/* Address to block number and vice versa. */\n#define BLOCK(A)   (((char*) (A) - heap->heapbase) / BLOCKSIZE + 1)\n#define ADDRESS(B) ((void*) (((B) - 1) * BLOCKSIZE + heap->heapbase))\n\n/*\n * Aligned allocation.\n */\nstatic void *\nalign( shmalloc_heap *heap,\n       size_t         size )\n{\n     void          *result;\n     unsigned long  adj;\n\n     D_DEBUG_AT( Fusion_SHMHeap, \"%s( %p, \"_ZU\" )\\n\", __FUNCTION__, heap, size );\n\n     D_MAGIC_ASSERT( heap, shmalloc_heap );\n\n     result = __shmalloc_brk( heap, size );\n\n     adj = (unsigned long) result % BLOCKSIZE;\n     if (adj != 0) {\n          adj = BLOCKSIZE - adj;\n          __shmalloc_brk( heap, adj );\n          result = (char*) result + adj;\n     }\n\n     return result;\n}\n\n/*\n * Get neatly aligned memory, initializing or growing the heap info table as necessary.\n */\nstatic void *\nmorecore( shmalloc_heap *heap,\n          size_t         size )\n{\n     void          *result;\n     shmalloc_info *newinfo, *oldinfo;\n     size_t         newsize;\n\n     D_DEBUG_AT( Fusion_SHMHeap, \"%s( %p, \"_ZU\" )\\n\", __FUNCTION__, heap, size );\n\n     D_MAGIC_ASSERT( heap, shmalloc_heap );\n\n     result = align( heap, size );\n     if (result == NULL)\n          return NULL;\n\n     /* Check if we need to grow the info table. */\n     if ((size_t) BLOCK( (char*) result + size ) > heap->heapsize) {\n          newsize = heap->heapsize;\n\n          while ((size_t) BLOCK( (char*) result + size ) > newsize)\n               newsize *= 2;\n\n          newinfo = (shmalloc_info*) align( heap, newsize * sizeof(shmalloc_info) );\n          if (newinfo == NULL) {\n               __shmalloc_brk( heap, -size );\n               return NULL;\n          }\n\n          direct_memcpy( newinfo, heap->heapinfo, heap->heapsize * sizeof(shmalloc_info) );\n\n          memset( newinfo + heap->heapsize, 0, (newsize - heap->heapsize) * sizeof(shmalloc_info) );\n\n          oldinfo = heap->heapinfo;\n\n          newinfo[BLOCK( oldinfo )].busy.type = 0;\n          newinfo[BLOCK( oldinfo )].busy.info.size = BLOCKIFY( heap->heapsize * sizeof(shmalloc_info) );\n\n          heap->heapinfo = newinfo;\n\n          _fusion_shfree( heap, oldinfo );\n\n          heap->heapsize = newsize;\n     }\n\n     heap->heaplimit = BLOCK( (char*) result + size );\n\n     return result;\n}\n\n/**********************************************************************************************************************/\n\nvoid *\n_fusion_shmalloc( shmalloc_heap *heap,\n                  size_t         size )\n{\n     void        *result;\n     size_t       i, block, blocks, lastblocks, start;\n     struct list *next;\n\n     D_DEBUG_AT( Fusion_SHMHeap, \"%s( %p, \"_ZU\" )\\n\", __FUNCTION__, heap, size );\n\n     D_MAGIC_ASSERT( heap, shmalloc_heap );\n\n     /* Some programs will call shmalloc with size = 0. We let them pass. */\n     if (size == 0)\n          return NULL;\n\n     if (size < sizeof(struct list))\n          size = sizeof(struct list);\n\n     /* Determine the allocation policy based on the request size. */\n     if (size <= BLOCKSIZE / 2) {\n          /* Small allocation to receive a fragment of a block.\n             Determine the logarithm to base two of the fragment size. */\n          size_t log = 1;\n          --size;\n          while ((size /= 2) != 0)\n               ++log;\n\n          /* Look in the fragment lists for a free fragment of the desired size. */\n          next = heap->fraghead[log].next;\n          if (next != NULL) {\n               /* There are free fragments of this size.\n                  Pop a fragment out of the fragment list and return it. */\n               result = next;\n               next->prev->next = next->next;\n               if (next->next != NULL)\n                    next->next->prev = next->prev;\n               block = BLOCK( result );\n               if (--heap->heapinfo[block].busy.info.frag.nfree != 0)\n                    heap->heapinfo[block].busy.info.frag.first = ((char*) next->next - (char*) NULL) % BLOCKSIZE >> log;\n\n               /* Update the statistics. */\n               heap->chunks_used++;\n               heap->bytes_used += 1 << log;\n               heap->chunks_free--;\n               heap->bytes_free -= 1 << log;\n          }\n          else {\n               /* No free fragments of the desired size.\n                  Get a new block and break it into fragments, returning the first. */\n               result = _fusion_shmalloc( heap, BLOCKSIZE );\n               if (result == NULL)\n                    return NULL;\n\n               heap->fragblocks[log]++;\n\n               /* Link all fragments but the first into the free list. */\n               for (i = 1; i < BLOCKSIZE >> log; ++i) {\n                    next = (struct list*) ((char*) result + (i << log));\n                    next->next = heap->fraghead[log].next;\n                    next->prev = &heap->fraghead[log];\n                    next->prev->next = next;\n                    if (next->next != NULL)\n                         next->next->prev = next;\n               }\n\n               /* Initialize the nfree and first counters for this block. */\n               block = BLOCK( result );\n               heap->heapinfo[block].busy.type = log;\n               heap->heapinfo[block].busy.info.frag.nfree = i - 1;\n               heap->heapinfo[block].busy.info.frag.first = i - 1;\n\n               heap->chunks_free += (BLOCKSIZE >> log) - 1;\n               heap->bytes_free += BLOCKSIZE - (1 << log);\n               heap->bytes_used -= BLOCKSIZE - (1 << log);\n          }\n     }\n     else {\n          /* Large allocation to receive one or more blocks.\n             Search the free list in a circle starting at the last place visited.\n             If we loop completely around without finding a large enough space,\n             we will have to get more memory from the system. */\n          blocks = BLOCKIFY( size );\n          start = block = heap->heapindex;\n          while (heap->heapinfo[block].free.size < blocks) {\n               block = heap->heapinfo[block].free.next;\n               if (block == start) {\n                    /* Need to get more from the system.\n                       Check to see if the new core will be contiguous with the final free block.\n                       If so we don't need to get as much. */\n                    block = heap->heapinfo[0].free.prev;\n                    lastblocks = heap->heapinfo[block].free.size;\n                    if (heap->heaplimit != 0 && block + lastblocks == heap->heaplimit &&\n                        __shmalloc_brk( heap, 0 ) == ADDRESS( block + lastblocks ) &&\n                        (morecore( heap, (blocks - lastblocks) * BLOCKSIZE) ) != NULL) {\n                         block = heap->heapinfo[0].free.prev;\n                         heap->heapinfo[block].free.size += blocks - lastblocks;\n                         heap->bytes_free += (blocks - lastblocks) * BLOCKSIZE;\n                         continue;\n                    }\n                    result = morecore( heap, blocks * BLOCKSIZE );\n                    if (result == NULL)\n                         return NULL;\n                    block = BLOCK( result );\n                    heap->heapinfo[block].busy.type = 0;\n                    heap->heapinfo[block].busy.info.size = blocks;\n                    heap->chunks_used++;\n                    heap->bytes_used += blocks * BLOCKSIZE;\n                    return result;\n               }\n          }\n\n          /* At this point we have found a suitable free list entry.\n             Figure out how to remove what we need from the list. */\n          result = ADDRESS( block );\n          if (heap->heapinfo[block].free.size > blocks) {\n               /* The block we found has a bit left over, so relink the tail end back into the free list. */\n               heap->heapinfo[block + blocks].free.size = heap->heapinfo[block].free.size - blocks;\n               heap->heapinfo[block + blocks].free.next = heap->heapinfo[block].free.next;\n               heap->heapinfo[block + blocks].free.prev = heap->heapinfo[block].free.prev;\n               heap->heapinfo[heap->heapinfo[block].free.next].free.prev = block + blocks;\n               heap->heapinfo[heap->heapinfo[block].free.prev].free.next = block + blocks;\n               heap->heapindex = block + blocks;\n          }\n          else {\n               /* The block exactly matches our requirements, so just remove it from the list. */\n               heap->heapinfo[heap->heapinfo[block].free.next].free.prev = heap->heapinfo[block].free.prev;\n               heap->heapinfo[heap->heapinfo[block].free.prev].free.next = heap->heapinfo[block].free.next;\n               heap->heapindex = heap->heapinfo[block].free.next;\n               heap->chunks_free--;\n          }\n\n          heap->heapinfo[block].busy.type = 0;\n          heap->heapinfo[block].busy.info.size = blocks;\n          heap->chunks_used++;\n          heap->bytes_used += blocks * BLOCKSIZE;\n          heap->bytes_free -= blocks * BLOCKSIZE;\n     }\n\n     return result;\n}\n\nvoid *\n_fusion_shrealloc( shmalloc_heap *heap,\n                   void          *ptr,\n                   size_t         size )\n{\n     void   *result;\n     int     type;\n     size_t  block, blocks, oldlimit;\n\n     D_DEBUG_AT( Fusion_SHMHeap, \"%s( %p, %p, \"_ZU\" )\\n\", __FUNCTION__, heap, ptr, size );\n\n     D_MAGIC_ASSERT( heap, shmalloc_heap );\n\n     if (ptr == NULL)\n          return _fusion_shmalloc( heap, size );\n     else if (size == 0) {\n          _fusion_shfree( heap, ptr );\n          return NULL;\n     }\n\n     block = BLOCK( ptr );\n\n     type = heap->heapinfo[block].busy.type;\n     switch (type) {\n          case 0:\n               /* Maybe reallocate a large block to a small fragment. */\n               if (size <= BLOCKSIZE / 2) {\n                    result = _fusion_shmalloc( heap, size );\n                    if (result != NULL) {\n                         direct_memcpy( result, ptr, size );\n                         _fusion_shfree( heap, ptr );\n                         return result;\n                    }\n               }\n\n               /* The new size is a large allocation as well; see if we can hold it in place. */\n               blocks = BLOCKIFY( size );\n               if (blocks < heap->heapinfo[block].busy.info.size) {\n                    /* The new size is smaller; return excess memory to the free list. */\n                    heap->heapinfo[block + blocks].busy.type = 0;\n                    heap->heapinfo[block + blocks].busy.info.size = heap->heapinfo[block].busy.info.size - blocks;\n                    heap->heapinfo[block].busy.info.size = blocks;\n                    _fusion_shfree( heap, ADDRESS( block + blocks ) );\n                    result = ptr;\n               }\n               else if (blocks == heap->heapinfo[block].busy.info.size)\n                    /* No size change necessary. */\n                    result = ptr;\n               else {\n                    /* Won't fit, so allocate a new region that will.\n                       Free the old region first in case there is sufficient adjacent space to grow without moving. */\n                    blocks = heap->heapinfo[block].busy.info.size;\n                    oldlimit = heap->heaplimit;\n                    heap->heaplimit = 0;\n                    _fusion_shfree( heap, ptr );\n                    heap->heaplimit = oldlimit;\n                    result = _fusion_shmalloc( heap, size );\n                    if (result == NULL) {\n                         /* We have to unfree the thing we just freed.\n                            Unfortunately it might have been coalesced with its neighbors. */\n                         if (heap->heapindex == block)\n                              _fusion_shmalloc( heap, blocks * BLOCKSIZE );\n                         else {\n                              void *previous = _fusion_shmalloc( heap, (block - heap->heapindex) * BLOCKSIZE );\n                              _fusion_shmalloc( heap, blocks * BLOCKSIZE );\n                              _fusion_shfree( heap, previous );\n                         }\n                         return NULL;\n                    }\n                    if (ptr != result)\n                         direct_memmove( result, ptr, blocks * BLOCKSIZE );\n               }\n               break;\n\n          default:\n               /* Old size is a fragment; type is logarithm to base two of the fragment size. */\n               if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type))\n                    /* The new size is the same kind of fragment. */\n                    result = ptr;\n               else {\n                    /* The new size is different; allocate a new space, copy the lesser of the new size and the old. */\n                    result = _fusion_shmalloc( heap, size );\n                    if (result == NULL)\n                         return NULL;\n                    direct_memcpy( result, ptr, MIN( size, (size_t) 1 << type ) );\n                    _fusion_shfree( heap, ptr );\n               }\n               break;\n     }\n\n     return result;\n}\n\nvoid\n_fusion_shfree( shmalloc_heap *heap,\n                void          *ptr )\n{\n     int          type;\n     size_t       i, block, blocks;\n     struct list *prev, *next;\n\n     D_DEBUG_AT( Fusion_SHMHeap, \"%s( %p, %p )\\n\", __FUNCTION__, heap, ptr );\n\n     D_MAGIC_ASSERT( heap, shmalloc_heap );\n\n     if (ptr == NULL)\n          return;\n\n     block = BLOCK( ptr );\n\n     type = heap->heapinfo[block].busy.type;\n     switch (type) {\n          case 0:\n               /* Get as many statistics as early as we can. */\n               heap->chunks_used--;\n               heap->bytes_used -= heap->heapinfo[block].busy.info.size * BLOCKSIZE;\n               heap->bytes_free += heap->heapinfo[block].busy.info.size * BLOCKSIZE;\n\n               /* Find the free cluster previous to this one in the free list. */\n               i = heap->heapindex;\n               if (i > block)\n                    while (i > block)\n                         i = heap->heapinfo[i].free.prev;\n               else {\n                    do\n                         i = heap->heapinfo[i].free.next;\n                    while (i > 0 && i < block);\n                    i = heap->heapinfo[i].free.prev;\n               }\n\n               /* Determine how to link this block into the free list. */\n               if (block == i + heap->heapinfo[i].free.size) {\n                    /* Coalesce this block with its predecessor. */\n                    heap->heapinfo[i].free.size += heap->heapinfo[block].busy.info.size;\n                    block = i;\n               }\n               else {\n                    /* Really link this block back into the free list. */\n                    heap->heapinfo[block].free.size = heap->heapinfo[block].busy.info.size;\n                    heap->heapinfo[block].free.next = heap->heapinfo[i].free.next;\n                    heap->heapinfo[block].free.prev = i;\n                    heap->heapinfo[i].free.next = block;\n                    heap->heapinfo[heap->heapinfo[block].free.next].free.prev = block;\n                    heap->chunks_free++;\n               }\n\n               /* Now that the block is linked in, see if we can coalesce it with its successor\n                  (by deleting its successor from the list and adding in its size). */\n               if (block + heap->heapinfo[block].free.size == heap->heapinfo[block].free.next) {\n                    heap->heapinfo[block].free.size += heap->heapinfo[heap->heapinfo[block].free.next].free.size;\n                    heap->heapinfo[block].free.next = heap->heapinfo[heap->heapinfo[block].free.next].free.next;\n                    heap->heapinfo[heap->heapinfo[block].free.next].free.prev = block;\n                    heap->chunks_free--;\n               }\n\n               blocks = heap->heapinfo[block].free.size;\n\n               /* Punch a hole into the tmpfs file to really free RAM. */\n               if (fusion_config->madv_remove)\n                    madvise( ADDRESS( block ), blocks * BLOCKSIZE, MADV_REMOVE );\n\n               /* Now see if we can truncate the end. */\n               if (blocks >= FINAL_FREE_BLOCKS && block + blocks == heap->heaplimit &&\n                   __shmalloc_brk( heap, 0 ) == ADDRESS( block + blocks )) {\n                    size_t bytes = blocks * BLOCKSIZE;\n                    heap->heaplimit -= blocks;\n                    __shmalloc_brk( heap, -bytes );\n                    heap->heapinfo[heap->heapinfo[block].free.prev].free.next = heap->heapinfo[block].free.next;\n                    heap->heapinfo[heap->heapinfo[block].free.next].free.prev = heap->heapinfo[block].free.prev;\n                    block = heap->heapinfo[block].free.prev;\n                    heap->chunks_free--;\n                    heap->bytes_free -= bytes;\n               }\n\n               /* Set the next search to begin at this block. */\n               heap->heapindex = block;\n               break;\n\n          default:\n               /* Do some of the statistics. */\n               heap->chunks_used--;\n               heap->bytes_used -= 1 << type;\n               heap->chunks_free++;\n               heap->bytes_free += 1 << type;\n\n               /* Get the address of the first free fragment in this block. */\n               prev = (struct list*) ((char*) ADDRESS( block ) + (heap->heapinfo[block].busy.info.frag.first << type));\n\n               if (heap->heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1 && heap->fragblocks[type] > 1)\n               {\n                    /* If all fragments of this block are free, remove them from the fragment list, free whole block. */\n                    heap->fragblocks[type]--;\n                    next = prev;\n                    for (i = 1; i < BLOCKSIZE >> type; ++i)\n                         next = next->next;\n                    prev->prev->next = next;\n                    if (next != NULL)\n                         next->prev = prev->prev;\n                    heap->heapinfo[block].busy.type = 0;\n                    heap->heapinfo[block].busy.info.size = 1;\n\n                    /* Keep the statistics accurate. */\n                    heap->chunks_used++;\n                    heap->bytes_used += BLOCKSIZE;\n                    heap->chunks_free -= BLOCKSIZE >> type;\n                    heap->bytes_free -= BLOCKSIZE;\n\n                    _fusion_shfree( heap, ADDRESS( block ) );\n               }\n               else if (heap->heapinfo[block].busy.info.frag.nfree != 0) {\n                    /* If some fragments of this block are free, link this fragment into the fragment list\n                       after the first free fragment of this block. */\n                    next = (struct list*) ptr;\n                    next->next = prev->next;\n                    next->prev = prev;\n                    prev->next = next;\n                    if (next->next != NULL)\n                         next->next->prev = next;\n                    heap->heapinfo[block].busy.info.frag.nfree++;\n               }\n               else {\n                    /* No fragments of this block are free, so link this fragment into the fragment list and\n                       announce that it is the first free fragment of this block. */\n                    prev = (struct list*) ptr;\n                    heap->heapinfo[block].busy.info.frag.nfree = 1;\n                    heap->heapinfo[block].busy.info.frag.first = ((char*) ptr - (char*) NULL) % BLOCKSIZE >> type;\n                    prev->next = heap->fraghead[type].next;\n                    prev->prev = &heap->fraghead[type];\n                    prev->prev->next = prev;\n                    if (prev->next != NULL)\n                         prev->next->prev = prev;\n               }\n               break;\n     }\n}\n\n/**********************************************************************************************************************/\n\nDirectResult\n__shmalloc_init_heap( FusionSHM  *shm,\n                      const char *filename,\n                      void       *addr_base,\n                      int         space,\n                      int        *ret_size )\n{\n     DirectResult   ret;\n     int            size;\n     int            heapsize = (space + BLOCKSIZE - 1) / BLOCKSIZE;\n     DirectFile     fd;\n     shmalloc_heap *heap = NULL;\n\n     D_DEBUG_AT( Fusion_SHMHeap, \"%s( %p, '%s', %p, %d, %p )\\n\", __FUNCTION__,\n                 shm, filename, addr_base, space, ret_size );\n\n     D_MAGIC_ASSERT( shm, FusionSHM );\n     D_MAGIC_ASSERT( shm->shared, FusionSHMShared );\n     D_ASSERT( shm->shared->tmpfs[0] != 0 );\n     D_ASSERT( filename != NULL );\n     D_ASSERT( addr_base != NULL );\n     D_ASSERT( ret_size != NULL );\n\n     size = BLOCKALIGN( sizeof(shmalloc_heap) ) + BLOCKALIGN( heapsize * sizeof(shmalloc_info) );\n\n     D_DEBUG_AT( Fusion_SHMHeap, \"  -> opening shared memory file '%s'...\\n\", filename );\n\n     /* Open the virtual file. */\n     ret = direct_file_open( &fd, filename, O_RDWR | O_CREAT | O_TRUNC, 0660 );\n     if (ret) {\n          D_DERROR( ret, \"Fusion/SHMHeap: Could not open shared memory file '%s'!\\n\", filename );\n          return ret;\n     }\n\n     if (fusion_config->shmfile_gid != -1) {\n          if (direct_file_chown( &fd, -1, fusion_config->shmfile_gid ))\n               D_WARN( \"changing owner on %s failed\", filename );\n     }\n\n     direct_file_chmod( &fd, fusion_config->secure_fusion ? 0640 : 0660 );\n\n     if (fusion_config->madv_remove)\n          ret = direct_file_truncate( &fd, size + space );\n     else\n          ret = direct_file_truncate( &fd, size );\n\n     if (ret) {\n          D_DERROR( ret, \"Fusion/SHMHeap: Could not truncate shared memory file '%s'!\\n\", filename );\n          goto error;\n     }\n\n     D_DEBUG_AT( Fusion_SHMHeap, \"  -> mapping shared memory file... (%d bytes)\\n\", size );\n\n     /* Map it shared. */\n     ret = direct_file_map( &fd, addr_base, 0, size + space, DFP_READ | DFP_WRITE, (void**) &heap );\n     if (ret) {\n          D_DERROR( ret, \"Fusion/SHMHeap: Could not mmap shared memory file '%s'!\\n\", filename );\n          goto error;\n     }\n\n     if (heap != addr_base) {\n          D_ERROR( \"Fusion/SHMHeap: The mmap returned address (%p) differs from requested (%p)!\\n\", heap, addr_base );\n          ret = DR_FUSION;\n          goto error;\n     }\n\n     direct_file_close( &fd );\n\n     D_DEBUG_AT( Fusion_SHMHeap, \"  -> done\\n\" );\n\n     heap->size     = size;\n     heap->heapsize = heapsize;\n     heap->heapinfo = (void*) heap + BLOCKALIGN( sizeof(shmalloc_heap) );\n     heap->heapbase = (char*) heap->heapinfo;\n\n     direct_snputs( heap->filename, filename, sizeof(heap->filename) );\n\n     D_MAGIC_SET( heap, shmalloc_heap );\n\n     *ret_size = size;\n\n     return DR_OK;\n\nerror:\n     if (heap)\n          direct_file_unmap( heap, size + space );\n\n     direct_file_close( &fd );\n     direct_unlink( filename );\n\n     return ret;\n}\n\nDirectResult\n__shmalloc_join_heap( FusionSHM  *shm,\n                      const char *filename,\n                      void       *addr_base,\n                      int         size,\n                      bool        write )\n{\n     DirectResult   ret;\n     DirectFile     fd;\n     shmalloc_heap *heap = NULL;\n     int            open_flags = write ? O_RDWR : O_RDONLY;\n     int            perms = DFP_READ;\n     int            heapsize   = (size + BLOCKSIZE - 1) / BLOCKSIZE;\n\n     if (write)\n          perms |= DFP_WRITE;\n\n     D_DEBUG_AT( Fusion_SHMHeap, \"%s( %p, '%s', %p, %d )\\n\", __FUNCTION__, shm, filename, addr_base, size );\n\n     D_MAGIC_ASSERT( shm, FusionSHM );\n     D_MAGIC_ASSERT( shm->shared, FusionSHMShared );\n     D_ASSERT( shm->shared->tmpfs[0] != 0 );\n     D_ASSERT( filename != NULL );\n     D_ASSERT( addr_base != NULL );\n\n     D_DEBUG_AT( Fusion_SHMHeap, \"  -> opening shared memory file '%s'...\\n\", filename );\n\n     /* Open the virtual file. */\n     ret = direct_file_open( &fd, filename, open_flags, 0 );\n     if (ret) {\n          D_DERROR( ret, \"Fusion/SHMHeap: Could not open shared memory file '%s'!\\n\", filename );\n          return ret;\n     }\n\n     size += BLOCKALIGN( sizeof(shmalloc_heap) ) + BLOCKALIGN( heapsize * sizeof(shmalloc_info) );\n\n     D_DEBUG_AT( Fusion_SHMHeap, \"  -> mapping shared memory file... (%d bytes)\\n\", size );\n\n     /* Map it shared. */\n     ret = direct_file_map( &fd, addr_base, 0, size, perms, (void**) &heap );\n     if (ret) {\n          D_DERROR( ret, \"Fusion/SHMHeap: Could not mmap shared memory file '%s'!\\n\", filename );\n          goto error;\n     }\n\n     if (heap != addr_base) {\n          D_ERROR( \"Fusion/SHMHeap: The mmap returned address (%p) differs from requested (%p)!\\n\", heap, addr_base );\n          ret = DR_FUSION;\n          goto error;\n     }\n\n     direct_file_close( &fd );\n\n     D_MAGIC_ASSERT( heap, shmalloc_heap );\n\n     D_DEBUG_AT( Fusion_SHMHeap, \"  -> done\\n\" );\n\n     return DR_OK;\n\nerror:\n     if (heap)\n          direct_file_unmap( heap, size );\n\n     direct_file_close( &fd );\n\n     return ret;\n}\n\nvoid *\n__shmalloc_brk( shmalloc_heap *heap,\n                int            increment )\n{\n     DirectResult ret;\n     DirectFile   fd;\n\n     D_DEBUG_AT( Fusion_SHMHeap, \"%s( %p, %d )\\n\", __FUNCTION__, heap, increment );\n\n     D_MAGIC_ASSERT( heap, shmalloc_heap );\n     D_MAGIC_ASSERT( heap->pool, FusionSHMPoolShared );\n\n     if (increment) {\n          int new_size = heap->size + increment;\n\n          if (new_size > heap->pool->max_size) {\n               D_WARN( \"maximum shared memory size exceeded\" );\n               fusion_print_memleaks( heap->pool );\n               return NULL;\n          }\n\n          if (!fusion_config->madv_remove) {\n               ret = direct_file_open( &fd, heap->filename, O_RDWR, 0 );\n               if (ret) {\n                    D_DERROR( ret, \"Fusion/SHMHeap: Could not open shared memory file '%s'!\\n\", heap->filename );\n                    return NULL;\n               }\n\n               ret = direct_file_truncate( &fd, new_size );\n               if (ret) {\n                    D_DERROR( ret, \"Fusion/SHMHeap: Could not truncate shared memory file '%s'!\\n\", heap->filename );\n                    return NULL;\n               }\n\n               direct_file_close( &fd );\n          }\n\n          heap->size = new_size;\n     }\n\n     return heap->pool->addr_base + heap->size - increment;\n}\n"
  },
  {
    "path": "lib/fusion/shm/pool.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/filesystem.h>\n#include <direct/mem.h>\n#include <fusion/shmalloc.h>\n#include <fusion/fusion_internal.h>\n#include <fusion/shm/pool.h>\n\n#if FUSION_BUILD_KERNEL\n#include <fusion/conf.h>\n#else /* FUSION_BUILD_KERNEL */\n#include <direct/system.h>\n#endif /* FUSION_BUILD_KERNEL */\n\nD_DEBUG_DOMAIN( Fusion_SHMPool, \"Fusion/SHMPool\", \"Fusion Shared Memory Pool\" );\n\n/**********************************************************************************************************************/\n\nstatic DirectResult init_pool    ( FusionSHM           *shm,\n                                   FusionSHMPool       *pool,\n                                   FusionSHMPoolShared *shared,\n                                   const char          *name,\n                                   unsigned int         max_size,\n                                   bool                 debug );\n\nstatic DirectResult join_pool    ( FusionSHM           *shm,\n                                   FusionSHMPool       *pool,\n                                   FusionSHMPoolShared *shared );\n\nstatic void         leave_pool   ( FusionSHM           *shm,\n                                   FusionSHMPool       *pool,\n                                   FusionSHMPoolShared *shared );\n\nstatic void         shutdown_pool( FusionSHM           *shm,\n                                   FusionSHMPool       *pool,\n                                   FusionSHMPoolShared *shared );\n\n/**********************************************************************************************************************/\n\nDirectResult\nfusion_shm_pool_create( FusionWorld          *world,\n                        const char           *name,\n                        unsigned int          max_size,\n                        bool                  debug,\n                        FusionSHMPoolShared **ret_pool )\n{\n     int           i;\n     DirectResult  ret;\n     FusionSHM    *shm;\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n     D_ASSERT( name != NULL );\n     D_ASSERT( max_size > 0 );\n     D_ASSERT( ret_pool != NULL );\n\n     D_DEBUG_AT( Fusion_SHMPool, \"%s( %p [%d], '%s', %u, %p, %sdebug )\\n\", __FUNCTION__,\n                 world, world->shared->world_index, name, max_size, ret_pool, debug ? \"\" : \"no-\" );\n\n     shm = &world->shm;\n\n     D_MAGIC_ASSERT( shm, FusionSHM );\n     D_MAGIC_ASSERT( shm->shared, FusionSHMShared );\n\n     if (max_size < 8192) {\n          D_ERROR( \"Fusion/SHMPool: Maximum size (%u) should be 8192 at least!\\n\", max_size );\n          return DR_INVARG;\n     }\n\n     ret = fusion_skirmish_prevail( &shm->shared->lock );\n     if (ret)\n          goto error;\n\n     if (shm->shared->num_pools == FUSION_SHM_MAX_POOLS) {\n          D_ERROR( \"Fusion/SHMPool: Maximum number of pools (%d) already reached!\\n\", FUSION_SHM_MAX_POOLS );\n          ret = DR_LIMITEXCEEDED;\n          goto error;\n     }\n\n     for (i = 0; i < FUSION_SHM_MAX_POOLS; i++) {\n          if (!shm->shared->pools[i].active)\n               break;\n\n          D_MAGIC_ASSERT( &shm->shared->pools[i], FusionSHMPoolShared );\n\n          D_MAGIC_ASSUME( &shm->pools[i], FusionSHMPool );\n     }\n\n     D_ASSERT( i < FUSION_SHM_MAX_POOLS );\n\n     D_DEBUG_AT( Fusion_SHMPool, \"  -> index %d\\n\", i );\n\n     memset( &shm->pools[i], 0, sizeof(FusionSHMPool) );\n     memset( &shm->shared->pools[i], 0, sizeof(FusionSHMPoolShared) );\n\n     shm->shared->pools[i].index = i;\n\n     ret = init_pool( shm, &shm->pools[i], &shm->shared->pools[i], name, max_size, debug );\n     if (ret)\n          goto error;\n\n     shm->shared->num_pools++;\n\n     fusion_skirmish_dismiss( &shm->shared->lock );\n\n     *ret_pool = &shm->shared->pools[i];\n\n     D_DEBUG_AT( Fusion_SHMPool, \"  -> %p\\n\", *ret_pool );\n\n     return DR_OK;\n\nerror:\n     fusion_skirmish_dismiss( &shm->shared->lock );\n\n     return ret;\n}\n\nDirectResult\nfusion_shm_pool_destroy( FusionWorld         *world,\n                         FusionSHMPoolShared *pool )\n{\n     DirectResult  ret;\n     FusionSHM    *shm;\n\n     D_DEBUG_AT( Fusion_SHMPool, \"%s( %p, %p )\\n\", __FUNCTION__, world, pool );\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n\n     shm = &world->shm;\n\n     D_MAGIC_ASSERT( shm, FusionSHM );\n     D_MAGIC_ASSERT( shm->shared, FusionSHMShared );\n     D_ASSERT( shm->shared == pool->shm );\n\n     ret = fusion_skirmish_prevail( &shm->shared->lock );\n     if (ret)\n          return ret;\n\n     ret = fusion_skirmish_prevail( &pool->lock );\n     if (ret) {\n          fusion_skirmish_dismiss( &shm->shared->lock );\n          return ret;\n     }\n\n     D_ASSERT( pool->active );\n     D_ASSERT( pool->index >= 0 );\n     D_ASSERT( pool->index < FUSION_SHM_MAX_POOLS );\n     D_ASSERT( pool->pool_id == shm->pools[pool->index].pool_id );\n     D_ASSERT( pool == &shm->shared->pools[pool->index] );\n     D_MAGIC_ASSERT( &shm->pools[pool->index], FusionSHMPool );\n\n     shutdown_pool( shm, &shm->pools[pool->index], pool );\n\n     shm->shared->num_pools--;\n\n     fusion_skirmish_dismiss( &shm->shared->lock );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_shm_pool_attach( FusionSHM           *shm,\n                        FusionSHMPoolShared *pool )\n{\n     D_DEBUG_AT( Fusion_SHMPool, \"%s( %p, %p )\\n\", __FUNCTION__, shm, pool );\n\n     D_MAGIC_ASSERT( shm, FusionSHM );\n     D_MAGIC_ASSERT( shm->shared, FusionSHMShared );\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( shm->shared == pool->shm );\n     D_ASSERT( pool->active );\n     D_ASSERT( pool->index >= 0 );\n     D_ASSERT( pool->index < FUSION_SHM_MAX_POOLS );\n     D_ASSERT( pool == &shm->shared->pools[pool->index] );\n     D_ASSERT( !shm->pools[pool->index].attached );\n\n     return join_pool( shm, &shm->pools[pool->index], pool );\n}\n\nDirectResult\nfusion_shm_pool_detach( FusionSHM           *shm,\n                        FusionSHMPoolShared *pool )\n{\n     D_DEBUG_AT( Fusion_SHMPool, \"%s( %p, %p )\\n\", __FUNCTION__, shm, pool );\n\n     D_MAGIC_ASSERT( shm, FusionSHM );\n     D_MAGIC_ASSERT( shm->shared, FusionSHMShared );\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( shm->shared == pool->shm );\n     D_ASSERT( pool->active );\n     D_ASSERT( pool->index >= 0 );\n     D_ASSERT( pool->index < FUSION_SHM_MAX_POOLS );\n     D_ASSERT( pool->pool_id == shm->pools[pool->index].pool_id );\n     D_ASSERT( pool == &shm->shared->pools[pool->index] );\n     D_ASSERT( shm->pools[pool->index].attached );\n     D_MAGIC_ASSERT( &shm->pools[pool->index], FusionSHMPool );\n\n     leave_pool( shm, &shm->pools[pool->index], pool );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_shm_pool_allocate( FusionSHMPoolShared  *pool,\n                          int                   size,\n                          bool                  clear,\n                          bool                  lock,\n                          void                **ret_data )\n{\n     DirectResult  ret;\n     void         *data;\n\n     D_DEBUG_AT( Fusion_SHMPool, \"%s( %p, %d, %sclear, %p )\\n\", __FUNCTION__, pool, size, clear ? \"\" : \"un\", ret_data );\n\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( size > 0 );\n     D_ASSERT( ret_data != NULL );\n\n     if (lock) {\n          ret = fusion_skirmish_prevail( &pool->lock );\n          if (ret)\n               return ret;\n     }\n\n     __shmalloc_brk( pool->heap, 0 );\n\n     data = _fusion_shmalloc( pool->heap, size );\n     if (!data) {\n          if (lock)\n               fusion_skirmish_dismiss( &pool->lock );\n          return DR_NOSHAREDMEMORY;\n     }\n\n     if (clear)\n          memset( data, 0, size );\n\n     *ret_data = data;\n\n     if (lock)\n          fusion_skirmish_dismiss( &pool->lock );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_shm_pool_reallocate( FusionSHMPoolShared  *pool,\n                            void                 *data,\n                            int                   size,\n                            bool                  lock,\n                            void                **ret_data )\n{\n     DirectResult  ret;\n     void         *new_data;\n\n     D_DEBUG_AT( Fusion_SHMPool, \"%s( %p, %p, %d, %p )\\n\", __FUNCTION__, pool, data, size, ret_data );\n\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( data != NULL );\n     D_ASSERT( data >= pool->addr_base );\n     D_ASSERT( data < pool->addr_base + pool->max_size );\n     D_ASSERT( size > 0 );\n     D_ASSERT( ret_data != NULL );\n\n     if (lock) {\n          ret = fusion_skirmish_prevail( &pool->lock );\n          if (ret)\n               return ret;\n     }\n\n     __shmalloc_brk( pool->heap, 0 );\n\n     new_data = _fusion_shrealloc( pool->heap, data, size );\n     if (!new_data) {\n          if (lock)\n               fusion_skirmish_dismiss( &pool->lock );\n          return DR_NOSHAREDMEMORY;\n     }\n\n     *ret_data = new_data;\n\n     if (lock)\n          fusion_skirmish_dismiss( &pool->lock );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_shm_pool_deallocate( FusionSHMPoolShared *pool,\n                            void                *data,\n                            bool                 lock )\n{\n     DirectResult ret;\n\n     D_DEBUG_AT( Fusion_SHMPool, \"%s( %p, %p )\\n\", __FUNCTION__, pool, data );\n\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( data != NULL );\n     D_ASSERT( data >= pool->addr_base );\n     D_ASSERT( data < pool->addr_base + pool->max_size );\n\n     if (lock) {\n          ret = fusion_skirmish_prevail( &pool->lock );\n          if (ret)\n               return ret;\n     }\n\n     __shmalloc_brk( pool->heap, 0 );\n\n     _fusion_shfree( pool->heap, data );\n\n     if (lock)\n          fusion_skirmish_dismiss( &pool->lock );\n\n     return DR_OK;\n}\n\n/**********************************************************************************************************************/\n\n#if FUSION_BUILD_KERNEL\n\nstatic DirectResult\ninit_pool( FusionSHM           *shm,\n           FusionSHMPool       *pool,\n           FusionSHMPoolShared *shared,\n           const char          *name,\n           unsigned int         max_size,\n           bool                 debug )\n{\n     DirectResult         ret;\n     int                  size;\n     FusionWorld         *world;\n     FusionSHMPoolNew     pool_new    = { .pool_id = 0 };\n     FusionSHMPoolAttach  pool_attach = { .pool_id = 0 };\n     FusionEntryInfo      info;\n     char                 buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 32];\n\n     D_DEBUG_AT( Fusion_SHMPool, \"%s( %p, %p, %p, '%s', %u, %sdebug )\\n\", __FUNCTION__,\n                 shm, pool, shared, name, max_size, debug ? \"\" : \"no-\" );\n\n     D_MAGIC_ASSERT( shm, FusionSHM );\n     D_MAGIC_ASSERT( shm->shared, FusionSHMShared );\n     D_MAGIC_ASSERT( shm->world, FusionWorld );\n     D_ASSERT( pool != NULL );\n     D_ASSERT( shared != NULL );\n     D_ASSERT( name != NULL );\n     D_ASSERT( max_size > sizeof(shmalloc_heap) );\n\n     world = shm->world;\n\n     /* Fill out information for new pool. */\n     pool_new.max_size = max_size;\n\n     pool_new.max_size += BLOCKALIGN( sizeof(shmalloc_heap) ) +\n                          BLOCKALIGN( (max_size + BLOCKSIZE - 1) / BLOCKSIZE * sizeof(shmalloc_info) );\n\n     /* Create the new pool. */\n     while (ioctl( world->fusion_fd, FUSION_SHMPOOL_NEW, &pool_new )) {\n          if (errno == EINTR)\n               continue;\n\n          D_PERROR( \"Fusion/SHMPool: FUSION_SHMPOOL_NEW\" );\n          return DR_FUSION;\n     }\n\n     /* Set the pool info. */\n     info.type = FT_SHMPOOL;\n     info.id   = pool_new.pool_id;\n\n     snprintf( info.name, sizeof(info.name), \"%s\", name );\n\n     ioctl( world->fusion_fd, FUSION_ENTRY_SET_INFO, &info );\n\n     fusion_entry_add_permissions( world, FT_SHMPOOL, pool_new.pool_id, 0,\n                                   FUSION_SHMPOOL_ATTACH,\n                                   FUSION_SHMPOOL_DETACH,\n                                   0 );\n\n     /* Set pool to attach to. */\n     pool_attach.pool_id = pool_new.pool_id;\n\n     /* Attach to the pool. */\n     while (ioctl( world->fusion_fd, FUSION_SHMPOOL_ATTACH, &pool_attach )) {\n          if (errno == EINTR)\n               continue;\n\n          D_PERROR( \"Fusion/SHMPool: FUSION_SHMPOOL_ATTACH\" );\n\n          while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DESTROY, &shared->pool_id )) {\n               if (errno != EINTR) {\n                    D_PERROR( \"Fusion/SHMPool: FUSION_SHMPOOL_DESTROY\" );\n                    break;\n               }\n          }\n\n          return DR_FUSION;\n     }\n\n     /* Generate filename. */\n     snprintf( buf, sizeof(buf), \"%s/fusion.%d.%d\",\n               shm->shared->tmpfs, fusion_world_index( shm->world ), pool_new.pool_id );\n\n     /* Initialize the heap. */\n     ret = __shmalloc_init_heap( shm, buf, pool_new.addr_base, max_size, &size );\n     if (ret) {\n          while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DESTROY, &shared->pool_id )) {\n               if (errno != EINTR) {\n                    D_PERROR( \"Fusion/SHMPool: FUSION_SHMPOOL_DESTROY\" );\n                    break;\n               }\n          }\n\n          return ret;\n     }\n\n     /* Initialize local data. */\n     pool->attached = true;\n     pool->shm      = shm;\n     pool->shared   = shared;\n     pool->pool_id  = pool_new.pool_id;\n     pool->filename = D_STRDUP( buf );\n\n     /* Initialize shared data. */\n     shared->active     = true;\n     shared->debug      = debug;\n     shared->shm        = shm->shared;\n     shared->max_size   = pool_new.max_size;\n     shared->pool_id    = pool_new.pool_id;\n     shared->addr_base  = pool_new.addr_base;\n     shared->heap       = pool_new.addr_base;\n     shared->heap->pool = shared;\n\n     fusion_skirmish_init2( &shared->lock, name, world, fusion_config->secure_fusion );\n\n     D_MAGIC_SET( pool, FusionSHMPool );\n     D_MAGIC_SET( shared, FusionSHMPoolShared );\n\n     shared->name = SHSTRDUP( shared, name );\n\n     return DR_OK;\n}\n\nstatic DirectResult\njoin_pool( FusionSHM           *shm,\n           FusionSHMPool       *pool,\n           FusionSHMPoolShared *shared )\n{\n     DirectResult         ret;\n     FusionWorld         *world;\n     FusionSHMPoolAttach  pool_attach = { .pool_id = 0 };\n     char                 buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 32];\n\n     D_DEBUG_AT( Fusion_SHMPool, \"%s( %p, %p, %p )\\n\", __FUNCTION__, shm, pool, shared );\n\n     D_MAGIC_ASSERT( shm, FusionSHM );\n     D_MAGIC_ASSERT( shm->shared, FusionSHMShared );\n     D_MAGIC_ASSERT( shm->world, FusionWorld );\n     D_MAGIC_ASSERT( shared, FusionSHMPoolShared );\n\n     world = shm->world;\n\n     /* Set pool to attach to. */\n     pool_attach.pool_id = shared->pool_id;\n\n     /* Attach to the pool. */\n     while (ioctl( world->fusion_fd, FUSION_SHMPOOL_ATTACH, &pool_attach )) {\n          if (errno == EINTR)\n               continue;\n\n          D_PERROR( \"Fusion/SHMPool: FUSION_SHMPOOL_ATTACH\" );\n          return DR_FUSION;\n     }\n\n     /* Generate filename. */\n     snprintf( buf, sizeof(buf), \"%s/fusion.%d.%d\",\n               shm->shared->tmpfs, fusion_world_index( shm->world ), shared->pool_id );\n\n     /* Join the heap. */\n     ret = __shmalloc_join_heap( shm, buf, pool_attach.addr_base, shared->max_size, !fusion_config->secure_fusion );\n     if (ret) {\n          while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DETACH, &shared->pool_id )) {\n               if (errno != EINTR) {\n                    D_PERROR( \"Fusion/SHMPool: FUSION_SHMPOOL_DETACH\" );\n                    break;\n               }\n          }\n\n          return ret;\n     }\n\n     /* Initialize local data. */\n     pool->attached = true;\n     pool->shm      = shm;\n     pool->shared   = shared;\n     pool->pool_id  = shared->pool_id;\n     pool->filename = D_STRDUP( buf );\n\n     D_MAGIC_SET( pool, FusionSHMPool );\n\n     return DR_OK;\n}\n\nstatic void\nleave_pool( FusionSHM           *shm,\n            FusionSHMPool       *pool,\n            FusionSHMPoolShared *shared )\n{\n     FusionWorld *world;\n\n     D_DEBUG_AT( Fusion_SHMPool, \"%s( %p, %p, %p )\\n\", __FUNCTION__, shm, pool, shared );\n\n     D_MAGIC_ASSERT( shm, FusionSHM );\n     D_MAGIC_ASSERT( shm->world, FusionWorld );\n     D_MAGIC_ASSERT( pool, FusionSHMPool );\n     D_MAGIC_ASSERT( shared, FusionSHMPoolShared );\n\n     world = shm->world;\n\n     while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DETACH, &shared->pool_id )) {\n          if (errno != EINTR) {\n               D_PERROR( \"Fusion/SHMPool: FUSION_SHMPOOL_DETACH\" );\n               break;\n          }\n     }\n\n     if (direct_file_unmap( shared->addr_base, shared->max_size ))\n          D_ERROR( \"Fusion/SHMPool: Could not unmap shared memory file '%s'!\\n\", pool->filename );\n\n     pool->attached = false;\n\n     D_FREE( pool->filename );\n\n     D_MAGIC_CLEAR( pool );\n}\n\nstatic void\nshutdown_pool( FusionSHM           *shm,\n               FusionSHMPool       *pool,\n               FusionSHMPoolShared *shared )\n{\n     FusionWorld *world;\n\n     D_DEBUG_AT( Fusion_SHMPool, \"%s( %p, %p, %p )\\n\", __FUNCTION__, shm, pool, shared );\n\n     D_MAGIC_ASSERT( shm, FusionSHM );\n     D_MAGIC_ASSERT( shm->world, FusionWorld );\n     D_MAGIC_ASSERT( pool, FusionSHMPool );\n     D_MAGIC_ASSERT( shared, FusionSHMPoolShared );\n\n     world = shm->world;\n\n     SHFREE( shared, shared->name );\n\n     fusion_print_memleaks( shared );\n\n     while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DESTROY, &shared->pool_id )) {\n          if (errno != EINTR) {\n               D_PERROR( \"Fusion/SHMPool: FUSION_SHMPOOL_DESTROY\" );\n               break;\n          }\n     }\n\n     if (direct_file_unmap( shared->addr_base, shared->max_size ))\n          D_ERROR( \"Fusion/SHMPool: Could not unmap shared memory file '%s'!\\n\", pool->filename );\n\n     if (direct_unlink( pool->filename ))\n          D_ERROR( \"Fusion/SHMPool: Could not unlink shared memory file '%s'!\\n\", pool->filename );\n\n     shared->active = false;\n\n     pool->attached = false;\n\n     D_FREE( pool->filename );\n\n     D_MAGIC_CLEAR( pool );\n\n     fusion_skirmish_destroy( &shared->lock );\n\n     D_MAGIC_CLEAR( shared );\n}\n\nvoid\n_fusion_shmpool_process( FusionWorld          *world,\n                         int                   pool_id,\n                         FusionSHMPoolMessage *msg )\n{\n     int           i;\n     DirectResult  ret;\n     FusionSHM    *shm;\n\n     D_DEBUG_AT( Fusion_SHMPool, \"%s( %p, %d, %p )\\n\", __FUNCTION__, world, pool_id, msg );\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     shm = &world->shm;\n\n     D_MAGIC_ASSERT( shm, FusionSHM );\n     D_MAGIC_ASSERT( shm->shared, FusionSHMShared );\n\n     ret = fusion_skirmish_prevail( &shm->shared->lock );\n     if (ret)\n          return;\n\n     for (i = 0; i < FUSION_SHM_MAX_POOLS; i++) {\n          if (shm->pools[i].attached) {\n               D_MAGIC_ASSERT( &shm->pools[i], FusionSHMPool );\n\n               if (shm->pools[i].pool_id == pool_id) {\n                    switch (msg->type) {\n                         case FSMT_REMAP:\n                              break;\n\n                         case FSMT_UNMAP:\n                              D_UNIMPLEMENTED();\n                              break;\n                    }\n\n                    break;\n               }\n          }\n     }\n\n     fusion_skirmish_dismiss( &shm->shared->lock );\n}\n\n#else /* FUSION_BUILD_KERNEL */\n\nstatic DirectResult\ninit_pool( FusionSHM           *shm,\n           FusionSHMPool       *pool,\n           FusionSHMPoolShared *shared,\n           const char          *name,\n           unsigned int         max_size,\n           bool                 debug )\n{\n     DirectResult  ret;\n     int           size;\n     long          page_size;\n     int           pool_id;\n     unsigned int  pool_max_size;\n     void         *pool_addr_base = NULL;\n     FusionWorld  *world;\n     char          buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 32];\n\n     D_DEBUG_AT( Fusion_SHMPool, \"%s( %p, %p, %p, '%s', %u, %sdebug )\\n\", __FUNCTION__,\n                 shm, pool, shared, name, max_size, debug ? \"\" : \"non-\" );\n\n     D_MAGIC_ASSERT( shm, FusionSHM );\n     D_MAGIC_ASSERT( shm->shared, FusionSHMShared );\n     D_MAGIC_ASSERT( shm->world, FusionWorld );\n     D_ASSERT( pool != NULL );\n     D_ASSERT( shared != NULL );\n     D_ASSERT( name != NULL );\n     D_ASSERT( max_size > sizeof(shmalloc_heap) );\n\n     world = shm->world;\n\n     page_size = direct_pagesize();\n\n     pool_id = ++world->shared->pool_ids;\n\n     pool_max_size = max_size + BLOCKALIGN( sizeof(shmalloc_heap) ) +\n                                BLOCKALIGN( (max_size + BLOCKSIZE - 1) / BLOCKSIZE * sizeof(shmalloc_info) );\n\n     pool_addr_base = world->shared->pool_base;\n     world->shared->pool_base += ((pool_max_size + page_size - 1) & ~(page_size - 1)) + page_size;\n     if (world->shared->pool_base > world->shared->pool_max)\n          return DR_NOSHAREDMEMORY;\n\n     /* Generate filename. */\n     snprintf( buf, sizeof(buf), \"%s/fusion.%d.%d\", shm->shared->tmpfs, fusion_world_index( world ), pool_id );\n\n     /* Initialize the heap. */\n     ret = __shmalloc_init_heap( shm, buf, pool_addr_base, max_size, &size );\n     if (ret)\n          return ret;\n\n     /* initialize local data. */\n     pool->attached = true;\n     pool->shm      = shm;\n     pool->shared   = shared;\n     pool->pool_id  = pool_id;\n     pool->filename = D_STRDUP( buf );\n\n     /* Initialize shared data. */\n     shared->active     = true;\n     shared->debug      = debug;\n     shared->shm        = shm->shared;\n     shared->max_size   = pool_max_size;\n     shared->pool_id    = pool_id;\n     shared->addr_base  = pool_addr_base;\n     shared->heap       = pool_addr_base;\n     shared->heap->pool = shared;\n\n     fusion_skirmish_init( &shared->lock, name, world );\n\n     D_MAGIC_SET( pool, FusionSHMPool );\n     D_MAGIC_SET( shared, FusionSHMPoolShared );\n\n     shared->name = SHSTRDUP( shared, name );\n\n     return DR_OK;\n}\n\nstatic DirectResult\njoin_pool( FusionSHM           *shm,\n           FusionSHMPool       *pool,\n           FusionSHMPoolShared *shared )\n{\n     DirectResult  ret;\n     FusionWorld  *world;\n     char          buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 32];\n\n     D_DEBUG_AT( Fusion_SHMPool, \"%s( %p, %p, %p )\\n\", __FUNCTION__, shm, pool, shared );\n\n     D_MAGIC_ASSERT( shm, FusionSHM );\n     D_MAGIC_ASSERT( shm->shared, FusionSHMShared );\n     D_MAGIC_ASSERT( shm->world, FusionWorld );\n     D_MAGIC_ASSERT( shared, FusionSHMPoolShared );\n\n     world = shm->world;\n\n     /* Generate filename. */\n     snprintf( buf, sizeof(buf), \"%s/fusion.%d.%d\", shm->shared->tmpfs, fusion_world_index( world ), shared->pool_id );\n\n     /* Join the heap. */\n     ret = __shmalloc_join_heap( shm, buf, shared->addr_base, shared->max_size, true );\n     if (ret)\n          return ret;\n\n     /* Initialize local data. */\n     pool->attached = true;\n     pool->shm      = shm;\n     pool->shared   = shared;\n     pool->pool_id  = shared->pool_id;\n     pool->filename = D_STRDUP( buf );\n\n     D_MAGIC_SET( pool, FusionSHMPool );\n\n     return DR_OK;\n}\n\nstatic void\nleave_pool( FusionSHM           *shm,\n            FusionSHMPool       *pool,\n            FusionSHMPoolShared *shared )\n{\n     D_DEBUG_AT( Fusion_SHMPool, \"%s( %p, %p, %p )\\n\", __FUNCTION__, shm, pool, shared );\n\n     D_MAGIC_ASSERT( shm, FusionSHM );\n     D_MAGIC_ASSERT( shm->world, FusionWorld );\n     D_MAGIC_ASSERT( pool, FusionSHMPool );\n     D_MAGIC_ASSERT( shared, FusionSHMPoolShared );\n\n     if (direct_file_unmap( shared->addr_base, shared->max_size ))\n          D_ERROR( \"Fusion/SHMPool: Could not unmap shared memory file '%s'!\\n\", pool->filename );\n\n     pool->attached = false;\n\n     D_FREE( pool->filename );\n\n     D_MAGIC_CLEAR( pool );\n}\n\nstatic void\nshutdown_pool( FusionSHM           *shm,\n               FusionSHMPool       *pool,\n               FusionSHMPoolShared *shared )\n{\n     D_DEBUG_AT( Fusion_SHMPool, \"%s( %p, %p, %p )\\n\", __FUNCTION__, shm, pool, shared );\n\n     D_MAGIC_ASSERT( shm, FusionSHM );\n     D_MAGIC_ASSERT( shm->world, FusionWorld );\n     D_MAGIC_ASSERT( pool, FusionSHMPool );\n     D_MAGIC_ASSERT( shared, FusionSHMPoolShared );\n\n     SHFREE( shared, shared->name );\n\n     fusion_print_memleaks( shared );\n\n     if (direct_file_unmap( shared->addr_base, shared->max_size ))\n          D_ERROR( \"Fusion/SHMPool: Could not unmap shared memory file '%s'!\\n\", pool->filename );\n\n     if (direct_unlink( pool->filename ))\n          D_ERROR( \"Fusion/SHMPool: Could not unlink shared memory file '%s'!\\n\", pool->filename );\n\n     shared->active = false;\n\n     pool->attached = false;\n\n     D_FREE( pool->filename );\n\n     D_MAGIC_CLEAR( pool );\n\n     fusion_skirmish_destroy( &shared->lock );\n\n     D_MAGIC_CLEAR( shared );\n}\n\n#endif /* FUSION_BUILD_KERNEL */\n"
  },
  {
    "path": "lib/fusion/shm/pool.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FUSION__SHM__POOL_H__\n#define __FUSION__SHM__POOL_H__\n\n#include <fusion/types.h>\n\n/**********************************************************************************************************************/\n\nDirectResult fusion_shm_pool_create    ( FusionWorld          *world,\n                                         const char           *name,\n                                         unsigned int          max_size,\n                                         bool                  debug,\n                                         FusionSHMPoolShared **ret_pool );\n\nDirectResult fusion_shm_pool_destroy   ( FusionWorld          *world,\n                                         FusionSHMPoolShared  *pool );\n\nDirectResult fusion_shm_pool_attach    ( FusionSHM            *shm,\n                                         FusionSHMPoolShared  *pool );\n\nDirectResult fusion_shm_pool_detach    ( FusionSHM            *shm,\n                                         FusionSHMPoolShared  *pool );\n\nDirectResult fusion_shm_pool_allocate  ( FusionSHMPoolShared  *pool,\n                                         int                   size,\n                                         bool                  clear,\n                                         bool                  lock,\n                                         void                **ret_data );\n\nDirectResult fusion_shm_pool_reallocate( FusionSHMPoolShared  *pool,\n                                         void                 *data,\n                                         int                   size,\n                                         bool                  lock,\n                                         void                **ret_data );\n\nDirectResult fusion_shm_pool_deallocate( FusionSHMPoolShared  *pool,\n                                         void                 *data,\n                                         bool                  lock );\n\n#endif\n"
  },
  {
    "path": "lib/fusion/shm/shm.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/filesystem.h>\n#include <fusion/conf.h>\n#include <fusion/fusion_internal.h>\n#include <fusion/shm/pool.h>\n#include <fusion/shm/shm.h>\n\nD_DEBUG_DOMAIN( Fusion_SHMInit, \"Fusion/SHMInit\", \"Fusion Shared Memory Init\" );\n\n/**********************************************************************************************************************/\n\nint\nfusion_find_tmpfs( char *name,\n                   int   len )\n{\n     int        largest = 0;\n     char       buffer[1024];\n     DirectFile mounts_handle;\n\n     if (direct_file_open( &mounts_handle, \"/proc/mounts\", O_RDONLY, 0 ))\n          return 0;\n\n     while (!direct_file_get_string( &mounts_handle, buffer, sizeof(buffer) )) {\n          char *mount_point;\n          char *mount_fs;\n          char *pointer = buffer;\n\n          strsep( &pointer, \" \" );\n\n          mount_point = strsep( &pointer, \" \" );\n          mount_fs = strsep( &pointer, \" \" );\n\n          if (mount_fs && mount_point && (direct_access( mount_point, W_OK ) == DR_OK) &&\n             (!strcmp( mount_fs, \"tmpfs\" ) || !strcmp( mount_fs, \"shmfs\" ) || !strcmp( mount_fs, \"ramfs\" ))) {\n               size_t size;\n\n               if (direct_filesystem_size( mount_point, &size )) {\n                    D_ERROR( \"Fusion/SHMInit: Failed to get filesystem size on '%s'!\\n\", mount_point );\n                    continue;\n               }\n\n               if (size > largest || (size == largest && !strcmp( mount_point, \"/dev/shm\" ))) {\n                    largest = size;\n\n                    direct_snputs( name, mount_point, len );\n               }\n          }\n     }\n\n     direct_file_close( &mounts_handle );\n\n     D_DEBUG_AT( Fusion_SHMInit, \"%s( %s )\\n\", __FUNCTION__, name );\n\n     return largest;\n}\n\nDirectResult\nfusion_shm_init( FusionWorld *world )\n{\n     int           i;\n     int           num;\n     DirectResult  ret;\n     FusionSHM    *shm;\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n\n     D_DEBUG_AT( Fusion_SHMInit, \"%s( %p )\\n\", __FUNCTION__, world );\n\n     shm = &world->shm;\n\n     /* Initialize local data. */\n     memset( shm, 0, sizeof(FusionSHM) );\n\n     shm->world  = world;\n     shm->shared = &world->shared->shm;\n\n     /* Initialize shared data. */\n     if (fusion_master( world )) {\n          memset( shm->shared, 0, sizeof(FusionSHMShared) );\n\n          if (fusion_config->tmpfs) {\n               direct_snputs( shm->shared->tmpfs, fusion_config->tmpfs, FUSION_SHM_TMPFS_PATH_NAME_LEN );\n          }\n          else if (!fusion_find_tmpfs( shm->shared->tmpfs, FUSION_SHM_TMPFS_PATH_NAME_LEN )) {\n               D_ERROR( \"Fusion/SHMInit: Could not find tmpfs mount point, falling back to /dev/shm!\\n\" );\n               snprintf( shm->shared->tmpfs, FUSION_SHM_TMPFS_PATH_NAME_LEN, \"/dev/shm\" );\n          }\n\n          shm->shared->world = world->shared;\n\n          /* Initialize shared lock. */\n          ret = fusion_skirmish_init2( &shm->shared->lock, \"Fusion SHM\", world, fusion_config->secure_fusion );\n          if (ret) {\n               D_DERROR( ret, \"Fusion/SHMInit: Failed to create skirmish!\\n\" );\n               return ret;\n          }\n\n          /* Initialize static pool array. */\n          for (i = 0; i < FUSION_SHM_MAX_POOLS; i++)\n               shm->shared->pools[i].index = i;\n\n          D_MAGIC_SET( shm, FusionSHM );\n          D_MAGIC_SET( shm->shared, FusionSHMShared );\n     }\n     else {\n          D_MAGIC_ASSERT( shm->shared, FusionSHMShared );\n\n          D_MAGIC_SET( shm, FusionSHM );\n\n          for (i = 0, num = 0; i < FUSION_SHM_MAX_POOLS; i++) {\n               if (shm->shared->pools[i].active) {\n                    D_MAGIC_ASSERT( &shm->shared->pools[i], FusionSHMPoolShared );\n\n                    ret = fusion_shm_pool_attach( shm, &shm->shared->pools[i] );\n                    if (ret) {\n                         for (--i; i >= 0; i--) {\n                              if (shm->shared->pools[i].active)\n                                   fusion_shm_pool_detach( shm, &shm->shared->pools[i] );\n                         }\n\n                         D_MAGIC_CLEAR( shm );\n\n                         return ret;\n                    }\n\n                    num++;\n               }\n          }\n\n          D_ASSERT( num == shm->shared->num_pools );\n     }\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_shm_deinit( FusionWorld *world )\n{\n     int           i;\n     DirectResult  ret;\n     FusionSHM    *shm;\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n\n     D_DEBUG_AT( Fusion_SHMInit, \"%s( %p )\\n\", __FUNCTION__, world );\n\n     shm = &world->shm;\n\n     D_MAGIC_ASSERT( shm, FusionSHM );\n     D_MAGIC_ASSERT( shm->shared, FusionSHMShared );\n\n     /* Deinitialize shared data. */\n     if (fusion_master( world )) {\n          ret = fusion_skirmish_prevail( &shm->shared->lock );\n          if (ret)\n               return ret;\n\n          D_ASSUME( shm->shared->num_pools == 0 );\n\n          for (i = 0; i < FUSION_SHM_MAX_POOLS; i++) {\n               if (shm->shared->pools[i].active) {\n                    D_MAGIC_ASSERT( &shm->shared->pools[i], FusionSHMPoolShared );\n                    D_MAGIC_ASSERT( &shm->pools[i], FusionSHMPool );\n\n                    D_WARN( \"destroying remaining '%s'\", shm->shared->pools[i].name );\n\n                    fusion_shm_pool_destroy( world, &shm->shared->pools[i] );\n               }\n          }\n\n          /* Destroy shared lock. */\n          fusion_skirmish_destroy( &shm->shared->lock );\n\n          D_MAGIC_CLEAR( shm->shared );\n     }\n     else {\n          for (i = 0; i < FUSION_SHM_MAX_POOLS; i++) {\n               if (shm->shared->pools[i].active) {\n                    D_MAGIC_ASSERT( &shm->shared->pools[i], FusionSHMPoolShared );\n                    D_MAGIC_ASSERT( &shm->pools[i], FusionSHMPool );\n\n                    fusion_shm_pool_detach( shm, &shm->shared->pools[i] );\n               }\n          }\n     }\n\n     D_MAGIC_CLEAR( shm );\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_shm_enum_pools( FusionWorld           *world,\n                       FusionSHMPoolCallback  callback,\n                       void                  *ctx )\n{\n     int        i;\n     FusionSHM *shm;\n\n     D_MAGIC_ASSERT( world, FusionWorld );\n     D_MAGIC_ASSERT( world->shared, FusionWorldShared );\n     D_ASSERT( callback != NULL );\n\n     shm = &world->shm;\n\n     D_MAGIC_ASSERT( shm, FusionSHM );\n     D_MAGIC_ASSERT( shm->shared, FusionSHMShared );\n\n     for (i = 0; i < FUSION_SHM_MAX_POOLS; i++) {\n          if (!shm->shared->pools[i].active)\n               continue;\n\n          if (!shm->pools[i].attached) {\n               D_BUG( \"not attached to pool\" );\n               continue;\n          }\n\n          D_MAGIC_ASSERT( &shm->pools[i], FusionSHMPool );\n          D_MAGIC_ASSERT( &shm->shared->pools[i], FusionSHMPoolShared );\n\n          if (callback( &shm->pools[i], ctx ) == DENUM_CANCEL)\n               break;\n     }\n\n     return DR_OK;\n}\n"
  },
  {
    "path": "lib/fusion/shm/shm.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FUSION__SHM__SHM_H__\n#define __FUSION__SHM__SHM_H__\n\n#include <fusion/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef DirectEnumerationResult (*FusionSHMPoolCallback)( FusionSHMPool *pool, void *ctx );\n\n/**********************************************************************************************************************/\n\nint          fusion_find_tmpfs    ( char                  *name,\n                                    int                    len );\n\nDirectResult fusion_shm_init      ( FusionWorld           *world );\n\nDirectResult fusion_shm_deinit    ( FusionWorld           *world );\n\nDirectResult fusion_shm_enum_pools( FusionWorld           *world,\n                                    FusionSHMPoolCallback  callback,\n                                    void                  *ctx );\n\n#endif\n"
  },
  {
    "path": "lib/fusion/shm/shm_internal.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FUSION__SHM__SHM_INTERNAL_H__\n#define __FUSION__SHM__SHM_INTERNAL_H__\n\n#include <direct/list.h>\n#include <fusion/lock.h>\n\n/**********************************************************************************************************************/\n\n#define FUSION_SHM_MAX_POOLS 16\n\n/*\n * The allocator divides the heap into blocks of fixed size.\n * Large requests receive one or more whole blocks, and small requests receive a fragment of a block.\n * Fragment sizes are powers of two, and all fragments of a block are the same size.\n * When all the fragments in a block have been freed, the block itself is freed.\n */\n#define BLOCKLOG 12\n\n/* Data structure giving per-block information. */\ntypedef union {\n     /* Heap information for a busy block. */\n     struct {\n          /* Zero for a large block, or positive giving the logarithm to the base two of the fragment size. */\n          int type;\n\n          union {\n               struct {\n                    size_t nfree; /* Free fragments in a fragmented block. */\n                    size_t first; /* First free fragment of the block. */\n               } frag;\n\n               /* Size (in blocks) of a large cluster. */\n               size_t size;\n          } info;\n     } busy;\n\n     /* Heap information for a free block. */\n     struct {\n          size_t size;            /* Size (in blocks) of a free cluster. */\n          size_t next;            /* Index of next free cluster. */\n          size_t prev;            /* Index of previous free cluster. */\n     } free;\n} shmalloc_info;\n\n/* Doubly linked lists of free fragments. */\nstruct list {\n     struct list *next;\n     struct list *prev;\n};\n\ntypedef struct {\n     int magic;\n\n     /* Pointer to first block of the heap. */\n     char *heapbase;\n\n     /* Block information table indexed by block number giving per-block information. */\n     shmalloc_info *heapinfo;\n\n     /* Number of info entries. */\n     size_t heapsize;\n\n     /* Current search index for the heap table. */\n     size_t heapindex;\n\n     /* Limit of valid info table indices. */\n     size_t heaplimit;\n\n     /* Count of large blocks allocated for each fragment size. */\n     int fragblocks[BLOCKLOG];\n\n     /* Free list headers for each fragment size. */\n     struct list fraghead[BLOCKLOG];\n\n     /* Instrumentation. */\n     size_t chunks_used;\n     size_t bytes_used;\n     size_t chunks_free;\n     size_t bytes_free;\n\n     /* Total size of heap in bytes. */\n     int size;\n\n     /* Back pointer to shared memory pool. */\n     FusionSHMPoolShared *pool;\n\n     /* Name of the shared memory file. */\n     char filename[FUSION_SHM_TMPFS_PATH_NAME_LEN+32];\n} shmalloc_heap;\n\n/*\n * Local pool data.\n */\nstruct __Fusion_FusionSHMPool {\n     int                  magic;\n\n     bool                 attached; /* Indicates usage of this entry in the static pool array. */\n\n     FusionSHM           *shm;      /* Back pointer to local SHM data. */\n\n     FusionSHMPoolShared *shared;   /* Pointer to shared pool data. */\n\n     int                  pool_id;  /* The pool's ID within the world. */\n\n     char                *filename; /* Name of the shared memory file. */\n};\n\n/*\n * Shared pool data.\n */\nstruct __Fusion_FusionSHMPoolShared {\n     int                  magic;\n\n     bool                 debug;     /* Debug allocations in this pool. */\n\n     int                  index;     /* Index within the static pool array. */\n     bool                 active;    /* Indicates usage of this entry in the static pool array. */\n\n     FusionSHMShared     *shm;       /* Back pointer to shared SHM data. */\n\n     int                  max_size;  /* Maximum possible size of the shared memory. */\n     int                  pool_id;   /* The pool's ID within the world. */\n     void                *addr_base; /* Virtual starting address of shared memory. */\n\n     FusionSkirmish       lock;      /* Lock for this pool. */\n\n     shmalloc_heap       *heap;      /* The actual heap information. */\n\n     char                *name;      /* Name of the pool (allocated in the pool). */\n\n     DirectLink          *allocs;    /* Used for debugging. */\n};\n\n/*\n * Local SHM data.\n */\nstruct __Fusion_FusionSHM {\n     int                  magic;\n\n     FusionWorld         *world;                       /* Back pointer to local world data. */\n\n     FusionSHMShared     *shared;                      /* Pointer to shared SHM data. */\n\n     FusionSHMPool        pools[FUSION_SHM_MAX_POOLS]; /* Local data of all pools. */\n};\n\n/*\n * Shared SHM data.\n */\nstruct __Fusion_FusionSHMShared {\n     int                  magic;\n\n     FusionWorldShared   *world;                                 /* Back pointer to shared world data. */\n\n     FusionSkirmish       lock;                                  /* Lock for list of pools. */\n\n     int                  num_pools;                             /* Number of active pools. */\n     FusionSHMPoolShared  pools[FUSION_SHM_MAX_POOLS];           /* Shared data of all pools. */\n\n     char                 tmpfs[FUSION_SHM_TMPFS_PATH_NAME_LEN]; /* Location of shared memory file. */\n};\n\n/**********************************************************************************************************************/\n\n#define BLOCKSIZE        (1 << BLOCKLOG)\n#define BLOCKIFY(SIZE)   (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)\n#define BLOCKALIGN(SIZE) (((SIZE) + BLOCKSIZE - 1) & ~(BLOCKSIZE - 1))\n\n#define SHMEMDESC_FUNC_NAME_LENGTH 48\n#define SHMEMDESC_FILE_NAME_LENGTH 24\n\ntypedef struct {\n     DirectLink    link;\n\n     const void   *mem;\n     size_t        bytes;\n     char          func[SHMEMDESC_FUNC_NAME_LENGTH];\n     char          file[SHMEMDESC_FILE_NAME_LENGTH];\n     unsigned int  line;\n\n     FusionID      fid;\n} SHMemDesc;\n\n/**********************************************************************************************************************/\n\n/*\n * Allocate memory from the heap.\n */\nvoid *_fusion_shmalloc ( shmalloc_heap *heap,\n                         size_t         size );\n\n/*\n * Resize the given region to the new size, returning a pointer to the (possibly moved) region.\n */\nvoid *_fusion_shrealloc( shmalloc_heap *heap,\n                         void          *ptr,\n                         size_t         size );\n\n/*\n * Return memory to the heap.\n */\nvoid  _fusion_shfree   ( shmalloc_heap *heap,\n                         void          *ptr );\n\n/**********************************************************************************************************************/\n\nDirectResult  __shmalloc_init_heap( FusionSHM     *shm,\n                                    const char    *filename,\n                                    void          *addr_base,\n                                    int            space,\n                                    int           *ret_size );\n\nDirectResult  __shmalloc_join_heap( FusionSHM     *shm,\n                                    const char    *filename,\n                                    void          *addr_base,\n                                    int            size,\n                                    bool           write );\n\nvoid         *__shmalloc_brk      ( shmalloc_heap *heap,\n                                    int            increment );\n\n#endif\n"
  },
  {
    "path": "lib/fusion/shmalloc.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <fusion/shmalloc.h>\n\n#if FUSION_BUILD_MULTI\n\n#include <direct/memcpy.h>\n#include <direct/system.h>\n#include <direct/log.h>\n#include <fusion/conf.h>\n#include <fusion/fusion_internal.h>\n#include <fusion/shm/pool.h>\n\n#else /* FUSION_BUILD_MULTI */\n\n#include <direct/mem.h>\n#include <fusion/shm/shm_internal.h>\n\n#endif /* FUSION_BUILD_MULTI */\n\n#if DIRECT_BUILD_DEBUGS\n\nD_DEBUG_DOMAIN( Fusion_SHM, \"Fusion/SHM\", \"Fusion Shared Memory allocation\" );\n\n#endif /* DIRECT_BUILD_DEBUGS */\n\n/**********************************************************************************************************************/\n\n#if FUSION_BUILD_MULTI\n\nvoid\nfusion_print_madvise()\n{\n     if (fusion_config->madv_remove_force) {\n          if (fusion_config->madv_remove)\n               D_INFO( \"Fusion/SHM: Using MADV_REMOVE (forced)\\n\" );\n          else\n               D_INFO( \"Fusion/SHM: Not using MADV_REMOVE (forced)!\\n\" );\n     }\n     else {\n          if (direct_madvise())\n               D_INFO( \"Fusion/SHM: Using MADV_REMOVE\\n\" );\n          else\n               D_INFO( \"Fusion/SHM: NOT using MADV_REMOVE!\\n\" );\n     }\n}\n\n#endif /* FUSION_BUILD_MULTI */\n\n#if DIRECT_BUILD_DEBUGS\n\n#if FUSION_BUILD_MULTI\n\nvoid\nfusion_print_memleaks( FusionSHMPoolShared *pool )\n{\n     DirectResult  ret;\n     SHMemDesc    *desc;\n     unsigned int  total = 0;\n\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n\n     ret = fusion_skirmish_prevail( &pool->lock );\n     if (ret) {\n          D_DERROR( ret, \"Fusion/SHM: Could not lock shared memory pool!\\n\" );\n          return;\n     }\n\n     if (pool->allocs) {\n          direct_log_printf( NULL, \"\\nShared memory allocations remaining (%d) in '%s': \\n\",\n                             direct_list_count_elements_EXPENSIVE( pool->allocs ), pool->name );\n\n          direct_list_foreach (desc, pool->allocs) {\n               direct_log_printf( NULL, \" \"_ZUn(9)\" bytes at %p [%8lu] in %-30s [%3lx] (%s: %u)\\n\",\n                                  desc->bytes, desc->mem, (unsigned long) desc->mem - (unsigned long) pool->heap,\n                                  desc->func, desc->fid, desc->file, desc->line );\n\n               total += desc->bytes;\n          }\n\n          direct_log_printf( NULL, \"   -------\\n  %7uk total\\n\", total >> 10 );\n          direct_log_printf( NULL, \"\\nShared memory file size: %dk\\n\", pool->heap->size >> 10 );\n     }\n\n     fusion_skirmish_dismiss( &pool->lock );\n}\n\nstatic SHMemDesc *\nfill_shmem_desc( SHMemDesc  *desc,\n                 int         bytes,\n                 const char *func,\n                 const char *file,\n                 int         line,\n                 FusionID    fusion_id )\n{\n     D_ASSERT( desc != NULL );\n\n     desc->mem   = desc + 1;\n     desc->bytes = bytes;\n\n     direct_snputs( desc->func, func, SHMEMDESC_FUNC_NAME_LENGTH );\n     direct_snputs( desc->file, file, SHMEMDESC_FILE_NAME_LENGTH );\n\n     desc->line = line;\n     desc->fid  = fusion_id;\n\n     return desc;\n}\n\nvoid *\nfusion_dbg_shmalloc( FusionSHMPoolShared *pool,\n                     const char          *file,\n                     int                  line,\n                     const char          *func,\n                     size_t               size )\n{\n     DirectResult  ret;\n     SHMemDesc    *desc;\n     void         *data = NULL;\n\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( file != NULL );\n     D_ASSERT( line > 0 );\n     D_ASSERT( func != NULL );\n     D_ASSERT( size > 0 );\n\n     if (!pool->debug)\n          return fusion_shmalloc( pool, size );\n\n     /* Lock the pool. */\n     ret = fusion_skirmish_prevail( &pool->lock );\n     if (ret) {\n          D_DERROR( ret, \"Fusion/SHM: Could not lock shared memory pool!\\n\" );\n          return NULL;\n     }\n\n     /* Allocate memory from the pool. */\n     ret = fusion_shm_pool_allocate( pool, size + sizeof(SHMemDesc), false, false, &data );\n     if (ret) {\n          D_DERROR( ret, \"Fusion/SHM: Could not allocate \"_ZU\" bytes from pool!\\n\", size + sizeof(SHMemDesc) );\n          fusion_skirmish_dismiss( &pool->lock );\n          return NULL;\n     }\n\n     /* Fill description. */\n     desc = fill_shmem_desc( data, size, func, file, line, _fusion_id( pool->shm->world ) );\n\n     D_DEBUG_AT( Fusion_SHM, \"Allocating \"_ZUn(9)\" bytes at %p [%8lu] in %-30s [%3lx] (%s: %u)\\n\",\n                 desc->bytes, desc->mem, (unsigned long) desc->mem - (unsigned long) pool->heap,\n                 desc->func, desc->fid, desc->file, desc->line );\n\n     /* Add description to list. */\n     direct_list_append( &pool->allocs, &desc->link );\n\n     /* Unlock the pool. */\n     fusion_skirmish_dismiss( &pool->lock );\n\n     return data + sizeof(SHMemDesc);\n}\n\nvoid *\nfusion_dbg_shcalloc( FusionSHMPoolShared *pool,\n                     const char          *file,\n                     int                  line,\n                     const char          *func,\n                     size_t               nmemb,\n                     size_t               size )\n{\n     DirectResult  ret;\n     SHMemDesc    *desc;\n     void         *data = NULL;\n\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( file != NULL );\n     D_ASSERT( line > 0 );\n     D_ASSERT( func != NULL );\n     D_ASSERT( nmemb > 0 );\n     D_ASSERT( size > 0 );\n\n     if (!pool->debug)\n          return fusion_shcalloc( pool, nmemb, size );\n\n     /* Lock the pool. */\n     ret = fusion_skirmish_prevail( &pool->lock );\n     if (ret) {\n          D_DERROR( ret, \"Fusion/SHM: Could not lock shared memory pool!\\n\" );\n          return NULL;\n     }\n\n     /* Allocate memory from the pool. */\n     ret = fusion_shm_pool_allocate( pool, nmemb * size + sizeof(SHMemDesc), true, false, &data );\n     if (ret) {\n          D_DERROR( ret, \"Fusion/SHM: Could not allocate \"_ZU\" bytes from pool!\\n\", nmemb * size + sizeof(SHMemDesc) );\n          fusion_skirmish_dismiss( &pool->lock );\n          return NULL;\n     }\n\n     /* Fill description. */\n     desc = fill_shmem_desc( data, nmemb * size, func, file, line, _fusion_id( pool->shm->world ) );\n\n     D_DEBUG_AT( Fusion_SHM, \"Allocating \"_ZUn(9)\" bytes at %p [%8lu] in %-30s [%3lx] (%s: %u)\\n\",\n                 desc->bytes, desc->mem, (unsigned long) desc->mem - (unsigned long) pool->heap,\n                 desc->func, desc->fid, desc->file, desc->line );\n\n     /* Add description to list. */\n     direct_list_append( &pool->allocs, &desc->link );\n\n     /* Unlock the pool. */\n     fusion_skirmish_dismiss( &pool->lock );\n\n     return data + sizeof(SHMemDesc);\n}\n\nvoid *\nfusion_dbg_shrealloc( FusionSHMPoolShared *pool,\n                      const char          *file,\n                      int                  line,\n                      const char          *func,\n                      const char          *what,\n                      void                *ptr,\n                      size_t               size )\n{\n     DirectResult  ret;\n     SHMemDesc    *desc;\n     void         *data = NULL;\n\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( file != NULL );\n     D_ASSERT( line > 0 );\n     D_ASSERT( func != NULL );\n     D_ASSERT( what != NULL );\n\n     if (!pool->debug)\n          return fusion_shrealloc( pool, ptr, size );\n\n     if (!ptr)\n          return fusion_dbg_shmalloc( pool, file, line, func, size );\n\n     if (!size) {\n          fusion_dbg_shfree( pool, file, line, func, what, ptr );\n          return NULL;\n     }\n\n     /* Lock the pool. */\n     ret = fusion_skirmish_prevail( &pool->lock );\n     if (ret) {\n          D_DERROR( ret, \"Fusion/SHM: Could not lock shared memory pool!\\n\" );\n          return NULL;\n     }\n\n     /* Lookup the corresponding description. */\n     direct_list_foreach (desc, pool->allocs) {\n          if (desc->mem == ptr)\n               break;\n     }\n\n     if (!desc) {\n          D_ERROR( \"Fusion/SHM: Cannot reallocate unknown chunk at %p (%s) from [%s:%d in %s()]!\\n\",\n                   ptr, what, file, line, func );\n          return NULL;\n     }\n\n     /* Remove the description in case the block moves. */\n     direct_list_remove( &pool->allocs, &desc->link );\n\n     /* Reallocate the memory block. */\n     ret = fusion_shm_pool_reallocate( pool, ptr - sizeof(SHMemDesc), size + sizeof(SHMemDesc), false, &data );\n     if (ret) {\n          D_DERROR( ret, \"Fusion/SHM: Could not reallocate from \"_ZU\" to \"_ZU\" bytes!\\n\",\n                    desc->bytes + sizeof(SHMemDesc), size + sizeof(SHMemDesc) );\n          fusion_skirmish_dismiss( &pool->lock );\n          return NULL;\n     }\n\n     /* Fill description. */\n     desc = fill_shmem_desc( data, size, func, file, line, _fusion_id( pool->shm->world ) );\n\n     D_DEBUG_AT( Fusion_SHM, \"Reallocating \"_ZUn(9)\" bytes at %p [%8lu] in %-30s [%3lx] (%s: %u) '%s'\\n\",\n                 desc->bytes, desc->mem, (unsigned long) desc->mem - (unsigned long) pool->heap,\n                 desc->func, desc->fid, desc->file, desc->line, what );\n\n     /* Add description to list. */\n     direct_list_append( &pool->allocs, &desc->link );\n\n     /* Unlock the pool. */\n     fusion_skirmish_dismiss( &pool->lock );\n\n     return data + sizeof(SHMemDesc);\n}\n\nchar *\nfusion_dbg_shstrdup( FusionSHMPoolShared *pool,\n                     const char          *file,\n                     int                  line,\n                     const char          *func,\n                     const char          *string )\n{\n     DirectResult  ret;\n     SHMemDesc    *desc;\n     void         *data = NULL;\n     int           length;\n\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( file != NULL );\n     D_ASSERT( line > 0 );\n     D_ASSERT( func != NULL );\n     D_ASSERT( string != NULL );\n\n     if (!pool->debug)\n          return fusion_shstrdup( pool, string );\n\n     length = strlen( string ) + 1;\n\n     /* Lock the pool. */\n     ret = fusion_skirmish_prevail( &pool->lock );\n     if (ret) {\n          D_DERROR( ret, \"Fusion/SHM: Could not lock shared memory pool!\\n\" );\n          return NULL;\n     }\n\n     /* Allocate memory from the pool. */\n     ret = fusion_shm_pool_allocate( pool, length + sizeof(SHMemDesc), false, false, &data );\n     if (ret) {\n          D_DERROR( ret, \"Fusion/SHM: Could not allocate \"_ZU\" bytes from pool!\\n\", length + sizeof(SHMemDesc) );\n          fusion_skirmish_dismiss( &pool->lock );\n          return NULL;\n     }\n\n     /* Fill description. */\n     desc = fill_shmem_desc( data, length, func, file, line, _fusion_id( pool->shm->world ) );\n\n     D_DEBUG_AT( Fusion_SHM, \"Allocating \"_ZUn(9)\" bytes at %p [%8lu] in %-30s [%3lx] (%s: %u) <- \\\"%s\\\"\\n\",\n                 desc->bytes, desc->mem, (unsigned long) desc->mem - (unsigned long) pool->heap,\n                 desc->func, desc->fid, desc->file, desc->line, string );\n\n     D_DEBUG_AT( Fusion_SHM, \"  -> allocs %p\\n\", pool->allocs );\n\n     /* Add description to list. */\n     direct_list_append( &pool->allocs, &desc->link );\n\n     /* Unlock the pool. */\n     fusion_skirmish_dismiss( &pool->lock );\n\n     /* Copy string content. */\n     direct_memcpy( data + sizeof(SHMemDesc), string, length );\n\n     return data + sizeof(SHMemDesc);\n}\n\nvoid\nfusion_dbg_shfree( FusionSHMPoolShared *pool,\n                   const char          *file,\n                   int                  line,\n                   const char          *func,\n                   const char          *what,\n                   void                *ptr )\n{\n     DirectResult  ret;\n     SHMemDesc    *desc;\n\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( file != NULL );\n     D_ASSERT( line > 0 );\n     D_ASSERT( func != NULL );\n     D_ASSERT( what != NULL );\n     D_ASSERT( ptr != NULL );\n\n     if (!pool->debug)\n          return fusion_shfree( pool, ptr );\n\n     /* Lock the pool. */\n     ret = fusion_skirmish_prevail( &pool->lock );\n     if (ret) {\n          D_DERROR( ret, \"Fusion/SHM: Could not lock shared memory pool!\\n\" );\n          return;\n     }\n\n     /* Lookup the corresponding description. */\n     direct_list_foreach (desc, pool->allocs) {\n          if (desc->mem == ptr)\n               break;\n     }\n\n     if (!desc) {\n          D_ERROR( \"Fusion/SHM: Cannot free unknown chunk at %p (%s) from [%s:%d in %s()]!\\n\",\n                   ptr, what, file, line, func );\n          return;\n     }\n\n     D_DEBUG_AT( Fusion_SHM, \"Freeing \"_ZUn(9)\" bytes at %p [%8lu] in %-30s [%3lx] (%s: %u) '%s'\\n\",\n                 desc->bytes, desc->mem, (unsigned long) desc->mem - (unsigned long) pool->heap,\n                 desc->func, desc->fid, desc->file, desc->line, what );\n\n     /* Remove the description. */\n     direct_list_remove( &pool->allocs, &desc->link );\n\n     /* Free the memory block. */\n     fusion_shm_pool_deallocate( pool, ptr - sizeof(SHMemDesc), false );\n\n     /* Unlock the pool. */\n     fusion_skirmish_dismiss( &pool->lock );\n}\n\n#else /* FUSION_BUILD_MULTI */\n\nvoid *\nfusion_dbg_shmalloc( FusionSHMPoolShared *pool,\n                     const char          *file,\n                     int                  line,\n                     const char          *func,\n                     size_t               size )\n{\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( size > 0 );\n\n     D_DEBUG_AT( Fusion_SHM, \"Allocating \"_ZUn(9)\" bytes in %-30s (%s: %d)\\n\", size, func, file, line );\n\n     if (pool->debug)\n          return direct_dbg_malloc( file, line, func, size );\n\n     return malloc( size );\n}\n\nvoid *\nfusion_dbg_shcalloc( FusionSHMPoolShared *pool,\n                     const char          *file,\n                     int                  line,\n                     const char          *func,\n                     size_t               nmemb,\n                     size_t               size )\n{\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( nmemb > 0 );\n     D_ASSERT( size > 0 );\n\n\n     D_DEBUG_AT( Fusion_SHM, \"Allocating \"_ZUn(9)\" bytes in %-30s (%s: %d)\\n\", size, func, file, line );\n\n     if (pool->debug)\n          return direct_dbg_calloc( file, line, func, nmemb, size );\n\n     return calloc( nmemb, size );\n}\n\nvoid *\nfusion_dbg_shrealloc( FusionSHMPoolShared *pool,\n                      const char          *file,\n                      int                  line,\n                      const char          *func,\n                      const char          *what,\n                      void                *ptr,\n                      size_t               size )\n{\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n\n     D_DEBUG_AT( Fusion_SHM, \"Reallocating \"_ZUn(9)\" bytes in %-30s (%s: %d) '%s'\\n\", size, func, file, line, what );\n\n     if (pool->debug)\n          return direct_dbg_realloc( file, line, func, what, ptr, size );\n\n     return realloc( ptr, size );\n}\n\nchar *\nfusion_dbg_shstrdup( FusionSHMPoolShared *pool,\n                     const char          *file,\n                     int                  line,\n                     const char          *func,\n                     const char          *string )\n{\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( string != NULL );\n\n     D_DEBUG_AT( Fusion_SHM, \"Allocating \"_ZUn(9)\" bytes in %-30s (%s: %d) <- \\\"%s\\\"\\n\",\n                 strlen( string ), func, file, line, string );\n\n     if (pool->debug)\n          return direct_dbg_strdup( file, line, func, string );\n\n     return strdup( string );\n}\n\nvoid\nfusion_dbg_shfree( FusionSHMPoolShared *pool,\n                   const char          *file,\n                   int                  line,\n                   const char          *func,\n                   const char          *what,\n                   void                *ptr )\n{\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( ptr != NULL );\n\n     D_DEBUG_AT( Fusion_SHM, \"Freeing bytes in %-30s (%s: %d) '%s'\\n\", func, file, line, what );\n\n     if (pool->debug)\n          direct_dbg_free( file, line, func, what, ptr );\n     else\n          free( ptr );\n}\n\n#endif /* FUSION_BUILD_MULTI */\n\n#else /* DIRECT_BUILD_DEBUGS */\n\n#if FUSION_BUILD_MULTI\n\nvoid\nfusion_print_memleaks( FusionSHMPoolShared *pool )\n{\n}\n\n#endif /* FUSION_BUILD_MULTI */\n\nvoid *\nfusion_dbg_shmalloc( FusionSHMPoolShared *pool,\n                     const char          *file,\n                     int                  line,\n                     const char          *func,\n                     size_t               size )\n{\n     return fusion_shmalloc( pool, size );\n}\n\nvoid *\nfusion_dbg_shcalloc( FusionSHMPoolShared *pool,\n                     const char          *file,\n                     int                  line,\n                     const char          *func,\n                     size_t               nmemb,\n                     size_t               size )\n{\n     return fusion_shcalloc( pool, nmemb, size );\n}\n\nvoid *\nfusion_dbg_shrealloc( FusionSHMPoolShared *pool,\n                      const char          *file,\n                      int                  line,\n                      const char          *func,\n                      const char          *what,\n                      void                *ptr,\n                      size_t               size )\n{\n     return fusion_shrealloc( pool, ptr, size );\n}\n\nchar *\nfusion_dbg_shstrdup( FusionSHMPoolShared *pool,\n                     const char          *file,\n                     int                  line,\n                     const char          *func,\n                     const char          *string )\n{\n     return fusion_shstrdup( pool, string );\n}\n\nvoid\nfusion_dbg_shfree( FusionSHMPoolShared *pool,\n                   const char          *file,\n                   int                  line,\n                   const char          *func,\n                   const char          *what,\n                   void                *ptr )\n{\n     return fusion_shfree( pool, ptr );\n}\n\n#endif /* DIRECT_BUILD_DEBUGS */\n\n#if FUSION_BUILD_MULTI\n\nvoid *\nfusion_shmalloc( FusionSHMPoolShared *pool,\n                 size_t               size )\n{\n     void *data = NULL;\n\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( size > 0 );\n\n     if (fusion_shm_pool_allocate( pool, size, false, true, &data ))\n          return NULL;\n\n     D_ASSERT( data != NULL );\n\n     return data;\n}\n\nvoid *\nfusion_shcalloc( FusionSHMPoolShared *pool,\n                 size_t               nmemb,\n                 size_t               size )\n{\n     void *data = NULL;\n\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( nmemb > 0 );\n     D_ASSERT( size > 0 );\n\n     if (fusion_shm_pool_allocate( pool, nmemb * size, true, true, &data ))\n          return NULL;\n\n     D_ASSERT( data != NULL );\n\n     return data;\n}\n\nvoid *\nfusion_shrealloc( FusionSHMPoolShared *pool,\n                  void                *ptr,\n                  size_t               size )\n{\n     void *data = NULL;\n\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n\n     if (!ptr)\n          return fusion_shmalloc( pool, size );\n\n     if (!size) {\n          fusion_shfree( pool, ptr );\n          return NULL;\n     }\n\n     if (fusion_shm_pool_reallocate( pool, ptr, size, true, &data ))\n          return NULL;\n\n     D_ASSERT( data != NULL || size == 0 );\n\n     return data;\n}\n\nchar *\nfusion_shstrdup( FusionSHMPoolShared *pool,\n                 const char          *string )\n{\n     int   len;\n     void *data = NULL;\n\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( string != NULL );\n\n     len = strlen( string ) + 1;\n\n     if (fusion_shm_pool_allocate( pool, len, false, true, &data ))\n          return NULL;\n\n     D_ASSERT( data != NULL );\n\n     direct_memcpy( data, string, len );\n\n     return data;\n}\n\nvoid\nfusion_shfree( FusionSHMPoolShared *pool,\n               void                *ptr )\n{\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( ptr != NULL );\n\n     fusion_shm_pool_deallocate( pool, ptr, true );\n}\n\n#else /* FUSION_BUILD_MULTI */\n\nvoid *\nfusion_shmalloc( FusionSHMPoolShared *pool,\n                 size_t               size )\n{\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( size > 0 );\n\n     return malloc( size );\n}\n\nvoid *\nfusion_shcalloc( FusionSHMPoolShared *pool,\n                 size_t               nmemb,\n                 size_t               size )\n{\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( nmemb > 0 );\n     D_ASSERT( size > 0 );\n\n     return calloc( nmemb, size );\n}\n\nvoid *\nfusion_shrealloc( FusionSHMPoolShared *pool,\n                  void                *ptr,\n                  size_t               size )\n{\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n\n     return realloc( ptr, size );\n}\n\nchar *\nfusion_shstrdup( FusionSHMPoolShared *pool,\n                 const char          *string )\n{\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( string != NULL );\n\n     return strdup( string );\n}\n\nvoid\nfusion_shfree( FusionSHMPoolShared *pool,\n               void                *ptr )\n{\n     D_MAGIC_ASSERT( pool, FusionSHMPoolShared );\n     D_ASSERT( ptr != NULL );\n\n     free( ptr );\n}\n\n#endif /* FUSION_BUILD_MULTI */\n"
  },
  {
    "path": "lib/fusion/shmalloc.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FUSION__SHMALLOC_H__\n#define __FUSION__SHMALLOC_H__\n\n#include <fusion/types.h>\n\n/**********************************************************************************************************************/\n\n#if FUSION_BUILD_MULTI\n\nvoid FUSION_API  fusion_print_madvise     ( void );\n\nvoid FUSION_API  fusion_print_memleaks    ( FusionSHMPoolShared *pool );\n\n#endif /* FUSION_BUILD_MULTI */\n\nvoid FUSION_API *fusion_dbg_shmalloc      ( FusionSHMPoolShared *pool,\n                                            const char          *file,\n                                            int                  line,\n                                            const char          *func,\n                                            size_t               size );\n\nvoid FUSION_API *fusion_dbg_shcalloc      ( FusionSHMPoolShared *pool,\n                                            const char          *file,\n                                            int                  line,\n                                            const char          *func,\n                                            size_t               nmemb,\n                                            size_t               size );\n\nvoid FUSION_API *fusion_dbg_shrealloc     ( FusionSHMPoolShared *pool,\n                                            const char          *file,\n                                            int                  line,\n                                            const char          *func,\n                                            const char          *what,\n                                            void                *ptr,\n                                            size_t               size );\n\nchar FUSION_API *fusion_dbg_shstrdup      ( FusionSHMPoolShared *pool,\n                                            const char          *file,\n                                            int                  line,\n                                            const char          *func,\n                                            const char          *string );\n\nvoid FUSION_API  fusion_dbg_shfree        ( FusionSHMPoolShared *pool,\n                                            const char          *file,\n                                            int                  line,\n                                            const char          *func,\n                                            const char          *what,\n                                            void                *ptr );\n\nvoid FUSION_API *fusion_shmalloc          ( FusionSHMPoolShared *pool,\n                                            size_t               size );\n\nvoid FUSION_API *fusion_shcalloc          ( FusionSHMPoolShared *pool,\n                                            size_t               nmemb,\n                                            size_t               size );\n\nvoid FUSION_API *fusion_shrealloc         ( FusionSHMPoolShared *pool,\n                                            void                *ptr,\n                                            size_t               size );\n\nchar FUSION_API *fusion_shstrdup          ( FusionSHMPoolShared *pool,\n                                            const char          *string );\n\nvoid FUSION_API  fusion_shfree            ( FusionSHMPoolShared *pool,\n                                            void                *ptr );\n\n/**********************************************************************************************************************/\n\n#if DIRECT_BUILD_DEBUG || defined(DIRECT_ENABLE_DEBUG)\n\n#define SHMALLOC(pool,bytes)       fusion_dbg_shmalloc ( pool, __FILE__, __LINE__, __FUNCTION__, bytes )\n#define SHCALLOC(pool,count,bytes) fusion_dbg_shcalloc ( pool, __FILE__, __LINE__, __FUNCTION__, count, bytes )\n#define SHREALLOC(pool,mem,bytes)  fusion_dbg_shrealloc( pool, __FILE__, __LINE__, __FUNCTION__, #mem, mem, bytes )\n#define SHSTRDUP(pool,string)      fusion_dbg_shstrdup ( pool, __FILE__, __LINE__, __FUNCTION__, string )\n#define SHFREE(pool,mem)           fusion_dbg_shfree   ( pool, __FILE__, __LINE__, __FUNCTION__, #mem, mem )\n\n#else /* DIRECT_BUILD_DEBUG || defined(DIRECT_ENABLE_DEBUG) */\n\n#define SHMALLOC                   fusion_shmalloc\n#define SHCALLOC                   fusion_shcalloc\n#define SHREALLOC                  fusion_shrealloc\n#define SHSTRDUP                   fusion_shstrdup\n#define SHFREE                     fusion_shfree\n\n#endif /* DIRECT_BUILD_DEBUG || defined(DIRECT_ENABLE_DEBUG) */\n\n#endif\n"
  },
  {
    "path": "lib/fusion/types.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FUSION__TYPES_H__\n#define __FUSION__TYPES_H__\n\n#include <direct/messages.h>\n#include <fusion/build.h>\n\n/**********************************************************************************************************************/\n\n#define FUSION_API\n\n#define FCEF_NODIRECT 0x80\n\n#define FUSION_SHM_TMPFS_PATH_NAME_LEN 64\n\n/**********************************************************************************************************************/\n\ntypedef struct __Fusion_FusionArena         FusionArena;\ntypedef struct __Fusion_FusionCall          FusionCall;\ntypedef struct __Fusion_FusionHash          FusionHash;\ntypedef struct __Fusion_FusionObject        FusionObject;\ntypedef struct __Fusion_FusionObjectPool    FusionObjectPool;\ntypedef struct __Fusion_FusionReactor       FusionReactor;\ntypedef struct __Fusion_FusionRef           FusionRef;\ntypedef struct __Fusion_FusionSHMPool       FusionSHMPool;\ntypedef struct __Fusion_FusionSHMPoolShared FusionSHMPoolShared;\ntypedef struct __Fusion_FusionSHM           FusionSHM;\ntypedef struct __Fusion_FusionSHMShared     FusionSHMShared;\ntypedef struct __Fusion_FusionWorld         FusionWorld;\ntypedef struct __Fusion_FusionWorldShared   FusionWorldShared;\n\n/**********************************************************************************************************************/\n\n#if FUSION_BUILD_MULTI && FUSION_BUILD_KERNEL\n\n#include <linux/fusion.h>\n\n#define FUSION_CALL_MAX_LENGTH (FUSION_MESSAGE_SIZE - sizeof(FusionReadMessage))\n\n#else /* FUSION_BUILD_MULTI && FUSION_BUILD_KERNEL */\n\ntypedef unsigned long FusionID;\n\ntypedef enum {\n     FCEF_NONE   = 0x00000000,\n     FCEF_ONEWAY = 0x00000001,\n     FCEF_QUEUE  = 0x00000002,\n     FCEF_ALL    = 0x00000003\n} FusionCallExecFlags;\n\n#if FUSION_BUILD_MULTI\n\n#include <fusion/protocol.h>\n\n#endif /* FUSION_BUILD_MULTI */\n\n#define FUSION_ID_MASTER 1L\n\n#define FUSION_CALL_MAX_LENGTH (64 * 1024)\n\n#endif /* FUSION_BUILD_MULTI && FUSION_BUILD_KERNEL */\n\n#if FUSION_BUILD_MULTI\n#define D_OOSHM() direct_messages_ooshm( __FUNCTION__, __FILE__, __LINE__ )\n#else /* FUSION_BUILD_MULTI */\n#define D_OOSHM() D_OOM()\n#endif /* FUSION_BUILD_MULTI */\n\n#endif\n"
  },
  {
    "path": "lib/fusion/vector.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/mem.h>\n#include <direct/memcpy.h>\n#include <fusion/shmalloc.h>\n#include <fusion/vector.h>\n\nD_DEBUG_DOMAIN( Fusion_Vector, \"Fusion/Vector\", \"Fusion Vector\" );\n\n/**********************************************************************************************************************/\n\nstatic __inline__ bool\nensure_capacity( FusionVector *vector )\n{\n     D_MAGIC_ASSERT( vector, FusionVector );\n     D_ASSERT( vector->capacity > 0 );\n\n     if (!vector->elements) {\n          if (vector->pool)\n               vector->elements = SHMALLOC( vector->pool, vector->capacity * sizeof(void*) );\n          else\n               vector->elements = D_MALLOC( vector->capacity * sizeof(void*) );\n\n          if (!vector->elements)\n               return false;\n     }\n     else if (vector->count == vector->capacity) {\n          void *elements;\n          void *oldelements = vector->elements;\n          int   capacity    = vector->capacity << 1;\n\n          if (vector->pool)\n               elements = SHMALLOC( vector->pool, capacity * sizeof(void*) );\n          else\n               elements = D_MALLOC( capacity * sizeof(void*) );\n\n          if (!elements)\n               return false;\n\n          direct_memcpy( elements, vector->elements, vector->count * sizeof(void*) );\n\n          vector->elements = elements;\n          vector->capacity = capacity;\n\n          if (vector->pool)\n               SHFREE( vector->pool, oldelements );\n          else\n               D_FREE( oldelements );\n     }\n\n     return true;\n}\n\nvoid\nfusion_vector_init( FusionVector        *vector,\n                    int                  capacity,\n                    FusionSHMPoolShared *pool )\n{\n     D_ASSERT( vector != NULL );\n     D_ASSERT( capacity > 0 );\n\n     D_DEBUG_AT( Fusion_Vector, \"Creating vector with initial capacity of %d...\\n\", capacity );\n\n     vector->elements = NULL;\n     vector->count    = 0;\n     vector->capacity = capacity;\n     vector->pool     = pool;\n\n     D_MAGIC_SET( vector, FusionVector );\n}\n\nvoid\nfusion_vector_destroy( FusionVector *vector )\n{\n     D_MAGIC_ASSERT( vector, FusionVector );\n     D_ASSERT( vector->count == 0 || vector->elements != NULL );\n\n     if (vector->elements) {\n          if (vector->pool)\n               SHFREE( vector->pool, vector->elements );\n          else\n               D_FREE( vector->elements );\n\n          vector->elements = NULL;\n     }\n\n     D_MAGIC_CLEAR( vector );\n}\n\nDirectResult\nfusion_vector_add( FusionVector *vector,\n                   void         *element )\n{\n     D_MAGIC_ASSERT( vector, FusionVector );\n     D_ASSERT( element != NULL );\n\n     /* Make sure there's a free entry left. */\n     if (!ensure_capacity( vector ))\n          return D_OOSHM();\n\n     /* Add the element to the vector. */\n     vector->elements[vector->count++] = element;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_vector_insert( FusionVector *vector,\n                      void         *element,\n                      int           index )\n{\n     D_MAGIC_ASSERT( vector, FusionVector );\n     D_ASSERT( element != NULL );\n     D_ASSERT( index >= 0 );\n     D_ASSERT( index <= vector->count );\n\n     /* Make sure there's a free entry left. */\n     if (!ensure_capacity( vector ))\n          return D_OOSHM();\n\n     /* Move elements from insertion point one up. */\n     memmove( &vector->elements[index+1], &vector->elements[index], (vector->count - index) * sizeof(void*) );\n\n     /* Insert the element into the vector. */\n     vector->elements[index] = element;\n\n     /* Increase the element counter. */\n     vector->count++;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_vector_move( FusionVector *vector,\n                    int           from,\n                    int           to )\n{\n     void *element;\n\n     D_MAGIC_ASSERT( vector, FusionVector );\n     D_ASSERT( from >= 0 );\n     D_ASSERT( from < vector->count );\n     D_ASSERT( to >= 0 );\n     D_ASSERT( to < vector->count );\n\n     if (to == from)\n          return DR_OK;\n\n     /* Save the element. */\n     element = vector->elements[from];\n\n     /* Move elements that lie on the way to the new position. */\n     if (to > from) {\n          /* Element is moving up -> move other elements down. */\n          memmove( &vector->elements[from], &vector->elements[from+1], (to - from) * sizeof(void*) );\n     }\n     else {\n          /* Element is moving down -> move other elements up. */\n          memmove( &vector->elements[to+1], &vector->elements[to], (from - to) * sizeof(void*) );\n     }\n\n     /* Restore the element at the new position. */\n     vector->elements[to] = element;\n\n     return DR_OK;\n}\n\nDirectResult\nfusion_vector_remove( FusionVector *vector,\n                      int           index )\n{\n     D_MAGIC_ASSERT( vector, FusionVector );\n     D_ASSERT( index >= 0 );\n     D_ASSERT( index < vector->count );\n\n     /* Move elements after this element one down. */\n     memmove( &vector->elements[index], &vector->elements[index+1], (vector->count - index - 1) * sizeof(void*) );\n\n     /* Decrease the element counter. */\n     vector->count--;\n\n     return DR_OK;\n}\n"
  },
  {
    "path": "lib/fusion/vector.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FUSION__VECTOR_H__\n#define __FUSION__VECTOR_H__\n\n#include <direct/debug.h>\n#include <fusion/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int                   magic;\n\n     void                **elements;\n     int                   count;\n\n     int                   capacity;\n\n     FusionSHMPoolShared  *pool;\n} FusionVector;\n\n/**********************************************************************************************************************/\n\nvoid         FUSION_API fusion_vector_init   ( FusionVector        *vector,\n                                               int                  capacity,\n                                               FusionSHMPoolShared *pool );\n\nvoid         FUSION_API fusion_vector_destroy( FusionVector        *vector );\n\nDirectResult FUSION_API fusion_vector_add    ( FusionVector        *vector,\n                                               void                *element );\n\nDirectResult FUSION_API fusion_vector_insert ( FusionVector        *vector,\n                                               void                *element,\n                                               int                  index );\n\nDirectResult FUSION_API fusion_vector_move   ( FusionVector        *vector,\n                                               int                  from,\n                                               int                  to );\n\nDirectResult FUSION_API fusion_vector_remove ( FusionVector        *vector,\n                                               int                  index );\n\n/**********************************************************************************************************************/\n\nstatic __inline__ bool\nfusion_vector_has_elements( const FusionVector *vector )\n{\n     D_MAGIC_ASSERT( vector, FusionVector );\n\n     return vector->count > 0;\n}\n\nstatic __inline__ bool\nfusion_vector_is_empty( const FusionVector *vector )\n{\n     D_MAGIC_ASSERT( vector, FusionVector );\n\n     return vector->count == 0;\n}\n\nstatic __inline__ int\nfusion_vector_size( const FusionVector *vector )\n{\n     D_MAGIC_ASSERT( vector, FusionVector );\n\n     return vector->count;\n}\n\nstatic __inline__ void *\nfusion_vector_at( const FusionVector *vector,\n                  int                 index )\n{\n     D_MAGIC_ASSERT( vector, FusionVector );\n     D_ASSERT( index >= 0 );\n     D_ASSERT( index < vector->count );\n\n     return vector->elements[index];\n}\n\nstatic __inline__ bool\nfusion_vector_contains( const FusionVector *vector,\n                        const void         *element )\n{\n     int           i;\n     int           count;\n     void * const *elements;\n\n     D_MAGIC_ASSERT( vector, FusionVector );\n     D_ASSERT( element != NULL );\n\n     count    = vector->count;\n     elements = vector->elements;\n\n     /* Start with more recently added elements. */\n     for (i = count - 1; i >= 0; i--)\n          if (elements[i] == element)\n               return true;\n\n     return false;\n}\n\nstatic __inline__ int\nfusion_vector_index_of( const FusionVector *vector,\n                        const void         *element )\n{\n     int           i;\n     int           count;\n     void * const *elements;\n\n     D_MAGIC_ASSERT( vector, FusionVector );\n     D_ASSERT( element != NULL );\n\n     count    = vector->count;\n     elements = vector->elements;\n\n     /* Start with more recently added elements. */\n     for (i = count - 1; i >= 0; i--)\n          if (elements[i] == element)\n               return i;\n\n     return INT_MIN >> 2;\n}\n\n#define fusion_vector_foreach(element,index,vector)                   \\\n     for ((index) = 0;                                                \\\n          (index) < (vector).count &&                                 \\\n          (element = (__typeof__(element)) (vector).elements[index]); \\\n          (index)++)\n\n#define fusion_vector_foreach_reverse(element,index,vector)           \\\n     for ((index) = (vector).count - 1;                               \\\n          (index) >= 0 && (vector).count && (vector).elements &&      \\\n          (element = (__typeof__(element)) (vector).elements[index]); \\\n          (index)--)\n\n#endif\n"
  },
  {
    "path": "meson.build",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\nproject('DirectFB2', 'c',\n        version: '2.0.0',\n        meson_version: '>= 0.61',\n        default_options: 'buildtype=release')\n\ndirectfb_version = meson.project_version()\ndirectfb_major_version = directfb_version.split('.')[0].to_int()\ndirectfb_minor_version = directfb_version.split('.')[1].to_int()\ndirectfb_micro_version = directfb_version.split('.')[2].to_int()\n\nif get_option('default_library') == 'both'\n  error('''Choose library type between 'shared' or 'static'.''')\nelif get_option('default_library') == 'shared'\n  libsuffix = '.so'\nelse\n  libsuffix = '.a'\nendif\n\nif get_option('default_library') == 'shared' and not get_option('constructors')\n  error('''Choose 'static' library type to disable use of constructor attribute.''')\nendif\n\nmoduledirname = get_option('moduledirname')\nif moduledirname == ''\n  if get_option('debug')\n    moduledirname = 'directfb-@0@.@1@-0-debug'.format(directfb_major_version, directfb_minor_version)\n  else\n    if not get_option('debug-support')\n      moduledirname = 'directfb-@0@.@1@-0-pure'.format(directfb_major_version, directfb_minor_version)\n    else\n      moduledirname = 'directfb-@0@.@1@-0'.format(directfb_major_version, directfb_minor_version)\n    endif\n  endif\nendif\nmoduledir = get_option('prefix') / get_option('libdir') / moduledirname\n\ncc = meson.get_compiler('c')\n\nconfig_conf = configuration_data()\n\nconfig_conf.set('SIZEOF_LONG', cc.sizeof('long'), description: 'The size of long, as computed by sizeof.')\n\nconfig_conf.set('WORDS_BIGENDIAN', host_machine.endian() == 'big', description: 'Byte ordering is bigendian.')\n\nif host_machine.cpu_family() == 'x86' or host_machine.cpu_family() == 'x86_64'\n  if get_option('mmx')\n    config_conf.set('USE_MMX', 1, description: 'Define to 1 if you are compiling MMX assembly support.')\n  endif\nendif\n\nif host_machine.cpu_family() == 'arm' or host_machine.cpu_family() == 'aarch64'\n  if get_option('neon')\n    config_conf.set('USE_NEON', 1, description: 'Define to 1 if you are compiling NEON assembly support.')\n  endif\nendif\n\nconfigure_file(configuration: config_conf, output: 'config.h')\n\nconfig_inc = include_directories('.')\nlib_inc = include_directories('lib')\ndirectfb_inc = [include_directories('include', 'src'), lib_inc]\n\nadd_global_arguments('-Wstrict-prototypes', language: 'c')\n\npkgconfig = import('pkgconfig')\n\n# core libraries\n\nsubdir('include')\nsubdir('lib/direct')\nsubdir('lib/fusion')\nsubdir('src')\n\n# core system modules\n\nsubdir('systems/dummy')\nif get_option('os') == 'linux'\n  if get_option('drmkms')\n    subdir('systems/drmkms')\n  endif\n  if get_option('fbdev')\n    subdir('systems/fbdev')\n  endif\nendif\n\n# input driver modules\n\nif get_option('os') == 'linux'\n  if get_option('linux_input')\n    subdir('inputdrivers/linux_input')\n  endif\nendif\n\n# interface modules\n\nsubdir('interfaces/ICoreResourceManager')\nsubdir('interfaces/IDirectFBFont')\nsubdir('interfaces/IDirectFBImageProvider')\nsubdir('interfaces/IDirectFBVideoProvider')\nsubdir('interfaces/IDirectFBWindows')\n\n# wm modules\n\nsubdir('wm/default')\n\n# generate the .pc files of the static modules\n\nif get_option('default_library') == 'static'\n  dfb_update_pkgconfig_conf = configuration_data()\n\n  dfb_update_pkgconfig_conf.set('PKGCONFIGDIR', get_option('prefix') / get_option('libdir') / 'pkgconfig')\n\n  dfb_update_pkgconfig_conf.set('VERSION', directfb_version)\n\n  dfb_update_pkgconfig = configure_file(configuration: dfb_update_pkgconfig_conf,\n                                        input: 'dfb-update-pkgconfig.in',\n                                        output: 'dfb-update-pkgconfig',\n                                        install: true,\n                                        install_dir: get_option('bindir'))\n\n  meson.add_install_script(dfb_update_pkgconfig)\nendif\n"
  },
  {
    "path": "meson_options.txt",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\noption('args-size',\n       type: 'integer',\n       value: '1024',\n       description: 'Maximum static args size (bytes) for Flux')\n\noption('constructors',\n       type: 'boolean',\n       description: 'Use constructor attribute for library initialization and loaded modules')\n\noption('debug-support',\n       type: 'boolean',\n       description: 'Debug support')\n\noption('drmkms',\n       type: 'boolean',\n       description: 'Linux DRM/KMS support')\n\noption('fbdev',\n       type: 'boolean',\n       description: 'Linux FBDev support')\n\noption('fluxcomp',\n       type : 'string',\n       value: 'fluxcomp.py',\n       description : 'The fluxcomp program to use')\n\noption('linux_input',\n       type: 'boolean',\n       description: 'Linux Input support')\n\noption('memcpy-probing',\n       type: 'boolean',\n       value: false,\n       description: 'Use memcpy() probing')\n\noption('message-size',\n       type: 'integer',\n       value: '16384',\n       description: 'Maximum message size (bytes) for Fusion')\n\noption('mmx',\n       type: 'boolean',\n       description: 'MMX assembly support')\n\noption('moduledirname',\n       type: 'string',\n       description: 'DirectFB module directory name')\n\noption('multi',\n       type: 'boolean',\n       value: false,\n       description: 'Multi application support')\n\noption('multi-kernel',\n       type: 'boolean',\n       value: false,\n       description: 'Use the Linux Fusion device for multi application')\n\noption('neon',\n       type: 'boolean',\n       description: 'NEON assembly support')\n\noption('network',\n       type: 'boolean',\n       description: 'Network support')\n\noption('os',\n       type: 'string',\n       value: 'linux',\n       description: 'OS name')\n\noption('piped-stream',\n       type: 'boolean',\n       description: 'Piped stream support')\n\noption('sentinels',\n       type: 'boolean',\n       value: false,\n       description: 'Sentinels')\n\noption('smooth-scaling',\n       type: 'boolean',\n       description: 'Smooth scaling')\n\noption('text',\n       type: 'boolean',\n       description: 'Text output')\n\noption('trace',\n       type: 'boolean',\n       value: false,\n       description: 'Call tracing')\n\noption('vendor-version',\n       type: 'string',\n       value: '',\n       description: 'Vendor version')\n"
  },
  {
    "path": "src/core/CoreDFB.flux",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\ninterface {\n        name    ICore\n        version 1.0\n        object  CoreDFB\n\n        method {\n                name    Initialize\n        }\n\n        method {\n                name    Register\n\n                arg {\n                        name        slave_call\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    CreateSurface\n\n                arg {\n                        name        config\n                        direction   input\n                        type        struct\n                        typename    CoreSurfaceConfig\n                }\n\n                arg {\n                        name        type\n                        direction   input\n                        type        enum\n                        typename    CoreSurfaceTypeFlags\n                }\n\n                arg {\n                        name        resource_id\n                        direction   input\n                        type        int\n                        typename    u64\n                }\n\n                arg {\n                        name        palette\n                        direction   input\n                        type        object\n                        typename    CorePalette\n                        optional    yes\n                }\n\n                arg {\n                        name        surface\n                        direction   output\n                        type        object\n                        typename    CoreSurface\n                }\n        }\n\n        method {\n                name    CreatePalette\n\n                arg {\n                        name        size\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        colorspace\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceColorSpace\n                }\n\n                arg {\n                        name        palette\n                        direction   output\n                        type        object\n                        typename    CorePalette\n                }\n        }\n\n        method {\n                name    ClipboardSet\n\n                arg {\n                        name        mime_type\n                        direction   input\n                        type        int\n                        typename    char\n                        count       mime_type_size\n                }\n\n                arg {\n                        name        mime_type_size\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        data\n                        direction   input\n                        type        int\n                        typename    char\n                        count       data_size\n                }\n\n                arg {\n                        name        data_size\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        timestamp_us\n                        direction   input\n                        type        int\n                        typename    u64\n                }\n        }\n\n        method {\n                name    ClipboardGet\n\n                arg {\n                        name        mime_type\n                        direction   output\n                        type        int\n                        typename    char\n                        max         MAX_CLIPBOARD_MIME_TYPE_SIZE\n                        count       mime_type_size\n                }\n\n                arg {\n                        name        mime_type_size\n                        direction   output\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        data\n                        direction   output\n                        type        int\n                        typename    char\n                        max         MAX_CLIPBOARD_DATA_SIZE\n                        count       data_size\n                }\n\n                arg {\n                        name        data_size\n                        direction   output\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    ClipboardGetTimestamp\n\n                arg {\n                        name        timestamp_us\n                        direction   output\n                        type        int\n                        typename    u64\n                }\n        }\n\n        method {\n                name    WaitIdle\n        }\n\n        method {\n                name    GetSurface\n\n                arg {\n                        name        surface_id\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        surface\n                        direction   output\n                        type        object\n                        typename    CoreSurface\n                }\n        }\n\n        method {\n                name    AllowSurface\n\n                arg {\n                        name        surface\n                        direction   input\n                        type        object\n                        typename    CoreSurface\n                }\n\n                arg {\n                        name        executable\n                        direction   input\n                        type        int\n                        typename    char\n                        count       executable_length\n                 }\n\n                 arg {\n                        name        executable_length\n                        direction   input\n                        type        int\n                        typename    u32\n                 }\n        }\n\n        method {\n                name    CreateState\n\n                arg {\n                        name        state\n                        direction   output\n                        type        object\n                        typename    CoreGraphicsState\n                }\n        }\n}\n"
  },
  {
    "path": "src/core/CoreDFB_CallMode.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core.h>\n#include <direct/system.h>\n#include <direct/thread.h>\n#include <fusion/conf.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     COREDFB_CALL_DENY     = 0x00000000,\n     COREDFB_CALL_DIRECT   = 0x00000001,\n     COREDFB_CALL_INDIRECT = 0x00000002\n} CoreDFBCallMode;\n\nstatic __inline__ CoreDFBCallMode\nCoreDFB_CallMode( CoreDFB *core )\n{\n#if FUSION_BUILD_MULTI\n     if (dfb_config->call_nodirect) {\n          if (dfb_core_is_master( core )) {\n               DirectThread *self = direct_thread_self();\n\n               if (self && fusion_dispatcher_tid( core->world ) == direct_thread_get_tid( self ))\n                    return COREDFB_CALL_DIRECT;\n          }\n\n          return COREDFB_CALL_INDIRECT;\n     }\n\n     if (core->shutdown_tid && core->shutdown_tid != direct_gettid() &&\n         direct_gettid() != fusion_dispatcher_tid(core->world)       &&\n         !Core_GetCalling()) {\n          while (core_dfb)\n               direct_thread_sleep( 10000 );\n\n          return COREDFB_CALL_DENY;\n     }\n\n     if (dfb_core_is_master( core ) || !fusion_config->secure_fusion)\n          return COREDFB_CALL_DIRECT;\n\n     return COREDFB_CALL_INDIRECT;\n#else /* FUSION_BUILD_MULTI */\n     if (dfb_config->call_nodirect) {\n          DirectThread *self = direct_thread_self();\n\n          if (self && fusion_dispatcher_tid( core->world ) == direct_thread_get_tid( self ))\n               return COREDFB_CALL_DIRECT;\n\n          return COREDFB_CALL_INDIRECT;\n     }\n\n     return COREDFB_CALL_DIRECT;\n#endif /* FUSION_BUILD_MULTI */\n}\n"
  },
  {
    "path": "src/core/CoreDFB_includes.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__COREDFB_INCLUDES_H__\n#define __CORE__COREDFB_INCLUDES_H__\n\n#include <core/core.h>\n#include <core/graphics_state.h>\n#include <core/layer_context.h>\n#include <core/palette.h>\n#include <core/surface_allocation.h>\n#include <core/surface_client.h>\n#include <core/windows.h>\n#include <core/windowstack.h>\n\n/**********************************************************************************************************************/\n\nstatic __inline__ DirectResult\nCoreDFB_Call( CoreDFB             *core,\n              FusionCallExecFlags  flags,\n              int                  call_arg,\n              void                *ptr,\n              unsigned int         length,\n              void                *ret_ptr,\n              unsigned int         ret_size,\n              unsigned int        *ret_length )\n{\n     return fusion_call_execute3( &core->shared->call, dfb_config->call_nodirect | flags, call_arg, ptr, length,\n                                  ret_ptr, ret_size, ret_length );\n}\n\n/**********************************************************************************************************************/\n\nstatic __inline__ DirectResult\nCoreGraphicsState_Catch( CoreDFB            *core,\n                         void               *object_ptr,\n                         CoreGraphicsState **ret_state )\n{\n     *ret_state = object_ptr;\n\n     return fusion_object_catch( object_ptr );\n}\n\nstatic __inline__ DirectResult\nCoreGraphicsState_Throw( CoreGraphicsState *state,\n                         FusionID           catcher,\n                         u32               *ret_object_id )\n{\n     *ret_object_id = state->object.id;\n\n     fusion_reactor_add_permissions( state->object.reactor, catcher, FUSION_REACTOR_PERMIT_ATTACH_DETACH );\n     fusion_ref_add_permissions( &state->object.ref, catcher,\n                                 FUSION_REF_PERMIT_REF_UNREF_LOCAL | FUSION_REF_PERMIT_CATCH );\n     fusion_call_add_permissions( &state->call, catcher, FUSION_CALL_PERMIT_EXECUTE );\n\n     if (dfb_config->graphics_state_call_limit)\n          fusion_call_set_quota( &state->call, catcher, dfb_config->graphics_state_call_limit );\n\n     fusion_object_add_owner( &state->object, catcher );\n\n     return fusion_ref_throw( &state->object.ref, catcher );\n}\n\n/**********************************************************************************************************************/\n\nstatic __inline__ u32\nCoreLayerContext_GetID( const CoreLayerContext *context )\n{\n     return context->object.id;\n}\n\nstatic __inline__ DirectResult\nCoreLayerContext_Lookup( CoreDFB           *core,\n                         u32                object_id,\n                         FusionID           caller,\n                         CoreLayerContext **ret_context )\n{\n     DFBResult         ret;\n     CoreLayerContext *context;\n\n     ret = dfb_core_get_layer_context( core, object_id, &context );\n     if (ret)\n          return ret;\n\n     if (fusion_object_check_owner( &context->object, caller, true )) {\n          dfb_layer_context_unref( context );\n          return DR_ACCESSDENIED;\n     }\n\n     *ret_context = context;\n\n     return DR_OK;\n}\n\nstatic __inline__ DirectResult\nCoreLayerContext_Unref( CoreLayerContext *context )\n{\n     return dfb_layer_context_unref( context );\n}\n\nstatic __inline__ DirectResult\nCoreLayerContext_Catch( CoreDFB           *core,\n                        void              *object_ptr,\n                        CoreLayerContext **ret_context )\n{\n     *ret_context = object_ptr;\n\n     return fusion_object_catch( object_ptr );\n}\n\nstatic __inline__ DirectResult\nCoreLayerContext_Throw( CoreLayerContext *context,\n                        FusionID          catcher,\n                        u32              *ret_object_id )\n{\n     *ret_object_id = context->object.id;\n\n     fusion_reactor_add_permissions( context->object.reactor, catcher, FUSION_REACTOR_PERMIT_ATTACH_DETACH );\n     fusion_ref_add_permissions( &context->object.ref, catcher,\n                                 FUSION_REF_PERMIT_REF_UNREF_LOCAL | FUSION_REF_PERMIT_CATCH );\n     fusion_call_add_permissions( &context->call, catcher, FUSION_CALL_PERMIT_EXECUTE );\n\n     if (context->stack)\n          fusion_call_add_permissions( &context->stack->call, catcher, FUSION_CALL_PERMIT_EXECUTE );\n\n     return fusion_ref_throw( &context->object.ref, catcher );\n}\n\n/**********************************************************************************************************************/\n\nstatic __inline__ DirectResult\nCoreLayerRegion_Catch( CoreDFB          *core,\n                       void             *object_ptr,\n                       CoreLayerRegion **ret_region )\n{\n     *ret_region = object_ptr;\n\n     return fusion_object_catch( object_ptr );\n}\n\nstatic __inline__ DirectResult\nCoreLayerRegion_Throw( CoreLayerRegion *region,\n                       FusionID         catcher,\n                       u32             *ret_object_id )\n{\n     *ret_object_id = region->object.id;\n\n     fusion_reactor_add_permissions( region->object.reactor, catcher, FUSION_REACTOR_PERMIT_ATTACH_DETACH );\n     fusion_ref_add_permissions( &region->object.ref, catcher,\n                                 FUSION_REF_PERMIT_REF_UNREF_LOCAL | FUSION_REF_PERMIT_CATCH );\n     fusion_call_add_permissions( &region->call, catcher, FUSION_CALL_PERMIT_EXECUTE );\n\n     return fusion_ref_throw( &region->object.ref, catcher );\n}\n\n/**********************************************************************************************************************/\n\nstatic __inline__ u32\nCorePalette_GetID( const CorePalette *palette )\n{\n     return palette->object.id;\n}\n\nstatic __inline__ DirectResult\nCorePalette_Lookup( CoreDFB      *core,\n                    u32           object_id,\n                    FusionID      caller,\n                    CorePalette **ret_palette )\n{\n     DFBResult    ret;\n     CorePalette *palette;\n\n     ret = dfb_core_get_palette( core, object_id, &palette );\n     if (ret)\n          return ret;\n\n     if (fusion_object_check_owner( &palette->object, caller, false )) {\n          dfb_palette_unref( palette );\n          return DR_ACCESSDENIED;\n     }\n\n     *ret_palette = palette;\n\n     return DR_OK;\n}\n\nstatic __inline__ DirectResult\nCorePalette_Unref( CorePalette *palette )\n{\n     return dfb_palette_unref( palette );\n}\n\nstatic __inline__ DirectResult\nCorePalette_Catch( CoreDFB      *core,\n                   void         *object_ptr,\n                   CorePalette **ret_palette )\n{\n     *ret_palette = object_ptr;\n\n     return fusion_object_catch( object_ptr );\n}\n\nstatic __inline__ DirectResult\nCorePalette_Throw( CorePalette *palette,\n                   FusionID     catcher,\n                   u32         *ret_object_id )\n{\n     *ret_object_id = palette->object.id;\n\n     fusion_reactor_add_permissions( palette->object.reactor, catcher, FUSION_REACTOR_PERMIT_ATTACH_DETACH );\n     fusion_ref_add_permissions( &palette->object.ref, catcher,\n                                 FUSION_REF_PERMIT_REF_UNREF_LOCAL | FUSION_REF_PERMIT_CATCH );\n     fusion_call_add_permissions( &palette->call, catcher, FUSION_CALL_PERMIT_EXECUTE );\n\n     fusion_object_add_owner( &palette->object, catcher );\n\n     return fusion_ref_throw( &palette->object.ref, catcher );\n}\n\n/**********************************************************************************************************************/\n\nstatic __inline__ u32\nCoreSurface_GetID( const CoreSurface *surface )\n{\n     return surface->object.id;\n}\n\nstatic __inline__ DirectResult\nCoreSurface_Lookup( CoreDFB      *core,\n                    u32           object_id,\n                    FusionID      caller,\n                    CoreSurface **ret_surface )\n{\n     DFBResult    ret;\n     CoreSurface *surface;\n\n     ret = fusion_object_lookup( core->shared->surface_pool, object_id, (FusionObject**) &surface );\n     if (ret)\n          return ret;\n\n     if (caller != FUSION_ID_MASTER && surface->object.identity != caller &&\n         fusion_object_check_owner( &surface->object, caller, false )) {\n          return DR_ACCESSDENIED;\n     }\n\n     *ret_surface = surface;\n\n     return DR_OK;\n}\n\nstatic __inline__ DirectResult\nCoreSurface_Unref( CoreSurface *surface )\n{\n     return DR_OK;\n}\n\nstatic __inline__ DirectResult\nCoreSurface_Catch( CoreDFB      *core,\n                   void         *object_ptr,\n                   CoreSurface **ret_surface )\n{\n     *ret_surface = object_ptr;\n\n     return fusion_object_catch( object_ptr );\n}\n\nstatic __inline__ DirectResult\nCoreSurface_Throw( CoreSurface *surface,\n                   FusionID     catcher,\n                   u32         *ret_object_id )\n{\n     *ret_object_id = surface->object.id;\n\n     fusion_reactor_add_permissions( surface->object.reactor, catcher,\n                                     FUSION_REACTOR_PERMIT_ATTACH_DETACH | FUSION_REACTOR_PERMIT_DISPATCH );\n     fusion_ref_add_permissions( &surface->object.ref, catcher,\n                                 FUSION_REF_PERMIT_REF_UNREF_LOCAL | FUSION_REF_PERMIT_CATCH );\n     fusion_call_add_permissions( &surface->call, catcher, FUSION_CALL_PERMIT_EXECUTE );\n\n     fusion_object_add_owner( &surface->object, catcher );\n\n     return fusion_ref_throw( &surface->object.ref, catcher );\n}\n\n/**********************************************************************************************************************/\n\nstatic __inline__ DirectResult\nCoreSurfaceAllocation_Catch( CoreDFB                *core,\n                             void                   *object_ptr,\n                             CoreSurfaceAllocation **ret_allocation )\n{\n     *ret_allocation = object_ptr;\n\n     return fusion_object_catch( object_ptr );\n}\n\nstatic __inline__ DirectResult\nCoreSurfaceAllocation_Throw( CoreSurfaceAllocation *allocation,\n                             FusionID               catcher,\n                             u32                   *ret_object_id )\n{\n     *ret_object_id = allocation->object.id;\n\n     fusion_reactor_add_permissions( allocation->object.reactor, catcher, FUSION_REACTOR_PERMIT_ATTACH_DETACH );\n     fusion_ref_add_permissions( &allocation->object.ref, catcher,\n                                 FUSION_REF_PERMIT_REF_UNREF_LOCAL | FUSION_REF_PERMIT_CATCH );\n     fusion_call_add_permissions( &allocation->call, catcher, FUSION_CALL_PERMIT_EXECUTE );\n\n     fusion_object_add_owner( &allocation->object, catcher );\n\n     return fusion_ref_throw( &allocation->object.ref, catcher );\n}\n\n/**********************************************************************************************************************/\n\nstatic __inline__ u32\nCoreSurfaceBuffer_GetID( const CoreSurfaceBuffer *buffer )\n{\n     return buffer->object.id;\n}\n\nstatic __inline__ DirectResult\nCoreSurfaceBuffer_Lookup( CoreDFB            *core,\n                          u32                 object_id,\n                          FusionID            caller,\n                          CoreSurfaceBuffer **ret_buffer )\n{\n     DFBResult          ret;\n     CoreSurfaceBuffer *buffer;\n\n     ret = dfb_core_get_surface_buffer( core, object_id, &buffer );\n     if (ret)\n          return ret;\n\n     if (fusion_object_check_owner( &buffer->object, caller, false )) {\n          dfb_surface_buffer_unref( buffer );\n          return DR_ACCESSDENIED;\n     }\n\n     *ret_buffer = buffer;\n\n     return DR_OK;\n}\n\nstatic __inline__ DirectResult\nCoreSurfaceBuffer_Unref( CoreSurfaceBuffer *buffer )\n{\n     return dfb_surface_buffer_unref( buffer );\n}\n\n/**********************************************************************************************************************/\n\nstatic __inline__ DirectResult\nCoreSurfaceClient_Catch( CoreDFB            *core,\n                         void               *object_ptr,\n                         CoreSurfaceClient **ret_client )\n{\n     *ret_client = object_ptr;\n\n     return fusion_object_catch( object_ptr );\n}\n\nstatic __inline__ DirectResult\nCoreSurfaceClient_Throw( CoreSurfaceClient *client,\n                         FusionID           catcher,\n                         u32               *ret_object_id )\n{\n     *ret_object_id = client->object.id;\n\n     fusion_reactor_add_permissions( client->object.reactor, catcher, FUSION_REACTOR_PERMIT_ATTACH_DETACH );\n     fusion_ref_add_permissions( &client->object.ref, catcher,\n                                 FUSION_REF_PERMIT_REF_UNREF_LOCAL | FUSION_REF_PERMIT_CATCH );\n     fusion_call_add_permissions( &client->call, catcher, FUSION_CALL_PERMIT_EXECUTE );\n\n     fusion_object_add_owner( &client->object, catcher );\n\n     return fusion_ref_throw( &client->object.ref, catcher );\n}\n\n/**********************************************************************************************************************/\n\nstatic __inline__ u32\nCoreWindow_GetID( const CoreWindow *window )\n{\n     return window->object.id;\n}\n\nstatic __inline__ DirectResult\nCoreWindow_Lookup( CoreDFB     *core,\n                   u32          object_id,\n                   FusionID     caller,\n                   CoreWindow **ret_window )\n{\n     DFBResult   ret;\n     CoreWindow *window;\n\n     ret = dfb_core_get_window( core, object_id, &window );\n     if (ret)\n          return ret;\n\n     if (caller != FUSION_ID_MASTER && window->object.identity != caller &&\n         fusion_object_check_owner( &window->object, caller, false )) {\n          dfb_window_unref( window );\n          return DR_ACCESSDENIED;\n     }\n\n     *ret_window = window;\n\n     return DR_OK;\n}\n\nstatic __inline__ DirectResult\nCoreWindow_Unref( CoreWindow *window )\n{\n     return dfb_window_unref( window );\n}\n\nstatic __inline__ DirectResult\nCoreWindow_Catch( CoreDFB     *core,\n                  void        *object_ptr,\n                  CoreWindow **ret_window )\n{\n     *ret_window = object_ptr;\n\n     return fusion_object_catch( object_ptr );\n}\n\nstatic __inline__ DirectResult\nCoreWindow_Throw( CoreWindow *window,\n                  FusionID    catcher,\n                  u32        *ret_object_id )\n{\n     *ret_object_id = window->object.id;\n\n     fusion_reactor_add_permissions( window->object.reactor, catcher,\n                                     FUSION_REACTOR_PERMIT_ATTACH_DETACH | FUSION_REACTOR_PERMIT_DISPATCH );\n     fusion_ref_add_permissions( &window->object.ref, catcher,\n                                 FUSION_REF_PERMIT_REF_UNREF_LOCAL | FUSION_REF_PERMIT_CATCH );\n     fusion_call_add_permissions( &window->call, catcher, FUSION_CALL_PERMIT_EXECUTE );\n\n     fusion_object_add_owner( &window->object, catcher );\n\n     return fusion_ref_throw( &window->object.ref, catcher );\n}\n\n#endif\n"
  },
  {
    "path": "src/core/CoreDFB_real.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreDFB.h>\n#include <core/core.h>\n#include <core/clipboard.h>\n#include <core/graphics_state.h>\n#include <core/palette.h>\n#include <direct/memcpy.h>\n#include <fusion/conf.h>\n\nD_DEBUG_DOMAIN( DirectFB_CoreDFB, \"DirectFB/Core\", \"DirectFB Core\" );\n\n/**********************************************************************************************************************/\n\nDFBResult\nICore_Real__Initialize( CoreDFB *obj )\n{\n     D_DEBUG_AT( DirectFB_CoreDFB, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreDFB );\n\n     if (Core_GetIdentity() != FUSION_ID_MASTER)\n          return DFB_ACCESSDENIED;\n\n     return dfb_core_initialize( core_dfb );\n}\n\nDFBResult\nICore_Real__Register( CoreDFB *obj,\n                      u32      slave_call )\n{\n     D_DEBUG_AT( DirectFB_CoreDFB, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreDFB );\n\n     return Core_Resource_AddIdentity( Core_GetIdentity(), slave_call );\n}\n\nDFBResult\nICore_Real__CreateSurface( CoreDFB                  *obj,\n                           const CoreSurfaceConfig  *config,\n                           CoreSurfaceTypeFlags      type,\n                           u64                       resource_id,\n                           CorePalette              *palette,\n                           CoreSurface             **ret_surface )\n{\n     DFBResult    ret;\n     CoreSurface *surface;\n\n     D_DEBUG_AT( DirectFB_CoreDFB, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreDFB );\n     D_ASSERT( config != NULL );\n     D_ASSERT( ret_surface != NULL );\n\n     ret = Core_Resource_CheckSurface( config, resource_id );\n     if (ret)\n          return ret;\n\n     ret = dfb_surface_create( obj, config, type, resource_id, palette, &surface );\n     if (ret)\n          return ret;\n\n     Core_Resource_AddSurface( surface );\n\n     *ret_surface = surface;\n\n     return DFB_OK;\n}\n\nDFBResult\nICore_Real__CreatePalette( CoreDFB               *obj,\n                           u32                    size,\n                           DFBSurfaceColorSpace   colorspace,\n                           CorePalette          **ret_palette )\n{\n     D_DEBUG_AT( DirectFB_CoreDFB, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreDFB );\n     D_ASSERT( ret_palette != NULL );\n\n     return dfb_palette_create( obj, size, colorspace, ret_palette );\n}\n\nDFBResult\nICore_Real__ClipboardSet( CoreDFB    *obj,\n                          const char *mime_type,\n                          u32         mime_type_size,\n                          const char *data,\n                          u32         data_size,\n                          u64         timestamp_us )\n{\n     struct timeval tv;\n\n     D_DEBUG_AT( DirectFB_CoreDFB, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     tv.tv_sec  = timestamp_us / 1000000;\n     tv.tv_usec = timestamp_us % 1000000;\n\n     return dfb_clipboard_set( dfb_core_get_part( core_dfb, DFCP_CLIPBOARD ), mime_type, data, data_size, &tv );\n}\n\nDFBResult\nICore_Real__ClipboardGet( CoreDFB *obj,\n                          char    *ret_mime_type,\n                          u32     *ret_mime_type_size,\n                          char    *ret_data,\n                          u32     *ret_data_size )\n{\n     DFBResult     ret;\n     char         *mime_type;\n     void         *data;\n     unsigned int  data_size;\n\n     D_DEBUG_AT( DirectFB_CoreDFB, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     ret = dfb_clipboard_get( dfb_core_get_part( core_dfb, DFCP_CLIPBOARD ), &mime_type, &data, &data_size );\n     if (ret)\n          return ret;\n\n     direct_memcpy( ret_mime_type, mime_type, strlen( mime_type ) + 1 );\n     *ret_mime_type_size = strlen( mime_type ) + 1;\n\n     direct_memcpy( ret_data, data, data_size );\n     *ret_data_size = data_size;\n\n     D_FREE( data );\n     D_FREE( mime_type );\n\n     return DFB_OK;\n}\n\nDFBResult\nICore_Real__ClipboardGetTimestamp( CoreDFB *obj,\n                                   u64     *ret_timestamp_us )\n{\n     DFBResult      ret;\n     struct timeval tv;\n\n     D_DEBUG_AT( DirectFB_CoreDFB, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     ret = dfb_clipboard_get_timestamp( dfb_core_get_part( core_dfb, DFCP_CLIPBOARD ), &tv );\n     if (ret)\n          return ret;\n\n     *ret_timestamp_us = tv.tv_sec * 1000000 + tv.tv_usec;\n\n     return DFB_OK;\n}\n\nDFBResult\nICore_Real__WaitIdle( CoreDFB *obj )\n{\n     D_DEBUG_AT( DirectFB_CoreDFB, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreDFB );\n\n     return dfb_gfxcard_sync();\n}\n\nDFBResult\nICore_Real__GetSurface( CoreDFB      *obj,\n                        u32           surface_id,\n                        CoreSurface **ret_surface )\n{\n     DFBResult    ret;\n     CoreSurface *surface;\n     char         path[1000];\n     size_t       path_length;\n\n     D_DEBUG_AT( DirectFB_CoreDFB, \"%s( %p, %u )\\n\", __FUNCTION__, obj, surface_id );\n\n     D_MAGIC_ASSERT( obj, CoreDFB );\n\n     if (fusion_config->secure_fusion && dfb_config->ownership_check && !dfb_core_is_master( core_dfb )) {\n          ret = fusion_get_fusionee_path( dfb_core_world( core_dfb ), Core_GetIdentity(), path, sizeof(path),\n                                          &path_length );\n          if (ret)\n               return ret;\n\n          D_DEBUG_AT( DirectFB_CoreDFB, \"  -> '%s'\\n\", path );\n     }\n\n     ret = dfb_core_get_surface( core_dfb, surface_id, &surface );\n     if (ret) {\n          D_DEBUG_AT( DirectFB_CoreDFB, \"  -> dfb_core_get_surface() failed!\\n\" );\n          return ret;\n     }\n\n     if (fusion_config->secure_fusion && dfb_config->ownership_check && !dfb_core_is_master( core_dfb )) {\n          ret = fusion_object_has_access( &surface->object, path );\n          if (ret) {\n               D_DEBUG_AT( DirectFB_CoreDFB, \"  -> no access!\\n\" );\n               dfb_surface_unref( surface );\n               return ret;\n          }\n\n          fusion_object_add_owner( &surface->object, Core_GetIdentity() );\n     }\n\n     D_DEBUG_AT( DirectFB_CoreDFB, \"  -> surface %p\\n\", surface );\n\n     *ret_surface = surface;\n\n     return DFB_OK;\n}\n\nDFBResult\nICore_Real__AllowSurface( CoreDFB     *obj,\n                          CoreSurface *surface,\n                          const char  *executable,\n                          u32          executable_length )\n{\n     D_DEBUG_AT( DirectFB_CoreDFB, \"%s( %p, %p, '%s' )\\n\", __FUNCTION__, obj, surface, executable );\n\n     D_MAGIC_ASSERT( obj, CoreDFB );\n     D_ASSERT( surface != NULL );\n     D_ASSERT( executable != NULL );\n\n     return fusion_object_add_access( &surface->object, executable );\n}\n\nDFBResult\nICore_Real__CreateState( CoreDFB            *obj,\n                         CoreGraphicsState **ret_state )\n{\n     D_DEBUG_AT( DirectFB_CoreDFB, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreDFB );\n     D_ASSERT( ret_state != NULL );\n\n     return dfb_graphics_state_create( core_dfb, ret_state );\n}\n"
  },
  {
    "path": "src/core/CoreGraphicsState.flux",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\ninterface {\n        name    IGraphicsState\n        version 1.0\n        object  CoreGraphicsState\n\n        method {\n                name    SetDrawingFlags\n                async   yes\n                queue   yes\n\n                arg {\n                        name        flags\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceDrawingFlags\n                }\n        }\n\n        method {\n                name    SetBlittingFlags\n                async   yes\n                queue   yes\n\n                arg {\n                        name        flags\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceBlittingFlags\n                }\n        }\n\n        method {\n                name    SetClip\n                async   yes\n                queue   yes\n\n                arg {\n                        name        region\n                        direction   input\n                        type        struct\n                        typename    DFBRegion\n                }\n        }\n\n        method {\n                name    SetColor\n                async   yes\n                queue   yes\n\n                arg {\n                        name        color\n                        direction   input\n                        type        struct\n                        typename    DFBColor\n                }\n        }\n\n        method {\n                name    SetColorAndIndex\n                async   yes\n                queue   yes\n\n                arg {\n                        name        color\n                        direction   input\n                        type        struct\n                        typename    DFBColor\n                }\n\n                arg {\n                        name        index\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    SetSrcBlend\n                async   yes\n                queue   yes\n\n                arg {\n                        name        function\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceBlendFunction\n                }\n        }\n\n        method {\n                name    SetDstBlend\n                async   yes\n                queue   yes\n\n                arg {\n                        name        function\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceBlendFunction\n                }\n        }\n\n        method {\n                name    SetSrcColorKey\n                async   yes\n                queue   yes\n\n                arg {\n                        name        key\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    SetDstColorKey\n                async   yes\n                queue   yes\n\n                arg {\n                        name        key\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    SetDestination\n                async   yes\n                queue   yes\n\n                arg {\n                        name        surface\n                        direction   input\n                        type        object\n                        typename    CoreSurface\n                }\n        }\n\n        method {\n                name    SetSource\n                async   yes\n                queue   yes\n\n                arg {\n                        name        surface\n                        direction   input\n                        type        object\n                        typename    CoreSurface\n                }\n        }\n\n        method {\n                name    SetSourceMask\n                async   yes\n                queue   yes\n\n                arg {\n                        name        surface\n                        direction   input\n                        type        object\n                        typename    CoreSurface\n                }\n        }\n\n        method {\n                name    SetSourceMaskVals\n                async   yes\n                queue   yes\n\n                arg {\n                        name        offset\n                        direction   input\n                        type        struct\n                        typename    DFBPoint\n                }\n\n                arg {\n                        name        flags\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceMaskFlags\n                }\n        }\n\n        method {\n                name    SetIndexTranslation\n                async   yes\n                queue   yes\n\n                arg {\n                        name        indices\n                        direction   input\n                        type        struct\n                        typename    s32\n                        count       num\n                }\n\n                arg {\n                        name        num\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    SetColorKey\n                async   yes\n                queue   yes\n\n                arg {\n                        name        key\n                        direction   input\n                        type        struct\n                        typename    DFBColorKey\n                }\n        }\n\n        method {\n                name    SetRenderOptions\n                async   yes\n                queue   yes\n\n                arg {\n                        name        options\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceRenderOptions\n                }\n        }\n\n        method {\n                name    SetMatrix\n                async   yes\n                queue   yes\n\n                arg {\n                        name        values\n                        direction   input\n                        type        struct\n                        typename    s32\n                        count       9\n                }\n        }\n\n        method {\n                name    SetSource2\n                async   yes\n                queue   yes\n\n                arg {\n                        name        surface\n                        direction   input\n                        type        object\n                        typename    CoreSurface\n                }\n        }\n\n        method {\n                name    SetFrom\n                async   yes\n                queue   yes\n\n                arg {\n                        name        role\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceBufferRole\n                }\n\n                arg {\n                        name        eye\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceStereoEye\n                }\n        }\n\n        method {\n                name    SetTo\n                async   yes\n                queue   yes\n\n                arg {\n                        name        role\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceBufferRole\n                }\n\n                arg {\n                        name        eye\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceStereoEye\n                }\n        }\n\n        method {\n                name    FillRectangles\n                async   yes\n                queue   yes\n\n                arg {\n                        name        rects\n                        direction   input\n                        type        struct\n                        typename    DFBRectangle\n                        count       num\n                }\n\n                arg {\n                        name        num\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    DrawRectangles\n                async   yes\n                queue   yes\n\n                arg {\n                        name        rects\n                        direction   input\n                        type        struct\n                        typename    DFBRectangle\n                        count       num\n                }\n\n                arg {\n                        name        num\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    DrawLines\n                async   yes\n                queue   yes\n\n                arg {\n                        name        lines\n                        direction   input\n                        type        struct\n                        typename    DFBRegion\n                        count       num\n                }\n\n                arg {\n                        name        num\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    FillTriangles\n                async   yes\n                queue   yes\n\n                arg {\n                        name        triangles\n                        direction   input\n                        type        struct\n                        typename    DFBTriangle\n                        count       num\n                }\n\n                arg {\n                        name        num\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    FillTrapezoids\n                async   yes\n                queue   yes\n\n                arg {\n                        name        trapezoids\n                        direction   input\n                        type        struct\n                        typename    DFBTrapezoid\n                        count       num\n                }\n\n                arg {\n                        name        num\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    FillQuadrangles\n                async   yes\n                queue   yes\n\n                arg {\n                        name        quadrangles\n                        direction   input\n                        type        struct\n                        typename    DFBPoint\n                        count       num\n                }\n\n                arg {\n                        name        num\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    FillSpans\n                async   yes\n                queue   yes\n\n                arg {\n                        name        y\n                        direction   input\n                        type        int\n                        typename    s32\n                }\n\n                arg {\n                        name        spans\n                        direction   input\n                        type        struct\n                        typename    DFBSpan\n                        count       num\n                }\n\n                arg {\n                        name        num\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    Blit\n                async   yes\n                queue   yes\n\n                arg {\n                        name        rects\n                        direction   input\n                        type        struct\n                        typename    DFBRectangle\n                        count       num\n                }\n\n                arg {\n                        name        points\n                        direction   input\n                        type        struct\n                        typename    DFBPoint\n                        count       num\n                }\n\n                arg {\n                        name        num\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    Blit2\n                async   yes\n                queue   yes\n\n                arg {\n                        name        rects\n                        direction   input\n                        type        struct\n                        typename    DFBRectangle\n                        count       num\n                }\n\n                arg {\n                        name        points1\n                        direction   input\n                        type        struct\n                        typename    DFBPoint\n                        count       num\n                }\n\n                arg {\n                        name        points2\n                        direction   input\n                        type        struct\n                        typename    DFBPoint\n                        count       num\n                }\n\n                arg {\n                        name        num\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    StretchBlit\n                async   yes\n                queue   yes\n\n                arg {\n                        name        srects\n                        direction   input\n                        type        struct\n                        typename    DFBRectangle\n                        count       num\n                }\n\n                arg {\n                        name        drects\n                        direction   input\n                        type        struct\n                        typename    DFBRectangle\n                        count       num\n                }\n\n                arg {\n                        name        num\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    TileBlit\n                async   yes\n                queue   yes\n\n                arg {\n                        name        rects\n                        direction   input\n                        type        struct\n                        typename    DFBRectangle\n                        count       num\n                }\n\n                arg {\n                        name        points1\n                        direction   input\n                        type        struct\n                        typename    DFBPoint\n                        count       num\n                }\n\n                arg {\n                        name        points2\n                        direction   input\n                        type        struct\n                        typename    DFBPoint\n                        count       num\n                }\n\n                arg {\n                        name        num\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    TextureTriangles\n                async   yes\n                queue   yes\n\n                arg {\n                        name        vertices\n                        direction   input\n                        type        struct\n                        typename    DFBVertex\n                        count       num\n                }\n\n                arg {\n                        name        num\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        formation\n                        direction   input\n                        type        enum\n                        typename    DFBTriangleFormation\n                }\n        }\n\n        method {\n                name    Flush\n                async   yes\n        }\n\n        method {\n                name    ReleaseSource\n                async   yes\n                queue   yes\n        }\n\n        method {\n                name    SetSrcConvolution\n                async   yes\n                queue   yes\n\n                arg {\n                        name        filter\n                        direction   input\n                        type        struct\n                        typename    DFBConvolutionFilter\n                }\n        }\n\n        method {\n                name    GetAccelerationMask\n\n                arg {\n                        name        accel\n                        direction   output\n                        type        enum\n                        typename    DFBAccelerationMask\n                }\n        }\n}\n"
  },
  {
    "path": "src/core/CoreGraphicsStateClient.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreDFB.h>\n#include <core/CoreGraphicsState.h>\n#include <core/CoreGraphicsStateClient.h>\n#include <core/core.h>\n#include <core/graphics_state.h>\n#include <fusion/conf.h>\n\nD_DEBUG_DOMAIN(\n     Core_GraphicsStateClient,       \"Core/GfxState/Client\",       \"DirectFB Core Graphics State Client\" );\nD_DEBUG_DOMAIN(\n     Core_GraphicsStateClient_Flush, \"Core/GfxState/Client/Flush\", \"DirectFB Core Graphics State Client Flush\" );\n\n/**********************************************************************************************************************/\n\ntypedef struct clients_s {\n     CoreGraphicsStateClient *client;\n     struct clients_s *next;\n} clients_t;\n\nstatic clients_t  *clients_begin = NULL, *clients_end;\nstatic int         lock_init = 0;\nstatic DirectMutex lock;\n\nvoid\nAddClient( CoreGraphicsStateClient *client )\n{\n     if (!lock_init) {\n          direct_mutex_init( &lock );\n          lock_init = 1;\n     }\n\n     direct_mutex_lock( &lock );\n\n     clients_t *clients = D_CALLOC (1, sizeof(clients_t));\n     clients->client = client;\n     clients->next = NULL;\n     if (!clients_begin)\n          clients_begin = clients_end = clients;\n     else {\n          clients_end->next = clients;\n          clients_end = clients;\n     }\n\n     direct_mutex_unlock( &lock );\n}\n\nvoid\nRemoveClient( CoreGraphicsStateClient *client )\n{\n     direct_mutex_lock( &lock );\n\n     clients_t *clients = clients_begin;\n\n     if (clients->client == client) {\n          if (clients->next) {\n               clients_begin = clients->next;\n               D_FREE( clients );\n          }\n          else {\n               D_FREE( clients );\n               clients_begin = NULL;\n               direct_mutex_unlock( &lock );\n               direct_mutex_deinit( &lock );\n               lock_init = 0;\n               return;\n          }\n     }\n     else {\n          while (clients->next) {\n               if (clients->next->client == client) {\n                    clients_t *tmp_clients = clients;\n                    tmp_clients = clients->next;\n                    clients->next = tmp_clients->next;\n                    if (!tmp_clients->next)\n                         clients_end = clients;\n                    D_FREE( tmp_clients );\n                    break;\n               }\n               clients = clients->next;\n          }\n     }\n\n     direct_mutex_unlock( &lock );\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\nCoreGraphicsStateClient_Init( CoreGraphicsStateClient *client,\n                              CardState               *state )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_GraphicsStateClient, \"%s( %p, %p )\\n\", __FUNCTION__, client, state );\n\n     D_ASSERT( client != NULL );\n     D_MAGIC_ASSERT( state, CardState );\n     D_MAGIC_ASSERT( state->core, CoreDFB );\n\n     client->magic     = 0;\n     client->core      = state->core;\n     client->state     = state;\n     client->gfx_state = NULL;\n\n     ret = CoreDFB_CreateState( state->core, &client->gfx_state );\n     if (ret)\n          return ret;\n\n     D_DEBUG_AT( Core_GraphicsStateClient, \"  -> gfxstate id 0x%x\\n\",\n                 (unsigned int) client->gfx_state->object.ref.multi.id );\n\n     D_MAGIC_SET( client, CoreGraphicsStateClient );\n\n     AddClient( client );\n\n     /* Make legacy functions use state client. */\n     state->client = client;\n\n     return DFB_OK;\n}\n\nvoid\nCoreGraphicsStateClient_Deinit( CoreGraphicsStateClient *client )\n{\n     D_DEBUG_AT( Core_GraphicsStateClient, \"%s( %p )\\n\", __FUNCTION__, client );\n\n     D_DEBUG_AT( Core_GraphicsStateClient, \"  -> gfxstate id 0x%x\\n\",\n                 (unsigned int) client->gfx_state->object.ref.multi.id );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n\n     CoreGraphicsStateClient_Flush( client );\n\n     dfb_graphics_state_unref( client->gfx_state );\n\n     RemoveClient( client );\n\n     D_MAGIC_CLEAR( client );\n}\n\nvoid\nCoreGraphicsStateClient_Flush( CoreGraphicsStateClient *client )\n{\n     D_DEBUG_AT( Core_GraphicsStateClient_Flush, \"%s( %p )\\n\", __FUNCTION__, client );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n\n      if (!dfb_config->call_nodirect && (dfb_core_is_master( client->core ) || !fusion_config->secure_fusion)) {\n           dfb_gfxcard_flush();\n      }\n      else {\n           CoreGraphicsState_Flush( client->gfx_state );\n      }\n}\n\nDFBResult\nCoreGraphicsStateClient_ReleaseSource( CoreGraphicsStateClient *client )\n{\n     D_DEBUG_AT( Core_GraphicsStateClient, \"%s( %p )\\n\", __FUNCTION__, client );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n\n     CoreGraphicsState_ReleaseSource( client->gfx_state );\n\n     return DFB_OK;\n}\n\nDFBResult\nCoreGraphicsStateClient_SetColorAndIndex( CoreGraphicsStateClient *client,\n                                          const DFBColor          *color,\n                                          u32                      index )\n{\n     D_DEBUG_AT( Core_GraphicsStateClient, \"%s( %p )\\n\", __FUNCTION__, client );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n\n     CoreGraphicsState_SetColorAndIndex( client->gfx_state, color, index );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nCoreGraphicsStateClient_SetState( CoreGraphicsStateClient *client,\n                                  CardState               *state,\n                                  StateModificationFlags   flags )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_GraphicsStateClient, \"%s( %p, %p, flags 0x%08x )\\n\", __FUNCTION__, client, state, flags );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n     D_MAGIC_ASSERT( state, CardState );\n\n     if (flags & SMF_DRAWING_FLAGS) {\n          ret = CoreGraphicsState_SetDrawingFlags( client->gfx_state, state->drawingflags );\n          if (ret)\n               return ret;\n     }\n\n     if (flags & SMF_BLITTING_FLAGS) {\n          ret = CoreGraphicsState_SetBlittingFlags( client->gfx_state, state->blittingflags );\n          if (ret)\n               return ret;\n     }\n\n     if (flags & SMF_CLIP) {\n          ret = CoreGraphicsState_SetClip( client->gfx_state, &state->clip );\n          if (ret)\n               return ret;\n     }\n\n     if (flags & SMF_COLOR) {\n          ret = CoreGraphicsState_SetColor( client->gfx_state, &state->color );\n          if (ret)\n               return ret;\n     }\n\n     if (flags & SMF_SRC_BLEND) {\n          ret = CoreGraphicsState_SetSrcBlend( client->gfx_state, state->src_blend );\n          if (ret)\n               return ret;\n     }\n\n     if (flags & SMF_DST_BLEND) {\n          ret = CoreGraphicsState_SetDstBlend( client->gfx_state, state->dst_blend );\n          if (ret)\n               return ret;\n     }\n\n     if (flags & SMF_SRC_COLORKEY) {\n          ret = CoreGraphicsState_SetSrcColorKey( client->gfx_state, state->src_colorkey );\n          if (ret)\n               return ret;\n     }\n\n     if (flags & SMF_DST_COLORKEY) {\n          ret = CoreGraphicsState_SetDstColorKey( client->gfx_state, state->dst_colorkey );\n          if (ret)\n               return ret;\n     }\n\n     if (flags & SMF_DESTINATION) {\n          D_DEBUG_AT( Core_GraphicsStateClient, \"  -> destination %p [%u]\\n\",\n                      state->destination, state->destination->object.id );\n\n          ret = CoreGraphicsState_SetDestination( client->gfx_state, state->destination );\n          if (ret)\n               return ret;\n     }\n\n     if (flags & SMF_SOURCE) {\n          ret = CoreGraphicsState_SetSource( client->gfx_state, state->source );\n          if (ret)\n               return ret;\n     }\n\n     if (flags & SMF_SOURCE_MASK) {\n          ret = CoreGraphicsState_SetSourceMask( client->gfx_state, state->source_mask );\n          if (ret)\n               return ret;\n     }\n\n     if (flags & SMF_SOURCE_MASK_VALS) {\n          ret = CoreGraphicsState_SetSourceMaskVals( client->gfx_state, &state->src_mask_offset,\n                                                     state->src_mask_flags );\n          if (ret)\n               return ret;\n     }\n\n     if (flags & SMF_INDEX_TRANSLATION) {\n          ret = CoreGraphicsState_SetIndexTranslation( client->gfx_state, state->index_translation,\n                                                       state->num_translation );\n          if (ret)\n               return ret;\n     }\n\n     if (flags & SMF_COLORKEY) {\n          ret = CoreGraphicsState_SetColorKey( client->gfx_state, &state->colorkey );\n          if (ret)\n               return ret;\n     }\n\n     if (flags & SMF_RENDER_OPTIONS) {\n          ret = CoreGraphicsState_SetRenderOptions( client->gfx_state, state->render_options );\n          if (ret)\n               return ret;\n     }\n\n     if (flags & SMF_MATRIX) {\n          ret = CoreGraphicsState_SetMatrix( client->gfx_state, state->matrix );\n          if (ret)\n               return ret;\n     }\n\n     if (flags & SMF_SOURCE2) {\n          ret = CoreGraphicsState_SetSource2( client->gfx_state, state->source2 );\n          if (ret)\n               return ret;\n     }\n\n     if (flags & SMF_FROM) {\n          ret = CoreGraphicsState_SetFrom( client->gfx_state, state->from, state->from_eye );\n          if (ret)\n               return ret;\n     }\n\n     if (flags & SMF_TO) {\n          ret = CoreGraphicsState_SetTo( client->gfx_state, state->to, state->to_eye );\n          if (ret)\n               return ret;\n     }\n\n     if (flags & SMF_SRC_CONVOLUTION) {\n          ret = CoreGraphicsState_SetSrcConvolution( client->gfx_state, &state->src_convolution );\n          if (ret)\n               return ret;\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nCoreGraphicsStateClient_Update( CoreGraphicsStateClient *client,\n                                DFBAccelerationMask      accel,\n                                CardState               *state )\n{\n     DFBResult              ret;\n     StateModificationFlags flags = SMF_TO | SMF_DESTINATION | SMF_CLIP | SMF_RENDER_OPTIONS;\n\n     D_DEBUG_AT( Core_GraphicsStateClient, \"%s( %p )\\n\", __FUNCTION__, client );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( state->mod_hw == SMF_NONE );\n\n     if (state->render_options & DSRO_MATRIX)\n          flags |= SMF_MATRIX;\n\n     if (DFB_DRAWING_FUNCTION( accel )) {\n          flags |= SMF_DRAWING_FLAGS | SMF_COLOR;\n\n          if (state->drawingflags & DSDRAW_BLEND)\n               flags |= SMF_SRC_BLEND | SMF_DST_BLEND;\n\n          if (state->drawingflags & DSDRAW_DST_COLORKEY)\n               flags |= SMF_DST_COLORKEY;\n     }\n     else {\n          flags |= SMF_BLITTING_FLAGS | SMF_FROM | SMF_SOURCE;\n\n          if (accel == DFXL_BLIT2)\n               flags |= SMF_FROM | SMF_SOURCE2;\n\n          if (state->blittingflags & (DSBLIT_BLEND_COLORALPHA | DSBLIT_COLORIZE | DSBLIT_SRC_PREMULTCOLOR))\n               flags |= SMF_COLOR;\n\n          if (state->blittingflags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA))\n               flags |= SMF_SRC_BLEND | SMF_DST_BLEND;\n\n          if (state->blittingflags & DSBLIT_SRC_COLORKEY)\n               flags |= SMF_SRC_COLORKEY;\n\n          if (state->blittingflags & DSBLIT_DST_COLORKEY)\n               flags |= SMF_DST_COLORKEY;\n\n          if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR))\n               flags |= SMF_FROM | SMF_SOURCE_MASK | SMF_SOURCE_MASK_VALS;\n\n          if (state->blittingflags & DSBLIT_INDEX_TRANSLATION)\n               flags |= SMF_INDEX_TRANSLATION;\n\n          if (state->blittingflags & DSBLIT_COLORKEY_PROTECT)\n               flags |= SMF_COLORKEY;\n\n          if (state->blittingflags & DSBLIT_SRC_CONVOLUTION)\n               flags |= SMF_SRC_CONVOLUTION;\n     }\n\n     ret = CoreGraphicsStateClient_SetState( client, state, state->modified & flags );\n     if (ret)\n          return ret;\n\n     state->modified = state->modified & ~flags;\n\n     return DFB_OK;\n}\n\nDFBResult\nCoreGraphicsStateClient_GetAccelerationMask( CoreGraphicsStateClient *client,\n                                             DFBAccelerationMask     *ret_accel )\n{\n     D_DEBUG_AT( Core_GraphicsStateClient, \"%s( %p )\\n\", __FUNCTION__, client );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n     D_ASSERT( ret_accel != NULL );\n\n     if (!dfb_config->call_nodirect && (dfb_core_is_master( client->core ) || !fusion_config->secure_fusion)) {\n          return dfb_state_get_acceleration_mask( client->state, ret_accel );\n     }\n     else {\n          DFBResult ret;\n\n          CoreGraphicsStateClient_Update( client, client->state->source ?\n                                          (client->state->source2 ? DFXL_BLIT2 : DFXL_BLIT) : DFXL_FILLRECTANGLE,\n                                          client->state );\n\n          ret = CoreGraphicsState_GetAccelerationMask( client->gfx_state, ret_accel );\n          if (ret)\n               return ret;\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nCoreGraphicsStateClient_FillRectangles( CoreGraphicsStateClient *client,\n                                        const DFBRectangle      *rects,\n                                        unsigned int             num )\n{\n     D_DEBUG_AT( Core_GraphicsStateClient, \"%s( %p )\\n\", __FUNCTION__, client );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n     D_ASSERT( rects != NULL );\n\n     if (!dfb_config->call_nodirect && (dfb_core_is_master( client->core ) || !fusion_config->secure_fusion)) {\n          dfb_gfxcard_fillrectangles( (DFBRectangle*) rects, num, client->state );\n     }\n     else {\n          DFBResult ret;\n\n          CoreGraphicsStateClient_Update( client, DFXL_FILLRECTANGLE, client->state );\n\n          ret = CoreGraphicsState_FillRectangles( client->gfx_state, rects, num );\n          if (ret)\n               return ret;\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nCoreGraphicsStateClient_DrawRectangles( CoreGraphicsStateClient *client,\n                                        const DFBRectangle      *rects,\n                                        unsigned int             num )\n{\n     D_DEBUG_AT( Core_GraphicsStateClient, \"%s( %p )\\n\", __FUNCTION__, client );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n     D_ASSERT( rects != NULL );\n\n     if (!dfb_config->call_nodirect && (dfb_core_is_master( client->core ) || !fusion_config->secure_fusion)) {\n          unsigned int i;\n\n          for (i = 0; i < num; i++)\n               dfb_gfxcard_drawrectangle( (DFBRectangle*) &rects[i], client->state );\n     }\n     else {\n          DFBResult ret;\n\n          CoreGraphicsStateClient_Update( client, DFXL_DRAWRECTANGLE, client->state );\n\n          ret = CoreGraphicsState_DrawRectangles( client->gfx_state, rects, num );\n          if (ret)\n               return ret;\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nCoreGraphicsStateClient_DrawLines( CoreGraphicsStateClient *client,\n                                   const DFBRegion         *lines,\n                                   unsigned int             num )\n{\n     D_DEBUG_AT( Core_GraphicsStateClient, \"%s( %p )\\n\", __FUNCTION__, client );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n     D_ASSERT( lines != NULL );\n\n     if (!dfb_config->call_nodirect && (dfb_core_is_master( client->core ) || !fusion_config->secure_fusion)) {\n          dfb_gfxcard_drawlines( (DFBRegion*) lines, num, client->state );\n     }\n     else {\n          DFBResult ret;\n\n          CoreGraphicsStateClient_Update( client, DFXL_DRAWLINE, client->state );\n\n          ret = CoreGraphicsState_DrawLines( client->gfx_state, lines, num );\n          if (ret)\n               return ret;\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nCoreGraphicsStateClient_FillTriangles( CoreGraphicsStateClient *client,\n                                       const DFBTriangle       *triangles,\n                                       unsigned int             num )\n{\n     D_DEBUG_AT( Core_GraphicsStateClient, \"%s( %p )\\n\", __FUNCTION__, client );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n     D_ASSERT( triangles != NULL );\n\n     if (!dfb_config->call_nodirect && (dfb_core_is_master( client->core ) || !fusion_config->secure_fusion)) {\n          dfb_gfxcard_filltriangles( (DFBTriangle*) triangles, num, client->state );\n     }\n     else {\n          DFBResult ret;\n\n          CoreGraphicsStateClient_Update( client, DFXL_FILLTRIANGLE, client->state );\n\n          ret = CoreGraphicsState_FillTriangles( client->gfx_state, triangles, num );\n          if (ret)\n               return ret;\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nCoreGraphicsStateClient_FillTrapezoids( CoreGraphicsStateClient *client,\n                                        const DFBTrapezoid      *trapezoids,\n                                        unsigned int             num )\n{\n     D_DEBUG_AT( Core_GraphicsStateClient, \"%s( %p )\\n\", __FUNCTION__, client );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n     D_ASSERT( trapezoids != NULL );\n\n     if (!dfb_config->call_nodirect && (dfb_core_is_master( client->core ) || !fusion_config->secure_fusion)) {\n          dfb_gfxcard_filltrapezoids( (DFBTrapezoid*) trapezoids, num, client->state );\n     }\n     else {\n          DFBResult ret;\n\n          CoreGraphicsStateClient_Update( client, DFXL_FILLTRAPEZOID, client->state );\n\n          ret = CoreGraphicsState_FillTrapezoids( client->gfx_state, trapezoids, num );\n          if (ret)\n               return ret;\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nCoreGraphicsStateClient_FillQuadrangles( CoreGraphicsStateClient *client,\n                                         const DFBPoint          *points,\n                                         unsigned int             num )\n{\n     D_DEBUG_AT( Core_GraphicsStateClient, \"%s( %p )\\n\", __FUNCTION__, client );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n     D_ASSERT( points != NULL );\n\n     if (!dfb_config->call_nodirect && (dfb_core_is_master( client->core ) || !fusion_config->secure_fusion)) {\n          dfb_gfxcard_fillquadrangles( (DFBPoint*) points, num, client->state );\n     }\n     else {\n          DFBResult ret;\n\n          CoreGraphicsStateClient_Update( client, DFXL_FILLQUADRANGLE, client->state );\n\n          ret = CoreGraphicsState_FillQuadrangles( client->gfx_state, points, num );\n          if (ret)\n               return ret;\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nCoreGraphicsStateClient_FillSpans( CoreGraphicsStateClient *client,\n                                   int                      y,\n                                   const DFBSpan           *spans,\n                                   unsigned int             num )\n{\n     D_DEBUG_AT( Core_GraphicsStateClient, \"%s( %p )\\n\", __FUNCTION__, client );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n     D_ASSERT( spans != NULL );\n\n     if (!dfb_config->call_nodirect && (dfb_core_is_master( client->core ) || !fusion_config->secure_fusion)) {\n          dfb_gfxcard_fillspans( y, (DFBSpan*) spans, num, client->state );\n     }\n     else {\n          DFBResult ret;\n\n          CoreGraphicsStateClient_Update( client, DFXL_FILLRECTANGLE, client->state );\n\n          ret = CoreGraphicsState_FillSpans( client->gfx_state, y, spans, num );\n          if (ret)\n               return ret;\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nCoreGraphicsStateClient_Blit( CoreGraphicsStateClient *client,\n                              const DFBRectangle      *rects,\n                              const DFBPoint          *points,\n                              unsigned int             num )\n{\n     D_DEBUG_AT( Core_GraphicsStateClient, \"%s( %p )\\n\", __FUNCTION__, client );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n     D_ASSERT( rects != NULL );\n     D_ASSERT( points != NULL );\n\n     if (!dfb_config->call_nodirect && (dfb_core_is_master( client->core ) || !fusion_config->secure_fusion)) {\n          dfb_gfxcard_batchblit( (DFBRectangle*) rects, (DFBPoint*) points, num, client->state );\n     }\n     else {\n          DFBResult    ret;\n          unsigned int i;\n\n          CoreGraphicsStateClient_Update( client, DFXL_BLIT, client->state );\n\n          for (i = 0; i < num; i += 200) {\n               ret = CoreGraphicsState_Blit( client->gfx_state, &rects[i], &points[i], MIN( 200, num - i ) );\n               if (ret)\n                    return ret;\n          }\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nCoreGraphicsStateClient_Blit2( CoreGraphicsStateClient *client,\n                               const DFBRectangle      *rects,\n                               const DFBPoint          *points1,\n                               const DFBPoint          *points2,\n                               unsigned int             num )\n{\n     D_DEBUG_AT( Core_GraphicsStateClient, \"%s( %p )\\n\", __FUNCTION__, client );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n     D_ASSERT( rects != NULL );\n     D_ASSERT( points1 != NULL );\n     D_ASSERT( points2 != NULL );\n\n     if (!dfb_config->call_nodirect && (dfb_core_is_master( client->core ) || !fusion_config->secure_fusion)) {\n          dfb_gfxcard_batchblit2( (DFBRectangle*) rects, (DFBPoint*) points1, (DFBPoint*) points2, num, client->state );\n     }\n     else {\n          DFBResult ret;\n\n          CoreGraphicsStateClient_Update( client, DFXL_BLIT2, client->state );\n\n          ret = CoreGraphicsState_Blit2( client->gfx_state, rects, points1, points2, num );\n          if (ret)\n               return ret;\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nCoreGraphicsStateClient_StretchBlit( CoreGraphicsStateClient *client,\n                                     const DFBRectangle      *srects,\n                                     const DFBRectangle      *drects,\n                                     unsigned int             num )\n{\n     D_DEBUG_AT( Core_GraphicsStateClient, \"%s( %p ) <- source buffer %p\\n\", __FUNCTION__,\n                 client, client->state->source_buffer );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n     D_ASSERT( srects != NULL );\n     D_ASSERT( drects != NULL );\n\n     if (num == 0)\n          return DFB_OK;\n\n     if (!dfb_config->call_nodirect && (dfb_core_is_master( client->core ) || !fusion_config->secure_fusion)) {\n          if (num == 1 && srects[0].w == drects[0].w && srects[0].h == drects[0].h) {\n               DFBPoint point = { drects[0].x, drects[0].y };\n\n               D_DEBUG_AT( Core_GraphicsStateClient, \"  -> %4d,%4d => %4d,%4d-%4dx%4d\\n\",\n                           srects[0].x, srects[0].y, drects[0].x, drects[0].x, drects[0].w, drects[0].h );\n\n               dfb_gfxcard_batchblit( (DFBRectangle*) srects, &point, 1, client->state );\n          }\n          else {\n               dfb_gfxcard_batchstretchblit( (DFBRectangle*) srects, (DFBRectangle*) drects, num, client->state );\n          }\n     }\n     else {\n          DFBResult ret;\n\n          if (num == 1 && srects[0].w == drects[0].w && srects[0].h == drects[0].h) {\n               CoreGraphicsStateClient_Update( client, DFXL_BLIT, client->state );\n\n               DFBPoint point = { drects[0].x, drects[0].y };\n               ret = CoreGraphicsState_Blit( client->gfx_state, srects, &point, 1 );\n               if (ret)\n                    return ret;\n          }\n          else {\n               CoreGraphicsStateClient_Update( client, DFXL_STRETCHBLIT, client->state );\n\n               ret = CoreGraphicsState_StretchBlit( client->gfx_state, srects, drects, num );\n               if (ret)\n                    return ret;\n          }\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nCoreGraphicsStateClient_TileBlit( CoreGraphicsStateClient *client,\n                                  const DFBRectangle      *rects,\n                                  const DFBPoint          *points1,\n                                  const DFBPoint          *points2,\n                                  unsigned int             num )\n{\n     D_DEBUG_AT( Core_GraphicsStateClient, \"%s( %p )\\n\", __FUNCTION__, client );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n     D_ASSERT( rects != NULL );\n     D_ASSERT( points1 != NULL );\n     D_ASSERT( points2 != NULL );\n\n     if (!dfb_config->call_nodirect && (dfb_core_is_master( client->core ) || !fusion_config->secure_fusion)) {\n          u32 i;\n\n          for (i = 0; i < num; i++)\n               dfb_gfxcard_tileblit( (DFBRectangle*) &rects[i], points1[i].x, points1[i].y, points2[i].x, points2[i].y,\n                                     client->state );\n     }\n     else {\n          DFBResult ret;\n\n          CoreGraphicsStateClient_Update( client, DFXL_BLIT, client->state );\n\n          ret = CoreGraphicsState_TileBlit( client->gfx_state, rects, points1, points2, num );\n          if (ret)\n               return ret;\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nCoreGraphicsStateClient_TextureTriangles( CoreGraphicsStateClient *client,\n                                          const DFBVertex         *vertices,\n                                          int                      num,\n                                          DFBTriangleFormation     formation )\n{\n     D_DEBUG_AT( Core_GraphicsStateClient, \"%s( %p )\\n\", __FUNCTION__, client );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n     D_ASSERT( vertices != NULL );\n\n     if (!dfb_config->call_nodirect && (dfb_core_is_master( client->core ) || !fusion_config->secure_fusion)) {\n          dfb_gfxcard_texture_triangles( (DFBVertex*) vertices, num, formation, client->state );\n     }\n     else {\n          DFBResult ret;\n\n          CoreGraphicsStateClient_Update( client, DFXL_TEXTRIANGLES, client->state );\n\n          ret = CoreGraphicsState_TextureTriangles( client->gfx_state, vertices, num, formation );\n          if (ret)\n               return ret;\n     }\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/core/CoreGraphicsStateClient.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__CORE_GRAPHICS_STATE_CLIENT_H__\n#define __CORE__CORE_GRAPHICS_STATE_CLIENT_H__\n\n#include <core/coretypes.h>\n\n/**********************************************************************************************************************/\n\nstruct __DFB_CoreGraphicsStateClient {\n     int                magic;\n\n     void              *priv;\n\n     CoreDFB           *core;\n     CardState         *state;     /* Local state structure. */\n\n     CoreGraphicsState *gfx_state; /* Remote object for rendering, syncing values from local state as needed. */\n};\n\n/**********************************************************************************************************************/\n\nDFBResult CoreGraphicsStateClient_Init               ( CoreGraphicsStateClient *client,\n                                                       CardState               *state );\n\nvoid      CoreGraphicsStateClient_Deinit             ( CoreGraphicsStateClient *client );\n\nvoid      CoreGraphicsStateClient_Flush              ( CoreGraphicsStateClient *client );\n\nDFBResult CoreGraphicsStateClient_ReleaseSource      ( CoreGraphicsStateClient *client );\n\nDFBResult CoreGraphicsStateClient_SetColorAndIndex   ( CoreGraphicsStateClient *client,\n                                                       const DFBColor          *color,\n                                                       u32                      index );\n\nDFBResult CoreGraphicsStateClient_Update             ( CoreGraphicsStateClient *client,\n                                                       DFBAccelerationMask      accel,\n                                                       CardState               *state );\n\nDFBResult CoreGraphicsStateClient_GetAccelerationMask( CoreGraphicsStateClient *client,\n                                                       DFBAccelerationMask     *ret_accel );\n\nDFBResult CoreGraphicsStateClient_FillRectangles     ( CoreGraphicsStateClient *client,\n                                                       const DFBRectangle      *rects,\n                                                       unsigned int             num );\n\nDFBResult CoreGraphicsStateClient_DrawRectangles     ( CoreGraphicsStateClient *client,\n                                                       const DFBRectangle      *rects,\n                                                       unsigned int             num );\n\nDFBResult CoreGraphicsStateClient_DrawLines          ( CoreGraphicsStateClient *client,\n                                                       const DFBRegion         *lines,\n                                                       unsigned int             num );\n\nDFBResult CoreGraphicsStateClient_FillTriangles      ( CoreGraphicsStateClient *client,\n                                                       const DFBTriangle       *triangles,\n                                                       unsigned int             num );\n\nDFBResult CoreGraphicsStateClient_FillTrapezoids     ( CoreGraphicsStateClient *client,\n                                                       const DFBTrapezoid      *trapezoids,\n                                                       unsigned int             num );\n\nDFBResult CoreGraphicsStateClient_FillQuadrangles    ( CoreGraphicsStateClient *client,\n                                                       const DFBPoint          *points,\n                                                       unsigned int             num );\n\nDFBResult CoreGraphicsStateClient_FillSpans          ( CoreGraphicsStateClient *client,\n                                                       int                      y,\n                                                       const DFBSpan           *spans,\n                                                       unsigned int             num );\n\nDFBResult CoreGraphicsStateClient_Blit               ( CoreGraphicsStateClient *client,\n                                                       const DFBRectangle      *rects,\n                                                       const DFBPoint          *points,\n                                                       unsigned int             num );\n\nDFBResult CoreGraphicsStateClient_Blit2              ( CoreGraphicsStateClient *client,\n                                                       const DFBRectangle      *rects,\n                                                       const DFBPoint          *points1,\n                                                       const DFBPoint          *points2,\n                                                       unsigned int             num );\n\nDFBResult CoreGraphicsStateClient_StretchBlit        ( CoreGraphicsStateClient *client,\n                                                       const DFBRectangle      *srects,\n                                                       const DFBRectangle      *drects,\n                                                       unsigned int             num );\n\nDFBResult CoreGraphicsStateClient_TileBlit           ( CoreGraphicsStateClient *client,\n                                                       const DFBRectangle      *rects,\n                                                       const DFBPoint          *points1,\n                                                       const DFBPoint          *points2,\n                                                       unsigned int             num );\n\nDFBResult CoreGraphicsStateClient_TextureTriangles   ( CoreGraphicsStateClient *client,\n                                                       const DFBVertex         *vertices,\n                                                       int                      num,\n                                                       DFBTriangleFormation     formation );\n\n#endif\n"
  },
  {
    "path": "src/core/CoreGraphicsState_includes.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreDFB_includes.h>\n\nstatic __inline__ DirectResult\nCoreGraphicsState_Call( CoreGraphicsState   *state,\n                        FusionCallExecFlags  flags,\n                        int                  call_arg,\n                        void                *ptr,\n                        unsigned int         length,\n                        void                *ret_ptr,\n                        unsigned int         ret_size,\n                        unsigned int        *ret_length )\n{\n     return fusion_call_execute3( &state->call, dfb_config->call_nodirect | flags, call_arg, ptr, length,\n                                  ret_ptr, ret_size, ret_length );\n}\n"
  },
  {
    "path": "src/core/CoreGraphicsState_real.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreGraphicsState.h>\n#include <core/graphics_state.h>\n\nD_DEBUG_DOMAIN( DirectFB_CoreGraphicsState, \"DirectFB/CoreGraphicsState\", \"DirectFB CoreGraphicsState\" );\n\n/**********************************************************************************************************************/\n\nDFBResult\nIGraphicsState_Real__SetDrawingFlags( CoreGraphicsState      *obj,\n                                      DFBSurfaceDrawingFlags  flags )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     dfb_state_set_drawing_flags( &obj->state, flags );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetBlittingFlags( CoreGraphicsState       *obj,\n                                       DFBSurfaceBlittingFlags  flags )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     dfb_state_set_blitting_flags( &obj->state, flags );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetClip( CoreGraphicsState *obj,\n                              const DFBRegion   *region )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( region != NULL );\n\n     dfb_state_set_clip( &obj->state, region );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetColor( CoreGraphicsState *obj,\n                               const DFBColor    *color )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( color != NULL );\n\n     dfb_state_set_color( &obj->state, color );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetColorAndIndex( CoreGraphicsState *obj,\n                                       const DFBColor    *color,\n                                       u32                index )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( color != NULL );\n\n     dfb_state_set_color( &obj->state, color );\n     dfb_state_set_color_index( &obj->state, index );\n\n     obj->state.colors[0]        = *color;\n     obj->state.color_indices[0] = index;\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetSrcBlend( CoreGraphicsState       *obj,\n                                  DFBSurfaceBlendFunction  function )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     dfb_state_set_src_blend( &obj->state, function );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetDstBlend( CoreGraphicsState       *obj,\n                                  DFBSurfaceBlendFunction  function )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     dfb_state_set_dst_blend( &obj->state, function );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetSrcColorKey( CoreGraphicsState *obj,\n                                     u32                key )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     dfb_state_set_src_colorkey( &obj->state, key );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetDstColorKey( CoreGraphicsState *obj,\n                                     u32                key )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     dfb_state_set_dst_colorkey( &obj->state, key );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetDestination( CoreGraphicsState *obj,\n                                     CoreSurface       *surface )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( surface != NULL );\n\n     dfb_state_set_destination( &obj->state, surface );\n\n     obj->state.modified |= SMF_DESTINATION;\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetSource( CoreGraphicsState *obj,\n                                CoreSurface       *surface )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( surface != NULL );\n\n     dfb_state_set_source( &obj->state, surface );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetSourceMask( CoreGraphicsState *obj,\n                                    CoreSurface       *surface )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( surface != NULL );\n\n     dfb_state_set_source_mask( &obj->state, surface );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetSourceMaskVals( CoreGraphicsState   *obj,\n                                        const DFBPoint      *offset,\n                                        DFBSurfaceMaskFlags  flags )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( offset != NULL );\n\n     dfb_state_set_source_mask_vals( &obj->state, offset, flags );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetIndexTranslation( CoreGraphicsState *obj,\n                                          const s32         *indices,\n                                          u32                num )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     dfb_state_set_index_translation( &obj->state, indices, num );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetColorKey( CoreGraphicsState *obj,\n                                  const DFBColorKey *key )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( key != NULL );\n\n     dfb_state_set_colorkey( &obj->state, key );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetRenderOptions( CoreGraphicsState       *obj,\n                                       DFBSurfaceRenderOptions  options )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     dfb_state_set_render_options( &obj->state, options );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetMatrix( CoreGraphicsState *obj,\n                                const s32         *values )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     dfb_state_set_matrix( &obj->state, values );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetSource2( CoreGraphicsState *obj,\n                                 CoreSurface       *surface )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( surface != NULL );\n\n     dfb_state_set_source2( &obj->state, surface );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetFrom( CoreGraphicsState    *obj,\n                              DFBSurfaceBufferRole  role,\n                              DFBSurfaceStereoEye   eye )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p, %u, %u )\\n\", __FUNCTION__, obj, role, eye );\n\n     dfb_state_set_from( &obj->state, role, eye );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetTo( CoreGraphicsState    *obj,\n                            DFBSurfaceBufferRole  role,\n                            DFBSurfaceStereoEye   eye )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p, %u, %u )\\n\", __FUNCTION__, obj, role, eye );\n\n     dfb_state_set_to( &obj->state, role, eye );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__FillRectangles( CoreGraphicsState  *obj,\n                                     const DFBRectangle *rects,\n                                     u32                 num )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     if (!obj->state.destination)\n          return DFB_NOCONTEXT;\n\n     dfb_gfxcard_fillrectangles( (DFBRectangle*) rects, num, &obj->state );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__DrawRectangles( CoreGraphicsState  *obj,\n                                     const DFBRectangle *rects,\n                                     u32                 num )\n{\n     u32 i;\n\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     if (!obj->state.destination)\n          return DFB_NOCONTEXT;\n\n     for (i = 0; i < num; i++)\n          dfb_gfxcard_drawrectangle( (DFBRectangle*) &rects[i], &obj->state );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__DrawLines( CoreGraphicsState *obj,\n                                const DFBRegion   *lines,\n                                u32                num )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     if (!obj->state.destination)\n          return DFB_NOCONTEXT;\n\n     dfb_gfxcard_drawlines( (DFBRegion*) lines, num, &obj->state );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__FillTriangles( CoreGraphicsState *obj,\n                                    const DFBTriangle *triangles,\n                                    u32                num )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     if (!obj->state.destination)\n          return DFB_NOCONTEXT;\n\n     dfb_gfxcard_filltriangles( (DFBTriangle*) triangles, num, &obj->state );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__FillTrapezoids( CoreGraphicsState  *obj,\n                                     const DFBTrapezoid *trapezoids,\n                                     u32                 num )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     if (!obj->state.destination)\n          return DFB_NOCONTEXT;\n\n     dfb_gfxcard_filltrapezoids( (DFBTrapezoid*) trapezoids, num, &obj->state );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__FillQuadrangles( CoreGraphicsState *obj,\n                                      const DFBPoint    *points,\n                                      u32                num )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     if (!obj->state.destination)\n          return DFB_NOCONTEXT;\n\n     dfb_gfxcard_fillquadrangles( (DFBPoint*) points, num, &obj->state );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__FillSpans( CoreGraphicsState *obj,\n                                s32                y,\n                                const DFBSpan     *spans,\n                                u32                num )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     if (!obj->state.destination)\n          return DFB_NOCONTEXT;\n\n     dfb_gfxcard_fillspans( y, (DFBSpan*) spans, num, &obj->state );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__Blit( CoreGraphicsState  *obj,\n                           const DFBRectangle *rects,\n                           const DFBPoint     *points,\n                           u32                 num )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     if (!obj->state.destination || !obj->state.source)\n          return DFB_NOCONTEXT;\n\n     if ((obj->state.blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) && !obj->state.source_mask)\n          return DFB_NOCONTEXT;\n\n     D_ASSERT( rects != NULL );\n     D_ASSERT( points != NULL );\n\n     dfb_gfxcard_batchblit( (DFBRectangle*) rects, (DFBPoint*) points, num, &obj->state );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__Blit2( CoreGraphicsState  *obj,\n                            const DFBRectangle *rects,\n                            const DFBPoint     *points1,\n                            const DFBPoint     *points2,\n                            u32                 num )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     if (!obj->state.destination || !obj->state.source || !obj->state.source2)\n          return DFB_NOCONTEXT;\n\n     if ((obj->state.blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) && !obj->state.source_mask)\n          return DFB_NOCONTEXT;\n\n     D_ASSERT( rects != NULL );\n     D_ASSERT( points1 != NULL );\n     D_ASSERT( points2 != NULL );\n\n     dfb_gfxcard_batchblit2( (DFBRectangle*) rects, (DFBPoint*) points1, (DFBPoint*) points2, num, &obj->state );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__StretchBlit( CoreGraphicsState  *obj,\n                                  const DFBRectangle *srects,\n                                  const DFBRectangle *drects,\n                                  u32                 num )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     if (!obj->state.destination || !obj->state.source)\n          return DFB_NOCONTEXT;\n\n     if ((obj->state.blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) && !obj->state.source_mask)\n          return DFB_NOCONTEXT;\n\n     D_ASSERT( srects != NULL );\n     D_ASSERT( drects != NULL );\n\n     dfb_gfxcard_batchstretchblit( (DFBRectangle*) srects, (DFBRectangle*) drects, num, &obj->state );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__TileBlit( CoreGraphicsState  *obj,\n                               const DFBRectangle *rects,\n                               const DFBPoint     *points1,\n                               const DFBPoint     *points2,\n                               u32                 num )\n{\n     u32 i;\n\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     if (!obj->state.destination || !obj->state.source)\n          return DFB_NOCONTEXT;\n\n     if ((obj->state.blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) && !obj->state.source_mask)\n          return DFB_NOCONTEXT;\n\n     D_ASSERT( rects != NULL );\n     D_ASSERT( points1 != NULL );\n     D_ASSERT( points2 != NULL );\n\n     for (i = 0; i < num; i++)\n          dfb_gfxcard_tileblit( (DFBRectangle*) &rects[i], points1[i].x, points1[i].y, points2[i].x, points2[i].y,\n                                &obj->state );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__TextureTriangles( CoreGraphicsState    *obj,\n                                       const DFBVertex      *vertices,\n                                       u32                   num,\n                                       DFBTriangleFormation  formation )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     if (!obj->state.destination || !obj->state.source)\n          return DFB_NOCONTEXT;\n\n     if ((obj->state.blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) && !obj->state.source_mask)\n          return DFB_NOCONTEXT;\n\n     D_ASSERT( vertices != NULL );\n\n     dfb_gfxcard_texture_triangles( (DFBVertex*) vertices, num, formation, &obj->state );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__Flush( CoreGraphicsState *obj )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     dfb_gfxcard_flush();\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__ReleaseSource( CoreGraphicsState *obj )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     dfb_state_set_source( &obj->state, NULL );\n     dfb_state_set_source_mask( &obj->state, NULL );\n     dfb_state_set_source2( &obj->state, NULL );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__SetSrcConvolution( CoreGraphicsState          *obj,\n                                        const DFBConvolutionFilter *filter )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( filter != NULL );\n\n     dfb_state_set_src_convolution( &obj->state, filter );\n\n     return DFB_OK;\n}\n\nDFBResult\nIGraphicsState_Real__GetAccelerationMask( CoreGraphicsState   *obj,\n                                          DFBAccelerationMask *ret_accel )\n{\n     D_DEBUG_AT( DirectFB_CoreGraphicsState, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( ret_accel != NULL );\n\n     return dfb_state_get_acceleration_mask( &obj->state, ret_accel );\n}\n"
  },
  {
    "path": "src/core/CoreInputDevice.flux",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\ninterface {\n        name    IInputDevice\n        version 1.0\n        object  CoreInputDevice\n\n        method {\n                name    SetKeymapEntry\n\n                arg {\n                        name        key_code\n                        direction   input\n                        type        int\n                        typename    s32\n                }\n\n                arg {\n                        name        entry\n                        direction   input\n                        type        struct\n                        typename    DFBInputDeviceKeymapEntry\n                }\n        }\n\n        method {\n                name    SetConfiguration\n\n                arg {\n                        name        config\n                        direction   input\n                        type        struct\n                        typename    DFBInputDeviceConfig\n                }\n        }\n}\n"
  },
  {
    "path": "src/core/CoreInputDevice_includes.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/input.h>\n#include <misc/conf.h>\n\nstatic __inline__ DirectResult\nCoreInputDevice_Call( CoreInputDevice     *device,\n                      FusionCallExecFlags  flags,\n                      int                  call_arg,\n                      void                *ptr,\n                      unsigned int         length,\n                      void                *ret_ptr,\n                      unsigned int         ret_size,\n                      unsigned int        *ret_length )\n{\n     D_ASSERT( device != NULL );\n     D_ASSERT( device->shared != NULL );\n\n     return fusion_call_execute3( &device->shared->call, dfb_config->call_nodirect | flags, call_arg, ptr, length,\n                                  ret_ptr, ret_size, ret_length );\n}\n"
  },
  {
    "path": "src/core/CoreInputDevice_real.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreInputDevice.h>\n#include <core/input.h>\n\nD_DEBUG_DOMAIN( DirectFB_CoreInputDevice, \"DirectFB/CoreInputDevice\", \"DirectFB CoreInputDevice\" );\n\n/**********************************************************************************************************************/\n\nDFBResult\nIInputDevice_Real__SetKeymapEntry( CoreInputDevice                 *obj,\n                                   s32                              key_code,\n                                   const DFBInputDeviceKeymapEntry *entry )\n{\n     D_DEBUG_AT( DirectFB_CoreInputDevice, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_input_device_set_keymap_entry( obj, key_code, entry );\n}\n\nDFBResult\nIInputDevice_Real__SetConfiguration( CoreInputDevice            *obj,\n                                     const DFBInputDeviceConfig *config )\n{\n     D_DEBUG_AT( DirectFB_CoreInputDevice, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_input_device_set_configuration( obj, config );\n}\n"
  },
  {
    "path": "src/core/CoreLayer.flux",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\ninterface {\n        name    ILayer\n        version 1.0\n        object  CoreLayer\n\n        method {\n                name    CreateContext\n\n                arg {\n                        name        context\n                        direction   output\n                        type        object\n                        typename    CoreLayerContext\n                }\n        }\n\n        method {\n                name    GetPrimaryContext\n\n                arg {\n                        name        activate\n                        direction   input\n                        type        enum\n                        typename    DFBBoolean\n                }\n\n                arg {\n                        name        context\n                        direction   output\n                        type        object\n                        typename    CoreLayerContext\n                }\n        }\n\n        method {\n                name    ActivateContext\n\n                arg {\n                        name        context\n                        direction   input\n                        type        object\n                        typename    CoreLayerContext\n                }\n        }\n\n        method {\n                name    GetCurrentOutputField\n\n                arg {\n                        name        field\n                        direction   output\n                        type        int\n                        typename    s32\n                }\n        }\n\n        method {\n                name    SetLevel\n\n                arg {\n                        name        level\n                        direction   input\n                        type        int\n                        typename    s32\n                }\n        }\n\n        method {\n                name    WaitVSync\n        }\n}\n"
  },
  {
    "path": "src/core/CoreLayerContext.flux",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\ninterface {\n        name    ILayerContext\n        version 1.0\n        object  CoreLayerContext\n\n        method {\n                name    GetPrimaryRegion\n\n                arg {\n                        name        create\n                        direction   input\n                        type        enum\n                        typename    DFBBoolean\n                }\n\n                arg {\n                        name        region\n                        direction   output\n                        type        object\n                        typename    CoreLayerRegion\n                }\n        }\n\n        method {\n                name    TestConfiguration\n\n                arg {\n                        name        config\n                        direction   input\n                        type        struct\n                        typename    DFBDisplayLayerConfig\n                }\n\n                arg {\n                        name        failed\n                        direction   output\n                        type        enum\n                        typename    DFBDisplayLayerConfigFlags\n                        optional    yes\n                }\n        }\n\n        method {\n                name    SetConfiguration\n\n                arg {\n                        name        config\n                        direction   input\n                        type        struct\n                        typename    DFBDisplayLayerConfig\n                }\n        }\n\n        method {\n                name    SetScreenLocation\n\n                arg {\n                        name        location\n                        direction   input\n                        type        struct\n                        typename    DFBLocation\n                }\n        }\n\n        method {\n                name    SetScreenPosition\n\n                arg {\n                        name        position\n                        direction   input\n                        type        struct\n                        typename    DFBPoint\n                }\n        }\n\n        method {\n                name    SetScreenRectangle\n\n                arg {\n                        name        rectangle\n                        direction   input\n                        type        struct\n                        typename    DFBRectangle\n                }\n        }\n\n        method {\n                name    SetStereoDepth\n\n                arg {\n                        name        follow_video\n                        direction   input\n                        type        enum\n                        typename    DFBBoolean\n                }\n\n                arg {\n                        name        z\n                        direction   input\n                        type        int\n                        typename    s32\n                }\n        }\n\n        method {\n                name    SetOpacity\n\n                arg {\n                        name        opacity\n                        direction   input\n                        type        int\n                        typename    u8\n                }\n        }\n\n        method {\n                name    SetSourceRectangle\n\n                arg {\n                        name        rectangle\n                        direction   input\n                        type        struct\n                        typename    DFBRectangle\n                }\n        }\n\n        method {\n                name    SetFieldParity\n\n                arg {\n                        name        field\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    SetClipRegions\n\n                arg {\n                        name        regions\n                        direction   input\n                        type        struct\n                        typename    DFBRegion\n                        count       num\n                }\n\n                arg {\n                        name        num\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        positive\n                        direction   input\n                        type        enum\n                        typename    DFBBoolean\n                }\n        }\n\n        method {\n                name    SetSrcColorKey\n\n                arg {\n                        name        key\n                        direction   input\n                        type        struct\n                        typename    DFBColorKey\n                }\n        }\n\n        method {\n                name    SetDstColorKey\n\n                arg {\n                        name        key\n                        direction   input\n                        type        struct\n                        typename    DFBColorKey\n                }\n        }\n\n        method {\n                name    SetColorAdjustment\n\n                arg {\n                        name        adjustment\n                        direction   input\n                        type        struct\n                        typename    DFBColorAdjustment\n                }\n        }\n\n        method {\n                name    CreateWindow\n\n                arg {\n                        name        description\n                        direction   input\n                        type        struct\n                        typename    DFBWindowDescription\n                }\n\n                arg {\n                        name        window\n                        direction   output\n                        type        object\n                        typename    CoreWindow\n                }\n        }\n\n        method {\n                name    FindWindow\n\n                arg {\n                        name        window_id\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        window\n                        direction   output\n                        type        object\n                        typename    CoreWindow\n                }\n        }\n\n        method {\n                name    SetRotation\n\n                arg {\n                        name        rotation\n                        direction   input\n                        type        int\n                        typename    s32\n                }\n        }\n\n        method {\n                name    FindWindowByResourceID\n\n                arg {\n                        name        resource_id\n                        direction   input\n                        type        int\n                        typename    u64\n                }\n\n                arg {\n                        name        window\n                        direction   output\n                        type        object\n                        typename    CoreWindow\n                }\n        }\n}\n"
  },
  {
    "path": "src/core/CoreLayerContext_includes.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreDFB_includes.h>\n\nstatic __inline__ DirectResult\nCoreLayerContext_Call( CoreLayerContext    *context,\n                       FusionCallExecFlags  flags,\n                       int                  call_arg,\n                       void                *ptr,\n                       unsigned int         length,\n                       void                *ret_ptr,\n                       unsigned int         ret_size,\n                       unsigned int        *ret_length )\n{\n     return fusion_call_execute3( &context->call, dfb_config->call_nodirect | flags, call_arg, ptr, length,\n                                  ret_ptr, ret_size, ret_length );\n}\n"
  },
  {
    "path": "src/core/CoreLayerContext_real.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreLayerContext.h>\n#include <core/core.h>\n#include <core/layer_context.h>\n#include <core/surface.h>\n#include <core/windows.h>\n#include <core/wm.h>\n\nD_DEBUG_DOMAIN( DirectFB_CoreLayerContext, \"DirectFB/CoreLayerContext\", \"DirectFB CoreLayerContext\" );\n\n/**********************************************************************************************************************/\n\nDFBResult\nILayerContext_Real__GetPrimaryRegion( CoreLayerContext  *obj,\n                                      DFBBoolean         create,\n                                      CoreLayerRegion  **ret_region )\n{\n     D_DEBUG_AT( DirectFB_CoreLayerContext, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( ret_region != NULL );\n\n     return dfb_layer_context_get_primary_region( obj, create, ret_region );\n}\n\nDFBResult\nILayerContext_Real__TestConfiguration( CoreLayerContext            *obj,\n                                       const DFBDisplayLayerConfig *config,\n                                       DFBDisplayLayerConfigFlags  *ret_failed )\n{\n     D_DEBUG_AT( DirectFB_CoreLayerContext, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( config != NULL );\n\n     return dfb_layer_context_test_configuration( obj, config, ret_failed );\n}\n\nDFBResult\nILayerContext_Real__SetConfiguration( CoreLayerContext            *obj,\n                                      const DFBDisplayLayerConfig *config )\n{\n     D_DEBUG_AT( DirectFB_CoreLayerContext, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( config != NULL );\n\n     return dfb_layer_context_set_configuration( obj, config );\n}\n\nDFBResult\nILayerContext_Real__SetScreenLocation( CoreLayerContext  *obj,\n                                       const DFBLocation *location )\n{\n     D_DEBUG_AT( DirectFB_CoreLayerContext, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( location != NULL );\n\n     return dfb_layer_context_set_screenlocation( obj, location );\n}\n\nDFBResult\nILayerContext_Real__SetScreenPosition( CoreLayerContext *obj,\n                                       const DFBPoint   *position )\n{\n     D_DEBUG_AT( DirectFB_CoreLayerContext, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( position != NULL );\n\n     return dfb_layer_context_set_screenposition( obj, position->x, position->y );\n}\n\nDFBResult\nILayerContext_Real__SetScreenRectangle( CoreLayerContext   *obj,\n                                        const DFBRectangle *rectangle )\n{\n     D_DEBUG_AT( DirectFB_CoreLayerContext, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( rectangle != NULL );\n\n     return dfb_layer_context_set_screenrectangle( obj, rectangle );\n}\n\nDFBResult\nILayerContext_Real__SetStereoDepth( CoreLayerContext *obj,\n                                    DFBBoolean        follow_video,\n                                    s32               z )\n{\n     D_DEBUG_AT( DirectFB_CoreLayerContext, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_layer_context_set_stereo_depth( obj, follow_video, z );\n}\n\nDFBResult\nILayerContext_Real__SetOpacity( CoreLayerContext *obj,\n                                u8                opacity )\n{\n     D_DEBUG_AT( DirectFB_CoreLayerContext, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_layer_context_set_opacity( obj, opacity );\n}\n\nDFBResult\nILayerContext_Real__SetSourceRectangle( CoreLayerContext   *obj,\n                                        const DFBRectangle *rectangle )\n{\n     D_DEBUG_AT( DirectFB_CoreLayerContext, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( rectangle != NULL );\n\n     return dfb_layer_context_set_sourcerectangle( obj, rectangle );\n}\n\nDFBResult\nILayerContext_Real__SetFieldParity( CoreLayerContext *obj,\n                                    u32               field )\n{\n     D_DEBUG_AT( DirectFB_CoreLayerContext, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_layer_context_set_field_parity( obj, field );\n}\n\n\nDFBResult\nILayerContext_Real__SetClipRegions( CoreLayerContext *obj,\n                                    const DFBRegion  *regions,\n                                    u32               num,\n                                    DFBBoolean        positive )\n{\n     D_DEBUG_AT( DirectFB_CoreLayerContext, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( regions != NULL );\n\n     return dfb_layer_context_set_clip_regions( obj, regions, num, positive ? DFB_TRUE : DFB_FALSE );\n}\n\nDFBResult\nILayerContext_Real__SetSrcColorKey( CoreLayerContext  *obj,\n                                    const DFBColorKey *key )\n{\n     D_DEBUG_AT( DirectFB_CoreLayerContext, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( key != NULL );\n\n     return dfb_layer_context_set_src_colorkey( obj, key->r, key->g, key->b, key->index );\n}\n\nDFBResult\nILayerContext_Real__SetDstColorKey( CoreLayerContext  *obj,\n                                    const DFBColorKey *key )\n{\n     D_DEBUG_AT( DirectFB_CoreLayerContext, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( key != NULL );\n\n     return dfb_layer_context_set_dst_colorkey( obj, key->r, key->g, key->b, key->index );\n}\n\nDFBResult\nILayerContext_Real__SetColorAdjustment( CoreLayerContext         *obj,\n                                        const DFBColorAdjustment *adjustment )\n{\n     D_DEBUG_AT( DirectFB_CoreLayerContext, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( adjustment != NULL );\n\n     return dfb_layer_context_set_coloradjustment( obj, adjustment );\n}\n\nDFBResult\nILayerContext_Real__CreateWindow( CoreLayerContext            *obj,\n                                  const DFBWindowDescription  *description,\n                                  CoreWindow                 **ret_window )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( DirectFB_CoreLayerContext, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( description != NULL );\n     D_ASSERT( ret_window != NULL );\n\n     if (description->flags & DWDESC_PARENT) {\n          CoreWindow *parent;\n\n          ret = dfb_core_get_window( core_dfb, description->parent_id, &parent );\n          if (ret)\n              return ret;\n\n          if (fusion_object_check_owner( &parent->object, Core_GetIdentity(), false )) {\n               dfb_window_unref( parent );\n               return DFB_ACCESSDENIED;\n          }\n\n          dfb_window_unref( parent );\n     }\n\n     if (description->flags & DWDESC_TOPLEVEL_ID) {\n          CoreWindow *toplevel;\n\n          ret = dfb_core_get_window( core_dfb, description->toplevel_id, &toplevel );\n          if (ret)\n              return ret;\n\n          if (fusion_object_check_owner( &toplevel->object, Core_GetIdentity(), false )) {\n               dfb_window_unref( toplevel );\n               return DFB_ACCESSDENIED;\n          }\n\n          dfb_window_unref( toplevel );\n     }\n\n     return dfb_layer_context_create_window( core_dfb, obj, description, ret_window );\n}\n\nDFBResult\nILayerContext_Real__FindWindow( CoreLayerContext  *obj,\n                                u32                window_id,\n                                CoreWindow       **ret_window )\n{\n     CoreWindow *window;\n     FusionID    caller;\n\n     D_DEBUG_AT( DirectFB_CoreLayerContext, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( ret_window != NULL );\n\n     window = dfb_layer_context_find_window( obj, window_id );\n     if (!window)\n          return DFB_IDNOTFOUND;\n\n     caller = Core_GetIdentity();\n\n     if (dfb_config->ownership_check && caller != FUSION_ID_MASTER && window->object.identity != caller &&\n         fusion_object_check_owner( &window->object, caller, false )) {\n          dfb_window_unref( window );\n          return DFB_ACCESSDENIED;\n     }\n\n     *ret_window = window;\n\n     return DFB_OK;\n}\n\nDFBResult\nILayerContext_Real__SetRotation( CoreLayerContext *obj,\n                                 s32               rotation )\n{\n     D_DEBUG_AT( DirectFB_CoreLayerContext, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_layer_context_set_rotation( obj, rotation );\n}\n\ntypedef struct {\n     unsigned long    resource_id;\n     CoreWindow      *window;\n} FindWindowByResourceID_Context;\n\nstatic DFBEnumerationResult\nFindWindowByResourceID_WindowCallback( CoreWindow *window,\n                                       void       *_ctx )\n{\n     FindWindowByResourceID_Context *ctx = _ctx;\n\n     if (window->surface) {\n          if (window->surface->resource_id == ctx->resource_id) {\n               ctx->window = window;\n               return DFENUM_CANCEL;\n          }\n     }\n\n     return DFENUM_OK;\n}\n\nDFBResult\nILayerContext_Real__FindWindowByResourceID( CoreLayerContext  *obj,\n                                            u64                resource_id,\n                                            CoreWindow       **ret_window )\n{\n     DFBResult                       ret;\n     CoreLayerContext               *context = obj;\n     CoreWindowStack                *stack;\n     FindWindowByResourceID_Context  ctx;\n\n     D_DEBUG_AT( DirectFB_CoreLayerContext, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( context->stack != NULL );\n     D_ASSERT( ret_window != NULL );\n\n     ret = dfb_layer_context_lock( context );\n     if (ret)\n          return ret;\n\n     stack = context->stack;\n\n     ctx.resource_id = resource_id;\n     ctx.window      = NULL;\n\n     ret = dfb_wm_enum_windows( stack, FindWindowByResourceID_WindowCallback, &ctx );\n     if (ret == DFB_OK) {\n          if (ctx.window) {\n               ret = dfb_window_ref( ctx.window );\n               if (ret == DFB_OK)\n                    *ret_window = ctx.window;\n          }\n          else\n               ret = DFB_IDNOTFOUND;\n     }\n\n     dfb_layer_context_unlock( context );\n\n     return ret;\n}\n"
  },
  {
    "path": "src/core/CoreLayerRegion.flux",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\ninterface {\n        name    ILayerRegion\n        version 1.0\n        object  CoreLayerRegion\n\n        method {\n                name    GetSurface\n\n                arg {\n                        name        surface\n                        direction   output\n                        type        object\n                        typename    CoreSurface\n                }\n        }\n\n        method {\n                name    FlipUpdate2\n\n                arg {\n                        name        left_update\n                        direction   input\n                        type        struct\n                        typename    DFBRegion\n                        optional    yes\n                }\n\n                arg {\n                        name        right_update\n                        direction   input\n                        type        struct\n                        typename    DFBRegion\n                        optional    yes\n                }\n\n                arg {\n                        name        flags\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceFlipFlags\n                }\n\n                arg {\n                        name        flip_count\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        pts\n                        direction   input\n                        type        int\n                        typename    s64\n                }\n        }\n\n        method {\n                name    SetSurface\n\n                arg {\n                        name        surface\n                        direction   input\n                        type        object\n                        typename    CoreSurface\n                }\n        }\n}\n"
  },
  {
    "path": "src/core/CoreLayerRegion_includes.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreDFB_includes.h>\n\nstatic __inline__ DirectResult\nCoreLayerRegion_Call( CoreLayerRegion     *region,\n                      FusionCallExecFlags  flags,\n                      int                  call_arg,\n                      void                *ptr,\n                      unsigned int         length,\n                      void                *ret_ptr,\n                      unsigned int         ret_size,\n                      unsigned int        *ret_length )\n{\n     return fusion_call_execute3( &region->call, dfb_config->call_nodirect | flags, call_arg, ptr, length,\n                                  ret_ptr, ret_size, ret_length );\n}\n"
  },
  {
    "path": "src/core/CoreLayerRegion_real.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreLayerRegion.h>\n#include <core/layer_region.h>\n\nD_DEBUG_DOMAIN( DirectFB_CoreLayerRegion, \"DirectFB/CoreLayerRegion\", \"DirectFB CoreLayerRegion\" );\n\n/**********************************************************************************************************************/\n\nDFBResult\nILayerRegion_Real__GetSurface( CoreLayerRegion  *obj,\n                               CoreSurface     **ret_surface )\n{\n     D_DEBUG_AT( DirectFB_CoreLayerRegion, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_layer_region_get_surface( obj, ret_surface );\n}\n\nDFBResult\nILayerRegion_Real__FlipUpdate2( CoreLayerRegion     *obj,\n                                const DFBRegion     *left_update,\n                                const DFBRegion     *right_update,\n                                DFBSurfaceFlipFlags  flags,\n                                u32                  flip_count,\n                                s64                  pts )\n{\n     D_DEBUG_AT( DirectFB_CoreLayerRegion, \"%s( %p, flags 0x%08x, flip_count %u, pts %lld )\\n\", __FUNCTION__,\n                 obj, flags, flip_count, (long long) pts );\n\n     return dfb_layer_region_flip_update2( obj, left_update, right_update, flags, flip_count, pts );\n}\n\nDFBResult\nILayerRegion_Real__SetSurface( CoreLayerRegion *obj,\n                               CoreSurface     *surface )\n{\n     D_DEBUG_AT( DirectFB_CoreLayerRegion, \"%s( %p, surface %p )\\n\", __FUNCTION__, obj, surface );\n\n     D_ASSERT( surface != NULL );\n\n     dfb_layer_region_set_surface( obj, surface, true );\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/core/CoreLayer_includes.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreDFB_includes.h>\n#include <core/layers.h>\n\nstatic __inline__ DirectResult\nCoreLayer_Call( CoreLayer           *layer,\n                FusionCallExecFlags  flags,\n                int                  call_arg,\n                void                *ptr,\n                unsigned int         length,\n                void                *ret_ptr,\n                unsigned int         ret_size,\n                unsigned int        *ret_length )\n{\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n\n     return fusion_call_execute3( &layer->shared->call, dfb_config->call_nodirect | flags, call_arg, ptr, length,\n                                  ret_ptr, ret_size, ret_length );\n}\n"
  },
  {
    "path": "src/core/CoreLayer_real.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreLayer.h>\n#include <core/layer_control.h>\n\nD_DEBUG_DOMAIN( DirectFB_CoreLayer, \"DirectFB/CoreLayer\", \"DirectFB CoreLayer\" );\n\n/**********************************************************************************************************************/\n\nDFBResult\nILayer_Real__CreateContext( CoreLayer         *obj,\n                            CoreLayerContext **ret_context )\n{\n     D_DEBUG_AT( DirectFB_CoreLayer, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( ret_context != NULL );\n\n     return dfb_layer_create_context( obj, false, ret_context );\n}\n\nDFBResult\nILayer_Real__GetPrimaryContext( CoreLayer         *obj,\n                                DFBBoolean         activate,\n                                CoreLayerContext **ret_context )\n{\n     D_DEBUG_AT( DirectFB_CoreLayer, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( ret_context != NULL );\n\n     return dfb_layer_get_primary_context( obj, activate, ret_context );\n}\n\nDFBResult\nILayer_Real__ActivateContext( CoreLayer        *obj,\n                              CoreLayerContext *context )\n{\n     D_DEBUG_AT( DirectFB_CoreLayer, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( context != NULL );\n\n     return dfb_layer_activate_context( obj, context );\n}\n\nDFBResult\nILayer_Real__GetCurrentOutputField( CoreLayer *obj,\n                                    s32       *ret_field )\n{\n     D_DEBUG_AT( DirectFB_CoreLayer, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( ret_field != NULL );\n\n     return dfb_layer_get_current_output_field( obj, ret_field );\n}\n\nDFBResult\nILayer_Real__SetLevel( CoreLayer *obj,\n                       s32        level )\n{\n     D_DEBUG_AT( DirectFB_CoreLayer, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_layer_set_level( obj, level );\n}\n\nDFBResult\nILayer_Real__WaitVSync( CoreLayer *obj )\n{\n     D_DEBUG_AT( DirectFB_CoreLayer, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_layer_wait_vsync( obj );\n}\n"
  },
  {
    "path": "src/core/CorePalette.flux",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\ninterface {\n        name    IPalette\n        version 1.0\n        object  CorePalette\n\n        method {\n                name    SetEntries\n\n                arg {\n                        name        colors\n                        direction   input\n                        type        struct\n                        typename    DFBColor\n                        count       num\n                }\n\n                arg {\n                        name        num\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        offset\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    SetEntriesYUV\n\n                arg {\n                        name        colors\n                        direction   input\n                        type        struct\n                        typename    DFBColorYUV\n                        count       num\n                }\n\n                arg {\n                        name        num\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        offset\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n}\n"
  },
  {
    "path": "src/core/CorePalette_includes.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreDFB_includes.h>\n\nstatic __inline__ DirectResult\nCorePalette_Call( CorePalette         *palette,\n                  FusionCallExecFlags  flags,\n                  int                  call_arg,\n                  void                *ptr,\n                  unsigned int         length,\n                  void                *ret_ptr,\n                  unsigned int         ret_size,\n                  unsigned int        *ret_length )\n{\n     return fusion_call_execute3( &palette->call, dfb_config->call_nodirect | flags, call_arg, ptr, length,\n                                  ret_ptr, ret_size, ret_length );\n}\n"
  },
  {
    "path": "src/core/CorePalette_real.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CorePalette.h>\n#include <core/palette.h>\n#include <direct/memcpy.h>\n#include <gfx/convert.h>\n\nD_DEBUG_DOMAIN( DirectFB_CorePalette, \"DirectFB/CorePalette\", \"DirectFB CorePalette\" );\n\n/**********************************************************************************************************************/\n\nDFBResult\nIPalette_Real__SetEntries( CorePalette    *obj,\n                           const DFBColor *colors,\n                           u32             num,\n                           u32             offset )\n{\n     D_DEBUG_AT( DirectFB_CorePalette, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( colors != NULL );\n\n     if (offset + num > obj->num_entries)\n          return DFB_INVARG;\n\n     if (num) {\n          u32 i;\n\n          direct_memcpy( obj->entries + offset, colors, num * sizeof(DFBColor) );\n\n          for (i = offset; i < offset + num; i++) {\n               obj->entries_yuv[i].a = obj->entries[i].a;\n\n               if (obj->colorspace == DSCS_BT601)\n                    RGB_TO_YCBCR_BT601( obj->entries[i].r, obj->entries[i].g, obj->entries[i].b,\n                                        obj->entries_yuv[i].y, obj->entries_yuv[i].u, obj->entries_yuv[i].v );\n               else if (obj->colorspace == DSCS_RGB || obj->colorspace == DSCS_BT709)\n                    RGB_TO_YCBCR_BT709( obj->entries[i].r, obj->entries[i].g, obj->entries[i].b,\n                                        obj->entries_yuv[i].y, obj->entries_yuv[i].u, obj->entries_yuv[i].v );\n               else if (obj->colorspace == DSCS_BT2020)\n                    RGB_TO_YCBCR_BT2020( obj->entries[i].r, obj->entries[i].g, obj->entries[i].b,\n                                         obj->entries_yuv[i].y, obj->entries_yuv[i].u, obj->entries_yuv[i].v );\n               else {\n                    obj->entries_yuv[i].y = 16;\n                    obj->entries_yuv[i].u = obj->entries_yuv[i].v = 128;\n               }\n          }\n\n          dfb_palette_update( obj, offset, offset + num - 1 );\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nIPalette_Real__SetEntriesYUV( CorePalette       *obj,\n                              const DFBColorYUV *colors,\n                              u32                num,\n                              u32                offset )\n{\n     D_DEBUG_AT( DirectFB_CorePalette, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( colors != NULL );\n\n     if (offset + num > obj->num_entries)\n          return DFB_INVARG;\n\n     if (num) {\n          u32 i;\n\n          direct_memcpy( obj->entries_yuv + offset, colors, num * sizeof(DFBColorYUV) );\n\n          for (i = offset; i < offset + num; i++) {\n               obj->entries[i].a = obj->entries_yuv[i].a;\n\n               if (obj->colorspace == DSCS_BT601)\n                    YCBCR_TO_RGB_BT601( obj->entries_yuv[i].y, obj->entries_yuv[i].u, obj->entries_yuv[i].v,\n                                        obj->entries[i].r, obj->entries[i].g, obj->entries[i].b );\n               else if (obj->colorspace == DSCS_RGB || obj->colorspace == DSCS_BT709)\n                    YCBCR_TO_RGB_BT709( obj->entries_yuv[i].y, obj->entries_yuv[i].u, obj->entries_yuv[i].v,\n                                        obj->entries[i].r, obj->entries[i].g, obj->entries[i].b );\n               else if (obj->colorspace == DSCS_BT2020)\n                    YCBCR_TO_RGB_BT2020( obj->entries_yuv[i].y, obj->entries_yuv[i].u, obj->entries_yuv[i].v,\n                                         obj->entries[i].r, obj->entries[i].g, obj->entries[i].b );\n               else {\n                    obj->entries[i].r = obj->entries[i].g = obj->entries[i].b = 0;\n               }\n          }\n\n          dfb_palette_update( obj, offset, offset + num - 1 );\n     }\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/core/CoreScreen.flux",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\ninterface {\n        name    IScreen\n        version 1.0\n        object  CoreScreen\n\n        method {\n                name    GetScreenSize\n\n                arg {\n                        name        size\n                        direction   output\n                        type        struct\n                        typename    DFBDimension\n                }\n        }\n\n        method {\n                name    SetPowerMode\n\n                arg {\n                        name        mode\n                        direction   input\n                        type        enum\n                        typename    DFBScreenPowerMode\n                }\n        }\n\n        method {\n                name    WaitVSync\n        }\n\n        method {\n                name    TestMixerConfig\n\n                arg {\n                        name        mixer\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        config\n                        direction   input\n                        type        struct\n                        typename    DFBScreenMixerConfig\n                }\n\n                arg {\n                        name        failed\n                        direction   output\n                        optional    yes\n                        type        enum\n                        typename    DFBScreenMixerConfigFlags\n                }\n        }\n\n        method {\n                name    SetMixerConfig\n\n                arg {\n                        name        mixer\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        config\n                        direction   input\n                        type        struct\n                        typename    DFBScreenMixerConfig\n                }\n        }\n\n        method {\n                name    TestEncoderConfig\n\n                arg {\n                        name        encoder\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        config\n                        direction   input\n                        type        struct\n                        typename    DFBScreenEncoderConfig\n                }\n\n                arg {\n                        name        failed\n                        direction   output\n                        optional    yes\n                        type        enum\n                        typename    DFBScreenEncoderConfigFlags\n                }\n        }\n\n        method {\n                name    SetEncoderConfig\n\n                arg {\n                        name        encoder\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        config\n                        direction   input\n                        type        struct\n                        typename    DFBScreenEncoderConfig\n                }\n        }\n\n        method {\n                name    TestOutputConfig\n\n                arg {\n                        name        output\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        config\n                        direction   input\n                        type        struct\n                        typename    DFBScreenOutputConfig\n                }\n\n                arg {\n                        name        failed\n                        direction   output\n                        optional    yes\n                        type        enum\n                        typename    DFBScreenOutputConfigFlags\n                }\n        }\n\n        method {\n                name    SetOutputConfig\n\n                arg {\n                        name        output\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        config\n                        direction   input\n                        type        struct\n                        typename    DFBScreenOutputConfig\n                }\n        }\n\n        method {\n                name    GetVSyncCount\n\n                arg {\n                        name        count\n                        direction   output\n                        type        int\n                        typename    u64\n                }\n        }\n}\n"
  },
  {
    "path": "src/core/CoreScreen_includes.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/screens.h>\n#include <misc/conf.h>\n\nstatic __inline__ DirectResult\nCoreScreen_Call( CoreScreen          *screen,\n                 FusionCallExecFlags  flags,\n                 int                  call_arg,\n                 void                *ptr,\n                 unsigned int         length,\n                 void                *ret_ptr,\n                 unsigned int         ret_size,\n                 unsigned int        *ret_length )\n{\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->shared != NULL );\n\n     return fusion_call_execute3( &screen->shared->call, dfb_config->call_nodirect | flags, call_arg, ptr, length,\n                                  ret_ptr, ret_size, ret_length );\n}\n"
  },
  {
    "path": "src/core/CoreScreen_real.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreScreen.h>\n#include <core/screen.h>\n\nD_DEBUG_DOMAIN( DirectFB_CoreScreen, \"DirectFB/CoreScreen\", \"DirectFB CoreScreen\" );\n\n/**********************************************************************************************************************/\n\nDFBResult\nIScreen_Real__GetScreenSize( CoreScreen   *obj,\n                             DFBDimension *ret_size )\n{\n     D_DEBUG_AT( DirectFB_CoreScreen, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( ret_size != NULL );\n\n     return dfb_screen_get_screen_size( obj, &ret_size->w, &ret_size->h );\n}\n\nDFBResult\nIScreen_Real__SetPowerMode( CoreScreen         *obj,\n                            DFBScreenPowerMode  mode )\n{\n     D_DEBUG_AT( DirectFB_CoreScreen, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_screen_set_powermode( obj, mode );\n}\n\nDFBResult\nIScreen_Real__WaitVSync( CoreScreen *obj )\n{\n     D_DEBUG_AT( DirectFB_CoreScreen, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_screen_wait_vsync( obj );\n}\n\nDFBResult\nIScreen_Real__TestMixerConfig( CoreScreen                 *obj,\n                               u32                         mixer,\n                               const DFBScreenMixerConfig *config,\n                               DFBScreenMixerConfigFlags  *ret_failed )\n{\n     D_DEBUG_AT( DirectFB_CoreScreen, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( config != NULL );\n\n     return dfb_screen_test_mixer_config( obj, mixer, config, ret_failed );\n}\n\nDFBResult\nIScreen_Real__SetMixerConfig( CoreScreen                 *obj,\n                              u32                         mixer,\n                              const DFBScreenMixerConfig *config )\n{\n     D_DEBUG_AT( DirectFB_CoreScreen, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( config != NULL );\n\n     return dfb_screen_set_mixer_config( obj, mixer, config );\n}\n\nDFBResult\nIScreen_Real__TestEncoderConfig( CoreScreen                   *obj,\n                                 u32                           encoder,\n                                 const DFBScreenEncoderConfig *config,\n                                 DFBScreenEncoderConfigFlags  *ret_failed )\n{\n     D_DEBUG_AT( DirectFB_CoreScreen, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( config != NULL );\n\n     return dfb_screen_test_encoder_config( obj, encoder, config, ret_failed );\n}\n\nDFBResult\nIScreen_Real__SetEncoderConfig( CoreScreen                   *obj,\n                                u32                           encoder,\n                                const DFBScreenEncoderConfig *config )\n{\n     D_DEBUG_AT( DirectFB_CoreScreen, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( config != NULL );\n\n     return dfb_screen_set_encoder_config( obj, encoder, config );\n}\n\nDFBResult\nIScreen_Real__TestOutputConfig( CoreScreen                  *obj,\n                                u32                          output,\n                                const DFBScreenOutputConfig *config,\n                                DFBScreenOutputConfigFlags  *ret_failed )\n{\n     D_DEBUG_AT( DirectFB_CoreScreen, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( config != NULL );\n\n     return dfb_screen_test_output_config( obj, output, config, ret_failed );\n}\n\nDFBResult\nIScreen_Real__SetOutputConfig( CoreScreen                  *obj,\n                               u32                          output,\n                               const DFBScreenOutputConfig *config )\n{\n     D_DEBUG_AT( DirectFB_CoreScreen, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( config != NULL );\n\n     return dfb_screen_set_output_config( obj, output, config );\n}\n\nDFBResult\nIScreen_Real__GetVSyncCount( CoreScreen *obj,\n                             u64        *ret_count )\n{\n     DFBResult     ret;\n     unsigned long count;\n\n     D_DEBUG_AT( DirectFB_CoreScreen, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     ret = dfb_screen_get_vsync_count( obj, &count );\n     if (ret)\n          return ret;\n\n     *ret_count = count;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/core/CoreSlave.flux",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\ninterface {\n        name     ICoreSlave\n        version  1.0\n        object   CoreSlave\n        dispatch CoreDFB\n\n        method {\n                name    GetData\n\n                arg {\n                        name        address\n                        direction   input\n                        type        int\n                        typename    \"void*\"\n                }\n\n                arg {\n                        name        bytes\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        data\n                        direction   output\n                        type        int\n                        typename    u8\n                        count       bytes\n                        max         bytes\n                }\n        }\n\n        method {\n                name    PutData\n\n                arg {\n                        name        address\n                        direction   input\n                        type        int\n                        typename    \"void*\"\n                }\n\n                arg {\n                        name        bytes\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        data\n                        direction   input\n                        type        int\n                        typename    u8\n                        count       bytes\n                }\n        }\n}\n"
  },
  {
    "path": "src/core/CoreSlave_includes.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__CORESLAVE_INCLUDES_H__\n#define __CORE__CORESLAVE_INCLUDES_H__\n\n#include <fusion/call.h>\n#include <misc/conf.h>\n\ntypedef struct {\n     FusionCall call;\n} CoreSlave;\n\nstatic __inline__ DirectResult\nCoreSlave_Call( CoreSlave           *slave,\n                FusionCallExecFlags  flags,\n                int                  call_arg,\n                void                *ptr,\n                unsigned int         length,\n                void                *ret_ptr,\n                unsigned int         ret_size,\n                unsigned int        *ret_length )\n{\n     return fusion_call_execute3( &slave->call, dfb_config->call_nodirect | flags, call_arg, ptr, length,\n                                  ret_ptr, ret_size, ret_length );\n}\n\n#endif\n"
  },
  {
    "path": "src/core/CoreSlave_real.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreSlave.h>\n#include <core/core.h>\n#include <direct/memcpy.h>\n\nD_DEBUG_DOMAIN( DirectFB_CoreSlave, \"DirectFB/CoreSlave\", \"DirectFB Core Slave\" );\n\n/**********************************************************************************************************************/\n\nDFBResult\nICoreSlave_Real__GetData( CoreDFB *obj,\n                          void    *address,\n                          u32      bytes,\n                          u8      *ret_data )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( DirectFB_CoreSlave, \"%s( %p, address %p, bytes %u ) from %lu\\n\", __FUNCTION__,\n                 obj, address, bytes, Core_GetIdentity() );\n\n     ret = dfb_core_memory_permissions_check( core_dfb, CMPF_READ, address, bytes );\n     if (ret)\n          return ret;\n\n     direct_memcpy( ret_data, address, bytes );\n\n     return DFB_OK;\n}\n\nDFBResult\nICoreSlave_Real__PutData( CoreDFB  *obj,\n                          void     *address,\n                          u32       bytes,\n                          const u8 *data )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( DirectFB_CoreSlave, \"%s( %p, address %p, bytes %u ) from %lu\\n\", __FUNCTION__,\n                 obj, address, bytes, Core_GetIdentity() );\n\n     ret = dfb_core_memory_permissions_check( core_dfb, CMPF_WRITE, address, bytes );\n     if (ret)\n          return ret;\n\n     direct_memcpy( address, data, bytes );\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/core/CoreSurface.flux",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\ninterface {\n        name    ISurface\n        version 1.0\n        object  CoreSurface\n\n        method {\n                name    SetConfig\n\n                arg {\n                        name        config\n                        direction   input\n                        type        struct\n                        typename    CoreSurfaceConfig\n                }\n        }\n\n        method {\n                name    GetPalette\n\n                arg {\n                        name        palette\n                        direction   output\n                        type        object\n                        typename    CorePalette\n                }\n        }\n\n        method {\n                name    SetPalette\n\n                arg {\n                        name        palette\n                        direction   input\n                        type        object\n                        typename    CorePalette\n                }\n        }\n\n        method {\n                name    SetAlphaRamp\n\n                arg {\n                        name        a0\n                        direction   input\n                        type        int\n                        typename    u8\n                }\n\n                arg {\n                        name        a1\n                        direction   input\n                        type        int\n                        typename    u8\n                }\n\n                arg {\n                        name        a2\n                        direction   input\n                        type        int\n                        typename    u8\n                }\n\n                arg {\n                        name        a3\n                        direction   input\n                        type        int\n                        typename    u8\n                }\n        }\n\n        method {\n                name    PreLockBuffer\n\n                arg {\n                        name        buffer\n                        direction   input\n                        type        object\n                        typename    CoreSurfaceBuffer\n                }\n\n                arg {\n                        name        accessor\n                        direction   input\n                        type        enum\n                        typename    CoreSurfaceAccessorID\n                }\n\n                arg {\n                        name        access\n                        direction   input\n                        type        enum\n                        typename    CoreSurfaceAccessFlags\n                }\n\n                arg {\n                        name        allocation\n                        direction   output\n                        type        object\n                        typename    CoreSurfaceAllocation\n                }\n        }\n\n        method {\n                name    PreLockBuffer2\n\n                arg {\n                        name        role\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceBufferRole\n                }\n\n                arg {\n                        name        eye\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceStereoEye\n                }\n\n                arg {\n                        name        accessor\n                        direction   input\n                        type        enum\n                        typename    CoreSurfaceAccessorID\n                }\n\n                arg {\n                        name        access\n                        direction   input\n                        type        enum\n                        typename    CoreSurfaceAccessFlags\n                }\n\n                arg {\n                        name        lock\n                        direction   input\n                        type        enum\n                        typename    DFBBoolean\n                }\n\n                arg {\n                        name        allocation\n                        direction   output\n                        type        object\n                        typename    CoreSurfaceAllocation\n                }\n        }\n\n        method {\n                name    PreLockBuffer3\n\n                arg {\n                        name        role\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceBufferRole\n                }\n\n                arg {\n                        name        flip_count\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        eye\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceStereoEye\n                }\n\n                arg {\n                        name        accessor\n                        direction   input\n                        type        enum\n                        typename    CoreSurfaceAccessorID\n                }\n\n                arg {\n                        name        access\n                        direction   input\n                        type        enum\n                        typename    CoreSurfaceAccessFlags\n                }\n\n                arg {\n                        name        lock\n                        direction   input\n                        type        enum\n                        typename    DFBBoolean\n                }\n\n                arg {\n                        name        allocation\n                        direction   output\n                        type        object\n                        typename    CoreSurfaceAllocation\n                }\n        }\n\n        method {\n                name     DispatchUpdate\n                async    yes\n\n                arg {\n                        name        swap\n                        direction   input\n                        type        enum\n                        typename    DFBBoolean\n                }\n\n                arg {\n                        name        left\n                        direction   input\n                        type        struct\n                        typename    DFBRegion\n                        optional    yes\n                }\n\n                arg {\n                        name        right\n                        direction   input\n                        type        struct\n                        typename    DFBRegion\n                        optional    yes\n                }\n\n                arg {\n                        name        flags\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceFlipFlags\n                }\n\n                arg {\n                        name        timestamp\n                        direction   input\n                        type        int\n                        typename    s64\n                }\n\n                arg {\n                        name        flip_count\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name     Flip2\n\n                arg {\n                        name        swap\n                        direction   input\n                        type        enum\n                        typename    DFBBoolean\n                }\n\n                arg {\n                        name        left\n                        direction   input\n                        type        struct\n                        typename    DFBRegion\n                        optional    yes\n                }\n\n                arg {\n                        name        right\n                        direction   input\n                        type        struct\n                        typename    DFBRegion\n                        optional    yes\n                }\n\n                arg {\n                        name        flags\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceFlipFlags\n                }\n\n                arg {\n                        name        timestamp\n                        direction   input\n                        type        int\n                        typename    s64\n                }\n        }\n\n        method {\n                name    SetField\n\n                arg {\n                        name        field\n                        direction   input\n                        type        int\n                        typename    s32\n                }\n        }\n\n        method {\n                name    CreateClient\n\n                arg {\n                        name        client\n                        direction   output\n                        type        object\n                        typename    CoreSurfaceClient\n                }\n        }\n\n        method {\n                name    Allocate\n\n                arg {\n                        name        role\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceBufferRole\n                }\n\n                arg {\n                        name        eye\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceStereoEye\n                }\n\n                arg {\n                        name        key\n                        direction   input\n                        type        int\n                        typename    char\n                        count       key_len\n                }\n\n                arg {\n                        name        key_len\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        handle\n                        direction   input\n                        type        int\n                        typename    u64\n                }\n\n                arg {\n                        name        allocation\n                        direction   output\n                        type        object\n                        typename    CoreSurfaceAllocation\n                }\n        }\n\n        method {\n                name    GetAllocation\n\n                arg {\n                        name        role\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceBufferRole\n                }\n\n                arg {\n                        name        eye\n                        direction   input\n                        type        enum\n                        typename    DFBSurfaceStereoEye\n                }\n\n                arg {\n                        name        key\n                        direction   input\n                        type        int\n                        typename    char\n                        count       key_len\n                }\n\n                arg {\n                        name        key_len\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        allocation\n                        direction   output\n                        type        object\n                        typename    CoreSurfaceAllocation\n                }\n        }\n}\n"
  },
  {
    "path": "src/core/CoreSurfaceAllocation.flux",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\ninterface {\n        name    ISurfaceAllocation\n        version 1.0\n        object  CoreSurfaceAllocation\n\n        method {\n                name    Updated\n                async   yes\n\n                arg {\n                        name        updates\n                        direction   input\n                        type        struct\n                        typename    DFBBox\n                        optional    yes\n                        count       num_updates\n                }\n\n                arg {\n                        name        num_updates\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n}\n"
  },
  {
    "path": "src/core/CoreSurfaceAllocation_includes.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreDFB_includes.h>\n\nstatic __inline__ DirectResult\nCoreSurfaceAllocation_Call( CoreSurfaceAllocation *allocation,\n                            FusionCallExecFlags    flags,\n                            int                    call_arg,\n                            void                  *ptr,\n                            unsigned int           length,\n                            void                  *ret_ptr,\n                            unsigned int           ret_size,\n                            unsigned int          *ret_length )\n{\n     return fusion_call_execute3( &allocation->call, dfb_config->call_nodirect | flags, call_arg, ptr, length,\n                                  ret_ptr, ret_size, ret_length );\n}\n"
  },
  {
    "path": "src/core/CoreSurfaceAllocation_real.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreSurfaceAllocation.h>\n#include <core/core.h>\n#include <core/surface_allocation.h>\n#include <core/surface_buffer.h>\n\nD_DEBUG_DOMAIN( DirectFB_CoreSurfaceAllocation, \"DirectFB/CoreSurfaceAllocation\", \"DirectFB CoreSurfaceAllocation\" );\n\n/**********************************************************************************************************************/\n\nDFBResult\nISurfaceAllocation_Real__Updated( CoreSurfaceAllocation *obj,\n                                  const DFBBox          *updates,\n                                  u32                    num_updates )\n{\n     DFBResult          ret;\n     CoreSurfaceBuffer *buffer;\n\n     D_DEBUG_AT( DirectFB_CoreSurfaceAllocation, \"%s( %p, updates %p, num %u )\\n\", __FUNCTION__,\n                 obj, updates, num_updates );\n\n     ret = fusion_object_get( core_dfb->shared->surface_buffer_pool, obj->buffer_id, (FusionObject**) &buffer );\n     if (ret && ret != DFB_DEAD)\n          return ret;\n\n     if (ret == DFB_DEAD) {\n          D_DEBUG_AT( DirectFB_CoreSurfaceAllocation, \"  -> dead object!\\n\" );\n     }\n     else {\n          CoreSurface *surface;\n\n          ret = fusion_object_get( core_dfb->shared->surface_pool, buffer->surface_id, (FusionObject**) &surface );\n          if (ret && ret != DFB_DEAD) {\n               dfb_surface_buffer_unref( buffer );\n               return ret;\n          }\n\n          if (ret == DFB_DEAD) {\n               D_DEBUG_AT( DirectFB_CoreSurfaceAllocation, \"  -> dead object!\\n\" );\n          }\n          else {\n               dfb_surface_lock( surface );\n\n               if (obj->buffer) {\n                    D_ASSERT( obj->buffer == buffer );\n\n                    D_DEBUG_AT( DirectFB_CoreSurfaceAllocation, \"  <- buffer  %p\\n\", buffer );\n                    D_DEBUG_AT( DirectFB_CoreSurfaceAllocation, \"  <- written %p\\n\", buffer->written );\n                    D_DEBUG_AT( DirectFB_CoreSurfaceAllocation, \"  <- read    %p\\n\", buffer->read );\n                    D_DEBUG_AT( DirectFB_CoreSurfaceAllocation, \"  <- serial  %lu (this %lu)\\n\", buffer->serial.value,\n                                obj->serial.value );\n\n                    direct_serial_increase( &buffer->serial );\n\n                    direct_serial_copy( &obj->serial, &buffer->serial );\n\n                    buffer->written = obj;\n                    buffer->read    = NULL;\n\n                    D_DEBUG_AT( DirectFB_CoreSurfaceAllocation, \"  -> serial  %lu\\n\", buffer->serial.value );\n               }\n               else {\n                    D_DEBUG_AT( DirectFB_CoreSurfaceAllocation, \"  -> already decoupled!\\n\" );\n               }\n\n               dfb_surface_unlock( surface );\n\n               dfb_surface_unref( surface );\n          }\n\n          dfb_surface_buffer_unref( buffer );\n     }\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/core/CoreSurfaceClient.flux",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\ninterface {\n        name    ISurfaceClient\n        version 1.0\n        object  CoreSurfaceClient\n\n        method {\n                name    FrameAck\n                async   yes\n\n                arg {\n                        name        flip_count\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n}\n"
  },
  {
    "path": "src/core/CoreSurfaceClient_includes.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreDFB_includes.h>\n\nstatic __inline__ DirectResult\nCoreSurfaceClient_Call( CoreSurfaceClient   *client,\n                        FusionCallExecFlags  flags,\n                        int                  call_arg,\n                        void                *ptr,\n                        unsigned int         length,\n                        void                *ret_ptr,\n                        unsigned int         ret_size,\n                        unsigned int        *ret_length )\n{\n     return fusion_call_execute3( &client->call, dfb_config->call_nodirect | flags, call_arg, ptr, length,\n                                  ret_ptr, ret_size, ret_length );\n}\n"
  },
  {
    "path": "src/core/CoreSurfaceClient_real.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreSurfaceClient.h>\n#include <core/surface.h>\n#include <core/surface_client.h>\n\nD_DEBUG_DOMAIN( DirectFB_CoreSurfaceClient, \"DirectFB/CoreSurfaceClient\", \"DirectFB CoreSurfaceClient\" );\n\n/**********************************************************************************************************************/\n\nDFBResult\nISurfaceClient_Real__FrameAck( CoreSurfaceClient *obj,\n                               u32                flip_count )\n{\n     CoreSurface *surface;\n\n     D_DEBUG_AT( DirectFB_CoreSurfaceClient, \"%s( %p, count %u ) <- old count %u\\n\", __FUNCTION__,\n                 obj, flip_count, obj->flip_count );\n\n     D_MAGIC_ASSERT( obj->surface, CoreSurface );\n\n     surface = obj->surface;\n\n     D_DEBUG_AT( DirectFB_CoreSurfaceClient, \"  -> surface %p (id %u)\\n\", surface, surface->object.id );\n\n     dfb_surface_lock( surface );\n\n     obj->flip_count = flip_count;\n\n     dfb_surface_check_acks( surface );\n\n     dfb_surface_unlock( surface );\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/core/CoreSurface_includes.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreDFB_includes.h>\n\nstatic __inline__ DirectResult\nCoreSurface_Call( CoreSurface         *surface,\n                  FusionCallExecFlags  flags,\n                  int                  call_arg,\n                  void                *ptr,\n                  unsigned int         length,\n                  void                *ret_ptr,\n                  unsigned int         ret_size,\n                  unsigned int        *ret_length )\n{\n     return fusion_call_execute3( &surface->call, dfb_config->call_nodirect | flags, call_arg, ptr, length,\n                                  ret_ptr, ret_size, ret_length );\n}\n"
  },
  {
    "path": "src/core/CoreSurface_real.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreSurface.h>\n#include <core/core.h>\n#include <core/gfxcard.h>\n#include <core/palette.h>\n#include <core/surface_allocation.h>\n#include <core/surface_buffer.h>\n#include <core/surface_client.h>\n#include <core/surface_pool.h>\n#include <gfx/util.h>\n\nD_DEBUG_DOMAIN( DirectFB_CoreSurface, \"DirectFB/CoreSurface\", \"DirectFB CoreSurface\" );\n\n/**********************************************************************************************************************/\n\nDFBResult\nISurface_Real__SetConfig( CoreSurface             *obj,\n                          const CoreSurfaceConfig *config )\n{\n     D_DEBUG_AT( DirectFB_CoreSurface, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( config != NULL );\n\n     return dfb_surface_reconfig( obj, config );\n}\n\nDFBResult\nISurface_Real__GetPalette( CoreSurface  *obj,\n                           CorePalette **ret_palette )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( DirectFB_CoreSurface, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( ret_palette != NULL );\n\n     if (!obj->palette)\n          return DFB_UNSUPPORTED;\n\n     ret = dfb_palette_ref( obj->palette );\n     if (ret)\n          return ret;\n\n     *ret_palette = obj->palette;\n\n     return DFB_OK;\n}\n\nDFBResult\nISurface_Real__SetPalette( CoreSurface *obj,\n                           CorePalette *palette )\n{\n     D_DEBUG_AT( DirectFB_CoreSurface, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( palette != NULL );\n\n     return dfb_surface_set_palette( obj, palette );\n}\n\nDFBResult\nISurface_Real__SetAlphaRamp( CoreSurface *obj,\n                             u8           a0,\n                             u8           a1,\n                             u8           a2,\n                             u8           a3 )\n{\n     D_DEBUG_AT( DirectFB_CoreSurface, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_surface_set_alpha_ramp( obj, a0, a1, a2, a3 );\n}\n\nstatic void\nmanage_interlocks( CoreSurfaceAllocation  *allocation,\n                   CoreSurfaceAccessorID   accessor,\n                   CoreSurfaceAccessFlags  access )\n{\n     int locks;\n\n     locks = dfb_surface_allocation_locks( allocation );\n\n     /* Software read/write access. */\n     if (accessor != CSAID_GPU) {\n          /* If hardware has written or is writing. */\n          if (allocation->accessed[CSAID_GPU] & CSAF_WRITE) {\n               /* Wait for the operation to finish. */\n               dfb_gfxcard_wait_serial( &allocation->gfx_serial );\n\n               /* Software read access after hardware write requires flush of the (bus) read cache. */\n               dfb_gfxcard_flush_read_cache();\n\n               if (!locks) {\n                    /* Clear hardware write access. */\n                    allocation->accessed[CSAID_GPU] &= ~CSAF_WRITE;\n\n                    /* Clear hardware read access (to avoid syncing twice). */\n                    allocation->accessed[CSAID_GPU] &= ~CSAF_READ;\n               }\n          }\n\n          /* Software write access. */\n          if (access & CSAF_WRITE) {\n               /* If hardware has (to) read... */\n               if (allocation->accessed[CSAID_GPU] & CSAF_READ) {\n                    /* Wait for the operation to finish. */\n                    dfb_gfxcard_wait_serial( &allocation->gfx_serial );\n\n                    /* Clear hardware read access. */\n                    if (!locks)\n                         allocation->accessed[CSAID_GPU] &= ~CSAF_READ;\n               }\n          }\n     }\n\n     /* Hardware read or write access. */\n     if (accessor == CSAID_GPU && access & (CSAF_READ | CSAF_WRITE)) {\n          /* If software has read or written before. */\n          if (allocation->accessed[CSAID_CPU] & (CSAF_READ | CSAF_WRITE)) {\n               /* Flush texture cache. */\n               dfb_gfxcard_flush_texture_cache();\n\n               /* Clear software read and write access. */\n               if (!locks)\n                    allocation->accessed[CSAID_CPU] &= ~(CSAF_READ | CSAF_WRITE);\n          }\n     }\n\n     allocation->accessed[accessor] |= access;\n}\n\nDFBResult\nISurface_Real__PreLockBuffer( CoreSurface             *obj,\n                              CoreSurfaceBuffer       *buffer,\n                              CoreSurfaceAccessorID    accessor,\n                              CoreSurfaceAccessFlags   access,\n                              CoreSurfaceAllocation  **ret_allocation )\n{\n     DFBResult              ret;\n     CoreSurfaceAllocation *allocation;\n     bool                   allocated = false;\n\n     D_DEBUG_AT( DirectFB_CoreSurface, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n\n     dfb_surface_lock( obj );\n\n     if (obj->state & CSSF_DESTROYED) {\n          dfb_surface_unlock( obj );\n          return DFB_DESTROYED;\n     }\n\n     if (!buffer->surface) {\n          dfb_surface_unlock( obj );\n          return DFB_BUFFEREMPTY;\n     }\n\n     /* Look for allocation with proper access. */\n     allocation = dfb_surface_buffer_find_allocation( buffer, accessor, access, true );\n     if (!allocation) {\n          /* If no allocation exists, create one. */\n          ret = dfb_surface_pools_allocate( buffer, accessor, access, &allocation );\n          if (ret) {\n               if (ret != DFB_NOVIDEOMEMORY && ret != DFB_UNSUPPORTED)\n                    D_DERROR( ret, \"DirectFB/CoreSurface: Buffer allocation failed!\\n\" );\n\n               goto out;\n          }\n\n          allocated = true;\n     }\n\n     CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n     /* Synchronize with other allocations. */\n     ret = dfb_surface_allocation_update( allocation, access );\n     if (ret) {\n          /* Destroy if newly created. */\n          if (allocated)\n               dfb_surface_allocation_decouple( allocation );\n          goto out;\n     }\n\n     ret = dfb_surface_pool_prelock( allocation->pool, allocation, accessor, access );\n     if (ret) {\n          /* Destroy if newly created. */\n          if (allocated)\n               dfb_surface_allocation_decouple( allocation );\n          goto out;\n     }\n\n     manage_interlocks( allocation, accessor, access );\n\n     dfb_surface_allocation_ref( allocation );\n\n     *ret_allocation = allocation;\n\nout:\n     dfb_surface_unlock( obj );\n\n     return ret;\n}\n\nDFBResult\nISurface_Real__PreLockBuffer2( CoreSurface             *obj,\n                               DFBSurfaceBufferRole     role,\n                               DFBSurfaceStereoEye      eye,\n                               CoreSurfaceAccessorID    accessor,\n                               CoreSurfaceAccessFlags   access,\n                               DFBBoolean               lock,\n                               CoreSurfaceAllocation  **ret_allocation )\n{\n     DFBResult              ret;\n     CoreSurfaceBuffer     *buffer;\n     CoreSurfaceAllocation *allocation;\n     bool                   allocated  = false;\n\n     D_DEBUG_AT( DirectFB_CoreSurface, \"%s( %p, role %u, eye %u, accessor 0x%02x, access 0x%02x, %slock )\\n\",\n                 __FUNCTION__, obj, role, eye, accessor, access, lock ? \"\" : \"no \" );\n\n     ret = dfb_surface_lock( obj );\n     if (ret)\n          return ret;\n\n     if (obj->state & CSSF_DESTROYED) {\n          dfb_surface_unlock( obj );\n          return DFB_DESTROYED;\n     }\n\n     if (obj->num_buffers < 1) {\n          dfb_surface_unlock( obj );\n          return DFB_BUFFEREMPTY;\n     }\n\n     buffer = dfb_surface_get_buffer2( obj, role, eye );\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n\n     D_DEBUG_AT( DirectFB_CoreSurface, \"  -> buffer %p\\n\", buffer );\n\n     if (!lock && access & CSAF_READ) {\n          if (fusion_vector_is_empty( &buffer->allocs )) {\n               dfb_surface_unlock( obj );\n               return DFB_NOALLOCATION;\n          }\n     }\n\n     /* Look for allocation with proper access. */\n     allocation = dfb_surface_buffer_find_allocation( buffer, accessor, access, lock );\n     if (!allocation) {\n          /* If no allocation exists, create one. */\n          ret = dfb_surface_pools_allocate( buffer, accessor, access, &allocation );\n          if (ret) {\n               if (ret != DFB_NOVIDEOMEMORY && ret != DFB_UNSUPPORTED)\n                    D_DERROR( ret, \"DirectFB/CoreSurface: Buffer allocation failed!\\n\" );\n\n               goto out;\n          }\n\n          allocated = true;\n     }\n\n     CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n     /* Synchronize with other allocations. */\n     ret = dfb_surface_allocation_update( allocation, access );\n     if (ret) {\n          /* Destroy if newly created. */\n          if (allocated)\n               dfb_surface_allocation_decouple( allocation );\n          goto out;\n     }\n\n     if (!lock) {\n          if (access & CSAF_WRITE) {\n               if (!(allocation->pool->desc.caps & CSPCAPS_WRITE))\n                    lock = DFB_TRUE;\n          }\n          else if (access & CSAF_READ) {\n               if (!(allocation->pool->desc.caps & CSPCAPS_READ))\n                    lock = DFB_TRUE;\n          }\n     }\n\n     if (lock) {\n          ret = dfb_surface_pool_prelock( allocation->pool, allocation, accessor, access );\n          if (ret) {\n               /* Destroy if newly created. */\n               if (allocated)\n                    dfb_surface_allocation_decouple( allocation );\n               goto out;\n          }\n\n          manage_interlocks( allocation, accessor, access );\n     }\n\n     dfb_surface_allocation_ref( allocation );\n\n     *ret_allocation = allocation;\n\nout:\n     dfb_surface_unlock( obj );\n\n     return ret;\n}\n\nDFBResult\nISurface_Real__PreLockBuffer3( CoreSurface             *obj,\n                               DFBSurfaceBufferRole     role,\n                               u32                      flip_count,\n                               DFBSurfaceStereoEye      eye,\n                               CoreSurfaceAccessorID    accessor,\n                               CoreSurfaceAccessFlags   access,\n                               DFBBoolean               lock,\n                               CoreSurfaceAllocation  **ret_allocation )\n{\n     DFBResult              ret;\n     CoreSurfaceBuffer     *buffer;\n     CoreSurfaceAllocation *allocation;\n     bool                   allocated  = false;\n\n     D_DEBUG_AT( DirectFB_CoreSurface, \"%s( %p, role %u, count %u, eye %u, accessor 0x%02x, access 0x%02x, %slock )\\n\",\n                 __FUNCTION__, obj, role, flip_count, eye, accessor, access, lock ? \"\" : \"no \" );\n\n     ret = dfb_surface_lock( obj );\n     if (ret)\n          return ret;\n\n     if (obj->num_buffers < 1) {\n          dfb_surface_unlock( obj );\n          return DFB_BUFFEREMPTY;\n     }\n\n     buffer = dfb_surface_get_buffer3( obj, role, eye, flip_count );\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n\n     D_DEBUG_AT( DirectFB_CoreSurface, \"  -> buffer %p\\n\", buffer );\n\n     if (!lock && access & CSAF_READ) {\n          if (fusion_vector_is_empty( &buffer->allocs )) {\n               dfb_surface_unlock( obj );\n               return DFB_NOALLOCATION;\n          }\n     }\n\n     /* Look for allocation with proper access. */\n     allocation = dfb_surface_buffer_find_allocation( buffer, accessor, access, lock );\n     if (!allocation) {\n          /* If no allocation exists, create one. */\n          ret = dfb_surface_pools_allocate( buffer, accessor, access, &allocation );\n          if (ret) {\n               if (ret != DFB_NOVIDEOMEMORY && ret != DFB_UNSUPPORTED)\n                    D_DERROR( ret, \"DirectFB/CoreSurface: Buffer allocation failed!\\n\" );\n\n               goto out;\n          }\n\n          allocated = true;\n     }\n\n     CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n     D_DEBUG_AT( DirectFB_CoreSurface, \"  -> allocation %p\\n\", allocation );\n\n     /* Synchronize with other allocations. */\n     ret = dfb_surface_allocation_update( allocation, access );\n     if (ret) {\n          /* Destroy if newly created. */\n          if (allocated)\n               dfb_surface_allocation_decouple( allocation );\n          goto out;\n     }\n\n     if (!lock) {\n          if (access & CSAF_WRITE) {\n               if (!(allocation->pool->desc.caps & CSPCAPS_WRITE))\n                    lock = DFB_TRUE;\n          }\n          else if (access & CSAF_READ) {\n               if (!(allocation->pool->desc.caps & CSPCAPS_READ))\n                    lock = DFB_TRUE;\n          }\n     }\n\n     if (lock) {\n          ret = dfb_surface_pool_prelock( allocation->pool, allocation, accessor, access );\n          if (ret) {\n               /* Destroy if newly created. */\n               if (allocated)\n                    dfb_surface_allocation_decouple( allocation );\n               goto out;\n          }\n\n          manage_interlocks( allocation, accessor, access );\n     }\n\n     dfb_surface_allocation_ref( allocation );\n\n     *ret_allocation = allocation;\n\nout:\n     dfb_surface_unlock( obj );\n\n     return ret;\n}\n\nDFBResult\nISurface_Real__DispatchUpdate( CoreSurface         *obj,\n                               DFBBoolean           swap,\n                               const DFBRegion     *left,\n                               const DFBRegion     *right,\n                               DFBSurfaceFlipFlags  flags,\n                               s64                  timestamp,\n                               u32                  flip_count )\n{\n     DFBRegion l, r;\n\n     D_DEBUG_AT( DirectFB_CoreSurface, \"%s( %p, timestamp %lld, flip_count %u )\\n\", __FUNCTION__,\n                 obj, (long long) timestamp, flip_count );\n\n     dfb_surface_lock( obj );\n\n     if (left)\n          l = *left;\n     else {\n          l.x1 = 0;\n          l.y1 = 0;\n          l.x2 = obj->config.size.w - 1;\n          l.y2 = obj->config.size.h - 1;\n     }\n\n     if (right)\n          r = *right;\n     else\n          r = l;\n\n     if (!(flags & DSFLIP_UPDATE))\n          obj->flips = flip_count;\n\n     dfb_surface_dispatch_update( obj, &l, &r, timestamp, flags );\n\n     dfb_surface_unlock( obj );\n\n     return DFB_OK;\n}\n\nDFBResult\nISurface_Real__Flip2( CoreSurface         *obj,\n                      DFBBoolean           swap,\n                      const DFBRegion     *left,\n                      const DFBRegion     *right,\n                      DFBSurfaceFlipFlags  flags,\n                      s64                  timestamp )\n{\n     DFBResult ret;\n     DFBRegion l, r;\n\n     D_DEBUG_AT( DirectFB_CoreSurface, \"%s( %p, timestamp %lld )\\n\", __FUNCTION__, obj, (long long) timestamp );\n\n     dfb_surface_lock( obj );\n\n     if (left)\n          l = *left;\n     else {\n          l.x1 = 0;\n          l.y1 = 0;\n          l.x2 = obj->config.size.w - 1;\n          l.y2 = obj->config.size.h - 1;\n     }\n\n     if (right)\n          r = *right;\n     else\n          r = l;\n\n     if (obj->config.caps & DSCAPS_FLIPPING) {\n          if (obj->config.caps & DSCAPS_STEREO) {\n               if ((flags & DSFLIP_SWAP) ||\n                   (!(flags & DSFLIP_BLIT)         &&\n                    l.x1 == 0 && l.y1 == 0         &&\n                    l.x2 == obj->config.size.w - 1 &&\n                    l.y2 == obj->config.size.h - 1 &&\n                    r.x1 == 0 && r.y1 == 0         &&\n                    r.x2 == obj->config.size.w - 1 &&\n                    r.y2 == obj->config.size.h - 1)) {\n                    ret = dfb_surface_flip_buffers( obj, swap );\n                    if (ret)\n                        goto out;\n               }\n               else {\n                    if (left)\n                         dfb_gfx_copy_regions_client( obj, DSBR_BACK, DSSE_LEFT, obj, DSBR_FRONT, DSSE_LEFT, &l,\n                                                      1, 0, 0, NULL );\n                    if (right)\n                         dfb_gfx_copy_regions_client( obj, DSBR_BACK, DSSE_RIGHT, obj, DSBR_FRONT, DSSE_RIGHT, &r,\n                                                      1, 0, 0, NULL );\n               }\n          }\n          else {\n               if ((flags & DSFLIP_SWAP) ||\n                   (!(flags & DSFLIP_BLIT)         &&\n                    l.x1 == 0 && l.y1 == 0         &&\n                    l.x2 == obj->config.size.w - 1 &&\n                    l.y2 == obj->config.size.h - 1)) {\n                    ret = dfb_surface_flip_buffers( obj, swap );\n                    if (ret)\n                        goto out;\n               }\n               else {\n                    dfb_gfx_copy_regions_client( obj, DSBR_BACK, DSSE_LEFT, obj, DSBR_FRONT, DSSE_LEFT, &l,\n                                                 1, 0, 0, NULL );\n               }\n          }\n     }\n\n     dfb_surface_dispatch_update( obj, &l, &r, timestamp, flags );\n\n     ret = DFB_OK;\n\nout:\n     dfb_surface_unlock( obj );\n\n     return ret;\n}\n\nDFBResult\nISurface_Real__SetField( CoreSurface *obj,\n                         s32          field )\n{\n     D_DEBUG_AT( DirectFB_CoreSurface, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_surface_set_field( obj, field );\n}\n\nDFBResult\nISurface_Real__CreateClient( CoreSurface        *obj,\n                             CoreSurfaceClient **ret_client )\n{\n     D_DEBUG_AT( DirectFB_CoreSurface, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_ASSERT( ret_client != NULL );\n\n     return dfb_surface_client_create( core_dfb, obj, ret_client );\n}\n\nDFBResult\nISurface_Real__Allocate( CoreSurface            *obj,\n                         DFBSurfaceBufferRole    role,\n                         DFBSurfaceStereoEye     eye,\n                         const char             *key,\n                         u32                     key_len,\n                         u64                     handle,\n                         CoreSurfaceAllocation **ret_allocation )\n{\n     DFBResult              ret;\n     CoreSurfaceBuffer     *buffer;\n     CoreSurfaceAllocation *allocation;\n\n     D_ASSERT( key != NULL );\n     D_ASSERT( key_len > 0 );\n     D_ASSERT( key[key_len-1] == 0 );\n     D_ASSERT( ret_allocation != NULL );\n\n     D_DEBUG_AT( DirectFB_CoreSurface, \"%s( %p, role %u, eye %u, key '%s', handle 0x%08llx )\\n\", __FUNCTION__,\n                 obj, role, eye, key, (unsigned long long) handle );\n\n     ret = dfb_surface_lock( obj );\n     if (ret)\n          return ret;\n\n     if (obj->num_buffers == 0) {\n          ret = DFB_NOBUFFER;\n          goto out;\n     }\n\n     buffer = dfb_surface_get_buffer3( obj, role, eye, obj->flips );\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n\n     ret = dfb_surface_pools_allocate_key( buffer, key, handle, &allocation );\n     if (ret)\n          goto out;\n\n     CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n     dfb_surface_allocation_update( allocation, CSAF_WRITE );\n\n     ret = dfb_surface_allocation_ref( allocation );\n     if (ret)\n          goto out;\n\n     *ret_allocation = allocation;\n\nout:\n     dfb_surface_unlock( obj );\n\n     return ret;\n}\n\nDFBResult\nISurface_Real__GetAllocation( CoreSurface            *obj,\n                              DFBSurfaceBufferRole    role,\n                              DFBSurfaceStereoEye     eye,\n                              const char             *key,\n                              u32                     key_len,\n                              CoreSurfaceAllocation **ret_allocation )\n{\n     DFBResult              ret;\n     CoreSurfaceBuffer     *buffer;\n     CoreSurfaceAllocation *allocation;\n\n     D_ASSERT( key != NULL );\n     D_ASSERT( key_len > 0 );\n     D_ASSERT( key[key_len-1] == 0 );\n     D_ASSERT( ret_allocation != NULL );\n\n     D_DEBUG_AT( DirectFB_CoreSurface, \"%s( %p, role %u, eye %u, key '%s' )\\n\", __FUNCTION__, obj, role, eye, key );\n\n     if (eye != DSSE_LEFT && eye != DSSE_RIGHT)\n          return DFB_INVARG;\n\n     ret = dfb_surface_lock( obj );\n     if (ret)\n          return ret;\n\n     if (obj->num_buffers == 0) {\n          ret = DFB_NOBUFFER;\n          goto out;\n     }\n\n     if (role > obj->num_buffers - 1) {\n          ret = DFB_LIMITEXCEEDED;\n          goto out;\n     }\n\n     if (eye == DSSE_RIGHT && !(obj->config.caps & DSCAPS_STEREO)) {\n          ret = DFB_INVAREA;\n          goto out;\n     }\n\n     buffer = dfb_surface_get_buffer3( obj, role, eye, obj->flips );\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n\n     allocation = dfb_surface_buffer_find_allocation_key( buffer, key );\n     if (!allocation) {\n          ret = DFB_ITEMNOTFOUND;\n          goto out;\n     }\n\n     CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n     dfb_surface_allocation_update( allocation, CSAF_WRITE );\n\n     ret = dfb_surface_allocation_ref( allocation );\n     if (ret)\n          goto out;\n\n     *ret_allocation = allocation;\n\nout:\n     dfb_surface_unlock( obj );\n\n     return ret;\n}\n"
  },
  {
    "path": "src/core/CoreWindow.flux",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\ninterface {\n        name    IWindow\n        version 1.0\n        object  CoreWindow\n\n        method {\n                name    SetConfig\n\n                arg {\n                        name        config\n                        direction   input\n                        type        struct\n                        typename    CoreWindowConfig\n                }\n\n                arg {\n                        name        keys\n                        direction   input\n                        type        enum\n                        typename    DFBInputDeviceKeySymbol\n                        count       num_keys\n                        optional    yes\n                }\n\n                arg {\n                        name        num_keys\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        flags\n                        direction   input\n                        type        enum\n                        typename    DFBWindowConfigFlags\n                }\n        }\n\n        method {\n                name    GetInsets\n\n                arg {\n                        name        insets\n                        direction   output\n                        type        struct\n                        typename    DFBInsets\n                }\n        }\n\n        method {\n                name    Destroy\n        }\n\n        method {\n                name    ChangeEvents\n\n                arg {\n                        name        disable\n                        direction   input\n                        type        enum\n                        typename    DFBWindowEventType\n                }\n\n                arg {\n                        name        enable\n                        direction   input\n                        type        enum\n                        typename    DFBWindowEventType\n                }\n        }\n\n        method {\n                name    ChangeOptions\n\n                arg {\n                        name        disable\n                        direction   input\n                        type        enum\n                        typename    DFBWindowOptions\n                }\n\n                arg {\n                        name        enable\n                        direction   input\n                        type        enum\n                        typename    DFBWindowOptions\n                }\n        }\n\n        method {\n                name    SetColor\n\n                arg {\n                        name        color\n                        direction   input\n                        type        struct\n                        typename    DFBColor\n                }\n        }\n\n        method {\n                name    SetColorKey\n\n                arg {\n                        name        key\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    SetOpacity\n\n                arg {\n                        name        opacity\n                        direction   input\n                        type        int\n                        typename    u8\n                }\n        }\n\n        method {\n                name    SetOpaque\n\n                arg {\n                        name        opaque\n                        direction   input\n                        type        struct\n                        typename    DFBRegion\n                }\n        }\n\n        method {\n                name    SetCursorShape\n\n                arg {\n                        name        shape\n                        direction   input\n                        type        object\n                        typename    CoreSurface\n                        optional    yes\n                }\n\n                arg {\n                        name        hotspot\n                        direction   input\n                        type        struct\n                        typename    DFBPoint\n                }\n        }\n\n        method {\n                name    Move\n\n                arg {\n                        name        dx\n                        direction   input\n                        type        int\n                        typename    s32\n                }\n\n                arg {\n                        name        dy\n                        direction   input\n                        type        int\n                        typename    s32\n                }\n        }\n\n        method {\n                name    MoveTo\n\n                arg {\n                        name        x\n                        direction   input\n                        type        int\n                        typename    s32\n                }\n\n                arg {\n                        name        y\n                        direction   input\n                        type        int\n                        typename    s32\n                }\n        }\n\n        method {\n                name    Resize\n\n                arg {\n                        name        width\n                        direction   input\n                        type        int\n                        typename    s32\n                }\n\n                arg {\n                        name        height\n                        direction   input\n                        type        int\n                        typename    s32\n                }\n        }\n\n        method {\n                name    SetBounds\n\n                arg {\n                        name        bounds\n                        direction   input\n                        type        struct\n                        typename    DFBRectangle\n                }\n        }\n\n        method {\n                name    SetStacking\n\n                arg {\n                        name        stacking\n                        direction   input\n                        type        enum\n                        typename    DFBWindowStackingClass\n                }\n        }\n\n        method {\n                name    Restack\n\n                arg {\n                        name        relative\n                        direction   input\n                        type        object\n                        typename    CoreWindow\n                        optional    yes\n                }\n\n                arg {\n                        name        relation\n                        direction   input\n                        type        int\n                        typename    s32\n                }\n        }\n\n        method {\n                name    Bind\n\n                arg {\n                        name        source\n                        direction   input\n                        type        object\n                        typename    CoreWindow\n                }\n\n                arg {\n                        name        x\n                        direction   input\n                        type        int\n                        typename    s32\n                }\n\n                arg {\n                        name        y\n                        direction   input\n                        type        int\n                        typename    s32\n                }\n        }\n\n        method {\n                name    Unbind\n\n                arg {\n                        name        source\n                        direction   input\n                        type        object\n                        typename    CoreWindow\n                }\n        }\n\n        method {\n                name    RequestFocus\n        }\n\n        method {\n                name    ChangeGrab\n\n                arg {\n                        name        target\n                        direction   input\n                        type        enum\n                        typename    CoreWMGrabTarget\n                }\n\n                arg {\n                        name        grab\n                        direction   input\n                        type        enum\n                        typename    DFBBoolean\n                }\n        }\n\n        method {\n                name    GrabKey\n\n                arg {\n                        name        symbol\n                        direction   input\n                        type        enum\n                        typename    DFBInputDeviceKeySymbol\n                }\n\n                arg {\n                        name        modifiers\n                        direction   input\n                        type        enum\n                        typename    DFBInputDeviceModifierMask\n                }\n        }\n\n        method {\n                name    UngrabKey\n\n                arg {\n                        name        symbol\n                        direction   input\n                        type        enum\n                        typename    DFBInputDeviceKeySymbol\n                }\n\n                arg {\n                        name        modifiers\n                        direction   input\n                        type        enum\n                        typename    DFBInputDeviceModifierMask\n                }\n        }\n\n        method {\n                name    SetKeySelection\n\n                arg {\n                        name        selection\n                        direction   input\n                        type        enum\n                        typename    DFBWindowKeySelection\n                }\n\n                arg {\n                        name        keys\n                        direction   input\n                        type        enum\n                        typename    DFBInputDeviceKeySymbol\n                        count       num_keys\n                        optional    yes\n                }\n\n                arg {\n                        name        num_keys\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    SetRotation\n\n                arg {\n                        name        rotation\n                        direction   input\n                        type        int\n                        typename    s32\n                }\n        }\n\n        method {\n                name    BeginUpdates\n\n                arg {\n                        name        update\n                        direction   input\n                        type        struct\n                        typename    DFBRegion\n                        optional    yes\n                }\n        }\n\n        method {\n                name    PostEvent\n\n                arg {\n                        name        event\n                        direction   input\n                        type        struct\n                        typename    DFBWindowEvent\n                }\n        }\n\n       method {\n                name    SetCursorPosition\n\n                arg {\n                        name        x\n                        direction   input\n                        type        int\n                        typename    s32\n                }\n\n                arg {\n                        name        y\n                        direction   input\n                        type        int\n                        typename    s32\n                }\n        }\n\n        method {\n                name    SetTypeHint\n\n                arg {\n                        name        type_hint\n                        direction   input\n                        type        enum\n                        typename    DFBWindowTypeHint\n                }\n        }\n\n        method {\n                name    ChangeHintFlags\n\n                arg {\n                        name        clear\n                        direction   input\n                        type        enum\n                        typename    DFBWindowHintFlags\n                }\n\n                arg {\n                        name        set\n                        direction   input\n                        type        enum\n                        typename    DFBWindowHintFlags\n                }\n        }\n \n        method {\n                name    AllowFocus\n        }\n\n        method {\n                name    GetSurface\n\n                arg {\n                        name        surface\n                        direction   output\n                        type        object\n                        typename    CoreSurface\n                }\n        }\n}\n"
  },
  {
    "path": "src/core/CoreWindowStack.flux",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\ninterface {\n        name    IWindowStack\n        version 1.0\n        object  CoreWindowStack\n\n        method {\n                name    RepaintAll\n        }\n\n        method {\n                name    BackgroundSetMode\n\n                arg {\n                        name        mode\n                        direction   input\n                        type        enum\n                        typename    DFBDisplayLayerBackgroundMode\n                }\n        }\n\n        method {\n                name    BackgroundSetImage\n\n                arg {\n                        name        image\n                        direction   input\n                        type        object\n                        typename    CoreSurface\n                }\n        }\n\n        method {\n                name    BackgroundSetColor\n\n                arg {\n                        name        color\n                        direction   input\n                        type        struct\n                        typename    DFBColor\n                }\n        }\n\n        method {\n                name    BackgroundSetColorIndex\n\n                arg {\n                        name        index\n                        direction   input\n                        type        int\n                        typename    s32\n                }\n        }\n\n        method {\n                name    CursorEnable\n\n                arg {\n                        name        enable\n                        direction   input\n                        type        enum\n                        typename    bool\n                }\n        }\n\n        method {\n                name    CursorGetPosition\n\n                arg {\n                        name        position\n                        direction   output\n                        type        struct\n                        typename    DFBPoint\n                }\n        }\n\n        method {\n                name    CursorWarp\n\n                arg {\n                        name        position\n                        direction   input\n                        type        struct\n                        typename    DFBPoint\n                }\n        }\n\n        method {\n                name    CursorSetAcceleration\n\n                arg {\n                        name        numerator\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        denominator\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n\n                arg {\n                        name        threshold\n                        direction   input\n                        type        int\n                        typename    u32\n                }\n        }\n\n        method {\n                name    CursorSetShape\n\n                arg {\n                        name        shape\n                        direction   input\n                        type        object\n                        typename    CoreSurface\n                }\n\n                arg {\n                        name        hotspot\n                        direction   input\n                        type        struct\n                        typename    DFBPoint\n                }\n        }\n\n        method {\n                name    CursorSetOpacity\n\n                arg {\n                        name        opacity\n                        direction   input\n                        type        int\n                        typename    u8\n                }\n        }\n}\n"
  },
  {
    "path": "src/core/CoreWindowStack_includes.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreDFB_includes.h>\n\nstatic __inline__ DirectResult\nCoreWindowStack_Call( CoreWindowStack     *stack,\n                      FusionCallExecFlags  flags,\n                      int                  call_arg,\n                      void                *ptr,\n                      unsigned int         length,\n                      void                *ret_ptr,\n                      unsigned int         ret_size,\n                      unsigned int        *ret_length )\n{\n     return fusion_call_execute3( &stack->call, dfb_config->call_nodirect | flags, call_arg, ptr, length,\n                                  ret_ptr, ret_size, ret_length );\n}\n"
  },
  {
    "path": "src/core/CoreWindowStack_real.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreWindowStack.h>\n#include <core/layer_context.h>\n#include <core/windowstack.h>\n\nD_DEBUG_DOMAIN( DirectFB_CoreWindowStack, \"DirectFB/CoreWindowStack\", \"DirectFB CoreWindowStack\" );\n\n/**********************************************************************************************************************/\n\nDFBResult\nIWindowStack_Real__RepaintAll( CoreWindowStack *obj )\n{\n     D_DEBUG_AT( DirectFB_CoreWindowStack, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_windowstack_repaint_all( obj );\n}\n\nDFBResult\nIWindowStack_Real__BackgroundSetMode( CoreWindowStack               *obj,\n                                      DFBDisplayLayerBackgroundMode  mode )\n{\n     D_DEBUG_AT( DirectFB_CoreWindowStack, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_windowstack_set_background_mode( obj, mode );\n}\n\nDFBResult\nIWindowStack_Real__BackgroundSetImage( CoreWindowStack *obj,\n                                       CoreSurface     *image )\n{\n     D_DEBUG_AT( DirectFB_CoreWindowStack, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_windowstack_set_background_image( obj, image );\n}\n\nDFBResult\nIWindowStack_Real__BackgroundSetColor( CoreWindowStack *obj,\n                                       const DFBColor  *color )\n{\n     D_DEBUG_AT( DirectFB_CoreWindowStack, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_windowstack_set_background_color( obj, color );\n}\n\nDFBResult\nIWindowStack_Real__BackgroundSetColorIndex( CoreWindowStack *obj,\n                                            s32              index )\n{\n     D_DEBUG_AT( DirectFB_CoreWindowStack, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_windowstack_set_background_color_index( obj, index );\n}\n\nDFBResult\nIWindowStack_Real__CursorEnable( CoreWindowStack *obj,\n                                 bool             enable )\n{\n     D_DEBUG_AT( DirectFB_CoreWindowStack, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_windowstack_cursor_enable( obj, enable );\n}\n\nDFBResult\nIWindowStack_Real__CursorGetPosition( CoreWindowStack *obj,\n                                      DFBPoint        *ret_position )\n{\n     D_DEBUG_AT( DirectFB_CoreWindowStack, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_windowstack_get_cursor_position( obj, &ret_position->x, &ret_position->y );\n}\n\nDFBResult\nIWindowStack_Real__CursorWarp( CoreWindowStack *obj,\n                               const DFBPoint  *position )\n{\n     D_DEBUG_AT( DirectFB_CoreWindowStack, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_windowstack_cursor_warp( obj, position->x, position->y );\n}\n\nDFBResult\nIWindowStack_Real__CursorSetAcceleration( CoreWindowStack *obj,\n                                          u32              numerator,\n                                          u32              denominator,\n                                          u32              threshold )\n{\n     D_DEBUG_AT( DirectFB_CoreWindowStack, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_windowstack_cursor_set_acceleration( obj, numerator, denominator, threshold );\n}\nDFBResult\nIWindowStack_Real__CursorSetShape( CoreWindowStack *obj,\n                                   CoreSurface     *shape,\n                                   const DFBPoint  *hotspot )\n{\n     D_DEBUG_AT( DirectFB_CoreWindowStack, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     dfb_layer_context_set_cursor_shape( obj->context, shape, hotspot->x, hotspot->y );\n\n     return dfb_windowstack_cursor_set_shape( obj, shape, hotspot->x, hotspot->y );\n}\n\nDFBResult\nIWindowStack_Real__CursorSetOpacity( CoreWindowStack *obj,\n                                     u8               opacity )\n{\n     D_DEBUG_AT( DirectFB_CoreWindowStack, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     return dfb_windowstack_cursor_set_opacity( obj, opacity );\n}\n"
  },
  {
    "path": "src/core/CoreWindow_includes.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreDFB_includes.h>\n\nstatic __inline__ DirectResult\nCoreWindow_Call( CoreWindow          *window,\n                 FusionCallExecFlags  flags,\n                 int                  call_arg,\n                 void                *ptr,\n                 unsigned int         length,\n                 void                *ret_ptr,\n                 unsigned int         ret_size,\n                 unsigned int        *ret_length )\n{\n     return fusion_call_execute3( &window->call, dfb_config->call_nodirect | flags, call_arg, ptr, length,\n                                  ret_ptr, ret_size, ret_length );\n}\n"
  },
  {
    "path": "src/core/CoreWindow_real.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreWindow.h>\n#include <core/core.h>\n#include <core/layer_context.h>\n#include <core/surface.h>\n#include <core/windowstack.h>\n#include <core/windows.h>\n#include <core/wm.h>\n\nD_DEBUG_DOMAIN( Core_Window, \"DirectFB/CoreWindow\", \"DirectFB CoreWindow\" );\n\n/**********************************************************************************************************************/\n\nDFBResult\nIWindow_Real__SetConfig( CoreWindow                    *obj,\n                         const CoreWindowConfig        *config,\n                         const DFBInputDeviceKeySymbol *keys,\n                         u32                            num_keys,\n                         DFBWindowConfigFlags           flags )\n{\n     CoreWindowConfig config_copy;\n\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n     D_ASSERT( config != NULL );\n\n     if ((flags & DWCONF_ASSOCIATION) && config->association) {\n          DFBResult ret;\n          CoreWindow *parent;\n\n          ret = dfb_core_get_window( core_dfb, config->association, &parent );\n          if (ret)\n               return ret;\n\n          if (fusion_object_check_owner( &parent->object, Core_GetIdentity(), false )) {\n               dfb_window_unref( parent );\n               return DFB_ACCESSDENIED;\n          }\n\n          dfb_window_unref( parent );\n     }\n\n     config_copy = *config;\n\n     config_copy.keys     = (DFBInputDeviceKeySymbol*) keys;\n     config_copy.num_keys = num_keys;\n\n     return dfb_window_set_config( obj, &config_copy, flags );\n}\n\nDFBResult\nIWindow_Real__GetInsets( CoreWindow *obj,\n                         DFBInsets  *ret_insets )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     ret = dfb_layer_context_lock( obj->stack->context );\n     if (ret)\n          return ret;\n\n     ret = dfb_wm_get_insets( obj->stack, obj, ret_insets );\n\n     dfb_layer_context_unlock( obj->stack->context );\n\n     return ret;\n}\n\nDFBResult\nIWindow_Real__Destroy( CoreWindow *obj )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     dfb_window_destroy( obj );\n\n     return DFB_OK;\n}\n\nDFBResult\nIWindow_Real__ChangeEvents( CoreWindow         *obj,\n                            DFBWindowEventType  disable,\n                            DFBWindowEventType  enable )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     return dfb_window_change_events( obj, disable, enable );\n}\n\nDFBResult\nIWindow_Real__ChangeOptions( CoreWindow       *obj,\n                             DFBWindowOptions  disable,\n                             DFBWindowOptions  enable )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     return dfb_window_change_options( obj, disable, enable );\n}\n\nDFBResult\nIWindow_Real__SetColor( CoreWindow     *obj,\n                        const DFBColor *color )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     return dfb_window_set_color( obj, *color );\n}\n\nDFBResult\nIWindow_Real__SetColorKey( CoreWindow *obj,\n                           u32         key )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     return dfb_window_set_colorkey( obj, key );\n}\n\nDFBResult\nIWindow_Real__SetOpacity( CoreWindow *obj,\n                          u8          opacity )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     return dfb_window_set_opacity( obj, opacity );\n}\n\nDFBResult\nIWindow_Real__SetOpaque( CoreWindow      *obj,\n                         const DFBRegion *opaque )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     return dfb_window_set_opaque( obj, opaque );\n}\n\nDFBResult\nIWindow_Real__SetCursorShape( CoreWindow     *obj,\n                              CoreSurface    *shape,\n                              const DFBPoint *hotspot )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     return dfb_window_set_cursor_shape( obj, shape, hotspot->x, hotspot->y );\n}\n\nDFBResult\nIWindow_Real__Move( CoreWindow *obj,\n                    s32         dx,\n                    s32         dy )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     return dfb_window_move( obj, dx, dy, true );\n}\n\nDFBResult\nIWindow_Real__MoveTo( CoreWindow *obj,\n                      s32         x,\n                      s32         y )\n{\n     DFBResult ret;\n     DFBInsets insets;\n\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     dfb_windowstack_lock( obj->stack );\n\n     dfb_wm_get_insets( obj->stack, obj, &insets );\n\n     ret = dfb_window_move( obj, x + insets.l, y + insets.t, false );\n\n     dfb_windowstack_unlock( obj->stack );\n\n     return ret;\n}\n\nDFBResult\nIWindow_Real__Resize( CoreWindow *obj,\n                      s32         width,\n                      s32         height )\n{\n     DFBResult ret;\n     DFBInsets insets;\n\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     dfb_windowstack_lock( obj->stack );\n\n     dfb_wm_get_insets( obj->stack, obj, &insets );\n\n     ret = dfb_window_resize( obj, width + insets.l+insets.r, height + insets.t+insets.b );\n\n     dfb_windowstack_unlock( obj->stack );\n\n     return ret;\n}\n\nDFBResult\nIWindow_Real__SetBounds( CoreWindow         *obj,\n                         const DFBRectangle *bounds )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     return dfb_window_set_bounds( obj, bounds->x, bounds->y, bounds->w, bounds->h );\n}\n\nDFBResult\nIWindow_Real__SetStacking( CoreWindow             *obj,\n                           DFBWindowStackingClass  stacking )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     return dfb_window_change_stacking( obj, stacking );\n}\n\nDFBResult\nIWindow_Real__Restack( CoreWindow *obj,\n                       CoreWindow *relative,\n                       s32         relation )\n{\n     DFBResult        ret;\n     CoreWindowStack *stack;\n\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n     D_ASSERT( obj->stack != NULL );\n\n     stack = obj->stack;\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( obj )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     /* Let the window manager do its work. */\n     ret = dfb_wm_restack_window( obj, relative, relation );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\nIWindow_Real__Bind( CoreWindow *obj,\n                    CoreWindow *source,\n                    s32         x,\n                    s32         y )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n     D_MAGIC_ASSERT( source, CoreWindow );\n\n     return dfb_window_bind( obj, source, x, y );\n}\n\nDFBResult\nIWindow_Real__Unbind( CoreWindow *obj,\n                      CoreWindow *source )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n     D_MAGIC_ASSERT( source, CoreWindow );\n\n     return dfb_window_unbind( obj, source );\n}\n\nDFBResult\nIWindow_Real__RequestFocus( CoreWindow *obj )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     return dfb_window_request_focus( obj );\n}\n\nDFBResult\nIWindow_Real__ChangeGrab( CoreWindow       *obj,\n                          CoreWMGrabTarget  target,\n                          DFBBoolean        grab )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     return dfb_window_change_grab( obj, target, grab );\n}\n\nDFBResult\nIWindow_Real__GrabKey( CoreWindow                 *obj,\n                       DFBInputDeviceKeySymbol     symbol,\n                       DFBInputDeviceModifierMask  modifiers )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     return dfb_window_grab_key( obj, symbol, modifiers );\n}\n\nDFBResult\nIWindow_Real__UngrabKey( CoreWindow                 *obj,\n                         DFBInputDeviceKeySymbol     symbol,\n                         DFBInputDeviceModifierMask  modifiers )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     return dfb_window_ungrab_key( obj, symbol, modifiers );\n}\n\nDFBResult\nIWindow_Real__SetKeySelection( CoreWindow                    *obj,\n                               DFBWindowKeySelection          selection,\n                               const DFBInputDeviceKeySymbol *keys,\n                               u32                            num_keys )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     return dfb_window_set_key_selection( obj, selection, keys, num_keys );\n}\n\nDFBResult\nIWindow_Real__SetRotation( CoreWindow *obj,\n                           s32         rotation )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     return dfb_window_set_rotation( obj, rotation );\n}\n\nDFBResult\nIWindow_Real__BeginUpdates( CoreWindow      *obj,\n                            const DFBRegion *update )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     dfb_windowstack_lock( obj->stack );\n\n     ret = dfb_wm_begin_updates( obj, update );\n\n     dfb_windowstack_unlock( obj->stack );\n\n     return ret;\n}\n\nDFBResult\nIWindow_Real__PostEvent( CoreWindow           *obj,\n                         const DFBWindowEvent *event )\n{\n     DFBWindowEvent e;\n\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     e = *event;\n\n     dfb_window_post_event( obj, &e );\n\n     return DFB_OK;\n}\n\nDFBResult\nIWindow_Real__SetCursorPosition( CoreWindow *obj,\n                                 s32         x,\n                                 s32         y )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     dfb_windowstack_lock( obj->stack );\n\n     ret = dfb_wm_set_cursor_position( obj, x, y );\n\n     dfb_windowstack_unlock( obj->stack );\n\n     return ret;\n}\n\nDFBResult\nIWindow_Real__SetTypeHint( CoreWindow        *obj,\n                           DFBWindowTypeHint  type_hint )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     return dfb_window_set_type_hint( obj, type_hint );\n}\n\nDFBResult\nIWindow_Real__ChangeHintFlags( CoreWindow         *obj,\n                               DFBWindowHintFlags  clear,\n                               DFBWindowHintFlags  set )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     return dfb_window_change_hint_flags( obj, clear, set );\n}\n\nDFBResult\nIWindow_Real__AllowFocus( CoreWindow *obj )\n{\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n\n     obj->caps = (DFBWindowCapabilities) ((obj->caps & ~DWCAPS_NOFOCUS) | (obj->requested_caps & DWCAPS_NOFOCUS));\n\n     return DFB_OK;\n}\n\nDFBResult\nIWindow_Real__GetSurface( CoreWindow   *obj,\n                          CoreSurface **ret_surface )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_Window, \"%s( %p )\\n\", __FUNCTION__, obj );\n\n     D_MAGIC_ASSERT( obj, CoreWindow );\n     D_ASSERT( ret_surface != NULL );\n\n     if (!obj->surface)\n          return DFB_UNSUPPORTED;\n\n     ret = dfb_surface_ref( obj->surface );\n     if (ret)\n          return ret;\n\n     *ret_surface = obj->surface;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/core/clipboard.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/clipboard.h>\n#include <core/core.h>\n#include <core/core_parts.h>\n#include <direct/memcpy.h>\n#include <fusion/conf.h>\n#include <fusion/shmalloc.h>\n\nD_DEBUG_DOMAIN( Core_Clipboard, \"Core/Clipboard\", \"DirectFB Core Clipboard\" );\n\n/**********************************************************************************************************************/\n\nDFB_CORE_PART( clipboard_core, ClipboardCore );\n\n/**********************************************************************************************************************/\n\nstatic DFBResult\ndfb_clipboard_core_initialize( CoreDFB                *core,\n                               DFBClipboardCore       *data,\n                               DFBClipboardCoreShared *shared )\n{\n     D_DEBUG_AT( Core_Clipboard, \"%s( %p, %p, %p )\\n\", __FUNCTION__, core, data, shared );\n\n     D_ASSERT( data != NULL );\n     D_ASSERT( shared != NULL );\n\n     data->core   = core;\n     data->shared = shared;\n\n     shared->shmpool = dfb_core_shmpool( core );\n\n     fusion_skirmish_init2( &shared->lock, \"Clipboard Core\", dfb_core_world( core ), fusion_config->secure_fusion );\n\n     D_MAGIC_SET( data, DFBClipboardCore );\n     D_MAGIC_SET( shared, DFBClipboardCoreShared );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_clipboard_core_join( CoreDFB                *core,\n                         DFBClipboardCore       *data,\n                         DFBClipboardCoreShared *shared )\n{\n     D_DEBUG_AT( Core_Clipboard, \"%s( %p, %p, %p )\\n\", __FUNCTION__, core, data, shared );\n\n     D_ASSERT( data != NULL );\n     D_MAGIC_ASSERT( shared, DFBClipboardCoreShared );\n\n     data->core   = core;\n     data->shared = shared;\n\n     D_MAGIC_SET( data, DFBClipboardCore );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_clipboard_core_shutdown( DFBClipboardCore *data,\n                             bool              emergency )\n{\n     DFBClipboardCoreShared *shared;\n\n     D_DEBUG_AT( Core_Clipboard, \"%s( %p, %semergency )\\n\", __FUNCTION__, data, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( data, DFBClipboardCore );\n     D_MAGIC_ASSERT( data->shared, DFBClipboardCoreShared );\n\n     shared = data->shared;\n\n     fusion_skirmish_destroy( &shared->lock );\n\n     if (shared->data)\n          SHFREE( shared->shmpool, shared->data );\n\n     if (shared->mime_type)\n          SHFREE( shared->shmpool, shared->mime_type );\n\n     D_MAGIC_CLEAR( data );\n     D_MAGIC_CLEAR( shared );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_clipboard_core_leave( DFBClipboardCore *data,\n                          bool              emergency )\n{\n     D_DEBUG_AT( Core_Clipboard, \"%s( %p, %semergency )\\n\", __FUNCTION__, data, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( data, DFBClipboardCore );\n     D_MAGIC_ASSERT( data->shared, DFBClipboardCoreShared );\n\n     D_MAGIC_CLEAR( data );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_clipboard_core_suspend( DFBClipboardCore *data )\n{\n     D_DEBUG_AT( Core_Clipboard, \"%s( %p )\\n\", __FUNCTION__, data );\n\n     D_MAGIC_ASSERT( data, DFBClipboardCore );\n     D_MAGIC_ASSERT( data->shared, DFBClipboardCoreShared );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_clipboard_core_resume( DFBClipboardCore *data )\n{\n     D_DEBUG_AT( Core_Clipboard, \"%s( %p )\\n\", __FUNCTION__, data );\n\n     D_MAGIC_ASSERT( data, DFBClipboardCore );\n     D_MAGIC_ASSERT( data->shared, DFBClipboardCoreShared );\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_clipboard_set( DFBClipboardCore *core,\n                   const char       *mime_type,\n                   const void       *data,\n                   unsigned int      size,\n                   struct timeval   *timestamp )\n{\n     DFBClipboardCoreShared *shared;\n\n     char *new_mime;\n     void *new_data;\n\n     D_MAGIC_ASSERT( core, DFBClipboardCore );\n     D_MAGIC_ASSERT( core->shared, DFBClipboardCoreShared );\n     D_ASSERT( mime_type != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( size > 0 );\n\n     shared = core->shared;\n\n     new_mime = SHSTRDUP( shared->shmpool, mime_type );\n     if (!new_mime)\n          return D_OOSHM();\n\n     new_data = SHMALLOC( shared->shmpool, size );\n     if (!new_data) {\n          SHFREE( shared->shmpool, new_mime );\n          return D_OOSHM();\n     }\n\n     direct_memcpy( new_data, data, size );\n\n     if (fusion_skirmish_prevail( &shared->lock )) {\n          SHFREE( shared->shmpool, new_data );\n          SHFREE( shared->shmpool, new_mime );\n          return DFB_FUSION;\n     }\n\n     if (shared->data)\n          SHFREE( shared->shmpool, shared->data );\n\n     if (shared->mime_type)\n          SHFREE( shared->shmpool, shared->mime_type );\n\n     shared->mime_type = new_mime;\n     shared->data      = new_data;\n     shared->size      = size;\n\n     shared->timestamp = *timestamp;\n\n     fusion_skirmish_dismiss( &shared->lock );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_clipboard_get( DFBClipboardCore  *core,\n                   char             **mime_type,\n                   void             **data,\n                   unsigned int      *size )\n{\n     DFBClipboardCoreShared *shared;\n\n     D_MAGIC_ASSERT( core, DFBClipboardCore );\n     D_MAGIC_ASSERT( core->shared, DFBClipboardCoreShared );\n\n     shared = core->shared;\n\n     if (fusion_skirmish_prevail( &shared->lock ))\n          return DFB_FUSION;\n\n     if (!shared->mime_type || !shared->data) {\n          fusion_skirmish_dismiss( &shared->lock );\n          return DFB_BUFFEREMPTY;\n     }\n\n     if (mime_type)\n          *mime_type = D_STRDUP( shared->mime_type );\n\n     if (data) {\n          *data = D_MALLOC( shared->size );\n          direct_memcpy( *data, shared->data, shared->size );\n     }\n\n     if (size)\n          *size = shared->size;\n\n     fusion_skirmish_dismiss( &shared->lock );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_clipboard_get_timestamp( DFBClipboardCore *core,\n                             struct timeval   *timestamp )\n{\n     DFBClipboardCoreShared *shared;\n\n     D_MAGIC_ASSERT( core, DFBClipboardCore );\n     D_MAGIC_ASSERT( core->shared, DFBClipboardCoreShared );\n     D_ASSERT( timestamp != NULL );\n\n     shared = core->shared;\n\n     if (fusion_skirmish_prevail( &shared->lock ))\n          return DFB_FUSION;\n\n     *timestamp = shared->timestamp;\n\n     fusion_skirmish_dismiss( &shared->lock );\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/core/clipboard.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__CLIPBOARD_H__\n#define __CORE__CLIPBOARD_H__\n\n#include <core/coretypes.h>\n#include <fusion/lock.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int                  magic;\n\n     FusionSkirmish       lock;\n     char                *mime_type;\n     void                *data;\n     unsigned int         size;\n     struct timeval       timestamp;\n\n     FusionSHMPoolShared *shmpool;\n} DFBClipboardCoreShared;\n\ntypedef struct {\n     int                     magic;\n\n     CoreDFB                *core;\n\n     DFBClipboardCoreShared *shared;\n} DFBClipboardCore;\n\n/**********************************************************************************************************************/\n\nDFBResult dfb_clipboard_set          ( DFBClipboardCore  *core,\n                                       const char        *mime_type,\n                                       const void        *data,\n                                       unsigned int       size,\n                                       struct timeval    *timestamp );\n\nDFBResult dfb_clipboard_get          ( DFBClipboardCore  *core,\n                                       char             **mime_type,\n                                       void             **data,\n                                       unsigned int      *size );\n\nDFBResult dfb_clipboard_get_timestamp( DFBClipboardCore  *core,\n                                       struct timeval    *timestamp );\n\n#endif\n"
  },
  {
    "path": "src/core/colorhash.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/colorhash.h>\n#include <core/core_parts.h>\n#include <core/palette.h>\n#include <gfx/convert.h>\n\nD_DEBUG_DOMAIN( Core_ColorHash, \"Core/ColorHash\", \"DirectFB Core ColorHash\" );\n\n/**********************************************************************************************************************/\n\nDFB_CORE_PART( colorhash_core, ColorHashCore );\n\n/**********************************************************************************************************************/\n\n#define HASH_SIZE 823\n\nstatic DFBColorHashCore *colorhash;\n\nstatic DFBResult\ndfb_colorhash_core_initialize( CoreDFB                *core,\n                               DFBColorHashCore       *data,\n                               DFBColorHashCoreShared *shared )\n{\n     D_DEBUG_AT( Core_ColorHash, \"%s( %p, %p, %p )\\n\", __FUNCTION__, core, data, shared );\n\n     D_ASSERT( data != NULL );\n     D_ASSERT( shared != NULL );\n\n     colorhash = data;\n\n     data->core   = core;\n     data->shared = shared;\n\n     data->hash = D_CALLOC( HASH_SIZE, sizeof(Colorhash) );\n     if (!data->hash)\n          return D_OOM();\n\n     direct_mutex_init( &data->hash_lock );\n\n     D_MAGIC_SET( data, DFBColorHashCore );\n     D_MAGIC_SET( shared, DFBColorHashCoreShared );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_colorhash_core_join( CoreDFB                *core,\n                         DFBColorHashCore       *data,\n                         DFBColorHashCoreShared *shared )\n{\n     D_DEBUG_AT( Core_ColorHash, \"%s( %p, %p, %p )\\n\", __FUNCTION__, core, data, shared );\n\n     D_ASSERT( data != NULL );\n     D_MAGIC_ASSERT( shared, DFBColorHashCoreShared );\n\n     colorhash = data;\n\n     data->core   = core;\n     data->shared = shared;\n\n     data->hash = D_CALLOC( HASH_SIZE, sizeof(Colorhash) );\n     if (!data->hash)\n          return D_OOM();\n\n     direct_mutex_init( &data->hash_lock );\n\n     D_MAGIC_SET( data, DFBColorHashCore );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_colorhash_core_shutdown( DFBColorHashCore *data,\n                             bool              emergency )\n{\n     D_DEBUG_AT( Core_ColorHash, \"%s( %p, %semergency )\\n\", __FUNCTION__, data, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( data, DFBColorHashCore );\n     D_MAGIC_ASSERT( data->shared, DFBColorHashCoreShared );\n\n     direct_mutex_deinit( &data->hash_lock );\n\n     D_FREE( data->hash );\n\n     D_MAGIC_CLEAR( data );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_colorhash_core_leave( DFBColorHashCore *data,\n                          bool              emergency )\n{\n     D_DEBUG_AT( Core_ColorHash, \"%s( %p, %semergency )\\n\", __FUNCTION__, data, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( data, DFBColorHashCore );\n     D_MAGIC_ASSERT( data->shared, DFBColorHashCoreShared );\n\n     direct_mutex_deinit( &data->hash_lock );\n\n     D_FREE( data->hash );\n\n     D_MAGIC_CLEAR( data );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_colorhash_core_suspend( DFBColorHashCore *data )\n{\n     D_DEBUG_AT( Core_ColorHash, \"%s( %p )\\n\", __FUNCTION__, data );\n\n     D_MAGIC_ASSERT( data, DFBColorHashCore );\n     D_MAGIC_ASSERT( data->shared, DFBColorHashCoreShared );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_colorhash_core_resume( DFBColorHashCore *data )\n{\n     D_DEBUG_AT( Core_ColorHash, \"%s( %p )\\n\", __FUNCTION__, data );\n\n     D_MAGIC_ASSERT( data, DFBColorHashCore );\n     D_MAGIC_ASSERT( data->shared, DFBColorHashCoreShared );\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nunsigned int\ndfb_colorhash_lookup( DFBColorHashCore *core,\n                      CorePalette      *palette,\n                      u8                r,\n                      u8                g,\n                      u8                b,\n                      u8                a )\n{\n     unsigned int pixel = PIXEL_ARGB( a, r, g, b );\n     unsigned int index = (pixel ^ (unsigned long) palette) % HASH_SIZE;\n\n     if (core) {\n          D_MAGIC_ASSERT( core, DFBColorHashCore );\n          D_MAGIC_ASSERT( core->shared, DFBColorHashCoreShared );\n     }\n     else\n          core = colorhash;\n\n     D_ASSERT( core->hash != NULL );\n\n     direct_mutex_lock( &core->hash_lock );\n\n     /* Try a lookup in the hash table. */\n     if (core->hash[index].palette_id == palette->object.id && core->hash[index].pixel == pixel) {\n          /* Set the return value. */\n          index = core->hash[index].index;\n     }\n     /* Look for the closest match. */\n     else {\n          DFBColor     *entries = palette->entries;\n          int           min_diff = 0;\n          unsigned int  i, min_index = 0;\n\n          for (i = 0; i < palette->num_entries; i++) {\n               int diff;\n\n               int r_diff = (int) entries[i].r - (int) r;\n               int g_diff = (int) entries[i].g - (int) g;\n               int b_diff = (int) entries[i].b - (int) b;\n               int a_diff = (int) entries[i].a - (int) a;\n\n               if (a)\n                    diff = (r_diff * r_diff + g_diff * g_diff +\n                            b_diff * b_diff + ((a_diff * a_diff) >> 6));\n               else\n                    diff = (r_diff + g_diff + b_diff + (a_diff * a_diff));\n\n               if (i == 0 || diff < min_diff) {\n                    min_diff = diff;\n                    min_index = i;\n               }\n\n               if (!diff)\n                    break;\n          }\n\n          /* Store the matching entry in the hash table. */\n          core->hash[index].pixel      = pixel;\n          core->hash[index].index      = min_index;\n          core->hash[index].palette_id = palette->object.id;\n\n          /* Set the return value. */\n          index = min_index;\n     }\n\n     direct_mutex_unlock( &core->hash_lock );\n\n     return index;\n}\n\nvoid\ndfb_colorhash_invalidate( DFBColorHashCore *core,\n                          CorePalette      *palette )\n{\n     unsigned int index = HASH_SIZE - 1;\n\n     if (core) {\n          D_MAGIC_ASSERT( core, DFBColorHashCore );\n          D_MAGIC_ASSERT( core->shared, DFBColorHashCoreShared );\n     }\n     else\n          core = colorhash;\n\n     D_ASSERT( core->hash != NULL );\n\n     direct_mutex_lock( &core->hash_lock );\n\n     /* Invalidate all entries owned by this palette. */\n     do {\n          if (core->hash[index].palette_id == palette->object.id)\n               core->hash[index].palette_id = 0;\n     } while (index--);\n\n     direct_mutex_unlock( &core->hash_lock );\n}\n"
  },
  {
    "path": "src/core/colorhash.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__COLORHASH_H__\n#define __CORE__COLORHASH_H__\n\n#include <core/coretypes.h>\n#include <direct/mutex.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     unsigned int pixel;\n     unsigned int index;\n     u32          palette_id;\n} Colorhash;\n\ntypedef struct {\n     int magic;\n} DFBColorHashCoreShared;\n\ntypedef struct {\n     int                     magic;\n\n     CoreDFB                *core;\n\n     DFBColorHashCoreShared *shared;\n\n     Colorhash              *hash;\n     DirectMutex             hash_lock;\n} DFBColorHashCore;\n\n/**********************************************************************************************************************/\n\nunsigned int dfb_colorhash_lookup    ( DFBColorHashCore *core,\n                                       CorePalette      *palette,\n                                       u8                r,\n                                       u8                g,\n                                       u8                b,\n                                       u8                a );\n\nvoid         dfb_colorhash_invalidate( DFBColorHashCore *core,\n                                       CorePalette      *palette );\n\n#endif\n"
  },
  {
    "path": "src/core/core.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreDFB.h>\n#include <core/CoreSlave.h>\n#include <core/core.h>\n#include <core/core_parts.h>\n#include <core/fonts.h>\n#include <core/graphics_state.h>\n#include <core/layer_context.h>\n#include <core/palette.h>\n#include <core/surface_allocation.h>\n#include <core/surface_client.h>\n#include <core/system.h>\n#include <core/wm.h>\n#include <direct/direct.h>\n#include <direct/hash.h>\n#include <direct/memcpy.h>\n#include <direct/signals.h>\n#include <direct/system.h>\n#include <direct/thread.h>\n#include <direct/trace.h>\n#include <fusion/conf.h>\n#include <fusion/hash.h>\n#include <fusion/shmalloc.h>\n#include <fusion/shm/pool.h>\n\nD_DEBUG_DOMAIN( Core_Main,     \"Core/Main\",     \"DirectFB Core\" );\nD_DEBUG_DOMAIN( Core_Resource, \"Core/Resource\", \"DirectFB Core Resource\" );\n\n/**********************************************************************************************************************/\n\nstruct __DFB_CoreCleanup {\n     DirectLink       link;\n\n     CoreCleanupFunc  func;      /* the cleanup function to be called */\n     void            *data;      /* context of the cleanup function */\n     bool             emergency; /* if true, cleanup is also done during emergency shutdown (from signal handler) */\n};\n\nstruct __DFB_CoreMemoryPermission {\n     DirectLink                 link;\n\n     CoreMemoryPermissionFlags  flags;\n\n     void                      *data;\n     void                      *end;\n     size_t                     length;\n};\n\nCoreDFB            *core_dfb      = NULL;\nstatic DirectMutex  core_dfb_lock = DIRECT_MUTEX_INITIALIZER();\nstatic DirectTLS    core_tls_key;\n\nextern CorePart dfb_clipboard_core;\nextern CorePart dfb_colorhash_core;\nextern CorePart dfb_graphics_core;\nextern CorePart dfb_input_core;\nextern CorePart dfb_layer_core;\nextern CorePart dfb_screen_core;\nextern CorePart dfb_surface_core;\nextern CorePart dfb_system_core;\nextern CorePart dfb_wm_core;\n\nstatic CorePart *core_parts[] = {\n     &dfb_clipboard_core,\n     &dfb_colorhash_core,\n     &dfb_surface_core,\n     &dfb_system_core,\n     &dfb_input_core,\n     &dfb_graphics_core,\n     &dfb_screen_core,\n     &dfb_layer_core,\n     &dfb_wm_core\n};\n\nstatic void dfb_core_deinit_check( void *ctx );\n\nstatic void dfb_core_thread_init_handler( DirectThread *thread, void *arg );\n\nstatic void dfb_core_process_cleanups( CoreDFB *core, bool emergency );\n\nstatic DirectSignalHandlerResult dfb_core_signal_handler( int num, void *addr, void *ctx );\n\nstatic DFBResult dfb_core_arena_initialize( void *ctx );\nstatic DFBResult dfb_core_arena_shutdown  ( void *ctx, bool emergency );\nstatic DFBResult dfb_core_arena_join      ( void *ctx );\nstatic DFBResult dfb_core_arena_leave     ( void *ctx, bool emergency );\n\ntypedef struct {\n     ICoreResourceClient *client;\n     CoreSlave            slave;\n} ResourceIdentity;\n\n/**********************************************************************************************************************/\n\nstatic FusionCallHandlerResult\nCore_AsyncCall_Handler( int           caller,   /* fusion id of the caller */\n                        int           call_arg, /* optional call parameter */\n                        void         *call_ptr, /* optional call parameter */\n                        void         *ctx,      /* optional handler context */\n                        unsigned int  serial,\n                        int          *ret_val )\n{\n     AsyncCall *call = call_ptr;\n\n     call->func( call->ctx, call->ctx2 );\n\n     return FCHR_RETURN;\n}\n\nDFBResult\ndfb_core_create( CoreDFB **ret_core )\n{\n     DFBResult  ret;\n#if FUSION_BUILD_MULTI\n     char       buf[16];\n#endif /* FUSION_BUILD_MULTI */\n     CoreDFB   *core = NULL;\n\n     D_ASSERT( ret_core != NULL );\n     D_ASSERT( dfb_config != NULL );\n\n     D_DEBUG_AT( Core_Main, \"%s()\\n\", __FUNCTION__ );\n\n     direct_mutex_lock( &core_dfb_lock );\n\n     D_ASSERT( core_dfb == NULL || core_dfb->refs > 0 );\n\n     if (core_dfb) {\n          D_MAGIC_ASSERT( core_dfb, CoreDFB );\n\n          core_dfb->refs++;\n\n          *ret_core = core_dfb;\n\n          direct_mutex_unlock( &core_dfb_lock );\n\n          return DFB_OK;\n     }\n\n     direct_initialize();\n\n     D_INFO( \"DirectFB/Core: %s Application Core. (\"BUILDTIME\") %s%s\\n\",\n             FUSION_BUILD_MULTI ? \"Multi\" : \"Single\",\n             DIRECT_BUILD_DEBUG ? \"[ DEBUG ]\" : \"\",\n             DIRECT_BUILD_TRACE ? \"[ TRACE ]\" : \"\" );\n\n     ret = dfb_system_lookup();\n     if (ret)\n          goto error;\n\n     if (dfb_system_caps() & CSCAPS_SECURE_FUSION) {\n          D_INFO( \"DirectFB/Core: Forcing 'secure-fusion' option (requested by system module)\\n\" );\n          fusion_config->secure_fusion = true;\n     }\n\n     if (dfb_system_caps() & CSCAPS_ALWAYS_INDIRECT) {\n          D_INFO( \"DirectFB/Core: Forcing 'always-indirect' option (requested by system module)\\n\" );\n          dfb_config->call_nodirect = FCEF_NODIRECT;\n     }\n\n     /* Allocate local core structure. */\n     core = D_CALLOC( 1, sizeof(CoreDFB) );\n     if (!core) {\n          ret = D_OOM();\n          goto error;\n     }\n\n     core->refs = 1;\n\n     core->init_handler = direct_thread_add_init_handler( dfb_core_thread_init_handler, core );\n\n#if FUSION_BUILD_MULTI\n     dfb_system_thread_init();\n#endif /* FUSION_BUILD_MULTI */\n\n     direct_find_best_memcpy();\n\n     D_MAGIC_SET( core, CoreDFB );\n\n     core_dfb = core;\n\n     ret = fusion_enter( dfb_config->session, DIRECTFB_CORE_ABI, FER_ANY, &core->world );\n     if (ret)\n          goto error;\n\n     core->fusion_id = fusion_id( core->world );\n\n#if FUSION_BUILD_MULTI\n     D_DEBUG_AT( Core_Main, \"  -> world %d, fusion id %lu\\n\", fusion_world_index( core->world ), core->fusion_id );\n\n     snprintf( buf, sizeof(buf), \"%d\", fusion_world_index( core->world ) );\n\n     setenv( \"DIRECTFB_SESSION\", buf, true );\n#endif /* FUSION_BUILD_MULTI */\n\n     if (dfb_config->sync) {\n          D_INFO( \"DirectFB/Core: Synchronize data on disk with memory\\n\" );\n          direct_sync();\n     }\n\n     if (dfb_config->core_sighandler)\n          direct_signal_handler_add( DIRECT_SIGNAL_ANY, dfb_core_signal_handler, core, &core->signal_handler );\n\n     /* Initialize async call. */\n     fusion_call_init( &core_dfb->async_call, Core_AsyncCall_Handler, core, core_dfb->world );\n     fusion_call_set_name( &core_dfb->async_call, \"Core_AsyncCall\" );\n\n     if (dfb_core_is_master( core_dfb ))\n          ret = dfb_core_arena_initialize( core_dfb );\n     else\n          ret = dfb_core_arena_join( core_dfb );\n\n     if (ret)\n          goto error;\n\n     if (dfb_config->block_all_signals)\n          direct_signals_block_all();\n\n     if (dfb_config->deinit_check)\n          direct_cleanup_handler_add( dfb_core_deinit_check, NULL, &core->cleanup_handler );\n\n     dfb_font_manager_create( core, &core->font_manager );\n\n     *ret_core = core;\n\n     direct_mutex_unlock( &core_dfb_lock );\n\n     D_DEBUG_AT( Core_Main, \"  -> core successfully created\\n\" );\n\n     return DFB_OK;\n\nerror:\n     if (core) {\n          if (core->world) {\n               fusion_call_destroy( &core_dfb->async_call );\n\n               fusion_exit( core->world, false );\n          }\n\n          if (core->init_handler)\n               direct_thread_remove_init_handler( core->init_handler );\n\n          if (core->signal_handler)\n               direct_signal_handler_remove( core->signal_handler );\n\n          D_MAGIC_CLEAR( core );\n\n          D_FREE( core );\n          core_dfb = NULL;\n     }\n\n     direct_mutex_unlock( &core_dfb_lock );\n\n     direct_shutdown();\n\n     return ret;\n}\n\nDFBResult\ndfb_core_destroy( CoreDFB *core,\n                  bool     emergency )\n{\n     DFBResult ret;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_ASSERT( core->refs > 0 );\n     D_ASSERT( core == core_dfb );\n\n     D_DEBUG_AT( Core_Main, \"%s()\\n\", __FUNCTION__ );\n\n     if (!emergency) {\n          direct_mutex_lock( &core_dfb_lock );\n\n          if (--core->refs) {\n               direct_mutex_unlock( &core_dfb_lock );\n               return DFB_OK;\n          }\n     }\n\n     if (!core->shutdown_running)\n          core->shutdown_running = 1;\n     else {\n          if (!emergency)\n               direct_mutex_unlock( &core_dfb_lock );\n          D_WARN( \"core shutdown already running\" );\n          return DFB_OK;\n     }\n\n     if (core->signal_handler) {\n          DirectSignalHandler *signal_handler = core->signal_handler;\n\n          core->signal_handler = NULL;\n\n          direct_signal_handler_remove( signal_handler );\n     }\n\n     if (core->cleanup_handler) {\n          DirectCleanupHandler *cleanup_handler = core->cleanup_handler;\n\n          core->cleanup_handler = NULL;\n\n          direct_cleanup_handler_remove( cleanup_handler );\n     }\n\n     direct_thread_sleep( 100000 );\n\n     if (core->font_manager)\n          dfb_font_manager_destroy( core->font_manager );\n\n     if (dfb_core_is_master( core )) {\n          if (emergency) {\n               fusion_kill( core->world, 0, SIGKILL, 1000 );\n          }\n          else {\n               fusion_kill( core->world, 0, SIGTERM, 5000 );\n               fusion_kill( core->world, 0, SIGKILL, 2000 );\n          }\n     }\n\n     dfb_core_process_cleanups( core, emergency );\n\n     if (dfb_core_is_master( core_dfb ))\n          ret = dfb_core_arena_shutdown( core_dfb, emergency );\n     else\n          ret = dfb_core_arena_leave( core_dfb, emergency );\n\n     fusion_call_destroy( &core_dfb->async_call );\n\n     fusion_exit( core->world, emergency );\n\n     if (!emergency)\n          direct_thread_remove_init_handler( core->init_handler );\n\n     D_MAGIC_CLEAR( core );\n\n     D_FREE( core );\n     core_dfb = NULL;\n\n     if (!emergency)\n          direct_mutex_unlock( &core_dfb_lock );\n\n     direct_shutdown();\n\n     return ret;\n}\n\nvoid *\ndfb_core_get_part( CoreDFB    *core,\n                   CorePartID  part_id )\n{\n     switch (part_id) {\n          case DFCP_CLIPBOARD:\n               return dfb_clipboard_core.data_local;\n\n          case DFCP_COLORHASH:\n               return dfb_colorhash_core.data_local;\n\n          case DFCP_GRAPHICS:\n               return dfb_graphics_core.data_local;\n\n          case DFCP_INPUT:\n               return dfb_input_core.data_local;\n\n          case DFCP_LAYER:\n               return dfb_layer_core.data_local;\n\n          case DFCP_SCREEN:\n               return dfb_screen_core.data_local;\n\n          case DFCP_SURFACE:\n               return dfb_surface_core.data_local;\n\n          case DFCP_SYSTEM:\n               return dfb_system_core.data_local;\n\n          case DFCP_WM:\n               return dfb_wm_core.data_local;\n\n          default:\n               D_BUG( \"unknown core part\" );\n     }\n\n     return NULL;\n}\n\nDFBResult\ndfb_core_initialize( CoreDFB *core )\n{\n     int            i;\n     DFBResult      ret;\n     CoreDFBShared *shared;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n\n     direct_hash_create( 23, &core->resource.identities );\n\n     direct_mutex_init( &core->memory_permissions_lock );\n\n     shared = core->shared;\n\n     ret = fusion_shm_pool_create( core->world, \"DirectFB Data Pool\", 0x1000000, fusion_config->debugshm,\n                                   &shared->shmpool_data );\n     if (ret)\n          return ret;\n\n     shared->graphics_state_pool     = dfb_graphics_state_pool_create( core->world );\n     shared->layer_context_pool      = dfb_layer_context_pool_create( core->world );\n     shared->layer_region_pool       = dfb_layer_region_pool_create( core->world );\n     shared->palette_pool            = dfb_palette_pool_create( core->world );\n     shared->surface_pool            = dfb_surface_pool_create( core->world );\n     shared->surface_allocation_pool = dfb_surface_allocation_pool_create( core->world );\n     shared->surface_buffer_pool     = dfb_surface_buffer_pool_create( core->world );\n     shared->surface_client_pool     = dfb_surface_client_pool_create( core->world );\n     shared->window_pool             = dfb_window_pool_create( core->world );\n\n     for (i = 0; i < D_ARRAY_SIZE(core_parts); i++) {\n          if ((ret = dfb_core_part_initialize( core, core_parts[i] )))\n               return ret;\n     }\n\n     if (dfb_config->resource_manager) {\n          DirectInterfaceFuncs *funcs;\n\n          ret = DirectGetInterface( &funcs, \"ICoreResourceManager\", dfb_config->resource_manager, NULL, NULL );\n          if (ret == DFB_OK) {\n               void *iface;\n\n               ret = funcs->Allocate( &iface );\n               if (ret == DFB_OK) {\n                    ret = funcs->Construct( iface, core );\n                    if (ret == DFB_OK) {\n                         D_INFO( \"Core/Resource: Using resource manager '%s'\\n\", dfb_config->resource_manager );\n\n                         core->resource.manager = iface;\n                    }\n                    else\n                         D_DERROR( ret, \"Core/Resource: Failed to construct manager '%s'!\\n\", dfb_config->resource_manager );\n               }\n               else\n                    D_DERROR( ret, \"Core/Resource: Failed to allocate manager '%s'!\\n\", dfb_config->resource_manager );\n          }\n          else\n               D_DERROR( ret, \"Core/Resource: Failed to load manager '%s'!\\n\", dfb_config->resource_manager );\n     }\n\n     return DFB_OK;\n}\n\nCoreGraphicsState *\ndfb_core_create_graphics_state( CoreDFB *core )\n{\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n     D_ASSERT( core->shared->graphics_state_pool != NULL );\n\n     shared = core->shared;\n\n     return (CoreGraphicsState*) fusion_object_create( shared->graphics_state_pool, core->world, Core_GetIdentity() );\n}\n\nCoreLayerContext *\ndfb_core_create_layer_context( CoreDFB *core )\n{\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n     D_ASSERT( core->shared->layer_context_pool != NULL );\n\n     shared = core->shared;\n\n     return (CoreLayerContext*) fusion_object_create( shared->layer_context_pool, core->world, Core_GetIdentity() );\n}\n\nCoreLayerRegion *\ndfb_core_create_layer_region( CoreDFB *core )\n{\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n     D_ASSERT( core->shared->layer_region_pool != NULL );\n\n     shared = core->shared;\n\n     return (CoreLayerRegion*) fusion_object_create( shared->layer_region_pool, core->world, Core_GetIdentity() );\n}\n\nCorePalette *\ndfb_core_create_palette( CoreDFB *core )\n{\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n     D_ASSERT( core->shared->palette_pool != NULL );\n\n     shared = core->shared;\n\n     return (CorePalette*) fusion_object_create( shared->palette_pool, core->world, Core_GetIdentity() );\n}\n\nCoreSurface *\ndfb_core_create_surface( CoreDFB *core )\n{\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n     D_ASSERT( core->shared->surface_pool != NULL );\n\n     shared = core->shared;\n\n     return (CoreSurface*) fusion_object_create( shared->surface_pool, core->world, Core_GetIdentity() );\n}\n\nCoreSurfaceAllocation *\ndfb_core_create_surface_allocation( CoreDFB *core )\n{\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n     D_ASSERT( core->shared->surface_allocation_pool != NULL );\n\n     shared = core->shared;\n\n     return (CoreSurfaceAllocation*) fusion_object_create( shared->surface_allocation_pool, core->world,\n                                                           Core_GetIdentity() );\n}\n\nCoreSurfaceBuffer *\ndfb_core_create_surface_buffer( CoreDFB *core )\n{\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n     D_ASSERT( core->shared->surface_buffer_pool != NULL );\n\n     shared = core->shared;\n\n     return (CoreSurfaceBuffer*) fusion_object_create( shared->surface_buffer_pool, core->world, Core_GetIdentity() );\n}\n\nCoreSurfaceClient *\ndfb_core_create_surface_client( CoreDFB *core )\n{\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n     D_ASSERT( core->shared->surface_client_pool != NULL );\n\n     shared = core->shared;\n\n     return (CoreSurfaceClient*) fusion_object_create( shared->surface_client_pool, core->world, Core_GetIdentity() );\n}\n\nCoreWindow *\ndfb_core_create_window( CoreDFB *core )\n{\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n     D_ASSERT( core->shared->window_pool != NULL );\n\n     shared = core->shared;\n\n     return (CoreWindow*) fusion_object_create( shared->window_pool, core->world, Core_GetIdentity() );\n}\n\nDFBResult\ndfb_core_get_graphics_state( CoreDFB            *core,\n                             u32                 object_id,\n                             CoreGraphicsState **ret_state )\n{\n     DFBResult      ret;\n     FusionObject  *object;\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n     D_ASSERT( core->shared->graphics_state_pool != NULL );\n     D_ASSERT( ret_state != NULL );\n\n     shared = core->shared;\n\n     ret = fusion_object_get( shared->graphics_state_pool, object_id, &object );\n     if (ret)\n          return ret;\n\n     *ret_state = (CoreGraphicsState*) object;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_core_get_layer_context( CoreDFB           *core,\n                            u32                object_id,\n                            CoreLayerContext **ret_context )\n{\n     DFBResult      ret;\n     FusionObject  *object;\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n     D_ASSERT( core->shared->layer_context_pool != NULL );\n     D_ASSERT( ret_context != NULL );\n\n     shared = core->shared;\n\n     ret = fusion_object_get( shared->layer_context_pool, object_id, &object );\n     if (ret)\n          return ret;\n\n     *ret_context = (CoreLayerContext*) object;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_core_get_layer_region( CoreDFB          *core,\n                           u32               object_id,\n                           CoreLayerRegion **ret_region )\n{\n     DFBResult      ret;\n     FusionObject  *object;\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n     D_ASSERT( core->shared->layer_region_pool != NULL );\n     D_ASSERT( ret_region != NULL );\n\n     shared = core->shared;\n\n     ret = fusion_object_get( shared->layer_region_pool, object_id, &object );\n     if (ret)\n          return ret;\n\n     *ret_region = (CoreLayerRegion*) object;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_core_get_palette( CoreDFB      *core,\n                      u32           object_id,\n                      CorePalette **ret_palette )\n{\n     DFBResult      ret;\n     FusionObject  *object;\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n     D_ASSERT( core->shared->palette_pool != NULL );\n     D_ASSERT( ret_palette != NULL );\n\n     shared = core->shared;\n\n     ret = fusion_object_get( shared->palette_pool, object_id, &object );\n     if (ret)\n          return ret;\n\n     *ret_palette = (CorePalette*) object;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_core_get_surface( CoreDFB      *core,\n                      u32           object_id,\n                      CoreSurface **ret_surface )\n{\n     DFBResult      ret;\n     FusionObject  *object;\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n     D_ASSERT( core->shared->surface_pool != NULL );\n     D_ASSERT( ret_surface != NULL );\n\n     shared = core->shared;\n\n     ret = fusion_object_get( shared->surface_pool, object_id, &object );\n     if (ret)\n          return ret;\n\n     *ret_surface = (CoreSurface*) object;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_core_get_surface_allocation( CoreDFB                *core,\n                                 u32                     object_id,\n                                 CoreSurfaceAllocation **ret_allocation )\n{\n     DFBResult      ret;\n     FusionObject  *object;\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n     D_ASSERT( core->shared->surface_allocation_pool != NULL );\n     D_ASSERT( ret_allocation != NULL );\n\n     shared = core->shared;\n\n     ret = fusion_object_get( shared->surface_allocation_pool, object_id, &object );\n     if (ret)\n          return ret;\n\n     *ret_allocation = (CoreSurfaceAllocation*) object;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_core_get_surface_buffer( CoreDFB            *core,\n                             u32                 object_id,\n                             CoreSurfaceBuffer **ret_buffer )\n{\n     DFBResult      ret;\n     FusionObject  *object;\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n     D_ASSERT( core->shared->surface_buffer_pool != NULL );\n     D_ASSERT( ret_buffer != NULL );\n\n     shared = core->shared;\n\n     ret = fusion_object_get( shared->surface_buffer_pool, object_id, &object );\n     if (ret)\n          return ret;\n\n     *ret_buffer = (CoreSurfaceBuffer*) object;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_core_get_surface_client( CoreDFB            *core,\n                             u32                 object_id,\n                             CoreSurfaceClient **ret_client )\n{\n     DFBResult      ret;\n     FusionObject  *object;\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n     D_ASSERT( core->shared->surface_client_pool != NULL );\n     D_ASSERT( ret_client != NULL );\n\n     shared = core->shared;\n\n     ret = fusion_object_get( shared->surface_client_pool, object_id, &object );\n     if (ret)\n          return ret;\n\n     *ret_client = (CoreSurfaceClient*) object;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_core_get_window( CoreDFB     *core,\n                     u32          object_id,\n                     CoreWindow **ret_window )\n{\n     DFBResult      ret;\n     FusionObject  *object;\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n     D_ASSERT( core->shared->window_pool != NULL );\n     D_ASSERT( ret_window != NULL );\n\n     shared = core->shared;\n\n     ret = fusion_object_get( shared->window_pool, object_id, &object );\n     if (ret)\n          return ret;\n\n     *ret_window = (CoreWindow*) object;\n\n     return DFB_OK;\n}\n\nDirectResult\ndfb_core_enum_graphics_states( CoreDFB              *core,\n                               FusionObjectCallback  callback,\n                               void                 *ctx )\n{\n     CoreDFBShared *shared;\n\n     D_ASSERT( core != NULL || core_dfb != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n\n     shared = core->shared;\n\n     return fusion_object_pool_enum( shared->graphics_state_pool, callback, ctx );\n}\n\nDirectResult\ndfb_core_enum_layer_contexts( CoreDFB              *core,\n                              FusionObjectCallback  callback,\n                              void                 *ctx )\n{\n     CoreDFBShared *shared;\n\n     D_ASSERT( core != NULL || core_dfb != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n\n     shared = core->shared;\n\n     return fusion_object_pool_enum( shared->layer_context_pool, callback, ctx );\n}\n\nDirectResult\ndfb_core_enum_layer_regions( CoreDFB              *core,\n                             FusionObjectCallback  callback,\n                             void                 *ctx )\n{\n     CoreDFBShared *shared;\n\n     D_ASSERT( core != NULL || core_dfb != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n\n     shared = core->shared;\n\n     return fusion_object_pool_enum( shared->layer_region_pool, callback, ctx );\n}\n\nDirectResult\ndfb_core_enum_layer_palettes( CoreDFB              *core,\n                              FusionObjectCallback  callback,\n                              void                 *ctx )\n{\n     CoreDFBShared *shared;\n\n     D_ASSERT( core != NULL || core_dfb != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n\n     shared = core->shared;\n\n     return fusion_object_pool_enum( shared->palette_pool, callback, ctx );\n}\n\nDirectResult\ndfb_core_enum_surfaces( CoreDFB              *core,\n                        FusionObjectCallback  callback,\n                        void                 *ctx )\n{\n     CoreDFBShared *shared;\n\n     D_ASSERT( core != NULL || core_dfb != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n\n     shared = core->shared;\n\n     return fusion_object_pool_enum( shared->surface_pool, callback, ctx );\n}\n\nDirectResult\ndfb_core_enum_surface_allocations( CoreDFB              *core,\n                                   FusionObjectCallback  callback,\n                                   void                 *ctx )\n{\n     CoreDFBShared *shared;\n\n     D_ASSERT( core != NULL || core_dfb != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n\n     shared = core->shared;\n\n     return fusion_object_pool_enum( shared->surface_allocation_pool, callback, ctx );\n}\n\nDirectResult\ndfb_core_enum_surface_buffers( CoreDFB              *core,\n                               FusionObjectCallback  callback,\n                               void                 *ctx )\n{\n     CoreDFBShared *shared;\n\n     D_ASSERT( core != NULL || core_dfb != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n\n     shared = core->shared;\n\n     return fusion_object_pool_enum( shared->surface_buffer_pool, callback, ctx );\n}\n\nDirectResult\ndfb_core_enum_surface_clients( CoreDFB              *core,\n                               FusionObjectCallback  callback,\n                               void                 *ctx )\n{\n     CoreDFBShared *shared;\n\n     D_ASSERT( core != NULL || core_dfb != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n\n     shared = core->shared;\n\n     return fusion_object_pool_enum( shared->surface_client_pool, callback, ctx );\n}\n\nDirectResult\ndfb_core_enum_windows( CoreDFB              *core,\n                       FusionObjectCallback  callback,\n                       void                 *ctx )\n{\n     CoreDFBShared *shared;\n\n     D_ASSERT( core != NULL || core_dfb != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n\n     shared = core->shared;\n\n     return fusion_object_pool_enum( shared->window_pool, callback, ctx );\n}\n\nstatic bool\ndump_objects( FusionObjectPool *pool,\n              FusionObject     *object,\n              void             *ctx )\n{\n     D_LOG( Core_Main, VERBOSE, \"        %p [id %u] ref 0x%x (single %d) identity %lu\\n\", object, object->id,\n            (unsigned int) object->ref.multi.id, object->ref.single.refs, object->identity );\n\n     direct_trace_print_stack( object->create_stack );\n\n     return true;\n}\n\nstatic void\ndfb_core_dump_all( CoreDFB *core )\n{\n     int            i;\n     CoreDFBShared *shared;\n\n     D_DEBUG_AT( Core_Main, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( core != NULL || core_dfb != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n\n     shared = core->shared;\n\n     FusionObjectPool *pools[] = {\n          shared->graphics_state_pool,\n          shared->layer_context_pool,\n          shared->layer_region_pool,\n          shared->palette_pool,\n          shared->surface_pool,\n          shared->surface_allocation_pool,\n          shared->surface_buffer_pool,\n          shared->surface_client_pool,\n          shared->window_pool\n     };\n\n     for (i = 0; i < D_ARRAY_SIZE(pools); i++) {\n          if (pools[i]) {\n               D_LOG( Core_Main, VERBOSE, \"  - Objects in '%s' -\\n\", pools[i]->name );\n\n               fusion_object_pool_enum( pools[i], dump_objects, NULL );\n          }\n     }\n}\n\nstatic DirectResult\ndfb_core_wait_all( CoreDFB   *core,\n                   long long  timeout )\n{\n     long long      start;\n     CoreDFBShared *shared;\n\n     D_DEBUG_AT( Core_Main, \"%s( timeout %lld us )\\n\", __FUNCTION__, timeout );\n\n     D_ASSERT( core != NULL || core_dfb != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n\n     shared = core->shared;\n\n     start = direct_clock_get_time( DIRECT_CLOCK_MONOTONIC );\n\n     while (true) {\n          int               i;\n          FusionObjectPool *pools[] = {\n               shared->graphics_state_pool,\n               shared->layer_context_pool,\n               shared->layer_region_pool,\n               shared->palette_pool,\n               shared->surface_pool,\n               shared->surface_allocation_pool,\n               shared->surface_buffer_pool,\n               shared->surface_client_pool,\n               shared->window_pool\n          };\n\n          long long now = direct_clock_get_time( DIRECT_CLOCK_MONOTONIC );\n\n          for (i = 0; i < D_ARRAY_SIZE(pools); i++) {\n               if (pools[i]) {\n                    size_t    num = 0;\n                    DFBResult ret;\n\n                    D_UNUSED_P( ret );\n\n                    ret = fusion_object_pool_size( pools[i], &num );\n                    if (ret)\n                         return ret;\n\n                    if (num > 0) {\n                         if (now - start >= timeout) {\n                              D_DEBUG_AT( Core_Main, \"  -> still \"_ZU\" objects in pool, timeout!\\n\", num );\n                              return DR_TIMEOUT;\n                         }\n\n                         D_DEBUG_AT( Core_Main, \"  -> still \"_ZU\" objects in '%s', waiting 10ms...\\n\", num,\n                                     pools[i]->name );\n                         break;\n                    }\n               }\n          }\n\n          if (i < D_ARRAY_SIZE(pools)) {\n               D_DEBUG_AT( Core_Main, \"  -> waiting another 10ms for objects to be dead...\\n\" );\n\n               direct_thread_sleep( 10000 );\n          }\n          else\n               break;\n     }\n\n     return DR_OK;\n}\n\nDirectResult\ncore_arena_add_shared_field( CoreDFB    *core,\n                             const char *name,\n                             void       *data )\n{\n     DirectResult   ret;\n     char          *shname;\n     CoreDFBShared *shared;\n\n     D_DEBUG_AT( Core_Main, \"%s( '%s', %p )\\n\", __FUNCTION__, name, data );\n\n     D_ASSERT( core != NULL );\n     D_ASSERT( core->shared != NULL );\n\n     shared = core->shared;\n\n     /* Give it the requested name. */\n     shname = SHSTRDUP( shared->shmpool, name );\n     if (shname)\n          ret = fusion_hash_replace( shared->field_hash, shname, data, NULL, NULL );\n     else\n          ret = D_OOSHM();\n\n     return ret;\n}\n\nDirectResult\ncore_arena_get_shared_field( CoreDFB     *core,\n                             const char  *name,\n                             void       **data )\n{\n     void          *ptr;\n     CoreDFBShared *shared;\n\n     D_DEBUG_AT( Core_Main, \"%s( '%s' )\\n\", __FUNCTION__, name );\n\n     D_ASSERT( core != NULL );\n     D_ASSERT( core->shared != NULL );\n\n     shared = core->shared;\n\n     /* Lookup entry. */\n     ptr = fusion_hash_lookup( shared->field_hash, name );\n\n     D_DEBUG_AT( Core_Main, \"  -> %p\\n\", ptr );\n\n     if (!ptr)\n          return DR_ITEMNOTFOUND;\n\n     *data = ptr;\n\n     return DR_OK;\n}\n\nbool\ndfb_core_is_master( CoreDFB *core )\n{\n     D_MAGIC_ASSERT( core, CoreDFB );\n\n     return core->fusion_id == FUSION_ID_MASTER;\n}\n\nvoid\ndfb_core_activate( CoreDFB *core )\n{\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n\n     /* Let others enter the world. */\n     fusion_world_activate( core->world );\n}\n\nFusionWorld *\ndfb_core_world( CoreDFB *core )\n{\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n\n     return core->world;\n}\n\nFusionSHMPoolShared *\ndfb_core_shmpool( CoreDFB *core )\n{\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n\n     shared = core->shared;\n\n     return shared->shmpool;\n}\n\nFusionSHMPoolShared *\ndfb_core_shmpool_data( CoreDFB *core )\n{\n     CoreDFBShared *shared;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n\n     shared = core->shared;\n\n     return shared->shmpool_data;\n}\n\nDFBResult\ndfb_core_suspend( CoreDFB *core )\n{\n     DFBResult ret;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n\n     if (!dfb_core_is_master( core ))\n          return DFB_ACCESSDENIED;\n\n     if (core->suspended)\n          return DFB_BUSY;\n\n     ret = dfb_input_core.Suspend( dfb_input_core.data_local );\n     if (ret)\n          goto error_input;\n\n     ret = dfb_layer_core.Suspend( dfb_layer_core.data_local );\n     if (ret)\n          goto error_layers;\n\n     ret = dfb_screen_core.Suspend( dfb_screen_core.data_local );\n     if (ret)\n          goto error_screens;\n\n     ret = dfb_graphics_core.Suspend( dfb_graphics_core.data_local );\n     if (ret)\n          goto error_graphics;\n\n     core->suspended = true;\n\n     return DFB_OK;\n\nerror_graphics:\n     dfb_screen_core.Resume( dfb_screen_core.data_local );\nerror_screens:\n     dfb_layer_core.Resume( dfb_layer_core.data_local );\nerror_layers:\n     dfb_input_core.Resume( dfb_input_core.data_local );\nerror_input:\n     return ret;\n}\n\nDFBResult\ndfb_core_resume( CoreDFB *core )\n{\n     DFBResult ret;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n\n     if (!dfb_core_is_master( core ))\n          return DFB_ACCESSDENIED;\n\n     if (!core->suspended)\n          return DFB_BUSY;\n\n     ret = dfb_graphics_core.Resume( dfb_graphics_core.data_local );\n     if (ret)\n          goto error_graphics;\n\n     ret = dfb_screen_core.Resume( dfb_screen_core.data_local );\n     if (ret)\n          goto error_screens;\n\n     ret = dfb_layer_core.Resume( dfb_layer_core.data_local );\n     if (ret)\n          goto error_layers;\n\n     ret = dfb_input_core.Resume( dfb_input_core.data_local );\n     if (ret)\n          goto error_input;\n\n     core->suspended = false;\n\n     return DFB_OK;\n\nerror_input:\n     dfb_layer_core.Suspend( dfb_layer_core.data_local );\nerror_layers:\n     dfb_screen_core.Suspend( dfb_screen_core.data_local );\nerror_screens:\n     dfb_graphics_core.Suspend( dfb_graphics_core.data_local );\nerror_graphics:\n     return ret;\n}\n\nCoreCleanup *\ndfb_core_cleanup_add( CoreDFB         *core,\n                      CoreCleanupFunc  func,\n                      void            *data,\n                      bool             emergency )\n{\n     CoreCleanup *cleanup;\n\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n\n     cleanup = D_CALLOC( 1, sizeof(CoreCleanup) );\n\n     cleanup->func      = func;\n     cleanup->data      = data;\n     cleanup->emergency = emergency;\n\n     direct_list_prepend( &core->cleanups, &cleanup->link );\n\n     return cleanup;\n}\n\nvoid\ndfb_core_cleanup_remove( CoreDFB     *core,\n                         CoreCleanup *cleanup )\n{\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n\n     direct_list_remove( &core->cleanups, &cleanup->link );\n\n     D_FREE( cleanup );\n}\n\nCoreFontManager *\ndfb_core_font_manager( CoreDFB *core )\n{\n     D_ASSUME( core != NULL );\n\n     if (!core)\n          core = core_dfb;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n\n     return core->font_manager;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_core_memory_permissions_add( CoreDFB                    *core,\n                                 CoreMemoryPermissionFlags   flags,\n                                 void                       *data,\n                                 size_t                      length,\n                                 CoreMemoryPermission      **ret_permission )\n{\n     CoreMemoryPermission *permission;\n\n     D_DEBUG_AT( Core_Main, \"%s( flags 0x%02x, data %p, length \"_ZU\" )\\n\", __FUNCTION__, flags, data, length );\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n\n     permission = D_CALLOC( 1, sizeof(CoreMemoryPermission) );\n     if (!permission)\n          return D_OOM();\n\n     permission->flags  = flags;\n     permission->data   = data;\n     permission->end    = data + length;\n     permission->length = length;\n\n     direct_mutex_lock( &core->memory_permissions_lock );\n\n     direct_list_prepend( &core->memory_permissions, &permission->link );\n\n     direct_mutex_unlock( &core->memory_permissions_lock );\n\n     *ret_permission = permission;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_core_memory_permissions_remove( CoreDFB              *core,\n                                    CoreMemoryPermission *permission )\n{\n     D_DEBUG_AT( Core_Main, \"%s( flags 0x%02x, data %p, length \"_ZU\" )\\n\", __FUNCTION__,\n                 permission->flags, permission->data, permission->length );\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n\n     direct_mutex_lock( &core->memory_permissions_lock );\n\n     direct_list_remove( &core->memory_permissions, &permission->link );\n\n     direct_mutex_unlock( &core->memory_permissions_lock );\n\n     D_FREE( permission );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_core_memory_permissions_check( CoreDFB                   *core,\n                                   CoreMemoryPermissionFlags  flags,\n                                   void                      *data,\n                                   size_t                     length )\n{\n     CoreMemoryPermission *permission;\n\n     D_DEBUG_LOG( Core_Main, 9, \"%s( flags 0x%02x, data %p, length \"_ZU\" )\\n\", __FUNCTION__, flags, data, length );\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n\n     direct_mutex_lock( &core->memory_permissions_lock );\n\n     direct_list_foreach (permission, core->memory_permissions) {\n          if (permission->data <= data && permission->end >= data + length &&\n              D_FLAGS_ARE_SET( permission->flags, flags )) {\n               D_DEBUG_LOG( Core_Main, 9, \"  -> found flags 0x%02x, data %p, length \"_ZU\"\\n\",\n                            permission->flags, permission->data, permission->length );\n\n               direct_mutex_unlock( &core->memory_permissions_lock );\n\n               return DFB_OK;\n          }\n     }\n\n     direct_mutex_unlock( &core->memory_permissions_lock );\n\n     return DFB_ITEMNOTFOUND;\n}\n\n/**********************************************************************************************************************/\n\nstatic void\ndfb_core_deinit_check( void *ctx )\n{\n     if (core_dfb && core_dfb->refs) {\n          D_WARN( \"application exited without deinitialization of DirectFB\" );\n\n          direct_print_interface_leaks();\n\n          dfb_core_destroy( core_dfb, false );\n     }\n}\n\nstatic void\ndfb_core_thread_init_handler( DirectThread *thread,\n                              void         *arg )\n{\n     dfb_system_thread_init();\n}\n\nstatic void\ndfb_core_process_cleanups( CoreDFB *core,\n                           bool     emergency )\n{\n     D_MAGIC_ASSERT( core, CoreDFB );\n\n     while (core->cleanups) {\n          CoreCleanup *cleanup = (CoreCleanup*) core->cleanups;\n\n          core->cleanups = core->cleanups->next;\n\n          if (cleanup->emergency || !emergency)\n               cleanup->func( cleanup->data, emergency );\n\n          D_FREE( cleanup );\n     }\n}\n\nstatic DirectSignalHandlerResult\ndfb_core_signal_handler( int   num,\n                         void *addr,\n                         void *ctx )\n{\n     bool     locked;\n     CoreDFB *core = ctx;\n\n     D_ASSERT( core == core_dfb );\n\n     locked = direct_mutex_trylock( &core_dfb_lock ) == 0;\n\n     dfb_core_destroy( core, true );\n\n     if (locked)\n          direct_mutex_unlock( &core_dfb_lock );\n\n     return DSHR_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic bool\nregion_callback( FusionObjectPool *pool,\n                 FusionObject     *object,\n                 void             *ctx )\n{\n     CoreLayerRegion *region = (CoreLayerRegion*) object;\n\n     if (region->state & CLRSF_ENABLED)\n          dfb_layer_region_disable( region );\n\n     return true;\n}\n\nstatic DFBResult\ndfb_core_shutdown( CoreDFB *core,\n                   bool     emergency )\n{\n     DFBResult      ret   = DFB_OK;\n     int            loops = 200;\n     CoreDFBShared *shared;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n\n     shared = core->shared;\n\n     /* Suspend input core to stop all input threads before shutting down. */\n     if (dfb_input_core.initialized)\n          dfb_input_core.Suspend( dfb_input_core.data_local );\n\n     core->shutdown_tid = direct_gettid();\n\n     if (dfb_wm_core.initialized)\n          dfb_wm_deactivate_all_stacks( dfb_wm_core.data_local );\n\n     dfb_core_enum_layer_regions( core, region_callback, core );\n\n     fusion_stop_dispatcher( core->world, false );\n\n     while (loops--) {\n          fusion_dispatch( core->world, 16384 );\n\n          /* Blocks until objects are gone or timeout is reached. */\n          ret = dfb_core_wait_all( core, 10000 );\n          if (ret == DFB_OK)\n               break;\n     }\n\n     if (ret == DFB_TIMEOUT) {\n          if (fusion_config->shutdown_info) {\n               D_ERROR( \"Core/Main: Some objects remain alive, application or internal ref counting issue!\\n\" );\n\n               /* Print objects from all pools. */\n               dfb_core_dump_all( core );\n\n               direct_print_interface_leaks();\n          }\n     }\n\n     /* Destroy window objects. */\n     fusion_object_pool_destroy( shared->window_pool, core->world, fusion_config->shutdown_info );\n     shared->window_pool = NULL;\n\n     /* Close window stacks. */\n     if (dfb_wm_core.initialized)\n          dfb_wm_close_all_stacks( dfb_wm_core.data_local );\n\n     CoreDFB_Deinit_Dispatch( &shared->call );\n\n     /* Destroy layer context and region objects. */\n     fusion_object_pool_destroy( shared->layer_region_pool, core->world, fusion_config->shutdown_info );\n     fusion_object_pool_destroy( shared->layer_context_pool, core->world, fusion_config->shutdown_info );\n\n     /* Shutdown WM core. */\n     dfb_core_part_shutdown( core, &dfb_wm_core, emergency );\n\n     /* Shutdown layer core. */\n     dfb_core_part_shutdown( core, &dfb_layer_core, emergency );\n     dfb_core_part_shutdown( core, &dfb_screen_core, emergency );\n\n     /* Destroy surface and palette objects. */\n     fusion_object_pool_destroy( shared->graphics_state_pool, core->world, fusion_config->shutdown_info );\n     fusion_object_pool_destroy( shared->surface_client_pool, core->world, fusion_config->shutdown_info );\n     fusion_object_pool_destroy( shared->surface_pool, core->world, fusion_config->shutdown_info );\n     fusion_object_pool_destroy( shared->surface_buffer_pool, core->world, fusion_config->shutdown_info );\n     fusion_object_pool_destroy( shared->surface_allocation_pool, core->world, fusion_config->shutdown_info );\n     fusion_object_pool_destroy( shared->palette_pool, core->world, fusion_config->shutdown_info );\n\n     /* Destroy remaining core parts. */\n     dfb_core_part_shutdown( core, &dfb_graphics_core, emergency );\n     dfb_core_part_shutdown( core, &dfb_surface_core, emergency );\n     dfb_core_part_shutdown( core, &dfb_input_core, emergency );\n     dfb_core_part_shutdown( core, &dfb_system_core, emergency );\n     dfb_core_part_shutdown( core, &dfb_colorhash_core, emergency );\n     dfb_core_part_shutdown( core, &dfb_clipboard_core, emergency );\n\n     /* Destroy shared memory pool for surface data. */\n     fusion_shm_pool_destroy( core->world, shared->shmpool_data );\n\n     direct_hash_destroy( core->resource.identities );\n\n     direct_mutex_deinit( &core->memory_permissions_lock );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_core_leave( CoreDFB *core,\n                bool     emergency )\n{\n     int i;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n\n     for (i = D_ARRAY_SIZE(core_parts) - 1; i >= 0; i--)\n          dfb_core_part_leave( core, core_parts[i], emergency );\n\n     CoreSlave_Deinit_Dispatch( &core->slave_call );\n\n     direct_hash_destroy( core->resource.identities );\n\n     direct_mutex_deinit( &core->memory_permissions_lock );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_core_join( CoreDFB *core )\n{\n     int i;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n\n     direct_hash_create( 23, &core->resource.identities );\n\n     direct_mutex_init( &core->memory_permissions_lock );\n\n     CoreSlave_Init_Dispatch( core, core, &core->slave_call );\n\n     if (fusion_config->secure_fusion)\n          CoreDFB_Register( core, core->slave_call.call_id );\n\n     for (i = 0; i < D_ARRAY_SIZE(core_parts); i++) {\n          DFBResult ret;\n\n          if ((ret = dfb_core_part_join( core, core_parts[i] ))) {\n               dfb_core_leave( core, true );\n               return ret;\n          }\n     }\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic void\ndfb_core_leave_callback( FusionWorld *world,\n                         FusionID     fusion_id,\n                         void        *ctx )\n{\n     Core_Resource_DisposeIdentity( fusion_id );\n}\n\nstatic DFBResult\ndfb_core_arena_initialize( void *ctx )\n{\n     DFBResult            ret;\n     CoreDFB             *core = ctx;\n     CoreDFBShared       *shared;\n     FusionSHMPoolShared *pool;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n\n     D_DEBUG_AT( Core_Main, \"%s() initializing...\\n\", __FUNCTION__ );\n\n     /* Create the shared memory pool first. */\n     ret = fusion_shm_pool_create( core->world, \"DirectFB Main Pool\", 0x400000, fusion_config->debugshm, &pool );\n     if (ret)\n          return ret;\n\n     /* Allocate shared structure in the new pool. */\n     shared = SHCALLOC( pool, 1, sizeof(CoreDFBShared) );\n     if (!shared) {\n          fusion_shm_pool_destroy( core->world, pool );\n          return D_OOSHM();\n     }\n\n     core->shared = shared;\n\n     shared->shmpool = pool;\n     shared->secure  = fusion_config->secure_fusion;\n\n     ret = fusion_hash_create( pool, HASH_STRING, HASH_PTR, 7, &shared->field_hash );\n     if (ret) {\n          SHFREE( pool, shared );\n          fusion_shm_pool_destroy( core->world, pool );\n          return ret;\n     }\n\n     fusion_hash_set_autofree( shared->field_hash, true, false );\n\n     D_MAGIC_SET( shared, CoreDFBShared );\n\n     CoreDFB_Init_Dispatch( core, core, &shared->call );\n\n     fusion_call_add_permissions( &shared->call, 0, FUSION_CALL_PERMIT_EXECUTE );\n\n     fusion_world_set_leave_callback( core->world, dfb_core_leave_callback, NULL );\n\n     /* Register shared data. */\n     fusion_world_set_root( core->world, shared );\n\n     /* Initialize. */\n     ret = CoreDFB_Initialize( core );\n     if (ret) {\n          dfb_core_arena_shutdown( core, true );\n          return ret;\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_core_arena_shutdown( void *ctx,\n                         bool  emergency )\n{\n     DFBResult            ret;\n     CoreDFB             *core = ctx;\n     CoreDFBShared       *shared;\n     FusionSHMPoolShared *pool;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n     D_MAGIC_ASSERT( core->shared, CoreDFBShared );\n\n     shared = core->shared;\n\n     pool = shared->shmpool;\n\n     D_DEBUG_AT( Core_Main, \"%s() shutting down...\\n\", __FUNCTION__ );\n\n     if (!dfb_core_is_master( core )) {\n          D_WARN( \"refusing shutdown in slave\" );\n          return dfb_core_leave( core, emergency );\n     }\n\n     if (core_dfb->resource.manager) {\n          core_dfb->resource.manager->Release(core_dfb->resource.manager);\n     }\n\n     /* Shutdown. */\n     ret = dfb_core_shutdown( core, emergency );\n\n     fusion_hash_destroy( shared->field_hash );\n\n     D_MAGIC_CLEAR( shared );\n\n     SHFREE( pool, shared );\n\n     fusion_shm_pool_destroy( core->world, pool );\n\n     return ret;\n}\n\nstatic DFBResult\ndfb_core_arena_join( void *ctx )\n{\n     DFBResult      ret;\n     CoreDFB       *core = ctx;\n     CoreDFBShared *shared;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n\n     D_DEBUG_AT( Core_Main, \"%s() joining...\\n\", __FUNCTION__ );\n\n     /* Get shared data. */\n     shared = fusion_world_get_root( core->world );\n\n     core->shared = shared;\n\n     if (fusion_config->secure_fusion != shared->secure) {\n          D_ERROR( \"Core/Main: Local secure-fusion config (%d) does not match with running session (%d)!\\n\",\n                   fusion_config->secure_fusion, shared->secure );\n\n          return DFB_UNSUPPORTED;\n     }\n\n     /* Join. */\n     ret = dfb_core_join( core );\n     if (ret)\n          return ret;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_core_arena_leave( void *ctx,\n                      bool  emergency )\n{\n     DFBResult  ret;\n     CoreDFB   *core = ctx;\n\n     D_MAGIC_ASSERT( core, CoreDFB );\n\n     D_DEBUG_AT( Core_Main, \"%s() leaving...\\n\", __FUNCTION__ );\n\n     /* Leave. */\n     ret = dfb_core_leave( core, emergency );\n     if (ret)\n          return ret;\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic void\ncore_tls_destroy( void *arg )\n{\n     CoreTLS *core_tls = arg;\n\n     D_MAGIC_ASSERT( core_tls, CoreTLS );\n\n     D_MAGIC_CLEAR( core_tls );\n\n     D_FREE( core_tls );\n}\n\nvoid\nCore_TLS__init()\n{\n     direct_tls_register( &core_tls_key, core_tls_destroy );\n}\n\nvoid\nCore_TLS__deinit()\n{\n     direct_tls_unregister( &core_tls_key );\n}\n\nCoreTLS *\nCore_GetTLS()\n{\n     CoreTLS *core_tls;\n\n     core_tls = direct_tls_get( &core_tls_key );\n     if (!core_tls) {\n          core_tls = D_CALLOC( 1, sizeof(CoreTLS) );\n          if (!core_tls) {\n               D_OOM();\n               return NULL;\n          }\n\n          D_MAGIC_SET( core_tls, CoreTLS );\n\n          direct_tls_set( &core_tls_key, core_tls );\n     }\n\n     D_MAGIC_ASSERT( core_tls, CoreTLS );\n\n     return core_tls;\n}\n\n/**********************************************************************************************************************/\n\nvoid\nCore_PushIdentity( FusionID caller )\n{\n     CoreTLS *core_tls = Core_GetTLS();\n\n     if (core_tls) {\n          core_tls->identity_count++;\n\n          if (core_tls->identity_count <= CORE_TLS_IDENTITY_STACK_MAX)\n               core_tls->identity[core_tls->identity_count-1] = caller ?: core_dfb->fusion_id;\n          else\n               D_WARN( \"identity stack overflow\" );\n     }\n     else\n          D_WARN( \"TLS error\" );\n}\n\nvoid\nCore_PopIdentity()\n{\n     CoreTLS *core_tls = Core_GetTLS();\n\n     if (core_tls) {\n          D_ASSERT( core_tls->identity_count > 0 );\n\n          if (core_tls->identity_count > 0)\n               core_tls->identity_count--;\n          else\n               D_BUG( \"no identity\" );\n     }\n     else\n          D_WARN( \"TLS error\" );\n}\n\nFusionID\nCore_GetIdentity()\n{\n     CoreTLS *core_tls = Core_GetTLS();\n\n     if (core_tls) {\n          if (core_tls->identity_count == 0) {\n               D_ASSERT( core_dfb != NULL );\n               D_ASSUME( core_dfb->fusion_id != 0 );\n\n               return core_dfb->fusion_id;\n          }\n\n          if (core_tls->identity_count <= CORE_TLS_IDENTITY_STACK_MAX)\n               return core_tls->identity[core_tls->identity_count-1];\n\n          D_WARN( \"wrong identity due to overflow\" );\n\n          return core_tls->identity[CORE_TLS_IDENTITY_STACK_MAX-1];\n     }\n\n     D_WARN( \"TLS error\" );\n\n     return 0;\n}\n\n#if FUSION_BUILD_MULTI\nvoid\nCore_PushCalling()\n{\n     CoreTLS *core_tls = Core_GetTLS();\n\n     if (core_tls)\n          core_tls->calling++;\n     else\n          D_WARN( \"TLS error\" );\n}\n\nvoid\nCore_PopCalling()\n{\n     CoreTLS *core_tls = Core_GetTLS();\n\n     if (core_tls) {\n          if (core_tls->calling == 0) {\n               D_BUG( \"no more call\" );\n               return;\n          }\n\n          core_tls->calling--;\n     }\n     else\n          D_WARN( \"TLS error\" );\n}\n\nint\nCore_GetCalling()\n{\n     CoreTLS *core_tls = Core_GetTLS();\n\n     if (core_tls)\n          return core_tls->calling;\n\n     D_WARN( \"TLS error\" );\n\n     return 0;\n}\n#endif /* FUSION_BUILD_MULTI */\n\n/**********************************************************************************************************************/\n\nDFBResult\nCore_Resource_CheckSurface( const CoreSurfaceConfig *config,\n                            u64                      resource_id )\n{\n     ICoreResourceClient *client;\n\n     D_DEBUG_AT( Core_Resource, \"%s( %dx%d, %s, resource id %llu ) <- identity %lu\\n\", __FUNCTION__,\n                 config->size.w, config->size.h, dfb_pixelformat_name( config->format ),\n                 (unsigned long long) resource_id, Core_GetIdentity() );\n\n     if (Core_GetIdentity() == core_dfb->fusion_id)\n          return DFB_OK;\n\n     if (core_dfb->resource.manager) {\n          client = Core_Resource_GetClient( Core_GetIdentity() );\n          if (!client)\n               return DFB_DEAD;\n\n          return client->CheckSurface( client, config, resource_id );\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nCore_Resource_CheckSurfaceUpdate( CoreSurface             *surface,\n                                  const CoreSurfaceConfig *config )\n{\n     ICoreResourceClient *client;\n\n     D_DEBUG_AT( Core_Resource, \"%s( %dx%d, %s, type %u, resource id %lu ) <- identity %lu\\n\", __FUNCTION__,\n                 config->size.w, config->size.h, dfb_pixelformat_name( config->format ), surface->type,\n                 surface->resource_id, surface->object.identity );\n\n     if (!surface->object.identity || surface->object.identity == core_dfb->fusion_id)\n          return DFB_OK;\n\n     if (core_dfb->resource.manager) {\n          client = Core_Resource_GetClient( surface->object.identity );\n          if (!client)\n               return DFB_DEAD;\n\n          return client->CheckSurfaceUpdate( client, surface, config );\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nCore_Resource_AddSurface( CoreSurface *surface )\n{\n     ICoreResourceClient *client;\n\n     D_DEBUG_AT( Core_Resource, \"%s( %dx%d, %s, type %u, resource id %lu ) <- identity %lu\\n\", __FUNCTION__,\n                 surface->config.size.w, surface->config.size.h, dfb_pixelformat_name( surface->config.format ),\n                 surface->type, surface->resource_id, Core_GetIdentity() );\n\n     if (!surface->object.identity || surface->object.identity == core_dfb->fusion_id)\n          return DFB_OK;\n\n     if (core_dfb->resource.manager) {\n          client = Core_Resource_GetClient( surface->object.identity );\n          if (!client)\n               return DFB_DEAD;\n\n          return client->AddSurface( client, surface );\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nCore_Resource_RemoveSurface( CoreSurface *surface )\n{\n     ICoreResourceClient *client;\n\n     D_DEBUG_AT( Core_Resource, \"%s( %dx%d, %s, type %u, resource id %lu ) <- identity %lu\\n\", __FUNCTION__,\n                 surface->config.size.w, surface->config.size.h, dfb_pixelformat_name( surface->config.format ),\n                 surface->type, surface->resource_id, surface->object.identity );\n\n     if (!surface->object.identity || surface->object.identity == core_dfb->fusion_id)\n          return DFB_OK;\n\n     if (core_dfb->resource.manager) {\n          client = Core_Resource_GetClient( surface->object.identity );\n          if (!client)\n               return DFB_DEAD;\n\n          return client->RemoveSurface( client, surface );\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nCore_Resource_UpdateSurface( CoreSurface             *surface,\n                             const CoreSurfaceConfig *config )\n{\n     ICoreResourceClient *client;\n\n     D_DEBUG_AT( Core_Resource, \"%s( %dx%d, %s, type %u, resource id %lu ) <- identity %lu\\n\", __FUNCTION__,\n                 config->size.w, config->size.h, dfb_pixelformat_name( config->format ), surface->type,\n                 surface->resource_id, surface->object.identity );\n\n     if (!surface->object.identity || surface->object.identity == core_dfb->fusion_id)\n          return DFB_OK;\n\n     if (core_dfb->resource.manager) {\n          client = Core_Resource_GetClient( surface->object.identity );\n          if (!client)\n               return DFB_DEAD;\n\n          return client->UpdateSurface( client, surface, config );\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nCore_Resource_AddIdentity( FusionID fusion_id,\n                           u32      slave_call )\n{\n     DFBResult         ret;\n     ResourceIdentity *identity;\n     FusionID          call_owner;\n\n     D_DEBUG_AT( Core_Resource, \"%s( %lu )\\n\", __FUNCTION__, fusion_id );\n\n     identity = direct_hash_lookup( core_dfb->resource.identities, fusion_id );\n     if (identity) {\n          D_BUG( \"alredy registered\" );\n          return DFB_BUSY;\n     }\n\n     identity = D_CALLOC( 1, sizeof(ResourceIdentity) );\n     if (!identity)\n          return D_OOM();\n\n     fusion_call_init_from( &identity->slave.call, slave_call, dfb_core_world( core_dfb ) );\n\n     ret = fusion_call_get_owner( &identity->slave.call, &call_owner );\n     if (ret) {\n          D_FREE( identity );\n          return ret;\n     }\n\n     if (call_owner != fusion_id) {\n          D_ERROR( \"Core/Resource: Slave call owner (%lu) does not match new identity (%lu)!\\n\", call_owner, fusion_id );\n          D_FREE( identity );\n          return DFB_FAILURE;\n     }\n\n     if (core_dfb->resource.manager) {\n          ret = core_dfb->resource.manager->CreateClient( core_dfb->resource.manager, fusion_id, &identity->client );\n          if (ret) {\n               D_DERROR( ret, \"Core/Resource: CreateClient() failed!\\n\" );\n               D_FREE( identity );\n               return ret;\n          }\n     }\n\n     ret = direct_hash_insert( core_dfb->resource.identities, fusion_id, identity );\n     if (ret) {\n          D_DERROR( ret, \"Core/Resource: Could not insert identity into hash table!\\n\" );\n\n          if (identity->client)\n               identity->client->Release( identity->client );\n\n          D_FREE( identity );\n          return ret;\n     }\n\n     return DFB_OK;\n}\n\nvoid\nCore_Resource_DisposeIdentity( FusionID fusion_id )\n{\n     ResourceIdentity *identity;\n\n     D_DEBUG_AT( Core_Resource, \"%s( %lu )\\n\", __FUNCTION__, fusion_id );\n\n     identity = direct_hash_lookup( core_dfb->resource.identities, fusion_id );\n     if (identity) {\n          if (identity->client)\n               identity->client->Release( identity->client );\n\n          direct_hash_remove( core_dfb->resource.identities, fusion_id );\n\n          D_FREE( identity );\n     }\n}\n\nICoreResourceClient *\nCore_Resource_GetClient( FusionID fusion_id )\n{\n     ResourceIdentity *identity;\n\n     D_DEBUG_AT( Core_Resource, \"%s( %lu )\\n\", __FUNCTION__, fusion_id );\n\n     identity = direct_hash_lookup( core_dfb->resource.identities, fusion_id );\n     if (identity)\n          return identity->client;\n\n     return NULL;\n}\n\nCoreSlave *\nCore_Resource_GetSlave( FusionID fusion_id )\n{\n     ResourceIdentity *identity;\n\n     D_DEBUG_AT( Core_Resource, \"%s( %lu )\\n\", __FUNCTION__, fusion_id );\n\n     identity = direct_hash_lookup( core_dfb->resource.identities, fusion_id );\n     if (identity)\n          return &identity->slave;\n\n     return NULL;\n}\n"
  },
  {
    "path": "src/core/core.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__CORE_H__\n#define __CORE__CORE_H__\n\n#include <core/CoreSlave_includes.h>\n#include <core/core_resourcemanager.h>\n#include <fusion/object.h>\n\n/**********************************************************************************************************************/\n\n#define DIRECTFB_CORE_ABI 46\n\ntypedef struct {\n     int                  magic;\n\n     bool                 secure;\n\n     FusionObjectPool    *graphics_state_pool;\n     FusionObjectPool    *layer_context_pool;\n     FusionObjectPool    *layer_region_pool;\n     FusionObjectPool    *palette_pool;\n     FusionObjectPool    *surface_pool;\n     FusionObjectPool    *surface_allocation_pool;\n     FusionObjectPool    *surface_buffer_pool;\n     FusionObjectPool    *surface_client_pool;\n     FusionObjectPool    *window_pool;\n\n     FusionSHMPoolShared *shmpool;\n     FusionSHMPoolShared *shmpool_data;\n\n     FusionCall           call;\n     FusionHash          *field_hash;\n} CoreDFBShared;\n\nstruct __DFB_CoreDFB {\n     int                        magic;\n\n     int                        refs;\n\n     FusionID                   fusion_id;\n\n     FusionWorld               *world;\n\n     CoreDFBShared             *shared;\n\n     bool                       suspended;\n\n     DirectLink                *cleanups;\n\n     DirectThreadInitHandler   *init_handler;\n\n     DirectSignalHandler       *signal_handler;\n\n     DirectCleanupHandler      *cleanup_handler;\n\n     CoreFontManager           *font_manager;\n\n     struct {\n          ICoreResourceManager *manager;\n          DirectHash           *identities;\n     } resource;\n\n     FusionCall                 async_call;\n\n     FusionCall                 slave_call;\n\n     DirectLink                *memory_permissions;\n     DirectMutex                memory_permissions_lock;\n\n     int                        shutdown_tid;\n     int                        shutdown_running;\n};\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     DFCP_CLIPBOARD = 0x00000000,\n     DFCP_COLORHASH = 0x00000001,\n     DFCP_GRAPHICS  = 0x00000002,\n     DFCP_INPUT     = 0x00000003,\n     DFCP_LAYER     = 0x00000004,\n     DFCP_SCREEN    = 0x00000005,\n     DFCP_SURFACE   = 0x00000006,\n     DFCP_SYSTEM    = 0x00000007,\n     DFCP_WM        = 0x00000008,\n} CorePartID;\n\ntypedef enum {\n     CMPF_READ  = 0x00000001,\n     CMPF_WRITE = 0x00000002,\n} CoreMemoryPermissionFlags;\n\ntypedef void (*CoreCleanupFunc)( void *data, int emergency );\n\ntypedef void (*AsyncCallFunc)( void *ctx, void *ctx2 );\n\ntypedef struct {\n     AsyncCallFunc  func;\n\n     void          *ctx;\n     void          *ctx2;\n} AsyncCall;\n\n#define CORE_TLS_IDENTITY_STACK_MAX 8\n\ntypedef struct {\n     int          magic;\n\n     FusionID     identity[CORE_TLS_IDENTITY_STACK_MAX];\n     unsigned int identity_count;\n\n     int          calling;\n} CoreTLS;\n\n/**********************************************************************************************************************/\n\nextern CoreDFB        *core_dfb;\n\n/*\n * Core initialization and deinitialization.\n */\nDFBResult              dfb_core_create                   ( CoreDFB                   **ret_core );\n\nDFBResult              dfb_core_destroy                  ( CoreDFB                    *core,\n                                                           bool                        emergency );\n\nvoid                  *dfb_core_get_part                 ( CoreDFB                    *core,\n                                                           CorePartID                  part_id );\n\nDFBResult              dfb_core_initialize               ( CoreDFB                    *core );\n\n/*\n * Object creation.\n */\nCoreGraphicsState     *dfb_core_create_graphics_state    ( CoreDFB                    *core );\nCoreLayerContext      *dfb_core_create_layer_context     ( CoreDFB                    *core );\nCoreLayerRegion       *dfb_core_create_layer_region      ( CoreDFB                    *core );\nCorePalette           *dfb_core_create_palette           ( CoreDFB                    *core );\nCoreSurface           *dfb_core_create_surface           ( CoreDFB                    *core );\nCoreSurfaceAllocation *dfb_core_create_surface_allocation( CoreDFB                    *core );\nCoreSurfaceBuffer     *dfb_core_create_surface_buffer    ( CoreDFB                    *core );\nCoreSurfaceClient     *dfb_core_create_surface_client    ( CoreDFB                    *core );\nCoreWindow            *dfb_core_create_window            ( CoreDFB                    *core );\n\n/*\n * Object accessor.\n */\nDFBResult              dfb_core_get_graphics_state       ( CoreDFB                    *core,\n                                                           u32                         object_id,\n                                                           CoreGraphicsState         **ret_state );\n\nDFBResult              dfb_core_get_layer_context        ( CoreDFB                    *core,\n                                                           u32                         object_id,\n                                                           CoreLayerContext          **ret_context );\n\nDFBResult              dfb_core_get_layer_region         ( CoreDFB                    *core,\n                                                           u32                         object_id,\n                                                           CoreLayerRegion           **ret_region );\n\nDFBResult              dfb_core_get_palette              ( CoreDFB                    *core,\n                                                           u32                         object_id,\n                                                           CorePalette               **ret_palette );\n\nDFBResult              dfb_core_get_surface              ( CoreDFB                    *core,\n                                                           u32                         object_id,\n                                                           CoreSurface               **ret_surface );\n\nDFBResult              dfb_core_get_surface_allocation   ( CoreDFB                    *core,\n                                                           u32                         object_id,\n                                                           CoreSurfaceAllocation     **ret_allocation );\n\nDFBResult              dfb_core_get_surface_buffer       ( CoreDFB                    *core,\n                                                           u32                         object_id,\n                                                           CoreSurfaceBuffer         **ret_surface );\n\nDFBResult              dfb_core_get_surface_client       ( CoreDFB                    *core,\n                                                           u32                         object_id,\n                                                           CoreSurfaceClient         **ret_client );\n\nDFBResult              dfb_core_get_window               ( CoreDFB                    *core,\n                                                           u32                         object_id,\n                                                           CoreWindow                **ret_window );\n\n/*\n * Object enumeration.\n */\nDirectResult           dfb_core_enum_graphics_states     ( CoreDFB                    *core,\n                                                           FusionObjectCallback        callback,\n                                                           void                       *ctx );\n\nDirectResult           dfb_core_enum_layer_contexts      ( CoreDFB                    *core,\n                                                           FusionObjectCallback        callback,\n                                                           void                       *ctx );\n\nDirectResult           dfb_core_enum_layer_regions       ( CoreDFB                    *core,\n                                                           FusionObjectCallback        callback,\n                                                           void                       *ctx );\n\nDirectResult           dfb_core_enum_palettes            ( CoreDFB                    *core,\n                                                           FusionObjectCallback        callback,\n                                                           void                       *ctx );\n\nDirectResult           dfb_core_enum_surfaces            ( CoreDFB                    *core,\n                                                           FusionObjectCallback        callback,\n                                                           void                       *ctx );\n\nDirectResult           dfb_core_enum_surface_allocations ( CoreDFB                    *core,\n                                                           FusionObjectCallback        callback,\n                                                           void                       *ctx );\n\nDirectResult           dfb_core_enum_surface_buffers     ( CoreDFB                    *core,\n                                                           FusionObjectCallback        callback,\n                                                           void                       *ctx );\n\nDirectResult           dfb_core_enum_surface_clients     ( CoreDFB                    *core,\n                                                           FusionObjectCallback        callback,\n                                                           void                       *ctx );\n\nDirectResult           dfb_core_enum_windows             ( CoreDFB                    *core,\n                                                           FusionObjectCallback        callback,\n                                                           void                       *ctx );\n\n/*\n * Arena shared fields.\n */\nDirectResult           core_arena_add_shared_field       ( CoreDFB                    *core,\n                                                           const char                 *name,\n                                                           void                       *data );\n\nDirectResult           core_arena_get_shared_field       ( CoreDFB                    *core,\n                                                           const char                 *name,\n                                                           void                      **data );\n\n/*\n * Returns true if the calling process is the master fusionee.\n */\nbool                   dfb_core_is_master                ( CoreDFB                    *core );\n\n/*\n * Allows other (blocking) fusionees to enter the DirectFB session.\n */\nvoid                   dfb_core_activate                 ( CoreDFB                    *core );\n\n/*\n * Returns the core's fusion world.\n */\nFusionWorld           *dfb_core_world                    ( CoreDFB                    *core );\n\n/*\n * Returns the shared memory pool of the core.\n */\nFusionSHMPoolShared   *dfb_core_shmpool                  ( CoreDFB                    *core );\n\n/*\n * Returns the shared memory pool for raw data, e.g. surface buffers.\n */\nFusionSHMPoolShared   *dfb_core_shmpool_data             ( CoreDFB                    *core );\n\n/*\n * Suspends all core parts, stopping input threads, closing devices...\n */\nDFBResult              dfb_core_suspend                  ( CoreDFB                    *core );\n\n/*\n * Resumes all core parts, reopening devices, starting input threads...\n */\nDFBResult              dfb_core_resume                   ( CoreDFB                    *core );\n\n/*\n * Adds a function to the cleanup stack that is called during deinitialization.\n */\nCoreCleanup           *dfb_core_cleanup_add              ( CoreDFB                    *core,\n                                                           CoreCleanupFunc             func,\n                                                           void                       *data,\n                                                           bool                        emergency );\n\n/*\n * Removes a function from the cleanup stack.\n */\nvoid                   dfb_core_cleanup_remove           ( CoreDFB                    *core,\n                                                           CoreCleanup                *cleanup );\n\n/*\n * Returns the font manager of the core.\n */\nCoreFontManager        *dfb_core_font_manager            ( CoreDFB                    *core );\n\n/*\n * Memory permissions management.\n */\n\nDFBResult              dfb_core_memory_permissions_add   ( CoreDFB                    *core,\n                                                           CoreMemoryPermissionFlags   flags,\n                                                           void                       *data,\n                                                           size_t                      length,\n                                                           CoreMemoryPermission      **ret_permission );\n\nDFBResult              dfb_core_memory_permissions_remove( CoreDFB                    *core,\n                                                           CoreMemoryPermission       *permission );\n\nDFBResult              dfb_core_memory_permissions_check ( CoreDFB                    *core,\n                                                           CoreMemoryPermissionFlags   flags,\n                                                           void                       *data,\n                                                           size_t                      length );\n\n/*\n * Thread Local Storage management.\n */\n\nvoid                   Core_TLS__init                    ( void );\n\nvoid                   Core_TLS__deinit                  ( void );\n\nCoreTLS               *Core_GetTLS                       ( void );\n\n/*\n * Identity management, incoming dispatch pushes ID of caller.\n */\n\nvoid                   Core_PushIdentity                 ( FusionID                    caller );\n\nvoid                   Core_PopIdentity                  ( void );\n\nFusionID               Core_GetIdentity                  ( void );\n\n#if FUSION_BUILD_MULTI\nvoid                   Core_PushCalling                  ( void );\nvoid                   Core_PopCalling                   ( void );\nint                    Core_GetCalling                   ( void );\n#else /* FUSION_BUILD_MULTI */\n#define                Core_PushCalling(x)\n#define                Core_PopCalling(x)\n#endif /* FUSION_BUILD_MULTI */\n\n/*\n * Resource management.\n */\n\nDFBResult              Core_Resource_CheckSurface        ( const CoreSurfaceConfig    *config,\n                                                           u64                         resource_id );\n\nDFBResult              Core_Resource_CheckSurfaceUpdate  ( CoreSurface                *surface,\n                                                           const CoreSurfaceConfig    *config );\n\nDFBResult              Core_Resource_AddSurface          ( CoreSurface                *surface );\n\nDFBResult              Core_Resource_RemoveSurface       ( CoreSurface                *surface );\n\nDFBResult              Core_Resource_UpdateSurface       ( CoreSurface                *surface,\n                                                           const CoreSurfaceConfig    *config );\n\n/*\n * Client instance management.\n */\n\nDFBResult              Core_Resource_AddIdentity         ( FusionID                    identity,\n                                                           u32                         slave_call );\n\nvoid                   Core_Resource_DisposeIdentity     ( FusionID                    identity );\n\nICoreResourceClient   *Core_Resource_GetClient           ( FusionID                    identity );\n\nCoreSlave             *Core_Resource_GetSlave            ( FusionID                    identity );\n\n/*\n * Runs a call on the Fusion dispatch thread.\n * Used for asynchronous destruct, i.e. when a call needs to destroy itself.\n */\nstatic __inline__ DFBResult\nCore_AsyncCall( AsyncCallFunc  func,\n                void          *ctx,\n                void          *ctx2 )\n{\n     AsyncCall call;\n\n     call.func = func;\n     call.ctx  = ctx;\n     call.ctx2 = ctx2;\n\n     return fusion_call_execute2( &core_dfb->async_call, FCEF_ONEWAY | FCEF_NODIRECT, 0, &call, sizeof(call), NULL );\n}\n\n#endif\n"
  },
  {
    "path": "src/core/core_parts.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core.h>\n#include <core/core_parts.h>\n#include <fusion/shmalloc.h>\n\nD_DEBUG_DOMAIN( Core_Parts, \"Core/Parts\", \"DirectFB Core Parts\" );\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_core_part_initialize( CoreDFB  *core,\n                          CorePart *core_part )\n{\n     DFBResult            ret;\n     void                *local  = NULL;\n     void                *shared = NULL;\n     FusionSHMPoolShared *pool;\n\n     pool = dfb_core_shmpool( core );\n\n     if (core_part->initialized) {\n          D_BUG( \"%s already initialized\", core_part->name );\n          return DFB_BUG;\n     }\n\n     D_DEBUG_AT( Core_Parts, \"Going to initialize '%s' core...\\n\", core_part->name );\n\n     if (core_part->size_local)\n          local = D_CALLOC( 1, core_part->size_local );\n\n     if (core_part->size_shared)\n          shared = SHCALLOC( pool, 1, core_part->size_shared );\n\n     core_part->data_local  = local;\n     core_part->data_shared = shared;\n\n     ret = core_part->Initialize( core, local, shared );\n     if (ret) {\n          D_DERROR( ret, \"Core/Parts: Could not initialize '%s' core!\\n\", core_part->name );\n\n          if (shared)\n               SHFREE( pool, shared );\n\n          if (local)\n               D_FREE( local );\n\n          core_part->data_local  = NULL;\n          core_part->data_shared = NULL;\n\n          return ret;\n     }\n\n     if (shared)\n          core_arena_add_shared_field( core, core_part->name, shared );\n\n     core_part->initialized = true;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_core_part_join( CoreDFB  *core,\n                    CorePart *core_part )\n{\n     DFBResult  ret;\n     void      *local  = NULL;\n     void      *shared = NULL;\n\n     if (core_part->initialized) {\n          D_BUG( \"%s already joined\", core_part->name );\n          return DFB_BUG;\n     }\n\n     D_DEBUG_AT( Core_Parts, \"Going to join '%s' core...\\n\", core_part->name );\n\n     if (core_part->size_shared &&\n         core_arena_get_shared_field( core, core_part->name, &shared ))\n          return DFB_FUSION;\n\n     if (core_part->size_local)\n          local = D_CALLOC( 1, core_part->size_local );\n\n     ret = core_part->Join( core, local, shared );\n     if (ret) {\n          D_DERROR( ret, \"Core/Parts: Could not join '%s' core!\\n\", core_part->name );\n          if (local)\n               D_FREE( local );\n\n          return ret;\n     }\n\n     core_part->data_local  = local;\n     core_part->data_shared = shared;\n     core_part->initialized = true;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_core_part_shutdown( CoreDFB  *core,\n                        CorePart *core_part,\n                        bool      emergency )\n{\n     DFBResult            ret;\n     FusionSHMPoolShared *pool;\n\n     pool = dfb_core_shmpool( core );\n\n     if (!core_part->initialized)\n          return DFB_OK;\n\n     D_DEBUG_AT( Core_Parts, \"Going to shutdown '%s' core...\\n\", core_part->name );\n\n     ret = core_part->Shutdown( core_part->data_local, emergency );\n     if (ret)\n          direct_messages_derror( ret, \"Core/Parts: Could not shutdown '%s' core!\\n\", core_part->name );\n\n     if (core_part->data_shared)\n          SHFREE( pool, core_part->data_shared );\n\n     if (core_part->data_local)\n          D_FREE( core_part->data_local );\n\n     core_part->data_local  = NULL;\n     core_part->data_shared = NULL;\n     core_part->initialized = false;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_core_part_leave( CoreDFB  *core,\n                     CorePart *core_part,\n                     bool      emergency )\n{\n     DFBResult ret;\n\n     if (!core_part->initialized)\n          return DFB_OK;\n\n     D_DEBUG_AT( Core_Parts, \"Going to leave '%s' core...\\n\", core_part->name );\n\n     ret = core_part->Leave( core_part->data_local, emergency );\n     if (ret)\n          D_DERROR( ret, \"Core/Parts: Could not leave '%s' core!\\n\", core_part->name );\n\n     if (core_part->data_local)\n          D_FREE( core_part->data_local );\n\n     core_part->data_local  = NULL;\n     core_part->data_shared = NULL;\n     core_part->initialized = false;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/core/core_parts.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__CORE_PARTS_H__\n#define __CORE__CORE_PARTS_H__\n\n#include <core/coretypes.h>\n\n/**********************************************************************************************************************/\n\ntypedef DFBResult (*CoreInitialize)( CoreDFB *core, void *data_local, void *data_shared );\ntypedef DFBResult (*CoreJoin)      ( CoreDFB *core, void *data_local, void *data_shared );\ntypedef DFBResult (*CoreShutdown)  ( void *data_local, bool emergency );\ntypedef DFBResult (*CoreLeave)     ( void *data_local, bool emergency );\ntypedef DFBResult (*CoreSuspend)   ( void *data_local );\ntypedef DFBResult (*CoreResume)    ( void *data_local );\n\ntypedef struct {\n     const char     *name;\n\n     int             size_local;\n     int             size_shared;\n\n     CoreInitialize  Initialize;\n     CoreJoin        Join;\n     CoreShutdown    Shutdown;\n     CoreLeave       Leave;\n     CoreSuspend     Suspend;\n     CoreResume      Resume;\n\n     void           *data_local;\n     void           *data_shared;\n\n     bool            initialized;\n} CorePart;\n\n/**********************************************************************************************************************/\n\nDFBResult dfb_core_part_initialize( CoreDFB  *core,\n                                    CorePart *core_part );\n\nDFBResult dfb_core_part_join      ( CoreDFB  *core,\n                                    CorePart *core_part );\n\nDFBResult dfb_core_part_shutdown  ( CoreDFB  *core,\n                                    CorePart *core_part,\n                                    bool      emergency );\n\nDFBResult dfb_core_part_leave     ( CoreDFB  *core,\n                                    CorePart *core_part,\n                                    bool      emergency );\n\n#define DFB_CORE_PART(part,Type)                                          \\\n                                                                          \\\nstatic DFBResult dfb_##part##_initialize( CoreDFB           *core,        \\\n                                          DFB##Type         *local,       \\\n                                          DFB##Type##Shared *shared );    \\\n                                                                          \\\nstatic DFBResult dfb_##part##_join      ( CoreDFB           *core,        \\\n                                          DFB##Type         *local,       \\\n                                          DFB##Type##Shared *shared );    \\\n                                                                          \\\nstatic DFBResult dfb_##part##_shutdown  ( DFB##Type         *local,       \\\n                                          bool               emergency ); \\\n                                                                          \\\nstatic DFBResult dfb_##part##_leave     ( DFB##Type         *local,       \\\n                                          bool               emergency ); \\\n                                                                          \\\nstatic DFBResult dfb_##part##_suspend   ( DFB##Type         *local );     \\\n                                                                          \\\nstatic DFBResult dfb_##part##_resume    ( DFB##Type         *local );     \\\n                                                                          \\\nCorePart dfb_##part = {                                                   \\\n     .name        = #part,                                                \\\n                                                                          \\\n     .size_local  = sizeof(DFB##Type),                                    \\\n     .size_shared = sizeof(DFB##Type##Shared),                            \\\n                                                                          \\\n     .Initialize  = (void*) dfb_##part##_initialize,                      \\\n     .Join        = (void*) dfb_##part##_join,                            \\\n     .Shutdown    = (void*) dfb_##part##_shutdown,                        \\\n     .Leave       = (void*) dfb_##part##_leave,                           \\\n     .Suspend     = (void*) dfb_##part##_suspend,                         \\\n     .Resume      = (void*) dfb_##part##_resume,                          \\\n}\n\n#endif\n"
  },
  {
    "path": "src/core/core_resourcemanager.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__CORE_RESOURCEMANAGER_H__\n#define __CORE__CORE_RESOURCEMANAGER_H__\n\n#include <core/coretypes.h>\n#include <fusion/fusion.h>\n\n/*\n * Resource manager interface.\n */\nD_DECLARE_INTERFACE( ICoreResourceManager )\nD_DECLARE_INTERFACE( ICoreResourceClient )\n\n/************************\n * ICoreResourceManager *\n ************************/\n\n/*\n * ICoreResourceManager is the resource manager interface.\n */\nD_DEFINE_INTERFACE( ICoreResourceManager,\n\n   /** Creating client **/\n\n     /*\n      * Create a new client instance (called within master,\n      * per slave).\n      */\n     DFBResult (*CreateClient) (\n          ICoreResourceManager              *thiz,\n          FusionID                           identity,\n          ICoreResourceClient              **ret_client\n     );\n)\n\n/*\n * ICoreResourceClient per slave resource accounting.\n */\nD_DEFINE_INTERFACE( ICoreResourceClient,\n\n   /** Tracking of the resource client instance **/\n\n     /*\n      * Check surface creation.\n      */\n     DFBResult (*CheckSurface) (\n          ICoreResourceClient               *thiz,\n          const CoreSurfaceConfig           *config,\n          u64                                resource_id\n     );\n\n     /*\n      * Check surface reconfig.\n      */\n     DFBResult (*CheckSurfaceUpdate) (\n          ICoreResourceClient               *thiz,\n          CoreSurface                       *surface,\n          const CoreSurfaceConfig           *config\n     );\n\n     /*\n      * Add surface.\n      */\n     DFBResult (*AddSurface) (\n          ICoreResourceClient               *thiz,\n          CoreSurface                       *surface\n     );\n\n     /*\n      * Remove surface.\n      */\n     DFBResult (*RemoveSurface) (\n          ICoreResourceClient               *thiz,\n          CoreSurface                       *surface\n     );\n\n     /*\n      * Update surface.\n      */\n     DFBResult (*UpdateSurface) (\n          ICoreResourceClient               *thiz,\n          CoreSurface                       *surface,\n          const CoreSurfaceConfig           *config\n     );\n)\n\n#endif\n"
  },
  {
    "path": "src/core/core_system.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__CORE_SYSTEM_H__\n#define __CORE__CORE_SYSTEM_H__\n\n#include <core/system.h>\n\n/**********************************************************************************************************************/\n\nstatic void           system_get_info             ( CoreSystemInfo   *info );\n\nstatic DFBResult      system_initialize           ( CoreDFB          *core,\n                                                    void            **ret_data );\n\nstatic DFBResult      system_join                 ( CoreDFB          *core,\n                                                    void            **ret_data );\n\nstatic DFBResult      system_shutdown             ( bool              emergency );\n\nstatic DFBResult      system_leave                ( bool              emergency );\n\nstatic DFBResult      system_suspend              ( void );\n\nstatic DFBResult      system_resume               ( void );\n\nstatic VideoMode     *system_get_modes            ( void );\n\nstatic VideoMode     *system_get_current_mode     ( void );\n\nstatic DFBResult      system_thread_init          ( void );\n\nstatic bool           system_input_filter         ( CoreInputDevice  *device,\n                                                    DFBInputEvent    *event );\n\nstatic volatile void *system_map_mmio             ( unsigned int      offset,\n                                                    int               length );\n\nstatic void           system_unmap_mmio           ( volatile void    *addr,\n                                                    int               length );\n\nstatic unsigned int   system_get_accelerator      ( void );\n\nstatic unsigned long  system_video_memory_physical( unsigned int      offset );\n\nstatic void          *system_video_memory_virtual ( unsigned int      offset );\n\nstatic unsigned int   system_videoram_length      ( void );\n\nstatic void           system_get_busid            ( int              *ret_bus,\n                                                    int              *ret_dev,\n                                                    int              *ret_func );\n\nstatic void           system_get_deviceid         ( unsigned int     *ret_vendor_id,\n                                                    unsigned int     *ret_device_id );\n\nstatic CoreSystemFuncs system_funcs = {\n     .GetSystemInfo       = system_get_info,\n     .Initialize          = system_initialize,\n     .Join                = system_join,\n     .Shutdown            = system_shutdown,\n     .Leave               = system_leave,\n     .Suspend             = system_suspend,\n     .Resume              = system_resume,\n     .GetModes            = system_get_modes,\n     .GetCurrentMode      = system_get_current_mode,\n     .ThreadInit          = system_thread_init,\n     .InputFilter         = system_input_filter,\n     .MapMMIO             = system_map_mmio,\n     .UnmapMMIO           = system_unmap_mmio,\n     .GetAccelerator      = system_get_accelerator,\n     .VideoMemoryPhysical = system_video_memory_physical,\n     .VideoMemoryVirtual  = system_video_memory_virtual,\n     .VideoRamLength      = system_videoram_length,\n     .GetBusID            = system_get_busid,\n     .GetDeviceID         = system_get_deviceid\n};\n\n#define DFB_CORE_SYSTEM(shortname)                         \\\n                                                           \\\n__dfb_constructor__                                        \\\nvoid                                                       \\\ndirectfb_##shortname##_ctor( void )                        \\\n{                                                          \\\n     direct_modules_register( &dfb_core_systems,           \\\n                              DFB_CORE_SYSTEM_ABI_VERSION, \\\n                              #shortname,                  \\\n                              &system_funcs );             \\\n}\n\n#endif\n"
  },
  {
    "path": "src/core/coredefs.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__COREDEFS_H__\n#define __CORE__COREDEFS_H__\n\n#define MAX_INPUT_GLOBALS              8\n#define MAX_INPUTDEVICES              16\n\n#define MAX_LAYERS                    24\n\n#define MAX_SCREENS                    4\n\n#define MAX_SURFACE_BUFFERS            6\n#define MAX_SURFACE_POOLS              8\n#define MAX_SURFACE_POOL_BRIDGES       4\n\n#define MAX_CLIPBOARD_MIME_TYPE_SIZE  (128)\n#define MAX_CLIPBOARD_DATA_SIZE       (48*1024)\n\n#endif\n"
  },
  {
    "path": "src/core/coretypes.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__CORETYPES_H__\n#define __CORE__CORETYPES_H__\n\n#include <build.h>\n#include <directfb.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct __DFB_CardState               CardState;\ntypedef struct __DFB_CoreCleanup             CoreCleanup;\ntypedef struct __DFB_CoreDFB                 CoreDFB;\ntypedef struct __DFB_CoreGraphicsState       CoreGraphicsState;\ntypedef struct __DFB_CoreGraphicsStateClient CoreGraphicsStateClient;\ntypedef struct __DFB_CoreFont                CoreFont;\ntypedef struct __DFB_CoreFontCache           CoreFontCache;\ntypedef struct __DFB_CoreFontCacheRow        CoreFontCacheRow;\ntypedef struct __DFB_CoreFontManager         CoreFontManager;\ntypedef struct __DFB_CoreGlyphData           CoreGlyphData;\ntypedef struct __DFB_CoreInputDevice         CoreInputDevice;\ntypedef struct __DFB_CoreLayer               CoreLayer;\ntypedef struct __DFB_CoreLayerContext        CoreLayerContext;\ntypedef struct __DFB_CoreLayerRegion         CoreLayerRegion;\ntypedef struct __DFB_CoreMemoryPermission    CoreMemoryPermission;\ntypedef struct __DFB_CorePalette             CorePalette;\ntypedef struct __DFB_CoreScreen              CoreScreen;\ntypedef struct __DFB_CoreSurface             CoreSurface;\ntypedef struct __DFB_CoreSurfaceAllocation   CoreSurfaceAllocation;\ntypedef struct __DFB_CoreSurfaceBuffer       CoreSurfaceBuffer;\ntypedef struct __DFB_CoreSurfaceBufferLock   CoreSurfaceBufferLock;\ntypedef struct __DFB_CoreSurfaceClient       CoreSurfaceClient;\ntypedef struct __DFB_CoreSurfaceConfig       CoreSurfaceConfig;\ntypedef struct __DFB_CoreSurfacePool         CoreSurfacePool;\ntypedef struct __DFB_CoreSurfacePoolBridge   CoreSurfacePoolBridge;\ntypedef struct __DFB_CoreWindow              CoreWindow;\ntypedef struct __DFB_CoreWindowConfig        CoreWindowConfig;\ntypedef struct __DFB_CoreWindowStack         CoreWindowStack;\ntypedef struct __DFB_GenefxState             GenefxState;\ntypedef struct __DFB_GraphicsDeviceInfo      GraphicsDeviceInfo;\ntypedef struct __DFB_GraphicsDriverInfo      GraphicsDriverInfo;\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     unsigned int serial;\n     unsigned int generation;\n} CoreGraphicsSerial;\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CWMGT_KEYBOARD        = 0x00000000,\n     CWMGT_POINTER         = 0x00000001,\n     CWMGT_KEY             = 0x00000002,\n     CWMGT_UNSELECTED_KEYS = 0x00000003,\n} CoreWMGrabTarget;\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CSAID_NONE    = 0x00000000, /* none or unknown accessor */\n\n     CSAID_CPU     = 0x00000001, /* local processor */\n\n     CSAID_GPU     = 0x00000002, /* primary accelerator, as in traditional 'gfxcard' core (ACCEL0) */\n\n     CSAID_ACCEL0  = 0x00000002, /* accelerators, decoders (CSAID_ACCEL0 + accel_id<0-5>) */\n     CSAID_ACCEL1  = 0x00000003,\n     CSAID_ACCEL2  = 0x00000004,\n     CSAID_ACCEL3  = 0x00000005,\n     CSAID_ACCEL4  = 0x00000006,\n     CSAID_ACCEL5  = 0x00000007,\n\n     CSAID_LAYER0  = 0x00000008, /* display layers (CSAID_LAYER0 + layer_id<0-MAX_LAYERS>) */\n     CSAID_LAYER1  = 0x00000009,\n     CSAID_LAYER2  = 0x0000000a,\n     CSAID_LAYER3  = 0x0000000b,\n     CSAID_LAYER4  = 0x0000000c,\n     CSAID_LAYER5  = 0x0000000d,\n     CSAID_LAYER6  = 0x0000000e,\n     CSAID_LAYER7  = 0x0000000f,\n     CSAID_LAYER8  = 0x00000010,\n     CSAID_LAYER9  = 0x00000011,\n     CSAID_LAYER10 = 0x00000012,\n     CSAID_LAYER11 = 0x00000013,\n     CSAID_LAYER12 = 0x00000014,\n     CSAID_LAYER13 = 0x00000015,\n     CSAID_LAYER14 = 0x00000016,\n     CSAID_LAYER15 = 0x00000017,\n\n     CSAID_NUM     = 0x00000018, /* number of statically assigned IDs for usage in static arrays */\n\n     CSAID_ANY     = 0x00000100  /* any other accessor needs to be registered using IDs starting from here */\n} CoreSurfaceAccessorID;\n\ntypedef unsigned int CoreSurfacePoolID;\n\ntypedef unsigned int CoreSurfacePoolBridgeID;\n\n#endif\n"
  },
  {
    "path": "src/core/cursor.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\nstatic const unsigned int cursor_data[] = {\n     0xe8fdfdfd, 0x83e8e8e8, 0x40d3d3d3, 0x1ed0d0d0,\n     0x15dddddd, 0x10ebebeb, 0x0af3f3f3, 0x05f8f8f8,\n     0x02fbfbfb, 0x01fdfdfd, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0xd9fcfcfc, 0xefffffff, 0xd0f9f9f9, 0x96e2e2e2,\n     0x51cccccc, 0x23cbcbcb, 0x15dadada, 0x0fe9e9e9,\n     0x0af2f2f2, 0x05f8f8f8, 0x02fbfbfb, 0x02fdfdfd,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0xa1e0e0e0, 0xdaffffff, 0xedffffff, 0xd6ffffff,\n     0xd0fafafa, 0x9be3e3e3, 0x56cccccc, 0x25c9c9c9,\n     0x15d8d8d8, 0x10e7e7e7, 0x0af1f1f1, 0x06f7f7f7,\n     0x03fbfbfb, 0x01fdfdfd, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x67b7b7b7, 0xd5fbfbfb, 0xd6ffffff, 0xebffffff,\n     0xd2ffffff, 0xcfffffff, 0xccfdfdfd, 0x9fe7e7e7,\n     0x5bcfcfcf, 0x28c9c9c9, 0x15d6d6d6, 0x10e7e7e7,\n     0x0af1f1f1, 0x06f7f7f7, 0x03fbfbfb, 0x01fdfdfd,\n     0x00fefefe, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x44a5a5a5, 0xb1d9d9d9, 0xd4ffffff, 0xd2ffffff,\n     0xe9ffffff, 0xceffffff, 0xccffffff, 0xc9ffffff,\n     0xc7fefefe, 0xa1ebebeb, 0x62d3d3d3, 0x2dcacaca,\n     0x15d4d4d4, 0x0fe5e5e5, 0x0af1f1f1, 0x06f7f7f7,\n     0x03fafafa, 0x01fdfdfd, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x36b3b3b3, 0x78ababab, 0xd1fdfdfd, 0xcfffffff,\n     0xceffffff, 0xccffffff, 0xcaffffff, 0xc7ffffff,\n     0xc5ffffff, 0xc2ffffff, 0xc0ffffff, 0xa7f0f0f0,\n     0x69d6d6d6, 0x30c9c9c9, 0x15d3d3d3, 0x0fe4e4e4,\n     0x0af0f0f0, 0x05f6f6f6, 0x03fbfbfb, 0x01fdfdfd,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x2ac9c9c9, 0x4e999999, 0xb4dcdcdc, 0xcdffffff,\n     0xccffffff, 0xcaffffff, 0xc7ffffff, 0xc6ffffff,\n     0xc3ffffff, 0xc1ffffff, 0xbfffffff, 0xbcffffff,\n     0xb9ffffff, 0xa4f2f2f2, 0x68d8d8d8, 0x2fcacaca,\n     0x14d3d3d3, 0x0ee5e5e5, 0x09f1f1f1, 0x05f7f7f7,\n     0x03fbfbfb, 0x01fdfdfd, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x1ed9d9d9, 0x39aaaaaa, 0x80acacac, 0xcafefefe,\n     0xc9ffffff, 0xc7ffffff, 0xc6ffffff, 0xc4ffffff,\n     0xc1ffffff, 0xbfffffff, 0xbdffffff, 0xbaffffff,\n     0xb8ffffff, 0xb6ffffff, 0xb3ffffff, 0x9ff3f3f3,\n     0x67d9d9d9, 0x2ccbcbcb, 0x13d4d4d4, 0x0ee6e6e6,\n     0x09f1f1f1, 0x05f7f7f7, 0x02fbfbfb, 0x01fefefe,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x14e5e5e5, 0x2dc3c3c3, 0x53959595, 0xb4e2e2e2,\n     0xc7ffffff, 0xc5ffffff, 0xc3ffffff, 0xc1ffffff,\n     0xbfffffff, 0xbeffffff, 0xbbffffff, 0xb9ffffff,\n     0xb7ffffff, 0xb4ffffff, 0xb1ffffff, 0xafffffff,\n     0xacffffff, 0x98f2f2f2, 0x5fd9d9d9, 0x29cbcbcb,\n     0x10d6d6d6, 0x0ce7e7e7, 0x08f2f2f2, 0x04f8f8f8,\n     0x02fcfcfc, 0x01fefefe, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x0deeeeee, 0x21d5d5d5, 0x3ca3a3a3, 0x85afafaf,\n     0xc4ffffff, 0xc2ffffff, 0xc1ffffff, 0xbfffffff,\n     0xbeffffff, 0xbbffffff, 0xb9ffffff, 0xb7ffffff,\n     0xb5ffffff, 0xb2ffffff, 0xb0ffffff, 0xaeffffff,\n     0xabffffff, 0xa9ffffff, 0xa6ffffff, 0x90f2f2f2,\n     0x58d8d8d8, 0x23cccccc, 0x0fd8d8d8, 0x0be9e9e9,\n     0x07f3f3f3, 0x03f9f9f9, 0x02fcfcfc, 0x01fefefe,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x08f5f5f5, 0x16e2e2e2, 0x2fbebebe, 0x57939393,\n     0xb3e7e7e7, 0xc0ffffff, 0xbfffffff, 0xbdffffff,\n     0xbbffffff, 0xb9ffffff, 0xb8ffffff, 0xb5ffffff,\n     0xb3ffffff, 0xb0ffffff, 0xafffffff, 0xacffffff,\n     0xa9ffffff, 0xa7ffffff, 0xa4ffffff, 0xa1ffffff,\n     0xa0ffffff, 0x87f0f0f0, 0x4ed6d6d6, 0x1dcdcdcd,\n     0x0ddcdcdc, 0x0aececec, 0x06f5f5f5, 0x03fafafa,\n     0x01fdfdfd, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x05f9f9f9, 0x0eececec, 0x22d1d1d1, 0x3d9e9e9e,\n     0x88b4b4b4, 0xbeffffff, 0xbcffffff, 0xbaffffff,\n     0xb9ffffff, 0xb7ffffff, 0xb5ffffff, 0xb3ffffff,\n     0xb1ffffff, 0xafffffff, 0xadffffff, 0xaaffffff,\n     0xa8ffffff, 0xa6ffffff, 0xa3ffffff, 0xa1ffffff,\n     0x9effffff, 0x9bffffff, 0x99ffffff, 0x7bececec,\n     0x3fd3d3d3, 0x16d0d0d0, 0x0be1e1e1, 0x08f0f0f0,\n     0x04f8f8f8, 0x02fcfcfc, 0x00fefefe, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x02fcfcfc, 0x08f4f4f4, 0x18dfdfdf, 0x30b9b9b9,\n     0x5c949494, 0xb3efefef, 0xb9ffffff, 0xb8ffffff,\n     0xb7ffffff, 0xb5ffffff, 0xb3ffffff, 0xb1ffffff,\n     0xafffffff, 0xadffffff, 0xaaffffff, 0xa9ffffff,\n     0xa6ffffff, 0xa4ffffff, 0xa1ffffff, 0x9fffffff,\n     0x9cffffff, 0x9affffff, 0x98ffffff, 0x95ffffff,\n     0x92fdfdfd, 0x6ae6e6e6, 0x2ed0d0d0, 0x0fd6d6d6,\n     0x0ae9e9e9, 0x06f4f4f4, 0x02fafafa, 0x01fefefe,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x01fefefe, 0x04f8f8f8, 0x0feaeaea, 0x24cdcdcd,\n     0x41989898, 0x8dbcbcbc, 0xb7ffffff, 0xb6ffffff,\n     0xb4ffffff, 0xb2ffffff, 0xb0ffffff, 0xafffffff,\n     0xadffffff, 0xabffffff, 0xa9ffffff, 0xa7ffffff,\n     0xa4ffffff, 0xa2ffffff, 0xa0ffffff, 0x9dffffff,\n     0x9bffffff, 0x99ffffff, 0x96ffffff, 0x93ffffff,\n     0x91ffffff, 0x8effffff, 0x84f9f9f9, 0x51dedede,\n     0x1ad0d0d0, 0x0ae1e1e1, 0x07f2f2f2, 0x02f9f9f9,\n     0x00fdfdfd, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x02fcfcfc, 0x09f2f2f2, 0x18dddddd,\n     0x31b3b3b3, 0x5f929292, 0xaff1f1f1, 0xb3ffffff,\n     0xb1ffffff, 0xb0ffffff, 0xafffffff, 0xadffffff,\n     0xaaffffff, 0xa9ffffff, 0xa7ffffff, 0xa5ffffff,\n     0xa2ffffff, 0xa1ffffff, 0x9effffff, 0x9bffffff,\n     0x9affffff, 0x97ffffff, 0x94ffffff, 0x92ffffff,\n     0x90ffffff, 0x8dffffff, 0x8bffffff, 0x88ffffff,\n     0x6ceeeeee, 0x2cd3d3d3, 0x0bdcdcdc, 0x07f0f0f0,\n     0x02f9f9f9, 0x00fefefe, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x01fdfdfd, 0x05f7f7f7, 0x10e8e8e8,\n     0x25c9c9c9, 0x42929292, 0x8bbebebe, 0xb0ffffff,\n     0xafffffff, 0xaeffffff, 0xacffffff, 0xaaffffff,\n     0xa9ffffff, 0xa7ffffff, 0xa5ffffff, 0xa2ffffff,\n     0xa1ffffff, 0x9effffff, 0x9cffffff, 0x9affffff,\n     0x98ffffff, 0x95ffffff, 0x92ffffff, 0x91ffffff,\n     0x8effffff, 0x8bffffff, 0x89ffffff, 0x86ffffff,\n     0x83ffffff, 0x78f8f8f8, 0x30d6d6d6, 0x0adddddd,\n     0x07f2f2f2, 0x02fafafa, 0x00fefefe, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x02fbfbfb, 0x0af1f1f1,\n     0x1adadada, 0x33adadad, 0x60909090, 0xaaf2f2f2,\n     0xacffffff, 0xabffffff, 0xa9ffffff, 0xa8ffffff,\n     0xa6ffffff, 0xa4ffffff, 0xa2ffffff, 0xa1ffffff,\n     0x9fffffff, 0x9cffffff, 0x9affffff, 0x98ffffff,\n     0x96ffffff, 0x93ffffff, 0x92ffffff, 0x8fffffff,\n     0x8cffffff, 0x8affffff, 0x88ffffff, 0x85ffffff,\n     0x83ffffff, 0x80ffffff, 0x72f6f6f6, 0x24d1d1d1,\n     0x09e2e2e2, 0x05f5f5f5, 0x01fcfcfc, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x01fdfdfd, 0x05f7f7f7,\n     0x11e6e6e6, 0x26c6c6c6, 0x428f8f8f, 0x87bcbcbc,\n     0xa9ffffff, 0xa9ffffff, 0xa7ffffff, 0xa6ffffff,\n     0xa4ffffff, 0xa2ffffff, 0xa1ffffff, 0x9effffff,\n     0x9cffffff, 0x9affffff, 0x99ffffff, 0x96ffffff,\n     0x94ffffff, 0x92ffffff, 0x90ffffff, 0x8dffffff,\n     0x8bffffff, 0x88ffffff, 0x86ffffff, 0x83ffffff,\n     0x81ffffff, 0x7effffff, 0x7cffffff, 0x60ebebeb,\n     0x14d0d0d0, 0x08ebebeb, 0x03f9f9f9, 0x00fefefe,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x03fbfbfb,\n     0x0af0f0f0, 0x1bd7d7d7, 0x33ababab, 0x5d8d8d8d,\n     0xa2f1f1f1, 0xa6ffffff, 0xa4ffffff, 0xa3ffffff,\n     0xa1ffffff, 0xa0ffffff, 0x9effffff, 0x9cffffff,\n     0x9affffff, 0x99ffffff, 0x96ffffff, 0x94ffffff,\n     0x92ffffff, 0x90ffffff, 0x8dffffff, 0x8bffffff,\n     0x89ffffff, 0x87ffffff, 0x84ffffff, 0x82ffffff,\n     0x7fffffff, 0x7dffffff, 0x7bffffff, 0x78fefefe,\n     0x36d6d6d6, 0x0adcdcdc, 0x05f4f4f4, 0x01fcfcfc,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x01fdfdfd,\n     0x06f6f6f6, 0x12e3e3e3, 0x27c3c3c3, 0x428c8c8c,\n     0x82bababa, 0xa3ffffff, 0xa1ffffff, 0xa1ffffff,\n     0x9fffffff, 0x9dffffff, 0x9bffffff, 0x9affffff,\n     0x98ffffff, 0x96ffffff, 0x94ffffff, 0x92ffffff,\n     0x90ffffff, 0x8effffff, 0x8bffffff, 0x8affffff,\n     0x87ffffff, 0x85ffffff, 0x83ffffff, 0x80ffffff,\n     0x7effffff, 0x7cffffff, 0x79ffffff, 0x76ffffff,\n     0x59e8e8e8, 0x12d0d0d0, 0x07ededed, 0x02fafafa,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x03fafafa, 0x0bededed, 0x1bd5d5d5, 0x33a8a8a8,\n     0x5a898989, 0x9df0f0f0, 0xa0ffffff, 0x9effffff,\n     0x9cffffff, 0x9bffffff, 0x9affffff, 0x98ffffff,\n     0x96ffffff, 0x94ffffff, 0x92ffffff, 0x90ffffff,\n     0x8effffff, 0x8cffffff, 0x8affffff, 0x88ffffff,\n     0x85ffffff, 0x83ffffff, 0x81ffffff, 0x7effffff,\n     0x7cffffff, 0x7affffff, 0x77ffffff, 0x74ffffff,\n     0x6df7f7f7, 0x1fcacaca, 0x09e5e5e5, 0x03f8f8f8,\n     0x01fdfdfd, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x01fdfdfd, 0x06f5f5f5, 0x12e2e2e2, 0x26c2c2c2,\n     0x40898989, 0x7db5b5b5, 0x9dffffff, 0x9bffffff,\n     0x9affffff, 0x99ffffff, 0x97ffffff, 0x95ffffff,\n     0x93ffffff, 0x92ffffff, 0x90ffffff, 0x8effffff,\n     0x8cffffff, 0x8affffff, 0x88ffffff, 0x85ffffff,\n     0x83ffffff, 0x81ffffff, 0x7fffffff, 0x7cffffff,\n     0x7bffffff, 0x78ffffff, 0x75ffffff, 0x74ffffff,\n     0x71fdfdfd, 0x2dcdcdcd, 0x0adedede, 0x04f5f5f5,\n     0x01fdfdfd, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00fefefe, 0x03fafafa, 0x0bededed, 0x1bd3d3d3,\n     0x32a7a7a7, 0x56848484, 0x95ededed, 0x99ffffff,\n     0x98ffffff, 0x96ffffff, 0x94ffffff, 0x92ffffff,\n     0x92ffffff, 0x90ffffff, 0x8dffffff, 0x8bffffff,\n     0x8affffff, 0x88ffffff, 0x86ffffff, 0x83ffffff,\n     0x82ffffff, 0x7fffffff, 0x7dffffff, 0x7bffffff,\n     0x79ffffff, 0x76ffffff, 0x74ffffff, 0x72ffffff,\n     0x6ffefefe, 0x35cfcfcf, 0x0bd8d8d8, 0x05f3f3f3,\n     0x01fcfcfc, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x01fcfcfc, 0x06f5f5f5, 0x12e2e2e2,\n     0x25c1c1c1, 0x3e888888, 0x75acacac, 0x96ffffff,\n     0x95ffffff, 0x93ffffff, 0x92ffffff, 0x91ffffff,\n     0x8fffffff, 0x8dffffff, 0x8bffffff, 0x8affffff,\n     0x88ffffff, 0x85ffffff, 0x83ffffff, 0x82ffffff,\n     0x80ffffff, 0x7dffffff, 0x7cffffff, 0x79ffffff,\n     0x77ffffff, 0x74ffffff, 0x72ffffff, 0x70ffffff,\n     0x6dfefefe, 0x35cccccc, 0x0cd6d6d6, 0x05f2f2f2,\n     0x01fcfcfc, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x01fefefe, 0x04f9f9f9, 0x0bececec,\n     0x1ad3d3d3, 0x30a8a8a8, 0x517e7e7e, 0x8ce5e5e5,\n     0x92ffffff, 0x91ffffff, 0x90ffffff, 0x8effffff,\n     0x8cffffff, 0x8bffffff, 0x89ffffff, 0x87ffffff,\n     0x85ffffff, 0x83ffffff, 0x82ffffff, 0x80ffffff,\n     0x7dffffff, 0x7cffffff, 0x79ffffff, 0x77ffffff,\n     0x74ffffff, 0x73ffffff, 0x70ffffff, 0x6effffff,\n     0x6cfdfdfd, 0x2fc4c4c4, 0x0dd7d7d7, 0x05f2f2f2,\n     0x01fcfcfc, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x01fcfcfc, 0x06f5f5f5,\n     0x11e2e2e2, 0x24c1c1c1, 0x3b898989, 0x6b9f9f9f,\n     0x90ffffff, 0x8effffff, 0x8dffffff, 0x8bffffff,\n     0x8affffff, 0x88ffffff, 0x87ffffff, 0x85ffffff,\n     0x83ffffff, 0x81ffffff, 0x7fffffff, 0x7dffffff,\n     0x7cffffff, 0x7affffff, 0x77ffffff, 0x75ffffff,\n     0x73ffffff, 0x71ffffff, 0x6effffff, 0x6dffffff,\n     0x65f5f5f5, 0x23bbbbbb, 0x0cdbdbdb, 0x05f4f4f4,\n     0x01fcfcfc, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x01fefefe, 0x03f9f9f9,\n     0x0aededed, 0x18d4d4d4, 0x2eaaaaaa, 0x4a797979,\n     0x81d6d6d6, 0x8bffffff, 0x8bffffff, 0x89ffffff,\n     0x88ffffff, 0x86ffffff, 0x84ffffff, 0x83ffffff,\n     0x81ffffff, 0x7fffffff, 0x7dffffff, 0x7cffffff,\n     0x79ffffff, 0x77ffffff, 0x75ffffff, 0x73ffffff,\n     0x71ffffff, 0x6fffffff, 0x6dffffff, 0x6bffffff,\n     0x53dfdfdf, 0x19bababa, 0x0be2e2e2, 0x03f5f5f5,\n     0x01fdfdfd, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x01fcfcfc,\n     0x06f5f5f5, 0x0fe3e3e3, 0x21c2c2c2, 0x378e8e8e,\n     0x5e8b8b8b, 0x88fafafa, 0x88ffffff, 0x86ffffff,\n     0x85ffffff, 0x83ffffff, 0x82ffffff, 0x80ffffff,\n     0x7effffff, 0x7cffffff, 0x7bffffff, 0x79ffffff,\n     0x77ffffff, 0x75ffffff, 0x73ffffff, 0x71ffffff,\n     0x6fffffff, 0x6dffffff, 0x6bffffff, 0x68ffffff,\n     0x39bebebe, 0x12c3c3c3, 0x08e8e8e8, 0x02f8f8f8,\n     0x00fefefe, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x01fefefe,\n     0x03fafafa, 0x09eeeeee, 0x16d6d6d6, 0x2aafafaf,\n     0x42777777, 0x71b8b8b8, 0x85ffffff, 0x83ffffff,\n     0x83ffffff, 0x81ffffff, 0x7fffffff, 0x7effffff,\n     0x7cffffff, 0x7bffffff, 0x79ffffff, 0x77ffffff,\n     0x74ffffff, 0x73ffffff, 0x71ffffff, 0x6fffffff,\n     0x6dffffff, 0x6bffffff, 0x69ffffff, 0x57e0e0e0,\n     0x20ababab, 0x0fd5d5d5, 0x06efefef, 0x02fbfbfb,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x01fdfdfd, 0x05f6f6f6, 0x0ee5e5e5, 0x1dc7c7c7,\n     0x32999999, 0x4e757575, 0x7ce0e0e0, 0x81ffffff,\n     0x80ffffff, 0x7effffff, 0x7dffffff, 0x7cffffff,\n     0x7affffff, 0x78ffffff, 0x76ffffff, 0x74ffffff,\n     0x73ffffff, 0x71ffffff, 0x6fffffff, 0x6dffffff,\n     0x6bffffff, 0x69ffffff, 0x62f4f4f4, 0x32a9a9a9,\n     0x16bdbdbd, 0x0be3e3e3, 0x04f5f5f5, 0x01fcfcfc,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x02fafafa, 0x07f1f1f1, 0x12dcdcdc,\n     0x23bababa, 0x37878787, 0x56808080, 0x7be9e9e9,\n     0x7dffffff, 0x7cffffff, 0x7bffffff, 0x79ffffff,\n     0x77ffffff, 0x75ffffff, 0x74ffffff, 0x72ffffff,\n     0x70ffffff, 0x6effffff, 0x6dffffff, 0x6bffffff,\n     0x69ffffff, 0x64f6f6f6, 0x3dacacac, 0x1cababab,\n     0x0fd6d6d6, 0x06eeeeee, 0x02f9f9f9, 0x00fefefe,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x01fdfdfd, 0x04f8f8f8, 0x0aebebeb,\n     0x16d3d3d3, 0x27b1b1b1, 0x397e7e7e, 0x54777777,\n     0x72d2d2d2, 0x7affffff, 0x78ffffff, 0x76ffffff,\n     0x74ffffff, 0x74ffffff, 0x72ffffff, 0x70ffffff,\n     0x6effffff, 0x6dffffff, 0x6bffffff, 0x68ffffff,\n     0x5ee3e3e3, 0x3d9e9e9e, 0x1fa1a1a1, 0x13cdcdcd,\n     0x09e7e7e7, 0x03f6f6f6, 0x01fdfdfd, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x01fcfcfc, 0x05f5f5f5,\n     0x0ce6e6e6, 0x18cdcdcd, 0x28adadad, 0x37808080,\n     0x49666666, 0x629b9b9b, 0x70dfdfdf, 0x74fefefe,\n     0x73ffffff, 0x71ffffff, 0x6fffffff, 0x6dffffff,\n     0x6cffffff, 0x6affffff, 0x63e6e6e6, 0x4fb1b1b1,\n     0x34898989, 0x219f9f9f, 0x14c8c8c8, 0x0ae3e3e3,\n     0x04f3f3f3, 0x01fbfbfb, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00fefefe, 0x02fafafa,\n     0x06f3f3f3, 0x0de4e4e4, 0x17cecece, 0x24b3b3b3,\n     0x31919191, 0x3d6d6d6d, 0x49666666, 0x56838383,\n     0x5ea4a4a4, 0x61bababa, 0x61c2c2c2, 0x5ebdbdbd,\n     0x57acacac, 0x4a929292, 0x397d7d7d, 0x2a888888,\n     0x1eababab, 0x14cbcbcb, 0x0be1e1e1, 0x05f1f1f1,\n     0x02fafafa, 0x00fefefe, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00fefefe,\n     0x02fafafa, 0x06f3f3f3, 0x0be6e6e6, 0x13d5d5d5,\n     0x1dc0c0c0, 0x26a9a9a9, 0x2f929292, 0x347b7b7b,\n     0x386c6c6c, 0x3a6b6b6b, 0x3a6e6e6e, 0x36717171,\n     0x30787878, 0x298c8c8c, 0x21a5a5a5, 0x19bebebe,\n     0x11d3d3d3, 0x0ae5e5e5, 0x05f2f2f2, 0x02fafafa,\n     0x00fefefe, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00fefefe, 0x02fbfbfb, 0x04f5f5f5, 0x08ededed,\n     0x0de0e0e0, 0x14d2d2d2, 0x19c4c4c4, 0x1eb8b8b8,\n     0x22afafaf, 0x23a9a9a9, 0x22a9a9a9, 0x20aeaeae,\n     0x1cb8b8b8, 0x17c4c4c4, 0x11d2d2d2, 0x0ce0e0e0,\n     0x07ececec, 0x04f5f5f5, 0x01fbfbfb, 0x00fefefe,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00fefefe, 0x01fcfcfc, 0x03f9f9f9,\n     0x05f4f4f4, 0x08ededed, 0x0be5e5e5, 0x0ededede,\n     0x0fd9d9d9, 0x11d6d6d6, 0x10d6d6d6, 0x0fd9d9d9,\n     0x0ddedede, 0x09e5e5e5, 0x07ededed, 0x04f4f4f4,\n     0x02f9f9f9, 0x01fcfcfc, 0x00fefefe, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00fefefe,\n     0x01fcfcfc, 0x02fafafa, 0x03f7f7f7, 0x04f4f4f4,\n     0x05f2f2f2, 0x06f1f1f1, 0x06f1f1f1, 0x05f2f2f2,\n     0x04f4f4f4, 0x03f7f7f7, 0x02fafafa, 0x01fcfcfc,\n     0x00fdfdfd, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00fefefe, 0x01fdfdfd, 0x01fcfcfc,\n     0x01fcfcfc, 0x01fcfcfc, 0x01fcfcfc, 0x01fcfcfc,\n     0x01fcfcfc, 0x01fdfdfd, 0x00fefefe, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,\n};\n"
  },
  {
    "path": "src/core/fluxcomp.py",
    "content": "#!/bin/env python3\n\nlicense = \"\"\"\n/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\"\"\"\n\nimport argparse\n\nparser = argparse.ArgumentParser(description=\"Flux Compiler Tool\")\n\nparser.add_argument(\"filename\")\nparser.add_argument(\"-c\", \"--generate-c\", action=\"store_true\", required=True, help=\"Generate C code\")\nparser.add_argument(\"-i\", \"--identity\", action=\"store_true\", help=\"Generate caller identity tracking code\")\nparser.add_argument(\"--object-ptrs\", action=\"store_true\", required=True, help=\"Return object pointers rather than IDs\")\nparser.add_argument(\"--call-mode\", action=\"store_true\", required=True, help=\"Use call mode function to determine call mode\")\nparser.add_argument(\"-p\", \"--include-prefix\", required=True, help=\"Override standard include prefix for includes\")\nparser.add_argument(\"--static-args-bytes\", default=1000, help=\"Override standard limit (1000) for stack based arguments\")\nparser.add_argument(\"--dispatch-error-abort\", action=\"store_true\", help=\"Abort execution when object lookups fail\")\nparser.add_argument(\"-o\", dest=\"output_dir\", default=\"\", help=\"Write to output directory\")\n\n# --------------------------------------------------------------------------------------------------------------------------\n\nclass Entity:\n    def __init__(self):\n        self.position = 0\n        self.entities = []\n\nclass Interface(Entity):\n    def SetProperty(self, name, value):\n        if name == \"name\":\n            self.name = value\n        elif name == \"object\":\n            self.object = value\n            self.dispatch = value\n        elif name == \"dispatch\":\n            self.dispatch = value\n\nclass Method(Entity):\n    sync = True\n    queue = False\n\n    def SetProperty(self, name, value):\n        if name == \"name\":\n            self.name = value\n        elif name == \"async\":\n            self.sync = not value == \"yes\"\n        elif name == \"queue\":\n            self.queue = value == \"yes\"\n\n    def ArgumentsAsParamDecl(self):\n        result = \"\"\n        first = True\n\n        for arg in self.entities:\n            result += \"\" if first else \",\\n\"\n\n            if arg.type == \"struct\":\n                if arg.direction == \"input\":\n                    result += f\"                    {'const ' + arg.type_name:<40}  *{arg.name}\"\n                else:\n                    result += f\"                    {arg.type_name:<40}  *ret_{arg.name}\"\n            elif arg.type == \"enum\" or arg.type == \"int\":\n                if arg.direction == \"input\":\n                    if arg.array:\n                        result += f\"                    {'const ' + arg.type_name:<40}  *{arg.name}\"\n                    else:\n                        result += f\"                    {arg.type_name:<40}   {arg.name}\"\n                else:\n                    result += f\"                    {arg.type_name:<40}  *ret_{arg.name}\"\n            else:\n                if arg.direction == \"input\":\n                    result += f\"                    {arg.type_name:<40}  *{arg.name}\"\n                else:\n                    result += f\"                    {arg.type_name:<40} **ret_{arg.name}\"\n\n            if first:\n                first = False\n\n        return result\n\n    def ArgumentsAsMemberDecl(self):\n        result = \"\"\n\n        for arg in self.entities:\n            if arg.array:\n                continue\n\n            if arg.direction == \"input\":\n                if arg.optional:\n                    result += f\"    bool                                       {arg.name}_set;\\n\"\n\n                if arg.type == \"struct\" or arg.type == \"enum\" or arg.type == \"int\":\n                    result += f\"    {arg.type_name:<40}   {arg.name};\\n\"\n                else:\n                    result += f\"    u32                                        {arg.name}_id;\\n\"\n\n        for arg in self.entities:\n            if not arg.array:\n                continue\n\n            if arg.direction == \"input\":\n                if arg.optional:\n                    result += f\"    bool                                       {arg.name}_set;\\n\"\n\n                result += f\"    /* '{arg.count}' {arg.type_name} follow ({arg.name}) */\\n\"\n\n        return result\n\n    def ArgumentsOutputAsMemberDecl(self):\n        result = \"    DFBResult                                  result;\\n\"\n\n        for arg in self.entities:\n            if arg.array:\n                continue\n\n            if arg.direction == \"output\":\n                if arg.type == \"struct\" or arg.type == \"enum\" or arg.type == \"int\":\n                    result += f\"    {arg.type_name:<40}   {arg.name};\\n\"\n                else:\n                    result += f\"    u32                                        {arg.name}_id;\\n\" \\\n                              f\"    void*                                      {arg.name}_ptr;\\n\"\n\n        for arg in self.entities:\n            if not arg.array:\n                continue\n\n            if arg.direction == \"output\":\n                result += f\"    /* '{arg.count}' {arg.type_name} follow ({arg.name}) */\\n\"\n\n        return result\n\n    def ArgumentsAsMemberParams(self):\n        result = \"\"\n        first = True\n        second_output_array = False\n\n        for arg in self.entities:\n            if first:\n                first = False\n            else:\n                result += \", \"\n\n            if arg.direction == \"input\":\n                if arg.optional:\n                    result += f\"args->{arg.name}_set ? \"\n\n                if arg.array:\n                    result += f\"({arg.type_name}*) ((char*)(args + 1){arg.offset(self, True, False)})\"\n                else:\n                    if arg.type == \"struct\":\n                        result += f\"&args->{arg.name}\"\n                    elif arg.type == \"enum\" or arg.type == \"int\":\n                        result += f\"args->{arg.name}\"\n                    else:\n                        result += f\"{arg.name}\"\n\n                if arg.optional:\n                    result += \" : NULL\"\n\n            if arg.direction == \"output\":\n                if arg.array:\n                    if second_output_array:\n                        result += f\"tmp_{arg.name}\"\n                    else:\n                        result += f\"({arg.type_name}*) ((char*)(return_args + 1){arg.offset(self, True, True)})\"\n                        second_output_array = True\n                else:\n                    if arg.type == \"struct\" or arg.type == \"enum\" or arg.type == \"int\":\n                        result += f\"&return_args->{arg.name}\"\n                    else:\n                        result += f\"&{arg.name}\"\n\n        return result\n\n    def ArgumentsInputAssignments(self):\n        result = \"\"\n\n        for arg in self.entities:\n            if arg.array:\n                continue\n\n            if arg.direction == \"input\":\n                if arg.optional:\n                    result += f\"    if ({arg.name}) {{\\n\"\n\n                    if arg.type == \"struct\":\n                        result += f\"        args->{arg.name} = *{arg.name};\\n\"\n                    elif arg.type == \"enum\" or arg.type == \"int\":\n                        result += f\"        args->{arg.name} = {arg.name};\\n\"\n                    else:\n                        result += f\"        args->{arg.name}_id = {arg.type_name}_GetID( {arg.name} );\\n\"\n\n                    result += f\"        args->{arg.name}_set = true;\\n\" \\\n                               \"    }\\n\" \\\n                               \"    else\\n\" \\\n                              f\"        args->{arg.name}_set = false;\\n\"\n                else:\n                    if arg.type == \"struct\":\n                        result += f\"    args->{arg.name} = *{arg.name};\\n\"\n                    elif arg.type == \"enum\" or arg.type == \"int\":\n                        result += f\"    args->{arg.name} = {arg.name};\\n\"\n                    else:\n                        result += f\"    args->{arg.name}_id = {arg.type_name}_GetID( {arg.name} );\\n\"\n\n        for arg in self.entities:\n            if not arg.array:\n                continue\n\n            if arg.direction == \"input\":\n                if arg.optional:\n                    result += f\"  if ({arg.name}) {{\\n\"\n\n                result +=  \"    direct_memcpy( (char*) (args + 1)\" \\\n                          f\"{arg.offset(self, False, False)}, {arg.name}, {arg.size(False)} );\\n\"\n\n                if arg.optional:\n                    result += f\"    args->{arg.name}_set = true;\\n\" \\\n                               \"  }\\n\" \\\n                               \"  else {\\n\" \\\n                              f\"    args->{arg.name}_set = false;\\n\" \\\n                              f\"    {arg.name} = 0;\\n\" \\\n                               \"  }\\n\"\n\n        return result\n\n    def ArgumentsOutputAssignments(self):\n        result = \"\"\n\n        for arg in self.entities:\n            if arg.array:\n                continue\n\n            if arg.direction == \"output\":\n                if arg.type == \"struct\" or arg.type == \"enum\" or arg.type == \"int\":\n                    if arg.optional:\n                        result += f\"    if (ret_{arg.name})\\n\" \\\n                                  f\"        *ret_{arg.name} = return_args->{arg.name};\\n\"\n                    else:\n                        result += f\"    *ret_{arg.name} = return_args->{arg.name};\\n\"\n\n        for arg in self.entities:\n            if not arg.array:\n                continue\n\n            if arg.direction == \"output\":\n                result += f\"    direct_memcpy( ret_{arg.name}, (char*) (return_args + 1)\" \\\n                          f\"{arg.offset(self, False, True)}, {arg.sizeReturn(self)} );\\n\"\n\n        return result\n\n    def ArgumentsAssertions(self):\n        result = \"\"\n\n        for arg in self.entities:\n            if (arg.type == \"struct\" or arg.type == \"object\") and not arg.optional :\n                result += \"    D_ASSERT( \" + (arg.name if arg.direction == \"input\" else f\"ret_{arg.name}\") + \" != NULL );\\n\"\n\n        return result\n\n    def ArgumentsOutputObjectDecl(self):\n        result = \"\"\n\n        for arg in self.entities:\n            if arg.direction == \"output\" and arg.type == \"object\":\n                result += f\"    {arg.type_name} *{arg.name} = NULL;\\n\"\n\n        return result\n\n    def ArgumentsOutputTmpDecl(self):\n        result = \"\"\n        second = False\n\n        for arg in self.entities:\n            if arg.direction == \"output\" and arg.array:\n                if second:\n                    result += f\"    {arg.type_name}  tmp_{arg.name}[{arg.max}];\\n\"\n                else:\n                    second = True\n\n        return result\n\n    def ArgumentsInputObjectDecl(self):\n        result = \"\"\n\n        for arg in self.entities:\n            if arg.direction == \"input\" and arg.type == \"object\":\n                result += f\"    {arg.type_name} *{arg.name} = NULL;\\n\"\n\n        return result\n\n    def ArgumentsOutputObjectCatch(self):\n        result = \"\"\n\n        for arg in self.entities:\n            if arg.direction == \"output\" and arg.type == \"object\":\n                result += f\"    ret = (DFBResult) {arg.type_name}_Catch\" \\\n                          f\"( core_dfb, return_args->{arg.name}_ptr, &{arg.name} );\\n\" \\\n                           \"    if (ret) {\\n\" \\\n                           \"         D_DERROR( ret, \\\"%s: \" \\\n                          f\"Catching {arg.name} by ID %u failed!\\\\n\\\", __FUNCTION__, return_args->{arg.name}_id );\\n\" \\\n                           \"         goto out;\\n\" \\\n                           \"    }\\n\" \\\n                           \"\\n\" \\\n                           \"    *\" + (arg.name if arg.direction == \"input\" else f\"ret_{arg.name}\") + f\" = {arg.name};\\n\" \\\n                           \"\\n\"\n\n        return result\n\n    def ArgumentsOutputObjectThrow(self):\n        result = \"\"\n\n        for arg in self.entities:\n            if arg.type == \"object\" and arg.direction == \"output\":\n                result += f\"                {arg.type_name}_Throw\" \\\n                          f\"( {arg.name}, caller, &return_args->{arg.name}_id );\\n\" \\\n                          f\"                return_args->{arg.name}_ptr = (void*) {arg.name};\\n\"\n\n        return result\n\n    def ArgumentsOutputTmpReturn(self):\n        result = \"\"\n        second_output_array = False\n\n        for arg in self.entities:\n            if arg.direction == \"output\" and arg.array:\n                if second_output_array:\n                    result += f\"                direct_memcpy( (char*) ((char*)(return_args + 1)\" \\\n                              f\"{arg.offset(self, True, True)}), tmp_{arg.name}, return_args->{arg.name}_size );\\n\"\n                else:\n                    second_output_array = True\n\n        return result\n\n    def ArgumentsInputObjectLookup(self):\n        result = \"\"\n\n        for arg in self.entities:\n            if arg.direction == \"input\" and arg.type == \"object\":\n                if arg.optional:\n                    result += f\"            if (args->{arg.name}_set) {{\\n\" \\\n                              f\"                ret = (DFBResult) {arg.type_name}_Lookup\" \\\n                              f\"( core_dfb, args->{arg.name}_id, caller, &{arg.name} );\\n\" \\\n                               \"                if (ret) {\\n\" \\\n                              f\"                     D_DERROR( ret, \\\"%s({self.name}): \" \\\n                              f\"Looking up {arg.name} by ID %u failed!\\\\n\\\", __FUNCTION__, args->{arg.name}_id );\\n\" + \\\n                              (\"                     return_args->result = ret;\\n\" if self.sync else \"\") + \\\n                              (\"                     D_BREAK( \\\"could not lookup object\\\" );\\n\" \\\n                               if config.dispatch_error_abort  else \"\") + \\\n                               \"                     return ret;\\n\" \\\n                               \"                }\\n\"\n                else:\n                    result += f\"            ret = (DFBResult) {arg.type_name}_Lookup\" \\\n                              f\"( core_dfb, args->{arg.name}_id, caller, &{arg.name} );\\n\" \\\n                               \"            if (ret) {\\n\" \\\n                              f\"                 D_DERROR( ret, \\\"%s({self.name}): \" \\\n                              f\"Looking up {arg.name} by ID %u failed!\\\\n\\\", __FUNCTION__, args->{arg.name}_id );\\n\" + \\\n                              (\"                 return_args->result = ret;\\n\" if self.sync else \"\") + \\\n                              (\"                 D_BREAK( \\\"could not lookup object\\\" );\\n\" \\\n                               if config.dispatch_error_abort  else \"\") + \\\n                               \"                 return ret;\\n\" \\\n\n                result += \"            }\\n\" \\\n                          \"\\n\"\n\n        return result\n\n    def ArgumentsInputDebug(self):\n        result = \"\"\n\n        for arg in self.entities:\n            if arg.array:\n                continue\n\n            if arg.optional:\n                result += f\"  if (args->{arg.name}_set)\\n\"\n\n            if arg.type == \"struct\":\n                result += f\"         ;    // TODO: {arg.type_name}_debug args->{arg.name};\\n\"\n            else:\n                result += f\"            D_DEBUG_AT( DirectFB_{face.object}, \\\"  -> {arg.name} = \"\n                if arg.type == \"object\":\n                    result += f\"%u\\\\n\\\", args->{arg.name}_id );\\n\"\n                else:\n                    result += f\"%{arg.formatCharacter()}\\\\n\\\", {arg.typeCast()}args->{arg.name} );\\n\"\n\n        return result\n\n    def ArgumentsInputObjectUnref(self):\n        result = \"\"\n\n        for arg in self.entities:\n            if arg.direction == \"input\" and arg.type == \"object\":\n               result += f\"            if ({arg.name})\\n\" \\\n                         f\"                {arg.type_name}_Unref( {arg.name} );\\n\" \\\n                          \"\\n\"\n\n        return result\n\n    def ArgumentsNames(self):\n        result = \"\"\n\n        for index, arg in enumerate(self.entities):\n            last = index == len(self.entities) - 1\n\n            result += arg.name if arg.direction == \"input\" else \"ret_\" + arg.name\n\n            if not last:\n                result += \", \"\n\n        return result\n\n    def ArgumentsSize(self, output):\n        result = \"sizeof(\"\n\n        if output:\n            result += f\"{face.object}{self.name}Return)\"\n        else:\n            result += f\"{face.object}{self.name})\"\n\n        for arg in self.entities:\n            if not arg.array:\n                continue\n\n            if output:\n                if arg.direction == \"output\":\n                    result += f\" + {arg.sizeMax()}\"\n            else:\n                if arg.direction == \"input\":\n                    result += f\" + {arg.size(False)}\"\n\n        return result\n\n    def ArgumentsSizeReturn(self):\n        result = f\"sizeof({face.object}{self.name}Return)\"\n\n        for arg in self.entities:\n            if not arg.array:\n                continue\n\n            if arg.direction == \"output\":\n                result += f\" + {arg.sizeReturn(self)}\"\n\n        return result\n\nclass Arg(Entity):\n    array = False\n    optional = False\n\n    def SetProperty(self, name, value):\n        if name == \"name\":\n            self.name = value\n        elif name == \"direction\":\n            self.direction = value\n        elif name == \"type\":\n            self.type = value\n        elif name == \"typename\":\n            self.type_name = value\n        elif name == \"optional\":\n            self.optional = value == \"yes\"\n        elif name == \"count\":\n            self.array = True\n            self.count = value\n        elif name == \"max\":\n            self.max = value\n\n    def formatCharacter(self):\n        if self.type == \"int\":\n            if self.type_name == \"u32\":\n                return \"u\"\n            elif self.type_name == \"s32\":\n                return \"d\"\n            elif self.type_name == \"u64\":\n                return \"llu\"\n            elif self.type_name == \"s64\":\n                return \"lld\"\n            else:\n                return \"p\"\n        else:\n            return \"x\"\n\n    def typeCast(self):\n        if self.type == \"int\":\n            if self.type_name == \"u64\":\n                return \"(unsigned long long) \"\n            elif self.type_name == \"s64\":\n                return \"(long long) \"\n\n        return \"\"\n\n    def size(self, use_args):\n        if use_args:\n            return f\"args->{self.count} * sizeof({self.type_name})\"\n        else:\n            return f\"{self.count} * sizeof({self.type_name})\"\n\n    def sizeMax(self):\n        return f\"{self.max} * sizeof({self.type_name})\"\n\n    def sizeReturn(self, method):\n        if self.array:\n            for arg in method.entities:\n                if arg.direction == \"input\":\n                    return f\"args->{self.count} * sizeof({self.type_name})\"\n                else:\n                    return f\"return_args->{self.count} * sizeof({self.type_name})\"\n\n    def offset(self, method, use_args, output):\n        result = \"\"\n\n        for arg in method.entities:\n            if not arg.array:\n                continue\n\n            if arg == self:\n                break\n\n            if output:\n                result += f\" + return_args->{arg.size(False)}\"\n            else:\n                result += f\" + {arg.size(use_args)}\"\n\n        return result\n\n# --------------------------------------------------------------------------------------------------------------------------\n\nface = Interface()\n\ndef GetEntities(position, out_vector):\n    with open(config.filename, 'r') as file:\n        file.seek(position)\n\n        content = file.read()\n\n        index = 0\n        level = 0\n        comment = False\n        quote = False\n        name = \"\"\n        names = {}\n\n        for char in content:\n            index += 1\n\n            if comment:\n                if char == '\\n':\n                    comment = False\n            elif quote:\n                if char == '\"':\n                    quote = False\n                else:\n                    name += char\n            else:\n                if char == '\"':\n                    quote = True\n                elif char == '#':\n                    comment = True\n                elif char in ('.', '-', '_', *'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'):\n                    name += char\n                else:\n                    if name:\n                        if level in names and names[level]:\n                            if level == 1:\n                                entity.SetProperty(names[level], name)\n                                name = \"\"\n\n                        names[level] = name\n                        name = \"\"\n\n                    if char == '{':\n                        if level == 0:\n                            if names[level] == \"interface\":\n                                entity = face\n                                entity.position = position + index\n                            elif names[level] == \"method\":\n                                entity = Method()\n                                entity.position = position + index\n                            else:\n                                entity = Arg()\n                                entity.position = position + index\n\n                        names[level] = \"\"\n                        level += 1\n\n                    elif char == '}':\n                        level -= 1\n\n                        if level == 0:\n                            GetEntities(entity.position, entity.entities)\n                            out_vector.append(entity)\n\n                        if level < 0:\n                            break\n\ndef GenerateHeader():\n    with open((config.output_dir + \"/\" if config.output_dir else \"\") + face.object + \".h\", \"w\") as file:\n        file.write( \"/*\\n\"\n                    \" * This file was automatically generated by fluxcomp; DO NOT EDIT!\\n\"\n                    \" */\\n\"\n                   f\"{license}\"\n                    \"\\n\")\n\n        # Start of header guard and includes\n\n        file.write(f\"#ifndef ___{face.object}__H___\\n\"\n                   f\"#define ___{face.object}__H___\\n\"\n                    \"\\n\"\n                   f\"#include <{config.include_prefix}/{face.object}_includes.h>\\n\"\n                    \"\\n\"\n                    \"/***************************************************************************************************\\n\"\n                   f\" * {face.object}\\n\"\n                    \" */\\n\"\n                    \"\\n\"\n                    \"#ifdef __cplusplus\\n\"\n                    \"#include <core/Interface.h>\\n\"\n                    \"\\n\"\n                    \"extern \\\"C\\\" {\\n\"\n                    \"#endif\\n\"\n                    \"\\n\"\n                    \"\\n\")\n\n        # C Wrappers\n\n        for method in face.entities:\n            if isinstance(method, Method):\n                file.write(f\"DFBResult {face.object}_{method.name}(\\n\"\n                           f\"                    {face.object:<40}  *obj\" +\n                           (\",\\n\" if method.entities else \"\\n\") +\n                           f\"{method.ArgumentsAsParamDecl()});\\n\"\n                            \"\\n\")\n\n        file.write( \"\\n\"\n                   f\"void {face.object}_Init_Dispatch(\\n\"\n                    \"                    CoreDFB              *core,\\n\"\n                   f\"                    {face.dispatch:<20} *obj,\\n\"\n                    \"                    FusionCall           *call\\n\"\n                    \");\\n\"\n                    \"\\n\"\n                   f\"void  {face.object}_Deinit_Dispatch(\\n\"\n                    \"                    FusionCall           *call\\n\"\n                    \");\\n\"\n                    \"\\n\"\n                    \"\\n\"\n                    \"#ifdef __cplusplus\\n\"\n                    \"}\\n\"\n                    \"#endif\\n\"\n                    \"\\n\"\n                    \"\\n\"\n                    \"\\n\"\n                    \"\\n\")\n\n        # Method IDs\n\n        file.write( \"/*\\n\"\n                   f\" * {face.object} Calls\\n\"\n                    \" */\\n\"\n                    \"typedef enum {\\n\")\n\n        index = 1\n        for method in face.entities:\n            if isinstance(method, Method):\n                file.write(f\"    _{face.object}_{method.name} = {index},\\n\")\n                index += 1\n\n        file.write(f\"}} {face.object}Call;\\n\"\n                    \"\\n\")\n\n        # Method Argument Structures\n\n        for method in face.entities:\n            if isinstance(method, Method):\n                file.write( \"/*\\n\"\n                           f\" * {face.object}_{method.name}\\n\"\n                            \" */\\n\"\n                            \"typedef struct {\\n\"\n                           f\"{method.ArgumentsAsMemberDecl()}\"\n                           f\"}} {face.object}{method.name};\\n\"\n                            \"\\n\"\n                            \"typedef struct {\\n\"\n                           f\"{method.ArgumentsOutputAsMemberDecl()}\"\n                           f\"}} {face.object}{method.name}Return;\\n\"\n                            \"\\n\"\n                            \"\\n\")\n\n        # Real Interface\n\n        for method in face.entities:\n            if isinstance(method, Method):\n                file.write(f\"DFBResult {face.name}_Real__{method.name}( {face.dispatch} *obj\" +\n                           (\",\\n\" if method.ArgumentsAsParamDecl() else \"\\n\") +\n                           f\"{method.ArgumentsAsParamDecl()} );\\n\"\n                            \"\\n\")\n\n        # Requestor Interface\n\n        for method in face.entities:\n            if isinstance(method, Method):\n                file.write(f\"DFBResult {face.name}_Requestor__{method.name}( {face.object} *obj\" +\n                           (\",\\n\" if method.ArgumentsAsParamDecl() else \"\\n\") +\n                           f\"{method.ArgumentsAsParamDecl()} );\\n\"\n                           \"\\n\")\n\n        # Dispatch Function\n\n        file.write( \"\\n\"\n                   f\"DFBResult {face.object}Dispatch__Dispatch( {face.dispatch} *obj,\\n\"\n                    \"                    FusionID      caller,\\n\"\n                    \"                    int           method,\\n\"\n                    \"                    void         *ptr,\\n\"\n                    \"                    unsigned int  length,\\n\"\n                    \"                    void         *ret_ptr,\\n\"\n                    \"                    unsigned int  ret_size,\\n\"\n                    \"                    unsigned int *ret_length );\\n\"\n                    \"\\n\")\n\n        # End of header guard\n\n        file.write( \"\\n\"\n                    \"#endif\\n\")\n\ndef GenerateSource():\n    direct = True\n    if face.object != face.dispatch:\n        direct = False\n\n    with open((config.output_dir + \"/\" if config.output_dir else \"\") + face.object + \".c\", \"w\") as file:\n        file.write( \"/*\\n\"\n                    \" * This file was automatically generated by fluxcomp; DO NOT EDIT!\\n\"\n                    \" */\\n\"\n                   f\"{license}\"\n                    \"\\n\")\n\n        # includes\n\n        file.write( \"#include <config.h>\\n\"\n                    \"\\n\"\n                   f\"#include \\\"{face.object}.h\\\"\\n\"\n                    \"\\n\"\n                    \"#include <directfb_util.h>\\n\"\n                    \"\\n\"\n                    \"#include <direct/debug.h>\\n\"\n                    \"#include <direct/mem.h>\\n\"\n                    \"#include <direct/memcpy.h>\\n\"\n                    \"#include <direct/messages.h>\\n\"\n                    \"\\n\"\n                    \"#include <fusion/conf.h>\\n\"\n                    \"\\n\"\n                    \"#include <core/core.h>\\n\"\n                    \"\\n\"\n                    \"#include <core/CoreDFB_CallMode.h>\\n\"\n                    \"\\n\"\n                   f\"D_DEBUG_DOMAIN( DirectFB_{face.object}, \\\"DirectFB/{face.object}\\\", \\\"DirectFB {face.object}\\\" );\\n\"\n                    \"\\n\"\n                    \"/**************************************************************************************************/\\n\"\n                    \"\\n\")\n\n        # C Wrappers\n\n        for method in face.entities:\n            if isinstance(method, Method):\n                file.write( \"DFBResult\\n\"\n                           f\"{face.object}_{method.name}(\\n\"\n                           f\"                    {face.object:<40}  *obj\" +\n                           (\",\\n\" if method.entities else \"\\n\") +\n                           f\"{method.ArgumentsAsParamDecl()}\\n\"\n                            \")\\n\"\n                            \"{\\n\"\n                            \"    DFBResult ret;\\n\"\n                            \"\\n\"\n                            \"    switch (CoreDFB_CallMode( core_dfb )) {\\n\"\n                            \"        case COREDFB_CALL_DIRECT:\")\n\n                if direct:\n                    file.write( \"{\\n\"\n                                \"            Core_PushCalling();\\n\"\n                               f\"            ret = {face.name}_Real__{method.name}( obj\" +\n                               (\", \" if method.ArgumentsAsParamDecl() else \"\") + f\"{method.ArgumentsNames()} );\\n\"\n                                \"            Core_PopCalling();\\n\"\n                                \"\\n\"\n                                \"            return ret;\\n\"\n                                \"        }\\n\")\n\n                file.write( \"\\n        case COREDFB_CALL_INDIRECT: {\\n\"\n                            \"            Core_PushCalling();\\n\"\n                           f\"            ret = {face.name}_Requestor__{method.name}( obj\" +\n                           (\", \" if method.ArgumentsAsParamDecl() else \"\") + f\"{method.ArgumentsNames()} );\\n\"\n                            \"            Core_PopCalling();\\n\"\n                            \"\\n\"\n                            \"            return ret;\\n\"\n                            \"        }\\n\"\n                            \"        case COREDFB_CALL_DENY:\\n\"\n                            \"            return DFB_DEAD;\\n\"\n                            \"    }\\n\"\n                            \"\\n\"\n                            \"    return DFB_UNIMPLEMENTED;\\n\"\n                            \"}\\n\"\n                            \"\\n\")\n\n        file.write( \"/**************************************************************************************************/\\n\"\n                    \"\\n\"\n                    \"static FusionCallHandlerResult\\n\"\n                   f\"{face.object}_Dispatch( int           caller,   /* fusion id of the caller */\\n\"\n                    \"                     int           call_arg, /* optional call parameter */\\n\"\n                    \"                     void         *ptr, /* optional call parameter */\\n\"\n                    \"                     unsigned int  length,\\n\"\n                    \"                     void         *ctx,      /* optional handler context */\\n\"\n                    \"                     unsigned int  serial,\\n\"\n                    \"                     void         *ret_ptr,\\n\"\n                    \"                     unsigned int  ret_size,\\n\"\n                    \"                     unsigned int *ret_length )\\n\"\n                    \"{\\n\"\n                   f\"    {face.dispatch} *obj = ({face.dispatch}*) ctx;\\n\"\n                   f\"    {face.object}Dispatch__Dispatch\"\n                    \"( obj, caller, call_arg, ptr, length, ret_ptr, ret_size, ret_length );\\n\"\n                    \"\\n\"\n                    \"    return FCHR_RETURN;\\n\"\n                    \"}\\n\"\n                    \"\\n\"\n                   f\"void {face.object}_Init_Dispatch(\\n\"\n                    \"                    CoreDFB              *core,\\n\"\n                   f\"                    {face.dispatch:<20} *obj,\\n\"\n                    \"                    FusionCall           *call\\n\"\n                    \")\\n\"\n                    \"{\\n\"\n                   f\"    fusion_call_init3( call, {face.object}_Dispatch, obj, core->world );\\n\"\n                    \"}\\n\"\n                    \"\\n\"\n                   f\"void  {face.object}_Deinit_Dispatch(\\n\"\n                    \"                    FusionCall           *call\\n\"\n                    \")\\n\"\n                    \"{\\n\"\n                    \"     fusion_call_destroy( call );\\n\"\n                    \"}\\n\"\n                    \"\\n\"\n                    \"/**************************************************************************************************/\\n\"\n                    \"\\n\")\n\n        # Requestor Methods\n\n        file.write( \"static __inline__ void *args_alloc( void *static_buffer, size_t size )\\n\"\n                    \"{\\n\"\n                    \"    void *buffer = static_buffer;\\n\"\n                    \"\\n\"\n                   f\"    if (size > {config.static_args_bytes}) {{\\n\"\n                    \"        buffer = D_MALLOC( size );\\n\"\n                    \"        if (!buffer)\\n\"\n                    \"            return NULL;\\n\"\n                    \"    }\\n\"\n                    \"\\n\"\n                    \"    return buffer;\\n\"\n                    \"}\\n\"\n                    \"\\n\"\n                    \"static __inline__ void args_free( void *static_buffer, void *buffer )\\n\"\n                    \"{\\n\"\n                    \"    if (buffer != static_buffer)\\n\"\n                    \"        D_FREE( buffer );\\n\"\n                    \"}\\n\"\n                    \"\\n\")\n\n        for method in face.entities:\n            if isinstance(method, Method):\n                file.write( \"\\n\"\n                            \"DFBResult\\n\"\n                           f\"{face.name}_Requestor__{method.name}( {face.object} *obj\" +\n                           (\",\\n\" if method.ArgumentsAsParamDecl() else \"\\n\") +\n                           f\"{method.ArgumentsAsParamDecl()}\\n\"\n                            \")\\n\"\n                            \"{\\n\"\n                            \"    DFBResult           ret = DFB_OK;\\n\"\n                           f\"{method.ArgumentsOutputObjectDecl()}\"\n                           f\"    char        args_static[{config.static_args_bytes}];\\n\")\n\n                if method.sync:\n                    file.write(f\"    char        return_args_static[{config.static_args_bytes}];\\n\")\n\n                file.write(f\"    {face.object}{method.name}       *args = ({face.object}{method.name}*) args_alloc\"\n                           f\"( args_static, {method.ArgumentsSize(False)} );\\n\")\n\n                if method.sync:\n                    file.write(f\"    {face.object}{method.name}Return *return_args;\\n\")\n\n                file.write( \"\\n\"\n                            \"    if (!args)\\n\"\n                            \"        return (DFBResult) D_OOM();\\n\"\n                            \"\\n\")\n\n                if method.sync:\n                    file.write(f\"    return_args = ({face.object}{method.name}Return*) args_alloc\"\n                               f\"( return_args_static, {method.ArgumentsSize(True)} );\\n\"\n                                \"\\n\")\n\n                if method.sync:\n                    file.write( \"    if (!return_args) {\\n\"\n                                \"        args_free( args_static, args );\\n\"\n                                \"        return (DFBResult) D_OOM();\\n\"\n                                \"    }\\n\"\n                                \"\\n\")\n\n                file.write(f\"    D_DEBUG_AT( DirectFB_{face.object}, \\\"{face.name}_Requestor::%s()\\\\n\\\", __FUNCTION__ );\\n\"\n                            \"\\n\"\n                           f\"{method.ArgumentsAssertions()}\"\n                            \"\\n\"\n                           f\"{method.ArgumentsInputAssignments()}\"\n                            \"\\n\"\n                           f\"    ret = (DFBResult) {face.object}_Call\")\n\n                if method.sync:\n                    file.write( \"( obj, FCEF_NONE\"\n                               f\", _{face.object}_{method.name}, args, {method.ArgumentsSize(False)}\"\n                               f\", return_args, {method.ArgumentsSize(True)}, NULL );\\n\")\n                else:\n                    file.write(\"( obj, (FusionCallExecFlags)(FCEF_ONEWAY\" + (\" | FCEF_QUEUE\" if method.queue else \"\") + \")\"\n                               f\", _{face.object}_{method.name}, args, {method.ArgumentsSize(False)}\"\n                                \", NULL, 0, NULL );\\n\")\n\n                file.write( \"    if (ret) {\\n\"\n                            \"        D_DERROR( ret, \\\"%s: \"\n                           f\"{face.object}_Call( {face.object}_{method.name} ) failed!\\\\n\\\", __FUNCTION__ );\\n\"\n                            \"        goto out;\\n\"\n                            \"    }\\n\"\n                            \"\\n\")\n\n                if method.sync:\n                    file.write( \"    if (return_args->result) {\\n\"\n                                \"        /*D_DERROR( return_args->result, \\\"%s: \"\n                               f\"{face.object}_{method.name} failed!\\\\n\\\", __FUNCTION__ );*/\\n\"\n                                \"        ret = return_args->result;\\n\"\n                                \"        goto out;\\n\"\n                                \"    }\\n\"\n                                \"\\n\")\n\n                file.write(f\"{method.ArgumentsOutputAssignments()}\"\n                            \"\\n\"\n                           f\"{method.ArgumentsOutputObjectCatch()}\"\n                            \"\\n\"\n                            \"out:\\n\")\n\n                if method.sync:\n                    file.write( \"    args_free( return_args_static, return_args );\\n\")\n\n                file.write( \"    args_free( args_static, args );\\n\"\n                            \"    return ret;\\n\"\n                            \"}\\n\"\n                            \"\\n\")\n\n        # Dispatch Object\n\n        file.write( \"/**************************************************************************************************/\\n\"\n                    \"\\n\"\n                    \"static DFBResult\\n\"\n                   f\"__{face.object}Dispatch__Dispatch( {face.dispatch} *obj,\\n\"\n                    \"                                FusionID      caller,\\n\"\n                    \"                                int           method,\\n\"\n                    \"                                void         *ptr,\\n\"\n                    \"                                unsigned int  length,\\n\"\n                    \"                                void         *ret_ptr,\\n\"\n                    \"                                unsigned int  ret_size,\\n\"\n                    \"                                unsigned int *ret_length )\\n\"\n                    \"{\\n\"\n                    \"    D_UNUSED\\n\"\n                    \"    DFBResult ret;\\n\"\n                    \"\\n\"\n                    \"\\n\"\n                    \"    switch (method) {\\n\")\n\n        # Dispatch Methods\n\n        for method in face.entities:\n            if isinstance(method, Method):\n                file.write(f\"        case _{face.object}_{method.name}: {{\\n\"\n                           f\"{method.ArgumentsInputObjectDecl()}\"\n                           f\"{method.ArgumentsOutputObjectDecl()}\")\n\n                if method.sync:\n                    file.write(f\"{method.ArgumentsOutputTmpDecl()}\")\n\n                file.write( \"            D_UNUSED\\n\"\n                           f\"            {face.object}{method.name}       *args        = \"\n                           f\"({face.object}{method.name} *) ptr;\\n\")\n\n                if method.sync:\n                    file.write(f\"            {face.object}{method.name}Return *return_args = \"\n                               f\"({face.object}{method.name}Return *) ret_ptr;\\n\")\n\n                file.write( \"\\n\"\n                           f\"            D_DEBUG_AT( DirectFB_{face.object}, \\\"=-> {face.object}_{method.name}\\\\n\\\" );\\n\"\n                            \"\\n\")\n\n                if not method.sync:\n                    file.write(f\"{method.ArgumentsInputDebug()}\"\n                                \"\\n\")\n\n                file.write(f\"{method.ArgumentsInputObjectLookup()}\")\n\n                if not method.sync:\n                    file.write(f\"            {face.name}_Real__{method.name}( obj\" +\n                               (\", \" if method.ArgumentsAsParamDecl() else \"\") + f\"{method.ArgumentsAsMemberParams()} );\\n\")\n                else:\n                    file.write(f\"            return_args->result = {face.name}_Real__{method.name}( obj\" +\n                               (\", \" if method.ArgumentsAsParamDecl() else \"\") + f\"{method.ArgumentsAsMemberParams()} );\\n\"\n                                \"            if (return_args->result == DFB_OK) {\\n\"\n                               f\"{method.ArgumentsOutputObjectThrow()}\"\n                               f\"{method.ArgumentsOutputTmpReturn()}\"\n                                \"            }\\n\"\n                                \"\\n\"\n                               f\"            *ret_length = {method.ArgumentsSizeReturn()};\\n\")\n\n                file.write( \"\\n\"\n                           f\"{method.ArgumentsInputObjectUnref()}\"\n                            \"            return DFB_OK;\\n\"\n                            \"        }\\n\"\n                            \"\\n\")\n\n        file.write( \"    }\\n\"\n                    \"\\n\"\n                    \"    return DFB_NOSUCHMETHOD;\\n\"\n                    \"}\\n\")\n\n        file.write( \"/**************************************************************************************************/\\n\"\n                    \"\\n\"\n                    \"DFBResult\\n\"\n                   f\"{face.object}Dispatch__Dispatch( {face.dispatch} *obj,\\n\"\n                    \"                                FusionID      caller,\\n\"\n                    \"                                int           method,\\n\"\n                    \"                                void         *ptr,\\n\"\n                    \"                                unsigned int  length,\\n\"\n                    \"                                void         *ret_ptr,\\n\"\n                    \"                                unsigned int  ret_size,\\n\"\n                    \"                                unsigned int *ret_length )\\n\"\n                    \"{\\n\"\n                    \"    DFBResult ret = DFB_OK;\\n\"\n                    \"\\n\"\n                   f\"    D_DEBUG_AT( DirectFB_{face.object}, \\\"{face.object}Dispatch::%s( %p )\\\\n\\\", \"\n                    \"__FUNCTION__, obj );\\n\")\n\n        if config.identity:\n            file.write( \"\\n\"\n                        \"    Core_PushIdentity( caller );\\n\")\n\n        file.write( \"\\n\"\n                   f\"    ret = __{face.object}Dispatch__Dispatch\"\n                    \"( obj, caller, method, ptr, length, ret_ptr, ret_size, ret_length );\\n\")\n\n        if config.identity:\n            file.write( \"\\n\"\n                        \"    Core_PopIdentity();\\n\")\n\n        file.write( \"\\n\"\n                    \"    return ret;\\n\"\n                    \"}\\n\")\n\n# --------------------------------------------------------------------------------------------------------------------------\n\nconfig = parser.parse_args()\n\nGetEntities(0, face.entities)\n\nGenerateHeader()\n\nGenerateSource()\n"
  },
  {
    "path": "src/core/fonts.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core.h>\n#include <core/fonts.h>\n#include <core/gfxcard.h>\n#include <core/surface.h>\n#include <direct/hash.h>\n#include <direct/map.h>\n#include <direct/utf8.h>\n#include <directfb_util.h>\n\nD_DEBUG_DOMAIN( Core_Font,         \"Core/Font\",          \"DirectFB Core Font\" );\nD_DEBUG_DOMAIN( Font_Cache,        \"Core/Font/Cache\",    \"DirectFB Core Font Cache\" );\nD_DEBUG_DOMAIN( Font_CacheRow,     \"Core/Font/CacheRow\", \"DirectFB Core Font Cache Row\" );\nD_DEBUG_DOMAIN( Core_FontSurfaces, \"Core/Font/Surf\",     \"DirectFB Core Font Surfaces\" );\nD_DEBUG_DOMAIN( Font_Manager,      \"Core/Font/Manager\",  \"DirectFB Core Font Manager\" );\n\n/**********************************************************************************************************************/\n\nstruct __DFB_CoreFontCache {\n     int                magic;\n\n     CoreFontManager   *manager;\n\n     CoreFontCacheType  type;\n\n     unsigned int       row_width;\n\n     DirectLink        *rows;\n};\n\nstruct __DFB_CoreFontCacheRow {\n     DirectLink           link;\n\n     int                  magic;\n\n     CoreFontCache       *cache;\n\n     unsigned long long   stamp;\n\n     CoreSurface         *surface;\n     unsigned int         next_x;\n\n     DirectLink          *glyphs;\n};\n\nstruct __DFB_CoreFontManager {\n     int                 magic;\n\n     CoreDFB            *core;\n\n     DirectMutex         lock;\n\n     DirectMap          *caches;\n\n     unsigned int        max_rows;\n     unsigned int        num_rows;\n     unsigned long long  row_stamp;\n};\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_font_manager_create( CoreDFB          *core,\n                         CoreFontManager **ret_manager )\n{\n     DFBResult        ret;\n     CoreFontManager *manager;\n\n     D_DEBUG_AT( Font_Manager, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( core != NULL );\n     D_ASSERT( ret_manager != NULL );\n\n     manager = D_CALLOC( 1, sizeof(CoreFontManager) );\n     if (!manager)\n          return D_OOM();\n\n     ret = dfb_font_manager_init( manager, core );\n     if (ret) {\n          D_FREE( manager );\n          return ret;\n     }\n\n     *ret_manager = manager;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_font_manager_destroy( CoreFontManager *manager )\n{\n     D_DEBUG_AT( Font_Manager, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( manager, CoreFontManager );\n     D_ASSERT( manager->max_rows > 0 );\n     D_ASSERT( manager->num_rows <= manager->max_rows );\n\n     dfb_font_manager_deinit( manager );\n\n     D_FREE( manager );\n\n     return DFB_OK;\n}\n\nstatic bool\nfont_cache_map_compare( DirectMap  *map,\n                        const void *key,\n                        void       *object,\n                        void       *ctx )\n{\n     const CoreFontCacheType *type  = key;\n     CoreFontCache           *cache = object;\n\n     return memcmp( type, &cache->type, sizeof(*type) ) == 0;\n}\n\nstatic unsigned int\nfont_cache_map_hash( DirectMap  *map,\n                     const void *key,\n                     void       *ctx )\n{\n     const CoreFontCacheType *type = key;\n\n     return (type->height * 131 + type->pixel_format) * 131 + type->surface_caps;\n}\n\nDFBResult\ndfb_font_manager_init( CoreFontManager *manager,\n                       CoreDFB         *core )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Font_Manager, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( core != NULL );\n     D_ASSERT( manager != NULL );\n\n     manager->core      = core;\n     manager->max_rows  = dfb_config->max_font_rows;\n\n     ret = direct_map_create( 11, font_cache_map_compare, font_cache_map_hash, NULL, &manager->caches );\n     if (ret)\n          return ret;\n\n     direct_recursive_mutex_init( &manager->lock );\n\n     D_MAGIC_SET( manager, CoreFontManager );\n\n     return DFB_OK;\n}\n\nstatic DirectEnumerationResult\ndestroy_caches( DirectMap *map,\n                void      *object,\n                void      *ctx )\n{\n     CoreFontCache *cache = object;\n\n     D_DEBUG_AT( Font_Manager, \"%s( %p )\\n\", __FUNCTION__, cache );\n\n     D_MAGIC_ASSERT( cache, CoreFontCache );\n\n     dfb_font_cache_destroy( cache );\n\n     return DENUM_OK;\n}\n\nDFBResult\ndfb_font_manager_deinit( CoreFontManager *manager )\n{\n     D_DEBUG_AT( Font_Manager, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( manager, CoreFontManager );\n     D_ASSERT( manager->max_rows > 0 );\n     D_ASSERT( manager->num_rows <= manager->max_rows );\n\n     direct_map_iterate( manager->caches, destroy_caches, NULL );\n     direct_map_destroy( manager->caches );\n\n     direct_mutex_deinit( &manager->lock );\n\n     D_MAGIC_CLEAR( manager );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_font_manager_lock( CoreFontManager *manager )\n{\n     D_DEBUG_AT( Font_Manager, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( manager, CoreFontManager );\n     D_ASSERT( manager->max_rows > 0 );\n     D_ASSERT( manager->num_rows <= manager->max_rows );\n\n     direct_mutex_lock( &manager->lock );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_font_manager_unlock( CoreFontManager *manager )\n{\n     D_DEBUG_AT( Font_Manager, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( manager, CoreFontManager );\n     D_ASSERT( manager->max_rows > 0 );\n     D_ASSERT( manager->num_rows <= manager->max_rows );\n\n     direct_mutex_unlock( &manager->lock );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_font_manager_get_cache( CoreFontManager          *manager,\n                            const CoreFontCacheType  *type,\n                            CoreFontCache           **ret_cache )\n{\n     D_DEBUG_AT( Font_Manager, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( manager, CoreFontManager );\n     D_ASSERT( manager->max_rows > 0 );\n     D_ASSERT( manager->num_rows <= manager->max_rows );\n     D_ASSERT( type != NULL );\n     D_ASSERT( ret_cache != NULL );\n\n     D_DEBUG_AT( Font_Manager, \"  -> height %u, format 0x%x, caps 0x%x\\n\",\n                 type->height, (unsigned int) type->pixel_format, (unsigned int) type->surface_caps );\n\n     DFBResult      ret;\n     CoreFontCache *cache;\n\n     CoreFontCacheType _type = *type;\n\n     if (_type.height < 8)\n          _type.height = 8;\n\n     cache = direct_map_lookup( manager->caches, &_type );\n     if (!cache) {\n          ret = dfb_font_cache_create( manager, &_type, &cache );\n          if (ret)\n               return ret;\n\n          ret = direct_map_insert( manager->caches, &_type, cache );\n          if (ret) {\n               dfb_font_cache_destroy( cache );\n               return ret;\n          }\n     }\n\n     *ret_cache = cache;\n\n     return DFB_OK;\n}\n\ntypedef struct {\n     unsigned int      lru_stamp;\n     CoreFontCacheRow *lru_row;\n} FindLruRowContext;\n\nstatic DirectEnumerationResult\nfind_lru_row( DirectMap *map,\n              void      *object,\n              void      *ctx )\n{\n     FindLruRowContext *context = ctx;\n     CoreFontCache     *cache   = object;\n     CoreFontCacheRow  *row;\n\n     D_DEBUG_AT( Font_Manager, \"%s( %p )\\n\", __FUNCTION__, cache );\n\n     D_MAGIC_ASSERT( cache, CoreFontCache );\n\n     direct_list_foreach (row, cache->rows) {\n          D_DEBUG_AT( Font_Manager, \"  -> stamp %llu\\n\", row->stamp );\n\n          if (!context->lru_row || context->lru_stamp > row->stamp) {\n               context->lru_row   = row;\n               context->lru_stamp = row->stamp;\n          }\n     }\n\n     return DENUM_OK;\n}\n\nDFBResult\ndfb_font_manager_remove_lru_row( CoreFontManager *manager )\n{\n     FindLruRowContext  context;\n     CoreFontCache     *cache;\n\n     D_DEBUG_AT( Font_Manager, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( manager, CoreFontManager );\n     D_ASSERT( manager->max_rows > 0 );\n     D_ASSERT( manager->num_rows <= manager->max_rows );\n\n     context.lru_stamp = 0;\n     context.lru_row   = NULL;\n\n     direct_map_iterate( manager->caches, find_lru_row, &context );\n\n     if (!context.lru_row) {\n          D_ERROR( \"Core/Font: Could not find any LRU row!\\n\" );\n          return DFB_ITEMNOTFOUND;\n     }\n\n     D_DEBUG_AT( Font_Manager, \"  -> row %p (stamp %llu)\\n\", context.lru_row, context.lru_row->stamp );\n\n     cache = context.lru_row->cache;\n\n     D_MAGIC_ASSERT( cache, CoreFontCache );\n\n     direct_list_remove( &cache->rows, &context.lru_row->link );\n\n     dfb_font_cache_row_destroy( context.lru_row );\n\n     /* Decrease row counter. */\n     manager->num_rows--;\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_font_cache_create( CoreFontManager          *manager,\n                       const CoreFontCacheType  *type,\n                       CoreFontCache           **ret_cache )\n{\n     DFBResult      ret;\n     CoreFontCache *cache;\n\n     D_MAGIC_ASSERT( manager, CoreFontManager );\n     D_ASSERT( manager->max_rows > 0 );\n     D_ASSERT( manager->num_rows <= manager->max_rows );\n     D_ASSERT( type != NULL );\n     D_ASSERT( ret_cache != NULL );\n\n     cache = D_CALLOC( 1, sizeof(CoreFontCache) );\n     if (!cache)\n          return D_OOM();\n\n     ret = dfb_font_cache_init( cache, manager, type );\n     if (ret) {\n          D_FREE( cache );\n          return ret;\n     }\n\n     *ret_cache = cache;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_font_cache_destroy( CoreFontCache *cache )\n{\n     D_MAGIC_ASSERT( cache, CoreFontCache );\n\n     dfb_font_cache_deinit( cache );\n\n     D_FREE( cache );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_font_cache_init( CoreFontCache           *cache,\n                     CoreFontManager         *manager,\n                     const CoreFontCacheType *type )\n{\n     D_ASSERT( cache != NULL );\n     D_MAGIC_ASSERT( manager, CoreFontManager );\n     D_ASSERT( manager->max_rows > 0 );\n     D_ASSERT( manager->num_rows <= manager->max_rows );\n     D_ASSERT( type != NULL );\n\n     cache->manager = manager;\n     cache->type    = *type;\n\n     cache->row_width = 2048 * type->height / 64;\n\n     if (cache->row_width > dfb_config->max_font_row_width)\n          cache->row_width = dfb_config->max_font_row_width;\n\n     if (cache->row_width < type->height)\n          cache->row_width = type->height;\n\n     cache->row_width = (cache->row_width + 7) & ~7;\n\n\n     D_MAGIC_SET( cache, CoreFontCache );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_font_cache_deinit( CoreFontCache *cache )\n{\n     CoreFontCacheRow *row, *next;\n\n     D_MAGIC_ASSERT( cache, CoreFontCache );\n\n     direct_list_foreach_safe (row, next, cache->rows) {\n          dfb_font_cache_row_destroy( row );\n     }\n\n     #if defined(__GNUC__) && __GNUC__ >= 10\n     #pragma GCC diagnostic push\n     #pragma GCC diagnostic ignored \"-Wanalyzer-null-dereference\"\n     #endif\n     cache->rows = NULL;\n\n     D_MAGIC_CLEAR( cache );\n     #if defined(__GNUC__) && __GNUC__ >= 10\n     #pragma GCC diagnostic pop\n     #endif\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_font_cache_get_row( CoreFontCache     *cache,\n                        unsigned int       width,\n                        CoreFontCacheRow **ret_row )\n{\n     DFBResult         ret;\n     CoreFontManager  *manager;\n     CoreFontCacheRow *row;\n     CoreFontCacheRow *best_row = NULL;\n     unsigned int      best_val = 0;\n\n     D_MAGIC_ASSERT( cache, CoreFontCache );\n     D_ASSERT( ret_row != NULL );\n\n     manager = cache->manager;\n\n     D_MAGIC_ASSERT( manager, CoreFontManager );\n     D_ASSERT( manager->max_rows > 0 );\n     D_ASSERT( manager->num_rows <= manager->max_rows );\n\n     /* Try freshest row first. */\n     row = (CoreFontCacheRow*) cache->rows;\n     if (row && row->next_x + width <= cache->row_width) {\n          *ret_row = row;\n\n          return DFB_OK;\n     }\n\n     /* Check for trailing space in each row. */\n     direct_list_foreach (row, cache->rows) {\n          D_MAGIC_ASSERT( row, CoreFontCacheRow );\n\n          /* If glyph fits... */\n          if (row->next_x + width <= cache->row_width) {\n               /* ...and no row yet or this row fits better... */\n               if (!best_row || best_val < row->next_x) {\n                    /* ...remember row. */\n                    best_row = row;\n                    best_val = row->next_x;\n               }\n          }\n     }\n\n     if (best_row) {\n          *ret_row = best_row;\n\n          return DFB_OK;\n     }\n\n     /* Maximum number of rows reached. */\n     if (manager->num_rows == manager->max_rows) {\n          /* Remove the least recently used row. */\n          ret = dfb_font_manager_remove_lru_row( manager );\n          if (ret)\n               return ret;\n     }\n\n     /* Create another row. */\n     ret = dfb_font_cache_row_create( cache, &row );\n     if (ret)\n          return ret;\n\n     /* Prepend to list (freshest is first). */\n     direct_list_prepend( &cache->rows, &row->link );\n\n     /* Increase row counter in manager. */\n     manager->num_rows++;\n\n     *ret_row = row;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_font_cache_row_create( CoreFontCache     *cache,\n                           CoreFontCacheRow **ret_row )\n{\n     DFBResult         ret;\n     CoreFontCacheRow *row;\n\n     row = D_CALLOC( 1, sizeof(CoreFontCacheRow) );\n     if (!row)\n          return D_OOM();\n\n     ret = dfb_font_cache_row_init( row, cache );\n     if (ret) {\n          D_FREE( row );\n          return ret;\n     }\n\n     *ret_row = row;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_font_cache_row_destroy( CoreFontCacheRow *row )\n{\n     D_MAGIC_ASSERT( row, CoreFontCacheRow );\n\n     dfb_font_cache_row_deinit( row );\n\n     D_FREE( row );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_font_cache_row_init( CoreFontCacheRow *row,\n                         CoreFontCache    *cache )\n{\n     DFBResult        ret;\n     CoreFontManager *manager;\n\n     D_MAGIC_ASSERT( cache, CoreFontCache );\n\n     manager = cache->manager;\n\n     D_MAGIC_ASSERT( manager, CoreFontManager );\n     D_ASSERT( manager->max_rows > 0 );\n     D_ASSERT( manager->num_rows <= manager->max_rows );\n\n     row->cache = cache;\n\n     /* Create a new font surface. */\n     ret = dfb_surface_create_simple( manager->core, cache->row_width, cache->type.height, cache->type.pixel_format,\n                                      DFB_COLORSPACE_DEFAULT( cache->type.pixel_format ), cache->type.surface_caps,\n                                      CSTF_FONT, dfb_config->font_resource_id, NULL, &row->surface );\n     if (ret) {\n          D_DERROR( ret, \"Core/Font: Could not create font surface!\\n\" );\n          return ret;\n     }\n\n     D_DEBUG_AT( Core_FontSurfaces, \"  -> new row %u - %dx%d %s\\n\",\n                 manager->num_rows, row->surface->config.size.w, row->surface->config.size.h,\n                 dfb_pixelformat_name( row->surface->config.format ) );\n\n     D_MAGIC_SET( row, CoreFontCacheRow );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_font_cache_row_deinit( CoreFontCacheRow *row )\n{\n     CoreGlyphData *glyph, *next;\n\n     D_MAGIC_ASSERT( row, CoreFontCacheRow );\n\n     /* Kick out all glyphs. */\n     direct_list_foreach_safe (glyph, next, row->glyphs) {\n          CoreFont *font = glyph->font;\n\n          D_MAGIC_ASSERT( glyph, CoreGlyphData );\n          D_ASSERT( glyph->layer < D_ARRAY_SIZE(font->layers) );\n\n          direct_hash_remove( font->layers[glyph->layer].glyph_hash, glyph->index );\n\n          if (glyph->index < 128)\n               font->layers[glyph->layer].glyph_data[glyph->index] = NULL;\n\n          D_MAGIC_CLEAR( glyph );\n          D_FREE( glyph );\n     }\n\n     dfb_surface_unref( row->surface );\n\n     D_MAGIC_CLEAR( row );\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_font_create( CoreDFB                   *core,\n                 const DFBFontDescription  *description,\n                 CoreFont                 **ret_font )\n{\n     DFBResult  ret;\n     int        i;\n     CoreFont  *font;\n\n     D_DEBUG_AT( Core_Font, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( core != NULL );\n     D_ASSERT( ret_font != NULL );\n\n     font = D_CALLOC( 1, sizeof(CoreFont) );\n     if (!font)\n          return D_OOM();\n\n     for (i = 0; i < DFB_FONT_MAX_LAYERS; i++) {\n          ret = direct_hash_create( 163, &font->layers[i].glyph_hash );\n          if (ret) {\n               while (i--)\n                    direct_hash_destroy( font->layers[i].glyph_hash );\n\n               D_FREE( font );\n               return ret;\n          }\n     }\n\n     font->core          = core;\n     font->manager       = dfb_core_font_manager( core );\n     font->description   = *description;\n     font->blittingflags = DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE;\n     font->pixel_format  = dfb_config->font_format;\n\n     if ((font->pixel_format == DSPF_ARGB     ||\n          font->pixel_format == DSPF_ABGR     ||\n          font->pixel_format == DSPF_ARGB8565 ||\n          font->pixel_format == DSPF_ARGB4444 ||\n          font->pixel_format == DSPF_RGBA4444 ||\n          font->pixel_format == DSPF_ARGB1555 ||\n          font->pixel_format == DSPF_RGBA5551) && dfb_config->font_premult) {\n          font->surface_caps = DSCAPS_PREMULTIPLIED;\n     }\n\n     D_MAGIC_SET( font, CoreFont );\n\n     *ret_font = font;\n\n     return DFB_OK;\n}\n\nvoid\ndfb_font_destroy( CoreFont *font )\n{\n     int i;\n\n     D_DEBUG_AT( Core_Font, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( font, CoreFont );\n     D_ASSERT( font->encodings != NULL || !font->last_encoding );\n\n     dfb_font_dispose( font );\n\n     for (i = 0; i < DFB_FONT_MAX_LAYERS; i++)\n          direct_hash_destroy( font->layers[i].glyph_hash );\n\n     for (i = DTEID_OTHER; i <= font->last_encoding; i++) {\n          CoreFontEncoding *encoding = font->encodings[i];\n\n          D_ASSERT( encoding != NULL );\n          D_ASSERT( encoding->name != NULL );\n\n          D_MAGIC_CLEAR( encoding );\n\n          D_FREE( encoding->name );\n          D_FREE( encoding );\n     }\n\n     if (font->encodings)\n          D_FREE( font->encodings );\n\n     D_MAGIC_CLEAR( font );\n\n     D_FREE( font );\n}\n\nstatic bool\nfree_glyphs( DirectHash    *hash,\n             unsigned long  key,\n             void          *value,\n             void          *ctx )\n{\n     CoreGlyphData    *data = value;\n     CoreFontCacheRow *row;\n\n     D_DEBUG_AT( Core_Font, \"%s( %lu )\\n\", __FUNCTION__, key );\n\n     D_MAGIC_ASSERT( data, CoreGlyphData );\n\n     CORE_GLYPH_DATA_DEBUG_AT( Core_Font, data );\n\n     /* Remove glyph from font. */\n     direct_hash_remove( hash, key );\n\n     row = data->row;\n     if (row) {\n          D_MAGIC_ASSERT( row, CoreFontCacheRow );\n\n          /* Remove glyph from cache row. */\n          direct_list_remove( &row->glyphs, &data->link );\n\n          /* If cache row got empty, destroy it. */\n          if (!row->glyphs) {\n               CoreFontManager *manager;\n               CoreFontCache   *cache = row->cache;\n\n               D_MAGIC_ASSERT( cache, CoreFontCache );\n\n               manager = cache->manager;\n\n               D_MAGIC_ASSERT( manager, CoreFontManager );\n               D_ASSERT( manager->max_rows > 0 );\n               D_ASSERT( manager->num_rows <= manager->max_rows );\n\n               /* Remove row from cache. */\n               direct_list_remove( &cache->rows, &row->link );\n\n               /* Destroy row. */\n               dfb_font_cache_row_destroy( row );\n\n               /* Decrease row counter in manager. */\n               manager->num_rows--;\n          }\n     }\n\n     D_MAGIC_CLEAR( data );\n\n     D_FREE( data );\n\n     return true;\n}\n\nDFBResult\ndfb_font_dispose( CoreFont *font )\n{\n     int i;\n\n     D_DEBUG_AT( Core_Font, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( font, CoreFont );\n\n     dfb_font_manager_lock( font->manager );\n\n     for (i = 0; i < DFB_FONT_MAX_LAYERS; i++) {\n          direct_hash_iterate( font->layers[i].glyph_hash, free_glyphs, NULL );\n\n          memset( font->layers[i].glyph_data, 0, sizeof(font->layers[i].glyph_data) );\n     }\n\n     dfb_font_manager_unlock( font->manager );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_font_get_glyph_data( CoreFont       *font,\n                         unsigned int    index,\n                         unsigned int    layer,\n                         CoreGlyphData **ret_data )\n{\n     DFBResult         ret;\n     CoreGlyphData    *data;\n     int               align;\n     CoreFontManager  *manager;\n     CoreFontCache    *cache;\n     CoreFontCacheRow *row = NULL;\n\n     D_DEBUG_AT( Core_Font, \"%s( index %u, layer %u )\\n\", __FUNCTION__, index, layer );\n\n     D_MAGIC_ASSERT( font, CoreFont );\n     D_ASSERT( layer < D_ARRAY_SIZE(font->layers) );\n     D_ASSERT( ret_data != NULL );\n\n     manager = font->manager;\n\n     D_MAGIC_ASSERT( manager, CoreFontManager );\n     D_ASSERT( (manager)->max_rows > 0 );\n     D_ASSERT( (manager)->num_rows <= (manager)->max_rows );\n\n     /* Quick Lookup in array. */\n     if (index < 128 && font->layers[layer].glyph_data[index]) {\n          data = font->layers[layer].glyph_data[index];\n          if (data->retry)\n               goto retry;\n\n          *ret_data = font->layers[layer].glyph_data[index];\n          return DFB_OK;\n     }\n\n     /* Standard lookup in hash. */\n     data = direct_hash_lookup( font->layers[layer].glyph_hash, index );\n     if (data) {\n          D_MAGIC_ASSERT( data, CoreGlyphData );\n\n          D_DEBUG_AT( Core_Font, \"  -> already in cache (%p)\\n\", data );\n\n          row = data->row;\n          if (row) {\n               D_MAGIC_ASSERT( row, CoreFontCacheRow );\n\n               row->stamp = manager->row_stamp++;\n          }\n\n          if (data->retry)\n               goto retry;\n\n          *ret_data = data;\n          return DFB_OK;\n     }\n\n     /* No glyph data available in cache, load new glyph. */\n\n     if (!font->GetGlyphData)\n          return DFB_UNSUPPORTED;\n\n     /* Allocate glyph data. */\n     data = D_CALLOC( 1, sizeof(CoreGlyphData) );\n     if (!data)\n          return D_OOM();\n\n     D_MAGIC_SET( data, CoreGlyphData );\n\n     data->font  = font;\n     data->index = index;\n     data->layer = layer;\n\nretry:\n     data->retry = false;\n\n     /* Get glyph data from font implementation. */\n     ret = font->GetGlyphData( font, index, data );\n     if (ret) {\n          D_DERROR( ret, \"Core/Font: Could not get glyph info for index %u!\\n\", index );\n          data->start = data->width = data->height = 0;\n\n          /* If the font module returned BUFFEREMPTY, we will retry loading next time. */\n          if (ret == DFB_BUFFEREMPTY)\n               data->retry = true;\n\n          goto out;\n     }\n\n     if (!(font->flags & CFF_SUBPIXEL_ADVANCE)) {\n          data->xadvance <<= 8;\n          data->yadvance <<= 8;\n     }\n\n     if (data->width < 1 || data->height < 1) {\n          D_DEBUG_AT( Core_Font, \"  -> zero size glyph bitmap!\\n\" );\n          data->start = data->width = data->height = 0;\n          goto out;\n     }\n\n     /* Get the proper cache based on size. */\n\n     CoreFontCacheType type;\n\n     type.height       = MAX( data->height, data->width );\n     type.pixel_format = font->pixel_format;\n     type.surface_caps = font->surface_caps;\n\n     /* Avoid too many surface switches during one string rendering. */\n     type.height       = MAX( font->height, type.height );\n\n     ret = dfb_font_manager_get_cache( font->manager, &type, &cache );\n     if (ret) {\n          D_DEBUG_AT( Core_Font, \"  -> could not get cache from manager!\\n\" );\n          goto error;\n     }\n\n     /* Check for a cache row (surface) to use. */\n     ret = dfb_font_cache_get_row( cache, data->width, &row );\n     if (ret) {\n          D_DEBUG_AT( Core_Font, \"  -> could not get row from cache!\\n\" );\n          goto error;\n     }\n\n     /* Add the glyph to the cache row. */\n\n     D_DEBUG_AT( Core_FontSurfaces, \"  -> render %u - %2dx%2d at %03u\\n\",\n                 index, data->width, data->height, row->next_x );\n\n     data->row     = row;\n     data->start   = row->next_x;\n     data->surface = row->surface;\n\n     align = (8 / (DFB_BYTES_PER_PIXEL( font->pixel_format ) ?: 1)) *\n             (DFB_PIXELFORMAT_ALIGNMENT( font->pixel_format ) + 1) - 1;\n\n     row->next_x  += (data->width + align) & ~align;\n\n     row->stamp = manager->row_stamp++;\n\n     /* Render the glyph data into the surface. */\n     ret = font->RenderGlyph( font, index, data );\n     if (ret) {\n          D_DEBUG_AT( Core_Font, \"  -> rendering glyph failed!\\n\" );\n          data->start = data->width = data->height = 0;\n\n          /* If the font module returned BUFFEREMPTY we will retry loading next time. */\n          if (ret == DFB_BUFFEREMPTY)\n               data->retry = true;\n\n          goto out;\n     }\n\n     dfb_gfxcard_flush_texture_cache();\n\n     CORE_GLYPH_DATA_DEBUG_AT( Core_Font, data );\n\nout:\n     if (!data->inserted) {\n          if (row)\n               direct_list_append( &row->glyphs, &data->link );\n\n          direct_hash_insert( font->layers[layer].glyph_hash, index, data );\n\n          if (index < 128)\n               font->layers[layer].glyph_data[index] = data;\n\n          data->inserted = true;\n     }\n\n     *ret_data = data;\n\n     return DFB_OK;\n\nerror:\n     D_MAGIC_CLEAR( data );\n     D_FREE( data );\n\n     return ret;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_font_register_encoding( CoreFont                    *font,\n                            const char                  *name,\n                            const CoreFontEncodingFuncs *funcs,\n                            DFBTextEncodingID            encoding_id )\n{\n     CoreFontEncoding  *encoding;\n     CoreFontEncoding **encodings;\n\n     D_DEBUG_AT( Core_Font, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( font, CoreFont );\n     D_ASSERT( encoding_id == DTEID_UTF8 || name != NULL );\n     D_ASSERT( funcs != NULL );\n\n     if (!funcs->GetCharacterIndex)\n          return DFB_INVARG;\n\n     /* Special case for default, native format. */\n     if (encoding_id == DTEID_UTF8) {\n          font->utf8 = funcs;\n\n          return DFB_OK;\n     }\n\n     if (!funcs->DecodeText)\n          return DFB_INVARG;\n\n     /* Setup new encoding information. */\n     encoding = D_CALLOC( 1, sizeof(CoreFontEncoding) );\n     if (!encoding)\n          return D_OOM();\n\n     encoding->encoding = font->last_encoding + 1;\n     encoding->funcs    = funcs;\n     encoding->name     = D_STRDUP( name );\n\n     if (!encoding->name) {\n          D_FREE( encoding );\n          return D_OOM();\n     }\n\n     /* Add to array. */\n     encodings = D_REALLOC( font->encodings,\n                            (encoding->encoding + 1) * sizeof(CoreFontEncoding*) );\n     if (!encodings) {\n          D_FREE( encoding->name );\n          D_FREE( encoding );\n          return D_OOM();\n     }\n\n     font->encodings = encodings;\n\n     font->last_encoding++;\n\n     D_ASSERT( font->last_encoding == encoding->encoding );\n\n     encodings[encoding->encoding] = encoding;\n\n     D_MAGIC_SET( encoding, CoreFontEncoding );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_font_decode_text( CoreFont          *font,\n                      DFBTextEncodingID  encoding,\n                      const void        *text,\n                      int                length,\n                      unsigned int      *ret_indices,\n                      int               *ret_num )\n{\n     int                          pos = 0, num = 0;\n     const u8                    *bytes = text;\n     const CoreFontEncodingFuncs *funcs;\n\n     D_DEBUG_AT( Core_Font, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( font, CoreFont );\n     D_ASSERT( text != NULL );\n     D_ASSERT( length >= 0 );\n     D_ASSERT( ret_indices != NULL );\n     D_ASSERT( ret_num != NULL );\n\n     if (encoding != DTEID_UTF8) {\n          if (encoding > font->last_encoding)\n               return DFB_IDNOTFOUND;\n\n          D_ASSERT( font->encodings[encoding] != NULL );\n\n          funcs = font->encodings[encoding]->funcs;\n\n          D_ASSERT( funcs != NULL );\n          D_ASSERT( funcs->DecodeText != NULL );\n\n          return funcs->DecodeText( font, text, length, ret_indices, ret_num );\n     }\n     else if (font->utf8) {\n          funcs = font->utf8;\n\n          if (funcs->DecodeText)\n               return funcs->DecodeText( font, text, length, ret_indices, ret_num );\n\n          D_ASSERT( funcs->GetCharacterIndex != NULL );\n\n          while (pos < length) {\n               unsigned int c;\n\n               if (bytes[pos] < 128)\n                    c = bytes[pos++];\n               else {\n                    c = DIRECT_UTF8_GET_CHAR( &bytes[pos] );\n                    pos += DIRECT_UTF8_SKIP( bytes[pos] );\n               }\n\n               if (funcs->GetCharacterIndex( font, c, &ret_indices[num] ) == DFB_OK)\n                    num++;\n          }\n     }\n     else {\n          while (pos < length) {\n               if (bytes[pos] < 128)\n                    ret_indices[num++] = bytes[pos++];\n               else {\n                    ret_indices[num++] = DIRECT_UTF8_GET_CHAR( &bytes[pos] );\n                    pos += DIRECT_UTF8_SKIP( bytes[pos] );\n               }\n          }\n     }\n\n     *ret_num = num;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_font_decode_character( CoreFont          *font,\n                           DFBTextEncodingID  encoding,\n                           u32                character,\n                           unsigned int      *ret_index )\n{\n     const CoreFontEncodingFuncs *funcs;\n\n     D_DEBUG_AT( Core_Font, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( font, CoreFont );\n     D_ASSERT( ret_index != NULL );\n\n     if (encoding > font->last_encoding)\n          return DFB_IDNOTFOUND;\n\n     if (encoding != DTEID_UTF8) {\n          D_ASSERT( font->encodings[encoding] != NULL );\n\n          funcs = font->encodings[encoding]->funcs;\n\n          D_ASSERT( funcs != NULL );\n          D_ASSERT( funcs->GetCharacterIndex != NULL );\n\n          return funcs->GetCharacterIndex( font, character, ret_index );\n     }\n     else if (font->utf8) {\n          funcs = font->utf8;\n\n          D_ASSERT( funcs->GetCharacterIndex != NULL );\n\n          return funcs->GetCharacterIndex( font, character, ret_index );\n     }\n     else\n          *ret_index = character;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/core/fonts.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__FONTS_H__\n#define __CORE__FONTS_H__\n\n#include <core/coretypes.h>\n#include <direct/list.h>\n\n/**********************************************************************************************************************/\n\n#define DFB_FONT_MAX_LAYERS 2\n\ntypedef struct {\n     DFBResult (*GetCharacterIndex)( CoreFont     *thiz,\n                                     unsigned int  character,\n                                     unsigned int *ret_index );\n\n     DFBResult (*DecodeText)       ( CoreFont     *thiz,\n                                     const void   *text,\n                                     int           length,\n                                     unsigned int *ret_indices,\n                                     int          *ret_num );\n} CoreFontEncodingFuncs;\n\ntypedef struct {\n     DirectLink                   link;\n\n     DFBTextEncodingID            encoding;\n     char                        *name;\n     const CoreFontEncodingFuncs *funcs;\n\n     int                          magic;\n} CoreFontEncoding;\n\ntypedef enum {\n     CFF_NONE             = 0x00000000,\n\n     CFF_SUBPIXEL_ADVANCE = 0x00000001,\n\n     CFF_ALL              = 0x00000001,\n} CoreFontFlags;\n\nstruct __DFB_CoreFont {\n     CoreDFB                      *core;\n\n     CoreFontManager              *manager;\n\n     DFBFontDescription            description;     /* original description used to create the font */\n\n     DFBSurfaceBlittingFlags       blittingflags;\n     DFBSurfacePixelFormat         pixel_format;\n     DFBSurfaceCapabilities        surface_caps;\n\n     DFBFontAttributes             attributes;\n\n     struct {\n          DirectHash              *glyph_hash;\n          CoreGlyphData           *glyph_data[128];\n     } layers[DFB_FONT_MAX_LAYERS];\n\n     int                           height;          /* font height */\n\n     int                           ascender;        /* a positive value, the distance from the baseline to the top */\n     int                           descender;       /* a negative value, the distance from the baseline to the bottom */\n     int                           maxadvance;      /* width of largest character */\n\n     float                         up_unit_x;       /* x coordinate of the unit vector pointing up */\n     float                         up_unit_y;       /* y coordinate of the unit vector pointing up */\n\n     const CoreFontEncodingFuncs  *utf8;            /* for default encoding, DTEID_UTF8 */\n     CoreFontEncoding            **encodings;       /* for other encodings */\n     DFBTextEncodingID             last_encoding;   /* dynamic allocation implementation helper  */\n\n     void                         *impl_data;       /* a pointer used by the implementation */\n\n     DFBResult                   (*GetGlyphData)( CoreFont      *thiz,\n                                                  unsigned int   index,\n                                                  CoreGlyphData *data );\n\n     DFBResult                   (*RenderGlyph) ( CoreFont      *thiz,\n                                                  unsigned int   index,\n                                                  CoreGlyphData *data );\n\n     DFBResult                   (*GetKerning)  ( CoreFont      *thiz,\n                                                  unsigned int   prev,\n                                                  unsigned int   current,\n                                                  int           *ret_x,\n                                                  int           *ret_y );\n\n     int                           magic;\n\n     int                           underline_position;\n     int                           underline_thickness;\n\n     CoreFontFlags                 flags;\n};\n\n#define CORE_FONT_DEBUG_AT(Domain,font)                                   \\\n     do {                                                                 \\\n          D_DEBUG_AT( Domain, \"  -> ascender  %d\\n\", (font)->ascender );  \\\n          D_DEBUG_AT( Domain, \"  -> descender %d\\n\", (font)->descender ); \\\n          D_DEBUG_AT( Domain, \"  -> height    %d\\n\", (font)->height );    \\\n     } while (0)\n\nstruct __DFB_CoreGlyphData {\n     DirectLink        link;\n\n     CoreFont         *font;\n\n     unsigned int      index;\n     unsigned int      layer;\n\n     CoreSurface      *surface;  /* contains bitmap of glyph */\n     int               start;    /* x offset of glyph in surface */\n     int               width;    /* width of the glyphs bitmap */\n     int               height;   /* height of the glyphs bitmap */\n     int               left;     /* x offset of the glyph */\n     int               top;      /* y offset of the glyph */\n     int               xadvance; /* x placement of next glyph */\n     int               yadvance; /* y placement of next glyph */\n\n     int               magic;\n\n     CoreFontCacheRow *row;\n\n     bool              inserted;\n     bool              retry;\n};\n\n#define CORE_GLYPH_DATA_DEBUG_AT(Domain,data)                           \\\n     do {                                                               \\\n          D_DEBUG_AT( Domain, \"  -> index    %u\\n\", (data)->index );    \\\n          D_DEBUG_AT( Domain, \"  -> layer    %u\\n\", (data)->layer );    \\\n          D_DEBUG_AT( Domain, \"  -> row      %p\\n\", (data)->row );      \\\n          D_DEBUG_AT( Domain, \"  -> surface  %p\\n\", (data)->surface );  \\\n          D_DEBUG_AT( Domain, \"  -> start    %d\\n\", (data)->start );    \\\n          D_DEBUG_AT( Domain, \"  -> width    %d\\n\", (data)->width );    \\\n          D_DEBUG_AT( Domain, \"  -> height   %d\\n\", (data)->height );   \\\n          D_DEBUG_AT( Domain, \"  -> left     %d\\n\", (data)->left );     \\\n          D_DEBUG_AT( Domain, \"  -> top      %d\\n\", (data)->top );      \\\n          D_DEBUG_AT( Domain, \"  -> xadvance %d\\n\", (data)->xadvance ); \\\n          D_DEBUG_AT( Domain, \"  -> yadvance %d\\n\", (data)->yadvance ); \\\n     } while (0)\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     unsigned int           height;\n     DFBSurfacePixelFormat  pixel_format;\n     DFBSurfaceCapabilities surface_caps;\n} CoreFontCacheType;\n\n/**********************************************************************************************************************/\n\nDFBResult dfb_font_manager_create        ( CoreDFB                      *core,\n                                           CoreFontManager             **ret_manager );\n\nDFBResult dfb_font_manager_destroy       ( CoreFontManager              *manager );\n\nDFBResult dfb_font_manager_init          ( CoreFontManager              *manager,\n                                           CoreDFB                      *core );\n\nDFBResult dfb_font_manager_deinit        ( CoreFontManager              *manager );\n\nDFBResult dfb_font_manager_lock          ( CoreFontManager              *manager );\n\nDFBResult dfb_font_manager_unlock        ( CoreFontManager              *manager );\n\nDFBResult dfb_font_manager_get_cache     ( CoreFontManager              *manager,\n                                           const CoreFontCacheType      *type,\n                                           CoreFontCache               **ret_cache );\n\nDFBResult dfb_font_manager_remove_lru_row( CoreFontManager              *manager );\n\n/**********************************************************************************************************************/\n\nDFBResult dfb_font_cache_create          ( CoreFontManager              *manager,\n                                           const CoreFontCacheType      *type,\n                                           CoreFontCache               **ret_cache );\n\nDFBResult dfb_font_cache_destroy         ( CoreFontCache                *cache );\n\nDFBResult dfb_font_cache_init            ( CoreFontCache                *cache,\n                                           CoreFontManager              *manager,\n                                           const CoreFontCacheType      *type );\n\nDFBResult dfb_font_cache_deinit          ( CoreFontCache                *cache );\n\nDFBResult dfb_font_cache_get_row         ( CoreFontCache                *cache,\n                                           unsigned int                  width,\n                                           CoreFontCacheRow            **ret_row );\n\nDFBResult dfb_font_cache_row_create      ( CoreFontCache                *cache,\n                                           CoreFontCacheRow            **ret_row );\n\nDFBResult dfb_font_cache_row_destroy     ( CoreFontCacheRow             *row );\n\nDFBResult dfb_font_cache_row_init        ( CoreFontCacheRow             *row,\n                                           CoreFontCache                *cache );\n\nDFBResult dfb_font_cache_row_deinit      ( CoreFontCacheRow             *row );\n\n/**********************************************************************************************************************/\n\n/*\n * Allocate and initialize a new font structure.\n */\nDFBResult dfb_font_create                ( CoreDFB                      *core,\n                                           const DFBFontDescription     *description,\n                                           CoreFont                    **ret_font );\n\n/*\n * Destroy all data in the font structure.\n */\nvoid      dfb_font_destroy               ( CoreFont                     *font );\n\n/*\n * Dispose resources that can be recreated, mainly glyph cache surfaces.\n */\nDFBResult dfb_font_dispose               ( CoreFont                     *font );\n\n/*\n * Load glyph data from font.\n */\nDFBResult dfb_font_get_glyph_data        ( CoreFont                     *font,\n                                           unsigned int                  index,\n                                           unsigned int                  layer,\n                                           CoreGlyphData               **glyph_data );\n\n/*\n * Register encoding implementations.\n *\n * The encoding can be DTEID_UTF8 or DTEID_OTHER, where in the latter case the actual id will be allocated dynamically.\n *\n * In the case of DTEID_UTF8, it's allowed to only provide GetCharacterIndex() and let the core do the DecodeText(), but\n * that would cause a GetCharacterIndex() call per decoded unicode character. So implementing both is advisable.\n *\n * If nothing is registered for DTEID_UTF8 at all, the core will pass the raw unicode characters to GetGlyphData(),\n * RenderGlyph() etc. It's a good choice if you want to avoid the character translation, having an efficient font module\n * which is based natively on unicode characters.\n *\n * For registering an encoding as DTEID_OTHER, both GetCharacterIndex() and DecodeText() must be provided.\n */\nDFBResult dfb_font_register_encoding     ( CoreFont                     *font,\n                                           const char                   *name,\n                                           const CoreFontEncodingFuncs  *funcs,\n                                           DFBTextEncodingID             encoding );\n\n/*\n * Decode a sequence of characters.\n */\nDFBResult dfb_font_decode_text           ( CoreFont                     *font,\n                                           DFBTextEncodingID             encoding,\n                                           const void                   *text,\n                                           int                           length,\n                                           unsigned int                 *ret_indices,\n                                           int                          *ret_num );\n\n/*\n * Get the raw index of a single character.\n */\nDFBResult dfb_font_decode_character      ( CoreFont                     *font,\n                                           DFBTextEncodingID             encoding,\n                                           u32                           character,\n                                           unsigned int                 *ret_index );\n\n/**********************************************************************************************************************/\n\n/*\n * Lock the font before accessing it.\n */\nstatic __inline__ void\ndfb_font_lock( CoreFont *font )\n{\n     D_MAGIC_ASSERT( font, CoreFont );\n\n     dfb_font_manager_lock( font->manager );\n}\n\n/*\n * Unlock the font after access.\n */\nstatic __inline__ void\ndfb_font_unlock( CoreFont *font )\n{\n     D_MAGIC_ASSERT( font, CoreFont );\n\n     dfb_font_manager_unlock( font->manager );\n}\n\n#endif\n"
  },
  {
    "path": "src/core/gfxcard.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreGraphicsStateClient.h>\n#include <core/core.h>\n#include <core/core_parts.h>\n#include <core/fonts.h>\n#include <core/gfxcard.h>\n#include <core/surface_allocation.h>\n#include <core/system.h>\n#include <fusion/conf.h>\n#include <fusion/shmalloc.h>\n#include <core/state.h>\n#include <gfx/clip.h>\n#include <gfx/generic/generic.h>\n#include <gfx/generic/generic_blit.h>\n#include <gfx/generic/generic_draw_line.h>\n#include <gfx/generic/generic_fill_rectangle.h>\n#include <gfx/generic/generic_stretch_blit.h>\n#include <gfx/generic/generic_texture_triangles.h>\n#include <gfx/util.h>\n\nD_DEBUG_DOMAIN( Core_Graphics,    \"Core/Graphics\",    \"DirectFB Core Graphics\" );\nD_DEBUG_DOMAIN( Core_GraphicsOps, \"Core/GraphicsOps\", \"DirectFB Core Graphics Operations\" );\nD_DEBUG_DOMAIN( Core_GfxState,    \"Core/GfxState\",    \"DirectFB Core Gfx State\" );\n\nDEFINE_MODULE_DIRECTORY( dfb_graphics_drivers, \"gfxdrivers\", DFB_GRAPHICS_DRIVER_ABI_VERSION );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int                      magic;\n\n     unsigned int             videoram_length;    /* Amount of usable memory */\n\n     char                    *module_name;\n\n     GraphicsDriverInfo       driver_info;\n     GraphicsDeviceInfo       device_info;\n     void                    *device_data;\n\n     FusionSkirmish           lock;\n     GraphicsDeviceLockFlags  lock_flags;\n\n     CardState               *state;              /* Current state of the graphics card. */\n     FusionID                 holder;             /* Fusion ID of state owner. */\n\n     FusionObjectID           last_allocation_id;\n     bool                     pending_ops;\n\n     long long                ts_start;\n     long long                ts_busy;\n     long long                ts_busy_sum;\n} DFBGraphicsCoreShared;\n\ntypedef struct {\n     int                        magic;\n\n     CoreDFB                   *core;\n\n     DFBGraphicsCoreShared     *shared;\n\n     DirectModuleEntry         *module;\n     const GraphicsDriverFuncs *driver_funcs;\n\n     void                      *driver_data;\n     void                      *device_data;  /* copy of shared->device_data */\n\n     CardCapabilities           caps;         /* local caps */\n     CardLimitations            limits;       /* local limits */\n\n     GraphicsDeviceFuncs        funcs;\n} DFBGraphicsCore;\n\nDFB_CORE_PART( graphics_core, GraphicsCore );\n\n/**********************************************************************************************************************/\n\nstatic DFBGraphicsCore *card = NULL;\n\n/*\n * Load/probe/unload a driver module one at a time until a suitable driver is found and return its symlinked functions.\n */\nstatic void\ndfb_gfxcard_find_driver( CoreDFB *core )\n{\n     DFBGraphicsCoreShared *shared;\n     DirectLink            *link;\n     FusionSHMPoolShared   *pool = dfb_core_shmpool( core );\n\n     D_DEBUG_AT( Core_Graphics, \"%s( %p )\\n\", __FUNCTION__, core );\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     shared = card->shared;\n\n     link = dfb_graphics_drivers.entries;\n\n     while (direct_list_check_link( link )) {\n          DirectModuleEntry         *module = (DirectModuleEntry*) link;\n          const GraphicsDriverFuncs *funcs;\n\n          D_DEBUG_AT( Core_Graphics, \"  -> module %p\\n\", module );\n\n          link = link->next;\n\n          funcs = direct_module_ref( module );\n          if (!funcs) {\n               D_DEBUG_AT( Core_Graphics, \"  -> ref failed!\\n\" );\n               continue;\n          }\n\n          if (!card->module) {\n               D_DEBUG_AT( Core_Graphics, \"  -> probing '%s'...\\n\", module->name );\n\n               if (funcs->Probe()) {\n                    D_DEBUG_AT( Core_Graphics, \"    => SUCCESS\\n\" );\n\n                    funcs->GetDriverInfo( &shared->driver_info );\n\n                    card->module       = module;\n                    card->driver_funcs = funcs;\n\n                    shared->module_name = SHSTRDUP( pool, module->name );\n\n                    continue;\n               }\n               else\n                    D_DEBUG_AT( Core_Graphics, \"    => FAIL\\n\" );\n          }\n          else\n               D_DEBUG_AT( Core_Graphics, \"  -> having driver\\n\" );\n\n          direct_module_unref( module );\n     }\n}\n\nstatic void\nInitDevice_Async( void *ctx,\n                  void *ctx2 )\n{\n     DFBResult                  ret;\n     DFBGraphicsCore           *data = ctx;\n     DFBGraphicsCoreShared     *shared;\n     const GraphicsDriverFuncs *funcs;\n\n     D_ASSERT( data != NULL );\n     D_ASSERT( data->shared != NULL );\n     D_ASSERT( data->driver_funcs != NULL );\n\n     shared = data->shared;\n     funcs  = data->driver_funcs;\n\n     ret = funcs->InitDevice( &shared->device_info, data->driver_data, data->device_data );\n     if (ret) {\n          D_DERROR( ret, \"Core/Graphics: Could not init device!\\n\" );\n          return;\n     }\n\n     if (data->funcs.EngineReset)\n          data->funcs.EngineReset( data->driver_data, data->device_data );\n\n     data->caps   = shared->device_info.caps;\n     data->limits = shared->device_info.limits;\n\n     D_INFO( \"DirectFB/Graphics: %s %s %d.%d (%s)\\n\", shared->device_info.vendor, shared->device_info.name,\n             shared->driver_info.version.major, shared->driver_info.version.minor, shared->driver_info.vendor );\n}\n\nstatic DFBResult\ndfb_graphics_core_initialize( CoreDFB               *core,\n                              DFBGraphicsCore       *data,\n                              DFBGraphicsCoreShared *shared )\n{\n     DFBResult            ret;\n     int                  videoram_length;\n     FusionSHMPoolShared *pool = dfb_core_shmpool( core );\n\n     D_DEBUG_AT( Core_Graphics, \"%s( %p, %p, %p )\\n\", __FUNCTION__, core, data, shared );\n\n     D_ASSERT( data != NULL );\n     D_ASSERT( shared != NULL );\n\n     card = data;\n\n     data->core   = core;\n     data->shared = shared;\n\n     /* Fill generic driver info. */\n     gGetDriverInfo( &shared->driver_info );\n\n     /* Fill generic device info. */\n     gGetDeviceInfo( &shared->device_info );\n\n     if (!shared->device_info.limits.dst_max.w)\n          shared->device_info.limits.dst_max.w = INT_MAX;\n\n     if (!shared->device_info.limits.dst_max.h)\n          shared->device_info.limits.dst_max.h = INT_MAX;\n\n     /* Limit video ram length. */\n     videoram_length = dfb_system_videoram_length();\n     if (videoram_length) {\n          if (dfb_config->videoram_limit > 0 && dfb_config->videoram_limit < videoram_length)\n               shared->videoram_length = dfb_config->videoram_limit;\n          else\n               shared->videoram_length = videoram_length;\n     }\n\n     /* Build a list of available drivers. */\n     direct_modules_explore_directory( &dfb_graphics_drivers );\n\n     /* Load driver. */\n     if (dfb_system_caps() & CSCAPS_ACCELERATION)\n          dfb_gfxcard_find_driver( core );\n\n     if (data->driver_funcs) {\n          const GraphicsDriverFuncs *funcs = data->driver_funcs;\n\n          data->driver_data = D_CALLOC( 1, shared->driver_info.driver_data_size );\n\n          data->device_data = shared->device_data = SHCALLOC( pool, 1, shared->driver_info.device_data_size );\n\n          ret = funcs->InitDriver( &data->funcs, data->driver_data, data->device_data, core );\n          if (ret) {\n               SHFREE( pool, shared->device_data );\n               SHFREE( pool, shared->module_name );\n               D_FREE( data->driver_data );\n               card = NULL;\n               return ret;\n          }\n\n          if (dfb_config->call_nodirect)\n               Core_AsyncCall( InitDevice_Async, data, NULL );\n          else\n               InitDevice_Async( data, NULL );\n     }\n     else\n          D_INFO( \"DirectFB/Graphics: %s %s %d.%d (%s)\\n\", shared->device_info.vendor, shared->device_info.name,\n                  shared->driver_info.version.major, shared->driver_info.version.minor, shared->driver_info.vendor );\n\n     if (dfb_config->software_only) {\n          if (data->funcs.CheckState) {\n               data->funcs.CheckState = NULL;\n\n               D_INFO( \"DirectFB/Graphics: Acceleration disabled (by 'no-hardware')\\n\" );\n          }\n     }\n     else {\n          data->caps   = shared->device_info.caps;\n          data->limits = shared->device_info.limits;\n     }\n\n     fusion_skirmish_init2( &shared->lock, \"GfxCard\", dfb_core_world( core ), fusion_config->secure_fusion );\n\n     D_MAGIC_SET( data, DFBGraphicsCore );\n     D_MAGIC_SET( shared, DFBGraphicsCoreShared );\n\n     return DFB_OK;\n}\n\n/*\n * Load the driver module used by the session.\n */\nstatic void\ndfb_gfxcard_load_driver( void )\n{\n     DFBGraphicsCoreShared *shared;\n     DirectLink            *link;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     shared = card->shared;\n\n     if (!shared->module_name)\n          return;\n\n     link = dfb_graphics_drivers.entries;\n\n     while (direct_list_check_link( link )) {\n          DirectModuleEntry         *module = (DirectModuleEntry*) link;\n          const GraphicsDriverFuncs *funcs;\n\n          link = link->next;\n\n          funcs = direct_module_ref( module );\n          if (!funcs)\n               continue;\n\n          if (!card->module && !strcmp( module->name, shared->module_name )) {\n               card->module       = module;\n               card->driver_funcs = funcs;\n          }\n          else\n               direct_module_unref( module );\n     }\n}\n\nstatic DFBResult\ndfb_graphics_core_join( CoreDFB               *core,\n                        DFBGraphicsCore       *data,\n                        DFBGraphicsCoreShared *shared )\n{\n     DFBResult          ret;\n     GraphicsDriverInfo driver_info;\n\n     D_DEBUG_AT( Core_Graphics, \"%s( %p, %p, %p )\\n\", __FUNCTION__, core, data, shared );\n\n     D_ASSERT( data != NULL );\n     D_MAGIC_ASSERT( shared, DFBGraphicsCoreShared );\n\n     card = data;\n\n     data->core   = core;\n     data->shared = shared;\n\n     /* Initialize software rasterizer. */\n     gGetDriverInfo( &driver_info );\n\n     /* Build a list of available drivers. */\n     direct_modules_explore_directory( &dfb_graphics_drivers );\n\n     /* Load driver. */\n     if (dfb_system_caps() & CSCAPS_ACCELERATION)\n          dfb_gfxcard_load_driver();\n\n     if (data->driver_funcs) {\n          const GraphicsDriverFuncs *funcs = data->driver_funcs;\n\n          data->driver_data = D_CALLOC( 1, shared->driver_info.driver_data_size );\n\n          data->device_data = shared->device_data;\n\n          ret = funcs->InitDriver( &data->funcs, data->driver_data, data->device_data, core );\n          if (ret) {\n               D_FREE( data->driver_data );\n               return ret;\n          }\n     }\n     else if (shared->module_name) {\n          D_ERROR( \"Core/Graphics: Could not load driver used by the running session!\\n\" );\n          return DFB_UNSUPPORTED;\n     }\n\n     D_INFO( \"DirectFB/Graphics: %s %s %d.%d (%s)\\n\", shared->device_info.vendor, shared->device_info.name,\n             shared->driver_info.version.major, shared->driver_info.version.minor, shared->driver_info.vendor );\n\n     if (dfb_config->software_only) {\n          if (data->funcs.CheckState) {\n               data->funcs.CheckState = NULL;\n               D_INFO( \"DirectFB/Graphics: Acceleration disabled (by 'no-hardware')\\n\" );\n          }\n     }\n     else {\n          data->caps   = shared->device_info.caps;\n          data->limits = shared->device_info.limits;\n     }\n\n     D_MAGIC_SET( data, DFBGraphicsCore );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_graphics_core_shutdown( DFBGraphicsCore *data,\n                            bool             emergency )\n{\n     DFBGraphicsCoreShared *shared;\n     FusionSHMPoolShared   *pool;\n\n     D_DEBUG_AT( Core_Graphics, \"%s( %p, %semergency )\\n\", __FUNCTION__, data, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( data, DFBGraphicsCore );\n     D_MAGIC_ASSERT( data->shared, DFBGraphicsCoreShared );\n\n     shared = data->shared;\n\n     pool = dfb_core_shmpool( data->core );\n\n     dfb_gfxcard_lock( GDLF_SYNC );\n\n     if (data->driver_funcs) {\n          const GraphicsDriverFuncs *funcs = data->driver_funcs;\n\n          funcs->CloseDevice( data->driver_data, data->device_data );\n          funcs->CloseDriver( data->driver_data );\n\n          direct_module_unref( data->module );\n\n          SHFREE( pool, data->device_data );\n          D_FREE( data->driver_data );\n     }\n\n     fusion_skirmish_destroy( &shared->lock );\n\n     if (shared->module_name)\n          SHFREE( pool, shared->module_name );\n\n     D_MAGIC_CLEAR( data );\n     D_MAGIC_CLEAR( shared );\n\n     card = NULL;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_graphics_core_leave( DFBGraphicsCore *data,\n                         bool             emergency )\n{\n     D_DEBUG_AT( Core_Graphics, \"%s( %p, %semergency )\\n\", __FUNCTION__, data, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( data, DFBGraphicsCore );\n     D_MAGIC_ASSERT( data->shared, DFBGraphicsCoreShared );\n\n     if (data->driver_funcs) {\n          data->driver_funcs->CloseDriver( data->driver_data );\n\n          direct_module_unref( data->module );\n\n          D_FREE( data->driver_data );\n     }\n\n     D_MAGIC_CLEAR( data );\n\n     card = NULL;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_graphics_core_suspend( DFBGraphicsCore *data )\n{\n     D_DEBUG_AT( Core_Graphics, \"%s( %p )\\n\", __FUNCTION__, data );\n\n     D_MAGIC_ASSERT( data, DFBGraphicsCore );\n     D_MAGIC_ASSERT( data->shared, DFBGraphicsCoreShared );\n\n     dfb_gfxcard_lock( GDLF_WAIT | GDLF_SYNC | GDLF_RESET | GDLF_INVALIDATE );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_graphics_core_resume( DFBGraphicsCore *data )\n{\n     D_DEBUG_AT( Core_Graphics, \"%s( %p )\\n\", __FUNCTION__, data );\n\n     D_MAGIC_ASSERT( data, DFBGraphicsCore );\n     D_MAGIC_ASSERT( data->shared, DFBGraphicsCoreShared );\n\n     dfb_gfxcard_unlock();\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic void dfb_gfxcard_update_stats( long long now );\nstatic void dfb_gfxcard_switch_busy ( void );\nstatic void dfb_gfxcard_switch_idle ( void );\n\nDFBResult\ndfb_gfxcard_lock( GraphicsDeviceLockFlags flags )\n{\n     DFBResult              ret;\n     DFBGraphicsCoreShared *shared;\n     GraphicsDeviceFuncs   *funcs;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     shared = card->shared;\n     funcs  = &card->funcs;\n\n     D_DEBUG_AT( Core_Graphics, \"%s()\\n\", __FUNCTION__ );\n\n     ret = fusion_skirmish_prevail( &shared->lock );\n     if (ret)\n          return ret;\n\n     if ((flags & GDLF_SYNC) && funcs->EngineSync) {\n          /* Start command processing if not already running. */\n          if (!dfb_config->gfx_emit_early && shared->pending_ops && card->funcs.EmitCommands) {\n               dfb_gfxcard_switch_busy();\n\n               card->funcs.EmitCommands( card->driver_data, card->device_data );\n\n               shared->pending_ops = false;\n          }\n\n          ret = funcs->EngineSync( card->driver_data, card->device_data );\n          if (ret) {\n               if (funcs->EngineReset)\n                    funcs->EngineReset( card->driver_data, card->device_data );\n\n               shared->state = NULL;\n\n               fusion_skirmish_dismiss( &shared->lock );\n\n               return ret;\n          }\n\n          dfb_gfxcard_switch_idle();\n     }\n\n     if ((shared->lock_flags & GDLF_RESET) && funcs->EngineReset)\n          funcs->EngineReset( card->driver_data, card->device_data );\n\n     if (shared->lock_flags & GDLF_INVALIDATE) {\n          if (funcs->InvalidateState)\n               funcs->InvalidateState( card->driver_data, card->device_data );\n          shared->state = NULL;\n     }\n\n     shared->lock_flags = flags;\n\n     return DFB_OK;\n}\n\nvoid\ndfb_gfxcard_unlock()\n{\n     DFBGraphicsCoreShared *shared;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_DEBUG_AT( Core_Graphics, \"%s()\\n\", __FUNCTION__ );\n\n     shared = card->shared;\n\n     fusion_skirmish_dismiss( &shared->lock );\n}\n\nDFBResult\ndfb_gfxcard_flush()\n{\n     DFBResult              ret;\n     DFBGraphicsCoreShared *shared;\n     GraphicsDeviceFuncs   *funcs;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_DEBUG_AT( Core_Graphics, \"%s()\\n\", __FUNCTION__ );\n\n     if (dfb_config->gfx_emit_early) {\n          D_DEBUG_AT( Core_Graphics, \"  -> gfx-emit-early\\n\" );\n\n          return DFB_OK;\n     }\n\n     shared = card->shared;\n     funcs  = &card->funcs;\n\n     ret = fusion_skirmish_prevail( &shared->lock );\n     if (ret)\n          return ret;\n\n     /* Start command processing if not already running. */\n     if (shared->pending_ops && funcs->EmitCommands) {\n          D_DEBUG_AT( Core_Graphics, \"  -> pending ops, emitting...\\n\" );\n\n          dfb_gfxcard_switch_busy();\n\n          funcs->EmitCommands( card->driver_data, card->device_data );\n\n          shared->pending_ops = false;\n     }\n     else\n          D_DEBUG_AT( Core_Graphics, \"  -> nothing to emit!\\n\" );\n\n     fusion_skirmish_dismiss( &shared->lock );\n\n     return DFB_OK;\n}\n\nvoid\ndfb_gfxcard_start_drawing( CardState *state )\n{\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n\n     if (card->funcs.StartDrawing)\n          card->funcs.StartDrawing( card->driver_data, card->device_data, state );\n}\n\nvoid\ndfb_gfxcard_stop_drawing( CardState *state )\n{\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n\n     if (card->funcs.StopDrawing)\n          card->funcs.StopDrawing( card->driver_data, card->device_data, state );\n}\n\nbool\ndfb_gfxcard_state_check( CardState           *state,\n                         DFBAccelerationMask  accel )\n{\n     DFBResult          ret;\n     int                cx2, cy2;\n     CoreSurfaceBuffer *dst_buffer;\n     CoreSurfaceBuffer *src_buffer;\n\n     D_ASSERT( card != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_MAGIC_ASSERT_IF( state->destination, CoreSurface );\n     D_MAGIC_ASSERT_IF( state->source, CoreSurface );\n     D_ASSERT( state->clip.x2 >= state->clip.x1 );\n     D_ASSERT( state->clip.y2 >= state->clip.y1 );\n     D_ASSERT( state->clip.x1 >= 0 );\n     D_ASSERT( state->clip.y1 >= 0 );\n\n     D_DEBUG_AT( Core_GraphicsOps, \"%s( %p, 0x%08x, %4d,%4d-%4d,%4d )\\n\", __FUNCTION__,\n                 state, accel, DFB_REGION_VALS( &state->clip ) );\n\n     if (DFB_BLITTING_FUNCTION(accel)) {\n          D_DEBUG_AT( Core_GfxState, \"%s( %p, 0x%08x ) blitting %p -> %p\\n\", __FUNCTION__,\n                      state, accel, state->source, state->destination );\n     }\n     else {\n          D_DEBUG_AT( Core_GfxState, \"%s( %p, 0x%08x ) drawing -> %p\\n\", __FUNCTION__,\n                      state, accel, state->destination );\n     }\n\n     if (state->clip.x1 < 0) {\n          state->clip.x1   = 0;\n          state->modified |= SMF_CLIP;\n     }\n\n     if (state->clip.y1 < 0) {\n          state->clip.y1   = 0;\n          state->modified |= SMF_CLIP;\n     }\n\n     D_DEBUG_AT( Core_GfxState, \"  <- checked 0x%08x, accel 0x%08x, modified 0x%08x, mod_hw 0x%08x\\n\",\n                 state->checked, state->accel, state->modified, state->mod_hw );\n\n     /* Destination may have been destroyed. */\n     if (!state->destination) {\n          D_BUG( \"no destination\" );\n          return false;\n     }\n\n     /* Destination buffer may have been destroyed (suspended). i.e by a vt-switching. */\n     if (state->destination->num_buffers == 0) {\n          D_DEBUG_AT( Core_GfxState, \"  -> no buffers in destination surface\\n\" );\n          return false;\n     }\n\n     if (DFB_BLITTING_FUNCTION( accel )) {\n          /* Source may have been destroyed. */\n          if (!state->source) {\n               D_BUG( \"no source\" );\n               return false;\n          }\n\n          /* Mask may have been destroyed. */\n          if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR) && !state->source_mask) {\n               D_BUG( \"no mask\" );\n               return false;\n          }\n\n          /* Source2 may have been destroyed. */\n          if (accel == DFXL_BLIT2 && !state->source2) {\n               D_BUG( \"no source2\" );\n               return false;\n          }\n     }\n\n     ret = dfb_surface_lock( state->destination );\n     if (ret)\n          return false;\n\n     dst_buffer = dfb_surface_get_buffer( state->destination, state->to );\n\n     D_MAGIC_ASSERT( dst_buffer, CoreSurfaceBuffer );\n\n     dfb_surface_unlock( state->destination );\n\n     D_ASSUME( state->clip.x2 < state->destination->config.size.w );\n     D_ASSUME( state->clip.y2 < state->destination->config.size.h );\n\n     cx2 = state->destination->config.size.w - 1;\n     cy2 = state->destination->config.size.h - 1;\n\n     if (state->clip.x2 > cx2) {\n          state->clip.x2 = cx2;\n\n          if (state->clip.x1 > cx2)\n               state->clip.x1 = cx2;\n\n          state->modified |= SMF_CLIP;\n     }\n\n     if (state->clip.y2 > cy2) {\n          state->clip.y2 = cy2;\n\n          if (state->clip.y1 > cy2)\n               state->clip.y1 = cy2;\n\n          state->modified |= SMF_CLIP;\n     }\n\n     /* If there's no CheckState() function, there's no acceleration at all.  */\n     if (!card->funcs.CheckState) {\n          D_DEBUG_AT( Core_GfxState, \"  -> no acceleration available\\n\" );\n          return false;\n     }\n\n     /*\n      * Check if this function has been disabled temporarily.\n      */\n     if (state->disabled & accel) {\n          D_DEBUG_AT( Core_GfxState, \"  -> acceleration disabled\\n\" );\n          return false;\n     }\n\n     /* If destination or blend functions have been changed... */\n     if (state->modified & (SMF_DESTINATION | SMF_SRC_BLEND | SMF_DST_BLEND | SMF_RENDER_OPTIONS)) {\n          /* ...force rechecking for all functions. */\n          state->checked = DFXL_NONE;\n     }\n     else {\n          /* If source/mask or blitting flags have been changed... */\n          if (state->modified & (SMF_SOURCE | SMF_BLITTING_FLAGS | SMF_SOURCE_MASK | SMF_SOURCE_MASK_VALS)) {\n               /* ...force rechecking for all blitting functions. */\n               state->checked &= ~DFXL_ALL_BLIT;\n          }\n          else if (state->modified & SMF_SOURCE2) {\n               /* Otherwise force rechecking for Blit2() function if source2 has been changed. */\n               state->checked &= ~DFXL_BLIT2;\n          }\n\n          /* If drawing flags have been changed... */\n          if (state->modified & SMF_DRAWING_FLAGS) {\n               /* ...force rechecking for all drawing functions. */\n               state->checked &= ~DFXL_ALL_DRAW;\n          }\n     }\n\n     D_DEBUG_AT( Core_GfxState, \"  -> checked 0x%08x, accel 0x%08x, modified 0x%08x, mod_hw 0x%08x\\n\",\n                 state->checked, state->accel, state->modified, state->mod_hw );\n\n     /* If the function needs to be checked. */\n     if (!(state->checked & accel)) {\n          /* Unset unchecked functions. */\n          state->accel &= state->checked;\n\n          /* Call driver to (re)set the bit if the function is supported. */\n          card->funcs.CheckState( card->driver_data, card->device_data, state, accel );\n\n          /* Add the function to 'checked' functions. */\n          state->checked |= accel;\n\n          /* Add additional functions the driver might have checked, too. */\n          state->checked |= state->accel;\n     }\n\n     D_DEBUG_AT( Core_GfxState, \"  -> checked 0x%08x, accel 0x%08x, modified 0x%08x, mod_hw 0x%08x\\n\",\n                 state->checked, state->accel, state->modified, state->mod_hw );\n\n     /* Move modification flags to the set for drivers. */\n     state->mod_hw   |= state->modified;\n     state->modified  = SMF_NONE;\n\n     /* If back_buffer policy is 'system only' and the GPU does not fully support system memory surfaces, there's no\n        acceleration available. */\n     if ((dst_buffer->policy == CSP_SYSTEMONLY &&\n          !(card->caps.flags & CCF_READSYSMEM && card->caps.flags & CCF_WRITESYSMEM)) ||\n         (!(card->caps.flags & CCF_RENDEROPTS) && (state->render_options & DSRO_MATRIX))) {\n          /* Clear 'accelerated' functions. */\n          state->accel   = DFXL_NONE;\n          state->checked = DFXL_ALL;\n     }\n     else if (DFB_BLITTING_FUNCTION( accel )) {\n          /* If the front buffer policy of the source is 'system only', no accelerated blitting is available. */\n          ret = dfb_surface_lock( state->source );\n          if (ret)\n               return false;\n\n          src_buffer = dfb_surface_get_buffer( state->source, state->from );\n\n          D_MAGIC_ASSERT( src_buffer, CoreSurfaceBuffer );\n\n          dfb_surface_unlock( state->source );\n\n          if (src_buffer->policy == CSP_SYSTEMONLY && !(card->caps.flags & CCF_READSYSMEM)) {\n               /* Clear 'accelerated blitting' functions. */\n               state->accel   &= ~DFXL_ALL_BLIT;\n               state->checked |=  DFXL_ALL_BLIT;\n          }\n     }\n\n     D_DEBUG_AT( Core_GfxState, \"  -> checked 0x%08x, accel 0x%08x, modified 0x%08x, mod_hw 0x%08x\\n\",\n                 state->checked, state->accel, state->modified, state->mod_hw );\n\n     /* Return whether the function bit is set. */\n     return state->accel & accel;\n}\n\n/*\n * This function returns non zero after successful locking the surface(s) for access by hardware.\n * Propagate state changes to driver.\n */\nstatic bool\ndfb_gfxcard_state_acquire( CardState *state, DFBAccelerationMask accel )\n{\n     DFBResult               ret;\n     DFBGraphicsCoreShared  *shared;\n     CoreSurfaceAccessFlags  access = CSAF_WRITE;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_MAGIC_ASSERT_IF( state->destination, CoreSurface );\n     D_MAGIC_ASSERT_IF( state->source, CoreSurface );\n\n     D_DEBUG_AT( Core_GraphicsOps, \"%s( %p, 0x%08x, %4d,%4d-%4d,%4d )\\n\", __FUNCTION__,\n                 state, accel, DFB_REGION_VALS( &state->clip ) );\n\n     shared = card->shared;\n\n     /* Find locking flags. */\n     if (DFB_BLITTING_FUNCTION( accel )) {\n          if (state->blittingflags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA | DSBLIT_DST_COLORKEY))\n               access |= CSAF_READ;\n     }\n     else if (state->drawingflags & (DSDRAW_BLEND | DSDRAW_DST_COLORKEY))\n          access |= CSAF_READ;\n\n     if (DFB_BLITTING_FUNCTION(accel)) {\n          D_DEBUG_AT( Core_GfxState, \"%s( %p, 0x%08x ) blitting %p -> %p\\n\", __FUNCTION__,\n                      state, accel, state->source, state->destination );\n     }\n     else {\n          D_DEBUG_AT( Core_GfxState, \"%s( %p, 0x%08x ) drawing -> %p\\n\", __FUNCTION__,\n                      state, accel, state->destination );\n     }\n\n     /* Push our own identity for buffer locking calls (locality of accessor). */\n     Core_PushIdentity( 0 );\n\n     /* Lock destination. */\n     ret = dfb_surface_lock_buffer2( state->destination, state->to, state->destination_flip_count_used ?\n                                     state->destination_flip_count : state->destination->flips,\n                                     state->to_eye, CSAID_GPU, access, &state->dst );\n     if (ret) {\n          D_DEBUG_AT( Core_GfxState, \"  -> could not lock destination for GPU access!\\n\" );\n          Core_PopIdentity();\n          return false;\n     }\n\n     /* If blitting... */\n     if (DFB_BLITTING_FUNCTION( accel )) {\n          /* ...lock source for reading. */\n          if (state->source_buffer) {\n               dfb_surface_lock( state->source );\n               CoreSurfaceBuffer *src_buffer = state->source_buffer;\n               ret = dfb_surface_buffer_lock( src_buffer, CSAID_GPU, CSAF_READ, &state->src );\n               dfb_surface_unlock( state->source );\n          }\n          else if (state->source_flip_count_used)\n               ret = dfb_surface_lock_buffer2( state->source, state->from, state->source_flip_count,\n                                               state->from_eye, CSAID_GPU, CSAF_READ, &state->src );\n          else\n               ret = dfb_surface_lock_buffer2( state->source, state->from, state->source->flips,\n                                               state->from_eye, CSAID_GPU, CSAF_READ, &state->src );\n          if (ret) {\n               D_DEBUG_AT( Core_GfxState, \"  -> could not lock source for GPU access!\\n\" );\n               dfb_surface_unlock_buffer( state->destination, &state->dst );\n               Core_PopIdentity();\n               return false;\n          }\n\n          /* If using a mask... */\n          if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) {\n               /* ...lock source mask for reading. */\n               ret = dfb_surface_lock_buffer2( state->source_mask, state->from, state->source_mask->flips,\n                                               state->from_eye, CSAID_GPU, CSAF_READ, &state->src_mask );\n               if (ret) {\n                    D_DEBUG_AT( Core_GfxState, \"  -> could not lock source mask for GPU access!\\n\" );\n                    dfb_surface_unlock_buffer( state->source, &state->src );\n                    dfb_surface_unlock_buffer( state->destination, &state->dst );\n                    Core_PopIdentity();\n                    return false;\n               }\n\n               state->flags |= CSF_SOURCE_MASK_LOCKED;\n          }\n\n          /* If using source2... */\n          if (accel == DFXL_BLIT2) {\n               /* ...lock source2 for reading. */\n               ret = dfb_surface_lock_buffer2( state->source2, state->from, state->source2->flips,\n                                               state->from_eye, CSAID_GPU, CSAF_READ, &state->src2 );\n               if (ret) {\n                    D_DEBUG_AT( Core_GfxState, \"  -> could not lock source2 for GPU access!\\n\" );\n\n                    if (state->flags & CSF_SOURCE_MASK_LOCKED) {\n                         dfb_surface_unlock_buffer( state->source_mask, &state->src_mask );\n                         state->flags &= ~CSF_SOURCE_MASK_LOCKED;\n                    }\n\n                    dfb_surface_unlock_buffer( state->source, &state->src );\n                    dfb_surface_unlock_buffer( state->destination, &state->dst );\n                    Core_PopIdentity();\n                    return false;\n               }\n\n               state->flags |= CSF_SOURCE2_LOCKED;\n          }\n\n          state->flags |= CSF_SOURCE_LOCKED;\n     }\n\n     /* Make sure that state setting with subsequent command execution isn't done by two processes simultaneously. */\n     ret = dfb_gfxcard_lock( GDLF_NONE );\n     if (ret) {\n          D_DERROR( ret, \"Core/GfxState: Could not lock GPU!\\n\" );\n\n          dfb_surface_unlock_buffer( state->destination, &state->dst );\n\n          if (state->flags & CSF_SOURCE_LOCKED) {\n               dfb_surface_unlock_buffer( state->source, &state->src );\n               state->flags &= ~CSF_SOURCE_LOCKED;\n          }\n\n          if (state->flags & CSF_SOURCE_MASK_LOCKED) {\n               dfb_surface_unlock_buffer( state->source_mask, &state->src_mask );\n               state->flags &= ~CSF_SOURCE_MASK_LOCKED;\n          }\n\n          if (state->flags & CSF_SOURCE2_LOCKED) {\n               dfb_surface_unlock_buffer( state->source2, &state->src2 );\n               state->flags &= ~CSF_SOURCE2_LOCKED;\n          }\n\n          Core_PopIdentity();\n\n          return false;\n     }\n\n     /* If we are switching to another state... */\n     if (state != shared->state || state->fusion_id != shared->holder) {\n          D_DEBUG_AT( Core_GfxState, \"  -> switch from %p [%lu] to %p [%lu]\\n\",\n                      shared->state, shared->holder, state, state->fusion_id );\n\n          /* ...set all modification bits and clear 'set' functions. */\n          state->mod_hw |= SMF_ALL;\n          state->set     = DFXL_NONE;\n\n          shared->state  = state;\n          shared->holder = state->fusion_id;\n     }\n\n     dfb_state_update( state, state->flags & (CSF_SOURCE_LOCKED | CSF_SOURCE2_LOCKED | CSF_SOURCE_MASK_LOCKED) );\n\n     D_DEBUG_AT( Core_GfxState, \"  -> modified 0x%08x, mod_hw 0x%08x\\n\", state->modified, state->mod_hw );\n\n     /* Move modification flags for drivers. */\n     state->mod_hw   |= state->modified;\n     state->modified  = SMF_ALL;\n\n     if (shared->last_allocation_id != state->dst.allocation->object.id) {\n          shared->last_allocation_id = state->dst.allocation->object.id;\n\n          /* Start command processing if not already running. */\n          if (!dfb_config->gfx_emit_early && shared->pending_ops && card->funcs.EmitCommands) {\n               dfb_gfxcard_switch_busy();\n\n               card->funcs.EmitCommands( card->driver_data, card->device_data );\n               shared->pending_ops = false;\n          }\n     }\n\n     /* If function hasn't been set or state is modified, call the driver function to propagate the state changes. */\n     D_DEBUG_AT( Core_GfxState, \"  -> mod_hw 0x%08x, set 0x%08x\\n\", state->mod_hw, state->set );\n     if (state->mod_hw || !(state->set & accel)) {\n          card->funcs.SetState( card->driver_data, card->device_data, &card->funcs, state, accel );\n          D_DEBUG_AT( Core_GfxState, \"  -> mod_hw 0x%08x, set 0x%08x\\n\", state->mod_hw, state->set );\n     }\n\n     state->modified = SMF_NONE;\n\n     return true;\n}\n\n/*\n * This function checks if acceleration is available for the specific function using the given state and returns\n * non zero after successful locking the surface(s) for access by hardware. Propagate state changes to driver.\n */\nstatic bool\ndfb_gfxcard_state_check_acquire( CardState           *state,\n                                 DFBAccelerationMask  accel )\n{\n     DFBResult               ret;\n     int                     cx2, cy2;\n     CoreSurfaceBuffer      *dst_buffer;\n     CoreSurfaceBuffer      *src_buffer;\n     DFBGraphicsCoreShared  *shared;\n     FusionSkirmish         *locks[4];\n     unsigned int            num_locks = 0;\n     CoreSurfaceAccessFlags  access    = CSAF_WRITE;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_MAGIC_ASSERT_IF( state->destination, CoreSurface );\n     D_MAGIC_ASSERT_IF( state->source, CoreSurface );\n     D_ASSERT( state->clip.x2 >= state->clip.x1 );\n     D_ASSERT( state->clip.y2 >= state->clip.y1 );\n     D_ASSERT( state->clip.x1 >= 0 );\n     D_ASSERT( state->clip.y1 >= 0 );\n\n     D_DEBUG_AT( Core_GraphicsOps, \"%s( %p, 0x%08x, %4d,%4d-%4d,%4d )\\n\", __FUNCTION__,\n                 state, accel, DFB_REGION_VALS( &state->clip ) );\n\n     shared = card->shared;\n\n     locks[num_locks++] = &state->destination->lock;\n\n     /* Find locking flags. */\n     if (DFB_BLITTING_FUNCTION( accel )) {\n          if (state->blittingflags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA | DSBLIT_DST_COLORKEY))\n               access |= CSAF_READ;\n     }\n     else if (state->drawingflags & (DSDRAW_BLEND | DSDRAW_DST_COLORKEY))\n          access |= CSAF_READ;\n\n     if (DFB_BLITTING_FUNCTION(accel)) {\n          D_DEBUG_AT( Core_GfxState, \"%s( %p, 0x%08x ) blitting %p -> %p\\n\", __FUNCTION__,\n                      state, accel, state->source, state->destination );\n\n          locks[num_locks++] = &state->source->lock;\n\n          /* If using a mask. */\n          if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR))\n               locks[num_locks++] = &state->source_mask->lock;\n\n          /* If using source2. */\n          if (accel == DFXL_BLIT2)\n               locks[num_locks++] = &state->source2->lock;\n     }\n     else {\n          D_DEBUG_AT( Core_GfxState, \"%s( %p, 0x%08x ) drawing -> %p\\n\", __FUNCTION__,\n                      state, accel, state->destination );\n     }\n\n     if (state->clip.x1 < 0) {\n          state->clip.x1   = 0;\n          state->modified |= SMF_CLIP;\n     }\n\n     if (state->clip.y1 < 0) {\n          state->clip.y1   = 0;\n          state->modified |= SMF_CLIP;\n     }\n\n     D_DEBUG_AT( Core_GfxState, \"  <- checked 0x%08x, accel 0x%08x, modified 0x%08x, mod_hw 0x%08x\\n\",\n                 state->checked, state->accel, state->modified, state->mod_hw );\n\n     /* Destination may have been destroyed. */\n     if (!state->destination) {\n          D_BUG( \"no destination\" );\n          return false;\n     }\n\n     /* Destination buffer may have been destroyed (suspended). i.e by a vt-switching */\n     if (state->destination->num_buffers == 0 )\n          return false;\n\n     if (DFB_BLITTING_FUNCTION( accel )) {\n          /* Source may have been destroyed. */\n          if (!state->source) {\n               D_BUG( \"no source\" );\n               return false;\n          }\n\n          /* Mask may have been destroyed. */\n          if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR) && !state->source_mask) {\n               D_BUG( \"no mask\" );\n               return false;\n          }\n\n          /* Source2 may have been destroyed. */\n          if (accel == DFXL_BLIT2 && !state->source2) {\n               D_BUG( \"no source2\" );\n               return false;\n          }\n     }\n\n     D_ASSUME( state->clip.x2 < state->destination->config.size.w );\n     D_ASSUME( state->clip.y2 < state->destination->config.size.h );\n\n     cx2 = state->destination->config.size.w - 1;\n     cy2 = state->destination->config.size.h - 1;\n\n     if (state->clip.x2 > cx2) {\n          state->clip.x2 = cx2;\n\n          if (state->clip.x1 > cx2)\n               state->clip.x1 = cx2;\n\n          state->modified |= SMF_CLIP;\n     }\n\n     if (state->clip.y2 > cy2) {\n          state->clip.y2 = cy2;\n\n          if (state->clip.y1 > cy2)\n               state->clip.y1 = cy2;\n\n          state->modified |= SMF_CLIP;\n     }\n\n     /* If there's no CheckState() function, there's no acceleration at all. */\n     if (!card->funcs.CheckState)\n          return false;\n\n     /* Check if this function has been disabled temporarily. */\n     if (state->disabled & accel)\n          return false;\n\n     if (core_dfb->shutdown_running)\n          return false;\n\n     if (fusion_skirmish_prevail_multi( locks, num_locks ))\n          return false;\n\n     dfb_state_update_destination( state );\n\n     /* If destination or blend functions have been changed... */\n     if (state->modified & (SMF_DESTINATION | SMF_SRC_BLEND | SMF_DST_BLEND | SMF_RENDER_OPTIONS)) {\n          /* ...force rechecking for all functions. */\n          state->checked = DFXL_NONE;\n\n          if (state->destination->config.size.w < card->limits.dst_min.w ||\n              state->destination->config.size.h < card->limits.dst_min.h ||\n              state->destination->config.size.w > card->limits.dst_max.w ||\n              state->destination->config.size.h > card->limits.dst_max.h) {\n               fusion_skirmish_dismiss_multi( locks, num_locks );\n               return false;\n          }\n     }\n     else {\n          /* If source/mask or blitting flags have been changed... */\n          if (state->modified & (SMF_SOURCE | SMF_BLITTING_FLAGS | SMF_SOURCE_MASK | SMF_SOURCE_MASK_VALS)) {\n               /* ...force rechecking for all blitting functions. */\n               state->checked &= ~DFXL_ALL_BLIT;\n          }\n          else if (state->modified & SMF_SOURCE2) {\n               /* Otherwise force rechecking for Blit2() function if source2 has been changed. */\n               state->checked &= ~DFXL_BLIT2;\n          }\n\n          /* If drawing flags have been changed... */\n          if (state->modified & SMF_DRAWING_FLAGS) {\n               /* ...force rechecking for all drawing functions. */\n               state->checked &= ~DFXL_ALL_DRAW;\n          }\n\n          if (state->source) {\n               if (state->source->config.size.w < card->limits.dst_min.w ||\n                   state->source->config.size.h < card->limits.dst_min.h ||\n                   state->source->config.size.w > card->limits.dst_max.w ||\n                   state->source->config.size.h > card->limits.dst_max.h) {\n                    fusion_skirmish_dismiss_multi( locks, num_locks );\n                    return false;\n               }\n          }\n     }\n\n     D_DEBUG_AT( Core_GfxState, \"  -> checked 0x%08x, accel 0x%08x, modified 0x%08x, mod_hw 0x%08x\\n\",\n                 state->checked, state->accel, state->modified, state->mod_hw );\n\n     if (DFB_BLITTING_FUNCTION(accel)) {\n          dfb_state_update_sources( state, CSF_SOURCE );\n\n          /* If using a mask. */\n          if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR))\n               dfb_state_update_sources( state, CSF_SOURCE_MASK );\n\n          /* If using source2. */\n          if (accel == DFXL_BLIT2)\n               dfb_state_update_sources( state, CSF_SOURCE2 );\n     }\n\n     /* If the function needs to be checked. */\n     if (!(state->checked & accel)) {\n          /* Unset unchecked functions. */\n          state->accel &= state->checked;\n\n          /* Call driver to (re)set the bit if the function is supported. */\n          card->funcs.CheckState( card->driver_data, card->device_data, state, accel );\n\n          /* Add the function to 'checked' functions. */\n          state->checked |= accel;\n\n          /* Add additional functions the driver might have checked, too. */\n          state->checked |= state->accel;\n     }\n\n     D_DEBUG_AT( Core_GfxState, \"  -> checked 0x%08x, accel 0x%08x, modified 0x%08x, mod_hw 0x%08x\\n\",\n                 state->checked, state->accel, state->modified, state->mod_hw );\n\n     /* Push our own identity for buffer locking calls (locality of accessor) */\n     Core_PushIdentity( 0 );\n\n     /* Move modification flags for drivers. */\n     state->mod_hw   |= state->modified;\n     state->modified  = SMF_NONE;\n\n     if (state->destination_flip_count_used)\n          dst_buffer = dfb_surface_get_buffer3( state->destination, state->to, state->to_eye,\n                                                state->destination_flip_count );\n     else\n          dst_buffer = dfb_surface_get_buffer3( state->destination, state->to, state->to_eye,\n                                                state->destination->flips );\n\n     D_MAGIC_ASSERT( dst_buffer, CoreSurfaceBuffer );\n\n     /* If back_buffer policy is 'system only' and the GPU does not fully support system memory surfaces, there's no\n        acceleration available. */\n     if ((dst_buffer->policy == CSP_SYSTEMONLY &&\n          !(card->caps.flags & CCF_READSYSMEM && card->caps.flags & CCF_WRITESYSMEM)) ||\n         (!(card->caps.flags & CCF_RENDEROPTS) && (state->render_options & DSRO_MATRIX))) {\n          /* Clear 'accelerated' functions. */\n          state->accel   = DFXL_NONE;\n          state->checked = DFXL_ALL;\n\n          Core_PopIdentity();\n          fusion_skirmish_dismiss_multi( locks, num_locks );\n          return false;\n     }\n\n     if (!(state->accel & accel)) {\n          D_DEBUG_AT( Core_GfxState, \"  -> not accelerated\\n\" );\n          Core_PopIdentity();\n          fusion_skirmish_dismiss_multi( locks, num_locks );\n          return false;\n     }\n\n     ret = dfb_surface_buffer_lock( dst_buffer, CSAID_GPU, access, &state->dst );\n     if (ret) {\n          D_DEBUG_AT( Core_GfxState, \"  -> could not lock destination for GPU access!\\n\" );\n          Core_PopIdentity();\n          fusion_skirmish_dismiss_multi( locks, num_locks );\n          return false;\n     }\n\n     if (DFB_BLITTING_FUNCTION( accel )) {\n          /* If the front buffer policy of the source is 'system only', no accelerated blitting is available. */\n          if (state->source_buffer)\n               src_buffer = state->source_buffer;\n          else if (state->source_flip_count_used)\n               src_buffer = dfb_surface_get_buffer3( state->source, state->from, state->from_eye,\n                                                     state->source_flip_count );\n          else\n               src_buffer = dfb_surface_get_buffer3( state->source, state->from, state->from_eye,\n                                                     state->source->flips );\n\n          D_MAGIC_ASSERT( src_buffer, CoreSurfaceBuffer );\n\n          if (src_buffer->policy == CSP_SYSTEMONLY && !(card->caps.flags & CCF_READSYSMEM)) {\n               D_DEBUG_AT( Core_GfxState, \"  -> cannot read source sysmem\\n\" );\n\n               /* Clear 'accelerated blitting' functions. */\n               state->accel   &= ~DFXL_ALL_BLIT;\n               state->checked |=  DFXL_ALL_BLIT;\n          }\n\n          ret = dfb_surface_buffer_lock( src_buffer, CSAID_GPU, CSAF_READ, &state->src );\n          if (ret) {\n               D_DEBUG_AT( Core_GfxState, \"  -> could not lock source for GPU access!\\n\" );\n               dfb_surface_unlock_buffer( state->destination, &state->dst );\n               Core_PopIdentity();\n               fusion_skirmish_dismiss_multi( locks, num_locks );\n               return false;\n          }\n\n          /* If using a mask... */\n          if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) {\n               /* ...lock source mask for reading */\n               ret = dfb_surface_lock_buffer2( state->source_mask, state->from, state->source_mask->flips,\n                                               state->from_eye, CSAID_GPU, CSAF_READ, &state->src_mask );\n               if (ret) {\n                    D_DEBUG_AT( Core_GfxState, \"  -> could not lock source mask for GPU access!\\n\" );\n                    dfb_surface_unlock_buffer( state->source, &state->src );\n                    dfb_surface_unlock_buffer( state->destination, &state->dst );\n                    Core_PopIdentity();\n                    fusion_skirmish_dismiss_multi( locks, num_locks );\n                    return false;\n               }\n\n               state->flags |= CSF_SOURCE_MASK_LOCKED;\n          }\n\n          /* If using source2... */\n          if (accel == DFXL_BLIT2) {\n               /* ...lock source2 for reading */\n               ret = dfb_surface_lock_buffer2( state->source2, state->from, state->source2->flips,\n                                               state->from_eye, CSAID_GPU, CSAF_READ, &state->src2 );\n               if (ret) {\n                    D_DEBUG_AT( Core_GfxState, \"  -> could not lock source2 for GPU access!\\n\" );\n                    if (state->flags & CSF_SOURCE_MASK_LOCKED) {\n                         dfb_surface_unlock_buffer( state->source_mask, &state->src_mask );\n                         state->flags &= ~CSF_SOURCE_MASK_LOCKED;\n                    }\n                    dfb_surface_unlock_buffer( state->source, &state->src );\n                    dfb_surface_unlock_buffer( state->destination, &state->dst );\n                    Core_PopIdentity();\n                    fusion_skirmish_dismiss_multi( locks, num_locks );\n                    return false;\n               }\n\n               state->flags |= CSF_SOURCE2_LOCKED;\n          }\n\n          state->flags |= CSF_SOURCE_LOCKED;\n     }\n\n     fusion_skirmish_dismiss_multi( locks, num_locks );\n\n     D_DEBUG_AT( Core_GfxState, \"  -> checked 0x%08x, accel 0x%08x, modified 0x%08x, mod_hw 0x%08x\\n\",\n                 state->checked, state->accel, state->modified, state->mod_hw );\n\n     /* Make sure that state setting with subsequent command execution isn't done by two processes simultaneously. */\n     if (dfb_gfxcard_lock( GDLF_NONE )) {\n          D_DERROR( ret, \"Core/GfxState: Could not lock GPU!\\n\" );\n\n          dfb_surface_unlock_buffer( state->destination, &state->dst );\n\n          if (state->flags & CSF_SOURCE_LOCKED) {\n               dfb_surface_unlock_buffer( state->source, &state->src );\n               state->flags &= ~CSF_SOURCE_LOCKED;\n          }\n\n          if (state->flags & CSF_SOURCE_MASK_LOCKED) {\n               dfb_surface_unlock_buffer( state->source_mask, &state->src_mask );\n               state->flags &= ~CSF_SOURCE_MASK_LOCKED;\n          }\n\n          if (state->flags & CSF_SOURCE2_LOCKED) {\n               dfb_surface_unlock_buffer( state->source2, &state->src2 );\n               state->flags &= ~CSF_SOURCE2_LOCKED;\n          }\n\n          Core_PopIdentity();\n\n          return false;\n     }\n\n     /* If we are switching to another state... */\n     if (state != shared->state || state->fusion_id != shared->holder) {\n          D_DEBUG_AT( Core_GfxState, \"  -> switch from %p [%lu] to %p [%lu]\\n\",\n                      shared->state, shared->holder, state, state->fusion_id );\n\n          /* ...set all modification bits and clear 'set' functions. */\n          state->mod_hw |= SMF_ALL;\n          state->set     = DFXL_NONE;\n\n          shared->state  = state;\n          shared->holder = state->fusion_id;\n     }\n\n     D_DEBUG_AT( Core_GfxState, \"  -> modified 0x%08x, mod_hw 0x%08x\\n\", state->modified, state->mod_hw );\n\n     /* Move modification flags for drivers. */\n     state->mod_hw   |= state->modified;\n     state->modified  = SMF_ALL;\n\n     if (shared->last_allocation_id != state->dst.allocation->object.id) {\n          shared->last_allocation_id = state->dst.allocation->object.id;\n\n          /* Start command processing if not already running. */\n          if (!dfb_config->gfx_emit_early && shared->pending_ops && card->funcs.EmitCommands) {\n               dfb_gfxcard_switch_busy();\n\n               card->funcs.EmitCommands( card->driver_data, card->device_data );\n               shared->pending_ops = false;\n          }\n     }\n\n     /* If function hasn't been set or state is modified, call the driver function to propagate the state changes. */\n     D_DEBUG_AT( Core_GfxState, \"  -> mod_hw 0x%08x, set 0x%08x\\n\", state->mod_hw, state->set );\n     if (state->mod_hw || !(state->set & accel)) {\n          card->funcs.SetState( card->driver_data, card->device_data, &card->funcs, state, accel );\n          D_DEBUG_AT( Core_GfxState, \"  -> mod_hw 0x%08x, set 0x%08x\\n\", state->mod_hw, state->set );\n     }\n\n     state->modified = SMF_NONE;\n\n     return true;\n}\n\n/*\n * Unlock destination and possibly the source.\n */\nstatic void\ndfb_gfxcard_state_release( CardState *state )\n{\n     DFBGraphicsCoreShared *shared;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( state->destination != NULL );\n\n     shared = card->shared;\n\n     if (!dfb_config->software_only) {\n          /* Store the serial of the operation. */\n          if (card->funcs.GetSerial)\n               card->funcs.GetSerial( card->driver_data, card->device_data, &state->dst.allocation->gfx_serial );\n\n          if (dfb_config->gfx_emit_early && card->funcs.EmitCommands) {\n               dfb_gfxcard_switch_busy();\n\n               card->funcs.EmitCommands( card->driver_data, card->device_data );\n               shared->pending_ops = false;\n          }\n          else\n               shared->pending_ops = true;\n     }\n\n     /* Allow others to use the hardware. */\n     dfb_gfxcard_unlock();\n\n     /* Destination always gets locked during acquisition. */\n     dfb_surface_unlock_buffer( state->destination, &state->dst );\n\n     if (state->flags & CSF_SOURCE_LOCKED) {\n          dfb_surface_unlock_buffer( state->source, &state->src );\n\n          state->flags &= ~CSF_SOURCE_LOCKED;\n     }\n\n     if (state->flags & CSF_SOURCE_MASK_LOCKED) {\n          dfb_surface_unlock_buffer( state->source_mask, &state->src_mask );\n\n          state->flags &= ~CSF_SOURCE_MASK_LOCKED;\n     }\n\n     if (state->flags & CSF_SOURCE2_LOCKED) {\n          dfb_surface_unlock_buffer( state->source2, &state->src2 );\n\n          state->flags &= ~CSF_SOURCE2_LOCKED;\n     }\n\n     Core_PopIdentity();\n}\n\nvoid\ndfb_gfxcard_state_init ( CardState *state )\n{\n     D_MAGIC_ASSERT( state, CardState );\n\n     if (dfb_config->software_only)\n          return;\n\n     if (card) {\n          D_ASSERT( card != NULL );\n          D_ASSERT( card->shared != NULL );\n\n          if (card->funcs.StateInit)\n               card->funcs.StateInit( card->driver_data, card->device_data, state );\n     }\n}\n\nvoid\ndfb_gfxcard_state_destroy ( CardState *state )\n{\n     D_MAGIC_ASSERT( state, CardState );\n\n     if (state->gfxs) {\n          GenefxState *gfxs = state->gfxs;\n\n          if (gfxs->ABstart)\n               D_FREE( gfxs->ABstart );\n\n          D_FREE( gfxs );\n     }\n\n     if (dfb_config->software_only)\n          return;\n\n     if (card) {\n          D_ASSERT( card != NULL );\n          D_ASSERT( card->shared != NULL );\n\n          if (card->funcs.StateDestroy)\n               card->funcs.StateDestroy( card->driver_data, card->device_data, state );\n     }\n}\n\n/**********************************************************************************************************************/\n\n#define DFB_TRANSFORM(x,y,m,affine)                                   \\\ndo {                                                                  \\\n     s32 _x, _y, _w;                                                  \\\n     if (affine) {                                                    \\\n          _x = ((x) * (m)[0] + (y) * (m)[1] + (m)[2] + 0x8000) >> 16; \\\n          _y = ((x) * (m)[3] + (y) * (m)[4] + (m)[5] + 0x8000) >> 16; \\\n     }                                                                \\\n     else {                                                           \\\n          _x = ((x) * (m)[0] + (y) * (m)[1] + (m)[2]);                \\\n          _y = ((x) * (m)[3] + (y) * (m)[4] + (m)[5]);                \\\n          _w = ((x) * (m)[6] + (y) * (m)[7] + (m)[8]);                \\\n          if (!_w) {                                                  \\\n               _x = (_x < 0) ? -0x7fffffff : 0x7fffffff;              \\\n               _y = (_y < 0) ? -0x7fffffff : 0x7fffffff;              \\\n          }                                                           \\\n          else {                                                      \\\n               _x /= _w;                                              \\\n               _y /= _w;                                              \\\n          }                                                           \\\n     }                                                                \\\n     (x) = _x;                                                        \\\n     (y) = _y;                                                        \\\n} while (0)\n\ntypedef struct {\n   int xi;\n   int xf;\n   int mi;\n   int mf;\n   int _2dy;\n} DDA;\n\n#define SETUP_DDA(xs,ys,xe,ye,dda)           \\\n     do {                                    \\\n          int dx = (xe) - (xs);              \\\n          int dy = (ye) - (ys);              \\\n          dda.xi = (xs);                     \\\n          if (dy != 0) {                     \\\n               dda.mi = dx / dy;             \\\n               dda.mf = 2 * (dx % dy);       \\\n               dda.xf = -dy;                 \\\n               dda._2dy = 2 * dy;            \\\n               if (dda.mf < 0) {             \\\n                    dda.mf += 2 * ABS( dy ); \\\n                    dda.mi--;                \\\n               }                             \\\n          }                                  \\\n          else {                             \\\n               dda.mi = 0;                   \\\n               dda.mf = 0;                   \\\n               dda.xf = 0;                   \\\n               dda._2dy = 0;                 \\\n          }                                  \\\n     } while (0)\n\n#define INC_DDA(dda)                         \\\n     do {                                    \\\n          dda.xi += dda.mi;                  \\\n          dda.xf += dda.mf;                  \\\n          if (dda.xf > 0) {                  \\\n               dda.xi++;                     \\\n               dda.xf -= dda._2dy;           \\\n          }                                  \\\n     } while (0)\n\nstatic void\nfill_tri( DFBTriangle *tri,\n          CardState   *state,\n          bool         accelerated )\n{\n     int y, yend;\n     DDA dda1    = { .xi = 0 };\n     DDA dda2    = { .xi = 0 };\n     int clip_x1 = state->clip.x1;\n     int clip_x2 = state->clip.x2;\n\n     D_MAGIC_ASSERT( state, CardState );\n\n     y = tri->y1;\n     yend = tri->y3;\n\n     if (yend > state->clip.y2)\n          yend = state->clip.y2;\n\n     SETUP_DDA( tri->x1, tri->y1, tri->x3, tri->y3, dda1 );\n     SETUP_DDA( tri->x1, tri->y1, tri->x2, tri->y2, dda2 );\n\n     while (y <= yend) {\n          DFBRectangle rect;\n\n          if (y == tri->y2) {\n               if (tri->y2 == tri->y3)\n                    return;\n               SETUP_DDA( tri->x2, tri->y2, tri->x3, tri->y3, dda2 );\n          }\n\n          rect.w = ABS( dda1.xi - dda2.xi );\n          rect.x = MIN( dda1.xi, dda2.xi );\n\n          if (clip_x2 < rect.x + rect.w)\n               rect.w = clip_x2 - rect.x + 1;\n\n          if (rect.w > 0) {\n               if (clip_x1 > rect.x) {\n                    rect.w -= (clip_x1 - rect.x);\n                    rect.x = clip_x1;\n               }\n               rect.y = y;\n               rect.h = 1;\n\n               if (rect.w > 0 && rect.y >= state->clip.y1) {\n                    if (accelerated)\n                         card->funcs.FillRectangle( card->driver_data, card->device_data, &rect );\n                    else\n                         gFillRectangle( state, &rect );\n               }\n          }\n\n          INC_DDA( dda1 );\n          INC_DDA( dda2 );\n\n          y++;\n     }\n}\n\nvoid\ndfb_gfxcard_fillrectangles( DFBRectangle *rects,\n                            int           num,\n                            CardState    *state )\n{\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( rects != NULL );\n     D_ASSERT( num > 0 );\n\n     D_DEBUG_AT( Core_GraphicsOps, \"%s( %p [%d], %p )\\n\", __FUNCTION__, rects, num, state );\n\n     /* The state is locked during graphics operations. */\n     dfb_state_lock( state );\n\n     /* Signal beginning of sequence of operations if not already done. */\n     dfb_state_start_drawing( state );\n\n     if (!(state->render_options & DSRO_MATRIX)) {\n          while (num > 0) {\n               if (dfb_rectangle_region_intersects( rects, &state->clip ))\n                    break;\n\n               rects++;\n               num--;\n          }\n     }\n\n     if (num > 0) {\n          DFBRectangle rect;\n          int          i = 0;\n\n          /* Check for acceleration and setup execution. */\n          if (dfb_gfxcard_state_check_acquire( state, DFXL_FILLRECTANGLE )) {\n               /* Now everything is prepared for execution of the FillRectangle() driver function.  */\n               for (; i < num; i++) {\n                    if (!(state->render_options & DSRO_MATRIX) &&\n                        !dfb_rectangle_region_intersects( &rects[i], &state->clip ))\n                         continue;\n\n                    rect = rects[i];\n\n                    if (rect.w > card->limits.dst_max.w || rect.h > card->limits.dst_max.h) {\n                         dfb_clip_rectangle( &state->clip, &rect );\n\n                         if (rect.w > card->limits.dst_max.w || rect.h > card->limits.dst_max.h) {\n                              D_DEBUG_AT( Core_GraphicsOps, \"  -> driver limits prevent hw operation\\n\" );\n                              break;\n                         }\n                    }\n                    else if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&\n                             !D_FLAGS_IS_SET( card->caps.clip, DFXL_FILLRECTANGLE ))\n                         dfb_clip_rectangle( &state->clip, &rect );\n\n                    if (!card->funcs.FillRectangle( card->driver_data, card->device_data, &rect )) {\n                         D_DEBUG_AT( Core_GraphicsOps, \"  -> driver returned false\\n\" );\n                         break;\n                    }\n               }\n\n               /* Release after state acquisition. */\n               dfb_gfxcard_state_release( state );\n          }\n\n          if (i < num) {\n               D_DEBUG_AT( Core_GraphicsOps, \"  -> using software fallback\\n\" );\n\n               /* Use software fallback. */\n               if (!(state->render_options & DSRO_MATRIX)) {\n                    if (gAcquire( state, DFXL_FILLRECTANGLE )) {\n                         for (; i < num; i++) {\n                              rect = rects[i];\n\n                              if (dfb_clip_rectangle( &state->clip, &rect ))\n                                   gFillRectangle( state, &rect );\n                         }\n\n                         gRelease( state );\n                    }\n               }\n               else if (state->matrix[1] == 0 && state->matrix[3] == 0) {\n                    /* Scaled/Translated rectangles. */\n                    DFBRectangle tr[num];\n                    int          n = 0;\n\n                    for (; i < num; i++) {\n                         int x1, y1, x2, y2;\n\n                         x1 = rects[i].x;      y1 = rects[i].y;\n                         x2 = x1 + rects[i].w; y2 = y1 + rects[i].h;\n                         DFB_TRANSFORM( x1, y1, state->matrix, state->affine_matrix );\n                         DFB_TRANSFORM( x2, y2, state->matrix, state->affine_matrix );\n\n                         if (x1 < x2) {\n                              tr[n].x = x1;\n                              tr[n].w = x2 - x1;\n                         }\n                         else {\n                              tr[n].x = x2;\n                              tr[n].w = x1 - x2;\n                         }\n                         if (y1 < y2) {\n                              tr[n].y = y1;\n                              tr[n].h = y2 - y1;\n                         }\n                         else {\n                              tr[n].y = y2;\n                              tr[n].h = y1 - y2;\n                         }\n\n                         if (dfb_clip_rectangle( &state->clip, &tr[n] ))\n                              n++;\n                    }\n\n                    if (n > 0) {\n                         state->render_options &= ~DSRO_MATRIX;\n                         state->modified       |= SMF_RENDER_OPTIONS;\n\n                         dfb_gfxcard_fillrectangles( tr, n, state );\n\n                         state->render_options |= DSRO_MATRIX;\n                         state->modified       |= SMF_RENDER_OPTIONS;\n                    }\n               }\n               else {\n                    /* Rotated rectangle: split into triangles. */\n                    if (gAcquire( state, DFXL_FILLRECTANGLE )) {\n                         for (; i < num; i++) {\n                              DFBTriangle tri;\n\n                              tri.x1 = rects[i].x;              tri.y1 = rects[i].y;\n                              tri.x2 = rects[i].x + rects[i].w; tri.y2 = rects[i].y;\n                              tri.x3 = rects[i].x + rects[i].w; tri.y3 = rects[i].y + rects[i].h;\n                              DFB_TRANSFORM( tri.x1, tri.y1, state->matrix, state->affine_matrix );\n                              DFB_TRANSFORM( tri.x2, tri.y2, state->matrix, state->affine_matrix );\n                              DFB_TRANSFORM( tri.x3, tri.y3, state->matrix, state->affine_matrix );\n\n                              dfb_sort_triangle( &tri );\n                              if (tri.y3 - tri.y1 > 0)\n                                   fill_tri( &tri, state, false );\n\n                              tri.x1 = rects[i].x;              tri.y1 = rects[i].y;\n                              tri.x2 = rects[i].x + rects[i].w; tri.y2 = rects[i].y + rects[i].h;\n                              tri.x3 = rects[i].x;              tri.y3 = rects[i].y + rects[i].h;\n                              DFB_TRANSFORM( tri.x1, tri.y1, state->matrix, state->affine_matrix );\n                              DFB_TRANSFORM( tri.x2, tri.y2, state->matrix, state->affine_matrix );\n                              DFB_TRANSFORM( tri.x3, tri.y3, state->matrix, state->affine_matrix );\n\n                              dfb_sort_triangle( &tri );\n                              if (tri.y3 - tri.y1 > 0)\n                                   fill_tri( &tri, state, false );\n                         }\n\n                         gRelease( state );\n                    }\n               }\n          }\n     }\n\n     /* Unlock after execution. */\n     dfb_state_unlock( state );\n}\n\nvoid\ndfb_gfxcard_drawrectangle( DFBRectangle *rect,\n                           CardState    *state )\n{\n     DFBRectangle rects[4];\n     bool         hw  = false;\n     int          i   = 0;\n     int          num = 0;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n     DFB_RECTANGLE_ASSERT( rect );\n\n     D_DEBUG_AT( Core_GraphicsOps, \"%s( %4d,%4d-%4dx%4d, %p )\\n\", __FUNCTION__, DFB_RECTANGLE_VALS( rect ), state );\n\n     /* The state is locked during graphics operations. */\n     dfb_state_lock( state );\n\n     /* Signal beginning of sequence of operations if not already done. */\n     dfb_state_start_drawing( state );\n\n     if (!(state->render_options & DSRO_MATRIX) &&\n         !dfb_rectangle_region_intersects( rect, &state->clip )) {\n          dfb_state_unlock( state );\n          return;\n     }\n\n     if (D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING )      ||\n         D_FLAGS_IS_SET( card->caps.clip, DFXL_DRAWRECTANGLE ) ||\n         !dfb_clip_needed( &state->clip, rect )) {\n          if (rect->w <= card->limits.dst_max.w && rect->h <= card->limits.dst_max.h &&\n              dfb_gfxcard_state_check_acquire( state, DFXL_DRAWRECTANGLE )) {\n               hw = card->funcs.DrawRectangle( card->driver_data, card->device_data, rect );\n               dfb_gfxcard_state_release( state );\n          }\n     }\n\n     if (!hw && !(state->render_options & DSRO_MATRIX)) {\n          dfb_build_clipped_rectangle_outlines( rect, &state->clip, rects, &num );\n\n          if (!num) {\n               dfb_state_unlock( state );\n               return;\n          }\n\n          if (dfb_gfxcard_state_check_acquire( state, DFXL_FILLRECTANGLE )) {\n               for (; i < num; i++) {\n                    hw = rects[i].w <= card->limits.dst_max.w && rects[i].h <= card->limits.dst_max.h &&\n                         card->funcs.FillRectangle( card->driver_data, card->device_data, &rects[i] );\n                    if (!hw)\n                         break;\n               }\n\n               dfb_gfxcard_state_release( state );\n          }\n     }\n\n     if (!hw) {\n          if (!(state->render_options & DSRO_MATRIX)) {\n               if (gAcquire( state, DFXL_FILLRECTANGLE )) {\n                    for (; i < num; i++)\n                         gFillRectangle( state, &rects[i] );\n\n                    gRelease( state );\n               }\n          }\n          else {\n                if (gAcquire( state, DFXL_DRAWLINE )) {\n                    int       x1, x2, x3, x4;\n                    int       y1, y2, y3, y4;\n                    DFBRegion line;\n\n                    x1 = rect->x;           y1 = rect->y;\n                    x2 = rect->x + rect->w; y2 = rect->y;\n                    x3 = rect->x + rect->w; y3 = rect->y + rect->h;\n                    x4 = rect->x;           y4 = rect->y + rect->h;\n                    DFB_TRANSFORM( x1, y1, state->matrix, state->affine_matrix );\n                    DFB_TRANSFORM( x2, y2, state->matrix, state->affine_matrix );\n                    DFB_TRANSFORM( x3, y3, state->matrix, state->affine_matrix );\n                    DFB_TRANSFORM( x4, y4, state->matrix, state->affine_matrix );\n\n                    line = (DFBRegion) { x1, y1, x2, y2 };\n                    if (dfb_clip_line( &state->clip, &line ))\n                         gDrawLine( state, &line );\n\n                    line = (DFBRegion) { x2, y2, x3, y3 };\n                    if (dfb_clip_line( &state->clip, &line ))\n                         gDrawLine( state, &line );\n\n                    line = (DFBRegion) { x3, y3, x4, y4 };\n                    if (dfb_clip_line( &state->clip, &line ))\n                         gDrawLine( state, &line );\n\n                    line = (DFBRegion) { x4, y4, x1, y1 };\n                    if (dfb_clip_line( &state->clip, &line ))\n                         gDrawLine( state, &line );\n\n                    gRelease( state );\n               }\n          }\n     }\n\n     dfb_state_unlock( state );\n}\n\nvoid\ndfb_gfxcard_drawlines( DFBRegion *lines,\n                       int        num,\n                       CardState *state )\n{\n     int i = 0;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( lines != NULL );\n     D_ASSERT( num > 0 );\n\n     D_DEBUG_AT( Core_GraphicsOps, \"%s( %p [%d], %p )\\n\", __FUNCTION__, lines, num, state );\n\n     /* The state is locked during graphics operations. */\n     dfb_state_lock( state );\n\n     /* Signal beginning of sequence of operations if not already done. */\n     dfb_state_start_drawing( state );\n\n     if (dfb_gfxcard_state_check_acquire( state, DFXL_DRAWLINE )) {\n          for (; i < num; i++) {\n               if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&\n                   !D_FLAGS_IS_SET( card->caps.clip, DFXL_DRAWLINE ) &&\n                   !dfb_clip_line( &state->clip, &lines[i] ))\n                    continue;\n\n               if (!card->funcs.DrawLine( card->driver_data, card->device_data, &lines[i] ))\n                    break;\n          }\n\n          dfb_gfxcard_state_release( state );\n     }\n\n     if (i < num) {\n          if (gAcquire( state, DFXL_DRAWLINE )) {\n               for (; i < num; i++) {\n                    if (state->render_options & DSRO_MATRIX) {\n                         DFB_TRANSFORM( lines[i].x1, lines[i].y1, state->matrix, state->affine_matrix );\n                         DFB_TRANSFORM( lines[i].x2, lines[i].y2, state->matrix, state->affine_matrix );\n                    }\n\n                    if (dfb_clip_line( &state->clip, &lines[i] ))\n                         gDrawLine( state, &lines[i] );\n               }\n\n               gRelease( state );\n          }\n     }\n\n     dfb_state_unlock( state );\n}\n\nvoid\ndfb_gfxcard_filltriangles( DFBTriangle *tris,\n                           int          num,\n                           CardState   *state )\n{\n     bool hw = false;\n     int  i  = 0;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( tris != NULL );\n     D_ASSERT( num > 0 );\n\n     D_DEBUG_AT( Core_GraphicsOps, \"%s( %p [%d], %p )\\n\", __FUNCTION__, tris, num, state );\n\n     /* The state is locked during graphics operations. */\n     dfb_state_lock( state );\n\n     /* Signal beginning of sequence of operations if not already done. */\n     dfb_state_start_drawing( state );\n\n     if (dfb_gfxcard_state_check_acquire( state, DFXL_FILLTRIANGLE )) {\n          if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&\n              !D_FLAGS_IS_SET( card->caps.clip, DFXL_FILLTRIANGLE )) {\n               DFBPoint p[6];\n               int      n;\n\n               for (; i < num; i++) {\n                    if (dfb_clip_triangle( &state->clip, &tris[i], p, &n )) {\n                         DFBTriangle tri;\n                         int         j;\n\n                         tri.x1 = p[0].x; tri.y1 = p[0].y;\n                         tri.x2 = p[1].x; tri.y2 = p[1].y;\n                         tri.x3 = p[2].x; tri.y3 = p[2].y;\n                         hw = card->funcs.FillTriangle( card->driver_data, card->device_data, &tri );\n                         if (!hw) {\n                              D_DEBUG_AT( Core_GraphicsOps, \"  -> driver returned false\\n\" );\n                              break;\n                         }\n\n                         for (j = 3; j < n; j++) {\n                              tri.x1 = p[0].x;   tri.y1 = p[0].y;\n                              tri.x2 = p[j-1].x; tri.y2 = p[j-1].y;\n                              tri.x3 = p[j].x;   tri.y3 = p[j].y;\n                              hw = card->funcs.FillTriangle( card->driver_data, card->device_data, &tri );\n                              if (!hw) {\n                                   D_DEBUG_AT( Core_GraphicsOps, \"  -> driver returned false\\n\" );\n                                   break;\n                              }\n                         }\n                    }\n               }\n          }\n          else {\n               for (; i < num; i++) {\n                    DFBTriangle tri = tris[i];\n\n                    hw = card->funcs.FillTriangle( card->driver_data, card->device_data, &tri );\n                    if (!hw) {\n                         D_DEBUG_AT( Core_GraphicsOps, \"  -> driver returned false\\n\" );\n                         break;\n                    }\n               }\n\n          }\n\n          dfb_gfxcard_state_release( state );\n     }\n\n     if (!hw && i < num) {\n          D_DEBUG_AT( Core_GraphicsOps, \"  -> using software fallback\\n\" );\n\n          /* Try hardware accelerated rectangle filling. */\n          if (!(card->caps.flags & CCF_NOTRIEMU) &&\n              dfb_gfxcard_state_check_acquire( state, DFXL_FILLRECTANGLE )) {\n               for (; i < num; i++) {\n                    DFBTriangle tri = tris[i];\n\n                    dfb_sort_triangle( &tri );\n\n                    if (tri.y3 - tri.y1 > 0)\n                         fill_tri( &tri, state, true );\n               }\n\n               dfb_gfxcard_state_release( state );\n          }\n          else if (gAcquire( state, DFXL_FILLRECTANGLE )) {\n               for (; i < num; i++) {\n                    DFBTriangle tri = tris[i];\n\n                    if (state->render_options & DSRO_MATRIX) {\n                         DFB_TRANSFORM( tri.x1, tri.y1, state->matrix, state->affine_matrix );\n                         DFB_TRANSFORM( tri.x2, tri.y2, state->matrix, state->affine_matrix );\n                         DFB_TRANSFORM( tri.x3, tri.y3, state->matrix, state->affine_matrix );\n                    }\n\n                    dfb_sort_triangle( &tri );\n\n                    if (tri.y3 - tri.y1 > 0)\n                         fill_tri( &tri, state, false );\n               }\n\n               gRelease( state );\n          }\n     }\n\n     dfb_state_unlock( state );\n}\n\nstatic void\nfill_trap( DFBTrapezoid *trap,\n           CardState    *state,\n           bool          accelerated )\n{\n     int y, yend;\n     DDA dda1    = { .xi = 0 };\n     DDA dda2    = { .xi = 0 };\n     int clip_x1 = state->clip.x1;\n     int clip_x2 = state->clip.x2;\n\n     D_MAGIC_ASSERT( state, CardState );\n\n     y = trap->y1;\n     yend = trap->y2;\n\n     if (yend > state->clip.y2)\n          yend = state->clip.y2;\n\n     /* Top left to bottom left. */\n     SETUP_DDA( trap->x1,                trap->y1, trap->x2,                trap->y2, dda1 );\n     /* Top right to bottom right. */\n     SETUP_DDA( trap->x1 + trap->w1 - 1, trap->y1, trap->x2 + trap->w2 - 1, trap->y2, dda2 );\n\n     while (y <= yend) {\n          DFBRectangle rect;\n\n          rect.w = ABS( dda1.xi - dda2.xi );\n          rect.x = MIN( dda1.xi, dda2.xi );\n\n          if (clip_x2 < rect.x + rect.w)\n               rect.w = clip_x2 - rect.x + 1;\n\n          if (rect.w > 0) {\n               if (clip_x1 > rect.x) {\n                    rect.w -= (clip_x1 - rect.x);\n                    rect.x = clip_x1;\n               }\n               rect.y = y;\n               rect.h = 1;\n\n               if (rect.w > 0 && rect.y >= state->clip.y1) {\n                    if (accelerated)\n                         card->funcs.FillRectangle( card->driver_data, card->device_data, &rect );\n                    else\n                         gFillRectangle( state, &rect );\n               }\n          }\n\n          INC_DDA( dda1 );\n          INC_DDA( dda2 );\n\n          y++;\n     }\n}\n\nvoid\ndfb_gfxcard_filltrapezoids( DFBTrapezoid *traps,\n                            int           num,\n                            CardState    *state )\n{\n     bool hw = false;\n     int  i  = 0;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( traps != NULL );\n     D_ASSERT( num > 0 );\n\n     D_DEBUG_AT( Core_GraphicsOps, \"%s( %p [%d], %p )\\n\", __FUNCTION__, traps, num, state );\n\n     /* The state is locked during graphics operations. */\n     dfb_state_lock( state );\n\n     /* Signal beginning of sequence of operations if not already done. */\n     dfb_state_start_drawing( state );\n\n     if (dfb_gfxcard_state_check_acquire( state, DFXL_FILLTRAPEZOID )) {\n          if (D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING )      ||\n              D_FLAGS_IS_SET( card->caps.clip, DFXL_FILLTRAPEZOID ) ||\n              (state->render_options & DSRO_MATRIX)) {\n               for (; i < num; i++) {\n                    DFBTrapezoid trap = traps[i];\n\n                    hw = card->funcs.FillTrapezoid( card->driver_data, card->device_data, &trap );\n                    if (!hw)\n                         break;\n               }\n\n          }\n\n          dfb_gfxcard_state_release( state );\n     }\n\n     /* Otherwise use two triangles. */\n     if (!hw && i < num) {\n          if (dfb_gfxcard_state_check_acquire( state, DFXL_FILLTRIANGLE )) {\n               for (; i < num; i++) {\n                    bool tri1_failed = true;\n                    bool tri2_failed = true;\n\n                    DFBTriangle tri1 = { traps[i].x1,                   traps[i].y1,\n                                         traps[i].x1 + traps[i].w1 - 1, traps[i].y1,\n                                         traps[i].x2,                   traps[i].y2 };\n\n                    DFBTriangle tri2 = { traps[i].x1 + traps[i].w1 - 1, traps[i].y1,\n                                         traps[i].x2,                   traps[i].y2,\n                                         traps[i].x2 + traps[i].w2 - 1, traps[i].y2 };\n\n                    if (D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING )     ||\n                        D_FLAGS_IS_SET( card->caps.clip, DFXL_FILLTRIANGLE ) ||\n                        (state->render_options & DSRO_MATRIX)) {\n                         tri1_failed = !card->funcs.FillTriangle( card->driver_data, card->device_data, &tri1 );\n                         tri2_failed = !card->funcs.FillTriangle( card->driver_data, card->device_data, &tri2 );\n                    }\n\n                    if (tri1_failed || tri2_failed) {\n                         dfb_gfxcard_state_release( state );\n\n                         if (gAcquire( state, DFXL_FILLTRIANGLE )) {\n                              if (state->render_options & DSRO_MATRIX) {\n                                   /* Transform first triangle completely. */\n                                   if (tri1_failed || tri2_failed) {\n                                        DFB_TRANSFORM( tri1.x1, tri1.y1, state->matrix, state->affine_matrix );\n                                        DFB_TRANSFORM( tri1.x2, tri1.y2, state->matrix, state->affine_matrix );\n                                        DFB_TRANSFORM( tri1.x3, tri1.y3, state->matrix, state->affine_matrix );\n                                   }\n\n                                   /* Transform last coordinate of first triangle, and assign first ones from first. */\n                                   if (tri2_failed) {\n                                        DFB_TRANSFORM( tri2.x3, tri2.y3, state->matrix, state->affine_matrix );\n                                        tri2.x1 = tri1.x2;\n                                        tri2.y1 = tri1.y2;\n                                        tri2.x2 = tri1.x3;\n                                        tri2.x2 = tri1.y3;\n                                   }\n\n                                   /* Sort triangles (matrix could have rotated them). */\n                                   dfb_sort_triangle( &tri1 );\n                                   dfb_sort_triangle( &tri2 );\n                              }\n\n                              if (tri1_failed && (tri1.y3 - tri1.y1 > 0))\n                                   fill_tri( &tri1, state, false );\n\n                              if (tri2_failed && (tri2.y3 - tri2.y1 > 0))\n                                   fill_tri( &tri2, state, false );\n\n                              gRelease( state );\n                         }\n\n                         dfb_gfxcard_state_acquire( state, DFXL_FILLTRIANGLE );\n                    }\n               }\n\n               dfb_gfxcard_state_release( state );\n          }\n          else if (gAcquire( state, DFXL_FILLTRIANGLE )) {\n               for (; i < num; i++) {\n                    DFBTrapezoid trap = traps[i];\n                    dfb_sort_trapezoid( &trap );\n\n                    if (state->render_options & DSRO_MATRIX) {\n                         /* Split into triangles, for easier rotation. */\n                         DFBTriangle tri1 = { trap.x1,                   traps[i].y1,\n                                              trap.x1 + traps[i].w1 - 1, traps[i].y1,\n                                              trap.x2,                   traps[i].y2 };\n\n                         DFBTriangle tri2 = { trap.x1 + traps[i].w1 - 1, traps[i].y1,\n                                              trap.x2,                   traps[i].y2,\n                                              trap.x2 + traps[i].w2 - 1, traps[i].y2 };\n\n\n                         /* Transform first triangle completely. */\n                         DFB_TRANSFORM( tri1.x1, tri1.y1, state->matrix, state->affine_matrix );\n                         DFB_TRANSFORM( tri1.x2, tri1.y2, state->matrix, state->affine_matrix );\n                         DFB_TRANSFORM( tri1.x3, tri1.y3, state->matrix, state->affine_matrix );\n\n                         /* Transform last coordinate of second triangle, and assign first ones from first. */\n                         tri2.x1 = tri1.x2;\n                         tri2.y1 = tri1.y2;\n                         tri2.x2 = tri1.x3;\n                         tri2.y2 = tri1.y3;\n                         DFB_TRANSFORM( tri2.x3, tri2.y3, state->matrix, state->affine_matrix );\n\n                         /* Sort triangles (matrix could have rotated them). */\n                         dfb_sort_triangle( &tri1 );\n                         dfb_sort_triangle( &tri2 );\n\n                         if (tri1.y3 - tri1.y1 > 0)\n                              fill_tri( &tri1, state, false );\n\n                         if (tri2.y3 - tri2.y1 > 0)\n                              fill_tri( &tri2, state, false );\n                    }\n                    else\n                         fill_trap( &trap, state, false );\n               }\n\n               gRelease( state );\n          }\n     }\n\n     dfb_state_unlock( state );\n}\n\nvoid\ndfb_gfxcard_fillquadrangles( DFBPoint  *points,\n                             int        num,\n                             CardState *state )\n{\n     bool hw = false;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, DFBGraphicsState );\n     D_ASSERT( points != NULL );\n\n     D_DEBUG_AT( Core_GraphicsOps, \"%s( %p [%d], %p )\\n\", __FUNCTION__, points, num, state );\n\n     /* The state is locked during graphics operations. */\n     dfb_state_lock( state );\n\n     /* Signal beginning of sequence of operations if not already done. */\n     dfb_state_start_drawing( state );\n\n     if (dfb_gfxcard_state_check_acquire( state, DFXL_FILLQUADRANGLE )) {\n          if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&\n              !D_FLAGS_IS_SET( card->caps.clip, DFXL_FILLQUADRANGLE ))\n               return;\n\n          hw = card->funcs.FillQuadrangles( card->driver_data, card->device_data, points, num );\n\n          dfb_gfxcard_state_release( state );\n     }\n\n     if (!hw) {\n          if (gAcquire( state, DFXL_FILLTRIANGLE )) {\n               int i;\n\n               for (i = 0; i < num * 4; i += 4) {\n                    if (state->render_options & DSRO_MATRIX) {\n                         DFB_TRANSFORM( points[i+0].x, points[i+0].y, state->matrix, state->affine_matrix );\n                         DFB_TRANSFORM( points[i+1].x, points[i+1].y, state->matrix, state->affine_matrix );\n                         DFB_TRANSFORM( points[i+2].x, points[i+2].y, state->matrix, state->affine_matrix );\n                         DFB_TRANSFORM( points[i+3].x, points[i+3].y, state->matrix, state->affine_matrix );\n                    }\n\n                    DFBTriangle tri1 = {\n                         points[i+0].x, points[i+0].y,\n                         points[i+1].x, points[i+1].y,\n                         points[i+2].x, points[i+2].y\n                    };\n\n                    DFBTriangle tri2 = {\n                         points[i+0].x, points[i+0].y,\n                         points[i+2].x, points[i+2].y,\n                         points[i+3].x, points[i+3].y\n                    };\n\n                    /* Sort triangles (matrix could have rotated them). */\n                    dfb_sort_triangle( &tri1 );\n                    dfb_sort_triangle( &tri2 );\n\n                    fill_tri( &tri1, state, false );\n                    fill_tri( &tri2, state, false );\n               }\n\n               gRelease( state );\n          }\n     }\n\n     dfb_state_unlock( state );\n}\n\nvoid\ndfb_gfxcard_fillspans( int        y,\n                       DFBSpan   *spans,\n                       int        num,\n                       CardState *state )\n{\n     int i = 0;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( spans != NULL );\n     D_ASSERT( num > 0 );\n\n     D_DEBUG_AT( Core_GraphicsOps, \"%s( %d, %p [%d], %p )\\n\", __FUNCTION__, y, spans, num, state );\n\n     /* The state is locked during graphics operations. */\n     dfb_state_lock( state );\n\n     /* Signal beginning of sequence of operations if not already done. */\n     dfb_state_start_drawing( state );\n\n     if (dfb_gfxcard_state_check_acquire( state, DFXL_FILLRECTANGLE )) {\n          if (card->funcs.BatchFill) {\n               unsigned int done = 0;\n\n               do {\n                    int           real_num;\n                    DFBRectangle *rects;\n\n                    if (num > 256) {\n                         rects = D_MALLOC( sizeof(DFBRectangle) * num );\n                         if (!rects) {\n                              D_OOM();\n                              break;\n                         }\n                    }\n                    else\n                         rects = alloca( sizeof(DFBRectangle) * num );\n\n                    for (real_num = 0; i < num; i++) {\n                         rects[real_num].x = spans[i].x;\n                         rects[real_num].y = y + i;\n                         rects[real_num].w = spans[i].w;\n                         rects[real_num].h = 1;\n\n                         if (rects[real_num].w > card->limits.dst_max.w ||\n                             rects[real_num].h > card->limits.dst_max.h) {\n                              if (!dfb_clip_rectangle( &state->clip, &rects[real_num] ))\n                                   continue;\n\n                              if (rects[real_num].w > card->limits.dst_max.w ||\n                                  rects[real_num].h > card->limits.dst_max.h)\n                                   continue;\n                         }\n                         else if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING )      &&\n                                  !D_FLAGS_IS_SET( card->caps.clip, DFXL_FILLRECTANGLE ) &&\n                                  !dfb_clip_rectangle( &state->clip, &rects[real_num] ))\n                              continue;\n\n                         real_num++;\n                    }\n\n                    if (card->funcs.BatchFill( card->driver_data, card->device_data, &rects[0], real_num, &done ))\n                         i = num;\n                    else\n                         i = done;\n\n                    if (num > 256)\n                         D_FREE( rects );\n               } while (0);\n          }\n\n          for (; i < num; i++) {\n               DFBRectangle rect = { spans[i].x, y + i, spans[i].w, 1 };\n\n               if (rect.w > card->limits.dst_max.w || rect.h > card->limits.dst_max.h) {\n                    if (!dfb_clip_rectangle( &state->clip, &rect ))\n                         continue;\n\n                    if (rect.w > card->limits.dst_max.w || rect.h > card->limits.dst_max.h)\n                         break;\n               }\n               else if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING )      &&\n                        !D_FLAGS_IS_SET( card->caps.clip, DFXL_FILLRECTANGLE ) &&\n                        !dfb_clip_rectangle( &state->clip, &rect ))\n                         continue;\n\n               if (!card->funcs.FillRectangle( card->driver_data, card->device_data, &rect ))\n                    break;\n          }\n\n          dfb_gfxcard_state_release( state );\n     }\n\n     if (i < num) {\n          if (gAcquire( state, DFXL_FILLRECTANGLE )) {\n               for (; i < num; i++) {\n                    DFBRectangle rect = { spans[i].x, y + i, spans[i].w, 1 };\n\n                    if (state->render_options & DSRO_MATRIX) {\n                         if (state->matrix[1] == 0 && state->matrix[3] == 0) {\n                              int x1, y1, x2, y2;\n\n                              x1 = rect.x;      y1 = rect.y;\n                              x2 = x1 + rect.w; y2 = y1 + rect.h;\n                              DFB_TRANSFORM( x1, y1, state->matrix, state->affine_matrix );\n                              DFB_TRANSFORM( x2, y2, state->matrix, state->affine_matrix );\n\n                              if (x1 < x2) {\n                                   rect.x = x1;\n                                   rect.w = x2 - x1;\n                              }\n                              else {\n                                   rect.x = x2;\n                                   rect.w = x1 - x2;\n                              }\n                              if (y1 < y2) {\n                                   rect.y = y1;\n                                   rect.h = y2 - y1;\n                              }\n                              else {\n                                   rect.y = y2;\n                                   rect.h = y1 - y2;\n                              }\n\n                              if (dfb_clip_rectangle( &state->clip, &rect ))\n                                   gFillRectangle( state, &rect );\n                         }\n                         else {\n                              DFBTriangle tri;\n\n                              tri.x1 = rect.x;          tri.y1 = rect.y;\n                              tri.x2 = rect.x + rect.w; tri.y2 = rect.y;\n                              tri.x3 = rect.x + rect.w; tri.y3 = rect.y + rect.h;\n                              DFB_TRANSFORM( tri.x1, tri.y1, state->matrix, state->affine_matrix );\n                              DFB_TRANSFORM( tri.x2, tri.y2, state->matrix, state->affine_matrix );\n                              DFB_TRANSFORM( tri.x3, tri.y3, state->matrix, state->affine_matrix );\n\n                              dfb_sort_triangle( &tri );\n                              if (tri.y3 - tri.y1 > 0)\n                                   fill_tri( &tri, state, false );\n\n                              tri.x1 = rect.x;          tri.y1 = rect.y;\n                              tri.x2 = rect.x + rect.w; tri.y2 = rect.y + rect.h;\n                              tri.x3 = rect.x;          tri.y3 = rect.y + rect.h;\n                              DFB_TRANSFORM( tri.x1, tri.y1, state->matrix, state->affine_matrix );\n                              DFB_TRANSFORM( tri.x2, tri.y2, state->matrix, state->affine_matrix );\n                              DFB_TRANSFORM( tri.x3, tri.y3, state->matrix, state->affine_matrix );\n\n                              dfb_sort_triangle( &tri );\n                              if (tri.y3 - tri.y1 > 0)\n                                   fill_tri( &tri, state, false );\n                         }\n                    }\n                    else {\n                         if (dfb_clip_rectangle( &state->clip, &rect ))\n                              gFillRectangle( state, &rect );\n                    }\n               }\n\n               gRelease( state );\n          }\n     }\n\n     dfb_state_unlock( state );\n}\n\nvoid\ndfb_gfxcard_draw_mono_glyphs( const void                   *glyph[],\n                              const DFBMonoGlyphAttributes *attributes,\n                              const DFBPoint               *points,\n                              unsigned int                  num,\n                              CardState                    *state )\n{\n     int i;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( (glyph != NULL) && (attributes != NULL) && (points != NULL) );\n\n     D_DEBUG_AT( Core_GraphicsOps, \"%s( %p, %p, %p, %p )\\n\", __FUNCTION__, glyph, attributes, points, state );\n\n     /* The state is locked during graphics operations. */\n     dfb_state_lock( state );\n\n     /* Signal beginning of sequence of operations if not already done. */\n     dfb_state_start_drawing( state );\n\n     if (dfb_gfxcard_state_check_acquire( state, DFXL_DRAWMONOGLYPH )) {\n          for (i = 0; i < num; i++) {\n               const DFBMonoGlyphAttributes *attri = &attributes[i];\n\n               card->funcs.DrawMonoGlyph( card->driver_data, card->device_data, glyph[i], attri->width, attri->height,\n                                          attri->rowbyte, attri->bitoffset, points[i].x, points[i].y,\n                                          attri->fgcolor, attri->bgcolor, attri->hzoom, attri->vzoom );\n          }\n\n          dfb_gfxcard_state_release( state );\n     }\n\n     dfb_state_unlock( state );\n}\n\nstatic void\nGenefxVertexAffine_Transform( GenefxVertexAffine *v,\n                              unsigned int        num,\n                              s32                 matrix[9],\n                              bool                affine )\n{\n     unsigned int i;\n\n     if (affine) {\n          for (i = 0; i < num; i++) {\n               int _x, _y;\n\n               _x = ((v[i].x) * matrix[0] + (v[i].y) * matrix[1] + matrix[2]) / 0x10000;\n               _y = ((v[i].x) * matrix[3] + (v[i].y) * matrix[4] + matrix[5]) / 0x10000;\n\n               v[i].x = _x;\n               v[i].y = _y;\n          }\n     }\n     else {\n          for (i = 0; i < num; i++) {\n               int _x, _y, _w;\n\n               _x = ((v[i].x) * matrix[0] + (v[i].y) * matrix[1] + matrix[2]);\n               _y = ((v[i].x) * matrix[3] + (v[i].y) * matrix[4] + matrix[5]);\n               _w = ((v[i].x) * matrix[6] + (v[i].y) * matrix[7] + matrix[8]);\n               if (!_w) {\n                    _x = (_x < 0) ? -0x7fffffff : 0x7fffffff;\n                    _y = (_y < 0) ? -0x7fffffff : 0x7fffffff;\n               }\n               else {\n                    _x /= _w;\n                    _y /= _w;\n               }\n\n               v[i].x = _x;\n               v[i].y = _y;\n          }\n     }\n}\n\nstatic void\ndfb_gfxcard_blit_locked( DFBRectangle *rect,\n                         int           dx,\n                         int           dy,\n                         CardState    *state )\n{\n     bool         hw    = false;\n     DFBRectangle drect = { dx, dy, rect->w, rect->h };\n\n     DFBSurfaceBlittingFlags blittingflags;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( state->source != NULL );\n     D_ASSERT( rect != NULL );\n     D_ASSERT( rect->x >= 0 );\n     D_ASSERT( rect->y >= 0 );\n     D_ASSERT( rect->x < state->source->config.size.w );\n     D_ASSERT( rect->y < state->source->config.size.h );\n     D_ASSERT( rect->x + rect->w - 1 < state->source->config.size.w );\n     D_ASSERT( rect->y + rect->h - 1 < state->source->config.size.h );\n\n     blittingflags = state->blittingflags;\n     dfb_simplify_blittingflags( &blittingflags );\n\n     if (blittingflags & DSBLIT_ROTATE90)\n          D_UTIL_SWAP( drect.w, drect.h );\n\n     D_DEBUG_AT( Core_GraphicsOps, \"%s( %4d,%4d-%4dx%4d -> %4d,%4d-%4dx%4d, %p )\\n\", __FUNCTION__,\n                 DFB_RECTANGLE_VALS( rect ), DFB_RECTANGLE_VALS( &drect ), state );\n\n     /* Signal beginning of sequence of operations if not already done. */\n     dfb_state_start_drawing( state );\n\n     if (!(state->render_options & DSRO_MATRIX) &&\n         !dfb_clip_blit_precheck( &state->clip, drect.w, drect.h, drect.x, drect.y ))\n          return;\n\n     if (dfb_gfxcard_state_check_acquire( state, DFXL_BLIT )) {\n          if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&\n              !D_FLAGS_IS_SET( card->caps.clip, DFXL_BLIT ))\n               dfb_clip_blit_flipped_rotated( &state->clip, rect, &drect, blittingflags );\n\n          hw = card->funcs.Blit( card->driver_data, card->device_data, rect, drect.x, drect.y );\n\n          dfb_gfxcard_state_release( state );\n     }\n\n     if (!hw) {\n          /* Use software fallback. */\n          if (!(state->render_options & DSRO_MATRIX)) {\n               if (gAcquire( state, DFXL_BLIT )) {\n                    dfb_clip_blit_flipped_rotated( &state->clip, rect, &drect, blittingflags );\n\n                    gBlit( state, rect, drect.x, drect.y );\n\n                    gRelease( state );\n               }\n          }\n          else if (state->matrix[0] == 0x10000 && state->matrix[1] == 0 &&\n                   state->matrix[3] == 0       && state->matrix[4] == 0x10000) {\n               state->render_options &= ~DSRO_MATRIX;\n               state->modified       |= SMF_RENDER_OPTIONS;\n\n               dfb_gfxcard_blit( rect,\n                                 dx + ((state->matrix[2] + 0x8000) >> 16),\n                                 dy + ((state->matrix[5] + 0x8000) >> 16), state );\n\n               state->render_options |= DSRO_MATRIX;\n               state->modified       |= SMF_RENDER_OPTIONS;\n          }\n          else {\n               if (state->matrix[0] < 0  || state->matrix[1] != 0 ||\n                   state->matrix[3] != 0 || state->matrix[4] < 0  ||\n                   state->matrix[6] != 0 || state->matrix[7] != 0) {\n                    if (gAcquire( state, DFXL_TEXTRIANGLES )) {\n                         GenefxVertexAffine v[4];\n\n                         v[0].x = dx;\n                         v[0].y = dy;\n                         v[0].s = rect->x * 0x10000;\n                         v[0].t = rect->y * 0x10000;\n\n                         v[1].x = dx + rect->w - 1;\n                         v[1].y = dy;\n                         v[1].s = (rect->x + rect->w - 1) * 0x10000;\n                         v[1].t = v[0].t;\n\n                         v[2].x = dx + rect->w - 1;\n                         v[2].y = dy + rect->h - 1;\n                         v[2].s = v[1].s;\n                         v[2].t = (rect->y + rect->h - 1) * 0x10000;\n\n                         v[3].x = dx;\n                         v[3].y = dy + rect->h - 1;\n                         v[3].s = v[0].s;\n                         v[3].t = v[2].t;\n\n                         GenefxVertexAffine_Transform( v, 4, state->matrix, state->affine_matrix );\n\n                         Genefx_TextureTrianglesAffine( state, v, 4, DTTF_FAN, &state->clip );\n\n                         gRelease( state );\n                    }\n               }\n               else if (gAcquire( state, DFXL_STRETCHBLIT )) {\n                    int x1, y1, x2, y2;\n\n                    x1 = dx;           y1 = dy;\n                    x2 = dx + rect->w; y2 = dy + rect->h;\n                    DFB_TRANSFORM( x1, y1, state->matrix, state->affine_matrix );\n                    DFB_TRANSFORM( x2, y2, state->matrix, state->affine_matrix );\n\n                    drect = (DFBRectangle) { x1, y1, x2 - x1, y2 - y1 };\n                    if (dfb_clip_blit_precheck( &state->clip, drect.w, drect.h, drect.x, drect.y ))\n                         gStretchBlit( state, rect, &drect );\n\n                    gRelease( state );\n               }\n          }\n     }\n}\n\nvoid\ndfb_gfxcard_blit( DFBRectangle *rect,\n                  int           dx,\n                  int           dy,\n                  CardState    *state )\n{\n     /* The state is locked during graphics operations. */\n     dfb_state_lock( state );\n     dfb_gfxcard_blit_locked( rect, dx, dy, state );\n     dfb_state_unlock( state );\n}\n\nstatic void\nclip_blits( const DFBRegion         *clip,\n            const DFBRectangle      *rects,\n            const DFBPoint          *points,\n            unsigned int             num,\n            DFBSurfaceBlittingFlags  flags,\n            DFBRectangle            *ret_rects,\n            DFBPoint                *ret_points,\n            unsigned int            *ret_num )\n{\n     unsigned int i;\n     unsigned int clipped_num = 0;\n\n     DFB_REGION_ASSERT( clip );\n     D_ASSERT( rects != NULL );\n     D_ASSERT( points != NULL );\n     D_ASSERT( ret_rects != NULL );\n     D_ASSERT( ret_points != NULL );\n     D_ASSERT( ret_num != NULL );\n     D_ASSERT( !(flags & (DSBLIT_ROTATE270 | DSBLIT_ROTATE180)) );\n\n     for (i = 0; i < num; i++) {\n          DFBRectangle drect = { points[i].x, points[i].y, rects[i].w, rects[i].h };\n\n          if (flags & (DSBLIT_ROTATE90))\n               D_UTIL_SWAP( drect.w, drect.h );\n\n          if (dfb_clip_blit_precheck( clip, drect.w, drect.h, drect.x, drect.y )) {\n               ret_rects[clipped_num] = rects[i];\n\n               dfb_clip_blit_flipped_rotated( clip, &ret_rects[clipped_num], &drect, flags );\n\n               ret_points[clipped_num].x = drect.x;\n               ret_points[clipped_num].y = drect.y;\n\n               clipped_num++;\n          }\n     }\n\n     *ret_num = clipped_num;\n}\n\nvoid\ndfb_gfxcard_batchblit( DFBRectangle *rects,\n                       DFBPoint     *points,\n                       int           num,\n                       CardState    *state )\n{\n     unsigned int i = 0;\n\n     DFBSurfaceBlittingFlags blittingflags;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( rects != NULL );\n     D_ASSERT( points != NULL );\n     D_ASSERT( num > 0 );\n\n     D_DEBUG_AT( Core_GraphicsOps, \"%s( %p, %p [%d], %p )\\n\", __FUNCTION__, rects, points, num, state );\n\n     blittingflags = state->blittingflags;\n     dfb_simplify_blittingflags( &blittingflags );\n\n     /* The state is locked during graphics operations. */\n     dfb_state_lock( state );\n\n     /* Signal beginning of sequence of operations if not already done. */\n     dfb_state_start_drawing( state );\n\n     if (dfb_gfxcard_state_check_acquire( state, DFXL_BLIT )) {\n          if (card->funcs.BatchBlit) {\n               unsigned int done = 0;\n\n               if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&\n                   !D_FLAGS_IS_SET( card->caps.clip, DFXL_BLIT )) {\n                    unsigned int  clipped_num;\n                    DFBRectangle *clipped_rects;\n                    DFBPoint     *clipped_points;\n\n                    if (num > 256) {\n                         clipped_rects = D_MALLOC( sizeof(DFBRectangle) * num );\n                         if (!clipped_rects) {\n                              D_OOM();\n                         }\n                         else {\n                              clipped_points = D_MALLOC( sizeof(DFBPoint) * num );\n                              if (!clipped_points) {\n                                   D_OOM();\n                                   D_FREE( clipped_rects );\n                              }\n                              else {\n                                   clip_blits( &state->clip, rects, points, num, blittingflags,\n                                               clipped_rects, clipped_points, &clipped_num );\n\n                                   /* The driver has to reject all or none. */\n                                   if (card->funcs.BatchBlit( card->driver_data, card->device_data,\n                                                              clipped_rects, clipped_points, clipped_num, &done ))\n                                        i = num;\n                                   else\n                                        i = done;\n\n                                   D_FREE( clipped_points );\n                                   D_FREE( clipped_rects );\n                              }\n                         }\n                    }\n                    else {\n                         clipped_rects  = alloca( sizeof(DFBRectangle) * num );\n                         clipped_points = alloca( sizeof(DFBPoint) * num );\n\n                         clip_blits( &state->clip, rects, points, num, blittingflags,\n                                     clipped_rects, clipped_points, &clipped_num );\n\n                         /* The driver has to reject all or none. */\n                         if (card->funcs.BatchBlit( card->driver_data, card->device_data,\n                                                    clipped_rects, clipped_points, clipped_num, &done ))\n                              i = num;\n                         else\n                              i = done;\n                    }\n               }\n               else {\n                    /* The driver has to reject all or none. */\n                    if (card->funcs.BatchBlit( card->driver_data, card->device_data, rects, points, num, &done ))\n                         i = num;\n                    else\n                         i = done;\n               }\n          }\n          else {\n               for (; i < num; i++) {\n                    DFBRectangle drect = { points[i].x, points[i].y, rects[i].w, rects[i].h };\n\n                    if (blittingflags & DSBLIT_ROTATE90)\n                         D_UTIL_SWAP( drect.w, drect.h );\n\n                    if ((state->render_options & DSRO_MATRIX) ||\n                        dfb_clip_blit_precheck( &state->clip, drect.w, drect.h, drect.x, drect.y )) {\n                         DFBRectangle srect = rects[i];\n\n                         if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&\n                             !D_FLAGS_IS_SET( card->caps.clip, DFXL_BLIT ))\n                              dfb_clip_blit_flipped_rotated( &state->clip, &srect, &drect, blittingflags );\n\n                         if (!card->funcs.Blit( card->driver_data, card->device_data, &srect, drect.x, drect.y ))\n                              break;\n                    }\n               }\n          }\n\n          dfb_gfxcard_state_release( state );\n     }\n\n     if (i < num) {\n          if (state->render_options & DSRO_MATRIX) {\n               if (state->matrix[0] < 0  || state->matrix[1] != 0 ||\n                   state->matrix[3] != 0 || state->matrix[4] < 0  ||\n                   state->matrix[6] != 0 || state->matrix[7] != 0) {\n                    if (gAcquire( state, DFXL_TEXTRIANGLES )) {\n                         for (; i < num; i++) {\n                              GenefxVertexAffine v[4];\n\n                              v[0].x = points[i].x;\n                              v[0].y = points[i].y;\n                              v[0].s = rects[i].x * 0x10000;\n                              v[0].t = rects[i].y * 0x10000;\n\n                              v[1].x = points[i].x + rects[i].w - 1;\n                              v[1].y = points[i].y;\n                              v[1].s = (rects[i].x + rects[i].w - 1) * 0x10000;\n                              v[1].t = v[0].t;\n\n                              v[2].x = points[i].x + rects[i].w - 1;\n                              v[2].y = points[i].y + rects[i].h - 1;\n                              v[2].s = v[1].s;\n                              v[2].t = (rects[i].y + rects[i].h - 1) * 0x10000;\n\n                              v[3].x = points[i].x;\n                              v[3].y = points[i].y + rects[i].h - 1;\n                              v[3].s = v[0].s;\n                              v[3].t = v[2].t;\n\n                              GenefxVertexAffine_Transform( v, 4, state->matrix, state->affine_matrix );\n\n                              Genefx_TextureTrianglesAffine( state, v, 4, DTTF_FAN, &state->clip );\n                         }\n\n                         gRelease( state );\n                    }\n               }\n               else if (gAcquire( state, DFXL_STRETCHBLIT )) {\n                    for (; i < num; i++) {\n                         int          x1, y1, x2, y2;\n                         DFBRectangle drect;\n\n                         x1 = points[i].x;     y1 = points[i].y;\n                         x2 = x1 + rects[i].w; y2 = y1 + rects[i].h;\n                         DFB_TRANSFORM( x1, y1, state->matrix, state->affine_matrix );\n                         DFB_TRANSFORM( x2, y2, state->matrix, state->affine_matrix );\n\n                         drect = (DFBRectangle) { x1, y1, x2 - x1, y2 - y1 };\n                         if (dfb_clip_blit_precheck( &state->clip, drect.w, drect.h, drect.x, drect.y ))\n                              gStretchBlit( state, &rects[i], &drect );\n                    }\n\n                    gRelease( state );\n               }\n          }\n          else {\n               if (gAcquire( state, DFXL_BLIT )) {\n                    for (; i < num; i++) {\n                         DFBRectangle drect = { points[i].x, points[i].y, rects[i].w, rects[i].h };\n\n                         if (blittingflags & DSBLIT_ROTATE90)\n                              D_UTIL_SWAP( drect.w, drect.h );\n\n                         if (dfb_clip_blit_precheck( &state->clip, drect.w, drect.h, drect.x, drect.y )) {\n                              DFBRectangle srect = rects[i];\n\n                              dfb_clip_blit_flipped_rotated( &state->clip, &srect, &drect, blittingflags );\n                              gBlit( state, &srect, drect.x, drect.y );\n                         }\n                    }\n\n                    gRelease( state );\n               }\n          }\n     }\n\n     dfb_state_unlock( state );\n}\n\nvoid\ndfb_gfxcard_batchblit2( DFBRectangle *rects,\n                        DFBPoint     *points,\n                        DFBPoint     *points2,\n                        int           num,\n                        CardState    *state )\n{\n     int i = 0;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( rects != NULL );\n     D_ASSERT( points != NULL );\n     D_ASSERT( points2 != NULL );\n     D_ASSERT( num > 0 );\n\n     D_DEBUG_AT( Core_GraphicsOps, \"%s( %p, %p, %p [%d], %p )\\n\", __FUNCTION__, rects, points, points2, num, state );\n\n     /* The state is locked during graphics operations. */\n     dfb_state_lock( state );\n\n     /* Signal beginning of sequence of operations if not already done. */\n     dfb_state_start_drawing( state );\n\n     if (dfb_gfxcard_state_check_acquire( state, DFXL_BLIT2 )) {\n          for (; i < num; i++) {\n               if ((state->render_options & DSRO_MATRIX) ||\n                   dfb_clip_blit_precheck( &state->clip, rects[i].w, rects[i].h, points[i].x, points[i].y )) {\n                    int dx = points[i].x;\n                    int dy = points[i].y;\n\n                    if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&\n                        !D_FLAGS_IS_SET( card->caps.clip, DFXL_BLIT2 )) {\n                         dfb_clip_blit( &state->clip, &rects[i], &dx, &dy );\n\n                         points2[i].x += dx - points[i].x;\n                         points2[i].y += dy - points[i].y;\n                    }\n\n                    if (!card->funcs.Blit2( card->driver_data, card->device_data, &rects[i], dx, dy,\n                                            points2[i].x, points2[i].y ))\n                         break;\n               }\n          }\n\n          dfb_gfxcard_state_release( state );\n     }\n\n     if (i < num) {\n          D_UNIMPLEMENTED();\n\n          for (; i < num; i++) {\n               D_DEBUG_AT( Core_GraphicsOps, \"  -> rects[%d]    %4d,%4d-%4dx%4d\\n\", i,\n                           DFB_RECTANGLE_VALS( &rects[i] ) );\n               D_DEBUG_AT( Core_GraphicsOps, \"  -> points[%d]   %4d,%4d\\n\", i, points[i].x, points[i].y );\n               D_DEBUG_AT( Core_GraphicsOps, \"  -> points2[%d]  %4d,%4d\\n\", i, points2[i].x, points2[i].y );\n\n               if ((state->render_options & DSRO_MATRIX) ||\n                   dfb_clip_blit_precheck( &state->clip, rects[i].w, rects[i].h, points[i].x, points[i].y )) {\n                    int dx = points[i].x;\n                    int dy = points[i].y;\n\n                    dfb_clip_blit( &state->clip, &rects[i], &dx, &dy );\n\n                    points2[i].x += dx - points[i].x;\n                    points2[i].y += dy - points[i].y;\n\n                    D_DEBUG_AT( Core_GraphicsOps, \"  -> rects[%d]    %4d,%4d-%4dx%4d\\n\", i,\n                                DFB_RECTANGLE_VALS( &rects[i] ) );\n                    D_DEBUG_AT( Core_GraphicsOps, \"  -> points[%d]   %4d,%4d\\n\", i, dx, dy );\n                    D_DEBUG_AT( Core_GraphicsOps, \"  -> points2[%d]  %4d,%4d\\n\", i, points2[i].x, points2[i].y );\n               }\n          }\n     }\n\n     dfb_state_unlock( state );\n}\n\nvoid\ndfb_gfxcard_batchstretchblit( DFBRectangle *srects,\n                              DFBRectangle *drects,\n                              unsigned int  num,\n                              CardState    *state )\n{\n     int  i;\n     bool need_clip;\n     bool acquired = false;\n\n     DFBSurfaceBlittingFlags blittingflags;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( srects != NULL );\n     D_ASSERT( drects != NULL );\n     D_ASSERT( num > 0 );\n\n     D_DEBUG_AT( Core_GraphicsOps, \"%s( %p )\\n\", __FUNCTION__, state );\n\n     for (i = 0; i < num; ++i)\n          D_DEBUG_AT( Core_GraphicsOps, \"  -> %4d,%4d-%4dx%4d -> %4d,%4d-%4dx%4d\\n\",\n                      DFB_RECTANGLE_VALS( &srects[i] ), DFB_RECTANGLE_VALS( &drects[i] ) );\n\n     blittingflags = state->blittingflags;\n     dfb_simplify_blittingflags( &blittingflags );\n\n     /* The state is locked during graphics operations. */\n     dfb_state_lock( state );\n\n     /* Signal beginning of sequence of operations if not already done. */\n     dfb_state_start_drawing( state );\n\n     need_clip = (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&\n                  !D_FLAGS_IS_SET( card->caps.clip, DFXL_STRETCHBLIT ));\n\n     for (i = 0; i < num; ++i) {\n          DFBRectangle *srect = &srects[i];\n          DFBRectangle *drect = &drects[i];\n\n          if (!acquired) {\n               if (!dfb_gfxcard_state_check_acquire( state, DFXL_STRETCHBLIT ))\n                    break;\n\n               acquired = true;\n          }\n\n          if ((srect->w == drect->w && srect->h == drect->h) ||\n              ((state->blittingflags & DSBLIT_ROTATE90) && (srect->w == drect->h && srect->h == drect->w))) {\n               dfb_gfxcard_state_release( state );\n               acquired = false;\n               dfb_gfxcard_blit_locked( srect, drect->x, drect->y, state );\n               continue;\n          }\n\n          if (!(state->render_options & DSRO_MATRIX) &&\n              !dfb_clip_blit_precheck( &state->clip, drect->w, drect->h, drect->x, drect->y ))\n               continue;\n\n          if (need_clip)\n               dfb_clip_stretchblit( &state->clip, srect, drect );\n\n          if (!card->funcs.StretchBlit( card->driver_data, card->device_data, srect, drect ))\n               break;\n     }\n\n     if (acquired)\n          dfb_gfxcard_state_release( state );\n\n     if (i < num) {\n          if ((state->render_options & DSRO_MATRIX) &&\n              (state->matrix[0] < 0  || state->matrix[1] != 0 ||\n               state->matrix[3] != 0 || state->matrix[4] < 0  ||\n               state->matrix[6] != 0 || state->matrix[7] != 0)) {\n               if (gAcquire( state, DFXL_TEXTRIANGLES )) {\n                    for (; i < num; ++i) {\n                         DFBRectangle *srect = &srects[i];\n                         DFBRectangle *drect = &drects[i];\n\n                         GenefxVertexAffine v[4];\n\n                         v[0].x = drect->x;\n                         v[0].y = drect->y;\n                         v[0].s = srect->x * 0x10000;\n                         v[0].t = srect->y * 0x10000;\n\n                         v[1].x = drect->x + drect->w - 1;\n                         v[1].y = drect->y;\n                         v[1].s = (srect->x + srect->w - 1) * 0x10000;\n                         v[1].t = v[0].t;\n\n                         v[2].x = drect->x + drect->w - 1;\n                         v[2].y = drect->y + drect->h - 1;\n                         v[2].s = v[1].s;\n                         v[2].t = (srect->y + srect->h - 1) * 0x10000;\n\n                         v[3].x = drect->x;\n                         v[3].y = drect->y + drect->h - 1;\n                         v[3].s = v[0].s;\n                         v[3].t = v[2].t;\n\n                         GenefxVertexAffine_Transform( v, 4, state->matrix, state->affine_matrix );\n\n                         Genefx_TextureTrianglesAffine( state, v, 4, DTTF_FAN, &state->clip );\n                    }\n\n                    gRelease( state );\n               }\n          }\n          else if (gAcquire( state, DFXL_STRETCHBLIT )) {\n               for (; i < num; ++i) {\n                    DFBRectangle *srect = &srects[i];\n                    DFBRectangle *drect = &drects[i];\n\n                    if (state->render_options & DSRO_MATRIX) {\n                         int x1, y1, x2, y2;\n\n                         x1 = drect->x;      y1 = drect->y;\n                         x2 = x1 + drect->w; y2 = y1 + drect->h;\n                         DFB_TRANSFORM( x1, y1, state->matrix, state->affine_matrix );\n                         DFB_TRANSFORM( x2, y2, state->matrix, state->affine_matrix );\n                         drect->x = x1;    drect->y = y1;\n                         drect->w = x2 - x1; drect->h = y2 - y1;\n                    }\n\n                    if (!dfb_clip_blit_precheck( &state->clip, drect->w, drect->h, drect->x, drect->y ))\n                         continue;\n\n                    gStretchBlit( state, srect, drect );\n               }\n\n               gRelease( state );\n          }\n     }\n\n     dfb_state_unlock( state );\n}\n\nvoid\ndfb_gfxcard_stretchblit( DFBRectangle *srect,\n                         DFBRectangle *drect,\n                         CardState    *state )\n{\n     dfb_gfxcard_batchstretchblit( srect, drect, 1, state );\n}\n\nvoid\ndfb_gfxcard_tileblit( DFBRectangle *rect,\n                      int           dx1,\n                      int           dy1,\n                      int           dx2,\n                      int           dy2,\n                      CardState    *state )\n{\n     int           x, y;\n     int           odx;\n     DFBRectangle  srect;\n     DFBRegion    *clip;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( rect != NULL );\n     D_ASSERT( rect->w >= 1 );\n     D_ASSERT( rect->h >= 1 );\n\n     D_DEBUG_AT( Core_GraphicsOps, \"%s( %4d,%4d-%4d,%4d, %p )\\n\", __FUNCTION__, dx1, dy1, dx2, dy2, state );\n\n     /* The state is locked during graphics operations. */\n     dfb_state_lock( state );\n\n     /* Signal beginning of sequence of operations if not already done. */\n     dfb_state_start_drawing( state );\n\n     clip = &state->clip;\n\n     /* Check if anything is drawn at all. */\n     if (!(state->render_options & DSRO_MATRIX) &&\n         !dfb_clip_blit_precheck( clip, dx2 - dx1 + 1, dy2 - dy1 + 1, dx1, dy1 )) {\n          dfb_state_unlock( state );\n          return;\n     }\n\n     /* Remove clipped tiles. */\n     if (dx1 < clip->x1) {\n          int outer = clip->x1 - dx1;\n\n          dx1 += outer - (outer % rect->w);\n     }\n\n     if (dy1 < clip->y1) {\n          int outer = clip->y1 - dy1;\n\n          dy1 += outer - (outer % rect->h);\n     }\n\n     if (dx2 > clip->x2) {\n          int outer = clip->x2 - dx2;\n\n          dx2 -= outer - (outer % rect->w);\n     }\n\n     if (dy2 > clip->y2) {\n          int outer = clip->y2 - dy2;\n\n          dy2 -= outer - (outer % rect->h);\n     }\n\n     odx = dx1;\n\n     if (dfb_gfxcard_state_check_acquire( state, DFXL_BLIT )) {\n          bool hw = true;\n\n          for (; dy1 < dy2; dy1 += rect->h) {\n               for (; dx1 < dx2; dx1 += rect->w) {\n\n                    if (!dfb_clip_blit_precheck( clip, rect->w, rect->h, dx1, dy1 ))\n                         continue;\n\n                    x = dx1;\n                    y = dy1;\n                    srect = *rect;\n\n                    if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&\n                        !D_FLAGS_IS_SET( card->caps.clip, DFXL_BLIT ))\n                         dfb_clip_blit( clip, &srect, &x, &y );\n\n                    hw = card->funcs.Blit( card->driver_data, card->device_data, &srect, x, y );\n                    if (!hw)\n                         break;\n               }\n\n               if (!hw)\n                    break;\n\n               dx1 = odx;\n          }\n\n          dfb_gfxcard_state_release( state );\n     }\n\n     if (dy1 < dy2) {\n          if (state->render_options & DSRO_MATRIX) {\n               if (state->matrix[0] < 0  || state->matrix[1] != 0 ||\n                   state->matrix[3] != 0 || state->matrix[4] < 0  ||\n                   state->matrix[6] != 0 || state->matrix[7] != 0) {\n                    if (gAcquire( state, DFXL_TEXTRIANGLES )) {\n                         /* Build mesh. */\n                         for (; dy1 < dy2; dy1 += rect->h) {\n                              for (; dx1 < dx2; dx1 += rect->w) {\n                                   GenefxVertexAffine v[4];\n\n                                   v[0].x = dx1;\n                                   v[0].y = dy1;\n                                   v[0].s = rect->x * 0x10000;\n                                   v[0].t = rect->y * 0x10000;\n\n                                   v[1].x = dx1 + rect->w - 1;\n                                   v[1].y = dy1;\n                                   v[1].s = (rect->x + rect->w - 1) * 0x10000;\n                                   v[1].t = v[0].t;\n\n                                   v[2].x = dx1 + rect->w - 1;\n                                   v[2].y = dy1 + rect->h - 1;\n                                   v[2].s = v[1].s;\n                                   v[2].t = (rect->y + rect->h - 1) * 0x10000;\n\n                                   v[3].x = dx1;\n                                   v[3].y = dy1 + rect->h - 1;\n                                   v[3].s = v[0].s;\n                                   v[3].t = v[2].t;\n\n                                   GenefxVertexAffine_Transform( v, 4, state->matrix, state->affine_matrix );\n\n                                   Genefx_TextureTrianglesAffine( state, v, 4, DTTF_FAN, &state->clip );\n                              }\n\n                              dx1 = odx;\n                         }\n\n                         gRelease( state );\n                    }\n               }\n               else if (gAcquire( state, DFXL_STRETCHBLIT )) {\n                    for (; dy1 < dy2; dy1 += rect->h) {\n                         for (; dx1 < dx2; dx1 += rect->w) {\n                              int          x1, y1, x2, y2;\n                              DFBRectangle drect;\n\n                              x1 = dx1;           y1 = dy1;\n                              x2 = dx1 + rect->w; y2 = dy1 + rect->h;\n                              DFB_TRANSFORM( x1, y1, state->matrix, state->affine_matrix );\n                              DFB_TRANSFORM( x2, y2, state->matrix, state->affine_matrix );\n\n                              drect = (DFBRectangle) { x1, y1, x2 - x1, y2 - y1 };\n                              if (dfb_clip_blit_precheck( &state->clip, drect.w, drect.h, drect.x, drect.y ))\n                                   gStretchBlit( state, rect, &drect );\n                         }\n\n                         dx1 = odx;\n                    }\n\n                    gRelease( state );\n               }\n          }\n          else {\n               if (gAcquire( state, DFXL_BLIT )) {\n                    for (; dy1 < dy2; dy1 += rect->h) {\n                         for (; dx1 < dx2; dx1 += rect->w) {\n                              if (!dfb_clip_blit_precheck( clip, rect->w, rect->h, dx1, dy1 ))\n                                   continue;\n\n                              x = dx1;\n                              y = dy1;\n                              srect = *rect;\n\n                              dfb_clip_blit( clip, &srect, &x, &y );\n\n                              gBlit( state, &srect, x, y );\n                         }\n\n                         dx1 = odx;\n                    }\n\n                    gRelease( state );\n               }\n          }\n     }\n\n     dfb_state_unlock( state );\n}\n\nvoid\ndfb_gfxcard_texture_triangles( DFBVertex            *vertices,\n                               int                   num,\n                               DFBTriangleFormation  formation,\n                               CardState            *state )\n{\n     bool hw = false;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( vertices != NULL );\n     D_ASSERT( num >= 3 );\n\n     D_DEBUG_AT( Core_GraphicsOps, \"%s( %p [%d], %s, %p )\\n\", __FUNCTION__, vertices, num,\n                 (formation == DTTF_LIST)  ? \"LIST\"  :\n                 (formation == DTTF_STRIP) ? \"STRIP\" :\n                 (formation == DTTF_FAN)   ? \"FAN\"   : \"unknown formation\", state );\n\n     /* The state is locked during graphics operations. */\n     dfb_state_lock( state );\n\n     /* Signal beginning of sequence of operations if not already done. */\n     dfb_state_start_drawing( state );\n\n     if ((D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) ||\n          D_FLAGS_IS_SET( card->caps.clip, DFXL_TEXTRIANGLES )) &&\n         dfb_gfxcard_state_check_acquire( state, DFXL_TEXTRIANGLES )) {\n          hw = card->funcs.TextureTriangles( card->driver_data, card->device_data, vertices, num, formation );\n\n          dfb_gfxcard_state_release( state );\n     }\n\n     if (!hw) {\n          if (gAcquire( state, DFXL_TEXTRIANGLES )) {\n               int                i;\n               GenefxVertexAffine v[num];\n\n               /* Convert vertices. */\n               for (i = 0; i < num; i++) {\n                    v[i].x = vertices[i].x;\n                    v[i].y = vertices[i].y;\n                    v[i].s = vertices[i].s * state->source->config.size.w * 0x10000;\n                    v[i].t = vertices[i].t * state->source->config.size.h * 0x10000;\n               }\n\n               Genefx_TextureTrianglesAffine( state, v, num, formation, &state->clip );\n\n               gRelease( state );\n          }\n     }\n\n     dfb_state_unlock( state );\n}\n\nstatic void\nfont_state_prepare( CardState   *state,\n                    CardState   *backup,\n                    CoreFont    *font,\n                    CoreSurface *surface,\n                    bool         set_blend )\n{\n     if (state->blittingflags != DSBLIT_INDEX_TRANSLATION) {\n          DFBSurfaceBlittingFlags flags = font->blittingflags;\n\n          backup->blittingflags = state->blittingflags;\n          backup->src_blend     = state->src_blend;\n          backup->dst_blend     = state->dst_blend;\n\n          /* Additional blending. */\n          if ((state->drawingflags & DSDRAW_BLEND) && (state->color.a != 0xff))\n               flags |= DSBLIT_BLEND_COLORALPHA;\n\n          if (state->drawingflags & DSDRAW_DST_COLORKEY)\n               flags |= DSBLIT_DST_COLORKEY;\n\n          if (state->drawingflags & DSDRAW_XOR)\n               flags |= DSBLIT_XOR;\n\n          if (flags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) {\n               /* Porter/Duff SRC_OVER composition. */\n               if ((DFB_PIXELFORMAT_HAS_ALPHA( surface->config.format ) &&\n                    (surface->config.caps & DSCAPS_PREMULTIPLIED)) ||\n                   (font->surface_caps & DSCAPS_PREMULTIPLIED)) {\n                    if (font->surface_caps & DSCAPS_PREMULTIPLIED) {\n                         if (flags & DSBLIT_BLEND_COLORALPHA)\n                              flags |= DSBLIT_SRC_PREMULTCOLOR;\n                    }\n                    else\n                         flags |= DSBLIT_SRC_PREMULTIPLY;\n\n                    if (set_blend)\n                         dfb_state_set_src_blend( state, DSBF_ONE );\n               }\n               else if (set_blend)\n                    dfb_state_set_src_blend( state, DSBF_SRCALPHA );\n\n               if (set_blend)\n                    dfb_state_set_dst_blend( state, DSBF_INVSRCALPHA );\n          }\n\n          dfb_state_set_blitting_flags( state, flags );\n     }\n     else {\n          backup->blittingflags = 0;\n          backup->src_blend     = 0;\n          backup->dst_blend     = 0;\n     }\n}\n\nstatic void\nfont_state_restore( CardState *state,\n                    CardState *backup )\n{\n     if (state->blittingflags != DSBLIT_INDEX_TRANSLATION) {\n          dfb_state_set_blitting_flags( state, backup->blittingflags );\n          dfb_state_set_src_blend( state, backup->src_blend );\n          dfb_state_set_dst_blend( state, backup->dst_blend );\n     }\n}\n\nvoid\ndfb_gfxcard_drawstring( const u8                *text,\n                        int                      bytes,\n                        DFBTextEncodingID        encoding,\n                        int                      x,\n                        int                      y,\n                        CoreFont                *font,\n                        unsigned int             layers,\n                        CoreGraphicsStateClient *client,\n                        DFBSurfaceTextFlags      flags )\n{\n     DFBResult     ret;\n     unsigned int  indices[bytes];\n     int           i, l, num;\n     int           kern_x;\n     int           kern_y;\n     DFBRectangle  rects[50];\n     DFBPoint      points[50];\n     CardState     state_backup;\n     CardState    *state;\n     CoreSurface  *surface;\n     int           num_blits = 0;\n     int           ox        = x;\n     int           oy        = y;\n     unsigned int  prev      = 0;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n\n     state = client->state;\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_MAGIC_ASSERT( state->destination, CoreSurface );\n     D_ASSERT( text != NULL );\n     D_ASSERT( bytes > 0 );\n     D_ASSERT( font != NULL );\n\n     if (encoding == DTEID_UTF8)\n          D_DEBUG_AT( Core_GraphicsOps, \"%s( '%s' [%d], %d,%d, %p, %p )\\n\", __FUNCTION__,\n                      text, bytes, x, y, font, client );\n     else\n          D_DEBUG_AT( Core_GraphicsOps, \"%s( %p [%d], %u, %d,%d, %p, %p )\\n\", __FUNCTION__,\n                      text, bytes, encoding, x, y, font, client );\n\n     surface = state->destination;\n\n     /* Simple prechecks. */\n     if (!(font->description.flags & DFDESC_ROTATION) || !font->description.rotation) {\n          if (!(state->render_options & DSRO_MATRIX) &&\n              (x > state->clip.x2 || y > state->clip.y2 ||\n               y + font->height <= state->clip.y1)) {\n               return;\n          }\n     }\n\n     /* Decode string to character indices. */\n     ret = dfb_font_decode_text( font, encoding, text, bytes, indices, &num );\n     if (ret)\n          return;\n\n     font_state_prepare( state, &state_backup, font, surface, !(flags & DSTF_BLEND_FUNCS) );\n\n     dfb_font_lock( font );\n\n     for (l = layers - 1; l >= 0; l--) {\n          x = ox << 8;\n          y = oy << 8;\n\n          if (layers > 1)\n               dfb_state_set_color( state, &state->colors[l] );\n\n          /* Blit glyphs. */\n          for (i = 0; i < num; i++) {\n               CoreGlyphData *glyph;\n               unsigned int   current = indices[i];\n\n               ret = dfb_font_get_glyph_data( font, current, l, &glyph );\n               if (ret) {\n                    D_DEBUG_AT( Core_GraphicsOps, \"  -> glyph data loading from font failed!\\n\" );\n                    prev = current;\n                    continue;\n               }\n\n               if (prev && font->GetKerning && font->GetKerning( font, prev, current, &kern_x, &kern_y) == DFB_OK) {\n                    x += kern_x << 8;\n                    y += kern_y << 8;\n               }\n\n               if (glyph->width) {\n                    if (glyph->surface != state->source || num_blits == D_ARRAY_SIZE(rects)) {\n                         if (num_blits) {\n                              CoreGraphicsStateClient_Blit( client, rects, points, num_blits );\n                              num_blits = 0;\n                         }\n\n                         if (glyph->surface != state->source)\n                              dfb_state_set_source( state, glyph->surface );\n                    }\n\n                    points[num_blits] = (DFBPoint) { (x >> 8) + glyph->left, (y >> 8) + glyph->top };\n                    rects[num_blits]  = (DFBRectangle) { glyph->start, 0, glyph->width, glyph->height };\n\n                    num_blits++;\n               }\n\n               x   += glyph->xadvance;\n               y   += glyph->yadvance;\n               prev = current;\n          }\n\n          if (num_blits) {\n               CoreGraphicsStateClient_Blit( client, rects, points, num_blits );\n               num_blits = 0;\n          }\n     }\n\n     dfb_font_unlock( font );\n\n     font_state_restore( state, &state_backup );\n}\n\nvoid\ndfb_gfxcard_drawglyph( CoreGlyphData           **glyph,\n                       int                       x,\n                       int                       y,\n                       CoreFont                 *font,\n                       unsigned int              layers,\n                       CoreGraphicsStateClient  *client,\n                       DFBSurfaceTextFlags       flags )\n{\n     int          l;\n     CardState    state_backup;\n     CardState   *state;\n     CoreSurface *surface;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( client, CoreGraphicsStateClient );\n\n     state = client->state;\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_MAGIC_ASSERT( state->destination, CoreSurface );\n     D_ASSERT( font != NULL );\n\n     D_DEBUG_AT( Core_GraphicsOps, \"%s( %d,%d, %u, %p, %p )\\n\", __FUNCTION__, x, y, layers, font, client );\n\n     surface = state->destination;\n\n     font_state_prepare( state, &state_backup, font, surface, !(flags & DSTF_BLEND_FUNCS) );\n\n     for (l = layers - 1; l >= 0; l--) {\n          if (layers > 1)\n               dfb_state_set_color( state, &state->colors[l] );\n\n          /* Blit glyph. */\n          if (glyph[l]->width) {\n               DFBRectangle rect  = { glyph[l]->start, 0, glyph[l]->width, glyph[l]->height };\n               DFBPoint     point = { x + glyph[l]->left, y + glyph[l]->top };\n\n               dfb_state_set_source( state, glyph[l]->surface );\n\n               CoreGraphicsStateClient_Blit( client, &rect, &point, 1 );\n          }\n     }\n\n     font_state_restore( state, &state_backup );\n}\n\nbool\ndfb_gfxcard_drawstring_check_state( CoreFont                *font,\n                                    CardState               *state,\n                                    CoreGraphicsStateClient *client,\n                                    DFBSurfaceTextFlags      flags )\n{\n     int                  i;\n     bool                 result = false;\n     CoreSurface         *surface;\n     CardState            state_backup;\n     CoreGlyphData       *data;\n     DFBAccelerationMask  mask;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_MAGIC_ASSERT( state->destination, CoreSurface );\n     D_ASSERT( font != NULL );\n     D_ASSERT( client != NULL );\n\n     D_DEBUG_AT( Core_GfxState, \"%s( %p, %p, %p )\\n\", __FUNCTION__, font, state, client );\n\n     surface = state->destination;\n\n     dfb_font_lock( font );\n\n     for (i = 0; i < 128; i++) {\n          if (dfb_font_get_glyph_data( font, i, 0, &data ) == DFB_OK)\n               break;\n     }\n\n     if (!data) {\n          D_DEBUG_AT( Core_GfxState, \"  -> no font data!\\n\" );\n          dfb_font_unlock( font );\n          return false;\n     }\n\n     font_state_prepare( state, &state_backup, font, surface, !(flags & DSTF_BLEND_FUNCS) );\n\n     /* Set the source. */\n     dfb_state_set_source( state, data->surface );\n\n     if (CoreGraphicsStateClient_GetAccelerationMask( client, &mask ) == DFB_OK)\n          result = mask & DFXL_BLIT;\n\n     dfb_font_unlock( font );\n\n     font_state_restore( state, &state_backup );\n\n     return result;\n}\n\nDFBResult\ndfb_gfxcard_sync()\n{\n     DFBResult ret;\n\n     if (!card)\n          return DFB_OK;\n\n     ret = dfb_gfxcard_lock( GDLF_SYNC );\n     if (ret)\n          return ret;\n\n     dfb_gfxcard_unlock();\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_gfxcard_wait_serial( const CoreGraphicsSerial *serial )\n{\n     DFBResult              ret;\n     DFBGraphicsCoreShared *shared;\n\n     D_ASSERT( serial != NULL );\n\n     if (!card || dfb_config->software_only)\n          return DFB_OK;\n\n     D_ASSERT( card->shared != NULL );\n\n     shared = card->shared;\n\n     ret = dfb_gfxcard_lock( GDLF_NONE );\n     if (ret)\n          return ret;\n\n     /* Start command processing if not already running. */\n     if (shared->pending_ops && card->funcs.EmitCommands) {\n          dfb_gfxcard_switch_busy();\n\n          card->funcs.EmitCommands( card->driver_data, card->device_data );\n\n          shared->pending_ops = false;\n     }\n\n     if (card->funcs.WaitSerial)\n          ret = card->funcs.WaitSerial( card->driver_data, card->device_data, serial );\n     else if (card->funcs.EngineSync)\n          ret = card->funcs.EngineSync( card->driver_data, card->device_data );\n\n     dfb_gfxcard_switch_idle();\n\n     if (ret) {\n          if (card->funcs.EngineReset)\n               card->funcs.EngineReset( card->driver_data, card->device_data );\n\n          shared->state = NULL;\n     }\n\n     dfb_gfxcard_unlock();\n\n     return ret;\n}\n\nvoid\ndfb_gfxcard_flush_texture_cache()\n{\n     if (dfb_config->software_only)\n          return;\n\n     if (card && card->funcs.FlushTextureCache)\n          card->funcs.FlushTextureCache( card->driver_data, card->device_data );\n}\n\nvoid\ndfb_gfxcard_flush_read_cache()\n{\n     if (dfb_config->software_only)\n          return;\n\n     if (card && card->funcs.FlushReadCache)\n          card->funcs.FlushReadCache( card->driver_data, card->device_data );\n}\n\nvoid\ndfb_gfxcard_after_set_var()\n{\n     if (dfb_config->software_only)\n          return;\n\n     if (card && card->funcs.AfterSetVar)\n          card->funcs.AfterSetVar( card->driver_data, card->device_data );\n}\n\nvoid\ndfb_gfxcard_get_capabilities( CardCapabilities *ret_caps )\n{\n     D_ASSERT( card != NULL );\n\n     D_ASSERT( ret_caps != NULL );\n\n     *ret_caps = card->caps;\n}\n\nvoid\ndfb_gfxcard_get_device_info( GraphicsDeviceInfo *ret_device_info )\n{\n     DFBGraphicsCoreShared *shared;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_ASSERT( ret_device_info != NULL );\n\n     shared = card->shared;\n\n     *ret_device_info = shared->device_info;\n}\n\nvoid\ndfb_gfxcard_get_driver_info( GraphicsDriverInfo *ret_driver_info )\n{\n     DFBGraphicsCoreShared *shared;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     D_ASSERT( ret_driver_info != NULL );\n\n     shared = card->shared;\n\n     *ret_driver_info = shared->driver_info;\n}\n\nint\ndfb_gfxcard_reserve_memory( unsigned int size )\n{\n     DFBGraphicsCoreShared *shared;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     shared = card->shared;\n\n     if (shared->device_info.limits.surface_byteoffset_alignment) {\n          size += shared->device_info.limits.surface_byteoffset_alignment - 1;\n          size -= (size % shared->device_info.limits.surface_byteoffset_alignment);\n     }\n     else\n          D_WARN( \"no alignment specified yet\" );\n\n     if (shared->videoram_length < size) {\n          D_WARN( \"not enough video memory (%u < %u)\", shared->videoram_length, size );\n          return -1;\n     }\n\n     shared->videoram_length -= size;\n\n     return shared->videoram_length;\n}\n\nunsigned int\ndfb_gfxcard_memory_length()\n{\n     DFBGraphicsCoreShared *shared;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     shared = card->shared;\n\n     return shared->videoram_length;\n}\n\nvolatile void *\ndfb_gfxcard_map_mmio( unsigned int offset,\n                      int          length )\n{\n     return dfb_system_map_mmio( offset, length );\n}\n\nvoid\ndfb_gfxcard_unmap_mmio( volatile void      *addr,\n                        int                 length )\n{\n     dfb_system_unmap_mmio( addr, length );\n}\n\nunsigned int\ndfb_gfxcard_get_accelerator()\n{\n     return dfb_system_get_accelerator();\n}\n\nvoid\ndfb_gfxcard_calc_buffer_size( CoreSurfaceBuffer *buffer,\n                              int               *ret_pitch,\n                              int               *ret_length )\n{\n     DFBResult    ret = DFB_FAILURE;\n     int          pitch;\n     int          length;\n     CoreSurface *surface;\n\n     D_ASSERT( card != NULL );\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n\n     surface = buffer->surface;\n\n     /* Use the Graphics card's own method to calculate the buffer size. */\n     if (card->funcs.CalcBufferSize) {\n          ret = card->funcs.CalcBufferSize( card->driver_data, card->device_data, buffer, &pitch, &length );\n     }\n\n     if (ret) {\n          /* Calculate the required length depending on limitations. */\n          pitch = MAX( surface->config.size.w, surface->config.min_size.w );\n\n          if (pitch < card->limits.surface_max_power_of_two_pixelpitch &&\n              surface->config.size.h < card->limits.surface_max_power_of_two_height)\n               pitch = 1 << direct_log2( pitch );\n\n          if (card->limits.surface_pixelpitch_alignment > 1) {\n               pitch += card->limits.surface_pixelpitch_alignment - 1;\n               pitch -= pitch % card->limits.surface_pixelpitch_alignment;\n          }\n\n          pitch = DFB_BYTES_PER_LINE( surface->config.format, pitch );\n\n          if (pitch < card->limits.surface_max_power_of_two_bytepitch &&\n              surface->config.size.h < card->limits.surface_max_power_of_two_height)\n               pitch = 1 << direct_log2( pitch );\n\n          if (card->limits.surface_bytepitch_alignment > 1) {\n               pitch += card->limits.surface_bytepitch_alignment - 1;\n               pitch -= pitch % card->limits.surface_bytepitch_alignment;\n          }\n\n          length = DFB_PLANE_MULTIPLY( surface->config.format,\n                                       MAX( surface->config.size.h, surface->config.min_size.h ) * pitch );\n\n          if (card->limits.surface_byteoffset_alignment > 1) {\n               length += card->limits.surface_byteoffset_alignment - 1;\n               length -= length % card->limits.surface_byteoffset_alignment;\n          }\n     }\n\n     if (ret_pitch)\n          *ret_pitch = pitch;\n\n     if (ret_length)\n          *ret_length = length;\n}\n\nunsigned long\ndfb_gfxcard_memory_physical( unsigned int offset )\n{\n     return dfb_system_video_memory_physical( offset );\n}\n\nvoid *\ndfb_gfxcard_memory_virtual( unsigned int offset )\n{\n     return dfb_system_video_memory_virtual( offset );\n}\n\nvoid *\ndfb_gfxcard_get_device_data()\n{\n     DFBGraphicsCoreShared *shared;\n\n     D_ASSERT( card != NULL );\n     D_ASSERT( card->shared != NULL );\n\n     shared = card->shared;\n\n     return shared->device_data;\n}\n\nvoid *\ndfb_gfxcard_get_driver_data()\n{\n     D_ASSERT( card != NULL );\n\n     return card->driver_data;\n}\n\n/**********************************************************************************************************************/\n\nstatic void\ndfb_gfxcard_update_stats( long long now )\n{\n     if (dfb_config->gfxcard_stats) {\n          DFBGraphicsCoreShared *shared;\n          long long              total;\n\n          D_ASSERT( card != NULL );\n          D_ASSERT( card->shared != NULL );\n\n          shared = card->shared;\n          total  = now - shared->ts_start;\n\n          if (total > dfb_config->gfxcard_stats * 1000LL) {\n               D_INFO( \"DirectFB/Graphics: Stats: busy %lld / %lld -> %3lld.%lld%%\\n\", shared->ts_busy_sum, total,\n                       (1000 * shared->ts_busy_sum / total) / 10LL, (1000 * shared->ts_busy_sum / total) % 10LL );\n\n               shared->ts_start    = now;\n               shared->ts_busy_sum = 0;\n          }\n     }\n}\n\nstatic void\ndfb_gfxcard_switch_busy()\n{\n     if (dfb_config->gfxcard_stats) {\n          DFBGraphicsCoreShared *shared;\n          long long              now = direct_clock_get_time( DIRECT_CLOCK_MONOTONIC );\n\n          D_ASSERT( card != NULL );\n          D_ASSERT( card->shared != NULL );\n\n          shared = card->shared;\n\n          if (shared->ts_busy)\n               shared->ts_busy_sum += now - shared->ts_busy;\n\n          shared->ts_busy = now;\n\n          if (!shared->ts_start)\n               shared->ts_start = shared->ts_busy;\n\n          dfb_gfxcard_update_stats( now );\n     }\n}\n\nstatic void\ndfb_gfxcard_switch_idle()\n{\n     if (dfb_config->gfxcard_stats) {\n          DFBGraphicsCoreShared *shared;\n          long long              now = direct_clock_get_time( DIRECT_CLOCK_MONOTONIC );\n\n          D_ASSERT( card != NULL );\n          D_ASSERT( card->shared != NULL );\n\n          shared = card->shared;\n\n          if (shared->ts_busy) {\n               shared->ts_busy_sum += now - shared->ts_busy;\n\n               shared->ts_busy = 0;\n          }\n\n          dfb_gfxcard_update_stats( now );\n     }\n}\n"
  },
  {
    "path": "src/core/gfxcard.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__GFXCARD_H__\n#define __CORE__GFXCARD_H__\n\n#include <core/coretypes.h>\n#include <direct/modules.h>\n\nDECLARE_MODULE_DIRECTORY( dfb_graphics_drivers );\n\n/**********************************************************************************************************************/\n\n#define DFB_GRAPHICS_DRIVER_ABI_VERSION          35\n\n#define DFB_GRAPHICS_DRIVER_INFO_URL_LENGTH     100\n#define DFB_GRAPHICS_DRIVER_INFO_LICENSE_LENGTH  40\n\ntypedef struct {\n     int major; /* major version */\n     int minor; /* minor version */\n} GraphicsDriverVersion;\n\nstruct __DFB_GraphicsDriverInfo {\n     GraphicsDriverVersion version;\n\n     char                  name[DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH];       /* Name of graphics driver */\n     char                  vendor[DFB_GRAPHICS_DRIVER_INFO_VENDOR_LENGTH];   /* Vendor (or author) of the driver */\n     char                  url[DFB_GRAPHICS_DRIVER_INFO_URL_LENGTH];         /* URL for driver updates */\n     char                  license[DFB_GRAPHICS_DRIVER_INFO_LICENSE_LENGTH]; /* License, e.g. 'LGPL' or 'proprietary' */\n\n     unsigned int          driver_data_size;                                 /* Driver private data size to allocate */\n     unsigned int          device_data_size;                                 /* Device private data size to allocate */\n};\n\n#define DFB_GRAPHICS_DEVICE_INFO_NAME_LENGTH     48\n#define DFB_GRAPHICS_DEVICE_INFO_VENDOR_LENGTH   64\n\ntypedef enum {\n     CCF_CLIPPING    = 0x00000001,\n     CCF_NOTRIEMU    = 0x00000002,\n     CCF_READSYSMEM  = 0x00000004,\n     CCF_WRITESYSMEM = 0x00000008,\n\n     CCF_RENDEROPTS  = 0x00000020\n} CardCapabilitiesFlags;\n\ntypedef struct {\n     CardCapabilitiesFlags   flags;\n\n     DFBAccelerationMask     accel;\n     DFBSurfaceBlittingFlags blitting;\n     DFBSurfaceDrawingFlags  drawing;\n     DFBAccelerationMask     clip;\n} CardCapabilities;\n\ntypedef struct {\n     unsigned int surface_byteoffset_alignment;\n     unsigned int surface_pixelpitch_alignment;\n     unsigned int surface_bytepitch_alignment;\n\n     unsigned int surface_max_power_of_two_pixelpitch;\n     unsigned int surface_max_power_of_two_bytepitch;\n     unsigned int surface_max_power_of_two_height;\n\n     DFBDimension dst_min;\n     DFBDimension dst_max;\n} CardLimitations;\n\nstruct __DFB_GraphicsDeviceInfo {\n     char             name[DFB_GRAPHICS_DEVICE_INFO_NAME_LENGTH];     /* Device name. */\n     char             vendor[DFB_GRAPHICS_DEVICE_INFO_VENDOR_LENGTH]; /* Vendor of the device. */\n\n     CardCapabilities caps;                                           /* Hardware acceleration capabilities. */\n\n     CardLimitations  limits;                                         /* Hardware limitations. */\n};\n\ntypedef struct _GraphicsDeviceFuncs {\n     /*\n      * Called after screen information is changed.\n      */\n     void      (*AfterSetVar)      ( void                        *driver_data,\n                                     void                        *device_data );\n\n     /*\n      * The driver should do the one time initialization of the engine, e.g. writing some registers that are supposed to\n      * have a fixed value.\n      */\n     void      (*EngineReset)      ( void                        *driver_data,\n                                     void                        *device_data );\n\n     /*\n      * Make sure that graphics hardware has finished all operations.\n      */\n     DFBResult (*EngineSync)       ( void                        *driver_data,\n                                     void                        *device_data );\n\n     /*\n      * Called during dfb_gfxcard_lock() to notify the driver that the current rendering state is no longer valid.\n      */\n     void      (*InvalidateState)  ( void                        *driver_data,\n                                     void                        *device_data );\n\n     /*\n      * After the video memory has been written to by the CPU (e.g. modification of a texture) make sure the accelerator\n      * won't use cached texture data.\n      */\n     void      (*FlushTextureCache)( void                        *driver_data,\n                                     void                        *device_data );\n\n     /*\n      * After the video memory has been written to by the accelerator make sure the CPU won't read back cached data.\n      */\n     void      (*FlushReadCache)   ( void                        *driver_data,\n                                     void                        *device_data );\n\n     /*\n      * Return the serial of the last (queued) operation.\n      * The serial is used to wait for finishing a specific graphics operation instead of the whole engine being idle.\n      */\n     void      (*GetSerial)        ( void                        *driver_data,\n                                     void                        *device_data,\n                                     CoreGraphicsSerial          *serial );\n\n     /*\n      * Make sure that graphics hardware has finished the specified operation.\n      */\n     DFBResult (*WaitSerial)       ( void                        *driver_data,\n                                     void                        *device_data,\n                                     const CoreGraphicsSerial    *serial );\n\n     /*\n      * Emit any buffered commands, i.e. trigger processing.\n      */\n     void      (*EmitCommands)     ( void                        *driver_data,\n                                     void                        *device_data );\n\n     /*\n      * Check if the function 'accel' can be accelerated with the 'state'.\n      * If that's true, the function sets the 'accel' bit in 'state->accel'.\n      */\n     void      (*CheckState)       ( void                        *driver_data,\n                                     void                        *device_data,\n                                     CardState                   *state,\n                                     DFBAccelerationMask          accel );\n\n     /*\n      * Program card for execution of the function 'accel' with the 'state'.\n      * 'state->modified' contains information about changed entries, at least 'accel' is set in 'state->set'.\n      * The driver may modify 'funcs' depending on 'state' settings.\n      */\n     void      (*SetState)         ( void                        *driver_data,\n                                     void                        *device_data,\n                                     struct _GraphicsDeviceFuncs *funcs,\n                                     CardState                   *state,\n                                     DFBAccelerationMask          accel );\n\n     /*\n      * Drawing functions.\n      */\n\n     bool      (*FillRectangle)    ( void                        *driver_data,\n                                     void                        *device_data,\n                                     DFBRectangle                *rect );\n\n     bool      (*DrawRectangle)    ( void                        *driver_data,\n                                     void                        *device_data,\n                                     DFBRectangle                *rect );\n\n     bool      (*DrawLine)         ( void                        *driver_data,\n                                     void                        *device_data,\n                                     DFBRegion                   *line );\n\n     bool      (*FillTriangle)     ( void                        *driver_data,\n                                     void                        *device_data,\n                                     DFBTriangle                 *tri );\n\n     bool      (*FillTrapezoid)    ( void                        *driver_data,\n                                     void                        *device_data,\n                                     DFBTrapezoid                *trap );\n\n     bool      (*FillQuadrangles)  ( void                        *driver_data,\n                                     void                        *device_data,\n                                     DFBPoint                    *points,\n                                     int                          num );\n\n     bool      (*DrawMonoGlyph)    ( void                        *driver_data,\n                                     void                        *device_data,\n                                     const void                  *glyph,\n                                     int                          glyph_width,\n                                     int                          glyph_height,\n                                     int                          glyph_rowbyte,\n                                     int                          glyph_offset,\n                                     int                          dx,\n                                     int                          dy,\n                                     int                          fg_color,\n                                     int                          bg_color,\n                                     int                          hzoom,\n                                     int                          vzoom );\n\n     /*\n      * Blitting functions.\n      */\n\n     bool      (*Blit)             ( void                        *driver_data,\n                                     void                        *device_data,\n                                     DFBRectangle                *rect,\n                                     int                          dx,\n                                     int                          dy );\n\n     bool      (*Blit2)            ( void                        *driver_data,\n                                     void                        *device_data,\n                                     DFBRectangle                *rect,\n                                     int                          dx,\n                                     int                          dy,\n                                     int                          sx2,\n                                     int                          sy2 );\n\n     bool      (*StretchBlit)      ( void                        *driver_data,\n                                     void                        *device_data,\n                                     DFBRectangle                *srect,\n                                     DFBRectangle                *drect );\n\n     bool      (*TextureTriangles) ( void                        *driver_data,\n                                     void                        *device_data,\n                                     DFBVertex                   *vertices,\n                                     int                          num,\n                                     DFBTriangleFormation         formation );\n\n     /*\n      * Signal beginning of a sequence of operations using this 'state'.\n      */\n     void      (*StartDrawing)     ( void                        *driver_data,\n                                     void                        *device_data,\n                                     CardState                   *state );\n\n     /*\n      * Signal end of sequence.\n      */\n     void      (*StopDrawing)      ( void                        *driver_data,\n                                     void                        *device_data,\n                                     CardState                   *state );\n\n     /*\n      * BatchBlit: when driver returns false (late fallback), it may set 'ret_num' to the number of successful blits in\n      * case of partial execution.\n      */\n     bool      (*BatchBlit)        ( void                        *driver_data,\n                                     void                        *device_data,\n                                     const DFBRectangle          *rects,\n                                     const DFBPoint              *points,\n                                     unsigned int                 num,\n                                     unsigned int                *ret_num );\n\n     /*\n      * BatchFill: when driver returns false (late fallback), it may set 'ret_num' to the number of successful fills in\n      * case of partial execution.\n      */\n     bool      (*BatchFill)        ( void                        *driver_data,\n                                     void                        *device_data,\n                                     const DFBRectangle          *rects,\n                                     unsigned int                 num,\n                                     unsigned int                *ret_num );\n\n     /*\n      * Callbacks when a state is created or destroyed. This allows a graphics driver to hold additional state.\n      */\n\n     void      (*StateInit)        ( void                        *driver_data,\n                                     void                        *device_data,\n                                     CardState                   *state );\n\n     void      (*StateDestroy)     ( void                        *driver_data,\n                                     void                        *device_data,\n                                     CardState                   *state );\n\n     /*\n      * Calculate the amount of memory and pitch for the specified surface buffer.\n      */\n     DFBResult (*CalcBufferSize)   ( void                        *driver_data,\n                                     void                        *device_data,\n                                     CoreSurfaceBuffer           *buffer,\n                                     int                         *ret_pitch,\n                                     int                         *ret_length );\n} GraphicsDeviceFuncs;\n\ntypedef struct {\n     int       (*Probe)        ( void );\n\n     void      (*GetDriverInfo)( GraphicsDriverInfo  *driver_info );\n\n     DFBResult (*InitDriver)   ( GraphicsDeviceFuncs *funcs,\n                                 void                *driver_data,\n                                 void                *device_data,\n                                 CoreDFB             *core );\n\n     DFBResult (*InitDevice)   ( GraphicsDeviceInfo  *device_info,\n                                 void                *driver_data,\n                                 void                *device_data );\n\n     void      (*CloseDevice)  ( void                *driver_data,\n                                 void                *device_data );\n\n     void      (*CloseDriver)  ( void                *driver_data );\n} GraphicsDriverFuncs;\n\ntypedef enum {\n     GDLF_NONE       = 0x00000000,\n\n     GDLF_WAIT       = 0x00000001,\n     GDLF_SYNC       = 0x00000002,\n     GDLF_INVALIDATE = 0x00000004,\n     GDLF_RESET      = 0x00000008\n} GraphicsDeviceLockFlags;\n\n/**********************************************************************************************************************/\n\nDFBResult      dfb_gfxcard_lock                  ( GraphicsDeviceLockFlags        flags );\n\nvoid           dfb_gfxcard_unlock                ( void );\n\nDFBResult      dfb_gfxcard_flush                 ( void );\n\n/*\n * Signal beginning of a sequence of operations using this state. Any number of states can be 'drawing'.\n */\nvoid           dfb_gfxcard_start_drawing         ( CardState                     *state );\n\n/*\n * Signal end of sequence, i.e. destination surface is consistent again.\n */\nvoid           dfb_gfxcard_stop_drawing          ( CardState                     *state );\n\n/*\n * This function returns non zero if acceleration is available for the specific function using the given state.\n */\nbool           dfb_gfxcard_state_check           ( CardState                     *state,\n                                                   DFBAccelerationMask            accel );\n\nvoid           dfb_gfxcard_state_init            ( CardState                     *state );\n\nvoid           dfb_gfxcard_state_destroy         ( CardState                     *state );\n\n/*\n * Drawing functions, lock source and destination surfaces, handle clipping and drawing method (hardware/software).\n */\n\nvoid           dfb_gfxcard_fillrectangles        ( DFBRectangle                  *rects,\n                                                   int                            num,\n                                                   CardState                     *state );\n\nvoid           dfb_gfxcard_drawrectangle         ( DFBRectangle                  *rect,\n                                                   CardState                     *state );\n\nvoid           dfb_gfxcard_drawlines             ( DFBRegion                     *lines,\n                                                   int                            num_lines,\n                                                   CardState                     *state );\n\nvoid           dfb_gfxcard_filltriangles         ( DFBTriangle                   *tris,\n                                                   int                            num,\n                                                   CardState                     *state );\n\nvoid           dfb_gfxcard_filltrapezoids        ( DFBTrapezoid                  *traps,\n                                                   int                            num,\n                                                   CardState                     *state );\n\nvoid           dfb_gfxcard_fillquadrangles       ( DFBPoint                      *points,\n                                                   int                            num,\n                                                   CardState                     *state );\n\nvoid           dfb_gfxcard_fillspans             ( int                            y,\n                                                   DFBSpan                       *spans,\n                                                   int                            num_spans,\n                                                   CardState                     *state );\n\nvoid           dfb_gfxcard_draw_mono_glyphs      ( const void                    *glyph[],\n                                                   const DFBMonoGlyphAttributes  *attributes,\n                                                   const DFBPoint                *points,\n                                                   unsigned int                   num,\n                                                   CardState                     *state );\n\nvoid           dfb_gfxcard_blit                  ( DFBRectangle                  *rect,\n                                                   int                            dx,\n                                                   int                            dy,\n                                                   CardState                     *state );\n\nvoid           dfb_gfxcard_batchblit             ( DFBRectangle                  *rects,\n                                                   DFBPoint                      *points,\n                                                   int                            num,\n                                                   CardState                     *state );\n\nvoid           dfb_gfxcard_batchblit2            ( DFBRectangle                  *rects,\n                                                   DFBPoint                      *points,\n                                                   DFBPoint                      *points2,\n                                                   int                            num,\n                                                   CardState                     *state );\n\nvoid           dfb_gfxcard_stretchblit           ( DFBRectangle                  *srect,\n                                                   DFBRectangle                  *drect,\n                                                   CardState                     *state );\n\nvoid           dfb_gfxcard_batchstretchblit      ( DFBRectangle                  *srects,\n                                                   DFBRectangle                  *drects,\n                                                   unsigned int                   num,\n                                                   CardState                     *state );\n\nvoid           dfb_gfxcard_tileblit              ( DFBRectangle                  *rect,\n                                                   int                            dx1,\n                                                   int                            dy1,\n                                                   int                            dx2,\n                                                   int                            dy2,\n                                                   CardState                     *state );\n\n\nvoid           dfb_gfxcard_texture_triangles     ( DFBVertex                     *vertices,\n                                                   int                            num,\n                                                   DFBTriangleFormation           formation,\n                                                   CardState                     *state );\n\nvoid           dfb_gfxcard_drawstring            ( const u8                      *text,\n                                                   int                            bytes,\n                                                   DFBTextEncodingID              encoding,\n                                                   int                            x,\n                                                   int                            y,\n                                                   CoreFont                      *font,\n                                                   unsigned int                   layers,\n                                                   CoreGraphicsStateClient       *client,\n                                                   DFBSurfaceTextFlags            flags );\n\nvoid           dfb_gfxcard_drawglyph             ( CoreGlyphData                **glyph,\n                                                   int                            x,\n                                                   int                            y,\n                                                   CoreFont                      *font,\n                                                   unsigned int                   layers,\n                                                   CoreGraphicsStateClient       *client,\n                                                   DFBSurfaceTextFlags            flags );\n\n/*\n * Check text rendering function.\n */\nbool           dfb_gfxcard_drawstring_check_state( CoreFont                      *font,\n                                                   CardState                     *state,\n                                                   CoreGraphicsStateClient       *client,\n                                                   DFBSurfaceTextFlags            flags );\n\nDFBResult      dfb_gfxcard_sync                  ( void );\n\nDFBResult      dfb_gfxcard_wait_serial           ( const CoreGraphicsSerial      *serial );\n\nvoid           dfb_gfxcard_flush_texture_cache   ( void );\n\nvoid           dfb_gfxcard_flush_read_cache      ( void );\n\nvoid           dfb_gfxcard_after_set_var         ( void );\n\nvoid           dfb_gfxcard_get_capabilities      ( CardCapabilities              *ret_caps );\n\nvoid           dfb_gfxcard_get_device_info       ( GraphicsDeviceInfo            *ret_device_info );\n\nvoid           dfb_gfxcard_get_driver_info       ( GraphicsDriverInfo            *ret_driver_info );\n\nint            dfb_gfxcard_reserve_memory        ( unsigned int                   size );\n\nunsigned int   dfb_gfxcard_memory_length         ( void );\n\nvolatile void *dfb_gfxcard_map_mmio              ( unsigned int                   offset,\n                                                   int                            length );\n\nvoid           dfb_gfxcard_unmap_mmio            ( volatile void                 *addr,\n                                                   int                            length );\n\nunsigned int   dfb_gfxcard_get_accelerator       ( void );\n\nvoid           dfb_gfxcard_calc_buffer_size      ( CoreSurfaceBuffer             *buffer,\n                                                   int                           *ret_pitch,\n                                                   int                           *ret_length );\n\nunsigned long  dfb_gfxcard_memory_physical       ( unsigned int                   offset );\n\nvoid          *dfb_gfxcard_memory_virtual        ( unsigned int                   offset );\n\nvoid          *dfb_gfxcard_get_device_data       ( void );\n\nvoid          *dfb_gfxcard_get_driver_data       ( void );\n\n#endif\n"
  },
  {
    "path": "src/core/graphics_driver.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__GRAPHICS_DRIVER_H__\n#define __CORE__GRAPHICS_DRIVER_H__\n\n#include <core/gfxcard.h>\n\n/**********************************************************************************************************************/\n\nstatic int       driver_probe       ( void );\n\nstatic void      driver_get_info    ( GraphicsDriverInfo  *driver_info );\n\nstatic DFBResult driver_init_driver ( GraphicsDeviceFuncs *funcs,\n                                      void                *driver_data,\n                                      void                *device_data,\n                                      CoreDFB             *core );\n\nstatic DFBResult driver_init_device ( GraphicsDeviceInfo  *device_info,\n                                      void                *driver_data,\n                                      void                *device_data );\n\nstatic void      driver_close_device( void                *driver_data,\n                                      void                *device_data );\n\nstatic void      driver_close_driver( void                *driver_data );\n\nstatic GraphicsDriverFuncs gfxdriver_funcs = {\n     .Probe         = driver_probe,\n     .GetDriverInfo = driver_get_info,\n     .InitDriver    = driver_init_driver,\n     .InitDevice    = driver_init_device,\n     .CloseDevice   = driver_close_device,\n     .CloseDriver   = driver_close_driver\n};\n\n#define DFB_GRAPHICS_DRIVER(shortname)                         \\\n                                                               \\\n__dfb_constructor__                                            \\\nvoid                                                           \\\ndirectfb_##shortname##_ctor( void )                            \\\n{                                                              \\\n     direct_modules_register( &dfb_graphics_drivers,           \\\n                              DFB_GRAPHICS_DRIVER_ABI_VERSION, \\\n                              #shortname,                      \\\n                              &gfxdriver_funcs );              \\\n}                                                              \\\n                                                               \\\n__dfb_destructor__                                             \\\nvoid                                                           \\\ndirectfb_##shortname##_dtor( void )                            \\\n{                                                              \\\n     direct_modules_unregister( &dfb_graphics_drivers,         \\\n                                #shortname );                  \\\n}\n\n#endif\n"
  },
  {
    "path": "src/core/graphics_state.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreGraphicsState.h>\n#include <core/core.h>\n#include <core/graphics_state.h>\n\nD_DEBUG_DOMAIN( Core_GraphicsState, \"Core/GraphicsState\", \"DirectFB Core Graphics State\" );\n\n/**********************************************************************************************************************/\n\nstatic void\nstate_destructor( FusionObject *object,\n                  bool          zombie,\n                  void         *ctx )\n{\n     CoreGraphicsState *state = (CoreGraphicsState*) object;\n\n     D_MAGIC_ASSERT( state, CoreGraphicsState );\n\n     D_DEBUG_AT( Core_GraphicsState, \"Destroying state %p (%p%s)\\n\", state, &state->state, zombie ? \" ZOMBIE\" : \"\" );\n\n     dfb_state_set_destination( &state->state, NULL );\n     dfb_state_set_source( &state->state, NULL );\n     dfb_state_set_source2( &state->state, NULL );\n     dfb_state_set_source_mask( &state->state, NULL );\n\n     dfb_state_destroy( &state->state );\n\n     CoreGraphicsState_Deinit_Dispatch( &state->call );\n\n     D_MAGIC_CLEAR( state );\n\n     /* Destroy the object. */\n     fusion_object_destroy( object );\n}\n\nFusionObjectPool *\ndfb_graphics_state_pool_create( const FusionWorld *world )\n{\n     FusionObjectPool *pool;\n\n     pool = fusion_object_pool_create( \"GraphicsState Pool\",\n                                       sizeof(CoreGraphicsState), sizeof(CoreGraphicsStateNotification),\n                                       state_destructor, NULL, world );\n\n     return pool;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_graphics_state_create( CoreDFB            *core,\n                           CoreGraphicsState **ret_state )\n{\n     CoreGraphicsState *state;\n\n     D_ASSERT( ret_state );\n\n     D_DEBUG_AT( Core_GraphicsState, \"%s()\\n\", __FUNCTION__ );\n\n     /* Create the state object. */\n     state = dfb_core_create_graphics_state( core );\n     if (!state)\n          return DFB_FUSION;\n\n     dfb_state_init( &state->state, core );\n\n     CoreGraphicsState_Init_Dispatch( core, state, &state->call );\n\n     if (dfb_config->graphics_state_call_limit)\n          fusion_call_set_quota( &state->call, state->object.identity, dfb_config->graphics_state_call_limit );\n\n     D_MAGIC_SET( state, CoreGraphicsState );\n\n     /* Activate the object. */\n     fusion_object_activate( &state->object );\n\n     /* Return the new state. */\n     *ret_state = state;\n\n     D_DEBUG_AT( Core_GraphicsState, \"  -> %p\\n\", state );\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/core/graphics_state.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__GRAPHICS_STATE_H__\n#define __CORE__GRAPHICS_STATE_H__\n\n#include <core/state.h>\n\n/**********************************************************************************************************************/\n\nstruct __DFB_CoreGraphicsState {\n     FusionObject object;\n     int          magic;\n\n     FusionCall   call;\n\n     CardState    state;\n};\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CGSNF_NONE = 0x00000000,\n} CoreGraphicsStateNotificationFlags;\n\ntypedef struct {\n     CoreGraphicsStateNotificationFlags flags;\n} CoreGraphicsStateNotification;\n\n/**********************************************************************************************************************/\n\n/*\n * Creates a pool of graphics state objects.\n */\nFusionObjectPool *dfb_graphics_state_pool_create( const FusionWorld  *world );\n\n/*\n * Generates dfb_graphics_state_ref(), dfb_graphics_state_attach() etc.\n */\nFUSION_OBJECT_METHODS( CoreGraphicsState, dfb_graphics_state )\n\n/**********************************************************************************************************************/\n\nDFBResult         dfb_graphics_state_create     ( CoreDFB            *core,\n                                                  CoreGraphicsState **ret_state );\n\n#endif\n"
  },
  {
    "path": "src/core/input.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreInputDevice.h>\n#include <core/core.h>\n#include <core/core_parts.h>\n#include <core/input.h>\n#include <core/layers.h>\n#include <core/layer_context.h>\n#include <core/layer_control.h>\n#include <core/system.h>\n#include <core/windowstack.h>\n#include <direct/filesystem.h>\n#if !FUSION_BUILD_MULTI\n#include <direct/system.h>\n#endif /* FUSION_BUILD_MULTI */\n#include <direct/trace.h>\n#include <directfb_keynames.h>\n#include <fusion/conf.h>\n#include <fusion/shmalloc.h>\n\nD_DEBUG_DOMAIN( Core_Input,    \"Core/Input\",     \"DirectFB Core Input\" );\nD_DEBUG_DOMAIN( Core_InputEvt, \"Core/Input/Evt\", \"DirectFB Core Input Events & Dispatch\" );\n\nDEFINE_MODULE_DIRECTORY( dfb_input_drivers, \"inputdrivers\", DFB_INPUT_DRIVER_ABI_VERSION );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int                    magic;\n\n     int                    num;\n     CoreInputDeviceShared *devices[MAX_INPUTDEVICES];\n     FusionReactor         *reactor;                   /* For input hot-plug event. */\n} DFBInputCoreShared;\n\ntypedef struct {\n     int                 magic;\n\n     CoreDFB            *core;\n\n     DFBInputCoreShared *shared;\n\n     DirectLink         *drivers;\n     DirectLink         *devices;\n} DFBInputCore;\n\nDFB_CORE_PART( input_core, InputCore );\n\n/**********************************************************************************************************************/\n\n#if FUSION_BUILD_MULTI\n#define CHECK_INTERVAL 20000\n#define CHECK_NUMBER   200\n#endif /* FUSION_BUILD_MULTI */\n\ntypedef struct {\n     bool           is_plugin; /* Hotplug in or not */\n     int            dev_id;    /* Input device ID */\n     struct timeval stamp;     /* Time stamp of event */\n} InputDeviceHotplugEvent;\n\ntypedef struct {\n     DFBInputDeviceKeySymbol      target;\n     DFBInputDeviceKeySymbol      result;\n} DeadKeyCombo;\n\ntypedef struct {\n     DFBInputDeviceKeySymbol      deadkey;\n     const DeadKeyCombo          *combos;\n} DeadKeyMap;\n\nstatic const DeadKeyCombo combos_grave[] = {\n     { DIKS_SPACE,     (unsigned char) '`' },\n     { DIKS_SMALL_A,   (unsigned char) '' },\n     { DIKS_SMALL_E,   (unsigned char) '' },\n     { DIKS_SMALL_I,   (unsigned char) '' },\n     { DIKS_SMALL_O,   (unsigned char) '' },\n     { DIKS_SMALL_U,   (unsigned char) '' },\n     { DIKS_CAPITAL_A, (unsigned char) '' },\n     { DIKS_CAPITAL_E, (unsigned char) '' },\n     { DIKS_CAPITAL_I, (unsigned char) '' },\n     { DIKS_CAPITAL_O, (unsigned char) '' },\n     { DIKS_CAPITAL_U, (unsigned char) '' },\n     { 0, 0 }\n};\n\nstatic const DeadKeyCombo combos_acute[] = {\n     { DIKS_SPACE,     (unsigned char) '\\'' },\n     { DIKS_SMALL_A,   (unsigned char) '' },\n     { DIKS_SMALL_E,   (unsigned char) '' },\n     { DIKS_SMALL_I,   (unsigned char) '' },\n     { DIKS_SMALL_O,   (unsigned char) '' },\n     { DIKS_SMALL_U,   (unsigned char) '' },\n     { DIKS_SMALL_Y,   (unsigned char) '' },\n     { DIKS_CAPITAL_A, (unsigned char) '' },\n     { DIKS_CAPITAL_E, (unsigned char) '' },\n     { DIKS_CAPITAL_I, (unsigned char) '' },\n     { DIKS_CAPITAL_O, (unsigned char) '' },\n     { DIKS_CAPITAL_U, (unsigned char) '' },\n     { DIKS_CAPITAL_Y, (unsigned char) '' },\n     { 0, 0 }\n};\n\nstatic const DeadKeyCombo combos_circumflex[] = {\n     { DIKS_SPACE,     (unsigned char) '^' },\n     { DIKS_SMALL_A,   (unsigned char) '' },\n     { DIKS_SMALL_E,   (unsigned char) '' },\n     { DIKS_SMALL_I,   (unsigned char) '' },\n     { DIKS_SMALL_O,   (unsigned char) '' },\n     { DIKS_SMALL_U,   (unsigned char) '' },\n     { DIKS_CAPITAL_A, (unsigned char) '' },\n     { DIKS_CAPITAL_E, (unsigned char) '' },\n     { DIKS_CAPITAL_I, (unsigned char) '' },\n     { DIKS_CAPITAL_O, (unsigned char) '' },\n     { DIKS_CAPITAL_U, (unsigned char) '' },\n     { 0, 0 }\n};\n\nstatic const DeadKeyCombo combos_diaeresis[] = {\n     { DIKS_SPACE,     (unsigned char) '' },\n     { DIKS_SMALL_A,   (unsigned char) '' },\n     { DIKS_SMALL_E,   (unsigned char) '' },\n     { DIKS_SMALL_I,   (unsigned char) '' },\n     { DIKS_SMALL_O,   (unsigned char) '' },\n     { DIKS_SMALL_U,   (unsigned char) '' },\n     { DIKS_CAPITAL_A, (unsigned char) '' },\n     { DIKS_CAPITAL_E, (unsigned char) '' },\n     { DIKS_CAPITAL_I, (unsigned char) '' },\n     { DIKS_CAPITAL_O, (unsigned char) '' },\n     { DIKS_CAPITAL_U, (unsigned char) '' },\n     { 0, 0 }\n};\n\nstatic const DeadKeyCombo combos_tilde[] = {\n     { DIKS_SPACE,     (unsigned char) '~' },\n     { DIKS_SMALL_A,   (unsigned char) '' },\n     { DIKS_SMALL_N,   (unsigned char) '' },\n     { DIKS_SMALL_O,   (unsigned char) '' },\n     { DIKS_CAPITAL_A, (unsigned char) '' },\n     { DIKS_CAPITAL_N, (unsigned char) '' },\n     { DIKS_CAPITAL_O, (unsigned char) '' },\n     { 0, 0 }\n};\n\nstatic const DeadKeyMap deadkey_maps[] = {\n     { DIKS_DEAD_GRAVE,      combos_grave },\n     { DIKS_DEAD_ACUTE,      combos_acute },\n     { DIKS_DEAD_CIRCUMFLEX, combos_circumflex },\n     { DIKS_DEAD_DIAERESIS,  combos_diaeresis },\n     { DIKS_DEAD_TILDE,      combos_tilde }\n};\n\nstatic ReactionFunc dfb_input_globals[MAX_INPUT_GLOBALS+1] = {\n     _dfb_windowstack_inputdevice_listener,\n     NULL\n};\n\n/* Define a lookup table to go from key IDs to names, used to look up the names provided in a loaded key table. */\nDirectFBKeySymbolNames(KeySymbolNames);\nDirectFBKeyIdentifierNames(KeyIdentifierNames);\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_input_add_global( ReactionFunc  func,\n                      int          *ret_index )\n{\n     int i;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p, %p )\\n\", __FUNCTION__, func, ret_index );\n\n     D_ASSERT( func != NULL );\n     D_ASSERT( ret_index != NULL );\n\n     for (i = 0; i < MAX_INPUT_GLOBALS; i++) {\n          if (!dfb_input_globals[i]) {\n               dfb_input_globals[i] = func;\n\n               D_DEBUG_AT( Core_Input, \"  -> index %d\\n\", i );\n\n               *ret_index = i;\n\n               return DFB_OK;\n          }\n     }\n\n     return DFB_LIMITEXCEEDED;\n}\n\nDFBResult\ndfb_input_set_global( ReactionFunc func,\n                      int          index )\n{\n     D_DEBUG_AT( Core_Input, \"%s( %p, %d )\\n\", __FUNCTION__, func, index );\n\n     D_ASSERT( func != NULL );\n     D_ASSERT( index >= 0 );\n     D_ASSERT( index < MAX_INPUT_GLOBALS );\n\n     D_ASSUME( dfb_input_globals[index] == NULL );\n\n     dfb_input_globals[index] = func;\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic DFBInputCore       *core_local;\nstatic DFBInputCoreShared *core_input;\n\nstatic void init_devices( CoreDFB *core );\nstatic void flush_keys  ( CoreInputDevice *device );\n\nstatic ReactionResult local_processing_hotplug( const void *msg_data, void *ctx );\n#if FUSION_BUILD_MULTI\nstatic Reaction       local_processing_react; /* Local reaction to hot-plug event */\n#endif /* FUSION_BUILD_MULTI */\n\nstatic DFBResult\ndfb_input_core_initialize( CoreDFB            *core,\n                           DFBInputCore       *data,\n                           DFBInputCoreShared *shared )\n{\n#if FUSION_BUILD_MULTI\n     DFBResult ret;\n#endif /* FUSION_BUILD_MULTI */\n\n     D_DEBUG_AT( Core_Input, \"%s( %p, %p, %p )\\n\", __FUNCTION__, core, data, shared );\n\n     D_ASSERT( data != NULL );\n     D_ASSERT( shared != NULL );\n\n     core_local = data;\n     core_input = shared;\n\n     data->core   = core;\n     data->shared = shared;\n\n     direct_modules_explore_directory( &dfb_input_drivers );\n\n#if FUSION_BUILD_MULTI\n     /* Create the reactor that responds input device hot-plug events. */\n     shared->reactor = fusion_reactor_new( sizeof(InputDeviceHotplugEvent), \"Input Hotplug\", dfb_core_world( core ) );\n     if (!shared->reactor) {\n          D_ERROR( \"Core/Input: fusion_reactor_new() failed!\\n\" );\n          return DFB_FAILURE;\n     }\n\n     fusion_reactor_add_permissions( shared->reactor, 0, FUSION_REACTOR_PERMIT_ATTACH_DETACH );\n\n     /* Attach the local processing function to the input hot-plug reactor. */\n     ret = fusion_reactor_attach( shared->reactor, local_processing_hotplug, core, &local_processing_react );\n     if (ret) {\n          fusion_reactor_destroy( shared->reactor );\n          D_ERROR( \"Core/Input: fusion_reactor_attach() failed!\\n\" );\n          return ret;\n     }\n#endif /* FUSION_BUILD_MULTI */\n\n     init_devices( core );\n\n     D_MAGIC_SET( data, DFBInputCore );\n     D_MAGIC_SET( shared, DFBInputCoreShared );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_input_core_join( CoreDFB            *core,\n                     DFBInputCore       *data,\n                     DFBInputCoreShared *shared )\n{\n#if FUSION_BUILD_MULTI\n     DFBResult ret;\n#endif /* FUSION_BUILD_MULTI */\n     int       i;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p, %p, %p )\\n\", __FUNCTION__, core, data, shared );\n\n     D_ASSERT( data != NULL );\n     D_MAGIC_ASSERT( shared, DFBInputCoreShared );\n     D_ASSERT( shared->reactor != NULL );\n\n     core_local = data;\n     core_input = shared;\n\n     data->core   = core;\n     data->shared = shared;\n\n#if FUSION_BUILD_MULTI\n     /* Attach the local processing function to the input hot-plug reactor. */\n     ret = fusion_reactor_attach( shared->reactor, local_processing_hotplug, core, &local_processing_react );\n     if (ret) {\n          D_ERROR( \"Core/Input: fusion_reactor_attach() failed!\\n\" );\n          return ret;\n     }\n#endif /* FUSION_BUILD_MULTI */\n\n     for (i = 0; i < shared->num; i++) {\n          CoreInputDevice       *device;\n          CoreInputDeviceShared *ishared = shared->devices[i];\n\n          device = D_CALLOC( 1, sizeof(CoreInputDevice) );\n          if (!device) {\n               D_OOM();\n               continue;\n          }\n\n          device->shared = ishared;\n\n#if FUSION_BUILD_MULTI\n          /* Increase the reference counter. */\n          fusion_ref_up( &ishared->ref, false );\n#endif /* FUSION_BUILD_MULTI */\n\n          /* Add it to the list. */\n          direct_list_append( &data->devices, &device->link );\n\n          D_MAGIC_SET( device, CoreInputDevice );\n     }\n\n     D_MAGIC_SET( data, DFBInputCore );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_input_core_shutdown( DFBInputCore *data,\n                         bool          emergency )\n{\n     DFBInputCoreShared     *shared;\n     CoreInputDevice        *device;\n     CoreInputDriver        *driver;\n     DirectLink             *next;\n     const InputDriverFuncs *funcs;\n     FusionSHMPoolShared    *pool;\n\n     D_UNUSED_P( shared );\n\n     D_DEBUG_AT( Core_Input, \"%s( %p, %semergency )\\n\", __FUNCTION__, data, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( data, DFBInputCore );\n     D_MAGIC_ASSERT( data->shared, DFBInputCoreShared );\n\n     shared = data->shared;\n\n     pool = dfb_core_shmpool( data->core );\n\n     /* Stop each input provider's hot-plug thread that supports device hot-plugging. */\n     direct_list_foreach_safe (driver, next, data->drivers) {\n          D_ASSERT( driver->funcs != NULL );\n\n          funcs = driver->funcs;\n\n          if (funcs->GetCapability && funcs->StopHotplug) {\n               if (IDC_HOTPLUG & funcs->GetCapability()) {\n                    D_DEBUG_AT( Core_Input, \"  -> stopping hot-plug detection in %s\\n\", driver->module->name );\n                    if (funcs->StopHotplug()) {\n                         D_ERROR( \"Core/Input: Failed to stop hot-plug detection in %s!\\n\", driver->module->name );\n                    }\n               }\n          }\n     }\n\n#if FUSION_BUILD_MULTI\n     fusion_reactor_detach( shared->reactor, &local_processing_react );\n     fusion_reactor_destroy( shared->reactor );\n#endif /* FUSION_BUILD_MULTI */\n\n     direct_list_foreach_safe (device, next, data->devices) {\n          CoreInputDeviceShared *ishared;\n\n          D_MAGIC_ASSERT( device, CoreInputDevice );\n          D_ASSERT( device->shared != NULL );\n          D_ASSERT( device->driver != NULL );\n\n          ishared = device->shared;\n          driver  = device->driver;\n\n          CoreInputDevice_Deinit_Dispatch( &ishared->call );\n\n          fusion_skirmish_destroy( &ishared->lock );\n\n          if (device->driver_data != NULL) {\n               void *driver_data;\n\n               D_ASSERT( driver->funcs != NULL );\n               D_ASSERT( driver->funcs->CloseDevice != NULL );\n\n               funcs = driver->funcs;\n\n               D_DEBUG_AT( Core_Input, \"  -> closing '%s' (%d) %d.%d (%s)\\n\",\n                           ishared->device_info.desc.name, ishared->num + 1,\n                           driver->info.version.major, driver->info.version.minor, driver->info.vendor );\n\n               driver_data = device->driver_data;\n               device->driver_data = NULL;\n               funcs->CloseDevice( driver_data );\n          }\n\n          if (!--driver->nr_devices) {\n               funcs = driver->funcs;\n\n               D_ASSERT( driver->funcs != NULL );\n               D_ASSERT( driver->funcs->GetAvailable != NULL );\n\n               funcs->GetAvailable();\n\n               direct_module_unref( driver->module );\n               D_FREE( driver );\n          }\n\n#if FUSION_BUILD_MULTI\n          fusion_ref_destroy( &ishared->ref );\n#else /* FUSION_BUILD_MULTI */\n          fusion_reactor_free( ishared->reactor );\n#endif /* FUSION_BUILD_MULTI */\n\n          fusion_reactor_free( ishared->reactor );\n\n          if (ishared->keymap.entries)\n               SHFREE( pool, ishared->keymap.entries );\n\n          if (ishared->axis_info)\n               SHFREE( pool, ishared->axis_info );\n\n          SHFREE( pool, ishared );\n\n          D_MAGIC_CLEAR( device );\n\n          D_FREE( device );\n     }\n\n     D_MAGIC_CLEAR( data );\n     D_MAGIC_CLEAR( shared );\n\n     core_local = NULL;\n     core_input = NULL;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_input_core_leave( DFBInputCore *data,\n                      bool          emergency )\n{\n     CoreInputDevice *device, *next;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p, %semergency )\\n\", __FUNCTION__, data, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( data, DFBInputCore );\n     D_MAGIC_ASSERT( data->shared, DFBInputCoreShared );\n\n#if FUSION_BUILD_MULTI\n     DFBInputCoreShared *shared = data->shared;\n     fusion_reactor_detach( shared->reactor, &local_processing_react );\n#endif /* FUSION_BUILD_MULTI */\n\n     direct_list_foreach_safe (device, next, data->devices) {\n          D_MAGIC_ASSERT( device, CoreInputDevice );\n          D_ASSERT( device->shared != NULL );\n\n#if FUSION_BUILD_MULTI\n          /* Decrease the ref between shared device and local device. */\n          CoreInputDeviceShared *ishared = device->shared;\n          fusion_ref_down( &ishared->ref, false );\n#endif /* FUSION_BUILD_MULTI */\n\n          D_FREE( device );\n     }\n\n     D_MAGIC_CLEAR( data );\n\n     core_local = NULL;\n     core_input = NULL;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_input_core_suspend( DFBInputCore *data )\n{\n     CoreInputDevice        *device;\n     CoreInputDriver        *driver;\n     const InputDriverFuncs *funcs;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p )\\n\", __FUNCTION__, data );\n\n     D_MAGIC_ASSERT( data, DFBInputCore );\n     D_MAGIC_ASSERT( data->shared, DFBInputCoreShared );\n\n     D_DEBUG_AT( Core_Input, \"  -> suspending...\\n\" );\n\n     /* Go through the drivers list and attempt to suspend all of the drivers that support the Suspend() function. */\n     direct_list_foreach (driver, data->drivers) {\n          DFBResult ret;\n\n          D_ASSERT( driver->funcs != NULL );\n          D_ASSERT( driver->funcs->Suspend != NULL );\n\n          funcs = driver->funcs;\n\n          ret = funcs->Suspend();\n          if (ret != DFB_OK && ret != DFB_UNSUPPORTED) {\n               D_DERROR( ret, \"Core/Input: Could not suspend '%s'!\\n\", driver->info.name );\n          }\n     }\n\n     direct_list_foreach (device, data->devices) {\n          CoreInputDeviceShared *ishared;\n\n          D_UNUSED_P( ishared );\n\n          D_MAGIC_ASSERT( device, CoreInputDevice );\n          D_ASSERT( device->shared != NULL );\n          D_ASSERT( device->driver != NULL );\n\n          ishared = device->shared;\n          driver  = device->driver;\n\n          if (device->driver_data != NULL) {\n               void *driver_data;\n\n               D_ASSERT( driver->funcs != NULL );\n               D_ASSERT( driver->funcs->CloseDevice != NULL );\n\n               funcs = driver->funcs;\n\n               D_DEBUG_AT( Core_Input, \"  -> closing '%s' (%d) %d.%d (%s)\\n\",\n                           ishared->device_info.desc.name, ishared->num + 1,\n                           driver->info.version.major, driver->info.version.minor, driver->info.vendor );\n\n               driver_data = device->driver_data;\n               device->driver_data = NULL;\n               funcs->CloseDevice( driver_data );\n          }\n\n          flush_keys( device );\n     }\n\n     D_DEBUG_AT( Core_Input, \"  -> suspended\\n\" );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_input_core_resume( DFBInputCore *data )\n{\n     DFBResult               ret;\n     CoreInputDevice        *device;\n     CoreInputDriver        *driver;\n     const InputDriverFuncs *funcs;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p )\\n\", __FUNCTION__, data );\n\n     D_MAGIC_ASSERT( data, DFBInputCore );\n     D_MAGIC_ASSERT( data->shared, DFBInputCoreShared );\n\n     D_DEBUG_AT( Core_Input, \"  -> resuming...\\n\" );\n\n     direct_list_foreach (device, data->devices) {\n          CoreInputDeviceShared *ishared;\n\n          D_MAGIC_ASSERT( device, CoreInputDevice );\n          D_ASSERT( device->shared != NULL );\n          D_ASSERT( device->driver != NULL );\n          D_ASSERT( device->driver->funcs != NULL );\n          D_ASSERT( device->driver->funcs->OpenDevice != NULL );\n\n          ishared = device->shared;\n          driver  = device->driver;\n          funcs   = driver->funcs;\n\n          D_DEBUG_AT( Core_Input, \"  -> reopening '%s' (%d) %d.%d (%s)\\n\",\n                      ishared->device_info.desc.name, ishared->num + 1,\n                      driver->info.version.major, driver->info.version.minor, driver->info.vendor );\n\n          D_ASSERT( device->driver_data == NULL );\n\n          ret = funcs->OpenDevice( device, ishared->num, &ishared->device_info, &device->driver_data );\n          if (ret) {\n               D_DERROR( ret, \"Core/Input: Failed reopening device '%s' during resume!\\n\",\n                         ishared->device_info.desc.name );\n               device->driver_data = NULL;\n          }\n     }\n\n     /* Go through the drivers list and attempt to resume all of the drivers that support the Resume() function. */\n     direct_list_foreach (driver, data->drivers) {\n          D_ASSERT( driver->funcs != NULL );\n          D_ASSERT( driver->funcs->Resume != NULL );\n\n          funcs = driver->funcs;\n\n          ret = funcs->Resume();\n          if (ret != DFB_OK && ret != DFB_UNSUPPORTED) {\n               D_DERROR( ret, \"Core/Input: Could not resume '%s'!\\n\", driver->info.name );\n          }\n     }\n\n     D_DEBUG_AT( Core_Input, \"  -> resumed\\n\" );\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic DFBInputDeviceKeymapEntry *get_keymap_entry( CoreInputDevice                 *device,\n                                                    int                              code );\nstatic DFBResult                  set_keymap_entry( CoreInputDevice                 *device,\n                                                    int                              code,\n                                                    const DFBInputDeviceKeymapEntry *entry );\nstatic DFBResult                  load_keymap     ( CoreInputDevice                 *device,\n                                                    char                            *filename );\nstatic DFBResult                  reload_keymap   ( CoreInputDevice                 *device );\n\nstatic bool lookup_from_table( CoreInputDevice *device, DFBInputEvent *event, DFBInputEventFlags lookup );\nstatic void fixup_key_event  ( CoreInputDevice *device, DFBInputEvent *event );\nstatic void fixup_mouse_event( CoreInputDevice *device, DFBInputEvent *event );\nstatic bool core_input_filter( CoreInputDevice *device, DFBInputEvent *event );\n\nvoid\ndfb_input_enumerate_devices( InputDeviceCallback         callback,\n                             void                       *ctx,\n                             DFBInputDeviceCapabilities  caps )\n{\n     CoreInputDevice       *device;\n     CoreInputDeviceShared *shared;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p, %p, 0x08%x )\\n\", __FUNCTION__, callback, ctx, caps );\n\n     D_ASSERT( core_input != NULL );\n\n     direct_list_foreach (device, core_local->devices) {\n          DFBInputDeviceCapabilities dev_caps;\n\n          D_MAGIC_ASSERT( device, CoreInputDevice );\n          D_ASSERT( device->shared != NULL );\n\n          shared = device->shared;\n\n          dev_caps = shared->device_info.desc.caps;\n\n          /* Always match if unclassified. */\n          if (!dev_caps)\n               dev_caps = DICAPS_ALL;\n\n          if ((dev_caps & caps) && callback( device, ctx ) == DFENUM_CANCEL)\n               break;\n     }\n}\n\nDirectResult\ndfb_input_attach( CoreInputDevice *device,\n                  ReactionFunc     func,\n                  void            *ctx,\n                  Reaction        *reaction )\n{\n     CoreInputDeviceShared *shared;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p, %p, %p, %p )\\n\", __FUNCTION__, device, func, ctx, reaction );\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->shared != NULL );\n\n     shared = device->shared;\n\n     return fusion_reactor_attach( shared->reactor, func, ctx, reaction );\n}\n\nDirectResult\ndfb_input_detach( CoreInputDevice *device,\n                  Reaction        *reaction )\n{\n     CoreInputDeviceShared *shared;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p, %p )\\n\", __FUNCTION__, device, reaction );\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->shared != NULL );\n\n     shared = device->shared;\n\n     return fusion_reactor_detach( shared->reactor, reaction );\n}\n\nDirectResult\ndfb_input_attach_global( CoreInputDevice *device,\n                         int              index,\n                         void            *ctx,\n                         GlobalReaction  *reaction )\n{\n     CoreInputDeviceShared *shared;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p, %d, %p, %p )\\n\", __FUNCTION__, device, index, ctx, reaction );\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->shared != NULL );\n\n     shared = device->shared;\n\n     return fusion_reactor_attach_global( shared->reactor, index, ctx, reaction );\n}\n\nDirectResult\ndfb_input_detach_global( CoreInputDevice *device,\n                         GlobalReaction  *reaction )\n{\n     CoreInputDeviceShared *shared;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p, %p )\\n\", __FUNCTION__, device, reaction );\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->shared != NULL );\n\n     shared = device->shared;\n\n     return fusion_reactor_detach_global( shared->reactor, reaction );\n}\n\nvoid\ndfb_input_dispatch( CoreInputDevice *device,\n                    DFBInputEvent   *event )\n{\n     CoreInputDeviceShared *shared;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p, %p )\\n\", __FUNCTION__, device, event );\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( event != NULL );\n\n     /* When a USB device is hot-removed, it is possible that there are pending events still being dispatched. */\n\n     shared = device->shared;\n\n     if (!shared) {\n          D_DEBUG_AT( Core_Input, \"  -> no shared data!\\n\" );\n          return;\n     }\n\n     D_ASSUME( shared->reactor != NULL );\n\n     if (!shared->reactor) {\n          D_DEBUG_AT( Core_Input, \"  -> no reactor!\\n\" );\n          return;\n     }\n\n     D_DEBUG_AT( Core_InputEvt, \"  -> (%02x) %s%s%s\\n\", event->type, dfb_input_event_type_name( event->type ),\n                 (event->flags & DIEF_FOLLOW) ? \" [FOLLOW]\" : \"\", (event->flags & DIEF_REPEAT) ? \" [REPEAT]\" : \"\" );\n\n     if (direct_log_domain_check( &Core_InputEvt )) {\n          if (event->flags & DIEF_TIMESTAMP)\n               D_DEBUG_AT( Core_InputEvt, \"  -> TIMESTAMP  %lu.%06lu\\n\",\n                           (unsigned long) event->timestamp.tv_sec, (unsigned long) event->timestamp.tv_usec );\n          if (event->flags & DIEF_AXISABS)\n               D_DEBUG_AT( Core_InputEvt, \"  -> AXISABS    %u at %d\\n\",  event->axis, event->axisabs );\n          if (event->flags & DIEF_AXISREL)\n               D_DEBUG_AT( Core_InputEvt, \"  -> AXISREL    %u by %d\\n\",  event->axis, event->axisrel );\n          if (event->flags & DIEF_KEYCODE)\n               D_DEBUG_AT( Core_InputEvt, \"  -> KEYCODE    %d\\n\",        event->key_code );\n          if (event->flags & DIEF_KEYID)\n               D_DEBUG_AT( Core_InputEvt, \"  -> KEYID      0x%04x\\n\",    event->key_id );\n          if (event->flags & DIEF_KEYSYMBOL)\n               D_DEBUG_AT( Core_InputEvt, \"  -> KEYSYMBOL  0x%04x\\n\",    event->key_symbol );\n          if (event->flags & DIEF_MODIFIERS)\n               D_DEBUG_AT( Core_InputEvt, \"  -> MODIFIERS  0x%04x\\n\",    event->modifiers );\n          if (event->flags & DIEF_LOCKS)\n               D_DEBUG_AT( Core_InputEvt, \"  -> LOCKS      0x%04x\\n\",    event->locks );\n          if (event->flags & DIEF_BUTTONS)\n               D_DEBUG_AT( Core_InputEvt, \"  -> BUTTONS    0x%04x\\n\",    event->buttons );\n          if (event->flags & DIEF_GLOBAL)\n               D_DEBUG_AT( Core_InputEvt, \"  -> GLOBAL\\n\" );\n     }\n\n     /* Fixup event. */\n\n     event->clazz     = DFEC_INPUT;\n     event->device_id = shared->id;\n\n     if (!(event->flags & DIEF_TIMESTAMP)) {\n          long long timestamp_us = direct_clock_get_abs_micros();\n\n          event->timestamp.tv_sec   = timestamp_us / 1000000;\n          event->timestamp.tv_usec  = timestamp_us % 1000000;\n          event->flags             |= DIEF_TIMESTAMP;\n     }\n\n     switch (event->type) {\n          case DIET_BUTTONPRESS:\n          case DIET_BUTTONRELEASE:\n               D_DEBUG_AT( Core_InputEvt, \"  -> BUTTON     0x%04x\\n\", event->button );\n\n               if (dfb_config->lefty) {\n                    if (event->button == DIBI_LEFT)\n                         event->button = DIBI_RIGHT;\n                    else if (event->button == DIBI_RIGHT)\n                         event->button = DIBI_LEFT;\n\n                    D_DEBUG_AT( Core_InputEvt, \"  -> LEFTY      0x%04x\\n\", event->button );\n               }\n\n          case DIET_AXISMOTION:\n               fixup_mouse_event( device, event );\n               break;\n\n          case DIET_KEYPRESS:\n          case DIET_KEYRELEASE:\n               if (dfb_config->capslock_meta) {\n                    if (shared->keymap.num_entries && (event->flags & DIEF_KEYCODE))\n                         lookup_from_table( device, event, (DIEF_KEYID | DIEF_KEYSYMBOL) & ~event->flags );\n\n                    if (event->key_id == DIKI_CAPS_LOCK || event->key_symbol == DIKS_CAPS_LOCK) {\n                         event->flags      |= DIEF_KEYID | DIEF_KEYSYMBOL;\n                         event->key_code    = -1;\n                         event->key_id      = DIKI_META_L;\n                         event->key_symbol  = DIKS_META;\n                    }\n               }\n\n               fixup_key_event( device, event );\n               break;\n\n          default:\n               ;\n     }\n\n     if (direct_log_domain_check( &Core_InputEvt )) {\n          if (event->flags & DIEF_TIMESTAMP)\n               D_DEBUG_AT( Core_InputEvt, \"  => TIMESTAMP  %lu.%06lu\\n\",\n                           (unsigned long) event->timestamp.tv_sec, (unsigned long) event->timestamp.tv_usec );\n          if (event->flags & DIEF_AXISABS)\n               D_DEBUG_AT( Core_InputEvt, \"  => AXISABS    %u at %d\\n\",  event->axis, event->axisabs );\n          if (event->flags & DIEF_AXISREL)\n               D_DEBUG_AT( Core_InputEvt, \"  => AXISREL    %u by %d\\n\",  event->axis, event->axisrel );\n          if (event->flags & DIEF_KEYCODE)\n               D_DEBUG_AT( Core_InputEvt, \"  => KEYCODE    %d\\n\",        event->key_code );\n          if (event->flags & DIEF_KEYID)\n               D_DEBUG_AT( Core_InputEvt, \"  => KEYID      0x%04x\\n\",    event->key_id );\n          if (event->flags & DIEF_KEYSYMBOL)\n               D_DEBUG_AT( Core_InputEvt, \"  => KEYSYMBOL  0x%04x\\n\",    event->key_symbol );\n          if (event->flags & DIEF_MODIFIERS)\n               D_DEBUG_AT( Core_InputEvt, \"  => MODIFIERS  0x%04x\\n\",    event->modifiers );\n          if (event->flags & DIEF_LOCKS)\n               D_DEBUG_AT( Core_InputEvt, \"  => LOCKS      0x%04x\\n\",    event->locks );\n          if (event->flags & DIEF_BUTTONS)\n               D_DEBUG_AT( Core_InputEvt, \"  => BUTTONS    0x%04x\\n\",    event->buttons );\n          if (event->flags & DIEF_GLOBAL)\n               D_DEBUG_AT( Core_InputEvt, \"  => GLOBAL\\n\" );\n     }\n\n     if (core_input_filter( device, event ))\n          D_DEBUG_AT( Core_InputEvt, \"  ****>> FILTERED\\n\" );\n     else\n          fusion_reactor_dispatch( shared->reactor, event, true, dfb_input_globals );\n}\n\nDFBInputDeviceID\ndfb_input_device_id( const CoreInputDevice *device )\n{\n     CoreInputDeviceShared *shared;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p )\\n\", __FUNCTION__, device );\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->shared != NULL );\n\n     shared = device->shared;\n\n     return shared->id;\n}\n\nCoreInputDevice *\ndfb_input_device_at( DFBInputDeviceID id )\n{\n     CoreInputDevice       *device;\n     CoreInputDeviceShared *shared;\n\n     D_DEBUG_AT( Core_Input, \"%s( 0x%02x )\\n\", __FUNCTION__, id );\n\n     D_ASSERT( core_input != NULL );\n\n     direct_list_foreach (device, core_local->devices) {\n          D_MAGIC_ASSERT( device, CoreInputDevice );\n          D_ASSERT( device->shared != NULL );\n\n          shared = device->shared;\n\n          if (shared->id == id)\n               return device;\n     }\n\n     return NULL;\n}\n\nDFBInputDeviceCapabilities\ndfb_input_device_caps( const CoreInputDevice *device )\n{\n     CoreInputDeviceShared *shared;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p )\\n\", __FUNCTION__, device );\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->shared != NULL );\n\n     shared = device->shared;\n\n     return shared->device_info.desc.caps;\n}\n\nvoid\ndfb_input_device_description( const CoreInputDevice     *device,\n                              DFBInputDeviceDescription *desc )\n{\n     CoreInputDeviceShared *shared;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p )\\n\", __FUNCTION__, device );\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->shared != NULL );\n\n     shared = device->shared;\n\n     *desc = shared->device_info.desc;\n}\n\nDFBResult\ndfb_input_device_get_keymap_entry( CoreInputDevice           *device,\n                                   int                        keycode,\n                                   DFBInputDeviceKeymapEntry *entry )\n{\n     DFBInputDeviceKeymapEntry *keymap_entry;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p, %d )\\n\", __FUNCTION__, device, keycode );\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( entry != NULL );\n\n     keymap_entry = get_keymap_entry( device, keycode );\n     if (!keymap_entry)\n          return DFB_FAILURE;\n\n     *entry = *keymap_entry;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_input_device_set_keymap_entry( CoreInputDevice                 *device,\n                                   int                              keycode,\n                                   const DFBInputDeviceKeymapEntry *entry )\n{\n     D_DEBUG_AT( Core_Input, \"%s( %p, %d )\\n\", __FUNCTION__, device, keycode );\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( entry != NULL );\n\n     return set_keymap_entry( device, keycode, entry );\n}\n\nDFBResult\ndfb_input_device_load_keymap( CoreInputDevice *device,\n                              char            *filename )\n{\n     D_DEBUG_AT( Core_Input, \"%s( %p, '%s' )\\n\", __FUNCTION__, device, filename );\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( filename != NULL );\n\n     return load_keymap( device, filename );\n}\n\nDFBResult\ndfb_input_device_reload_keymap( CoreInputDevice *device )\n{\n     CoreInputDeviceShared *shared;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p )\\n\", __FUNCTION__, device );\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->shared != NULL );\n\n     shared = device->shared;\n\n     D_INFO( \"DirectFB/Input: Reloading keymap for '%s' [0x%02x]...\\n\", shared->device_info.desc.name, shared->id );\n\n     return reload_keymap( device );\n}\n\nDFBResult\ndfb_input_device_get_state( CoreInputDevice  *device,\n                            InputDeviceState *ret_state )\n{\n     CoreInputDeviceShared *shared;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p )\\n\", __FUNCTION__, device );\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->shared != NULL );\n\n     shared = device->shared;\n\n     *ret_state = shared->state;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_input_device_set_configuration( CoreInputDevice            *device,\n                                    const DFBInputDeviceConfig *config )\n{\n     CoreInputDriver        *driver;\n     const InputDriverFuncs *funcs;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p, %p )\\n\", __FUNCTION__, device, config );\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->driver != NULL );\n     D_ASSERT( device->driver->funcs != NULL );\n\n     driver = device->driver;\n     funcs  = driver->funcs;\n\n     if (!funcs->SetConfiguration)\n          return DFB_UNSUPPORTED;\n\n     return funcs->SetConfiguration( device, device->driver_data, config );\n}\n\n/**********************************************************************************************************************/\n\nstatic void\ninput_add_device( CoreInputDevice *device )\n{\n     CoreInputDeviceShared *shared;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p )\\n\", __FUNCTION__, device );\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->shared != NULL );\n\n     shared = device->shared;\n\n     if (core_input->num == MAX_INPUTDEVICES) {\n          D_ERROR( \"Core/Input: Maximum number of devices reached!\\n\" );\n          return;\n     }\n\n     direct_list_append( &core_local->devices, &device->link );\n\n     core_input->devices[core_input->num++] = shared;\n}\n\nstatic void\nallocate_device_keymap( CoreDFB         *core,\n                        CoreInputDevice *device )\n{\n     int                        i;\n     DFBInputDeviceKeymapEntry *entries;\n     FusionSHMPoolShared       *pool = dfb_core_shmpool( core );\n     CoreInputDeviceShared     *shared;\n     DFBInputDeviceDescription *desc;\n     int                        num_entries;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p, %p )\\n\", __FUNCTION__, core, device );\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->shared != NULL );\n\n     shared = device->shared;\n\n     desc = &shared->device_info.desc;\n     num_entries = desc->max_keycode - desc->min_keycode + 1;\n\n     entries = SHCALLOC( pool, num_entries, sizeof(DFBInputDeviceKeymapEntry) );\n     if (!entries) {\n          D_OOSHM();\n          return;\n     }\n\n     /* Write -1 indicating entry is not fetched yet from driver. */\n     for (i = 0; i < num_entries; i++)\n          entries[i].code = -1;\n\n     shared->keymap.min_keycode = desc->min_keycode;\n     shared->keymap.max_keycode = desc->max_keycode;\n     shared->keymap.num_entries = num_entries;\n     shared->keymap.entries     = entries;\n\n#if FUSION_BUILD_MULTI\n     /* We need to fetch the whole map, otherwise a slave would try to. */\n     for (i = desc->min_keycode; i <= desc->max_keycode; i++)\n          get_keymap_entry( device, i );\n#endif /* FUSION_BUILD_MULTI */\n}\n\nstatic int\nmake_id( DFBInputDeviceID prefered )\n{\n     CoreInputDevice       *device;\n     CoreInputDeviceShared *shared;\n\n     D_DEBUG_AT( Core_Input, \"%s( 0x%02x )\\n\", __FUNCTION__, prefered );\n\n     D_ASSERT( core_input != NULL );\n\n     direct_list_foreach (device, core_local->devices) {\n          D_MAGIC_ASSERT( device, CoreInputDevice );\n          D_ASSERT( device->shared != NULL );\n\n          shared = device->shared;\n\n          if (shared->id == prefered)\n               return make_id( (prefered < DIDID_ANY) ? DIDID_ANY : (prefered + 1) );\n     }\n\n     return prefered;\n}\n\nstatic DFBResult\ninit_axes( CoreInputDevice *device )\n{\n     DFBResult               ret;\n     int                     i, num;\n     CoreInputDeviceShared  *shared;\n     CoreInputDriver        *driver;\n     const InputDriverFuncs *funcs;\n\n     D_DEBUG_AT( Core_Input, \"%s( %p )\\n\", __FUNCTION__, device );\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->shared != NULL );\n     D_ASSERT( device->driver != NULL );\n     D_ASSERT( device->driver->funcs != NULL );\n\n     shared = device->shared;\n     driver = device->driver;\n     funcs  = driver->funcs;\n\n     if (shared->device_info.desc.max_axis < 0)\n          return DFB_OK;\n\n     num = shared->device_info.desc.max_axis + 1;\n\n     shared->axis_info = SHCALLOC( dfb_core_shmpool(device->core), num, sizeof(InputDeviceAxisInfo) );\n     if (!shared->axis_info)\n          return D_OOSHM();\n\n     shared->axis_num = num;\n\n     if (funcs->GetAxisInfo) {\n          for (i = 0; i < num; i++) {\n               ret = funcs->GetAxisInfo( device, device->driver_data, i, &shared->axis_info[i] );\n               if (ret)\n                    D_DERROR( ret, \"Core/Input: Could not get axis info for '%s' [%u] on axis %d!\\n\",\n                              shared->device_info.desc.name, shared->id, i );\n          }\n     }\n\n     return DFB_OK;\n}\n\nstatic void\ninit_devices( CoreDFB *core )\n{\n     DirectModuleEntry   *module, *next;\n     FusionSHMPoolShared *pool = dfb_core_shmpool( core );\n\n     D_DEBUG_AT( Core_Input, \"%s( %p )\\n\", __FUNCTION__, core );\n\n     D_ASSERT( core_input != NULL );\n\n     direct_list_foreach_safe (module, next, dfb_input_drivers.entries) {\n          DFBResult               ret;\n          CoreInputDriver        *driver;\n          const InputDriverFuncs *funcs;\n          InputDriverCapability   driver_cap;\n          int                     n;\n\n          driver_cap = IDC_NONE;\n\n          funcs = direct_module_ref( module );\n          if (!funcs)\n               continue;\n\n          driver = D_CALLOC( 1, sizeof(CoreInputDriver) );\n          if (!driver) {\n               D_OOM();\n               direct_module_unref( module );\n               continue;\n          }\n\n          D_ASSERT( funcs->GetDriverInfo != NULL );\n\n          funcs->GetDriverInfo( &driver->info );\n\n          D_DEBUG_AT( Core_Input, \"  -> probing '%s'...\\n\", driver->info.name );\n\n          driver->nr_devices = funcs->GetAvailable();\n\n          /* If the input provider supports hot-plug, always load the module. */\n          if (!funcs->GetCapability) {\n               D_DEBUG_AT( Core_Input, \"  -> GetCapability() is NULL\\n\" );\n          }\n          else {\n               driver_cap = funcs->GetCapability();\n          }\n\n          if (!driver->nr_devices && !(driver_cap & IDC_HOTPLUG)) {\n               direct_module_unref( module );\n               D_FREE( driver );\n               continue;\n          }\n\n          D_DEBUG_AT( Core_Input, \"  -> %d available device(s) provided by '%s'\\n\",\n                      driver->nr_devices, driver->info.name );\n\n          driver->module = module;\n          driver->funcs  = funcs;\n\n          direct_list_prepend( &core_local->drivers, &driver->link );\n\n          for (n = 0; n < driver->nr_devices; n++) {\n               char                   buf[128];\n               CoreInputDevice       *device;\n               InputDeviceInfo        device_info;\n               CoreInputDeviceShared *shared;\n               void                  *driver_data;\n\n               device = D_CALLOC( 1, sizeof(CoreInputDevice) );\n               if (!device) {\n                    D_OOM();\n                    continue;\n               }\n\n               shared = SHCALLOC( pool, 1, sizeof(CoreInputDeviceShared) );\n               if (!shared) {\n                    D_OOSHM();\n                    D_FREE( device );\n                    continue;\n               }\n\n               device->core = core;\n\n               memset( &device_info, 0, sizeof(InputDeviceInfo) );\n\n               device_info.desc.min_keycode = -1;\n               device_info.desc.max_keycode = -1;\n\n               D_MAGIC_SET( device, CoreInputDevice );\n\n               if (funcs->OpenDevice( device, n, &device_info, &driver_data )) {\n                    SHFREE( pool, shared );\n                    D_MAGIC_CLEAR( device );\n                    D_FREE( device );\n                    continue;\n               }\n\n               D_DEBUG_AT( Core_Input, \"  -> opened '%s' (%d) %d.%d (%s)\\n\",\n                           device_info.desc.name, n + 1,\n                           driver->info.version.major, driver->info.version.minor, driver->info.vendor );\n\n               if (driver->nr_devices > 1)\n                    snprintf( buf, sizeof(buf), \"%s (%d)\", device_info.desc.name, n + 1 );\n               else\n                    snprintf( buf, sizeof(buf), \"%s\", device_info.desc.name );\n\n               /* Init skirmish. */\n               fusion_skirmish_init2( &shared->lock, buf, dfb_core_world( core ), fusion_config->secure_fusion );\n\n               /* Create reactor. */\n               shared->reactor = fusion_reactor_new( sizeof(DFBInputEvent), buf, dfb_core_world( core ) );\n\n               fusion_reactor_direct( shared->reactor, false );\n\n               fusion_reactor_add_permissions( shared->reactor, 0, FUSION_REACTOR_PERMIT_ATTACH_DETACH );\n\n               fusion_reactor_set_lock( shared->reactor, &shared->lock );\n\n               /* Init call. */\n               CoreInputDevice_Init_Dispatch( core, device, &shared->call );\n\n               /* Initialize shared data. */\n               shared->id          = make_id( device_info.prefered_id );\n               shared->num         = n;\n               shared->device_info = device_info;\n               shared->last_key    = DIKI_UNKNOWN;\n               shared->first_press = true;\n\n               /* Initialize local data. */\n               device->shared      = shared;\n               device->driver      = driver;\n               device->driver_data = driver_data;\n\n               D_INFO( \"DirectFB/Input: %s %d.%d (%s)\\n\", buf,\n                       driver->info.version.major, driver->info.version.minor, driver->info.vendor );\n\n#if FUSION_BUILD_MULTI\n               /* Initialize the ref between shared device and local device. */\n               snprintf( buf, sizeof(buf), \"Ref of input device(%u)\", shared->id );\n               fusion_ref_init( &shared->ref, buf, dfb_core_world( core ) );\n\n               fusion_ref_add_permissions( &shared->ref, 0, FUSION_REF_PERMIT_REF_UNREF_LOCAL );\n\n               /* Increase reference counter. */\n               fusion_ref_up( &shared->ref, false );\n#endif /* FUSION_BUILD_MULTI */\n\n               if (device_info.desc.min_keycode > device_info.desc.max_keycode) {\n                    D_BUG( \"min_keycode > max_keycode\" );\n                    device_info.desc.min_keycode = -1;\n                    device_info.desc.max_keycode = -1;\n               }\n               else if (device_info.desc.min_keycode >= 0 && device_info.desc.max_keycode >= 0)\n                    allocate_device_keymap( core, device );\n\n               init_axes( device );\n\n               /* Add it to the list. */\n               input_add_device( device );\n          }\n\n          /* If the driver supports hot-plug, launch its hot-plug thread to respond to hot-plug events. */\n          if (driver_cap == IDC_HOTPLUG) {\n               ret = funcs->LaunchHotplug( core, driver );\n\n               /* On failure, the input provider can still be used without hot-plug. */\n               if (ret) {\n                    D_INFO( \"DirectFB/Input: Failed to enable hot-plug detection with %s\\n\", driver->info.name );\n               }\n               else {\n                    D_INFO( \"DirectFB/Input: Hot-plug detection enabled with %s\\n\", driver->info.name );\n               }\n          }\n     }\n}\n\nstatic void\nrelease_key( CoreInputDevice             *device,\n             DFBInputDeviceKeyIdentifier  id )\n{\n     DFBInputEvent evt;\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n\n     evt.type = DIET_KEYRELEASE;\n\n     if (DFB_KEY_TYPE( id ) == DIKT_IDENTIFIER) {\n          evt.flags  = DIEF_KEYID;\n          evt.key_id = id;\n     }\n     else {\n          evt.flags      = DIEF_KEYSYMBOL;\n          evt.key_symbol = id;\n     }\n\n     dfb_input_dispatch( device, &evt );\n}\n\nstatic void\nflush_keys( CoreInputDevice *device )\n{\n     CoreInputDeviceShared *shared;\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->shared != NULL );\n\n     shared = device->shared;\n\n     if (shared->state.modifiers_l) {\n          if (shared->state.modifiers_l & DIMM_ALT)\n               release_key( device, DIKI_ALT_L );\n\n          if (shared->state.modifiers_l & DIMM_CONTROL)\n               release_key( device, DIKI_CONTROL_L );\n\n          if (shared->state.modifiers_l & DIMM_HYPER)\n               release_key( device, DIKI_HYPER_L );\n\n          if (shared->state.modifiers_l & DIMM_META)\n               release_key( device, DIKI_META_L );\n\n          if (shared->state.modifiers_l & DIMM_SHIFT)\n               release_key( device, DIKI_SHIFT_L );\n\n          if (shared->state.modifiers_l & DIMM_SUPER)\n               release_key( device, DIKI_SUPER_L );\n     }\n\n     if (shared->state.modifiers_r) {\n          if (shared->state.modifiers_r & DIMM_ALTGR)\n               release_key( device, DIKS_ALTGR );\n\n          if (shared->state.modifiers_r & DIMM_ALT)\n               release_key( device, DIKI_ALT_R );\n\n          if (shared->state.modifiers_r & DIMM_CONTROL)\n               release_key( device, DIKI_CONTROL_R );\n\n          if (shared->state.modifiers_r & DIMM_HYPER)\n               release_key( device, DIKI_HYPER_R );\n\n          if (shared->state.modifiers_r & DIMM_META)\n               release_key( device, DIKI_META_R );\n\n          if (shared->state.modifiers_r & DIMM_SHIFT)\n               release_key( device, DIKI_SHIFT_R );\n\n          if (shared->state.modifiers_r & DIMM_SUPER)\n               release_key( device, DIKI_SUPER_R );\n     }\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_input_create_device( int      device_index,\n                         CoreDFB *core_in,\n                         void    *driver_in )\n{\n     DFBResult               ret;\n     char                    buf[128];\n     CoreInputDevice        *device;\n     InputDeviceInfo         device_info;\n     CoreInputDeviceShared  *shared;\n     CoreInputDriver        *driver = driver_in;\n     void                   *driver_data;\n     const InputDriverFuncs *funcs;\n     FusionSHMPoolShared    *pool;\n\n     D_DEBUG_AT( Core_Input, \"%s()\\n\", __FUNCTION__ );\n\n     funcs = driver->funcs;\n     pool  = dfb_core_shmpool( core_in );\n\n     if (!funcs) {\n          return DFB_FAILURE;\n     }\n\n     device = D_CALLOC( 1, sizeof(CoreInputDevice) );\n     if (!device) {\n          return D_OOM();\n     }\n\n     shared = SHCALLOC( pool, 1, sizeof(CoreInputDeviceShared) );\n     if (!shared) {\n          D_FREE( device );\n          return D_OOSHM();\n     }\n\n     device->core = core_in;\n\n     memset( &device_info, 0, sizeof(InputDeviceInfo) );\n\n     device_info.desc.min_keycode = -1;\n     device_info.desc.max_keycode = -1;\n\n     D_MAGIC_SET( device, CoreInputDevice );\n\n     if (funcs->OpenDevice( device, device_index, &device_info, &driver_data )) {\n          SHFREE( pool, shared );\n          D_MAGIC_CLEAR( device );\n          D_FREE( device );\n          D_ERROR( \"Core/Input: Could not open device!\\n\" );\n          return DFB_FAILURE;\n     }\n\n     snprintf( buf, sizeof(buf), \"%s (%d)\", device_info.desc.name, device_index );\n\n     /* Init skirmish. */\n     ret = fusion_skirmish_init2( &shared->lock, buf, dfb_core_world( device->core ), fusion_config->secure_fusion );\n     if (ret) {\n          funcs->CloseDevice( driver_data );\n          SHFREE( pool, shared );\n          D_MAGIC_CLEAR( device );\n          D_FREE( device );\n          D_ERROR( \"Core/Input: fusion_skirmish_init2() failed!\\n\" );\n          return DFB_FAILURE;\n     }\n\n     /* Create reactor. */\n     shared->reactor = fusion_reactor_new( sizeof(DFBInputEvent), buf, dfb_core_world( device->core ) );\n     if (!shared->reactor) {\n          funcs->CloseDevice( driver_data );\n          SHFREE( pool, shared );\n          D_MAGIC_CLEAR( device );\n          D_FREE( device );\n          fusion_skirmish_destroy( &shared->lock );\n          D_ERROR( \"Core/Input: fusion_reactor_new() failed!\\n\" );\n          return DFB_FAILURE;\n     }\n\n     fusion_reactor_direct( shared->reactor, false );\n\n     fusion_reactor_add_permissions( shared->reactor, 0, FUSION_REACTOR_PERMIT_ATTACH_DETACH );\n\n     fusion_reactor_set_lock( shared->reactor, &shared->lock );\n\n     /* Init call. */\n     CoreInputDevice_Init_Dispatch( device->core, device, &shared->call );\n\n     /* Initialize shared data. */\n     shared->id          = make_id( device_info.prefered_id );\n     shared->num         = device_index;\n     shared->device_info = device_info;\n     shared->last_key    = DIKI_UNKNOWN;\n     shared->first_press = true;\n\n     /* Initialize local data. */\n     device->shared      = shared;\n     device->driver      = driver;\n     device->driver_data = driver_data;\n\n     D_INFO( \"DirectFB/Input: %s %d.%d (%s)\\n\", buf,\n             driver->info.version.major, driver->info.version.minor, driver->info.vendor );\n\n#if FUSION_BUILD_MULTI\n     snprintf( buf, sizeof(buf), \"Ref of input device(%u)\", shared->id );\n     fusion_ref_init( &shared->ref, buf, dfb_core_world( core_in ) );\n     fusion_ref_add_permissions( &shared->ref, 0, FUSION_REF_PERMIT_REF_UNREF_LOCAL );\n     fusion_ref_up( &shared->ref, false );\n#endif /* FUSION_BUILD_MULTI */\n\n     if (device_info.desc.min_keycode > device_info.desc.max_keycode) {\n          D_BUG( \"min_keycode > max_keycode\" );\n          device_info.desc.min_keycode = -1;\n          device_info.desc.max_keycode = -1;\n     }\n     else if (device_info.desc.min_keycode >= 0 && device_info.desc.max_keycode >= 0)\n          allocate_device_keymap( device->core, device );\n\n     /* Add it into local device list and shared dev array. */\n     input_add_device( device );\n     driver->nr_devices++;\n\n     D_DEBUG_AT( Core_Input, \"  -> add new input device with dev_id = %u\\n\", shared->id );\n\n     /* Setup the hot-plug in message. */\n     InputDeviceHotplugEvent message;\n     long long               timestamp_us = direct_clock_get_abs_micros();\n\n     message.is_plugin = true;\n     message.dev_id = shared->id;\n     message.stamp.tv_sec  = timestamp_us / 1000000;\n     message.stamp.tv_usec = timestamp_us % 1000000;\n\n     /* Send the hot-plug in message. */\n#if FUSION_BUILD_MULTI\n     fusion_reactor_dispatch( core_input->reactor, &message, true, NULL );\n#else /* FUSION_BUILD_MULTI */\n     local_processing_hotplug( &message, core_in );\n#endif /* FUSION_BUILD_MULTI */\n\n     return DFB_OK;\n}\n\n/*\n * Tell whether the DFB input device handling of the system input device indicated by 'device_index' is already created.\n */\nstatic CoreInputDevice *\nsearch_device_created( int   device_index,\n                       void *driver_in )\n{\n     CoreInputDevice        *device, *next;\n     CoreInputDeviceShared  *shared;\n     CoreInputDriver        *driver;\n     const InputDriverFuncs *funcs;\n\n     D_UNUSED_P( shared );\n\n     D_ASSERT( driver_in != NULL );\n\n     direct_list_foreach_safe (device, next, core_local->devices) {\n          D_ASSERT( device->shared != NULL );\n          D_ASSERT( device->driver != NULL );\n\n          shared = device->shared;\n          driver = device->driver;\n\n          if (driver != driver_in)\n               continue;\n\n          if (device->driver_data == NULL) {\n               D_DEBUG_AT( Core_Input, \"  -> the device %u has been closed!\\n\", shared->id );\n               return NULL;\n          }\n\n          D_ASSERT( device->driver->funcs != NULL );\n\n          funcs = driver->funcs;\n\n          if (funcs->IsCreated && !funcs->IsCreated(device_index, device->driver_data)) {\n               return device;\n          }\n     }\n\n     return NULL;\n}\n\nDFBResult\ndfb_input_remove_device( int   device_index,\n                         void *driver_in )\n{\n     CoreInputDevice        *device;\n     CoreInputDeviceShared  *shared;\n     CoreInputDriver        *driver;\n     const InputDriverFuncs *funcs;\n     FusionSHMPoolShared    *pool;\n     int                     i;\n     int                     found = 0;\n     int                     device_id;\n\n     D_DEBUG_AT( Core_Input, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( driver_in != NULL );\n\n     device = search_device_created( device_index, driver_in );\n     if (device == NULL) {\n          D_DEBUG_AT( Core_Input, \"  -> failed to find the device[%d] or the device is closed\\n\", device_index );\n          return DFB_FAILURE;\n     }\n\n     D_ASSERT( device->shared != NULL );\n     D_ASSERT( device->driver != NULL );\n     D_ASSERT( device->driver->funcs != NULL );\n\n     shared = device->shared;\n     driver = device->driver;\n     funcs  = driver->funcs;\n\n     pool = dfb_core_shmpool( device->core );\n     device_id = shared->id;\n\n     D_DEBUG_AT( Core_Input, \"  -> find the device with dev_id = %d\\n\", device_id );\n\n     funcs->CloseDevice( device->driver_data );\n\n     driver->nr_devices--;\n\n     /* Setup the hot-plug out message. */\n     InputDeviceHotplugEvent message;\n     long long               timestamp_us = direct_clock_get_abs_micros();\n\n     message.is_plugin = false;\n     message.dev_id = device_id;\n     message.stamp.tv_sec  = timestamp_us / 1000000;\n     message.stamp.tv_usec = timestamp_us % 1000000;\n\n     /* Send the hot-plug out message. */\n#if FUSION_BUILD_MULTI\n     fusion_reactor_dispatch( core_input->reactor, &message, true, NULL );\n\n     int loop = CHECK_NUMBER;\n\n     while (--loop) {\n          if (fusion_ref_zero_trylock( &shared->ref ) == DR_OK) {\n               fusion_ref_unlock( &shared->ref );\n               break;\n          }\n\n          usleep( CHECK_INTERVAL );\n     }\n\n     if (!loop)\n          D_DEBUG_AT( Core_Input, \"  -> the device can be connected by others\\n\" );\n\n     fusion_ref_destroy( &shared->ref );\n#else /* FUSION_BUILD_MULTI */\n     local_processing_hotplug( &message, device->core );\n#endif /* FUSION_BUILD_MULTI */\n\n     /* Remove the device from shared array. */\n     for (i = 0; i < core_input->num; i++) {\n          if (!found && (core_input->devices[i]->id == shared->id))\n               found = 1;\n\n          if (found)\n               core_input->devices[i] = core_input->devices[(i + 1) % MAX_INPUTDEVICES];\n     }\n\n     if (found)\n          core_input->devices[core_input->num -1] = NULL;\n\n     core_input->num--;\n\n     CoreInputDevice_Deinit_Dispatch( &shared->call );\n\n     fusion_skirmish_destroy( &shared->lock );\n\n     fusion_reactor_free( shared->reactor );\n\n     if (shared->keymap.entries)\n          SHFREE( pool, shared->keymap.entries );\n\n     SHFREE( pool, shared );\n\n     D_DEBUG_AT( Core_Input, \"  -> successfully remove the device with dev_id = %d\\n\", device_id );\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\n/*\n * Create local input device and add it into the local input devices list.\n */\nstatic CoreInputDevice *\nadd_device_into_local_list( int dev_id )\n{\n     int i;\n\n     for (i = 0; i < core_input->num; i++) {\n          if (core_input->devices[i]->id == dev_id) {\n               CoreInputDevice       *device;\n               CoreInputDeviceShared *shared;\n\n               D_DEBUG_AT( Core_Input, \"  -> find the device with dev_id = %d, and allocate local device\\n\", dev_id );\n\n               shared = core_input->devices[i];\n\n               device = D_CALLOC( 1, sizeof(CoreInputDevice) );\n               if (!device)\n                   return NULL;\n\n               device->shared = shared;\n\n#if FUSION_BUILD_MULTI\n               /* Increase the reference counter. */\n               fusion_ref_up( &shared->ref, false );\n#endif /* FUSION_BUILD_MULTI */\n\n               /* Add it to the list. */\n               direct_list_append( &core_local->devices, &device->link );\n\n               D_MAGIC_SET( device, CoreInputDevice );\n\n               return device;\n          }\n     }\n\n     return NULL;\n}\n\n/*\n * Local input device function that handles hot-plug in/out messages.\n */\nstatic ReactionResult\nlocal_processing_hotplug( const void *msg_data,\n                          void       *ctx )\n{\n     const InputDeviceHotplugEvent *message = msg_data;\n     CoreInputDevice               *device;\n\n     D_DEBUG_AT( Core_Input, \"%s()\\n\", __FUNCTION__ );\n\n     D_DEBUG_AT( Core_Input, \"  -> <PID:%6d> hotplug-in:%d device_id=%d message\\n\",\n                 getpid(), message->is_plugin, message->dev_id );\n\n     if (message->is_plugin) {\n          device = dfb_input_device_at( message->dev_id );\n\n          if (!device) {\n               /* Update local device list according to shared devices array. */\n               if (!(device = add_device_into_local_list( message->dev_id ))) {\n                    D_ERROR( \"Core/Input: Failed to update local device list!\\n\" );\n                    return RS_DROP;\n               }\n          }\n\n          /* Attach the device to event buffer containers. */\n          eventbuffer_containers_attach_device( device );\n\n          /* Attach the device to stack containers.  */\n          stack_containers_attach_device( device );\n     }\n     else {\n          device = dfb_input_device_at( message->dev_id );\n\n          if (device) {\n               direct_list_remove( &core_local->devices, &device->link );\n\n               eventbuffer_containers_detach_device( device );\n\n               stack_containers_detach_device( device );\n\n#if FUSION_BUILD_MULTI\n               /* Decrease reference counter. */\n               CoreInputDeviceShared *shared = shared = device->shared;\n               fusion_ref_down( &shared->ref, false );\n#endif /* FUSION_BUILD_MULTI */\n\n               D_MAGIC_CLEAR( device );\n               D_FREE( device );\n          }\n          else\n               D_ERROR( \"Core/Input: Can't find the device to be removed!\\n\" );\n     }\n\n     return RS_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic DFBInputDeviceKeyIdentifier symbol_to_id( DFBInputDeviceKeySymbol     symbol );\nstatic DFBInputDeviceKeySymbol     id_to_symbol( DFBInputDeviceKeyIdentifier id,\n                                                 DFBInputDeviceModifierMask  modifiers,\n                                                 DFBInputDeviceLockState     locks );\n\n/*\n * Get a single keymap entry with the code-entry pair.\n */\nstatic DFBInputDeviceKeymapEntry *\nget_keymap_entry( CoreInputDevice *device,\n                  int              code )\n{\n     InputDeviceKeymap         *map;\n     DFBInputDeviceKeymapEntry *entry;\n     CoreInputDeviceShared     *shared;\n     CoreInputDriver           *driver;\n     const InputDriverFuncs    *funcs;\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->shared != NULL );\n     D_ASSERT( device->shared->keymap.entries != NULL );\n     D_ASSERT( device->driver != NULL );\n     D_ASSERT( device->driver->funcs != NULL );\n\n     shared = device->shared;\n     driver = device->driver;\n     funcs  = driver->funcs;\n\n     map = &shared->keymap;\n\n     /* Safety check. */\n     if (!device->driver_data)\n          return NULL;\n\n     if (code < map->min_keycode || code > map->max_keycode)\n          return NULL;\n\n     /* Point to right array index. */\n     entry = &map->entries[code - map->min_keycode];\n\n     /* Need to initialize. */\n     if (entry->code != code) {\n          DFBResult  ret;\n\n          /* Write keycode to entry. */\n          entry->code = code;\n\n          /* Fetch entry from driver. */\n          ret = funcs->GetKeymapEntry( device, device->driver_data, entry );\n          if (ret)\n               return NULL;\n\n          /* Drivers may leave this blank. */\n          if (entry->identifier == DIKI_UNKNOWN)\n               entry->identifier = symbol_to_id( entry->symbols[DIKSI_BASE] );\n\n          if (entry->symbols[DIKSI_BASE_SHIFT] == DIKS_NULL)\n               entry->symbols[DIKSI_BASE_SHIFT] = entry->symbols[DIKSI_BASE];\n\n          if (entry->symbols[DIKSI_ALT] == DIKS_NULL)\n               entry->symbols[DIKSI_ALT] = entry->symbols[DIKSI_BASE];\n\n          if (entry->symbols[DIKSI_ALT_SHIFT] == DIKS_NULL)\n               entry->symbols[DIKSI_ALT_SHIFT] = entry->symbols[DIKSI_ALT];\n     }\n\n     return entry;\n}\n\n/*\n * Replace a single keymap entry with the code-entry pair.\n */\nstatic DFBResult\nset_keymap_entry( CoreInputDevice                 *device,\n                  int                              code,\n                  const DFBInputDeviceKeymapEntry *entry )\n{\n     InputDeviceKeymap     *map;\n     CoreInputDeviceShared *shared;\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->shared != NULL );\n     D_ASSERT( device->shared->keymap.entries != NULL );\n\n     shared = device->shared;\n\n     map = &shared->keymap;\n\n     /* Sanity check. */\n     if (code < map->min_keycode || code > map->max_keycode)\n          return DFB_FAILURE;\n\n     /* Copy the entry to the map. */\n     map->entries[code - map->min_keycode] = *entry;\n\n     return DFB_OK;\n}\n\nstatic DFBInputDeviceKeyIdentifier\nlookup_keyidentifier( char *identifiername )\n{\n     int i;\n\n     /* We want uppercase. */\n     for (i = 0; i < strlen( identifiername ); i++)\n          if (identifiername[i] >= 'a' && identifiername[i] <= 'z')\n               identifiername[i] = identifiername[i] - 'a' + 'A';\n\n     for (i = 0; i < D_ARRAY_SIZE(KeyIdentifierNames); i++) {\n          if (strcmp( identifiername, KeyIdentifierNames[i].name ) == 0)\n               return KeyIdentifierNames[i].identifier;\n     }\n\n     return DIKI_UNKNOWN;\n}\n\nstatic DFBInputDeviceKeySymbol\nlookup_keysymbol( char *symbolname )\n{\n     int i;\n\n     /* We want uppercase. */\n     for (i = 0; i < strlen( symbolname ); i++)\n          if (symbolname[i] >= 'a' && symbolname[i] <= 'z')\n               symbolname[i] = symbolname[i] - 'a' + 'A';\n\n     for (i = 0; i < D_ARRAY_SIZE(KeySymbolNames); i++) {\n          if (strcmp( symbolname, KeySymbolNames[i].name ) == 0)\n               return KeySymbolNames[i].symbol;\n     }\n\n     /* Not found, maybe starting with 0x for raw conversion. We are already at uppercase. */\n     if (symbolname[0] == '0' && symbolname[1] == 'X') {\n          int code = 0;\n\n          symbolname += 2;\n\n          while (*symbolname) {\n               if (*symbolname >= '0' && *symbolname <= '9') {\n                    code = code * 16 + *symbolname - '0';\n               }\n               else if (*symbolname >= 'A' && *symbolname <= 'F') {\n                    code = code * 16 + *symbolname - 'A' + 10;\n               }\n               else {\n                    /* Invalid character. */\n                    return DIKS_NULL;\n               }\n               symbolname++;\n          }\n          return code;\n     }\n\n     return DIKS_NULL;\n}\n\n/*\n * Replace the complete current keymap with a keymap from a file.\n */\nstatic DFBResult\nload_keymap( CoreInputDevice *device,\n             char            *filename )\n{\n     DFBResult                ret;\n     DirectFile               fd;\n     InputDeviceKeymap       *map;\n     CoreInputDeviceShared   *shared;\n     DFBInputDeviceLockState  lockstate = 0;\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->shared != NULL );\n     D_ASSERT( device->shared->keymap.entries != NULL );\n\n     shared = device->shared;\n\n     map = &shared->keymap;\n\n     /* Open the file. */\n     ret = direct_file_open( &fd, filename, O_RDONLY, 0 );\n     if (ret)\n          return ret;\n\n     /* Read the file, line by line, and consume the mentioned scancodes. */\n     while (1) {\n          int  i;\n          int  dummy;\n          char buffer[201];\n          int  keycode;\n          char diki[201];\n          char diks[4][201];\n\n          DFBInputDeviceKeymapEntry entry = { .code = 0 };\n\n          ret = direct_file_get_string( &fd, buffer, 200 );\n          if (ret) {\n               if (ret == DFB_EOF) {\n                    direct_file_close( &fd );\n                    return DFB_OK;\n               }\n               direct_file_close( &fd );\n               return ret;\n          }\n\n          /* Comment or empty line. */\n          if (buffer[0] == '#' || strcmp( buffer, \"\\n\" ) == 0)\n               continue;\n\n          /* Check for lock state change. */\n          if (!strncmp( buffer, \"capslock:\", 9)) { lockstate |=  DILS_CAPS; continue; }\n          if (!strncmp( buffer, \":capslock\", 9)) { lockstate &= ~DILS_CAPS; continue; }\n          if (!strncmp( buffer, \"numlock:\", 8))  { lockstate |=  DILS_NUM;  continue; }\n          if (!strncmp( buffer, \":numlock\", 8))  { lockstate &= ~DILS_NUM;  continue; }\n\n          i = sscanf( buffer, \" keycode %i = %s = %s %s %s %s %i\\n\",\n                      &keycode, diki, diks[0], diks[1], diks[2], diks[3], &dummy );\n\n          if (i < 3 || i > 6) {\n               /* We want 1 to 4 key symbols. */\n               D_INFO( \"DirectFB/Input: skipped erroneous input line %s\\n\", buffer );\n               continue;\n          }\n\n          if (keycode > map->max_keycode || keycode < map->min_keycode) {\n               D_INFO( \"DirectFB/Input: skipped keycode %d out of range\\n\", keycode );\n               continue;\n          }\n\n          entry.code       = keycode;\n          entry.locks      = lockstate;\n          entry.identifier = lookup_keyidentifier( diki );\n\n          switch (i) {\n               case 6:  entry.symbols[3] = lookup_keysymbol( diks[3] );\n               case 5:  entry.symbols[2] = lookup_keysymbol( diks[2] );\n               case 4:  entry.symbols[1] = lookup_keysymbol( diks[1] );\n               case 3:  entry.symbols[0] = lookup_keysymbol( diks[0] );\n                    /* fall through */\n          }\n\n          switch (i) {\n               case 3:  entry.symbols[1] = entry.symbols[0];\n               case 4:  entry.symbols[2] = entry.symbols[0];\n               case 5:  entry.symbols[3] = entry.symbols[1];\n                    /* fall through */\n          }\n\n          ret = CoreInputDevice_SetKeymapEntry( device, keycode, &entry );\n          if (ret)\n               return ret;\n     }\n}\n\n/*\n * Reload the keymap.\n */\nstatic DFBResult\nreload_keymap( CoreInputDevice *device )\n{\n     int                    i;\n     InputDeviceKeymap     *map;\n     CoreInputDeviceShared *shared;\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->shared != NULL );\n     D_ASSERT( device->shared->keymap.entries != NULL );\n\n     shared = device->shared;\n\n     map = &shared->keymap;\n\n     if (shared->device_info.desc.min_keycode < 0 || shared->device_info.desc.max_keycode < 0)\n          return DFB_UNSUPPORTED;\n\n     /* Write -1 indicating entry is not fetched yet from driver. */\n     for (i = 0; i < shared->keymap.num_entries; i++)\n          map->entries[i].code = -1;\n\n     /* Fetch the whole map. */\n     for (i = shared->keymap.min_keycode; i <= shared->keymap.max_keycode; i++)\n          get_keymap_entry( device, i );\n\n     D_INFO( \"DirectFB/Input: Reloaded keymap for '%s' [0x%02x]\\n\", shared->device_info.desc.name, shared->id );\n\n     return DFB_OK;\n}\n\nstatic bool\nlookup_from_table( CoreInputDevice    *device,\n                   DFBInputEvent      *event,\n                   DFBInputEventFlags  lookup )\n{\n     DFBInputDeviceKeymapEntry *entry;\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( event != NULL );\n\n     /* Fetch the entry from the keymap, possibly calling the driver. */\n     entry = get_keymap_entry( device, event->key_code );\n     if (!entry)\n          return false;\n\n     /* Lookup identifier. */\n     if (lookup & DIEF_KEYID)\n          event->key_id = entry->identifier;\n\n     /* Lookup symbol. */\n     if (lookup & DIEF_KEYSYMBOL) {\n          DFBInputDeviceKeymapSymbolIndex index =\n               (event->modifiers & DIMM_ALTGR) ? DIKSI_ALT : DIKSI_BASE;\n\n          if (!(event->modifiers & DIMM_SHIFT) ^ !(entry->locks & event->locks))\n               index++;\n\n          /* Don't modify modifiers. */\n          if (DFB_KEY_TYPE( entry->symbols[DIKSI_BASE] ) == DIKT_MODIFIER)\n               event->key_symbol = entry->symbols[DIKSI_BASE];\n          else\n               event->key_symbol = entry->symbols[index];\n     }\n\n     return true;\n}\n\nstatic int\nfind_key_code_by_id( CoreInputDevice             *device,\n                     DFBInputDeviceKeyIdentifier  id )\n{\n     int                    i;\n     InputDeviceKeymap     *map;\n     CoreInputDeviceShared *shared;\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->shared != NULL );\n\n     shared = device->shared;\n\n     map = &shared->keymap;\n\n     for (i = 0; i < map->num_entries; i++) {\n          DFBInputDeviceKeymapEntry *entry = &map->entries[i];\n\n          if (entry->identifier == id)\n               return entry->code;\n     }\n\n     return -1;\n}\n\nstatic int\nfind_key_code_by_symbol( CoreInputDevice         *device,\n                         DFBInputDeviceKeySymbol  symbol )\n{\n     int                    i;\n     InputDeviceKeymap     *map;\n     CoreInputDeviceShared *shared;\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( core_input != NULL );\n     D_ASSERT( device->shared != NULL );\n     D_ASSERT( device->shared->keymap.entries != NULL );\n\n     shared = device->shared;\n\n     map = &shared->keymap;\n\n     for (i = 0; i < map->num_entries; i++) {\n          int                        n;\n          DFBInputDeviceKeymapEntry *entry = &map->entries[i];\n\n          for (n = 0; n <= DIKSI_LAST; n++)\n               if (entry->symbols[n] == symbol)\n                    return entry->code;\n     }\n\n     return -1;\n}\n\n#define FIXUP_KEY_FIELDS (DIEF_MODIFIERS | DIEF_LOCKS | DIEF_KEYCODE | DIEF_KEYID | DIEF_KEYSYMBOL)\n\n/*\n * Fill partially missing values for key_code, key_id and key_symbol by translating those that are set.\n * Fix modifiers/locks before if not set.\n *\n * There are five valid constellations that give reasonable values.\n * (not counting the constellation where everything is set)\n *\n * Device has no translation table\n *   1. key_id is set, key_symbol not\n *        -> key_code defaults to -1, key_symbol from key_id (up-translation)\n *   2. key_symbol is set, key_id not\n *        -> key_code defaults to -1, key_id from key_symbol (down-translation)\n *\n * Device has a translation table\n *   3. key_code is set\n *        -> look up key_id and/or key_symbol (key_code being the index)\n *   4. key_id is set\n *        -> look up key_code and possibly key_symbol (key_id being searched for)\n *   5. key_symbol is set\n *        -> look up key_code and key_id (key_symbol being searched for)\n *\n * Fields remaining will be set to the default, e.g. key_code to -1.\n */\nstatic void\nfixup_key_event( CoreInputDevice *device,\n                 DFBInputEvent   *event )\n{\n     int                    i;\n     DFBInputEventFlags     valid   = event->flags & FIXUP_KEY_FIELDS;\n     DFBInputEventFlags     missing = valid ^ FIXUP_KEY_FIELDS;\n     CoreInputDeviceShared *shared;\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( device->shared != NULL );\n\n     shared = device->shared;\n\n     /* Add missing flags. */\n     event->flags |= missing;\n\n     /* Use cached values for modifiers/locks if they are missing. */\n     if (missing & DIEF_MODIFIERS)\n          event->modifiers = shared->state.modifiers_l | shared->state.modifiers_r;\n\n     if (missing & DIEF_LOCKS)\n          event->locks = shared->state.locks;\n\n     /* With translation table. */\n     if (shared->keymap.num_entries) {\n          if (valid & DIEF_KEYCODE) {\n               lookup_from_table( device, event, missing );\n               missing &= ~(DIEF_KEYID | DIEF_KEYSYMBOL);\n          }\n          else if (valid & DIEF_KEYID) {\n               event->key_code = find_key_code_by_id( device, event->key_id );\n\n               if (event->key_code != -1) {\n                    lookup_from_table( device, event, missing );\n                    missing &= ~(DIEF_KEYCODE | DIEF_KEYSYMBOL);\n               }\n               else if (missing & DIEF_KEYSYMBOL) {\n                    event->key_symbol = id_to_symbol( event->key_id, event->modifiers, event->locks );\n                    missing &= ~DIEF_KEYSYMBOL;\n               }\n          }\n          else if (valid & DIEF_KEYSYMBOL) {\n               event->key_code = find_key_code_by_symbol( device, event->key_symbol );\n\n               if (event->key_code != -1) {\n                    lookup_from_table( device, event, missing );\n                    missing &= ~(DIEF_KEYCODE | DIEF_KEYID);\n               }\n               else {\n                    event->key_id = symbol_to_id( event->key_symbol );\n                    missing &= ~DIEF_KEYSYMBOL;\n               }\n          }\n     }\n     /* Without translation table. */\n     else {\n          if (valid & DIEF_KEYID) {\n               if (missing & DIEF_KEYSYMBOL) {\n                    event->key_symbol = id_to_symbol( event->key_id, event->modifiers, event->locks );\n                    missing &= ~DIEF_KEYSYMBOL;\n               }\n          }\n          else if (valid & DIEF_KEYSYMBOL) {\n               event->key_id = symbol_to_id( event->key_symbol );\n               missing &= ~DIEF_KEYID;\n          }\n     }\n\n     /* Clear remaining fields. */\n\n     if (missing & DIEF_KEYCODE)\n          event->key_code = -1;\n\n     if (missing & DIEF_KEYID)\n          event->key_id = DIKI_UNKNOWN;\n\n     if (missing & DIEF_KEYSYMBOL)\n          event->key_symbol = DIKS_NULL;\n\n     /* Update cached values for modifiers. */\n     if (DFB_KEY_TYPE( event->key_symbol ) == DIKT_MODIFIER) {\n          if (event->type == DIET_KEYPRESS) {\n               switch (event->key_id) {\n                    case DIKI_SHIFT_L:\n                         shared->state.modifiers_l |= DIMM_SHIFT;\n                         break;\n                    case DIKI_SHIFT_R:\n                         shared->state.modifiers_r |= DIMM_SHIFT;\n                         break;\n                    case DIKI_CONTROL_L:\n                         shared->state.modifiers_l |= DIMM_CONTROL;\n                         break;\n                    case DIKI_CONTROL_R:\n                         shared->state.modifiers_r |= DIMM_CONTROL;\n                         break;\n                    case DIKI_ALT_L:\n                         shared->state.modifiers_l |= DIMM_ALT;\n                         break;\n                    case DIKI_ALT_R:\n                         shared->state.modifiers_r |= (event->key_symbol == DIKS_ALTGR) ? DIMM_ALTGR : DIMM_ALT;\n                         break;\n                    case DIKI_META_L:\n                         shared->state.modifiers_l |= DIMM_META;\n                         break;\n                    case DIKI_META_R:\n                         shared->state.modifiers_r |= DIMM_META;\n                         break;\n                    case DIKI_SUPER_L:\n                         shared->state.modifiers_l |= DIMM_SUPER;\n                         break;\n                    case DIKI_SUPER_R:\n                         shared->state.modifiers_r |= DIMM_SUPER;\n                         break;\n                    case DIKI_HYPER_L:\n                         shared->state.modifiers_l |= DIMM_HYPER;\n                         break;\n                    case DIKI_HYPER_R:\n                         shared->state.modifiers_r |= DIMM_HYPER;\n                         break;\n                    default:\n                         ;\n               }\n          }\n          else {\n               switch (event->key_id) {\n                    case DIKI_SHIFT_L:\n                         shared->state.modifiers_l &= ~DIMM_SHIFT;\n                         break;\n                    case DIKI_SHIFT_R:\n                         shared->state.modifiers_r &= ~DIMM_SHIFT;\n                         break;\n                    case DIKI_CONTROL_L:\n                         shared->state.modifiers_l &= ~DIMM_CONTROL;\n                         break;\n                    case DIKI_CONTROL_R:\n                         shared->state.modifiers_r &= ~DIMM_CONTROL;\n                         break;\n                    case DIKI_ALT_L:\n                         shared->state.modifiers_l &= ~DIMM_ALT;\n                         break;\n                    case DIKI_ALT_R:\n                         shared->state.modifiers_r &= (event->key_symbol == DIKS_ALTGR) ? ~DIMM_ALTGR : ~DIMM_ALT;\n                         break;\n                    case DIKI_META_L:\n                         shared->state.modifiers_l &= ~DIMM_META;\n                         break;\n                    case DIKI_META_R:\n                         shared->state.modifiers_r &= ~DIMM_META;\n                         break;\n                    case DIKI_SUPER_L:\n                         shared->state.modifiers_l &= ~DIMM_SUPER;\n                         break;\n                    case DIKI_SUPER_R:\n                         shared->state.modifiers_r &= ~DIMM_SUPER;\n                         break;\n                    case DIKI_HYPER_L:\n                         shared->state.modifiers_l &= ~DIMM_HYPER;\n                         break;\n                    case DIKI_HYPER_R:\n                         shared->state.modifiers_r &= ~DIMM_HYPER;\n                         break;\n                    default:\n                         ;\n               }\n          }\n\n          /* Write back to event. */\n          if (missing & DIEF_MODIFIERS)\n               event->modifiers = shared->state.modifiers_l | shared->state.modifiers_r;\n     }\n\n     /*\n      * Update cached values for locks.\n      */\n     if (event->type == DIET_KEYPRESS) {\n\n          /* When we receive a new key press, toggle lock flags. */\n          if (shared->first_press || shared->last_key != event->key_id) {\n              switch (event->key_id) {\n                   case DIKI_CAPS_LOCK:\n                        shared->state.locks ^= DILS_CAPS;\n                        break;\n                   case DIKI_NUM_LOCK:\n                        shared->state.locks ^= DILS_NUM;\n                        break;\n                   case DIKI_SCROLL_LOCK:\n                        shared->state.locks ^= DILS_SCROLL;\n                        break;\n                   default:\n                        ;\n              }\n          }\n\n          /* Write back to event. */\n          if (missing & DIEF_LOCKS)\n               event->locks = shared->state.locks;\n\n          /* Store last pressed key. */\n          shared->last_key    = event->key_id;\n          shared->first_press = false;\n     }\n     else if (event->type == DIET_KEYRELEASE) {\n          shared->first_press = true;\n     }\n\n     /* Handle dead keys. */\n     if (DFB_KEY_TYPE( shared->last_symbol ) == DIKT_DEAD) {\n          for (i = 0; i < D_ARRAY_SIZE(deadkey_maps); i++) {\n               const DeadKeyMap *map = &deadkey_maps[i];\n\n               if (map->deadkey == shared->last_symbol) {\n                    for (i = 0; map->combos[i].target; i++) {\n                         if (map->combos[i].target == event->key_symbol) {\n                              event->key_symbol = map->combos[i].result;\n                              break;\n                         }\n                    }\n                    break;\n               }\n          }\n\n          if (event->type == DIET_KEYRELEASE && DFB_KEY_TYPE( event->key_symbol ) != DIKT_MODIFIER)\n               shared->last_symbol = event->key_symbol;\n     }\n     else\n          shared->last_symbol = event->key_symbol;\n}\n\nstatic void\nfixup_mouse_event( CoreInputDevice *device,\n                   DFBInputEvent    *event )\n{\n     CoreInputDeviceShared *shared;\n\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n     D_ASSERT( device->shared != NULL );\n\n     shared = device->shared;\n\n     if (event->flags & DIEF_BUTTONS) {\n          shared->state.buttons = event->buttons;\n     }\n     else {\n          switch (event->type) {\n               case DIET_BUTTONPRESS:\n                    shared->state.buttons |= (1 << event->button);\n                    break;\n               case DIET_BUTTONRELEASE:\n                    shared->state.buttons &= ~(1 << event->button);\n                    break;\n               default:\n                    ;\n          }\n\n          /* Add missing flag. */\n          event->flags |= DIEF_BUTTONS;\n\n          event->buttons = shared->state.buttons;\n     }\n\n     switch (event->type) {\n          case DIET_AXISMOTION:\n               if ((event->flags & DIEF_AXISABS) && event->axis >= 0 && event->axis < shared->axis_num) {\n                    if (!(event->flags & DIEF_MIN) && (shared->axis_info[event->axis].flags & IDAIF_ABS_MIN)) {\n                         event->min    = shared->axis_info[event->axis].abs_min;\n                         event->flags |= DIEF_MIN;\n                    }\n\n                    if (!(event->flags & DIEF_MAX) && (shared->axis_info[event->axis].flags & IDAIF_ABS_MAX)) {\n                         event->max    = shared->axis_info[event->axis].abs_max;\n                         event->flags |= DIEF_MAX;\n                    }\n               }\n               break;\n\n          default:\n               break;\n     }\n}\n\n/**********************************************************************************************************************/\n\nstatic DFBInputDeviceKeyIdentifier\nsymbol_to_id( DFBInputDeviceKeySymbol symbol )\n{\n     if (symbol >= 'a' && symbol <= 'z')\n          return DIKI_A + symbol - 'a';\n\n     if (symbol >= 'A' && symbol <= 'Z')\n          return DIKI_A + symbol - 'A';\n\n     if (symbol >= '0' && symbol <= '9')\n          return DIKI_0 + symbol - '0';\n\n     if (symbol >= DIKS_F1 && symbol <= DIKS_F12)\n          return DIKI_F1 + symbol - DIKS_F1;\n\n     switch (symbol) {\n          case DIKS_ESCAPE:\n               return DIKI_ESCAPE;\n\n          case DIKS_CURSOR_LEFT:\n               return DIKI_LEFT;\n\n          case DIKS_CURSOR_RIGHT:\n               return DIKI_RIGHT;\n\n          case DIKS_CURSOR_UP:\n               return DIKI_UP;\n\n          case DIKS_CURSOR_DOWN:\n               return DIKI_DOWN;\n\n          case DIKS_ALTGR:\n               return DIKI_ALT_R;\n\n          case DIKS_CONTROL:\n               return DIKI_CONTROL_L;\n\n          case DIKS_SHIFT:\n               return DIKI_SHIFT_L;\n\n          case DIKS_ALT:\n               return DIKI_ALT_L;\n\n          case DIKS_META:\n               return DIKI_META_L;\n\n          case DIKS_SUPER:\n               return DIKI_SUPER_L;\n\n          case DIKS_HYPER:\n               return DIKI_HYPER_L;\n\n          case DIKS_TAB:\n               return DIKI_TAB;\n\n          case DIKS_ENTER:\n               return DIKI_ENTER;\n\n          case DIKS_SPACE:\n               return DIKI_SPACE;\n\n          case DIKS_BACKSPACE:\n               return DIKI_BACKSPACE;\n\n          case DIKS_INSERT:\n               return DIKI_INSERT;\n\n          case DIKS_DELETE:\n               return DIKI_DELETE;\n\n          case DIKS_HOME:\n               return DIKI_HOME;\n\n          case DIKS_END:\n               return DIKI_END;\n\n          case DIKS_PAGE_UP:\n               return DIKI_PAGE_UP;\n\n          case DIKS_PAGE_DOWN:\n               return DIKI_PAGE_DOWN;\n\n          case DIKS_CAPS_LOCK:\n               return DIKI_CAPS_LOCK;\n\n          case DIKS_NUM_LOCK:\n               return DIKI_NUM_LOCK;\n\n          case DIKS_SCROLL_LOCK:\n               return DIKI_SCROLL_LOCK;\n\n          case DIKS_PRINT:\n               return DIKI_PRINT;\n\n          case DIKS_PAUSE:\n               return DIKI_PAUSE;\n\n          case DIKS_BACKSLASH:\n               return DIKI_BACKSLASH;\n\n          case DIKS_PERIOD:\n               return DIKI_PERIOD;\n\n          case DIKS_COMMA:\n               return DIKI_COMMA;\n\n          default:\n               ;\n     }\n\n     return DIKI_UNKNOWN;\n}\n\nstatic DFBInputDeviceKeySymbol\nid_to_symbol( DFBInputDeviceKeyIdentifier id,\n              DFBInputDeviceModifierMask  modifiers,\n              DFBInputDeviceLockState     locks )\n{\n     bool shift = !(modifiers & DIMM_SHIFT) ^ !(locks & DILS_CAPS);\n\n     if (id >= DIKI_A && id <= DIKI_Z)\n          return (shift ? DIKS_CAPITAL_A : DIKS_SMALL_A) + id - DIKI_A;\n\n     if (id >= DIKI_0 && id <= DIKI_9)\n          return DIKS_0 + id - DIKI_0;\n\n     if (id >= DIKI_KP_0 && id <= DIKI_KP_9)\n          return DIKS_0 + id - DIKI_KP_0;\n\n     if (id >= DIKI_F1 && id <= DIKI_F12)\n          return DIKS_F1 + id - DIKI_F1;\n\n     switch (id) {\n          case DIKI_ESCAPE:\n               return DIKS_ESCAPE;\n\n          case DIKI_LEFT:\n               return DIKS_CURSOR_LEFT;\n\n          case DIKI_RIGHT:\n               return DIKS_CURSOR_RIGHT;\n\n          case DIKI_UP:\n               return DIKS_CURSOR_UP;\n\n          case DIKI_DOWN:\n               return DIKS_CURSOR_DOWN;\n\n          case DIKI_CONTROL_L:\n          case DIKI_CONTROL_R:\n               return DIKS_CONTROL;\n\n          case DIKI_SHIFT_L:\n          case DIKI_SHIFT_R:\n               return DIKS_SHIFT;\n\n          case DIKI_ALT_L:\n          case DIKI_ALT_R:\n               return DIKS_ALT;\n\n          case DIKI_META_L:\n          case DIKI_META_R:\n               return DIKS_META;\n\n          case DIKI_SUPER_L:\n          case DIKI_SUPER_R:\n               return DIKS_SUPER;\n\n          case DIKI_HYPER_L:\n          case DIKI_HYPER_R:\n               return DIKS_HYPER;\n\n          case DIKI_TAB:\n               return DIKS_TAB;\n\n          case DIKI_ENTER:\n               return DIKS_ENTER;\n\n          case DIKI_SPACE:\n               return DIKS_SPACE;\n\n          case DIKI_BACKSPACE:\n               return DIKS_BACKSPACE;\n\n          case DIKI_INSERT:\n               return DIKS_INSERT;\n\n          case DIKI_DELETE:\n               return DIKS_DELETE;\n\n          case DIKI_HOME:\n               return DIKS_HOME;\n\n          case DIKI_END:\n               return DIKS_END;\n\n          case DIKI_PAGE_UP:\n               return DIKS_PAGE_UP;\n\n          case DIKI_PAGE_DOWN:\n               return DIKS_PAGE_DOWN;\n\n          case DIKI_CAPS_LOCK:\n               return DIKS_CAPS_LOCK;\n\n          case DIKI_NUM_LOCK:\n               return DIKS_NUM_LOCK;\n\n          case DIKI_SCROLL_LOCK:\n               return DIKS_SCROLL_LOCK;\n\n          case DIKI_PRINT:\n               return DIKS_PRINT;\n\n          case DIKI_PAUSE:\n               return DIKS_PAUSE;\n\n          case DIKI_KP_DIV:\n               return DIKS_SLASH;\n\n          case DIKI_KP_MULT:\n               return DIKS_ASTERISK;\n\n          case DIKI_KP_MINUS:\n               return DIKS_MINUS_SIGN;\n\n          case DIKI_KP_PLUS:\n               return DIKS_PLUS_SIGN;\n\n          case DIKI_KP_ENTER:\n               return DIKS_ENTER;\n\n          case DIKI_KP_SPACE:\n               return DIKS_SPACE;\n\n          case DIKI_KP_TAB:\n               return DIKS_TAB;\n\n          case DIKI_KP_EQUAL:\n               return DIKS_EQUALS_SIGN;\n\n          case DIKI_KP_DECIMAL:\n               return DIKS_PERIOD;\n\n          case DIKI_KP_SEPARATOR:\n               return DIKS_COMMA;\n\n          case DIKI_BACKSLASH:\n               return DIKS_BACKSLASH;\n\n          case DIKI_EQUALS_SIGN:\n               return DIKS_EQUALS_SIGN;\n\n          case DIKI_LESS_SIGN:\n               return DIKS_LESS_THAN_SIGN;\n\n          case DIKI_MINUS_SIGN:\n               return DIKS_MINUS_SIGN;\n\n          case DIKI_PERIOD:\n               return DIKS_PERIOD;\n\n          case DIKI_QUOTE_LEFT:\n          case DIKI_QUOTE_RIGHT:\n               return DIKS_QUOTATION;\n\n          case DIKI_SEMICOLON:\n               return DIKS_SEMICOLON;\n\n          case DIKI_SLASH:\n               return DIKS_SLASH;\n\n          default:\n               ;\n     }\n\n     return DIKS_NULL;\n}\n\n/**********************************************************************************************************************/\n\nstatic void\ndump_primary_layer_surface( CoreDFB *core )\n{\n     CoreLayer        *layer = dfb_layer_at( DLID_PRIMARY );\n     CoreLayerContext *context;\n\n     /* Get the currently active context. */\n     if (dfb_layer_get_active_context( layer, &context ) == DFB_OK) {\n          CoreLayerRegion *region;\n\n          /* Get the first region. */\n          if (dfb_layer_context_get_primary_region( context, false, &region ) == DFB_OK) {\n               CoreSurface *surface;\n\n               /* Lock the region to avoid tearing due to concurrent updates. */\n               dfb_layer_region_lock( region );\n\n               /* Get the surface of the region. */\n               if (dfb_layer_region_get_surface( region, &surface ) == DFB_OK) {\n                    /* Dump the surface contents. */\n                    dfb_surface_dump_buffer( surface, DSBR_FRONT, dfb_config->screenshot_dir, \"dfb\" );\n\n                    /* Release the surface. */\n                    dfb_surface_unref( surface );\n               }\n\n               /* Unlock the region. */\n               dfb_layer_region_unlock( region );\n\n               /* Release the region. */\n               dfb_layer_region_unref( region );\n          }\n\n          /* Release the context. */\n          dfb_layer_context_unref( context );\n     }\n}\n\nstatic bool\ncore_input_filter( CoreInputDevice *device,\n                   DFBInputEvent   *event )\n{\n     D_MAGIC_ASSERT( device, CoreInputDevice );\n\n     if (dfb_system_input_filter( device, event ))\n          return true;\n\n     if (event->type == DIET_KEYPRESS) {\n          switch (event->key_symbol) {\n               case DIKS_PRINT:\n                    if (!event->modifiers && dfb_config->screenshot_dir) {\n                         dump_primary_layer_surface( device->core );\n                         return true;\n                    }\n                    break;\n\n               case DIKS_BACKSPACE:\n                    if (event->modifiers == DIMM_META)\n                         direct_trace_print_stacks();\n\n                    break;\n\n               case DIKS_ESCAPE:\n                    if (event->modifiers == DIMM_META) {\n#if FUSION_BUILD_MULTI\n                         DFBResult         ret;\n                         CoreLayer        *layer = dfb_layer_at( DLID_PRIMARY );\n                         CoreLayerContext *context;\n\n                         /* Get primary (shared) context. */\n                         ret = dfb_layer_get_primary_context( layer, false, &context );\n                         if (ret)\n                              return false;\n\n                         /* Activate the context. */\n                         dfb_layer_activate_context( layer, context );\n\n                         /* Release the context. */\n                         dfb_layer_context_unref( context );\n#else /* FUSION_BUILD_MULTI */\n                         direct_kill( 0, SIGINT );\n#endif /* FUSION_BUILD_MULTI */\n\n                         return true;\n                    }\n                    break;\n\n               default:\n                    break;\n          }\n     }\n\n     return false;\n}\n"
  },
  {
    "path": "src/core/input.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__INPUT_H__\n#define __CORE__INPUT_H__\n\n#include <core/coretypes.h>\n#include <direct/modules.h>\n#include <fusion/call.h>\n#include <fusion/reactor.h>\n#include <fusion/ref.h>\n\nDECLARE_MODULE_DIRECTORY( dfb_input_drivers );\n\n/**********************************************************************************************************************/\n\n#define DFB_INPUT_DRIVER_ABI_VERSION           7\n\n#define DFB_INPUT_DRIVER_INFO_NAME_LENGTH     60\n#define DFB_INPUT_DRIVER_INFO_VENDOR_LENGTH   80\n#define DFB_INPUT_DRIVER_INFO_URL_LENGTH     120\n#define DFB_INPUT_DRIVER_INFO_LICENSE_LENGTH  40\n\ntypedef struct {\n     int major; /* major version */\n     int minor; /* minor version */\n} InputDriverVersion;\n\ntypedef struct {\n     InputDriverVersion version;\n\n     char               name[DFB_INPUT_DRIVER_INFO_NAME_LENGTH];       /* Name of input driver */\n     char               vendor[DFB_INPUT_DRIVER_INFO_VENDOR_LENGTH];   /* Vendor (or author) of the driver */\n     char               url[DFB_INPUT_DRIVER_INFO_URL_LENGTH];         /* URL for driver updates */\n     char               license[DFB_INPUT_DRIVER_INFO_LICENSE_LENGTH]; /* License, e.g. 'LGPL' or 'proprietary' */\n} InputDriverInfo;\n\ntypedef enum {\n     IDC_NONE    = 0x00000000, /* None. */\n\n     IDC_HOTPLUG = 0x00000001, /* Input devices support hot-plug. */\n\n     IDC_ALL     = 0x00000001  /* All flags supported. */\n} InputDriverCapability;\n\ntypedef struct {\n     unsigned int              prefered_id; /* Prefered predefined input device id. */\n\n     DFBInputDeviceDescription desc;        /* Capabilities, type, etc. */\n} InputDeviceInfo;\n\ntypedef enum {\n     IDAIF_NONE    = 0x00000000, /* None of these. */\n\n     IDAIF_ABS_MIN = 0x00000001, /* Minimum possible value. */\n     IDAIF_ABS_MAX = 0x00000002, /* Maximum possible value. */\n\n     IDAIF_ALL     = 0x00000003  /* All of these. */\n} InputDeviceAxisInfoFlags;\n\ntypedef struct {\n     InputDeviceAxisInfoFlags flags;\n     int                      abs_min;\n     int                      abs_max;\n} InputDeviceAxisInfo;\n\ntypedef struct {\n     int                   (*GetAvailable)    ( void );\n\n     void                  (*GetDriverInfo)   ( InputDriverInfo               *driver_info );\n\n     DFBResult             (*OpenDevice)      ( CoreInputDevice               *device,\n                                                unsigned int                   number,\n                                                InputDeviceInfo               *device_info,\n                                                void                         **driver_data );\n\n     DFBResult             (*GetKeymapEntry)  ( CoreInputDevice               *device,\n                                                void                          *driver_data,\n                                                DFBInputDeviceKeymapEntry     *entry );\n\n     void                  (*CloseDevice)     ( void                          *driver_data );\n\n     DFBResult             (*Suspend)         ( void );\n\n     DFBResult             (*Resume)          ( void );\n\n     DFBResult             (*IsCreated)       ( int                            index,\n                                                void                          *data );\n\n     InputDriverCapability (*GetCapability)   ( void );\n\n     DFBResult             (*LaunchHotplug)   ( CoreDFB                       *core,\n                                                void                          *input_driver );\n\n     DFBResult             (*StopHotplug)     ( void );\n\n     DFBResult             (*GetAxisInfo)     ( CoreInputDevice               *device,\n                                                void                          *driver_data,\n                                                DFBInputDeviceAxisIdentifier   axis,\n                                                InputDeviceAxisInfo           *ret_info );\n\n     DFBResult             (*SetConfiguration)( CoreInputDevice               *device,\n                                                void                          *driver_data,\n                                                const DFBInputDeviceConfig    *config );\n} InputDriverFuncs;\n\ntypedef struct {\n     int                        min_keycode;\n     int                        max_keycode;\n     int                        num_entries;\n     DFBInputDeviceKeymapEntry *entries;\n} InputDeviceKeymap;\n\ntypedef struct {\n     DFBInputDeviceModifierMask modifiers_l;\n     DFBInputDeviceModifierMask modifiers_r;\n     DFBInputDeviceLockState    locks;\n     DFBInputDeviceButtonMask   buttons;\n} InputDeviceState;\n\ntypedef struct {\n     int                          magic;\n\n     DFBInputDeviceID             id;          /* unique device id */\n\n     int                          num;\n\n     InputDeviceInfo              device_info;\n\n     InputDeviceKeymap            keymap;\n\n     InputDeviceState             state;\n\n     DFBInputDeviceKeyIdentifier  last_key;    /* last key pressed */\n     DFBInputDeviceKeySymbol      last_symbol; /* last symbol pressed */\n     bool                         first_press; /* first press of key */\n\n     FusionReactor               *reactor;     /* event dispatcher */\n     FusionSkirmish               lock;\n\n     unsigned int                 axis_num;\n     InputDeviceAxisInfo         *axis_info;\n     FusionRef                    ref;         /* ref between shared device & local device */\n\n     FusionCall                   call;\n} CoreInputDeviceShared;\n\ntypedef struct {\n     DirectLink              link;\n\n     int                     magic;\n\n     DirectModuleEntry      *module;\n\n     const InputDriverFuncs *funcs;\n\n     InputDriverInfo         info;\n\n     int                     nr_devices;\n} CoreInputDriver;\n\nstruct __DFB_CoreInputDevice {\n     DirectLink             link;\n\n     int                    magic;\n\n     CoreInputDeviceShared *shared;\n\n     CoreInputDriver       *driver;\n     void                  *driver_data;\n\n     CoreDFB               *core;\n};\n\n/**********************************************************************************************************************/\n\ntypedef DFBEnumerationResult (*InputDeviceCallback)( CoreInputDevice *device, void *ctx );\n\n/**********************************************************************************************************************/\n\nDFBResult                   dfb_input_add_global                ( ReactionFunc                     func,\n                                                                  int                             *ret_index );\n\nDFBResult                   dfb_input_set_global                ( ReactionFunc                     func,\n                                                                  int                              index );\n\nvoid                        dfb_input_enumerate_devices         ( InputDeviceCallback              callback,\n                                                                  void                            *ctx,\n                                                                  DFBInputDeviceCapabilities       caps );\n\nDirectResult                dfb_input_attach                    ( CoreInputDevice                 *device,\n                                                                  ReactionFunc                     func,\n                                                                  void                            *ctx,\n                                                                  Reaction                        *reaction );\n\nDirectResult                dfb_input_detach                    ( CoreInputDevice                 *device,\n                                                                  Reaction                        *reaction );\n\nDirectResult                dfb_input_attach_global             ( CoreInputDevice                 *device,\n                                                                  int                              index,\n                                                                  void                            *ctx,\n                                                                  GlobalReaction                  *reaction );\n\nDirectResult                dfb_input_detach_global             ( CoreInputDevice                 *device,\n                                                                  GlobalReaction                  *reaction );\n\nvoid                        dfb_input_dispatch                  ( CoreInputDevice                 *device,\n                                                                  DFBInputEvent                   *event );\n\nDFBInputDeviceID            dfb_input_device_id                 ( const CoreInputDevice           *device );\n\nCoreInputDevice            *dfb_input_device_at                 ( DFBInputDeviceID                 id );\n\nDFBInputDeviceCapabilities  dfb_input_device_caps               ( const CoreInputDevice           *device );\n\nvoid                        dfb_input_device_description        ( const CoreInputDevice           *device,\n                                                                  DFBInputDeviceDescription       *desc );\n\nDFBResult                   dfb_input_device_get_keymap_entry   ( CoreInputDevice                 *device,\n                                                                  int                              keycode,\n                                                                  DFBInputDeviceKeymapEntry       *entry );\n\nDFBResult                   dfb_input_device_set_keymap_entry   ( CoreInputDevice                 *device,\n                                                                  int                              keycode,\n                                                                  const DFBInputDeviceKeymapEntry *entry );\n\nDFBResult                   dfb_input_device_load_keymap        ( CoreInputDevice                 *device,\n                                                                  char                            *filename );\n\nDFBResult                   dfb_input_device_reload_keymap      ( CoreInputDevice                 *device );\n\nDFBResult                   dfb_input_device_get_state          ( CoreInputDevice                 *device,\n                                                                  InputDeviceState                *ret_state );\n\nDFBResult                   dfb_input_device_set_configuration  ( CoreInputDevice                 *device,\n                                                                  const DFBInputDeviceConfig      *config );\n\nvoid                        eventbuffer_containers_attach_device( CoreInputDevice                 *device );\n\nvoid                        eventbuffer_containers_detach_device( CoreInputDevice                 *device );\n\nvoid                        stack_containers_attach_device      ( CoreInputDevice                 *device );\n\nvoid                        stack_containers_detach_device      ( CoreInputDevice                 *device );\n\n/*\n * Create the DFB shared core input device, add the input device into the local device list and shared dev array, and\n * broadcast the hot-plug in message to all slaves.\n */\nDFBResult                   dfb_input_create_device             ( int                              device_index,\n                                                                  CoreDFB                         *core_in,\n                                                                  void                            *driver_in );\n\n/*\n * Remove the DFB shared core input device handling of the system input device indicated by 'device_index' and broadcast\n * the hot-plug out message to all slaves.\n */\nDFBResult                   dfb_input_remove_device             ( int                              device_index,\n                                                                  void                            *driver_in );\n\n#endif\n"
  },
  {
    "path": "src/core/input_driver.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__INPUT_DRIVER_H__\n#define __CORE__INPUT_DRIVER_H__\n\n#include <core/input.h>\n\n/**********************************************************************************************************************/\n\nstatic int                   driver_get_available    ( void );\n\nstatic void                  driver_get_info         ( InputDriverInfo               *driver_info );\n\nstatic DFBResult             driver_open_device      ( CoreInputDevice               *device,\n                                                       unsigned int                   number,\n                                                       InputDeviceInfo               *device_info,\n                                                       void                         **driver_data );\n\nstatic DFBResult             driver_get_keymap_entry ( CoreInputDevice               *device,\n                                                       void                          *driver_data,\n                                                       DFBInputDeviceKeymapEntry     *entry );\n\nstatic void                  driver_close_device     ( void                          *driver_data );\n\nstatic DFBResult             driver_suspend          ( void );\n\nstatic DFBResult             driver_resume           ( void );\n\nstatic DFBResult             is_created              ( int                            index,\n                                                       void                          *driver_data );\n\nstatic InputDriverCapability get_capability          ( void );\n\nstatic DFBResult             launch_hotplug          ( CoreDFB                       *core,\n                                                       void                          *input_driver );\n\nstatic DFBResult             stop_hotplug            ( void );\n\n#ifdef DFB_INPUTDRIVER_HAS_AXIS_INFO\nstatic DFBResult             driver_get_axis_info    ( CoreInputDevice               *device,\n                                                       void                          *driver_data,\n                                                       DFBInputDeviceAxisIdentifier   axis,\n                                                       InputDeviceAxisInfo           *ret_info );\n#endif\n\n#ifdef DFB_INPUTDRIVER_HAS_SET_CONFIGURATION\nstatic DFBResult             driver_set_configuration( CoreInputDevice               *device,\n                                                       void                          *driver_data,\n                                                       const DFBInputDeviceConfig    *config );\n#endif\n\n/*\n * Add hot-plug stub function implementations for all input drivers by default.\n */\n#if !defined(DISABLE_INPUT_HOTPLUG_FUNCTION_STUB)\nstatic DFBResult\ndriver_suspend()\n{\n     return DFB_UNSUPPORTED;\n}\n\nstatic DFBResult\ndriver_resume()\n{\n     return DFB_UNSUPPORTED;\n}\n\nstatic DFBResult\nis_created( int   index,\n            void *driver_data )\n{\n     return DFB_UNSUPPORTED;\n}\n\nstatic InputDriverCapability\nget_capability()\n{\n     return IDC_NONE;\n}\n\nstatic DFBResult\nlaunch_hotplug( CoreDFB *core,\n                void    *input_driver )\n{\n     return DFB_UNSUPPORTED;\n}\n\nstatic DFBResult\nstop_hotplug()\n{\n     return DFB_UNSUPPORTED;\n}\n#endif\n\nstatic const InputDriverFuncs inputdriver_funcs = {\n     .GetAvailable     = driver_get_available,\n     .GetDriverInfo    = driver_get_info,\n     .OpenDevice       = driver_open_device,\n     .GetKeymapEntry   = driver_get_keymap_entry,\n     .CloseDevice      = driver_close_device,\n     .Suspend          = driver_suspend,\n     .Resume           = driver_resume,\n     .IsCreated        = is_created,\n     .GetCapability    = get_capability,\n     .LaunchHotplug    = launch_hotplug,\n     .StopHotplug      = stop_hotplug,\n#ifdef DFB_INPUTDRIVER_HAS_AXIS_INFO\n     .GetAxisInfo      = driver_get_axis_info,\n#endif\n#ifdef DFB_INPUTDRIVER_HAS_SET_CONFIGURATION\n     .SetConfiguration = driver_set_configuration\n#endif\n};\n\n#define DFB_INPUT_DRIVER(shortname)                         \\\n                                                            \\\n__dfb_constructor__                                         \\\nvoid                                                        \\\ndirectfb_##shortname##_ctor( void )                         \\\n{                                                           \\\n     direct_modules_register( &dfb_input_drivers,           \\\n                              DFB_INPUT_DRIVER_ABI_VERSION, \\\n                              #shortname,                   \\\n                              &inputdriver_funcs );         \\\n}                                                           \\\n                                                            \\\n__dfb_destructor__                                          \\\nvoid                                                        \\\ndirectfb_##shortname##_dtor( void )                         \\\n{                                                           \\\n     direct_modules_unregister( &dfb_input_drivers,         \\\n                                #shortname );               \\\n}\n\n#endif\n"
  },
  {
    "path": "src/core/layer_context.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreLayerContext.h>\n#include <core/core.h>\n#include <core/layers.h>\n#include <core/layer_context.h>\n#include <core/layer_control.h>\n#include <core/screen.h>\n#include <core/windowstack.h>\n#include <core/wm.h>\n#include <direct/memcpy.h>\n#include <direct/thread.h>\n#include <fusion/conf.h>\n#include <fusion/shmalloc.h>\n\nD_DEBUG_DOMAIN( Core_LayerContext, \"Core/LayerContext\", \"DirectFB Core Display Layer Context\" );\n\n/**********************************************************************************************************************/\n\nstatic void\ncontext_destructor( FusionObject *object,\n                    bool          zombie,\n                    void         *ctx )\n{\n     CoreLayerContext *context = (CoreLayerContext*) object;\n     CoreLayer        *layer;\n     CoreLayerShared  *shared;\n\n     D_UNUSED_P( shared );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     layer = dfb_layer_at( context->layer_id );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n\n     shared = layer->shared;\n\n     D_DEBUG_AT( Core_LayerContext, \"Destroying context %p (%s, %sactive%s)\\n\",\n                 context, shared->description.name, context->active ? \"\" : \"in\", zombie ? \" ZOMBIE\" : \"\" );\n\n     CoreLayerContext_Deinit_Dispatch( &context->call );\n\n     /* Remove the context from the layer's context stack. */\n     dfb_layer_remove_context( layer, context );\n\n     /* Detach input devices before taking the context lock to prevent a deadlock between windowstack destruction and\n        input event processing. */\n     if (context->stack)\n          dfb_windowstack_detach_devices( context->stack );\n\n     dfb_layer_context_lock( context );\n\n     if (context->cursor.surface)\n          dfb_surface_unlink( &context->cursor.surface );\n\n     /* Destroy the window stack. */\n     if (context->stack) {\n          dfb_windowstack_destroy( context->stack );\n          context->stack = NULL;\n     }\n\n     /* Destroy the region vector. */\n     fusion_vector_destroy( &context->regions );\n\n     /* Deinitialize the lock. */\n     fusion_skirmish_destroy( &context->lock );\n\n     /* Free clip regions. */\n     if (context->primary.config.clips)\n          SHFREE( context->shmpool, context->primary.config.clips );\n\n     D_MAGIC_CLEAR( context );\n\n     /* Destroy the object. */\n     fusion_object_destroy( object );\n}\n\nFusionObjectPool *\ndfb_layer_context_pool_create( const FusionWorld *world )\n{\n     FusionObjectPool *pool;\n\n     pool = fusion_object_pool_create( \"Layer Context Pool\",\n                                       sizeof(CoreLayerContext), sizeof(CoreLayerContextNotification),\n                                       context_destructor, NULL, world );\n\n     return pool;\n}\n\n/**********************************************************************************************************************/\n\nstatic void\nscreen_rectangle( CoreLayerContext  *context,\n                  const DFBLocation *location,\n                  DFBRectangle      *rect )\n{\n     DFBResult  ret;\n     int        width;\n     int        height;\n     CoreLayer *layer;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p, %p )\\n\", __FUNCTION__, context, location, rect );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n     D_ASSERT( location != NULL );\n     D_ASSERT( rect != NULL );\n\n     D_DEBUG_AT( Core_LayerContext, \"  <- %4.2f,%4.2f-%4.2f,%4.2f\\n\",\n                 location->x, location->y, location->w, location->h );\n\n     layer = dfb_layer_at( context->layer_id );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->screen != NULL );\n\n     ret = dfb_screen_get_layer_dimension( layer->screen, layer, &width, &height );\n     if (ret) {\n          D_WARN( \"could not determine mixer/screen dimension of layer %u\", context->layer_id );\n\n          rect->x = location->x * 720;\n          rect->y = location->y * 576;\n          rect->w = location->w * 720;\n          rect->h = location->h * 576;\n     }\n     else {\n          rect->x = location->x * width;\n          rect->y = location->y * height;\n          rect->w = location->w * width;\n          rect->h = location->h * height;\n     }\n\n     D_DEBUG_AT( Core_LayerContext, \"  -> %4d,%4d-%4d,%4d\\n\", DFB_RECTANGLE_VALS( rect ) );\n}\n\nstatic void\ninit_region_config( CoreLayerContext      *context,\n                    CoreLayerRegionConfig *config )\n{\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p )\\n\", __FUNCTION__, context, config );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n     D_ASSERT( config  != NULL );\n\n     memset( config, 0, sizeof(CoreLayerRegionConfig) );\n\n     /* Initialize values from layer config. */\n     config->width        = context->config.width;\n     config->height       = context->config.height;\n     config->format       = context->config.pixelformat;\n     config->colorspace   = context->config.colorspace;\n     config->buffermode   = context->config.buffermode;\n     config->options      = context->config.options;\n     config->source_id    = context->config.source;\n     config->surface_caps = context->config.surface_caps;\n\n     /* Initialize source rectangle. */\n     config->source.x = 0;\n     config->source.y = 0;\n     config->source.w = config->width;\n     config->source.h = config->height;\n\n     /* Initialize screen rectangle. */\n     screen_rectangle( context, &context->screen.location, &config->dest );\n\n     /* Set default opacity. */\n     config->opacity = 0xff;\n\n     /* Set default alpha ramp. */\n     config->alpha_ramp[0] = 0x00;\n     config->alpha_ramp[1] = 0x55;\n     config->alpha_ramp[2] = 0xaa;\n     config->alpha_ramp[3] = 0xff;\n}\n\nstatic void\nupdate_stack_geometry( CoreLayerContext *context )\n{\n     DFBDimension     size;\n     int              rotation;\n     CoreLayerRegion *region;\n     CoreSurface     *surface;\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     rotation = context->rotation;\n\n     switch (rotation) {\n          default:\n               D_BUG( \"invalid rotation %d\", rotation );\n          case 0:\n          case 180:\n               size.w = context->config.width;\n               size.h = context->config.height;\n               break;\n\n          case 90:\n          case 270:\n               size.w = context->config.height;\n               size.h = context->config.width;\n               break;\n     }\n\n     region = context->primary.region;\n     if (region) {\n          surface = region->surface;\n          if (surface) {\n               D_MAGIC_ASSERT( surface, CoreSurface );\n\n               rotation -= surface->rotation;\n               if (rotation < 0)\n                    rotation += 360;\n          }\n     }\n\n     if (context->stack)\n          dfb_windowstack_resize( context->stack, size.w, size.h, rotation );\n}\n\nDFBResult\ndfb_layer_context_init( CoreLayerContext *context,\n                        CoreLayer        *layer,\n                        bool              stack )\n{\n     CoreLayerShared *shared;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p )\\n\", __FUNCTION__, context, layer );\n\n     D_ASSERT( context != NULL );\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n\n     shared = layer->shared;\n\n     D_DEBUG_AT( Core_LayerContext, \"  -> %s\", shared->description.name );\n\n     context->shmpool = shared->shmpool;\n\n     /* Initialize the lock. */\n     if (fusion_skirmish_init2( &context->lock, \"Layer Context\", dfb_core_world( layer->core ),\n                                fusion_config->secure_fusion )) {\n          fusion_object_destroy( &context->object );\n          return DFB_FUSION;\n     }\n\n     /* Initialize the region vector. */\n     fusion_vector_init( &context->regions, 4, context->shmpool );\n\n     /* Store layer ID, default configuration and default color adjustment. */\n     context->layer_id   = shared->layer_id;\n     context->config     = shared->default_config;\n     context->adjustment = shared->default_adjustment;\n\n     /* Get the layer rotation. */\n     if (dfb_config->layers[dfb_layer_id_translated( layer )].rotate_set)\n          context->rotation = dfb_config->layers[dfb_layer_id_translated( layer )].rotate;\n     else\n          dfb_screen_get_rotation( layer->screen, &context->rotation );\n\n     /* Initialize screen location. */\n     context->screen.location.x = 0.0f;\n     context->screen.location.y = 0.0f;\n     context->screen.location.w = 1.0f;\n     context->screen.location.h = 1.0f;\n\n     if (D_FLAGS_IS_SET( shared->description.caps, DLCAPS_SCREEN_LOCATION ))\n          context->screen.mode = CLLM_LOCATION;\n     else if (D_FLAGS_IS_SET( shared->description.caps, DLCAPS_SCREEN_POSITION ))\n          context->screen.mode = CLLM_CENTER;\n\n     /* Change global reaction lock. */\n     fusion_object_set_lock( &context->object, &context->lock );\n\n     D_MAGIC_SET( context, CoreLayerContext );\n\n     /* Initialize the primary region's configuration. */\n     init_region_config( context, &context->primary.config );\n\n     /* Activate the object. */\n     fusion_object_activate( &context->object );\n\n     dfb_layer_context_lock( context );\n\n     /* Create the window stack. */\n     if (stack && shared->description.caps & DLCAPS_SURFACE) {\n          context->stack = dfb_windowstack_create( context );\n          if (!context->stack) {\n               dfb_layer_context_unlock( context );\n               dfb_layer_context_unref( context );\n               return D_OOSHM();\n          }\n     }\n\n     /* Tell the window stack about its size. */\n     update_stack_geometry( context );\n\n     CoreLayerContext_Init_Dispatch( layer->core, context, &context->call );\n\n     dfb_layer_context_unlock( context );\n\n     return DFB_OK;\n}\n\nDirectResult\ndfb_layer_context_lock( CoreLayerContext *context )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p )\\n\", __FUNCTION__, context );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     ret = fusion_skirmish_prevail( &context->lock );\n     if (ret == DFB_OK) {\n          int locked;\n\n          ret = fusion_skirmish_lock_count( &context->lock, &locked );\n          if (ret == DFB_OK)\n               D_DEBUG_AT( Core_LayerContext, \"  -> locked %dx now\\n\", locked );\n     }\n\n     return ret;\n}\n\nDirectResult\ndfb_layer_context_unlock( CoreLayerContext *context )\n{\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p )\\n\", __FUNCTION__, context );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     return fusion_skirmish_dismiss( &context->lock );\n}\n\nbool\ndfb_layer_context_active( const CoreLayerContext *context )\n{\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p )\\n\", __FUNCTION__, context );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     return context->active;\n}\n\nDFBResult\ndfb_layer_context_activate( CoreLayerContext *context )\n{\n     DFBResult                ret;\n     int                      index;\n     CoreLayer               *layer;\n     CoreLayerShared         *shared;\n     CoreLayerRegion         *region;\n     const DisplayLayerFuncs *funcs;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p )\\n\", __FUNCTION__, context );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     layer = dfb_layer_at( context->layer_id );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n     D_ASSERT( layer->funcs != NULL );\n\n     shared = layer->shared;\n     funcs  = layer->funcs;\n\n     /* Lock the context. */\n     if (dfb_layer_context_lock( context ))\n          return DFB_FUSION;\n\n     D_ASSUME( !context->active );\n\n     if (context->active) {\n          dfb_layer_context_unlock( context );\n          return DFB_OK;\n     }\n\n     /* Iterate through all regions. */\n     fusion_vector_foreach (region, index, context->regions) {\n          /* First reallocate. */\n          if (region->surface && region->surface->num_buffers == 0) {\n               ret = dfb_layer_context_reallocate_surface( layer, context, region, &region->config );\n               if (ret)\n                    D_DERROR( ret, \"Core/LayerContext: Reallocation of layer surface failed!\\n\" );\n          }\n\n          /* Then activate each region. */\n          if (dfb_layer_region_activate( region ))\n               D_WARN( \"could not activate region\" );\n     }\n\n     context->active = true;\n\n     /* Remember new primary pixel format. */\n     shared->pixelformat = context->primary.config.format;\n\n     /* Set new adjustment. */\n     if (funcs->SetColorAdjustment)\n          funcs->SetColorAdjustment( layer, layer->driver_data, layer->layer_data, &context->adjustment );\n\n     /* Resume window stack. */\n     if (context->stack) {\n          CoreWindowStack *stack = context->stack;\n\n          D_MAGIC_ASSERT( stack, CoreWindowStack );\n\n          if (stack->flags & CWSF_INITIALIZED)\n               dfb_wm_set_active( stack, true );\n     }\n\n     /* Unlock the context. */\n     dfb_layer_context_unlock( context );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_context_deactivate( CoreLayerContext *context )\n{\n     int              index;\n     CoreLayerRegion *region;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p )\\n\", __FUNCTION__, context );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     /* Lock the context. */\n     if (dfb_layer_context_lock( context ))\n          return DFB_FUSION;\n\n     D_ASSUME( context->active );\n\n     if (!context->active) {\n          dfb_layer_context_unlock( context );\n          return DFB_OK;\n     }\n\n     /* Iterate through all regions. */\n     fusion_vector_foreach (region, index, context->regions) {\n          /* Deactivate each region. */\n          dfb_layer_region_deactivate( region );\n     }\n\n     context->active = false;\n\n     /* Suspend window stack. */\n     if (context->stack) {\n          CoreWindowStack *stack = context->stack;\n\n          D_MAGIC_ASSERT( stack, CoreWindowStack );\n\n          if (stack->flags & CWSF_ACTIVATED)\n               dfb_wm_set_active( stack, false );\n     }\n\n     /* Unlock the context. */\n     dfb_layer_context_unlock( context );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_context_add_region( CoreLayerContext *context,\n                              CoreLayerRegion  *region )\n{\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p )\\n\", __FUNCTION__, context, region );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n     D_ASSERT( region != NULL );\n\n     /* Lock the context. */\n     if (dfb_layer_context_lock( context ))\n          return DFB_FUSION;\n\n     D_ASSUME( !fusion_vector_contains( &context->regions, region ) );\n\n     if (fusion_vector_contains( &context->regions, region )) {\n          dfb_layer_context_unlock( context );\n          return DFB_OK;\n     }\n\n     /* Add region to vector. */\n     if (fusion_vector_add( &context->regions, region )) {\n          dfb_layer_context_unlock( context );\n          return DFB_FUSION;\n     }\n\n     /* Inherit state from context. */\n     if (context->active)\n          region->state |= CLRSF_ACTIVE;\n\n     /* Unlock the context. */\n     dfb_layer_context_unlock( context );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_context_remove_region( CoreLayerContext *context,\n                                 CoreLayerRegion  *region )\n{\n     int index;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p )\\n\", __FUNCTION__, context );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n     D_ASSERT( region != NULL );\n\n     /* Lock the context. */\n     if (dfb_layer_context_lock( context ))\n          return DFB_FUSION;\n\n     D_ASSUME( fusion_vector_contains( &context->regions, region ) );\n\n     /* Lookup region. */\n     index = fusion_vector_index_of( &context->regions, region );\n     if (index < 0) {\n          dfb_layer_context_unlock( context );\n          return DFB_OK;\n     }\n\n     /* Remove region from vector. */\n     fusion_vector_remove( &context->regions, index );\n\n     /* Check if the primary region is removed. */\n     if (region == context->primary.region)\n          context->primary.region = NULL;\n\n     /* Unlock the context. */\n     dfb_layer_context_unlock( context );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_context_get_primary_region( CoreLayerContext  *context,\n                                      bool               create,\n                                      CoreLayerRegion  **ret_region )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %screate )\\n\", __FUNCTION__, context, create ? \"\" : \"don't \" );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n     D_ASSERT( ret_region != NULL );\n\n     /* Lock the context. */\n     if (dfb_layer_context_lock( context ))\n          return DFB_FUSION;\n\nrestart:\n     while (context->primary.region) {\n          /* Make sure the primary region's reference count is non-zero. If it is, a failure is returned to indicate\n             that it is unavailable. In this scenario, this prevents the object_reference_watcher() from being called\n             more than once triggered by the reference count changing from 1 to 0 again. */\n          int num = 0;\n          if (dfb_layer_region_ref_stat( context->primary.region, &num ) || num == 0) {\n               dfb_layer_context_unlock( context );\n               return DFB_TEMPUNAVAIL;\n          }\n\n          /* Increase the primary region's reference counter. */\n          ret = dfb_layer_region_ref( context->primary.region );\n          if (ret == DFB_OK)\n               break;\n\n          dfb_layer_context_unlock( context );\n\n          if (ret == DFB_LOCKED) {\n               /* If the primary region is Fusion zero-locked (being destroyed) and creating a new primary region is\n                  not requested, return an error immediately. */\n               if (!create)\n                    return DFB_TEMPUNAVAIL;\n\n               direct_thread_sleep( 10000 );\n\n               if (dfb_layer_context_lock( context ))\n                    return DFB_FUSION;\n          }\n          else\n               return DFB_FUSION;\n     }\n\n     if (!context->primary.region) {\n          if (create) {\n              CoreLayerRegion *region;\n\n              /* Unlock the context. */\n              dfb_layer_context_unlock( context );\n\n              /* Create the primary region. */\n              ret = dfb_layer_region_create( context, &region );\n              if (ret) {\n                   D_ERROR( \"Core/LayerContext: Could not create primary region!\\n\" );\n                   return ret;\n              }\n\n              /* Lock the context again. */\n              if (dfb_layer_context_lock( context )) {\n                   dfb_layer_region_unref( region );\n                   return DFB_FUSION;\n              }\n\n              /* Check for race. */\n              if (context->primary.region) {\n                   dfb_layer_region_unref( region );\n                   goto restart;\n              }\n\n              /* Set the region configuration. */\n              ret = dfb_layer_region_set_configuration( region, &context->primary.config, CLRCF_ALL );\n              if (ret) {\n                   D_DERROR( ret, \"Core/LayerContext: Could not set primary region config!\\n\" );\n                   dfb_layer_region_unref( region );\n                   dfb_layer_context_unlock( context );\n                   return ret;\n              }\n\n              /* Remember the primary region. */\n              context->primary.region = region;\n\n              /* Allocate surface, enable region etc. */\n              ret = dfb_layer_context_set_configuration( context, &context->config );\n              if (ret) {\n                   D_DERROR( ret, \"Core/LayerContext: Could not set layer context config!\\n\" );\n                   context->primary.region = NULL;\n                   dfb_layer_region_unref( region );\n                   dfb_layer_context_unlock( context );\n                   return ret;\n              }\n          }\n          else {\n               dfb_layer_context_unlock( context );\n               return DFB_TEMPUNAVAIL;\n          }\n     }\n\n     /* Return region. */\n     *ret_region = context->primary.region;\n\n     /* Unlock the context. */\n     dfb_layer_context_unlock( context );\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic void\nbuild_updated_config( CoreLayer                   *layer,\n                      CoreLayerContext            *context,\n                      const DFBDisplayLayerConfig *update,\n                      CoreLayerRegionConfig       *ret_config,\n                      CoreLayerRegionConfigFlags  *ret_flags )\n{\n     CoreLayerRegionConfigFlags flags = CLRCF_NONE;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p, %p, %p, %p )\\n\", __FUNCTION__,\n                 layer, context, update, ret_config, ret_flags );\n\n     D_ASSERT( layer != NULL );\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n     D_ASSERT( update != NULL );\n     D_ASSERT( ret_config != NULL );\n\n     /* Get the current region configuration. */\n     *ret_config = context->primary.config;\n\n     /* Change width. */\n     if (update->flags & DLCONF_WIDTH) {\n          flags |= CLRCF_WIDTH;\n          ret_config->width  = update->width;\n     }\n\n     /* Change height. */\n     if (update->flags & DLCONF_HEIGHT) {\n          flags |= CLRCF_HEIGHT;\n          ret_config->height = update->height;\n     }\n\n     /* Update source and destination rectangle. */\n     if (update->flags & (DLCONF_WIDTH | DLCONF_HEIGHT)) {\n          int width, height;\n          DFBResult ret;\n\n          flags |= CLRCF_SOURCE | CLRCF_DEST;\n\n          ret_config->source.x = 0;\n          ret_config->source.y = 0;\n          ret_config->source.w = ret_config->width;\n          ret_config->source.h = ret_config->height;\n\n          switch (context->screen.mode) {\n               case CLLM_CENTER:\n                    ret = dfb_screen_get_layer_dimension( layer->screen, layer, &width, &height );\n                    if (ret == DFB_OK) {\n                         ret_config->dest.x = (width  - ret_config->width)  / 2;\n                         ret_config->dest.y = (height - ret_config->height) / 2;\n                    }\n                    /* fall through */\n\n               case CLLM_POSITION:\n                    ret_config->dest.w = ret_config->width;\n                    ret_config->dest.h = ret_config->height;\n                    break;\n\n               case CLLM_LOCATION:\n               case CLLM_RECTANGLE: {\n                    CoreLayerShared *shared;\n\n                    D_ASSERT( layer->shared != NULL );\n\n                    shared = layer->shared;\n\n                    /*  If the display layer does not support scaling and the destination rectangle size is not the same\n                        as the source rectangle, change it to match.  The origin is left alone to allow the driver to\n                        handle it. */\n                    if (!D_FLAGS_IS_SET( shared->description.caps, DLCAPS_SCREEN_SIZE ) &&\n                        (ret_config->dest.w != ret_config->source.w || ret_config->dest.h != ret_config->source.h)) {\n                         ret_config->dest.w = ret_config->width;\n                         ret_config->dest.h = ret_config->height;\n                    }\n                    break;\n               }\n\n               default:\n                    D_ERROR( \"Core/LayerContext: Invalid layout mode!\\n\" );\n          }\n     }\n\n     /* Change pixel format. */\n     if (update->flags & DLCONF_PIXELFORMAT) {\n          flags |= CLRCF_FORMAT;\n          ret_config->format = update->pixelformat;\n\n          flags |= CLRCF_COLORSPACE;\n          ret_config->colorspace = DFB_COLORSPACE_DEFAULT( ret_config->format );\n     }\n\n     /* Change color space. */\n     if (update->flags & DLCONF_COLORSPACE) {\n          flags |= CLRCF_COLORSPACE;\n          ret_config->colorspace = DFB_COLORSPACE_IS_COMPATIBLE( update->colorspace, ret_config->format ) ?\n                                   update->colorspace : DFB_COLORSPACE_DEFAULT( ret_config->format );\n     }\n\n     /* Change buffer mode. */\n     if (update->flags & DLCONF_BUFFERMODE) {\n          flags |= CLRCF_BUFFERMODE;\n          ret_config->buffermode = update->buffermode;\n     }\n\n     /* Change options. */\n     if (update->flags & DLCONF_OPTIONS) {\n          flags |= CLRCF_OPTIONS;\n          ret_config->options = update->options;\n     }\n\n     /* Change source id. */\n     if (update->flags & DLCONF_SOURCE) {\n          flags |= CLRCF_SOURCE_ID;\n          ret_config->source_id = update->source;\n     }\n\n     /* Change surface caps. */\n     if (update->flags & DLCONF_SURFACE_CAPS) {\n          flags |= CLRCF_SURFACE_CAPS;\n          ret_config->surface_caps = update->surface_caps;\n     }\n\n     /* Return translated flags. */\n     if (ret_flags)\n          *ret_flags = flags;\n}\n\nDFBResult\ndfb_layer_context_test_configuration( CoreLayerContext            *context,\n                                      const DFBDisplayLayerConfig *config,\n                                      DFBDisplayLayerConfigFlags  *ret_failed )\n{\n     DFBResult                   ret = DFB_OK;\n     CoreLayer                  *layer;\n     CoreLayerShared            *shared;\n     CoreLayerRegionConfig       region_config;\n     CoreLayerRegionConfigFlags  failed;\n     const DisplayLayerFuncs    *funcs;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p, %p )\\n\", __FUNCTION__, context, config, ret_failed );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n     D_ASSERT( config != NULL );\n\n     /* Lock the context. */\n     if (dfb_layer_context_lock( context ))\n          return DFB_FUSION;\n\n     layer = dfb_layer_at( context->layer_id );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n     D_ASSERT( layer->funcs != NULL );\n     D_ASSERT( layer->funcs->TestRegion != NULL );\n\n     shared = layer->shared;\n     funcs  = layer->funcs;\n\n     /* Build a new region configuration with the changes. */\n     build_updated_config( layer, context, config, &region_config, NULL );\n\n     /* Unlock the context. */\n     dfb_layer_context_unlock( context );\n\n     /* Test the region configuration. */\n     if (region_config.buffermode == DLBM_WINDOWS) {\n          if (!D_FLAGS_IS_SET( shared->description.caps, DLCAPS_WINDOWS )) {\n               failed = CLRCF_BUFFERMODE;\n               ret = DFB_UNSUPPORTED;\n          }\n     }\n     else {\n          /* Let the driver examine the modified configuration. */\n          ret = funcs->TestRegion( layer, layer->driver_data, layer->layer_data, &region_config, &failed );\n     }\n\n     /* Return flags for failing entries. */\n     if (ret_failed) {\n          DFBDisplayLayerConfigFlags flags = DLCONF_NONE;\n\n          /* Translate flags. */\n          if (ret) {\n               if (failed & CLRCF_WIDTH)\n                    flags |= DLCONF_WIDTH;\n\n               if (failed & CLRCF_HEIGHT)\n                    flags |= DLCONF_HEIGHT;\n\n               if (failed & CLRCF_FORMAT)\n                    flags |= DLCONF_PIXELFORMAT;\n\n               if (failed & CLRCF_BUFFERMODE)\n                    flags |= DLCONF_BUFFERMODE;\n\n               if (failed & CLRCF_OPTIONS)\n                    flags |= DLCONF_OPTIONS;\n\n               if (failed & CLRCF_SOURCE_ID)\n                    flags |= DLCONF_SOURCE;\n\n               if (failed & CLRCF_SURFACE_CAPS)\n                    flags |= DLCONF_SURFACE_CAPS;\n          }\n\n          *ret_failed = flags;\n     }\n\n     return ret;\n}\n\nDFBResult\ndfb_layer_context_set_configuration( CoreLayerContext            *context,\n                                     const DFBDisplayLayerConfig *config )\n{\n     int                         i;\n     DFBResult                   ret;\n     CoreLayer                  *layer;\n     CoreLayerShared            *shared;\n     CoreLayerRegionConfig       region_config;\n     CoreLayerRegionConfigFlags  flags;\n     const DisplayLayerFuncs    *funcs;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p )\\n\", __FUNCTION__, context, config );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n     D_ASSERT( config != NULL );\n\n     /* Lock the context. */\n     if (dfb_layer_context_lock( context ))\n          return DFB_FUSION;\n\n     layer  = dfb_layer_at( context->layer_id );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n     D_ASSERT( layer->funcs != NULL );\n     D_ASSERT( layer->funcs->TestRegion != NULL );\n\n     shared = layer->shared;\n     funcs  = layer->funcs;\n\n     /* Build a new region configuration with the changes. */\n     build_updated_config( layer, context, config, &region_config, &flags );\n\n     /* Test the region configuration first. */\n     if (region_config.buffermode == DLBM_WINDOWS) {\n          if (!D_FLAGS_IS_SET( shared->description.caps, DLCAPS_WINDOWS )) {\n               dfb_layer_context_unlock( context );\n               return DFB_UNSUPPORTED;\n          }\n     }\n     else {\n          ret = funcs->TestRegion( layer, layer->driver_data, layer->layer_data, &region_config, NULL );\n          if (ret) {\n               dfb_layer_context_unlock( context );\n               return ret;\n          }\n     }\n\n     /* Set the region configuration. */\n     if (context->primary.region) {\n          CoreLayerRegion *region = context->primary.region;\n\n          /* Add local reference. */\n          if (dfb_layer_region_ref( region )) {\n               dfb_layer_context_unlock( context );\n               return DFB_FUSION;\n          }\n\n          /* Lock the region. */\n          if (dfb_layer_region_lock( region )) {\n               dfb_layer_region_unref( region );\n               dfb_layer_context_unlock( context );\n               return DFB_FUSION;\n          }\n\n          /* Normal buffer mode. */\n          if (region_config.buffermode != DLBM_WINDOWS) {\n               bool                      surface    = shared->description.caps & DLCAPS_SURFACE;\n               CoreLayerRegionStateFlags configured = region->state & CLRSF_CONFIGURED;\n\n               if (shared->description.caps & DLCAPS_SOURCES) {\n                    for (i = 0; i < shared->description.sources; i++) {\n                         if (shared->sources[i].description.source_id == region_config.source_id)\n                              break;\n                    }\n\n                    D_ASSERT( i < shared->description.sources );\n\n                    surface = shared->sources[i].description.caps & DDLSCAPS_SURFACE;\n               }\n\n               D_FLAGS_CLEAR( region->state, CLRSF_CONFIGURED );\n\n               /* (Re)allocate the region's surface. */\n               if (surface) {\n                    flags |= CLRCF_SURFACE | CLRCF_PALETTE;\n\n                    if (region->surface) {\n                         ret = dfb_layer_context_reallocate_surface( layer, context, region, &region_config );\n                         if (ret)\n                              D_DERROR( ret, \"Core/LayerContext: Reallocation of layer surface failed!\\n\" );\n                    }\n                    else {\n                         ret = dfb_layer_context_allocate_surface( layer, context, region, &region_config );\n                         if (ret)\n                              D_DERROR( ret, \"Core/LayerContext: Allocation of layer surface failed!\\n\" );\n                    }\n\n                    if (ret) {\n                         dfb_layer_region_unlock( region );\n                         dfb_layer_region_unref( region );\n                         dfb_layer_context_unlock( context );\n                         return ret;\n                    }\n               }\n               else if (region->surface)\n                    dfb_layer_context_deallocate_surface( layer, context, region );\n\n               region->state |= configured;\n\n               /* Set the new region configuration. */\n               dfb_layer_region_set_configuration( region, &region_config, flags | CLRCF_FREEZE );\n\n               /* Enable the primary region. */\n               if (!D_FLAGS_IS_SET( region->state, CLRSF_ENABLED ))\n                    dfb_layer_region_enable( region );\n          }\n          else {\n               /* Disable and deallocate the primary region. */\n               if (D_FLAGS_IS_SET( region->state, CLRSF_ENABLED )) {\n                    dfb_layer_region_disable( region );\n\n                    if (region->surface)\n                         dfb_layer_context_deallocate_surface( layer, context, region );\n               }\n          }\n\n          /* Unlock the region and give up the local reference. */\n          dfb_layer_region_unlock( region );\n          dfb_layer_region_unref( region );\n     }\n\n     /* Remember new region config. */\n     context->primary.config = region_config;\n\n     /* Remember new primary pixel format. */\n     shared->pixelformat = region_config.format;\n\n     /* Write back modified entries. */\n\n     if (config->flags & DLCONF_WIDTH)\n          context->config.width = config->width;\n\n     if (config->flags & DLCONF_HEIGHT)\n          context->config.height = config->height;\n\n     if (config->flags & DLCONF_PIXELFORMAT)\n          context->config.pixelformat = config->pixelformat;\n\n     if (config->flags & DLCONF_COLORSPACE)\n          context->config.colorspace = config->colorspace;\n\n     if (config->flags & DLCONF_BUFFERMODE)\n          context->config.buffermode = config->buffermode;\n\n     if (config->flags & DLCONF_OPTIONS)\n          context->config.options = config->options;\n\n     if (config->flags & DLCONF_SOURCE)\n          context->config.source = config->source;\n\n     if (config->flags & DLCONF_SURFACE_CAPS)\n          context->config.surface_caps = config->surface_caps;\n\n     /* Update the window stack. */\n     if (context->stack) {\n          CoreWindowStack *stack = context->stack;\n\n          /* Update hardware flag. */\n          stack->hw_mode = (region_config.buffermode == DLBM_WINDOWS);\n\n          /* Tell the windowing core about the new size. */\n          if (config->flags &\n              (DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE | DLCONF_SURFACE_CAPS)) {\n               update_stack_geometry( context );\n\n               /* Fixed window stack repainting to not be performed when the region is frozen, because a frozen\n                  display layer should not be allocated and made visible until absolutely necessary. This prevents\n                  a display layer surface flip from being done and showing an uninitialized buffer. */\n               if (context->primary.region &&\n                   !D_FLAGS_IS_SET( context->primary.region->state, CLRSF_FROZEN )) {\n                    dfb_windowstack_repaint_all( stack );\n               }\n          }\n     }\n\n     /* Unlock the context. */\n     dfb_layer_context_unlock( context );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_context_get_configuration( CoreLayerContext      *context,\n                                     DFBDisplayLayerConfig *ret_config )\n{\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p )\\n\", __FUNCTION__, context, ret_config );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n     D_ASSERT( ret_config != NULL );\n\n     *ret_config = context->config;\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic DFBResult\nupdate_primary_region_config( CoreLayerContext           *context,\n                              CoreLayerRegionConfig      *config,\n                              CoreLayerRegionConfigFlags  flags )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p, 0x%08x )\\n\", __FUNCTION__, context, config, flags );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n     D_ASSERT( config != NULL );\n\n     if (context->primary.region) {\n          if (flags != CLRCF_DEST)\n               flags |= CLRCF_FREEZE;\n\n          /* Set the new configuration. */\n          ret = dfb_layer_region_set_configuration( context->primary.region, config, flags );\n     }\n     else {\n          CoreLayer               *layer = dfb_layer_at( context->layer_id );\n          const DisplayLayerFuncs *funcs;\n\n          D_ASSERT( layer->funcs != NULL );\n          D_ASSERT( layer->funcs->TestRegion != NULL );\n\n          funcs = layer->funcs;\n\n          /* Just test the new configuration. */\n          ret = funcs->TestRegion( layer, layer->driver_data, layer->layer_data, config, NULL );\n     }\n\n     if (ret)\n          return ret;\n\n     /* Remember the configuration. */\n     context->primary.config = *config;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_context_set_src_colorkey( CoreLayerContext *context,\n                                    u8                r,\n                                    u8                g,\n                                    u8                b,\n                                    int               index )\n{\n     DFBResult             ret;\n     CoreLayerRegionConfig config;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %02x %02x %02x - %d )\\n\", __FUNCTION__, context, r, g, b, index );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     /* Lock the context. */\n     if (dfb_layer_context_lock( context ))\n          return DFB_FUSION;\n\n     /* Take the current configuration. */\n     config = context->primary.config;\n\n     /* Change the color key. */\n     config.src_key.r = r;\n     config.src_key.g = g;\n     config.src_key.b = b;\n\n     if (index >= 0)\n          config.src_key.index = index & 0xff;\n\n     /* Try to set the new configuration. */\n     ret = update_primary_region_config( context, &config, CLRCF_SRCKEY );\n\n     /* Unlock the context. */\n     dfb_layer_context_unlock( context );\n\n     return ret;\n}\n\nDFBResult\ndfb_layer_context_set_dst_colorkey( CoreLayerContext *context,\n                                    u8                r,\n                                    u8                g,\n                                    u8                b,\n                                    int               index )\n{\n     DFBResult             ret;\n     CoreLayerRegionConfig config;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %02x %02x %02x - %d )\\n\", __FUNCTION__, context, r, g, b, index );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     /* Lock the context. */\n     if (dfb_layer_context_lock( context ))\n          return DFB_FUSION;\n\n     /* Take the current configuration. */\n     config = context->primary.config;\n\n     /* Change the color key. */\n     config.dst_key.r = r;\n     config.dst_key.g = g;\n     config.dst_key.b = b;\n\n     if (index >= 0)\n          config.dst_key.index = index & 0xff;\n\n     /* Try to set the new configuration. */\n     ret = update_primary_region_config( context, &config, CLRCF_DSTKEY );\n\n     /* Unlock the context. */\n     dfb_layer_context_unlock( context );\n\n     return ret;\n}\n\nDFBResult\ndfb_layer_context_set_sourcerectangle( CoreLayerContext   *context,\n                                       const DFBRectangle *source )\n{\n     DFBResult                   ret;\n     CoreLayer                  *layer;\n     CoreLayerShared            *shared;\n     CoreLayerRegionConfig       config;\n     CoreLayerRegionConfigFlags  flags;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p )\\n\", __FUNCTION__, context, source );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n     D_ASSERT( source != NULL );\n\n     /* Lock the context. */\n     if (dfb_layer_context_lock( context ))\n          return DFB_FUSION;\n\n     /* Take the current configuration. */\n     config = context->primary.config;\n\n     /* Do nothing if the source rectangle didn't change. */\n     if (DFB_RECTANGLE_EQUAL( config.source, *source )) {\n          dfb_layer_context_unlock( context );\n          return DFB_OK;\n     }\n\n     /* Check if the new source rectangle is valid. */\n     if (source->x < 0 || source->y < 0 ||\n         source->x + source->w > config.width ||\n         source->y + source->h > config.height) {\n          dfb_layer_context_unlock( context );\n          return DFB_INVAREA;\n     }\n\n     /* Change the source rectangle. */\n     config.source = *source;\n\n     flags = CLRCF_SOURCE;\n\n     layer = dfb_layer_at( context->layer_id );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n\n     shared = layer->shared;\n\n     /*  If the display layer does not support scaling and the destination rectangle size is not the same as the source,\n         change it to match. The origin is left alone to allow the driver to handle it. */\n     if (!D_FLAGS_IS_SET( shared->description.caps, DLCAPS_SCREEN_SIZE ) &&\n         (config.dest.w != config.source.w || config.dest.h != config.source.h)) {\n          config.dest.w = config.source.w;\n          config.dest.h = config.source.h;\n\n          flags |= CLRCF_DEST;\n     }\n\n     /* Try to set the new configuration. */\n     ret = update_primary_region_config( context, &config, flags );\n\n     /* Unlock the context. */\n     dfb_layer_context_unlock( context );\n\n     return ret;\n}\n\nDFBResult\ndfb_layer_context_set_screenlocation( CoreLayerContext  *context,\n                                      const DFBLocation *location )\n{\n     DFBResult             ret;\n     CoreLayerRegionConfig config;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p )\\n\", __FUNCTION__, context, location );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n     D_ASSERT( location != NULL );\n\n     /* Lock the context. */\n     if (dfb_layer_context_lock( context ))\n          return DFB_FUSION;\n\n     /* Take the current configuration. */\n     config = context->primary.config;\n\n     /* Calculate new absolute screen coordinates. */\n     screen_rectangle( context, location, &config.dest );\n\n     /* Try to set the new configuration. */\n     ret = update_primary_region_config( context, &config, CLRCF_DEST );\n     if (ret == DFB_OK) {\n          context->screen.location  = *location;\n          context->screen.rectangle = config.dest;\n          context->screen.mode      = CLLM_LOCATION;\n     }\n\n     /* Unlock the context. */\n     dfb_layer_context_unlock( context );\n\n     return ret;\n}\n\nDFBResult\ndfb_layer_context_set_screenrectangle( CoreLayerContext   *context,\n                                       const DFBRectangle *rect )\n{\n     DFBResult             ret;\n     CoreLayerRegionConfig config;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p )\\n\", __FUNCTION__, context, rect );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     DFB_RECTANGLE_ASSERT( rect );\n\n     /* Lock the context. */\n     if (dfb_layer_context_lock( context ))\n          return DFB_FUSION;\n\n     /* Take the current configuration. */\n     config = context->primary.config;\n\n     /* Use supplied absolute screen coordinates. */\n     config.dest = *rect;\n\n     /* Try to set the new configuration. */\n     ret = update_primary_region_config( context, &config, CLRCF_DEST );\n     if (ret == DFB_OK) {\n          context->screen.rectangle = config.dest;\n          context->screen.mode      = CLLM_RECTANGLE;\n     }\n\n     /* Unlock the context. */\n     dfb_layer_context_unlock( context );\n\n     return ret;\n}\n\nDFBResult\ndfb_layer_context_set_screenposition( CoreLayerContext *context,\n                                      int               x,\n                                      int               y )\n{\n     DFBResult             ret;\n     CoreLayerRegionConfig config;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %4d,%4d )\\n\", __FUNCTION__, context, x, y );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     /* Lock the context. */\n     if (dfb_layer_context_lock( context ))\n          return DFB_FUSION;\n\n     /* Do nothing if the location didn't change. */\n     if (context->primary.config.dest.x == x && context->primary.config.dest.y == y) {\n          dfb_layer_context_unlock( context );\n          return DFB_OK;\n     }\n\n     /* Take the current configuration. */\n     config = context->primary.config;\n\n     /* Set new absolute screen coordinates. */\n     config.dest.x = x;\n     config.dest.y = y;\n\n     /* Try to set the new configuration. */\n     ret = update_primary_region_config( context, &config, CLRCF_DEST );\n     if (ret == DFB_OK) {\n          context->screen.rectangle = config.dest;\n          context->screen.mode      = CLLM_POSITION;\n     }\n\n     /* Unlock the context. */\n     dfb_layer_context_unlock( context );\n\n     return ret;\n}\n\nDFBResult\ndfb_layer_context_set_opacity( CoreLayerContext *context,\n                               u8                opacity )\n{\n     DFBResult             ret;\n     CoreLayerRegionConfig config;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %u )\\n\", __FUNCTION__, context, opacity );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     /* Lock the context. */\n     if (dfb_layer_context_lock( context ))\n          return DFB_FUSION;\n\n     /* Do nothing if the opacity didn't change. */\n     if (context->primary.config.opacity == opacity) {\n          dfb_layer_context_unlock( context );\n          return DFB_OK;\n     }\n\n     /* Take the current configuration. */\n     config = context->primary.config;\n\n     /* Change the opacity. */\n     config.opacity = opacity;\n\n     /* Try to set the new configuration. */\n     ret = update_primary_region_config( context, &config, CLRCF_OPACITY );\n     if (ret == DFB_OK)\n          context->primary.config.opacity = opacity;\n\n     /* Unlock the context. */\n     dfb_layer_context_unlock( context );\n\n     return ret;\n}\n\nDFBResult\ndfb_layer_context_set_rotation( CoreLayerContext *context,\n                                int               rotation )\n{\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %d )\\n\", __FUNCTION__, context, rotation );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     /* Lock the context. */\n     if (dfb_layer_context_lock( context ))\n          return DFB_FUSION;\n\n     /* Do nothing if the rotation didn't change. */\n     if (context->rotation != rotation) {\n          context->rotation = rotation;\n\n          update_stack_geometry( context );\n\n          if (context->stack)\n               dfb_windowstack_repaint_all( context->stack );\n     }\n\n     /* Unlock the context. */\n     dfb_layer_context_unlock( context );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_context_set_coloradjustment( CoreLayerContext         *context,\n                                       const DFBColorAdjustment *adjustment )\n{\n     DFBResult                ret;\n     DFBColorAdjustment       adj;\n     CoreLayer               *layer;\n     const DisplayLayerFuncs *funcs;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p )\\n\", __FUNCTION__, context, adjustment );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n     D_ASSERT( adjustment != NULL );\n\n     layer = dfb_layer_at( context->layer_id );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->funcs != NULL );\n\n     funcs = layer->funcs;\n\n     adj = context->adjustment;\n\n     if (!funcs->SetColorAdjustment)\n          return DFB_UNSUPPORTED;\n\n     /* If flags are set that are not in the default adjustment. */\n     if (adjustment->flags & ~context->adjustment.flags)\n          return DFB_UNSUPPORTED;\n\n     /* Take over changed values. */\n     if (adjustment->flags & DCAF_BRIGHTNESS)  adj.brightness = adjustment->brightness;\n     if (adjustment->flags & DCAF_CONTRAST)    adj.contrast   = adjustment->contrast;\n     if (adjustment->flags & DCAF_HUE)         adj.hue        = adjustment->hue;\n     if (adjustment->flags & DCAF_SATURATION)  adj.saturation = adjustment->saturation;\n\n     /* Set new adjustment. */\n     ret = funcs->SetColorAdjustment( layer, layer->driver_data, layer->layer_data, &adj );\n     if (ret)\n          return ret;\n\n     /* Keep new adjustment. */\n     context->adjustment = adj;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_context_get_coloradjustment( CoreLayerContext   *context,\n                                       DFBColorAdjustment *ret_adjustment )\n{\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p )\\n\", __FUNCTION__, context, ret_adjustment );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n     D_ASSERT( ret_adjustment != NULL );\n\n     *ret_adjustment = context->adjustment;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_context_set_stereo_depth( CoreLayerContext *context,\n                                    bool              follow_video,\n                                    int               z )\n{\n     DFBResult                ret;\n     CoreLayer               *layer;\n     const DisplayLayerFuncs *funcs;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %d, %d )\\n\", __FUNCTION__, context, follow_video, z );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     layer = dfb_layer_at( context->layer_id );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->funcs != NULL );\n\n     funcs = layer->funcs;\n\n     if (!funcs->SetStereoDepth)\n          return DFB_UNSUPPORTED;\n\n     /* Set new depth. */\n     ret = funcs->SetStereoDepth( layer, layer->driver_data, layer->layer_data, follow_video, z );\n     if (ret)\n          return ret;\n\n     /* Keep new depth. */\n     context->follow_video = follow_video;\n     context->z            = z;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_context_get_stereo_depth( CoreLayerContext *context,\n                                    bool             *ret_follow_video,\n                                    int              *ret_z )\n{\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p, %p )\\n\", __FUNCTION__, context, ret_follow_video, ret_z );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n     D_ASSERT( ret_follow_video != NULL );\n     D_ASSERT( ret_z != NULL );\n\n     *ret_follow_video = context->follow_video;\n     *ret_z            = context->z;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_context_set_field_parity( CoreLayerContext *context,\n                                    int               field )\n{\n     DFBResult             ret;\n     CoreLayerRegionConfig config;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %d )\\n\", __FUNCTION__, context, field );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     /* Lock the context. */\n     if (dfb_layer_context_lock( context ))\n          return DFB_FUSION;\n\n     /* Do nothing if the parity didn't change. */\n     if (context->primary.config.parity == field) {\n          dfb_layer_context_unlock( context );\n          return DFB_OK;\n     }\n\n     /* Take the current configuration. */\n     config = context->primary.config;\n\n     /* Change the parity. */\n     config.parity = field;\n\n     /* Try to set the new configuration. */\n     ret = update_primary_region_config( context, &config, CLRCF_PARITY );\n\n     /* Unlock the context. */\n     dfb_layer_context_unlock( context );\n\n     return ret;\n}\n\nDFBResult\ndfb_layer_context_set_clip_regions( CoreLayerContext *context,\n                                    const DFBRegion  *regions,\n                                    int               num_regions,\n                                    DFBBoolean        positive )\n{\n     DFBResult              ret;\n     CoreLayerRegionConfig  config;\n     DFBRegion             *clips;\n     DFBRegion             *old_clips;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p [%d], %s )\\n\", __FUNCTION__,\n                 context, regions, num_regions, positive ? \"positive\" : \"negative\" );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     clips = SHMALLOC( context->shmpool, sizeof(DFBRegion) * num_regions );\n     if (!clips)\n          return D_OOSHM();\n\n     direct_memcpy( clips, regions, sizeof(DFBRegion) * num_regions );\n\n     /* Lock the context. */\n     if (dfb_layer_context_lock( context )) {\n          SHFREE( context->shmpool, clips );\n          return DFB_FUSION;\n     }\n\n     /* Take the current configuration. */\n     config = context->primary.config;\n\n     /* Remember for freeing later on. */\n     old_clips = config.clips;\n\n     /* Change the clip regions. */\n     config.clips     = clips;\n     config.num_clips = num_regions;\n     config.positive  = positive;\n\n     /* Try to set the new configuration. */\n     ret = update_primary_region_config( context, &config, CLRCF_CLIPS );\n\n     /* Unlock the context. */\n     dfb_layer_context_unlock( context );\n\n     if (ret)\n          SHFREE( context->shmpool, clips );\n     else if (old_clips)\n          SHFREE( context->shmpool, old_clips );\n\n     return ret;\n}\n\nDFBResult\ndfb_layer_context_set_cursor_shape( CoreLayerContext *context,\n                                    CoreSurface      *shape,\n                                    int               hot_x,\n                                    int               hot_y )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p, %d, %d )\\n\", __FUNCTION__, context, shape, hot_x, hot_y );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     context->cursor.hot_x = hot_x;\n     context->cursor.hot_y = hot_y;\n\n     if (context->cursor.surface)\n          dfb_surface_unlink( &context->cursor.surface );\n\n     if (shape) {\n          ret = dfb_surface_link( &context->cursor.surface, shape );\n          if (ret)\n               return ret;\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_context_get_cursor_shape( CoreLayerContext  *context,\n                                    CoreSurface      **ret_shape,\n                                    int               *ret_hot_x,\n                                    int               *ret_hot_y )\n{\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p, %p, %p )\\n\", __FUNCTION__, context, ret_shape, ret_hot_x, ret_hot_y );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n     D_ASSERT( ret_shape != NULL );\n     D_ASSERT( ret_hot_x != NULL );\n     D_ASSERT( ret_hot_y != NULL );\n\n     *ret_shape = context->cursor.surface;\n     *ret_hot_x   = context->cursor.hot_x;\n     *ret_hot_y   = context->cursor.hot_y;\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_layer_context_create_window( CoreDFB                     *core,\n                                 CoreLayerContext            *context,\n                                 const DFBWindowDescription  *desc,\n                                 CoreWindow                 **ret_window )\n{\n     DFBResult        ret;\n     CoreWindow      *window;\n     CoreWindowStack *stack;\n     CoreLayer       *layer;\n     CoreLayerShared *shared;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p, %p, %p )\\n\", __FUNCTION__, core, context, desc, ret_window );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n     D_ASSERT( desc != NULL );\n     D_ASSERT( ret_window != NULL );\n\n     layer = dfb_layer_at( context->layer_id );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n\n     shared = layer->shared;\n\n     if ((shared->description.caps & DLCAPS_SURFACE) == 0) {\n          D_DEBUG_AT( Core_LayerContext, \"  -> no DLCAPS_SURFACE!\\n\" );\n          return DFB_UNSUPPORTED;\n     }\n\n     if (!context->stack) {\n          D_DEBUG_AT( Core_LayerContext, \"  -> no stack!\\n\" );\n          return DFB_UNSUPPORTED;\n     }\n\n     if (dfb_layer_context_lock( context )) {\n          D_DEBUG_AT( Core_LayerContext, \"  -> dfb_layer_context_lock() failed!\\n\" );\n          return DFB_FUSION;\n     }\n\n     stack = context->stack;\n\n     if (!stack->cursor.set) {\n          ret = dfb_windowstack_cursor_enable( stack, true );\n          if (ret) {\n               D_DEBUG_AT( Core_LayerContext, \"  -> dfb_windowstack_cursor_enable() failed!\\n\" );\n               dfb_layer_context_unlock( context );\n               return ret;\n          }\n     }\n\n     /* Create the window object. */\n     ret = dfb_window_create( stack, desc, &window );\n     if (ret) {\n          D_DEBUG_AT( Core_LayerContext, \"  -> dfb_window_create() failed!\\n\" );\n          dfb_layer_context_unlock( context );\n          return ret;\n     }\n\n     /* Return the new window. */\n     *ret_window = window;\n\n     dfb_layer_context_unlock( context );\n\n     return DFB_OK;\n}\n\nCoreWindow *\ndfb_layer_context_find_window( CoreLayerContext *context,\n                               DFBWindowID       id )\n{\n     CoreWindowStack *stack;\n     CoreWindow      *window;\n     CoreLayer       *layer;\n     CoreLayerShared *shared;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %u )\\n\", __FUNCTION__, context, id );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     layer = dfb_layer_at( context->layer_id );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n\n     shared = layer->shared;\n\n     if ((shared->description.caps & DLCAPS_SURFACE) == 0)\n          return NULL;\n\n     D_ASSERT( context->stack != NULL );\n\n     stack = context->stack;\n\n     if (dfb_layer_context_lock( context ))\n         return NULL;\n\n     if (dfb_wm_window_lookup( stack, id, &window ) || dfb_window_ref( window ))\n          window = NULL;\n\n     dfb_layer_context_unlock( context );\n\n     return window;\n}\n\nCoreWindowStack *\ndfb_layer_context_windowstack( const CoreLayerContext *context )\n{\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     return context->stack;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_layer_context_allocate_surface( CoreLayer             *layer,\n                                    CoreLayerContext      *context,\n                                    CoreLayerRegion       *region,\n                                    CoreLayerRegionConfig *config )\n{\n     DFBResult                ret;\n     CoreSurface             *surface;\n     CoreSurfaceTypeFlags     type = CSTF_LAYER;\n     CoreSurfaceConfig        scon;\n     CoreLayerShared         *shared;\n     const DisplayLayerFuncs *funcs;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p, %p )\\n\", __FUNCTION__, layer, region, config );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n     D_ASSERT( layer->funcs != NULL );\n     D_ASSERT( region != NULL );\n     D_ASSERT( region->surface == NULL );\n     D_ASSERT( config != NULL );\n     D_ASSERT( config->buffermode != DLBM_WINDOWS );\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     shared = layer->shared;\n     funcs  = layer->funcs;\n\n     /* Create a new surface for the region. */\n     if (funcs->AllocateSurface) {\n          /* Let the driver create the surface. */\n          ret = funcs->AllocateSurface( layer, layer->driver_data, layer->layer_data, region->region_data, config,\n                                        &surface );\n          if (ret) {\n               D_ERROR( \"Core/LayerContext: Failed to allocate surface!\\n\" );\n               return ret;\n          }\n     }\n     else {\n          DFBSurfaceCapabilities  caps = shared->description.surface_caps ?: DSCAPS_VIDEOONLY;\n\n          /* Choose surface capabilities depending on the buffer mode. */\n          switch (config->buffermode) {\n               case DLBM_FRONTONLY:\n                    break;\n\n               case DLBM_BACKVIDEO:\n               case DLBM_BACKSYSTEM:\n                    caps |= DSCAPS_DOUBLE;\n                    break;\n\n               case DLBM_TRIPLE:\n                    caps |= DSCAPS_TRIPLE;\n                    break;\n\n               default:\n                    D_BUG( \"unknown buffermode\" );\n                    break;\n          }\n\n          if (context->rotation == 90 || context->rotation == 270)\n               caps |= DSCAPS_ROTATED;\n\n          if (config->options & DLOP_DEINTERLACING)\n               caps |= DSCAPS_INTERLACED;\n\n          if (config->options & DLOP_STEREO)\n               caps |= DSCAPS_STEREO;\n\n          /* Add available surface capabilities. */\n          caps |= config->surface_caps & (DSCAPS_INTERLACED | DSCAPS_SEPARATED | DSCAPS_PREMULTIPLIED | DSCAPS_GL);\n\n          scon.flags      = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_COLORSPACE | CSCONF_CAPS;\n          scon.size.w     = config->width;\n          scon.size.h     = config->height;\n          scon.format     = config->format;\n          scon.colorspace = config->colorspace;\n          scon.caps       = caps;\n\n          if (shared->contexts.primary == context)\n               type |= CSTF_SHARED;\n\n          /* Use the default surface creation. */\n          ret = dfb_surface_create( layer->core, &scon, type, shared->layer_id, NULL, &surface );\n          if (ret) {\n               D_DERROR( ret, \"Core/LayerContext: Surface creation failed!\\n\" );\n               return ret;\n          }\n\n          if (config->buffermode == DLBM_BACKSYSTEM) {\n               surface->left_buffers[1]->policy = CSP_SYSTEMONLY;\n\n               if (config->options & DLOP_STEREO)\n                    surface->right_buffers[1]->policy = CSP_SYSTEMONLY;\n          }\n     }\n\n     if (surface->config.caps & DSCAPS_ROTATED)\n          surface->rotation = context->rotation;\n     else\n          surface->rotation = (context->rotation == 180) ? 180 : 0;\n\n     /* Tell the region about its new surface (adds a global reference). */\n     ret = dfb_layer_region_set_surface( region, surface, false );\n\n     /* Remove local reference of dfb_surface_create(). */\n     dfb_surface_unref( surface );\n\n     return ret;\n}\n\nDFBResult\ndfb_layer_context_reallocate_surface( CoreLayer             *layer,\n                                      CoreLayerContext      *context,\n                                      CoreLayerRegion       *region,\n                                      CoreLayerRegionConfig *config )\n{\n     DFBResult                ret;\n     CoreSurface             *surface;\n     CoreSurfaceConfig        sconfig;\n     const DisplayLayerFuncs *funcs;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p, %p )\\n\", __FUNCTION__, layer, region, config );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->funcs != NULL );\n     D_ASSERT( region != NULL );\n     D_ASSERT( region->surface != NULL );\n     D_ASSERT( config != NULL );\n     D_ASSERT( config->buffermode != DLBM_WINDOWS );\n\n     D_MAGIC_ASSERT( context, CoreLayerContext );\n\n     funcs   = layer->funcs;\n     surface = region->surface;\n\n     if (funcs->ReallocateSurface)\n          return funcs->ReallocateSurface( layer, layer->driver_data, layer->layer_data, region->region_data, config,\n                                           surface );\n\n     sconfig.flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_COLORSPACE | CSCONF_CAPS;\n\n     sconfig.caps = surface->config.caps & ~(DSCAPS_FLIPPING      | DSCAPS_INTERLACED | DSCAPS_SEPARATED |\n                                             DSCAPS_PREMULTIPLIED | DSCAPS_ROTATED    | DSCAPS_STEREO);\n\n     switch (config->buffermode) {\n          case DLBM_TRIPLE:\n               sconfig.caps |= DSCAPS_TRIPLE;\n               break;\n\n          case DLBM_BACKVIDEO:\n          case DLBM_BACKSYSTEM:\n               sconfig.caps |= DSCAPS_DOUBLE;\n               break;\n\n          case DLBM_FRONTONLY:\n               break;\n\n          default:\n               D_BUG( \"unknown buffermode\" );\n               return DFB_BUG;\n     }\n\n     if (context->rotation == 90 || context->rotation == 270)\n          sconfig.caps |= DSCAPS_ROTATED;\n\n     /* Add available surface capabilities. */\n     sconfig.caps |= config->surface_caps & (DSCAPS_INTERLACED | DSCAPS_SEPARATED  | DSCAPS_PREMULTIPLIED | DSCAPS_GL);\n\n     if (config->options & DLOP_DEINTERLACING)\n          sconfig.caps |= DSCAPS_INTERLACED;\n\n     if (config->options & DLOP_STEREO)\n          sconfig.caps |= DSCAPS_STEREO;\n\n     sconfig.size.w     = config->width;\n     sconfig.size.h     = config->height;\n     sconfig.format     = config->format;\n     sconfig.colorspace = config->colorspace;\n\n     ret = dfb_surface_lock( surface );\n     if (ret)\n          return ret;\n\n     if (config->buffermode == DLBM_BACKSYSTEM)\n          surface->flips = 0;\n     else if (!(surface->config.caps & DSCAPS_FLIPPING))\n          surface->flips++;\n\n     ret = dfb_surface_reconfig( surface, &sconfig );\n     if (ret) {\n          dfb_surface_unlock( surface );\n          return ret;\n     }\n\n     if (DFB_PIXELFORMAT_IS_INDEXED( surface->config.format ) && !surface->palette) {\n          ret = dfb_surface_init_palette( layer->core, surface );\n          if (ret)\n               D_DERROR( ret, \"Core/LayerContext: Could not initialize palette while switching to indexed mode!\\n\" );\n     }\n\n     switch (config->buffermode) {\n          case DLBM_BACKSYSTEM:\n               surface->left_buffers[1]->policy = CSP_SYSTEMONLY;\n\n               if (config->options & DLOP_STEREO)\n                    surface->right_buffers[1]->policy = CSP_SYSTEMONLY;\n               break;\n\n          case DLBM_TRIPLE:\n          case DLBM_BACKVIDEO:\n          case DLBM_FRONTONLY:\n               break;\n\n          default:\n               D_BUG( \"unknown buffermode\" );\n               return DFB_BUG;\n     }\n\n     if (surface->config.caps & DSCAPS_ROTATED)\n          surface->rotation = context->rotation;\n     else\n          surface->rotation = (context->rotation == 180) ? 180 : 0;\n\n     dfb_surface_unlock( surface );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_context_deallocate_surface( CoreLayer        *layer,\n                                      CoreLayerContext *context,\n                                      CoreLayerRegion  *region )\n{\n     DFBResult                ret;\n     CoreSurface             *surface;\n     const DisplayLayerFuncs *funcs;\n\n     D_DEBUG_AT( Core_LayerContext, \"%s( %p, %p )\\n\", __FUNCTION__, layer, region );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->funcs != NULL );\n     D_ASSERT( region != NULL );\n\n     D_ASSUME( region->surface != NULL );\n\n     funcs   = layer->funcs;\n     surface = region->surface;\n\n     if (surface) {\n          /* Special deallocation by the driver. */\n          if (funcs->DeallocateSurface) {\n               ret = funcs->DeallocateSurface( layer, layer->driver_data, layer->layer_data, region->region_data,\n                                               surface );\n               if (ret)\n                    return ret;\n          }\n\n          /* Detach the global listener. */\n          dfb_surface_detach_global( surface, &region->surface_reaction );\n\n          dfb_surface_deallocate_buffers( region->surface );\n\n          /* Unlink from structure. */\n          dfb_surface_unlink( &region->surface );\n     }\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/core/layer_context.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__LAYER_CONTEXT_H__\n#define __CORE__LAYER_CONTEXT_H__\n\n#include <core/layer_region.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CLLM_LOCATION  = 0x00000000, /* Keep normalized area. */\n     CLLM_CENTER    = 0x00000001, /* Center layer after resizing destination area. */\n     CLLM_POSITION  = 0x00000002, /* Keep pixel position, but resize area. */\n     CLLM_RECTANGLE = 0x00000003  /* Keep pixel based area. */\n} CoreLayerLayoutMode;\n\nstruct __DFB_CoreLayerContext {\n     FusionObject                object;\n\n     int                         magic;\n\n     DFBDisplayLayerID           layer_id;     /* layer id */\n\n     FusionSkirmish              lock;         /* Lock for layer context handling. */\n\n     bool                        active;       /* Active context. */\n\n     DFBDisplayLayerConfig       config;       /* Current layer configuration. */\n     int                         rotation;     /* Rotation. */\n\n     FusionVector                regions;      /* All regions created within this context. */\n\n     struct {\n          CoreLayerRegion       *region;       /* Region of layer config if buffer mode is not DLBM_WINDOWS. */\n          CoreLayerRegionConfig  config;       /* Region config used to implement layer config and settings. */\n     } primary;\n\n     struct {\n          DFBLocation            location;     /* Normalized screen location. */\n          DFBRectangle           rectangle;    /* Pixel based position and size. */\n\n          CoreLayerLayoutMode    mode;         /* Resizing influences them. */\n     } screen;\n\n     DFBColorAdjustment          adjustment;   /* Color adjustment of the layer.*/\n\n     bool                        follow_video; /* Stereo ofset is determined by video metadata. */\n     int                         z;            /* Stereo offset to use when the layer is mixed. */\n\n     CoreWindowStack            *stack;        /* Every layer has its own window stack as every layer has its own\n                                                  pixel buffer. */\n\n     FusionSHMPoolShared        *shmpool;      /* Shared memory pool. */\n\n     FusionCall                  call;         /* dispatch */\n\n     struct {\n          int                    hot_x;        /* x position of cursor hot spot */\n          int                    hot_y;        /* y position of cursor hot spot */\n          CoreSurface           *surface;      /* cursor shape surface */\n     } cursor;\n};\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CLCNF_ACTIVATED   = 0x00000001,\n     CLCNF_DEACTIVATED = 0x00000002\n} CoreLayerContextNotificationFlags;\n\ntypedef struct {\n     CoreLayerContextNotificationFlags  flags;\n     CoreLayerContext                  *context;\n} CoreLayerContextNotification;\n\n/**********************************************************************************************************************/\n\n/*\n * Creates a pool of layer context objects.\n */\nFusionObjectPool *dfb_layer_context_pool_create        ( const FusionWorld            *world );\n\n/*\n * Generates dfb_layer_context_ref(), dfb_layer_context_attach() etc.\n */\nFUSION_OBJECT_METHODS( CoreLayerContext, dfb_layer_context )\n\n/**********************************************************************************************************************/\n\nDFBResult         dfb_layer_context_init               ( CoreLayerContext             *context,\n                                                         CoreLayer                    *layer,\n                                                         bool                          stack );\n\nDirectResult      dfb_layer_context_lock               ( CoreLayerContext             *context );\n\nDirectResult      dfb_layer_context_unlock             ( CoreLayerContext             *context );\n\nbool              dfb_layer_context_active             ( const CoreLayerContext       *context );\n\nDFBResult         dfb_layer_context_activate           ( CoreLayerContext             *context );\n\nDFBResult         dfb_layer_context_deactivate         ( CoreLayerContext             *context );\n\nDFBResult         dfb_layer_context_add_region         ( CoreLayerContext             *context,\n                                                         CoreLayerRegion              *region );\n\nDFBResult         dfb_layer_context_remove_region      ( CoreLayerContext             *context,\n                                                         CoreLayerRegion              *region );\n\nDFBResult         dfb_layer_context_get_primary_region ( CoreLayerContext             *context,\n                                                         bool                          create,\n                                                         CoreLayerRegion             **ret_region );\n\n/*\n * Configuration testing/setting/getting.\n */\n\nDFBResult         dfb_layer_context_test_configuration ( CoreLayerContext             *context,\n                                                         const DFBDisplayLayerConfig  *config,\n                                                         DFBDisplayLayerConfigFlags   *ret_failed );\n\nDFBResult         dfb_layer_context_set_configuration  ( CoreLayerContext             *context,\n                                                         const DFBDisplayLayerConfig  *config );\n\nDFBResult         dfb_layer_context_get_configuration  ( CoreLayerContext             *context,\n                                                         DFBDisplayLayerConfig        *ret_config );\n\n/*\n * Configuration details.\n */\n\nDFBResult         dfb_layer_context_set_src_colorkey   ( CoreLayerContext             *context,\n                                                         u8                            r,\n                                                         u8                            g,\n                                                         u8                            b,\n                                                         int                           index );\n\nDFBResult         dfb_layer_context_set_dst_colorkey   ( CoreLayerContext             *context,\n                                                         u8                            r,\n                                                         u8                            g,\n                                                         u8                            b,\n                                                         int                           index );\n\nDFBResult         dfb_layer_context_set_sourcerectangle( CoreLayerContext             *context,\n                                                         const DFBRectangle           *source );\n\nDFBResult         dfb_layer_context_set_screenlocation ( CoreLayerContext             *context,\n                                                         const DFBLocation            *location );\n\nDFBResult         dfb_layer_context_set_screenrectangle( CoreLayerContext             *context,\n                                                         const DFBRectangle           *rect );\n\nDFBResult         dfb_layer_context_set_screenposition ( CoreLayerContext             *context,\n                                                         int                           x,\n                                                         int                           y );\n\nDFBResult         dfb_layer_context_set_opacity        ( CoreLayerContext             *context,\n                                                         u8                            opacity );\n\nDFBResult         dfb_layer_context_set_rotation       ( CoreLayerContext             *context,\n                                                         int                           rotation );\n\nDFBResult         dfb_layer_context_set_coloradjustment( CoreLayerContext             *context,\n                                                         const DFBColorAdjustment     *adjustment );\n\nDFBResult         dfb_layer_context_get_coloradjustment( CoreLayerContext             *context,\n                                                         DFBColorAdjustment           *ret_adjustment );\n\nDFBResult         dfb_layer_context_set_stereo_depth   ( CoreLayerContext             *context,\n                                                         bool                          follow_video,\n                                                         int                           z );\n\nDFBResult         dfb_layer_context_get_stereo_depth   ( CoreLayerContext             *context,\n                                                         bool                         *ret_follow_video,\n                                                         int                          *ret_z );\n\nDFBResult         dfb_layer_context_set_field_parity   ( CoreLayerContext             *context,\n                                                         int                           field );\n\nDFBResult         dfb_layer_context_set_clip_regions   ( CoreLayerContext             *context,\n                                                         const DFBRegion              *regions,\n                                                         int                           num_regions,\n                                                         DFBBoolean                    positive );\n\nDFBResult         dfb_layer_context_set_cursor_shape   ( CoreLayerContext             *context,\n                                                         CoreSurface                  *shape,\n                                                         int                           hot_x,\n                                                         int                           hot_y );\n\nDFBResult         dfb_layer_context_get_cursor_shape   ( CoreLayerContext             *context,\n                                                         CoreSurface                 **ret_shape,\n                                                         int                          *ret_hot_x,\n                                                         int                          *ret_hot_y );\n\n/*\n * Window control.\n */\n\nDFBResult         dfb_layer_context_create_window      ( CoreDFB                      *core,\n                                                         CoreLayerContext             *context,\n                                                         const DFBWindowDescription   *desc,\n                                                         CoreWindow                  **ret_window );\n\nCoreWindow       *dfb_layer_context_find_window        ( CoreLayerContext             *context,\n                                                         DFBWindowID                   id );\n\nCoreWindowStack  *dfb_layer_context_windowstack        ( const CoreLayerContext       *context );\n\n/*\n * Region surface (re/de)allocation.\n */\n\nDFBResult         dfb_layer_context_allocate_surface   ( CoreLayer                    *layer,\n                                                         CoreLayerContext             *context,\n                                                         CoreLayerRegion              *region,\n                                                         CoreLayerRegionConfig        *config );\n\nDFBResult         dfb_layer_context_reallocate_surface ( CoreLayer                    *layer,\n                                                         CoreLayerContext             *context,\n                                                         CoreLayerRegion              *region,\n                                                         CoreLayerRegionConfig        *config );\n\nDFBResult         dfb_layer_context_deallocate_surface ( CoreLayer                    *layer,\n                                                         CoreLayerContext             *context,\n                                                         CoreLayerRegion              *region );\n\n#endif\n"
  },
  {
    "path": "src/core/layer_control.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core.h>\n#include <core/layers.h>\n#include <core/layer_context.h>\n#include <core/layer_control.h>\n#include <core/screen.h>\n\nD_DEBUG_DOMAIN( Core_LayerControl, \"Core/LayerControl\", \"DirectFB Core Display Layer Control\" );\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_layer_suspend( CoreLayer *layer )\n{\n     CoreLayerShared   *shared;\n     CoreLayerContexts *contexts;\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n\n     shared   = layer->shared;\n     contexts = &shared->contexts;\n\n     /* Lock the layer. */\n     if (fusion_skirmish_prevail( &shared->lock ))\n          return DFB_FUSION;\n\n     D_ASSUME( !shared->suspended );\n\n     if (shared->suspended) {\n          fusion_skirmish_dismiss( &shared->lock );\n          return DFB_OK;\n     }\n\n     /* Deactivate current context. */\n     if (contexts->active >= 0) {\n          DFBResult         ret;\n          CoreLayerContext *current = fusion_vector_at( &contexts->stack, contexts->active );\n\n          ret = dfb_layer_context_deactivate( current );\n          if (ret) {\n               D_DERROR( ret, \"Core/LayerControl: Could not deactivate current context of '%s'!\\n\",\n                         shared->description.name );\n          }\n     }\n\n     shared->suspended = true;\n\n     /* Unlock the layer. */\n     fusion_skirmish_dismiss( &shared->lock );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_resume( CoreLayer *layer )\n{\n     CoreLayerShared   *shared;\n     CoreLayerContexts *contexts;\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n\n     shared   = layer->shared;\n     contexts = &shared->contexts;\n\n     /* Lock the layer. */\n     if (fusion_skirmish_prevail( &shared->lock ))\n          return DFB_FUSION;\n\n     D_ASSUME( shared->suspended );\n\n     if (!shared->suspended) {\n          fusion_skirmish_dismiss( &shared->lock );\n          return DFB_OK;\n     }\n\n     /* (Re)Activate current context. */\n     if (contexts->active >= 0) {\n          DFBResult         ret;\n          CoreLayerContext *current = fusion_vector_at( &contexts->stack, contexts->active );\n\n          ret = dfb_layer_context_activate( current );\n          if (ret) {\n               D_DERROR( ret, \"Core/LayerControl: Could not activate current context of '%s'!\\n\",\n                         shared->description.name );\n          }\n     }\n\n     shared->suspended = false;\n\n     /* Unlock the layer. */\n     fusion_skirmish_dismiss( &shared->lock );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_create_context( CoreLayer         *layer,\n                          bool               stack,\n                          CoreLayerContext **ret_context )\n{\n     DFBResult          ret;\n     CoreLayerShared   *shared;\n     CoreLayerContexts *contexts;\n     CoreLayerContext  *context;\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n     D_ASSERT( ret_context != NULL );\n\n     shared   = layer->shared;\n     contexts = &shared->contexts;\n\n     D_DEBUG_AT( Core_LayerControl, \"%s( %s )\\n\", __FUNCTION__, shared->description.name );\n\n     /* Create the object. */\n     context = dfb_core_create_layer_context( layer->core );\n     if (!context)\n          return DFB_FUSION;\n\n     /* Lock the layer. */\n     if (fusion_skirmish_prevail( &shared->lock )) {\n          fusion_object_destroy( &context->object );\n          return DFB_FUSION;\n     }\n\n     /* Initialize the new context. */\n     ret = dfb_layer_context_init( context, layer, stack );\n     if (ret) {\n          fusion_skirmish_dismiss( &shared->lock );\n          return ret;\n     }\n\n     /* Add it to the context stack. */\n     if (fusion_vector_add( &contexts->stack, context )) {\n          dfb_layer_context_unref( context );\n          fusion_skirmish_dismiss( &shared->lock );\n          return DFB_FUSION;\n     }\n\n     /* Unlock the layer. */\n     fusion_skirmish_dismiss( &shared->lock );\n\n     /* Return the context. */\n     *ret_context = context;\n\n     D_DEBUG_AT( Core_LayerControl, \"  -> %p\\n\", context );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_get_active_context( CoreLayer         *layer,\n                              CoreLayerContext **ret_context )\n{\n     CoreLayerShared   *shared;\n     CoreLayerContexts *contexts;\n     CoreLayerContext  *context;\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n     D_ASSERT( ret_context != NULL );\n\n     shared   = layer->shared;\n     contexts = &shared->contexts;\n\n     D_DEBUG_AT( Core_LayerControl, \"%s( %s )\\n\", __FUNCTION__, shared->description.name );\n\n     /* Lock the layer. */\n     if (fusion_skirmish_prevail( &shared->lock ))\n          return DFB_FUSION;\n\n     /* Check for active context. */\n     if (contexts->active < 0) {\n          fusion_skirmish_dismiss( &shared->lock );\n          return DFB_NOCONTEXT;\n     }\n\n     /* Fetch active context. */\n     context = fusion_vector_at( &contexts->stack, contexts->active );\n\n     /* Increase the context's reference counter. */\n     if (dfb_layer_context_ref( context )) {\n          fusion_skirmish_dismiss( &shared->lock );\n          return DFB_FUSION;\n     }\n\n     D_DEBUG_AT( Core_LayerControl, \"  -> %p, %4dx%4d %s\\n\", context,\n                 context->config.width, context->config.height, dfb_pixelformat_name( context->config.pixelformat ) );\n\n     /* Return the context. */\n     *ret_context = context;\n\n     /* Unlock the layer. */\n     fusion_skirmish_dismiss( &shared->lock );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_get_primary_context( CoreLayer         *layer,\n                               bool               activate,\n                               CoreLayerContext **ret_context )\n{\n     DFBResult          ret;\n     CoreLayerShared   *shared;\n     CoreLayerContexts *contexts;\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n     D_ASSERT( ret_context != NULL );\n\n     shared   = layer->shared;\n     contexts = &shared->contexts;\n\n     /* Lock the layer. */\n     if (fusion_skirmish_prevail( &shared->lock ))\n          return DFB_FUSION;\n\n     D_DEBUG_AT( Core_LayerControl, \"%s( %s, %sactivate ) <- active: %d\\n\", __FUNCTION__, shared->description.name,\n                 activate ? \"\" : \"don't \", contexts->active );\n\n     /* Check for primary context. */\n     if (contexts->primary) {\n          /* Increase the context's reference counter. */\n          if (dfb_layer_context_ref( contexts->primary )) {\n               fusion_skirmish_dismiss( &shared->lock );\n               return DFB_FUSION;\n          }\n     }\n     else {\n          CoreLayerContext *primary;\n\n          /* Unlock the layer. */\n          fusion_skirmish_dismiss( &shared->lock );\n\n          /* Create the primary (shared) context. */\n          ret = dfb_layer_create_context( layer, true, &primary );\n          if (ret)\n               return ret;\n\n          /* Lock the layer again. */\n          if (fusion_skirmish_prevail( &shared->lock )) {\n               dfb_layer_context_unref( primary );\n               return DFB_FUSION;\n          }\n\n          /* Check if there was a race. */\n          if (contexts->primary) {\n               /* Throw away ours, the other was faster. */\n               dfb_layer_context_unref( primary );\n\n               /* Increase the context's reference counter. */\n               if (dfb_layer_context_ref( contexts->primary )) {\n                    fusion_skirmish_dismiss( &shared->lock );\n                    return DFB_FUSION;\n               }\n          }\n          else\n               contexts->primary = primary;\n     }\n\n     /* Activate if no context is active. */\n     if (contexts->active < 0 && activate) {\n          ret = dfb_layer_activate_context( layer, contexts->primary );\n          if (ret) {\n               dfb_layer_context_unref( contexts->primary );\n               fusion_skirmish_dismiss( &shared->lock );\n               return ret;\n          }\n     }\n\n     /* Return the context. */\n     *ret_context = contexts->primary;\n\n     /* Unlock the layer. */\n     fusion_skirmish_dismiss( &shared->lock );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_activate_context( CoreLayer        *layer,\n                            CoreLayerContext *context )\n{\n     DFBResult          ret;\n     int                index;\n     CoreLayerShared   *shared;\n     CoreLayerContexts *ctxs;\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n     D_ASSERT( context != NULL );\n\n     shared = layer->shared;\n     ctxs   = &shared->contexts;\n\n     /* Lock the layer. */\n     if (fusion_skirmish_prevail( &shared->lock ))\n          return DFB_FUSION;\n\n     D_DEBUG_AT( Core_LayerControl, \"%s( %s, %p )\\n\", __FUNCTION__, shared->description.name, context );\n\n     D_ASSERT( fusion_vector_contains( &ctxs->stack, context ) );\n\n     /* Lookup the context in the context stack. */\n     index = fusion_vector_index_of( &ctxs->stack, context );\n\n     /* Lock the context. */\n     if (dfb_layer_context_lock( context )) {\n          fusion_skirmish_dismiss( &shared->lock );\n          return DFB_FUSION;\n     }\n\n     /* Need to activate. */\n     if (ctxs->active != index) {\n          /* Another context currently active. */\n          if (ctxs->active >= 0) {\n               CoreLayerContext *current = fusion_vector_at( &ctxs->stack, ctxs->active );\n\n               /* Deactivate current context. */\n               if (!shared->suspended) {\n                    ret = dfb_layer_context_deactivate( current );\n                    if (ret)\n                         goto error;\n               }\n\n               /* No active context. */\n               ctxs->active = -1;\n          }\n\n          /* Activate context now. */\n          if (!shared->suspended) {\n               ret = dfb_layer_context_activate( context );\n               if (ret)\n                    goto error;\n          }\n\n          ctxs->active = index;\n     }\n\n     /* Unlock the context. */\n     dfb_layer_context_unlock( context );\n\n     /* Unlock the layer. */\n     fusion_skirmish_dismiss( &shared->lock );\n\n     return DFB_OK;\n\nerror:\n     dfb_layer_context_unlock( context );\n\n     fusion_skirmish_dismiss( &shared->lock );\n\n     return ret;\n}\n\nDFBResult\ndfb_layer_remove_context( CoreLayer        *layer,\n                          CoreLayerContext *context )\n{\n     int                index;\n     CoreLayerShared   *shared;\n     CoreLayerContexts *ctxs;\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n     D_ASSERT( context != NULL );\n\n     shared = layer->shared;\n     ctxs   = &shared->contexts;\n\n     /* Lock the layer. */\n     if (fusion_skirmish_prevail( &shared->lock ))\n          return DFB_FUSION;\n\n     D_DEBUG_AT( Core_LayerControl, \"%s( %s, %p )\\n\", __FUNCTION__, shared->description.name, context );\n\n     D_ASSUME( fusion_vector_contains( &ctxs->stack, context ) );\n\n     /* Lookup the context in the context stack. */\n     index = fusion_vector_index_of( &ctxs->stack, context );\n     if (index < 0) {\n          fusion_skirmish_dismiss( &shared->lock );\n          return DFB_OK;\n     }\n\n     /* Lock the context. */\n     if (dfb_layer_context_lock( context )) {\n          fusion_skirmish_dismiss( &shared->lock );\n          return DFB_FUSION;\n     }\n\n     /* Remove context from context stack. */\n     fusion_vector_remove( &ctxs->stack, index );\n\n     /* Check if the primary context is removed. */\n     if (context == ctxs->primary)\n          ctxs->primary = NULL;\n\n     /* Need to deactivate. */\n     if (ctxs->active == index) {\n          /* Deactivate the context. */\n          if (!shared->suspended)\n               dfb_layer_context_deactivate( context );\n\n          /* There's no active context anymore. */\n          ctxs->active = -1;\n\n          if (ctxs->primary)\n               D_ASSERT( fusion_vector_contains( &ctxs->stack, ctxs->primary ) );\n\n          if (fusion_vector_has_elements( &ctxs->stack )) {\n               CoreLayerContext *ctx;\n\n               /* Activate most recent context. */\n               index = fusion_vector_size( &ctxs->stack ) - 1;\n               ctx   = fusion_vector_at( &ctxs->stack, index );\n\n               if (shared->suspended || dfb_layer_context_activate( ctx ) == DFB_OK)\n                    ctxs->active = index;\n          }\n     }\n     else if (ctxs->active > index) {\n          /* Adjust index of active context due to the removed context. */\n          ctxs->active--;\n     }\n\n     /* Unlock the context. */\n     dfb_layer_context_unlock( context );\n\n     /* Unlock the layer. */\n     fusion_skirmish_dismiss( &shared->lock );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_get_current_output_field( CoreLayer *layer,\n                                    int       *ret_field )\n{\n     DFBResult                ret;\n     const DisplayLayerFuncs *funcs;\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->funcs != NULL );\n     D_ASSERT( ret_field != NULL );\n\n     funcs = layer->funcs;\n\n     if (!funcs->GetCurrentOutputField)\n          return DFB_UNSUPPORTED;\n\n     ret = funcs->GetCurrentOutputField( layer, layer->driver_data, layer->layer_data, ret_field );\n     if (ret)\n          return ret;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_get_level( CoreLayer *layer,\n                     int       *ret_level )\n{\n     const DisplayLayerFuncs *funcs;\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->funcs != NULL );\n     D_ASSERT( ret_level != NULL );\n\n     funcs = layer->funcs;\n\n     if (!funcs->GetLevel)\n          return DFB_UNSUPPORTED;\n\n     return funcs->GetLevel( layer, layer->driver_data, layer->layer_data, ret_level );\n}\n\nDFBResult\ndfb_layer_set_level( CoreLayer *layer,\n                     int        level )\n{\n     const DisplayLayerFuncs *funcs;\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->funcs != NULL );\n\n     funcs = layer->funcs;\n\n     if (!funcs->SetLevel)\n          return DFB_UNSUPPORTED;\n\n     return funcs->SetLevel( layer, layer->driver_data, layer->layer_data, level );\n}\n\nDFBResult\ndfb_layer_wait_vsync( CoreLayer *layer )\n{\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->screen != NULL );\n\n     return dfb_screen_wait_vsync( layer->screen );\n}\n\nDFBResult\ndfb_layer_get_source_info( CoreLayer                        *layer,\n                           int                               source,\n                           DFBDisplayLayerSourceDescription *ret_desc )\n{\n     CoreLayerShared *shared;\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n     D_ASSERT( source >= 0 );\n     D_ASSERT( source < layer->shared->description.sources );\n     D_ASSERT( ret_desc != NULL );\n\n     shared = layer->shared;\n\n     *ret_desc = shared->sources[source].description;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/core/layer_control.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__LAYER_CONTROL_H__\n#define __CORE__LAYER_CONTROL_H__\n\n#include <core/coretypes.h>\n\n/**********************************************************************************************************************/\n\nDFBResult dfb_layer_suspend                 ( CoreLayer                         *layer );\n\nDFBResult dfb_layer_resume                  ( CoreLayer                         *layer );\n\nDFBResult dfb_layer_create_context          ( CoreLayer                         *layer,\n                                              bool                               stack,\n                                              CoreLayerContext                 **ret_context );\n\nDFBResult dfb_layer_get_active_context      ( CoreLayer                         *layer,\n                                              CoreLayerContext                 **ret_context );\n\nDFBResult dfb_layer_get_primary_context     ( CoreLayer                         *layer,\n                                              bool                               activate,\n                                              CoreLayerContext                 **ret_context );\n\nDFBResult dfb_layer_activate_context        ( CoreLayer                         *layer,\n                                              CoreLayerContext                  *context );\n\nDFBResult dfb_layer_remove_context          ( CoreLayer                         *layer,\n                                              CoreLayerContext                  *context );\n\nDFBResult dfb_layer_get_current_output_field( CoreLayer                         *layer,\n                                              int                               *ret_field );\n\nDFBResult dfb_layer_get_level               ( CoreLayer                         *layer,\n                                              int                               *ret_level );\n\nDFBResult dfb_layer_set_level               ( CoreLayer                         *layer,\n                                              int                                level );\n\nDFBResult dfb_layer_wait_vsync              ( CoreLayer                         *layer );\n\nDFBResult dfb_layer_get_source_info         ( CoreLayer                         *layer,\n                                              int                                source,\n                                              DFBDisplayLayerSourceDescription  *ret_desc );\n\n#endif\n"
  },
  {
    "path": "src/core/layer_region.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreLayerRegion.h>\n#include <core/CoreSurface.h>\n#include <core/CoreSurfaceClient.h>\n#include <core/core.h>\n#include <core/layers.h>\n#include <core/layer_context.h>\n#include <core/layer_control.h>\n#include <core/layer_region.h>\n#include <core/screen.h>\n#include <core/surface_allocation.h>\n#include <core/surface_client.h>\n#include <core/system.h>\n#include <fusion/conf.h>\n#include <fusion/shmalloc.h>\n#include <gfx/util.h>\n\nD_DEBUG_DOMAIN( Core_LayerRegion,       \"Core/LayerRegion\",        \"DirectFB Core Display Layer Region\" );\nD_DEBUG_DOMAIN( Core_LayerRegionLock,   \"Core/LayerRegion/Lock\",   \"DirectFB Core Display Layer Region Lock\" );\nD_DEBUG_DOMAIN( Core_LayerRegionUpdate, \"Core/LayerRegion/Update\", \"DirectFB Core Display Layer Region Update\" );\n\n/**********************************************************************************************************************/\n\nstatic DFBResult region_buffer_unlock      ( CoreLayerRegion            *region,\n                                             CoreSurfaceBufferLock      *left_buffer_lock,\n                                             CoreSurfaceBufferLock      *right_buffer_lock );\n\nstatic DFBResult region_buffer_lock        ( CoreLayerRegion            *region,\n                                             CoreSurface                *surface,\n                                             DFBSurfaceBufferRole        role,\n                                             CoreSurfaceBufferLock      *left_buffer_lock,\n                                             CoreSurfaceBufferLock      *right_buffer_lock );\n\nstatic DFBResult dfb_layer_region_set      ( CoreLayerRegion            *region,\n                                             CoreLayerRegionConfig      *config,\n                                             CoreLayerRegionConfigFlags  flags,\n                                             CoreSurface                *surface );\n\nstatic DFBResult dfb_layer_region_realize  ( CoreLayerRegion            *region,\n                                             bool                        set );\n\nstatic DFBResult dfb_layer_region_unrealize( CoreLayerRegion            *region );\n\n/**********************************************************************************************************************/\n\nstatic void\nregion_destructor( FusionObject *object,\n                   bool          zombie,\n                   void         *ctx )\n{\n     DFBResult         ret;\n     CoreLayerRegion  *region = (CoreLayerRegion*) object;\n     CoreLayer        *layer;\n     CoreLayerShared  *shared;\n     CoreLayerContext *context;\n\n     layer  = dfb_layer_at( region->layer_id );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n\n     shared = layer->shared;\n\n     D_DEBUG_AT( Core_LayerRegion, \"Destroying region %p (%s, %dx%d, %s, %s, %s, %s%s)\\n\",\n                 region, shared->description.name, region->config.width, region->config.height,\n                 D_FLAGS_IS_SET( region->state, CLRSF_CONFIGURED ) ? \"configured\" : \"unconfigured\",\n                 D_FLAGS_IS_SET( region->state, CLRSF_ENABLED )    ? \"enabled\" : \"disabled\",\n                 D_FLAGS_IS_SET( region->state, CLRSF_ACTIVE )     ? \"active\" : \"inactive\",\n                 D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )   ? \"realized\" : \"not realized\",\n                 zombie ? \" ZOMBIE\" : \"\" );\n\n     /* Hide region etc. */\n     if (D_FLAGS_IS_SET( region->state, CLRSF_ENABLED ))\n          dfb_layer_region_disable( region );\n\n     /* Remove the region from the context. */\n     ret = fusion_object_lookup( core_dfb->shared->layer_context_pool, region->context_id, (FusionObject**) &context );\n     if (ret == DFB_OK)\n          dfb_layer_context_remove_region( context, region );\n\n     /* Throw away its surface. */\n     if (region->surface) {\n          /* Detach the global listener. */\n          dfb_surface_detach_global( region->surface, &region->surface_reaction );\n\n          /* Detach the surface event listener. */\n          dfb_surface_detach( region->surface, &region->surface_event_reaction );\n\n          dfb_surface_client_unref( region->surface_client );\n\n          /* Unlink from structure. */\n          dfb_surface_unlink( &region->surface );\n     }\n\n     /* Free driver's region data. */\n     if (region->region_data)\n          SHFREE( shared->shmpool, region->region_data );\n\n     CoreLayerRegion_Deinit_Dispatch( &region->call );\n\n     /* Deinitialize the lock. */\n     fusion_skirmish_destroy( &region->lock );\n\n     /* Destroy the object. */\n     fusion_object_destroy( object );\n}\n\nFusionObjectPool *\ndfb_layer_region_pool_create( const FusionWorld *world )\n{\n     FusionObjectPool *pool;\n\n     pool = fusion_object_pool_create( \"Layer Region Pool\",\n                                       sizeof(CoreLayerRegion), sizeof(CoreLayerRegionNotification),\n                                       region_destructor, NULL, world );\n\n     return pool;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_layer_region_create( CoreLayerContext  *context,\n                         CoreLayerRegion  **ret_region )\n{\n     CoreLayer       *layer;\n     CoreLayerShared *shared;\n     CoreLayerRegion *region;\n\n     D_ASSERT( context != NULL );\n     D_ASSERT( ret_region != NULL );\n\n     D_DEBUG_AT( Core_LayerRegion, \"%s()\\n\", __FUNCTION__ );\n\n     layer = dfb_layer_at( context->layer_id );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n\n     shared = layer->shared;\n\n     /* Create the region object. */\n     region = dfb_core_create_layer_region( layer->core );\n     if (!region)\n          return DFB_FUSION;\n\n     region->layer_id   = context->layer_id;\n     region->context_id = context->object.id;\n\n     /* Initialize the lock. */\n     if (fusion_skirmish_init2( &region->lock, \"Layer Region\", dfb_core_world( layer->core ),\n                                fusion_config->secure_fusion )) {\n          fusion_object_destroy( &region->object );\n          return DFB_FUSION;\n     }\n\n     /* Change global reaction lock. */\n     fusion_object_set_lock( &region->object, &region->lock );\n\n     region->state = CLRSF_FROZEN;\n\n     if (shared->description.surface_accessor)\n          region->surface_accessor = shared->description.surface_accessor;\n     else\n          region->surface_accessor = CSAID_LAYER0 + region->layer_id;\n\n     CoreLayerRegion_Init_Dispatch( layer->core, region, &region->call );\n\n     /* Activate the object. */\n     fusion_object_activate( &region->object );\n\n     /* Add the region to the context. */\n     dfb_layer_context_add_region( context, region );\n\n     /* Return the new region. */\n     *ret_region = region;\n\n     D_DEBUG_AT( Core_LayerRegion, \"  -> %p\\n\", region );\n\n     return DFB_OK;\n}\n\nDirectResult\ndfb_layer_region_lock( CoreLayerRegion *region )\n{\n     D_ASSERT( region != NULL );\n\n     return fusion_skirmish_prevail( &region->lock );\n}\n\nDirectResult\ndfb_layer_region_unlock( CoreLayerRegion *region )\n{\n     D_ASSERT( region != NULL );\n\n     return fusion_skirmish_dismiss( &region->lock );\n}\n\nDFBResult\ndfb_layer_region_activate( CoreLayerRegion *region )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_LayerRegion, \"%s( %p )\\n\", __FUNCTION__, region );\n\n     D_ASSERT( region != NULL );\n\n     /* Lock the region. */\n     if (dfb_layer_region_lock( region ))\n          return DFB_FUSION;\n\n     D_ASSUME( !D_FLAGS_IS_SET( region->state, CLRSF_ACTIVE ) );\n\n     if (D_FLAGS_IS_SET( region->state, CLRSF_ACTIVE )) {\n          dfb_layer_region_unlock( region );\n          return DFB_OK;\n     }\n\n     /* Realize the region if it's enabled. */\n     if (D_FLAGS_IS_SET( region->state, CLRSF_ENABLED )) {\n          ret = dfb_layer_region_realize( region, true );\n          if (ret) {\n               dfb_layer_region_unlock( region );\n               return ret;\n          }\n     }\n\n     /* Update the region's state. */\n     D_FLAGS_SET( region->state, CLRSF_ACTIVE );\n\n     /* Unlock the region. */\n     dfb_layer_region_unlock( region );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_region_deactivate( CoreLayerRegion *region )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_LayerRegion, \"%s( %p )\\n\", __FUNCTION__, region );\n\n     D_ASSERT( region != NULL );\n\n     /* Lock the region. */\n     if (dfb_layer_region_lock( region ))\n          return DFB_FUSION;\n\n     D_ASSUME( D_FLAGS_IS_SET( region->state, CLRSF_ACTIVE ) );\n\n     if (!D_FLAGS_IS_SET( region->state, CLRSF_ACTIVE )) {\n          dfb_layer_region_unlock( region );\n          return DFB_OK;\n     }\n\n     /* Unrealize the region. */\n     if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) {\n          ret = dfb_layer_region_unrealize( region );\n          if (ret) {\n               dfb_layer_region_unlock( region );\n               return ret;\n          }\n     }\n\n     /* Update the region's state. */\n     D_FLAGS_CLEAR( region->state, CLRSF_ACTIVE );\n\n     /* Unlock the region. */\n     dfb_layer_region_unlock( region );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_region_enable( CoreLayerRegion *region )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_LayerRegion, \"%s( %p )\\n\", __FUNCTION__, region );\n\n     D_ASSERT( region != NULL );\n\n     /* Lock the region. */\n     if (dfb_layer_region_lock( region ))\n          return DFB_FUSION;\n\n     D_ASSUME( !D_FLAGS_IS_SET( region->state, CLRSF_ENABLED ) );\n\n     if (D_FLAGS_IS_SET( region->state, CLRSF_ENABLED )) {\n          dfb_layer_region_unlock( region );\n          return DFB_OK;\n     }\n\n     /* Realize the region if it's active. */\n     if (D_FLAGS_IS_SET( region->state, CLRSF_ACTIVE )) {\n          ret = dfb_layer_region_realize( region, true );\n          if (ret) {\n               dfb_layer_region_unlock( region );\n               return ret;\n          }\n     }\n\n     /* Update the region's state. */\n     D_FLAGS_SET( region->state, CLRSF_ENABLED );\n\n     /* Unlock the region. */\n     dfb_layer_region_unlock( region );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_region_disable( CoreLayerRegion *region )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_LayerRegion, \"%s( %p )\\n\", __FUNCTION__, region );\n\n     D_ASSERT( region != NULL );\n\n     /* Lock the region. */\n     if (dfb_layer_region_lock( region ))\n          return DFB_FUSION;\n\n     D_ASSUME( D_FLAGS_IS_SET( region->state, CLRSF_ENABLED ) );\n\n     if (!D_FLAGS_IS_SET( region->state, CLRSF_ENABLED )) {\n          dfb_layer_region_unlock( region );\n          return DFB_OK;\n     }\n\n     /* Unrealize the region. */\n     if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) {\n          ret = dfb_layer_region_unrealize( region );\n          if (ret)\n               return ret;\n     }\n\n     /* Update the region's state. */\n     D_FLAGS_CLEAR( region->state, CLRSF_ENABLED );\n\n     /* Unlock the region. */\n     dfb_layer_region_unlock( region );\n\n     return DFB_OK;\n}\n\nstatic ReactionResult\nregion_surface_react( const void *msg_data,\n                      void       *ctx )\n{\n     const DFBSurfaceEvent *evt  = msg_data;\n     CoreLayerRegion       *region = ctx;\n\n     D_DEBUG_AT( Core_LayerRegionUpdate, \"%s( %p ) <- type %06x\\n\", __FUNCTION__, evt, evt->type );\n     D_DEBUG_AT( Core_LayerRegionUpdate, \"  -> surface id %u\\n\", evt->surface_id );\n\n     if (evt->type == DSEVT_UPDATE) {\n          D_DEBUG_AT( Core_LayerRegionUpdate, \"  -> updated %4d,%4d-%4dx%4d (left)\\n\",\n                      DFB_RECTANGLE_VALS_FROM_REGION( &evt->update ) );\n          D_DEBUG_AT( Core_LayerRegionUpdate, \"  -> updated %4d,%4d-%4dx%4d (right)\\n\",\n                      DFB_RECTANGLE_VALS_FROM_REGION( &evt->update_right ) );\n          D_DEBUG_AT( Core_LayerRegionUpdate, \"  -> flip count %u\\n\", evt->flip_count );\n          D_DEBUG_AT( Core_LayerRegionUpdate, \"  -> time stamp %lld\\n\", evt->time_stamp );\n          D_DEBUG_AT( Core_LayerRegionUpdate, \"  -> layer region %p\\n\", region );\n\n          if (direct_log_domain_check( &Core_LayerRegionUpdate )) {\n               dfb_surface_lock( region->surface );\n               CoreSurfaceBuffer *buffer;\n               D_UNUSED_P( buffer );\n               buffer = dfb_surface_get_buffer3( region->surface, DSBR_FRONT, DSSE_LEFT, evt->flip_count );\n               D_DEBUG_AT( Core_LayerRegionUpdate, \"  -> buffer       %p\\n\", buffer );\n               dfb_surface_unlock( region->surface );\n          }\n\n          region->surface_flip_count = evt->flip_count;\n\n          if (!CoreLayerRegion_FlipUpdate2( region, &evt->update, &evt->update_right, DSFLIP_ONSYNC | DSFLIP_UPDATE,\n                                            evt->flip_count, evt->time_stamp ))\n               CoreSurfaceClient_FrameAck( region->surface_client, evt->flip_count );\n     }\n     else if (evt->type == DSEVT_DESTROYED)\n          return RS_REMOVE;\n\n     return RS_OK;\n}\n\nDFBResult\ndfb_layer_region_set_surface( CoreLayerRegion *region,\n                              CoreSurface     *surface,\n                              bool             update )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_LayerRegion, \"%s( %p, %p, %d )\\n\", __FUNCTION__, region, surface, update );\n\n     D_ASSERT( region != NULL );\n     D_ASSERT( surface != NULL );\n\n     /* Lock the region. */\n     if (dfb_layer_region_lock( region ))\n          return DFB_FUSION;\n\n     if (region->surface != surface) {\n          /* Setup hardware for the new surface if the region is realized. */\n          if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) {\n               ret = dfb_layer_region_set( region, &region->config, CLRCF_SURFACE | CLRCF_PALETTE, surface );\n               if (ret) {\n                    dfb_layer_region_unlock( region );\n                    return ret;\n               }\n          }\n\n          /* Throw away the old surface. */\n          if (region->surface) {\n               /* Detach the global listener. */\n               dfb_surface_detach_global( region->surface, &region->surface_reaction );\n\n               /* Detach the surface event listener. */\n               dfb_surface_detach( region->surface, &region->surface_event_reaction );\n\n               dfb_surface_client_unref( region->surface_client );\n\n               /* Unlink surface from structure. */\n               dfb_surface_unlink( &region->surface );\n          }\n\n          /* Take the new surface. */\n          if (surface) {\n               /* Link surface into structure. */\n               if (dfb_surface_link( &region->surface, surface )) {\n                    D_WARN( \"region has lost its surface\" );\n                    dfb_layer_region_unlock( region );\n                    return DFB_FUSION;\n               }\n\n               /* Create the surface client. */\n               ret = CoreSurface_CreateClient( region->surface, &region->surface_client );\n               if (ret) {\n                    D_WARN( \"failed to create surface client\" );\n                    dfb_layer_region_unlock( region );\n                    return ret;\n               }\n\n               /* Attach the global listener. */\n               dfb_surface_attach_global( region->surface, DFB_LAYER_REGION_SURFACE_LISTENER, region,\n                                          &region->surface_reaction );\n\n               /* Attach the surface event listener. */\n               dfb_surface_attach_channel( region->surface, CSCH_EVENT, region_surface_react, region,\n                                           &region->surface_event_reaction );\n          }\n\n          if (update && D_FLAGS_ARE_SET( region->state, CLRSF_ENABLED | CLRSF_ACTIVE )) {\n               region->surface_flip_count = surface->flips;\n\n               dfb_layer_region_flip_update( region, NULL, DSFLIP_UPDATE );\n          }\n     }\n\n     /* Unlock the region. */\n     dfb_layer_region_unlock( region );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_region_get_surface( CoreLayerRegion  *region,\n                              CoreSurface     **ret_surface )\n{\n     D_DEBUG_AT( Core_LayerRegion, \"%s( %p )\\n\", __FUNCTION__, region );\n\n     D_ASSERT( region != NULL );\n     D_ASSERT( ret_surface != NULL );\n\n     /* Lock the region. */\n     if (dfb_layer_region_lock( region ))\n          return DFB_FUSION;\n\n     D_ASSUME( region->surface != NULL );\n\n     /* Check for NULL surface. */\n     if (!region->surface) {\n          dfb_layer_region_unlock( region );\n          return DFB_UNSUPPORTED;\n     }\n\n     /* Increase the surface's reference counter. */\n     if (dfb_surface_ref( region->surface )) {\n          dfb_layer_region_unlock( region );\n          return DFB_FUSION;\n     }\n\n     /* Return the surface. */\n     *ret_surface = region->surface;\n\n     /* Unlock the region. */\n     dfb_layer_region_unlock( region );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_region_flip_update( CoreLayerRegion     *region,\n                              const DFBRegion     *update,\n                              DFBSurfaceFlipFlags  flags )\n{\n     DFBResult                ret = DFB_OK;\n     DFBRegion                unrotated;\n     DFBRegion                rotated;\n     CoreLayer               *layer;\n     CoreSurface             *surface;\n     const DisplayLayerFuncs *funcs;\n\n     if (update)\n          D_DEBUG_AT( Core_LayerRegion, \"%s( %p, %p, 0x%08x ) <- [%4d,%4d-%4dx%4d]\\n\", __FUNCTION__,\n                      region, update, flags, DFB_RECTANGLE_VALS_FROM_REGION( update ) );\n     else\n          D_DEBUG_AT( Core_LayerRegion, \"%s( %p, %p, 0x%08x )\\n\", __FUNCTION__, region, update, flags );\n\n\n     D_ASSERT( region != NULL );\n\n     /* Lock the region. */\n     if (dfb_layer_region_lock( region ))\n          return DFB_FUSION;\n\n     /* Check for stereo region */\n     if (region->config.options & DLOP_STEREO) {\n          ret = dfb_layer_region_flip_update_stereo( region, update, update, flags );\n          dfb_layer_region_unlock( region );\n          return ret;\n     }\n\n     D_ASSUME( region->surface != NULL );\n\n     /* Check for NULL surface. */\n     if (!region->surface) {\n          D_DEBUG_AT( Core_LayerRegion, \"  -> no surface => no update!\\n\" );\n          dfb_layer_region_unlock( region );\n          return DFB_UNSUPPORTED;\n     }\n\n     surface = region->surface;\n\n     layer = dfb_layer_at( region->layer_id );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->funcs != NULL );\n\n     funcs = layer->funcs;\n\n     /* Unfreeze region. */\n     if (D_FLAGS_IS_SET( region->state, CLRSF_FROZEN )) {\n          D_FLAGS_CLEAR( region->state, CLRSF_FROZEN );\n\n          if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) {\n               ret = dfb_layer_region_set( region, &region->config, CLRCF_ALL, surface );\n               if (ret)\n                    D_DERROR( ret, \"Core/LayerRegion: \"\n                                   \"dfb_layer_region_set() in dfb_layer_region_flip_update() failed!\\n\" );\n          }\n          else if (D_FLAGS_ARE_SET( region->state, CLRSF_ENABLED | CLRSF_ACTIVE )) {\n               ret = dfb_layer_region_realize( region, true );\n               if (ret)\n                    D_DERROR( ret, \"Core/LayerRegion: \"\n                                   \"dfb_layer_region_realize() in dfb_layer_region_flip_update() failed!\\n\" );\n          }\n\n          if (ret) {\n               dfb_layer_region_unlock( region );\n               return ret;\n          }\n     }\n\n     dfb_gfxcard_flush();\n\n     dfb_surface_lock( surface );\n\n     if (!(surface->frametime_config.flags & DFTCF_INTERVAL))\n          dfb_screen_get_frame_interval( layer->screen, &surface->frametime_config.interval );\n\n     if (flags & DSFLIP_UPDATE)\n          goto update_only;\n\n     /* Depending on the buffer mode. */\n     switch (region->config.buffermode) {\n          case DLBM_TRIPLE:\n          case DLBM_BACKVIDEO:\n               /* Check if simply swapping the buffers is possible. */\n               if ((flags & DSFLIP_SWAP) ||\n                   (!(flags & DSFLIP_BLIT) && !surface->rotation &&\n                    (!update || (update->x1 == 0                          &&\n                                 update->y1 == 0                          &&\n                                 update->x2 == surface->config.size.w - 1 &&\n                                 update->y2 == surface->config.size.h - 1)))) {\n                    D_DEBUG_AT( Core_LayerRegion, \"  -> going to swap buffers...\\n\" );\n\n                    /* Use the driver's routine if the region is realized. */\n                    if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) {\n                         CoreSurfaceBufferLock left;\n\n                         D_ASSUME( funcs->FlipRegion != NULL );\n\n                         ret = region_buffer_lock( region, surface, DSBR_BACK, &left, NULL );\n                         if (ret)\n                              goto out;\n\n                         D_DEBUG_AT( Core_LayerRegion, \"  -> flipping region using driver...\\n\" );\n\n                         if (funcs->FlipRegion)\n                              ret = funcs->FlipRegion( layer, layer->driver_data, layer->layer_data,\n                                                       region->region_data, surface, flags, update, &left, NULL, NULL );\n\n                         if (!(dfb_system_caps() & CSCAPS_NOTIFY_DISPLAY)) {\n                              D_DEBUG_AT( Core_LayerRegion, \"  -> system without notify_display support, calling it now\\n\" );\n\n                              dfb_surface_notify_display2( surface, left.allocation->index );\n                         }\n\n                         /* Unlock region buffer since the lock is no longer needed. */\n                         region_buffer_unlock(region, &left, NULL);\n                    }\n                    else {\n                         D_DEBUG_AT( Core_LayerRegion, \"  -> flipping region not using driver...\\n\" );\n\n                         /* Just do the hardware independent work. */\n                         dfb_surface_flip_buffers( surface, false );\n                    }\n                    break;\n               }\n               /* fall through */\n\n          case DLBM_BACKSYSTEM:\n               D_DEBUG_AT( Core_LayerRegion, \"  -> going to copy portion...\\n\" );\n\n               if ((flags & DSFLIP_WAITFORSYNC) == DSFLIP_WAITFORSYNC) {\n                    D_DEBUG_AT( Core_LayerRegion, \"  -> waiting for VSync...\\n\" );\n\n                    dfb_layer_wait_vsync( layer );\n               }\n\n               D_DEBUG_AT( Core_LayerRegion, \"  -> copying content from back to front buffer...\\n\" );\n\n               /* Copy updated contents from back to front buffer. */\n               dfb_back_to_front_copy_stereo( surface, DSSE_LEFT, update, NULL, surface->rotation );\n\n               if ((flags & DSFLIP_WAITFORSYNC) == DSFLIP_WAIT) {\n                    D_DEBUG_AT( Core_LayerRegion, \"  -> waiting for VSync...\\n\" );\n\n                    dfb_layer_wait_vsync( layer );\n               }\n               /* fall through */\n\n          case DLBM_FRONTONLY:\nupdate_only:\n               /* Tell the driver about the update if the region is realized. */\n               if (funcs->UpdateRegion && D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) {\n                    CoreSurfaceBufferLock left;\n\n                    if (surface) {\n                         /* Lock region buffer before it is used. */\n                         region_buffer_lock( region, surface, DSBR_FRONT, &left, NULL );\n\n                         D_ASSERT( left.allocation != NULL );\n                    }\n\n                    D_DEBUG_AT( Core_LayerRegion, \"  -> notifying driver about updated content...\\n\" );\n\n                    if (!update) {\n                         unrotated = DFB_REGION_INIT_FROM_RECTANGLE_VALS( 0, 0,\n                                                                          region->config.width, region->config.height );\n                         update    = &unrotated;\n                    }\n\n                    dfb_region_from_rotated( &rotated, update, &surface->config.size, surface->rotation );\n\n                    ret = funcs->UpdateRegion( layer, layer->driver_data, layer->layer_data,\n                                               region->region_data, surface, &rotated, &left, NULL, NULL );\n\n                    if (!(dfb_system_caps() & CSCAPS_NOTIFY_DISPLAY)) {\n                         D_DEBUG_AT( Core_LayerRegion, \"  -> system without notify_display support, calling it now\\n\" );\n\n                         dfb_surface_notify_display2( surface, left.allocation->index );\n                    }\n\n                    /* Unlock region buffer since the lock is no longer needed. */\n                    if (surface)\n                         region_buffer_unlock(region, &left, NULL);\n               }\n               break;\n\n          default:\n               D_BUG( \"unknown buffer mode\" );\n               ret = DFB_BUG;\n     }\n\n     D_DEBUG_AT( Core_LayerRegion, \"  -> done\\n\" );\n\nout:\n     dfb_surface_unlock( surface );\n\n     /* Unlock the region. */\n     dfb_layer_region_unlock( region );\n\n     return ret;\n}\n\nDFBResult\ndfb_layer_region_flip_update_stereo( CoreLayerRegion     *region,\n                                     const DFBRegion     *left_update,\n                                     const DFBRegion     *right_update,\n                                     DFBSurfaceFlipFlags  flags )\n{\n     DFBResult                ret = DFB_OK;\n     DFBRegion                unrotated;\n     DFBRegion                left_rotated, right_rotated;\n     CoreLayer               *layer;\n     CoreSurface             *surface;\n     const DisplayLayerFuncs *funcs;\n     DFBSurfaceStereoEye      eyes = 0;\n\n     D_DEBUG_AT( Core_LayerRegion, \"%s( %p, %p, %p, 0x%08x )\\n\", __FUNCTION__, region, left_update, right_update, flags );\n     if (left_update)\n          D_DEBUG_AT( Core_LayerRegion, \"Left: [%4d,%4d-%4dx%4d]\\n\", DFB_RECTANGLE_VALS_FROM_REGION( left_update ) );\n     if (right_update)\n          D_DEBUG_AT( Core_LayerRegion, \"Right: [%4d,%4d-%4dx%4d]\\n\", DFB_RECTANGLE_VALS_FROM_REGION( right_update ) );\n\n     D_ASSERT( region != NULL );\n\n     /* Lock the region. */\n     if (dfb_layer_region_lock( region ))\n          return DFB_FUSION;\n\n     /* Check for stereo region */\n     if (!(region->config.options & DLOP_STEREO)) {\n          D_DEBUG_AT( Core_LayerRegion, \"  -> not a stereo region!\\n\" );\n          dfb_layer_region_unlock( region );\n          return DFB_UNSUPPORTED;\n     }\n\n     D_ASSUME( region->surface != NULL );\n\n     /* Check for NULL surface. */\n     if (!region->surface) {\n          D_DEBUG_AT( Core_LayerRegion, \"  -> no surface => no update!\\n\" );\n          dfb_layer_region_unlock( region );\n          return DFB_UNSUPPORTED;\n     }\n\n     surface = region->surface;\n     layer   = dfb_layer_at( region->layer_id );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->funcs != NULL );\n\n     funcs = layer->funcs;\n\n     /* Unfreeze region. */\n     if (D_FLAGS_IS_SET( region->state, CLRSF_FROZEN )) {\n          D_FLAGS_CLEAR( region->state, CLRSF_FROZEN );\n\n          if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) {\n               ret = dfb_layer_region_set( region, &region->config, CLRCF_ALL, surface );\n               if (ret)\n                    D_DERROR( ret, \"Core/LayerRegion: \"\n                                   \"dfb_layer_region_set() in dfb_layer_region_flip_update() failed!\\n\" );\n          }\n          else if (D_FLAGS_ARE_SET( region->state, CLRSF_ENABLED | CLRSF_ACTIVE )) {\n               ret = dfb_layer_region_realize( region, true );\n               if (ret)\n                    D_DERROR( ret, \"Core/LayerRegion: \"\n                                   \"dfb_layer_region_realize() in dfb_layer_region_flip_update() failed!\\n\" );\n          }\n\n          if (ret) {\n               dfb_layer_region_unlock( region );\n               return ret;\n          }\n     }\n\n     dfb_gfxcard_flush();\n\n     dfb_surface_lock( surface );\n\n     if (!(surface->frametime_config.flags & DFTCF_INTERVAL))\n          dfb_screen_get_frame_interval( layer->screen, &surface->frametime_config.interval );\n\n     if (flags & DSFLIP_UPDATE)\n          goto update_only;\n\n     /* Depending on the buffer mode. */\n     switch (region->config.buffermode) {\n          case DLBM_TRIPLE:\n          case DLBM_BACKVIDEO:\n               /* Check if simply swapping the buffers is possible. */\n               if ((flags & DSFLIP_SWAP) ||\n                   (!(flags & DSFLIP_BLIT) && !surface->rotation &&\n                    ((!left_update && !right_update) ||\n                     ((left_update->x1 == 0                          &&\n                       left_update->y1 == 0                          &&\n                       left_update->x2 == surface->config.size.w - 1 &&\n                       left_update->y2 == surface->config.size.h - 1) &&\n                      (right_update->x1 == 0                          &&\n                       right_update->y1 == 0                          &&\n                       right_update->x2 == surface->config.size.w - 1 &&\n                       right_update->y2 == surface->config.size.h - 1))))) {\n                    D_DEBUG_AT( Core_LayerRegion, \"  -> going to swap buffers...\\n\" );\n\n                    /* Use the driver's routine if the region is realized. */\n                    if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) {\n                         CoreSurfaceBufferLock left, right;\n\n                         D_ASSUME( funcs->FlipRegion != NULL );\n\n                         ret = region_buffer_lock( region, surface, DSBR_BACK, &left, &right );\n                         if (ret)\n                              goto out;\n\n                         D_DEBUG_AT( Core_LayerRegion, \"  -> flipping region using driver...\\n\" );\n\n                         if (funcs->FlipRegion)\n                              ret = funcs->FlipRegion( layer, layer->driver_data, layer->layer_data,\n                                                       region->region_data, surface, flags, left_update, &left,\n                                                       right_update, &right );\n\n                         /* Unlock region buffer since the lock is no longer needed. */\n                         region_buffer_unlock( region, &left, &right );\n                    }\n                    else {\n                         D_DEBUG_AT( Core_LayerRegion, \"  -> flipping region not using driver...\\n\" );\n\n                         /* Just do the hardware independent work. */\n                         dfb_surface_flip_buffers( surface, false );\n                    }\n                    break;\n               }\n               /* fall through */\n\n          case DLBM_BACKSYSTEM:\n               D_DEBUG_AT( Core_LayerRegion, \"  -> going to copy portion...\\n\" );\n\n               if ((flags & DSFLIP_WAITFORSYNC) == DSFLIP_WAITFORSYNC) {\n                    D_DEBUG_AT( Core_LayerRegion, \"  -> waiting for VSync...\\n\" );\n\n                    dfb_layer_wait_vsync( layer );\n               }\n\n               D_DEBUG_AT( Core_LayerRegion, \"  -> copying content from back to front buffer...\\n\" );\n\n               if (left_update)\n                    eyes |= DSSE_LEFT;\n\n               if (right_update)\n                    eyes |= DSSE_RIGHT;\n\n               /* Copy updated contents from back to front buffer. */\n               dfb_back_to_front_copy_stereo( surface, eyes, left_update, right_update, surface->rotation );\n\n               if ((flags & DSFLIP_WAITFORSYNC) == DSFLIP_WAIT) {\n                    D_DEBUG_AT( Core_LayerRegion, \"  -> waiting for VSync...\\n\" );\n\n                    dfb_layer_wait_vsync( layer );\n               }\n               /* fall through */\n\n          case DLBM_FRONTONLY:\nupdate_only:\n               /* Tell the driver about the update if the region is realized. */\n               if (funcs->UpdateRegion && D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) {\n                    CoreSurfaceBufferLock left, right;\n\n                    if (surface) {\n                         /* Lock region buffer before it is used. */\n                         region_buffer_lock( region, surface, DSBR_FRONT, &left, &right );\n\n                         D_ASSERT( left.allocation != NULL );\n                         D_ASSERT( right.allocation != NULL );\n                    }\n\n                    D_DEBUG_AT( Core_LayerRegion, \"  -> notifying driver about updated content...\\n\" );\n\n                    if (!left_update && !right_update) {\n\n                         unrotated = DFB_REGION_INIT_FROM_RECTANGLE_VALS( 0, 0,\n                                                                          region->config.width, region->config.height );\n                         left_update = &unrotated;\n\n                         unrotated = DFB_REGION_INIT_FROM_RECTANGLE_VALS( 0, 0,\n                                                                          region->config.width, region->config.height );\n                         right_update = &unrotated;\n                    }\n                    else if (!left_update) {\n                         left_update  = right_update;\n                    }\n                    else if (!right_update) {\n                         right_update = left_update;\n                    }\n\n                    dfb_region_from_rotated( &left_rotated, left_update, &surface->config.size, surface->rotation );\n\n                    if (left_update != right_update)\n                         dfb_region_from_rotated( &right_rotated, right_update, &surface->config.size,\n                                                  surface->rotation );\n                    else\n                         right_rotated = left_rotated;\n\n                    ret = funcs->UpdateRegion( layer, layer->driver_data, layer->layer_data,\n                                               region->region_data, surface, &left_rotated, &left,\n                                               &right_rotated, &right );\n\n                    /* Unlock region buffer since the lock is no longer needed. */\n                    if (surface)\n                         region_buffer_unlock( region, &left, &right );\n               }\n               break;\n\n          default:\n               D_BUG( \"unknown buffer mode\" );\n               ret = DFB_BUG;\n     }\n\n     D_DEBUG_AT( Core_LayerRegion, \"  -> done\\n\" );\n\nout:\n     dfb_surface_unlock( surface );\n\n     /* Unlock the region. */\n     dfb_layer_region_unlock( region );\n\n     return ret;\n}\n\nDFBResult\ndfb_layer_region_flip_update2( CoreLayerRegion     *region,\n                               const DFBRegion     *left_update,\n                               const DFBRegion     *right_update,\n                               DFBSurfaceFlipFlags  flags,\n                               unsigned int         flip_count,\n                               long long            pts )\n{\n     if (region->config.options & DLOP_STEREO)\n          return dfb_layer_region_flip_update_stereo( region, left_update, right_update, flags );\n\n     return dfb_layer_region_flip_update( region, left_update, flags );\n}\n\nDFBResult\ndfb_layer_region_set_configuration( CoreLayerRegion             *region,\n                                    const CoreLayerRegionConfig *config,\n                                    CoreLayerRegionConfigFlags   flags )\n{\n     DFBResult                   ret;\n     CoreLayer                  *layer;\n     const DisplayLayerFuncs    *funcs;\n     CoreLayerRegionConfig       new_config;\n     CoreLayerRegionConfigFlags  failed;\n\n     D_DEBUG_AT( Core_LayerRegion, \"%s( %p, %p, 0x%08x )\\n\", __FUNCTION__, region, config, flags );\n\n     D_ASSERT( region != NULL );\n     D_ASSERT( config != NULL );\n     D_ASSERT( config->buffermode != DLBM_WINDOWS );\n     D_ASSERT( (flags == CLRCF_ALL) || (region->state & CLRSF_CONFIGURED) );\n\n     D_ASSUME( flags != CLRCF_NONE );\n     D_ASSUME( !(flags & ~CLRCF_ALL) );\n\n     layer = dfb_layer_at( region->layer_id );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->funcs != NULL );\n     D_ASSERT( layer->funcs->TestRegion != NULL );\n\n     funcs = layer->funcs;\n\n     /* Lock the region. */\n     if (dfb_layer_region_lock( region ))\n          return DFB_FUSION;\n\n     /* Full configuration supplied. */\n     if (flags == CLRCF_ALL) {\n          new_config = *config;\n     }\n     else {\n          /* Use the current configuration. */\n          new_config = region->config;\n\n          /* Update each modified entry. */\n          if (flags & CLRCF_WIDTH)\n               new_config.width = config->width;\n\n          if (flags & CLRCF_HEIGHT)\n               new_config.height = config->height;\n\n          if (flags & CLRCF_FORMAT)\n               new_config.format = config->format;\n\n          if (flags & CLRCF_COLORSPACE)\n               new_config.colorspace = config->colorspace;\n\n          if (flags & CLRCF_SURFACE_CAPS)\n               new_config.surface_caps = config->surface_caps;\n\n          if (flags & CLRCF_BUFFERMODE)\n               new_config.buffermode = config->buffermode;\n\n          if (flags & CLRCF_OPTIONS)\n               new_config.options = config->options;\n\n          if (flags & CLRCF_SOURCE_ID)\n               new_config.source_id = config->source_id;\n\n          if (flags & CLRCF_SOURCE)\n               new_config.source = config->source;\n\n          if (flags & CLRCF_DEST)\n               new_config.dest = config->dest;\n\n          if (flags & CLRCF_OPACITY)\n               new_config.opacity = config->opacity;\n\n          if (flags & CLRCF_ALPHA_RAMP) {\n               new_config.alpha_ramp[0] = config->alpha_ramp[0];\n               new_config.alpha_ramp[1] = config->alpha_ramp[1];\n               new_config.alpha_ramp[2] = config->alpha_ramp[2];\n               new_config.alpha_ramp[3] = config->alpha_ramp[3];\n          }\n\n          if (flags & CLRCF_SRCKEY)\n               new_config.src_key = config->src_key;\n\n          if (flags & CLRCF_DSTKEY)\n               new_config.dst_key = config->dst_key;\n\n          if (flags & CLRCF_PARITY)\n               new_config.parity = config->parity;\n\n          if (flags & CLRCF_CLIPS) {\n               new_config.clips     = config->clips;\n               new_config.num_clips = config->num_clips;\n               new_config.positive  = config->positive;\n          }\n     }\n\n     DFB_CORE_LAYER_REGION_CONFIG_DEBUG_AT( Core_LayerRegion, &new_config );\n\n     /* Check if the new configuration is supported. */\n     ret = funcs->TestRegion( layer, layer->driver_data, layer->layer_data, &new_config, &failed );\n     if (ret) {\n          D_DEBUG_AT( Core_LayerRegion, \"  -> FAILED 0x%08x\\n\", failed );\n          dfb_layer_region_unlock( region );\n          return ret;\n     }\n\n     /* Check if the region should be frozen, thus requiring to apply changes explicitly. */\n     if (flags & CLRCF_FREEZE) {\n          D_DEBUG_AT( Core_LayerRegion, \"  -> FREEZE...\\n\" );\n          region->state |= CLRSF_FROZEN;\n     }\n\n     /* Propagate new configuration to the driver if the region is realized. */\n     if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED ) && !D_FLAGS_IS_SET( region->state, CLRSF_FROZEN )) {\n          ret = dfb_layer_region_set( region, &new_config, flags, region->surface );\n          if (ret) {\n               dfb_layer_region_unlock( region );\n               return ret;\n          }\n     }\n\n     /* Update the region's current configuration. */\n     region->config = new_config;\n\n     /* Update the region's state. */\n     D_FLAGS_SET( region->state, CLRSF_CONFIGURED );\n\n     /* Unlock the region. */\n     dfb_layer_region_unlock( region );\n\n     D_DEBUG_AT( Core_LayerRegion, \"  -> done\\n\" );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_region_get_configuration( CoreLayerRegion       *region,\n                                    CoreLayerRegionConfig *ret_config )\n{\n     D_DEBUG_AT( Core_LayerRegion, \"%s( %p )\\n\", __FUNCTION__, region );\n\n     D_ASSERT( region != NULL );\n     D_ASSERT( ret_config != NULL );\n     D_ASSERT( D_FLAGS_IS_SET( region->state, CLRSF_CONFIGURED ) );\n\n     /* Lock the region. */\n     if (dfb_layer_region_lock( region ))\n          return DFB_FUSION;\n\n     /* Return the current configuration. */\n     *ret_config = region->config;\n\n     /* Unlock the region. */\n     dfb_layer_region_unlock( region );\n\n     return DFB_OK;\n}\n\nReactionResult\n_dfb_layer_region_surface_listener( const void *msg_data,\n                                    void       *ctx )\n{\n     CoreSurfaceNotificationFlags   flags;\n     CoreSurface                   *surface;\n     CoreLayer                     *layer;\n     CoreLayerShared               *shared;\n     const DisplayLayerFuncs       *funcs;\n     const CoreSurfaceNotification *notification = msg_data;\n     CoreLayerRegion               *region       = ctx;\n\n     D_ASSERT( notification != NULL );\n     D_ASSERT( notification->surface != NULL );\n     D_ASSERT( region != NULL );\n\n     D_DEBUG_AT( Core_LayerRegion, \"%s( %p, %p ) <- 0x%08x\\n\", __FUNCTION__,\n                 notification, region, notification->flags );\n\n     D_ASSUME( notification->surface == region->surface );\n\n     if (notification->surface != region->surface)\n          return RS_OK;\n\n     layer = dfb_layer_at( region->layer_id );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n     D_ASSERT( layer->funcs != NULL );\n     D_ASSERT( layer->funcs->SetRegion != NULL );\n\n     funcs   = layer->funcs;\n     shared  = layer->shared;\n\n     flags   = notification->flags;\n     surface = notification->surface;\n\n     if (flags & CSNF_BUFFER_ALLOCATION_DESTROY)\n          return RS_OK;\n\n     if (flags & CSNF_DESTROY) {\n          D_WARN( \"layer region surface destroyed\" );\n          region->surface = NULL;\n          return RS_REMOVE;\n     }\n\n     if (flags & CSNF_DISPLAY)\n          return RS_OK;\n\n     if (dfb_layer_region_lock( region ))\n          return RS_OK;\n\n     if (D_FLAGS_ARE_SET( region->state, CLRSF_REALIZED | CLRSF_CONFIGURED ) &&\n         !D_FLAGS_IS_SET( region->state, CLRSF_FROZEN )) {\n          if (D_FLAGS_IS_SET( flags, CSNF_PALETTE_CHANGE | CSNF_PALETTE_UPDATE )) {\n               if (surface->palette) {\n                    CoreSurfaceBufferLock left, right;\n\n                    dfb_surface_lock( surface );\n\n                    /* Lock region buffer before it is used. */\n                    region_buffer_lock( region, surface, DSBR_BACK, &left, &right );\n\n                    D_ASSERT( left.buffer != NULL );\n\n                    funcs->SetRegion( layer, layer->driver_data, layer->layer_data,\n                                      region->region_data, &region->config, CLRCF_PALETTE, surface, surface->palette,\n                                      &left, &right );\n\n                    /* Unlock region buffer since the lock is no longer needed. */\n                    region_buffer_unlock( region, &left, &right );\n\n                    dfb_surface_unlock( surface );\n               }\n          }\n\n          if ((flags & CSNF_FIELD) && funcs->SetInputField)\n               funcs->SetInputField( layer, layer->driver_data, layer->layer_data,\n                                     region->region_data, surface->field );\n\n          if ((flags & CSNF_ALPHA_RAMP) && (shared->description.caps & DLCAPS_ALPHA_RAMP)) {\n               CoreSurfaceBufferLock left, right;\n\n               region->config.alpha_ramp[0] = surface->alpha_ramp[0];\n               region->config.alpha_ramp[1] = surface->alpha_ramp[1];\n               region->config.alpha_ramp[2] = surface->alpha_ramp[2];\n               region->config.alpha_ramp[3] = surface->alpha_ramp[3];\n\n               dfb_surface_lock( surface );\n\n               /* Lock region buffer before it is used. */\n               region_buffer_lock( region, surface, DSBR_BACK, &left, &right );\n\n               D_ASSERT( left.buffer != NULL );\n\n               funcs->SetRegion( layer, layer->driver_data, layer->layer_data,\n                                 region->region_data, &region->config, CLRCF_ALPHA_RAMP, surface, surface->palette,\n                                 &left, &right );\n\n               /* Unlock region buffer since the lock is no longer needed. */\n               region_buffer_unlock( region, &left, &right );\n\n               dfb_surface_unlock( surface );\n          }\n     }\n\n     dfb_layer_region_unlock( region );\n\n     return RS_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic DFBResult\nregion_buffer_unlock( CoreLayerRegion       *region,\n                      CoreSurfaceBufferLock *left_buffer_lock,\n                      CoreSurfaceBufferLock *right_buffer_lock )\n{\n     DFBResult ret = DFB_OK;\n\n     D_ASSERT( region != NULL );\n     D_ASSERT( left_buffer_lock != NULL );\n\n     D_DEBUG_AT( Core_LayerRegionLock, \"%s( %p )\\n\", __FUNCTION__, region );\n\n     if (left_buffer_lock->buffer)\n          D_DEBUG_AT( Core_LayerRegionLock, \"  -> lock buffer left %p\\n\", left_buffer_lock->buffer );\n     if (right_buffer_lock && right_buffer_lock->buffer)\n          D_DEBUG_AT( Core_LayerRegionLock, \"  -> lock buffer right %p\\n\", right_buffer_lock->buffer );\n\n     /* Unlock any previously locked buffer. */\n     if (left_buffer_lock->buffer) {\n          D_MAGIC_ASSERT( left_buffer_lock->buffer, CoreSurfaceBuffer );\n\n          ret = dfb_surface_unlock_buffer( left_buffer_lock->buffer->surface, left_buffer_lock );\n     }\n\n     if (right_buffer_lock && right_buffer_lock->buffer) {\n          D_MAGIC_ASSERT( right_buffer_lock->buffer, CoreSurfaceBuffer );\n\n          ret = dfb_surface_unlock_buffer( right_buffer_lock->buffer->surface, right_buffer_lock );\n     }\n\n     return ret;\n}\n\nstatic DFBResult\nregion_buffer_lock( CoreLayerRegion       *region,\n                    CoreSurface           *surface,\n                    DFBSurfaceBufferRole   role,\n                    CoreSurfaceBufferLock *left_buffer_lock,\n                    CoreSurfaceBufferLock *right_buffer_lock )\n{\n     DFBResult          ret;\n     CoreSurfaceBuffer *buffer;\n     bool               stereo;\n\n     D_ASSERT( region != NULL );\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     D_ASSERT( left_buffer_lock != NULL );\n\n     FUSION_SKIRMISH_ASSERT( &surface->lock );\n\n     D_DEBUG_AT( Core_LayerRegionLock, \"%s( %p, %p, role %u )\\n\", __FUNCTION__, region, surface, role );\n\n     Core_PushIdentity( FUSION_ID_MASTER );\n\n     /* Save current buffer focus. */\n     buffer = dfb_surface_get_buffer3( surface, role, DSSE_LEFT, region->surface_flip_count );\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n\n     D_DEBUG_AT( Core_LayerRegionLock, \"  -> buffer  %p\\n\", buffer );\n\n     /* Lock the surface buffer. */\n     ret = dfb_surface_buffer_lock( buffer, region->surface_accessor, CSAF_READ, left_buffer_lock );\n     if (ret) {\n          D_DERROR( ret, \"Core/LayerRegion: Could not lock region surface!\\n\" );\n          Core_PopIdentity();\n          return ret;\n     }\n\n     D_ASSERT( left_buffer_lock->allocation != NULL );\n\n     stereo = surface->config.caps & DSCAPS_STEREO;\n\n     if (stereo) {\n          D_ASSERT( right_buffer_lock != NULL );\n\n          buffer = dfb_surface_get_buffer3( surface, role, DSSE_RIGHT, region->surface_flip_count );\n\n          D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n\n          D_DEBUG_AT( Core_LayerRegionLock, \"  -> buffer  %p\\n\", buffer );\n\n          /* Lock the surface buffer. */\n          ret = dfb_surface_buffer_lock( buffer, region->surface_accessor, CSAF_READ, right_buffer_lock );\n          if (ret) {\n               D_DERROR( ret, \"Core/LayerRegion: Could not lock region surface!\\n\" );\n               Core_PopIdentity();\n               return ret;\n          }\n\n          D_ASSERT( right_buffer_lock->allocation != NULL );\n     }\n     else if (right_buffer_lock) {\n          /* Clear for region_buffer_unlock(). */\n          right_buffer_lock->buffer = NULL;\n     }\n\n     Core_PopIdentity();\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_region_set( CoreLayerRegion            *region,\n                      CoreLayerRegionConfig      *config,\n                      CoreLayerRegionConfigFlags  flags,\n                      CoreSurface                *surface )\n{\n     DFBResult                ret;\n     CoreLayer               *layer;\n     CoreLayerShared         *shared;\n     const DisplayLayerFuncs *funcs;\n     CoreSurfaceBufferLock    left, right;\n     bool                     locked = false;\n\n     D_UNUSED_P( shared );\n\n     D_DEBUG_AT( Core_LayerRegion, \"%s( %p, %p, 0x%08x, %p )\\n\", __FUNCTION__, region, config, flags, surface );\n\n     D_ASSERT( region != NULL );\n     D_ASSERT( config != NULL );\n     D_ASSERT( config->buffermode != DLBM_WINDOWS );\n     D_ASSERT( D_FLAGS_IS_SET( region->state, CLRSF_REALIZED ) );\n\n     DFB_CORE_LAYER_REGION_CONFIG_DEBUG_AT( Core_LayerRegion, config );\n\n     D_DEBUG_AT( Core_LayerRegion, \"  -> state 0x%08x\\n\", region->state );\n\n     layer = dfb_layer_at( region->layer_id );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n     D_ASSERT( layer->funcs != NULL );\n     D_ASSERT( layer->funcs->SetRegion != NULL );\n\n     if (region->state & CLRSF_FROZEN) {\n          D_DEBUG_AT( Core_LayerRegion, \"  -> FROZEN!\\n\" );\n          return DFB_OK;\n     }\n\n     shared = layer->shared;\n     funcs  = layer->funcs;\n\n     if (surface) {\n          if (flags & (CLRCF_SURFACE | CLRCF_WIDTH  | CLRCF_HEIGHT | CLRCF_FORMAT | CLRCF_SRCKEY | CLRCF_DSTKEY |\n                       CLRCF_OPACITY | CLRCF_SOURCE | CLRCF_DEST)) {\n               dfb_surface_lock( surface );\n\n               ret = region_buffer_lock( region, surface, DSBR_FRONT, &left, &right );\n\n               dfb_surface_unlock( surface );\n\n               if (ret)\n                    return ret;\n\n               locked = true;\n          }\n     }\n\n     D_DEBUG_AT( Core_LayerRegion, \"  -> setting region of '%s'\\n\", shared->description.name );\n\n     /* Setup hardware. */\n     ret =  funcs->SetRegion( layer, layer->driver_data, layer->layer_data,\n                              region->region_data, config, flags, surface, surface ? surface->palette : NULL,\n                              &left, &right );\n     if (ret)\n          D_DERROR( ret, \"Core/LayerRegion: Could not set region!\\n\" );\n\n     /* Unlock the region buffer since the lock is no longer necessary. */\n     if (locked)\n          region_buffer_unlock( region, &left, &right );\n\n     return ret;\n}\n\nDFBResult\ndfb_layer_region_realize( CoreLayerRegion *region,\n                          bool             set )\n{\n     DFBResult                ret;\n     CoreLayer               *layer;\n     CoreLayerShared         *shared;\n     const DisplayLayerFuncs *funcs;\n\n     D_DEBUG_AT( Core_LayerRegion, \"%s( %p )\\n\", __FUNCTION__, region );\n\n     D_ASSERT( region != NULL );\n\n     DFB_CORE_LAYER_REGION_CONFIG_DEBUG_AT( Core_LayerRegion, &region->config );\n\n     D_DEBUG_AT( Core_LayerRegion, \"  -> state 0x%08x\\n\", region->state );\n\n     if (region->state & CLRSF_FROZEN) {\n          D_DEBUG_AT( Core_LayerRegion, \"  -> FROZEN!\\n\" );\n          return DFB_OK;\n     }\n\n     D_ASSERT( D_FLAGS_IS_SET( region->state, CLRSF_CONFIGURED ) );\n     D_ASSERT( !D_FLAGS_IS_SET( region->state, CLRSF_REALIZED ) );\n\n     layer = dfb_layer_at( region->layer_id );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n     D_ASSERT( layer->funcs != NULL );\n\n     shared = layer->shared;\n     funcs  = layer->funcs;\n\n     D_ASSERT( !fusion_vector_contains( &shared->added_regions, region ) );\n\n     /* Allocate the driver's region data. */\n     if (funcs->RegionDataSize) {\n          int size = funcs->RegionDataSize();\n\n          if (size > 0) {\n               region->region_data = SHCALLOC( shared->shmpool, 1, size );\n               if (!region->region_data)\n                    return D_OOSHM();\n          }\n     }\n\n     D_DEBUG_AT( Core_LayerRegion, \"  -> adding region to '%s'\\n\", shared->description.name );\n\n     /* Add the region to the driver. */\n     if (funcs->AddRegion) {\n          ret = funcs->AddRegion( layer, layer->driver_data, layer->layer_data, region->region_data, &region->config );\n          if (ret) {\n               D_DERROR( ret, \"Core/LayerRegion: Could not add region!\\n\" );\n\n               if (region->region_data) {\n                    SHFREE( shared->shmpool, region->region_data );\n                    region->region_data = NULL;\n               }\n\n               return ret;\n          }\n     }\n\n     /* Add the region to the 'added' list. */\n     fusion_vector_add( &shared->added_regions, region );\n\n     /* Update the region's state. */\n     D_FLAGS_SET( region->state, CLRSF_REALIZED );\n\n     /* Initially setup hardware. */\n     if (set) {\n          ret = dfb_layer_region_set( region, &region->config, CLRCF_ALL, region->surface );\n          if (ret) {\n               dfb_layer_region_unrealize( region );\n               return ret;\n          }\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_layer_region_unrealize( CoreLayerRegion *region )\n{\n     DFBResult                ret;\n     int                      index;\n     CoreLayer               *layer;\n     CoreLayerShared         *shared;\n     const DisplayLayerFuncs *funcs;\n\n     D_DEBUG_AT( Core_LayerRegion, \"%s( %p )\\n\", __FUNCTION__, region );\n\n     D_ASSERT( region != NULL );\n     D_ASSERT( D_FLAGS_IS_SET( region->state, CLRSF_REALIZED ) );\n\n     DFB_CORE_LAYER_REGION_CONFIG_DEBUG_AT( Core_LayerRegion, &region->config );\n\n     D_DEBUG_AT( Core_LayerRegion, \"  -> state 0x%08x\\n\", region->state );\n\n     layer = dfb_layer_at( region->layer_id );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n     D_ASSERT( layer->funcs != NULL );\n\n     shared = layer->shared;\n     funcs  = layer->funcs;\n\n     D_ASSERT( fusion_vector_contains( &shared->added_regions, region ) );\n\n     index = fusion_vector_index_of( &shared->added_regions, region );\n\n     D_DEBUG_AT( Core_LayerRegion, \"  -> removing region from '%s'\\n\", shared->description.name );\n\n     /* Remove the region from hardware and driver. */\n     if (funcs->RemoveRegion) {\n          ret = funcs->RemoveRegion( layer, layer->driver_data, layer->layer_data, region->region_data );\n          if (ret) {\n               D_DERROR( ret, \"Core/LayerRegion: Could not remove region!\\n\" );\n               return ret;\n          }\n     }\n\n     /* Remove the region from the 'added' list. */\n     fusion_vector_remove( &shared->added_regions, index );\n\n     /* Deallocate the driver's region data. */\n     if (region->region_data) {\n          SHFREE( shared->shmpool, region->region_data );\n          region->region_data = NULL;\n     }\n\n     /* Update the region's state. */\n     D_FLAGS_CLEAR( region->state, CLRSF_REALIZED );\n     D_FLAGS_SET( region->state, CLRSF_FROZEN );\n\n     /* Unlock the region buffer if it is locked. */\n     if (region->surface && !region->config.keep_buffers)\n          dfb_surface_deallocate_buffers( region->surface );\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/core/layer_region.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__LAYER_REGION_H__\n#define __CORE__LAYER_REGION_H__\n\n#include <core/coretypes.h>\n#include <fusion/object.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CLRSF_NONE       = 0x00000000,\n\n     CLRSF_CONFIGURED = 0x00000001,\n     CLRSF_ENABLED    = 0x00000002,\n     CLRSF_ACTIVE     = 0x00000004,\n     CLRSF_REALIZED   = 0x00000008,\n     CLRSF_FROZEN     = 0x00000010,\n\n     CLRSF_ALL        = 0x0000001F\n} CoreLayerRegionStateFlags;\n\ntypedef struct {\n     int                        width;         /* width of the source in pixels */\n     int                        height;        /* height of the source in pixels */\n     DFBSurfacePixelFormat      format;        /* pixel format of the source surface */\n     DFBSurfaceColorSpace       colorspace;    /* color space of the source surface */\n     DFBSurfaceCapabilities     surface_caps;  /* capabilities of the source surface */\n     DFBDisplayLayerBufferMode  buffermode;    /* surface buffer configuration */\n\n     DFBDisplayLayerOptions     options;       /* various configuration options */\n\n     DFBDisplayLayerSourceID    source_id;     /* selected source */\n\n     DFBRectangle               source;        /* viewport within source (input) */\n     DFBRectangle               dest;          /* viewport on screen (output) */\n\n     u8                         opacity;       /* global region alpha */\n\n     DFBColorKey                src_key;       /* source color key */\n     DFBColorKey                dst_key;       /* destination color key */\n\n     int                        parity;        /* field parity (for interlaced) */\n\n     u8                         alpha_ramp[4]; /* alpha values for 1 or 2 bit lookup */\n\n     DFBRegion                 *clips;         /* clip regions */\n     int                        num_clips;     /* number of clip regions */\n     DFBBoolean                 positive;      /* show or cut out regions */\n\n     bool                       keep_buffers;  /* keep buffers */\n} CoreLayerRegionConfig;\n\n#if D_DEBUG_ENABLED\n#define DFB_CORE_LAYER_REGION_CONFIG_DEBUG_AT(domain,config)                                                           \\\n     do {                                                                                                              \\\n          D_DEBUG_AT( domain, \"  -> size       %dx%d\\n\",                   (config)->width, (config)->height );        \\\n          D_DEBUG_AT( domain, \"  -> format     %s\\n\",                      dfb_pixelformat_name( (config)->format ) ); \\\n          D_DEBUG_AT( domain, \"  -> color spc  %u\\n\",                      (config)->colorspace );                     \\\n          D_DEBUG_AT( domain, \"  -> surf caps  0x%08x\\n\",                  (config)->surface_caps );                   \\\n          D_DEBUG_AT( domain, \"  -> buffermode %u\\n\",                      (config)->buffermode );                     \\\n          D_DEBUG_AT( domain, \"  -> options    0x%08x\\n\",                  (config)->options );                        \\\n          D_DEBUG_AT( domain, \"  -> source     %4d,%4d-%4dx%4d\\n\",         DFB_RECTANGLE_VALS( &(config)->source ) );  \\\n          D_DEBUG_AT( domain, \"  -> dest       %4d,%4d-%4dx%4d\\n\",         DFB_RECTANGLE_VALS( &(config)->dest ) );    \\\n          D_DEBUG_AT( domain, \"  -> opacity    %d\\n\",                      (config)->opacity );                        \\\n          D_DEBUG_AT( domain, \"  -> src_key    %02x%02x%02x (index %d)\\n\", DFB_COLORKEY_VALS( &(config)->src_key ) );  \\\n          D_DEBUG_AT( domain, \"  -> dst_key    %02x%02x%02x (index %d)\\n\", DFB_COLORKEY_VALS( &(config)->dst_key ) );  \\\n     } while (0)\n#else\n#define DFB_CORE_LAYER_REGION_CONFIG_DEBUG_AT(domain,config)                                                           \\\n     do {                                                                                                              \\\n     } while (0)\n#endif\n\nstruct __DFB_CoreLayerRegion {\n     FusionObject               object;\n\n     FusionObjectID             context_id;\n\n     FusionSkirmish             lock;\n\n     CoreLayerRegionStateFlags  state;\n\n     CoreLayerRegionConfig      config;\n\n     CoreSurface               *surface;\n     GlobalReaction             surface_reaction;\n\n     CoreSurfaceClient         *surface_client;\n     Reaction                   surface_event_reaction;\n\n     void                      *region_data;\n\n     CoreSurfaceAccessorID      surface_accessor;\n\n     FusionCall                 call;\n\n     DFBDisplayLayerID          layer_id;\n\n     u32                        surface_flip_count;\n};\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CLRCF_NONE         = 0x00000000,\n\n     CLRCF_WIDTH        = 0x00000001,\n     CLRCF_HEIGHT       = 0x00000002,\n     CLRCF_FORMAT       = 0x00000004,\n     CLRCF_SURFACE_CAPS = 0x00000008,\n     CLRCF_BUFFERMODE   = 0x00000010,\n     CLRCF_OPTIONS      = 0x00000020,\n     CLRCF_SOURCE_ID    = 0x00000040,\n     CLRCF_COLORSPACE   = 0x00000080,\n     CLRCF_SOURCE       = 0x00000100,\n     CLRCF_DEST         = 0x00000200,\n     CLRCF_CLIPS        = 0x00000400,\n\n     CLRCF_OPACITY      = 0x00001000,\n     CLRCF_ALPHA_RAMP   = 0x00002000,\n\n     CLRCF_SRCKEY       = 0x00010000,\n     CLRCF_DSTKEY       = 0x00020000,\n\n     CLRCF_PARITY       = 0x00100000,\n\n     CLRCF_SURFACE      = 0x10000000,\n     CLRCF_PALETTE      = 0x20000000,\n     CLRCF_FREEZE       = 0x40000000,\n\n     CLRCF_ALL          = 0x701337FF\n} CoreLayerRegionConfigFlags;\n\ntypedef enum {\n     CLRNF_NONE = 0x00000000\n} CoreLayerRegionNotificationFlags;\n\ntypedef struct {\n     CoreLayerRegionNotificationFlags  flags;\n     CoreLayerRegion                  *region;\n} CoreLayerRegionNotification;\n\n/**********************************************************************************************************************/\n\n/*\n * Creates a pool of layer region objects.\n */\nFusionObjectPool *dfb_layer_region_pool_create       ( const FusionWorld           *world );\n\n/*\n * Generates dfb_layer_region_ref(), dfb_layer_region_attach() etc.\n */\nFUSION_OBJECT_METHODS( CoreLayerRegion, dfb_layer_region )\n\n/**********************************************************************************************************************/\n\nDFBResult         dfb_layer_region_create            ( CoreLayerContext             *context,\n                                                       CoreLayerRegion             **ret_region );\n\nDirectResult      dfb_layer_region_lock              ( CoreLayerRegion              *region );\n\nDirectResult      dfb_layer_region_unlock            ( CoreLayerRegion              *region );\n\nDFBResult         dfb_layer_region_activate          ( CoreLayerRegion              *region );\n\nDFBResult         dfb_layer_region_deactivate        ( CoreLayerRegion              *region );\n\nDFBResult         dfb_layer_region_enable            ( CoreLayerRegion              *region );\n\nDFBResult         dfb_layer_region_disable           ( CoreLayerRegion              *region );\n\nDFBResult         dfb_layer_region_set_surface       ( CoreLayerRegion              *region,\n                                                       CoreSurface                  *surface,\n                                                       bool                          update );\n\nDFBResult         dfb_layer_region_get_surface       ( CoreLayerRegion              *region,\n                                                       CoreSurface                 **ret_surface );\n\nDFBResult         dfb_layer_region_flip_update       ( CoreLayerRegion              *region,\n                                                       const DFBRegion              *update,\n                                                       DFBSurfaceFlipFlags           flags );\n\nDFBResult         dfb_layer_region_flip_update_stereo( CoreLayerRegion              *region,\n                                                       const DFBRegion              *left_update,\n                                                       const DFBRegion              *right_update,\n                                                       DFBSurfaceFlipFlags           flags );\n\nDFBResult         dfb_layer_region_flip_update2      ( CoreLayerRegion              *region,\n                                                       const DFBRegion              *left_update,\n                                                       const DFBRegion              *right_update,\n                                                       DFBSurfaceFlipFlags           flags,\n                                                       unsigned int                  flip_count,\n                                                       long long                     pts );\n\n/*\n * Configuration setting/getting.\n */\n\nDFBResult         dfb_layer_region_set_configuration ( CoreLayerRegion              *region,\n                                                       const CoreLayerRegionConfig  *config,\n                                                       CoreLayerRegionConfigFlags    flags );\n\nDFBResult         dfb_layer_region_get_configuration ( CoreLayerRegion              *region,\n                                                       CoreLayerRegionConfig        *ret_config );\n\n/*\n * Global reaction, listen to the layer's surface.\n */\nReactionResult   _dfb_layer_region_surface_listener  ( const void                   *msg_data,\n                                                       void                         *ctx );\n\n#endif\n"
  },
  {
    "path": "src/core/layers.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreLayer.h>\n#include <core/core.h>\n#include <core/core_parts.h>\n#include <core/layers.h>\n#include <core/layer_control.h>\n#include <direct/memcpy.h>\n#include <fusion/conf.h>\n#include <fusion/shmalloc.h>\n\nD_DEBUG_DOMAIN( Core_Layers, \"Core/Layers\", \"DirectFB Core Display Layers\" );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int              magic;\n\n     int              num;\n     CoreLayerShared *layers[MAX_LAYERS];\n} DFBLayerCoreShared;\n\ntypedef struct {\n     int                 magic;\n\n     CoreDFB            *core;\n\n     DFBLayerCoreShared *shared;\n} DFBLayerCore;\n\nDFB_CORE_PART( layer_core, LayerCore );\n\n/**********************************************************************************************************************/\n\nstatic int        num_layers = 0;\nstatic CoreLayer *layers[MAX_LAYERS];\n\nstatic DFBResult\ndfb_layer_core_initialize( CoreDFB            *core,\n                           DFBLayerCore       *data,\n                           DFBLayerCoreShared *shared )\n{\n     DFBResult            ret;\n     FusionSHMPoolShared *pool;\n     int                  i;\n\n     D_DEBUG_AT( Core_Layers, \"%s( %p, %p, %p )\\n\", __FUNCTION__, core, data, shared );\n\n     D_ASSERT( data != NULL );\n     D_ASSERT( shared != NULL );\n\n     data->core   = core;\n     data->shared = shared;\n\n     pool = dfb_core_shmpool( core );\n\n     /* Initialize all registered layers. */\n     for (i = 0; i < num_layers; i++) {\n          CoreLayer               *layer = layers[i];\n          CoreLayerShared         *lshared;\n          const DisplayLayerFuncs *funcs = layer->funcs;\n          char                     buf[24];\n\n          /* Allocate shared data. */\n          lshared = SHCALLOC( pool, 1, sizeof(CoreLayerShared) );\n\n          /* Assign ID (zero based index). */\n          lshared->layer_id = i;\n          lshared->shmpool  = pool;\n\n          snprintf( buf, sizeof(buf), \"Display Layer %d\", i );\n\n          /* Initialize the lock. */\n          ret = fusion_skirmish_init2( &lshared->lock, buf, dfb_core_world( core ), fusion_config->secure_fusion );\n          if (ret) {\n               SHFREE( pool, lshared );\n               return DFB_FUSION;\n          }\n\n          /* Allocate driver's layer data. */\n          if (funcs->LayerDataSize) {\n               int size = funcs->LayerDataSize();\n\n               if (size > 0) {\n                    lshared->layer_data = SHCALLOC( pool, 1, size );\n                    if (!lshared->layer_data) {\n                         fusion_skirmish_destroy( &lshared->lock );\n                         SHFREE( pool, lshared );\n                         return D_OOSHM();\n                    }\n               }\n          }\n\n          /* Initialize the layer, get the layer description, the default configuration and default color adjustment. */\n          ret = funcs->InitLayer( layer, layer->driver_data, lshared->layer_data, &lshared->description,\n                                  &lshared->default_config, &lshared->default_adjustment );\n          if (ret) {\n               D_DERROR( ret, \"Core/Layers: Failed to initialize layer %u!\\n\", lshared->layer_id );\n\n               fusion_skirmish_destroy( &lshared->lock );\n\n               if (lshared->layer_data)\n                    SHFREE( pool, lshared->layer_data );\n\n               SHFREE( pool, lshared );\n\n               return ret;\n          }\n\n          if (lshared->description.caps & DLCAPS_SOURCES) {\n               int n;\n\n               lshared->sources = SHCALLOC( pool, lshared->description.sources, sizeof(CoreLayerSource) );\n\n               for (n = 0; n < lshared->description.sources; n++) {\n                    CoreLayerSource *source = &lshared->sources[n];\n\n                    source->index = n;\n\n                    funcs->InitSource( layer, layer->driver_data, lshared->layer_data, n, &source->description );\n               }\n          }\n\n          if (D_FLAGS_IS_SET( lshared->description.caps, DLCAPS_SCREEN_LOCATION ))\n               D_FLAGS_SET( lshared->description.caps, DLCAPS_SCREEN_POSITION | DLCAPS_SCREEN_SIZE );\n\n          if (D_FLAGS_ARE_SET( lshared->description.caps, DLCAPS_SCREEN_POSITION | DLCAPS_SCREEN_SIZE ))\n               D_FLAGS_SET( lshared->description.caps, DLCAPS_SCREEN_LOCATION );\n\n          /* Initialize the vector for the contexts. */\n          fusion_vector_init( &lshared->contexts.stack, 4, pool );\n\n          /* Initialize the vector for realized (added) regions. */\n          fusion_vector_init( &lshared->added_regions, 4, pool );\n\n          /* No active context by default. */\n          lshared->contexts.active = -1;\n\n          /* Store layer data. */\n          layer->layer_data = lshared->layer_data;\n\n          /* Store pointer to shared data and core. */\n          layer->shared = lshared;\n          layer->core   = core;\n\n          CoreLayer_Init_Dispatch( core, layer, &lshared->call );\n\n          fusion_call_add_permissions( &lshared->call, 0, FUSION_CALL_PERMIT_EXECUTE );\n\n          /* Add the layer to the shared list. */\n          shared->layers[shared->num++] = lshared;\n     }\n\n     D_MAGIC_SET( data, DFBLayerCore );\n     D_MAGIC_SET( shared, DFBLayerCoreShared );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_layer_core_join( CoreDFB            *core,\n                     DFBLayerCore       *data,\n                     DFBLayerCoreShared *shared )\n{\n     int i;\n\n     D_DEBUG_AT( Core_Layers, \"%s( %p, %p, %p )\\n\", __FUNCTION__, core, data, shared );\n\n     D_ASSERT( data != NULL );\n     D_MAGIC_ASSERT( shared, DFBLayerCoreShared );\n\n     data->core   = core;\n     data->shared = shared;\n\n     if (num_layers != shared->num) {\n          D_ERROR( \"Core/Layers: Number of layers does not match!\\n\" );\n          return DFB_BUG;\n     }\n\n     for (i = 0; i < num_layers; i++) {\n          CoreLayer       *layer   = layers[i];\n          CoreLayerShared *lshared = shared->layers[i];\n\n          /* Make a copy for faster access. */\n          layer->layer_data = lshared->layer_data;\n\n          /* Store pointer to shared data and core. */\n          layer->shared = lshared;\n          layer->core   = core;\n     }\n\n     D_MAGIC_SET( data, DFBLayerCore );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_layer_core_shutdown( DFBLayerCore *data,\n                         bool          emergency )\n{\n     DFBResult           ret;\n     DFBLayerCoreShared *shared;\n     int                 i;\n\n     D_UNUSED_P( shared );\n\n     D_DEBUG_AT( Core_Layers, \"%s( %p, %semergency )\\n\", __FUNCTION__, data, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( data, DFBLayerCore );\n     D_MAGIC_ASSERT( data->shared, DFBLayerCoreShared );\n\n     shared = data->shared;\n\n     /* Begin with the most recently added layer. */\n     for (i = num_layers - 1; i >= 0; i--) {\n          CoreLayer               *layer   = layers[i];\n          CoreLayerShared         *lshared = layer->shared;\n          const DisplayLayerFuncs *funcs   = layer->funcs;\n\n          D_ASSUME( emergency || fusion_vector_is_empty( &lshared->added_regions ) );\n\n          /* Remove all regions during emergency shutdown. */\n          if (emergency && funcs->RemoveRegion) {\n               int              n;\n               CoreLayerRegion *region;\n\n               fusion_vector_foreach (region, n, lshared->added_regions) {\n                   D_DEBUG_AT( Core_Layers, \"  -> removing region (%4d,%4d-%4dx%4d) from '%s'\\n\",\n                               DFB_RECTANGLE_VALS( &region->config.dest ), lshared->description.name );\n\n                   ret = funcs->RemoveRegion( layer, layer->driver_data, layer->layer_data, region->region_data );\n                   if (ret)\n                        D_DERROR( ret, \"Core/Layers: Could not remove region!\\n\" );\n               }\n          }\n\n          /* Shut the layer down. */\n          if (funcs->ShutdownLayer) {\n               ret = funcs->ShutdownLayer( layer, layer->driver_data, lshared->layer_data );\n               if (ret)\n                    D_DERROR( ret, \"Core/Layers: Failed to shutdown layer %u!\\n\", lshared->layer_id );\n          }\n\n          CoreLayer_Deinit_Dispatch( &lshared->call );\n\n          /* Deinitialize the lock. */\n          fusion_skirmish_destroy( &lshared->lock );\n\n          /* Deinitialize the state for window stack repaints. */\n          dfb_state_destroy( &layer->state );\n\n          /* Deinitialize the vector for the contexts. */\n          fusion_vector_destroy( &lshared->contexts.stack );\n\n          /* Deinitialize the vector for the realized (added) regions. */\n          fusion_vector_destroy( &lshared->added_regions );\n\n          /* Free the driver's layer data. */\n          if (lshared->layer_data)\n               SHFREE( lshared->shmpool, lshared->layer_data );\n\n          /* Free the shared layer data. */\n          SHFREE( lshared->shmpool, lshared );\n\n          /* Free the local layer data. */\n          D_FREE( layer );\n     }\n\n     num_layers = 0;\n\n     D_MAGIC_CLEAR( data );\n     D_MAGIC_CLEAR( shared );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_layer_core_leave( DFBLayerCore *data,\n                      bool          emergency )\n{\n     int i;\n\n     D_DEBUG_AT( Core_Layers, \"%s( %p, %semergency )\\n\", __FUNCTION__, data, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( data, DFBLayerCore );\n     D_MAGIC_ASSERT( data->shared, DFBLayerCoreShared );\n\n     /* Deinitialize all local stuff. */\n     for (i = 0; i < num_layers; i++) {\n          CoreLayer *layer = layers[i];\n\n          /* Deinitialize the state for window stack repaints. */\n          dfb_state_destroy( &layer->state );\n\n          /* Free local layer data. */\n          D_FREE( layer );\n     }\n\n     num_layers = 0;\n\n     D_MAGIC_CLEAR( data );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_layer_core_suspend( DFBLayerCore *data )\n{\n     int i;\n\n     D_DEBUG_AT( Core_Layers, \"%s( %p )\\n\", __FUNCTION__, data );\n\n     D_MAGIC_ASSERT( data, DFBLayerCore );\n     D_MAGIC_ASSERT( data->shared, DFBLayerCoreShared );\n\n     for (i = num_layers - 1; i >= 0; i--)\n          dfb_layer_suspend( layers[i] );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_layer_core_resume( DFBLayerCore *data )\n{\n     int i;\n\n     D_DEBUG_AT( Core_Layers, \"%s( %p )\\n\", __FUNCTION__, data );\n\n     D_MAGIC_ASSERT( data, DFBLayerCore );\n     D_MAGIC_ASSERT( data->shared, DFBLayerCoreShared );\n\n     for (i = 0; i < num_layers; i++)\n          dfb_layer_resume( layers[i] );\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nCoreLayer *\ndfb_layers_register( CoreScreen              *screen,\n                     void                    *driver_data,\n                     const DisplayLayerFuncs *funcs )\n{\n     CoreLayer *layer;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( funcs != NULL );\n\n     if (num_layers == MAX_LAYERS) {\n          D_ERROR( \"Core/Layers: Maximum number of layers reached!\\n\" );\n          return NULL;\n     }\n\n     /* Allocate local data. */\n     layer = D_CALLOC( 1, sizeof(CoreLayer) );\n\n     /* Assign local pointers. */\n     layer->screen      = screen;\n     layer->driver_data = driver_data;\n     layer->funcs       = funcs;\n\n     /* Initialize the state for window stack repaints. */\n     dfb_state_init( &layer->state, NULL );\n\n     /* Add it to the local list. */\n     layers[num_layers++] = layer;\n\n     return layer;\n}\n\ntypedef void (*AnyFunc)( void );\n\nCoreLayer *\ndfb_layers_hook_primary( void               *driver_data,\n                         DisplayLayerFuncs  *funcs,\n                         DisplayLayerFuncs  *primary_funcs,\n                         void              **primary_driver_data )\n{\n     int        i;\n     int        entries;\n     CoreLayer *primary = layers[0];\n\n     D_ASSERT( primary != NULL );\n     D_ASSERT( funcs != NULL );\n\n     /* Copy content of original function table. */\n     if (primary_funcs)\n          direct_memcpy( primary_funcs, primary->funcs, sizeof(DisplayLayerFuncs) );\n\n     /* Copy pointer to original driver data. */\n     if (primary_driver_data)\n          *primary_driver_data = primary->driver_data;\n\n     /* Replace all entries in the old table that aren't NULL in the new one. */\n     entries = sizeof(DisplayLayerFuncs) / sizeof(void (*)( void ));\n     for (i = 0; i < entries; i++) {\n          AnyFunc *newfuncs = (AnyFunc*) funcs;\n          AnyFunc *oldfuncs = (AnyFunc*) primary->funcs;\n\n          if (newfuncs[i])\n               oldfuncs[i] = newfuncs[i];\n     }\n\n     /* Replace driver data pointer. */\n     primary->driver_data = driver_data;\n\n     return primary;\n}\n\nvoid\ndfb_layer_get_description( const CoreLayer            *layer,\n                           DFBDisplayLayerDescription *ret_desc )\n{\n     CoreLayerShared *shared;\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n     D_ASSERT( ret_desc != NULL );\n\n     shared = layer->shared;\n\n     *ret_desc = shared->description;\n}\n\nDFBSurfacePixelFormat\ndfb_primary_layer_pixelformat()\n{\n     CoreLayerShared *shared;\n     CoreLayer       *layer = dfb_layer_at_translated( DLID_PRIMARY );\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n\n     shared = layer->shared;\n\n     return shared->pixelformat;\n}\n\nvoid\ndfb_layers_enumerate( DisplayLayerCallback  callback,\n                      void                 *ctx )\n{\n     int i;\n\n     D_ASSERT( callback != NULL );\n\n     for (i = 0; i < num_layers; i++) {\n          if (callback( layers[i], ctx ) == DFENUM_CANCEL)\n               break;\n     }\n}\n\nint\ndfb_layers_num()\n{\n     return num_layers;\n}\n\nCoreLayer *\ndfb_layer_at( DFBDisplayLayerID id )\n{\n     D_ASSERT( id >= 0 );\n     D_ASSERT( id < num_layers );\n\n     return layers[id];\n}\n\nCoreLayer *\ndfb_layer_at_translated( DFBDisplayLayerID id )\n{\n     D_ASSERT( id >= 0 );\n     D_ASSERT( id < num_layers );\n     D_ASSERT( dfb_config != NULL );\n\n     if (dfb_config->primary_layer > 0 && dfb_config->primary_layer < num_layers) {\n          if (id == DLID_PRIMARY)\n               return dfb_layer_at( dfb_config->primary_layer );\n\n          if (id == dfb_config->primary_layer)\n               return dfb_layer_at( DLID_PRIMARY );\n     }\n\n     return dfb_layer_at( id );\n}\n\nDFBDisplayLayerID\ndfb_layer_id( const CoreLayer *layer )\n{\n     CoreLayerShared *shared;\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n\n     shared = layer->shared;\n\n     return shared->layer_id;\n}\n\nDFBDisplayLayerID\ndfb_layer_id_translated( const CoreLayer *layer )\n{\n     CoreLayerShared *shared;\n\n     D_ASSERT( layer != NULL );\n     D_ASSERT( layer->shared != NULL );\n     D_ASSERT( dfb_config != NULL );\n\n     shared = layer->shared;\n\n     if (dfb_config->primary_layer > 0 && dfb_config->primary_layer < num_layers) {\n          if (shared->layer_id == DLID_PRIMARY)\n               return dfb_config->primary_layer;\n\n          if (shared->layer_id == dfb_config->primary_layer)\n               return DLID_PRIMARY;\n     }\n\n     return shared->layer_id;\n}\n"
  },
  {
    "path": "src/core/layers.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__LAYERS_H__\n#define __CORE__LAYERS_H__\n\n#include <core/state.h>\n#include <core/layer_region.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     /*\n      * Return size of layer data (shared memory).\n      */\n     int       (*LayerDataSize)        ( void );\n\n     /*\n      * Return size of region data (shared memory).\n      */\n     int       (*RegionDataSize)       ( void );\n\n     /*\n      * Called once by the master to initialize layer data and reset hardware.\n      * Return layer description, default configuration and color adjustment.\n      */\n     DFBResult (*InitLayer)            ( CoreLayer                         *layer,\n                                         void                              *driver_data,\n                                         void                              *layer_data,\n                                         DFBDisplayLayerDescription        *description,\n                                         DFBDisplayLayerConfig             *config,\n                                         DFBColorAdjustment                *adjustment );\n\n     /*\n      * Called once by the master to shutdown the layer.\n      * Use this function to free any resources that were taken during init.\n      */\n     DFBResult (*ShutdownLayer)        ( CoreLayer                         *layer,\n                                         void                              *driver_data,\n                                         void                              *layer_data );\n\n     /*\n      * Called once by the master for each source.\n      * Driver fills description.\n      */\n     DFBResult (*InitSource)           ( CoreLayer                         *layer,\n                                         void                              *driver_data,\n                                         void                              *layer_data,\n                                         int                                source,\n                                         DFBDisplayLayerSourceDescription  *description );\n\n     /*\n      * Return the currently displayed field (interlaced only).\n      */\n     DFBResult (*GetCurrentOutputField)( CoreLayer                         *layer,\n                                         void                              *driver_data,\n                                         void                              *layer_data,\n                                         int                               *field );\n\n     /*\n      * Return the z position of the layer.\n      */\n     DFBResult (*GetLevel)             ( CoreLayer                         *layer,\n                                         void                              *driver_data,\n                                         void                              *layer_data,\n                                         int                               *level );\n\n     /*\n      * Move the layer below or on top of others (z position).\n      */\n     DFBResult (*SetLevel)             ( CoreLayer                         *layer,\n                                         void                              *driver_data,\n                                         void                              *layer_data,\n                                         int                                level );\n\n     /*\n      * Adjust brightness, contrast, saturation etc.\n      */\n     DFBResult (*SetColorAdjustment)   ( CoreLayer                         *layer,\n                                         void                              *driver_data,\n                                         void                              *layer_data,\n                                         DFBColorAdjustment                *adjustment );\n\n     /*\n      * Set the stereo depth for L/R mono and stereo layers.\n      */\n     DFBResult (*SetStereoDepth)       ( CoreLayer                         *layer,\n                                         void                              *driver_data,\n                                         void                              *layer_data,\n                                         bool                               follow_video,\n                                         int                                z );\n\n     /*\n      * Check all parameters and return if this region is supported.\n      */\n     DFBResult (*TestRegion)           ( CoreLayer                         *layer,\n                                         void                              *driver_data,\n                                         void                              *layer_data,\n                                         CoreLayerRegionConfig             *config,\n                                         CoreLayerRegionConfigFlags        *ret_failed );\n\n     /*\n      * Add a new region to the layer, but don't program hardware, yet.\n      */\n     DFBResult (*AddRegion)            ( CoreLayer                         *layer,\n                                         void                              *driver_data,\n                                         void                              *layer_data,\n                                         void                              *region_data,\n                                         CoreLayerRegionConfig             *config );\n\n     /*\n      * Setup hardware, called once after AddRegion() or when parameters have changed.\n      * Surface and palette are only set if updated or new.\n      */\n     DFBResult (*SetRegion)            ( CoreLayer                         *layer,\n                                         void                              *driver_data,\n                                         void                              *layer_data,\n                                         void                              *region_data,\n                                         CoreLayerRegionConfig             *config,\n                                         CoreLayerRegionConfigFlags         updated,\n                                         CoreSurface                       *surface,\n                                         CorePalette                       *palette,\n                                         CoreSurfaceBufferLock             *left_lock,\n                                         CoreSurfaceBufferLock             *right_lock );\n\n     /*\n      * Remove a region from the layer.\n      */\n     DFBResult (*RemoveRegion)         ( CoreLayer                         *layer,\n                                         void                              *driver_data,\n                                         void                              *layer_data,\n                                         void                              *region_data );\n\n     /*\n      * Flip the surface of the region.\n      */\n     DFBResult (*FlipRegion)           ( CoreLayer                         *layer,\n                                         void                              *driver_data,\n                                         void                              *layer_data,\n                                         void                              *region_data,\n                                         CoreSurface                       *surface,\n                                         DFBSurfaceFlipFlags                flags,\n                                         const DFBRegion                   *left_update,\n                                         CoreSurfaceBufferLock             *left_lock,\n                                         const DFBRegion                   *right_update,\n                                         CoreSurfaceBufferLock             *right_lock );\n\n     /*\n      * Indicate updates to the front buffer content.\n      */\n     DFBResult (*UpdateRegion)         ( CoreLayer                         *layer,\n                                         void                              *driver_data,\n                                         void                              *layer_data,\n                                         void                              *region_data,\n                                         CoreSurface                       *surface,\n                                         const DFBRegion                   *left_update,\n                                         CoreSurfaceBufferLock             *left_lock,\n                                         const DFBRegion                   *right_update,\n                                         CoreSurfaceBufferLock             *right_lock );\n\n     /*\n      * Control hardware deinterlacing.\n      */\n     DFBResult (*SetInputField)        ( CoreLayer                         *layer,\n                                         void                              *driver_data,\n                                         void                              *layer_data,\n                                         void                              *region_data,\n                                         int                                field );\n\n     /*\n      * Allocate the surface of the region.\n      */\n     DFBResult (*AllocateSurface)      ( CoreLayer                         *layer,\n                                         void                              *driver_data,\n                                         void                              *layer_data,\n                                         void                              *region_data,\n                                         CoreLayerRegionConfig             *config,\n                                         CoreSurface                      **ret_surface );\n\n     /*\n      * Reallocate the surface of the region.\n      */\n     DFBResult (*ReallocateSurface)    ( CoreLayer                         *layer,\n                                         void                              *driver_data,\n                                         void                              *layer_data,\n                                         void                              *region_data,\n                                         CoreLayerRegionConfig             *config,\n                                         CoreSurface                       *surface );\n\n     /*\n      * Deallocate the surface of the region.\n      */\n     DFBResult (*DeallocateSurface)    ( CoreLayer                         *layer,\n                                         void                              *driver_data,\n                                         void                              *layer_data,\n                                         void                              *region_data,\n                                         CoreSurface                       *surface );\n} DisplayLayerFuncs;\n\ntypedef struct {\n     int                              index;\n     DFBDisplayLayerSourceDescription description;\n} CoreLayerSource;\n\ntypedef struct {\n     FusionVector      stack;\n     int               active;\n\n     CoreLayerContext *primary;\n} CoreLayerContexts;\n\ntypedef struct {\n     DFBDisplayLayerID           layer_id;\n\n     DFBDisplayLayerDescription  description;\n     DFBDisplayLayerConfig       default_config;\n     DFBColorAdjustment          default_adjustment;\n\n     CoreLayerSource            *sources;\n\n     FusionSHMPoolShared        *shmpool;\n\n     void                       *layer_data;         /* local data (impl) */\n\n     FusionSkirmish              lock;\n\n     CoreLayerContexts           contexts;\n\n     bool                        suspended;\n\n     FusionVector                added_regions;\n\n     FusionCall                  call;               /* dispatch */\n\n     DFBSurfacePixelFormat       pixelformat;\n} CoreLayerShared;\n\nstruct __DFB_CoreLayer {\n     CoreLayerShared         *shared;\n\n     CoreDFB                 *core;\n\n     CoreScreen              *screen;\n\n     void                    *driver_data;\n     void                    *layer_data;  /* copy of shared->layer_data */\n\n     CardState                state;\n\n     const DisplayLayerFuncs *funcs;\n};\n\n/**********************************************************************************************************************/\n\ntypedef DFBEnumerationResult (*DisplayLayerCallback)( CoreLayer *layer, void *ctx );\n\n/**********************************************************************************************************************/\n\n/*\n * Add a layer to a graphics device by pointing to a table containing driver functions.\n * The supplied 'driver_data' will be passed to these functions.\n */\nCoreLayer             *dfb_layers_register          ( CoreScreen                  *screen,\n                                                      void                        *driver_data,\n                                                      const DisplayLayerFuncs     *funcs );\n\n/*\n * Replace functions of the primary layer implementation by passing an alternative driver function table.\n * All non-NULL functions in the new table replace the functions in the original function table.\n * The original function table is written to 'primary_funcs' before to allow drivers to use existing functionality\n * from the original implementation.\n */\nCoreLayer             *dfb_layers_hook_primary      ( void                        *driver_data,\n                                                      DisplayLayerFuncs           *funcs,\n                                                      DisplayLayerFuncs           *primary_funcs,\n                                                      void                       **primary_driver_data );\n\n/*\n * Get the description of the specified layer.\n */\nvoid                   dfb_layer_get_description    ( const CoreLayer             *layer,\n                                                      DFBDisplayLayerDescription  *ret_desc );\n\n/*\n * Return the pixel format of the primary layer.\n */\nDFBSurfacePixelFormat  dfb_primary_layer_pixelformat( void );\n\n/*\n * Enumerate all registered layers by invoking the callback for each layer.\n */\nvoid                   dfb_layers_enumerate         ( DisplayLayerCallback         callback,\n                                                      void                        *ctx );\n/*\n * Return the number of layers.\n */\nint                    dfb_layers_num               ( void );\n\n/*\n * Return the layer with the specified ID.\n */\nCoreLayer             *dfb_layer_at                 ( DFBDisplayLayerID            id );\n\n/*\n * Return the (translated) layer with the specified ID.\n */\nCoreLayer             *dfb_layer_at_translated      ( DFBDisplayLayerID            id );\n\n/*\n * Return the ID of the specified layer.\n */\nDFBDisplayLayerID      dfb_layer_id                 ( const CoreLayer             *layer );\n\n/*\n * Return the (translated) ID of the specified layer.\n */\nDFBDisplayLayerID      dfb_layer_id_translated      ( const CoreLayer             *layer );\n\n#endif\n"
  },
  {
    "path": "src/core/local_surface_pool.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/surface_allocation.h>\n#include <core/surface_buffer.h>\n#include <core/surface_pool.h>\n#include <core/system.h>\n#include <misc/conf.h>\n\nD_DEBUG_DOMAIN( Core_Local, \"Core/Local\", \"DirectFB Core Local Surface Pool\" );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int   magic;\n     void *addr;\n     int   pitch;\n     int   size;\n} LocalAllocationData;\n\n/**********************************************************************************************************************/\n\nstatic int\nlocalAllocationDataSize( void )\n{\n     return sizeof(LocalAllocationData);\n}\n\nstatic DFBResult\nlocalInitPool( CoreDFB                    *core,\n               CoreSurfacePool            *pool,\n               void                       *pool_data,\n               void                       *pool_local,\n               void                       *system_data,\n               CoreSurfacePoolDescription *ret_desc )\n{\n     D_DEBUG_AT( Core_Local, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_ASSERT( ret_desc != NULL );\n\n     ret_desc->caps              = CSPCAPS_VIRTUAL;\n     ret_desc->access[CSAID_CPU] = CSAF_READ | CSAF_WRITE | CSAF_SHARED;\n     ret_desc->types             = CSTF_LAYER | CSTF_WINDOW | CSTF_CURSOR | CSTF_FONT | CSTF_SHARED | CSTF_INTERNAL;\n     ret_desc->priority          = CSPP_DEFAULT;\n\n     if (dfb_system_caps() & CSCAPS_SYSMEM_EXTERNAL)\n          ret_desc->types |= CSTF_EXTERNAL;\n\n     snprintf( ret_desc->name, DFB_SURFACE_POOL_DESC_NAME_LENGTH, \"System Memory\" );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nlocalJoinPool( CoreDFB         *core,\n               CoreSurfacePool *pool,\n               void            *pool_data,\n               void            *pool_local,\n               void            *system_data )\n{\n     D_DEBUG_AT( Core_Local, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nlocalDestroyPool( CoreSurfacePool *pool,\n                  void            *pool_data,\n                  void            *pool_local )\n{\n     D_DEBUG_AT( Core_Local, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nlocalLeavePool( CoreSurfacePool *pool,\n                void            *pool_data,\n                void            *pool_local )\n{\n     D_DEBUG_AT( Core_Local, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nlocalAllocateBuffer( CoreSurfacePool       *pool,\n                     void                  *pool_data,\n                     void                  *pool_local,\n                     CoreSurfaceBuffer     *buffer,\n                     CoreSurfaceAllocation *allocation,\n                     void                  *alloc_data )\n{\n     CoreSurface         *surface;\n     LocalAllocationData *alloc = alloc_data;\n\n     D_DEBUG_AT( Core_Local, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n     D_ASSERT( alloc != NULL );\n\n     surface = buffer->surface;\n\n     /* Create aligned local system surface buffer if both base address and pitch are non-zero. */\n     if (dfb_config->system_surface_align_base && dfb_config->system_surface_align_pitch) {\n          /* Make sure base address and pitch are a positive power of two. */\n          D_ASSERT( dfb_config->system_surface_align_base >= 4 );\n          D_ASSERT( !(dfb_config->system_surface_align_base & (dfb_config->system_surface_align_base - 1)) );\n          D_ASSERT( dfb_config->system_surface_align_pitch >= 2 );\n          D_ASSERT( !(dfb_config->system_surface_align_pitch & (dfb_config->system_surface_align_pitch - 1)) );\n\n          dfb_surface_calc_buffer_size( surface, dfb_config->system_surface_align_pitch, 0,\n                                        &alloc->pitch, &alloc->size );\n\n          /* posix_memalign() function requires base alignment to actually be at least four. */\n          int err = posix_memalign( &alloc->addr, dfb_config->system_surface_align_base, alloc->size );\n          if (err) {\n              D_ERROR( \"Core/Local: Error from posix_memalign with base alignment %u\\n\",\n                       dfb_config->system_surface_align_base );\n              return DFB_FAILURE;\n          }\n     }\n     /* Create un-aligned local system surface buffer. */\n     else {\n          dfb_surface_calc_buffer_size( surface, 8, 0, &alloc->pitch, &alloc->size );\n\n          alloc->addr = D_MALLOC( alloc->size );\n          if (!alloc->addr)\n               return D_OOM();\n     }\n\n     D_MAGIC_SET( alloc, LocalAllocationData );\n\n     allocation->flags = CSALF_VOLATILE;\n     allocation->size  = alloc->size;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nlocalDeallocateBuffer( CoreSurfacePool       *pool,\n                       void                  *pool_data,\n                       void                  *pool_local,\n                       CoreSurfaceBuffer     *buffer,\n                       CoreSurfaceAllocation *allocation,\n                       void                  *alloc_data )\n{\n     LocalAllocationData *alloc = alloc_data;\n\n     D_DEBUG_AT( Core_Local, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( alloc, LocalAllocationData );\n\n     if (dfb_config->system_surface_align_base && dfb_config->system_surface_align_pitch)\n          /* This was allocated by posix_memalign() function and requires free(). */\n          free( alloc->addr );\n     else\n          D_FREE( alloc->addr );\n\n     D_MAGIC_CLEAR( alloc );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nlocalLock( CoreSurfacePool       *pool,\n           void                  *pool_data,\n           void                  *pool_local,\n           CoreSurfaceAllocation *allocation,\n           void                  *alloc_data,\n           CoreSurfaceBufferLock *lock )\n{\n     LocalAllocationData *alloc = alloc_data;\n\n     D_DEBUG_AT( Core_Local, \"%s() <- size %d\\n\", __FUNCTION__, alloc->size );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );\n     D_MAGIC_ASSERT( alloc, LocalAllocationData );\n\n     lock->addr  = alloc->addr;\n     lock->pitch = alloc->pitch;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nlocalUnlock( CoreSurfacePool       *pool,\n             void                  *pool_data,\n             void                  *pool_local,\n             CoreSurfaceAllocation *allocation,\n             void                  *alloc_data,\n             CoreSurfaceBufferLock *lock )\n{\n     LocalAllocationData *alloc = alloc_data;\n\n     D_DEBUG_AT( Core_Local, \"%s()\\n\", __FUNCTION__ );\n\n     D_UNUSED_P( alloc );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );\n     D_MAGIC_ASSERT( alloc, LocalAllocationData );\n\n     return DFB_OK;\n}\n\nconst SurfacePoolFuncs localSurfacePoolFuncs = {\n     .AllocationDataSize = localAllocationDataSize,\n     .InitPool           = localInitPool,\n     .JoinPool           = localJoinPool,\n     .DestroyPool        = localDestroyPool,\n     .LeavePool          = localLeavePool,\n     .AllocateBuffer     = localAllocateBuffer,\n     .DeallocateBuffer   = localDeallocateBuffer,\n     .Lock               = localLock,\n     .Unlock             = localUnlock\n};\n"
  },
  {
    "path": "src/core/meson.build",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\nflux_files = [\n  'CoreDFB',\n  'CoreGraphicsState',\n  'CoreInputDevice',\n  'CoreLayer',\n  'CoreLayerContext',\n  'CoreLayerRegion',\n  'CorePalette',\n  'CoreSlave',\n  'CoreScreen',\n  'CoreSurface',\n  'CoreSurfaceAllocation',\n  'CoreSurfaceClient',\n  'CoreWindow',\n  'CoreWindowStack'\n]\n\nfluxcomp = find_program(get_option('fluxcomp'))\n\nflux_sources = []\nforeach flux_file : flux_files\n  flux_sources += custom_target(flux_file,\n                                input: flux_file + '.flux',\n                                output: [flux_file + '.c', flux_file + '.h'],\n                                command: [fluxcomp, '--call-mode',\n                                                    '--dispatch-error-abort',\n                                                    '--identity',\n                                                    '--include-prefix=core',\n                                                    '--object-ptrs',\n                                                    '--static-args-bytes=FLUXED_ARGS_BYTES',\n                                                    '-c', '@INPUT@', '-o=src/core'])\nendforeach\n"
  },
  {
    "path": "src/core/palette.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CorePalette.h>\n#include <core/colorhash.h>\n#include <core/core.h>\n#include <core/palette.h>\n#include <core/surface.h>\n#include <fusion/shmalloc.h>\n\nD_DEBUG_DOMAIN( Core_Palette, \"Core/Palette\", \"DirectFB Core Palette\" );\n\n/**********************************************************************************************************************/\n\nstatic const ReactionFunc dfb_palette_globals[] = {\n     _dfb_surface_palette_listener,\n     NULL\n};\n\nstatic void\npalette_destructor( FusionObject *object,\n                    bool          zombie,\n                    void         *ctx )\n{\n     CorePaletteNotification  notification;\n     CorePalette             *palette = (CorePalette*) object;\n\n     D_MAGIC_ASSERT( palette, CorePalette );\n     D_ASSERT( palette->entries != NULL );\n     D_ASSERT( palette->entries_yuv != NULL );\n\n     D_DEBUG_AT( Core_Palette, \"Destroying palette %p (%u%s)\\n\",\n                 palette, palette->num_entries, zombie ? \" ZOMBIE\" : \"\" );\n\n     notification.flags   = CPNF_DESTROY;\n     notification.palette = palette;\n\n     dfb_palette_dispatch( palette, &notification, dfb_palette_globals );\n\n     dfb_colorhash_invalidate( NULL, palette );\n\n     SHFREE( palette->shmpool, palette->entries_yuv );\n     SHFREE( palette->shmpool, palette->entries );\n\n     CorePalette_Deinit_Dispatch( &palette->call );\n\n     D_MAGIC_CLEAR( palette );\n\n     /* Destroy the object. */\n     fusion_object_destroy( object );\n}\n\nFusionObjectPool *\ndfb_palette_pool_create( const FusionWorld *world )\n{\n     FusionObjectPool *pool;\n\n     pool = fusion_object_pool_create( \"Palette Pool\",\n                                       sizeof(CorePalette), sizeof(CorePaletteNotification),\n                                       palette_destructor, NULL, world );\n\n     return pool;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_palette_create( CoreDFB               *core,\n                    unsigned int           size,\n                    DFBSurfaceColorSpace   colorspace,\n                    CorePalette          **ret_palette )\n{\n     CorePalette *palette;\n\n     D_ASSERT( ret_palette );\n\n     D_DEBUG_AT( Core_Palette, \"%s( %u )\\n\", __FUNCTION__, size );\n\n     /* Create the palette object. */\n     palette = dfb_core_create_palette( core );\n     if (!palette)\n          return DFB_FUSION;\n\n     palette->shmpool = dfb_core_shmpool( core );\n\n     if (size) {\n          palette->entries = SHCALLOC( palette->shmpool, size, sizeof(DFBColor) );\n          if (!palette->entries) {\n               fusion_object_destroy( &palette->object );\n               return D_OOSHM();\n          }\n\n          palette->entries_yuv = SHCALLOC( palette->shmpool, size, sizeof(DFBColorYUV) );\n          if (!palette->entries_yuv) {\n               SHFREE( palette->shmpool, palette->entries );\n               fusion_object_destroy( &palette->object );\n               return D_OOSHM();\n          }\n     }\n\n     palette->num_entries = size;\n     palette->colorspace  = colorspace;\n\n     CorePalette_Init_Dispatch( core, palette, &palette->call );\n\n     D_MAGIC_SET( palette, CorePalette );\n\n     /* Activate the object. */\n     fusion_object_activate( &palette->object );\n\n     /* Return the new palette. */\n     *ret_palette = palette;\n\n     D_DEBUG_AT( Core_Palette, \"  -> %p\\n\", palette );\n\n     return DFB_OK;\n}\n\nstatic const u8 lookup3to8[] = { 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff };\nstatic const u8 lookup2to8[] = { 0x00, 0x55, 0xaa, 0xff };\n\nvoid\ndfb_palette_generate_rgb332_map( CorePalette *palette )\n{\n     unsigned int i;\n     DFBColor     entries[256];\n\n     D_DEBUG_AT( Core_Palette, \"%s( %p )\\n\", __FUNCTION__, palette );\n\n     D_MAGIC_ASSERT( palette, CorePalette );\n\n     if (!palette->num_entries)\n          return;\n\n     for (i = 0; i < palette->num_entries; i++) {\n          entries[i].a = i ? 0xff : 0x00;\n          entries[i].r = lookup3to8[(i & 0xE0) >> 5];\n          entries[i].g = lookup3to8[(i & 0x1C) >> 2];\n          entries[i].b = lookup2to8[(i & 0x03)];\n     }\n\n     CorePalette_SetEntries( palette, entries, palette->num_entries, 0 );\n}\n\nvoid\ndfb_palette_generate_rgb121_map( CorePalette *palette )\n{\n     unsigned int i;\n     DFBColor     entries[256];\n\n     D_DEBUG_AT( Core_Palette, \"%s( %p )\\n\", __FUNCTION__, palette );\n\n     D_MAGIC_ASSERT( palette, CorePalette );\n\n     if (!palette->num_entries)\n          return;\n\n     for (i = 0; i < palette->num_entries; i++) {\n          entries[i].a = i ? 0xff : 0x00;\n          entries[i].r = (i & 0x8) ? 0xff : 0x00;\n          entries[i].g = lookup2to8[(i & 0x6) >> 1];\n          entries[i].b = (i & 0x1) ? 0xff : 0x00;\n     }\n\n     CorePalette_SetEntries( palette, entries, palette->num_entries, 0 );\n}\n\nunsigned int\ndfb_palette_search( CorePalette *palette,\n                    u8           r,\n                    u8           g,\n                    u8           b,\n                    u8           a )\n{\n     unsigned int index;\n\n     D_DEBUG_AT( Core_Palette, \"%s( %p )\\n\", __FUNCTION__, palette );\n\n     D_MAGIC_ASSERT( palette, CorePalette );\n\n     index = dfb_colorhash_lookup( NULL, palette, r, g, b, a );\n\n     return index;\n}\n\nvoid\ndfb_palette_update( CorePalette *palette,\n                    int          first,\n                    int          last )\n{\n     CorePaletteNotification notification;\n\n     D_DEBUG_AT( Core_Palette, \"%s( %p, %d, %d )\\n\", __FUNCTION__, palette, first, last );\n\n     D_MAGIC_ASSERT( palette, CorePalette );\n     D_ASSERT( first >= 0 );\n     D_ASSERT( first < palette->num_entries );\n     D_ASSERT( last >= 0 );\n     D_ASSERT( last < palette->num_entries );\n     D_ASSERT( first <= last );\n\n     notification.flags   = CPNF_ENTRIES;\n     notification.palette = palette;\n     notification.first   = first;\n     notification.last    = last;\n\n     dfb_colorhash_invalidate( NULL, palette );\n\n     dfb_palette_dispatch( palette, &notification, dfb_palette_globals );\n}\n\nbool\ndfb_palette_equal( CorePalette *palette1,\n                   CorePalette *palette2 )\n{\n     u32 *entries1;\n     u32 *entries2;\n     int  i;\n\n     D_DEBUG_AT( Core_Palette, \"%s( %p, %p )\\n\", __FUNCTION__, palette1, palette2 );\n\n     D_ASSERT( palette1 != NULL );\n     D_ASSERT( palette2 != NULL );\n\n     if (palette1 == palette2) {\n          D_DEBUG_AT( Core_Palette, \"  -> SAME\\n\" );\n          return true;\n     }\n\n     if (palette1->num_entries != palette2->num_entries) {\n          D_DEBUG_AT( Core_Palette, \"  -> NOT EQUAL (%u/%u)\\n\", palette1->num_entries, palette2->num_entries );\n          return false;\n     }\n\n     entries1 = (u32*) palette1->entries;\n     entries2 = (u32*) palette2->entries;\n\n     for (i = 0; i < palette1->num_entries; i++) {\n          if (entries1[i] != entries2[i]) {\n               D_DEBUG_AT( Core_Palette, \"  -> NOT EQUAL (%d)\\n\", i );\n               return false;\n          }\n     }\n\n     D_DEBUG_AT( Core_Palette, \"  -> EQUAL\\n\" );\n\n     return true;\n}\n"
  },
  {
    "path": "src/core/palette.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__PALETTE_H__\n#define __CORE__PALETTE_H__\n\n#include <core/coretypes.h>\n#include <fusion/object.h>\n\n/**********************************************************************************************************************/\n\nstruct __DFB_CorePalette {\n     FusionObject          object;\n     int                   magic;\n\n     unsigned int          num_entries;\n     DFBColor             *entries;\n     DFBColorYUV          *entries_yuv;\n     DFBSurfaceColorSpace  colorspace;\n\n     FusionSHMPoolShared  *shmpool;\n\n     FusionCall           call;\n};\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CPNF_ENTRIES = 0x00000001,\n     CPNF_DESTROY = 0x00000002\n} CorePaletteNotificationFlags;\n\ntypedef struct {\n     CorePaletteNotificationFlags  flags;\n     CorePalette                  *palette;\n     int                           first;\n     int                           last;\n} CorePaletteNotification;\n\n/**********************************************************************************************************************/\n\n/*\n * Creates a pool of palette objects.\n */\nFusionObjectPool *dfb_palette_pool_create        ( const FusionWorld     *world );\n\n/*\n * Generates dfb_palette_ref(), dfb_palette_attach() etc.\n */\nFUSION_OBJECT_METHODS( CorePalette, dfb_palette )\n\ntypedef enum {\n     DFB_SURFACE_PALETTE_LISTENER = 0x00000000\n} DFB_PALETTE_GLOBALS;\n\n/**********************************************************************************************************************/\n\nDFBResult         dfb_palette_create             ( CoreDFB               *core,\n                                                   unsigned int           size,\n                                                   DFBSurfaceColorSpace   colorspace,\n                                                   CorePalette          **ret_palette );\n\nvoid              dfb_palette_generate_rgb332_map( CorePalette           *palette );\n\nvoid              dfb_palette_generate_rgb121_map( CorePalette           *palette );\n\nunsigned int      dfb_palette_search             ( CorePalette           *palette,\n                                                   u8                     r,\n                                                   u8                     g,\n                                                   u8                     b,\n                                                   u8                     a );\n\nvoid              dfb_palette_update             ( CorePalette           *palette,\n                                                   int                    first,\n                                                   int                    last );\n\nbool              dfb_palette_equal              ( CorePalette           *palette1,\n                                                   CorePalette           *palette2 );\n\n#endif\n"
  },
  {
    "path": "src/core/prealloc_surface_pool.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core.h>\n#include <core/surface_allocation.h>\n#include <core/surface_buffer.h>\n#include <core/surface_pool.h>\n\nD_DEBUG_DOMAIN( Core_PreAlloc, \"Core/PreAlloc\", \"DirectFB Core PreAlloc Surface Pool\" );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     void *addr;\n     int   pitch;\n} PreallocAllocationData;\n\n/**********************************************************************************************************************/\n\nstatic int\npreallocAllocationDataSize( void )\n{\n     return sizeof(PreallocAllocationData);\n}\n\nstatic DFBResult\npreallocInitPool( CoreDFB                    *core,\n                  CoreSurfacePool            *pool,\n                  void                       *pool_data,\n                  void                       *pool_local,\n                  void                       *system_data,\n                  CoreSurfacePoolDescription *ret_desc )\n{\n     D_DEBUG_AT( Core_PreAlloc, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_ASSERT( ret_desc != NULL );\n\n     ret_desc->caps              = CSPCAPS_NONE;\n     ret_desc->access[CSAID_CPU] = CSAF_READ | CSAF_WRITE;\n     ret_desc->types             = CSTF_PREALLOCATED | CSTF_INTERNAL;\n     ret_desc->priority          = CSPP_DEFAULT;\n\n     snprintf( ret_desc->name, DFB_SURFACE_POOL_DESC_NAME_LENGTH, \"Preallocated Memory\" );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\npreallocTestConfig( CoreSurfacePool         *pool,\n                    void                    *pool_data,\n                    void                    *pool_local,\n                    CoreSurfaceBuffer       *buffer,\n                    const CoreSurfaceConfig *config )\n{\n     D_DEBUG_AT( Core_PreAlloc, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_ASSERT( config != NULL );\n\n     if (!(config->flags & CSCONF_PREALLOCATED))\n          return DFB_UNSUPPORTED;\n\n     if (Core_GetIdentity() != buffer->surface->object.identity)\n          return DFB_UNSUPPORTED;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\npreallocAllocateBuffer( CoreSurfacePool       *pool,\n                        void                  *pool_data,\n                        void                  *pool_local,\n                        CoreSurfaceBuffer     *buffer,\n                        CoreSurfaceAllocation *allocation,\n                        void                  *alloc_data )\n{\n     int                     index;\n     CoreSurface            *surface;\n     PreallocAllocationData *alloc    = alloc_data;\n     FusionID                identity = Core_GetIdentity();\n\n     D_DEBUG_AT( Core_PreAlloc, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n\n     surface = buffer->surface;\n\n     D_DEBUG_AT( Core_PreAlloc, \"  -> surface identity %lu\\n\", surface->object.identity );\n     D_DEBUG_AT( Core_PreAlloc, \"  -> core identity    %lu\\n\", identity );\n\n     if (!(surface->config.flags & CSCONF_PREALLOCATED))\n          return DFB_BUG;\n\n     if (identity != surface->object.identity) {\n          D_ERROR( \"Core/PreAlloc: Cannot allocate buffer for other (%lu) than creator (%lu)!\\n\",\n                   identity, surface->object.identity );\n          return DFB_ACCESSDENIED;\n     }\n\n     index = dfb_surface_buffer_index( buffer );\n\n     if (!surface->config.preallocated[index].addr ||\n          surface->config.preallocated[index].pitch < DFB_BYTES_PER_LINE(surface->config.format,\n                                                                         surface->config.size.w)) {\n          return DFB_BUG;\n     }\n\n     alloc->addr  = surface->config.preallocated[index].addr;\n     alloc->pitch = surface->config.preallocated[index].pitch;\n\n     allocation->flags = CSALF_PREALLOCATED;\n     allocation->size  = surface->config.preallocated[index].pitch *\n                         DFB_PLANE_MULTIPLY( surface->config.format, surface->config.size.h );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\npreallocDeallocateBuffer( CoreSurfacePool       *pool,\n                          void                  *pool_data,\n                          void                  *pool_local,\n                          CoreSurfaceBuffer     *buffer,\n                          CoreSurfaceAllocation *allocation,\n                          void                  *alloc_data )\n{\n     D_DEBUG_AT( Core_PreAlloc, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\npreallocLock( CoreSurfacePool       *pool,\n              void                  *pool_data,\n              void                  *pool_local,\n              CoreSurfaceAllocation *allocation,\n              void                  *alloc_data,\n              CoreSurfaceBufferLock *lock )\n{\n     CoreSurface            *surface;\n     PreallocAllocationData *alloc    = alloc_data;\n     FusionID                identity = Core_GetIdentity();\n\n     D_DEBUG_AT( Core_PreAlloc, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( allocation->surface, CoreSurface );\n     D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );\n\n     surface = allocation->surface;\n\n     if (identity != surface->object.identity) {\n          D_ERROR( \"Core/PreAlloc: Cannot lock buffer by other (%lu) than creator (%lu)!\\n\",\n                   identity, surface->object.identity );\n          return DFB_ACCESSDENIED;\n     }\n\n     lock->addr  = alloc->addr;\n     lock->pitch = alloc->pitch;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\npreallocUnlock( CoreSurfacePool       *pool,\n                void                  *pool_data,\n                void                  *pool_local,\n                CoreSurfaceAllocation *allocation,\n                void                  *alloc_data,\n                CoreSurfaceBufferLock *lock )\n{\n     D_DEBUG_AT( Core_PreAlloc, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\npreallocPrealloc( CoreSurfacePool             *pool,\n                  void                        *pool_data,\n                  void                        *pool_local,\n                  const DFBSurfaceDescription *description,\n                  CoreSurfaceConfig           *config )\n{\n     unsigned int i, num = 1;\n\n     D_DEBUG_AT( Core_PreAlloc, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n     if (config->caps & DSCAPS_VIDEOONLY)\n          return DFB_UNSUPPORTED;\n\n     if (config->caps & DSCAPS_DOUBLE)\n          num = 2;\n     else if (config->caps & DSCAPS_TRIPLE)\n          num = 3;\n\n     for (i = 0; i < num; i++) {\n          config->preallocated[i].addr  = description->preallocated[i].data;\n          config->preallocated[i].pitch = description->preallocated[i].pitch;\n     }\n\n     return DFB_OK;\n}\n\nconst SurfacePoolFuncs preallocSurfacePoolFuncs = {\n     .AllocationDataSize = preallocAllocationDataSize,\n     .InitPool           = preallocInitPool,\n     .TestConfig         = preallocTestConfig,\n     .AllocateBuffer     = preallocAllocateBuffer,\n     .DeallocateBuffer   = preallocDeallocateBuffer,\n     .Lock               = preallocLock,\n     .Unlock             = preallocUnlock,\n     .PreAlloc           = preallocPrealloc\n};\n"
  },
  {
    "path": "src/core/prealloc_surface_pool_bridge.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreSlave.h>\n#include <core/core.h>\n#include <core/surface_allocation.h>\n#include <core/surface_buffer.h>\n#include <core/surface_core.h>\n#include <core/surface_pool_bridge.h>\n\nD_DEBUG_DOMAIN( PreAlloc_Bridge, \"Core/PreAlloc/Bridge\", \"DirectFB Core PreAlloc Surface Pool Bridge\" );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     CoreSurfacePool *shared_pool;\n     CoreSurfacePool *prealloc_pool;\n} preallocPoolBridgeData;\n\n/**********************************************************************************************************************/\n\nstatic int\npreallocPoolBridgeDataSize( void )\n{\n     return sizeof(preallocPoolBridgeData);\n}\n\nstatic DFBResult\npreallocInitPoolBridge( CoreDFB                          *core,\n                        CoreSurfacePoolBridge            *bridge,\n                        void                             *bridge_data,\n                        void                             *bridge_local,\n                        void                             *ctx,\n                        CoreSurfacePoolBridgeDescription *ret_desc )\n{\n     preallocPoolBridgeData *data = bridge_data;\n     DFBSurfaceCore         *sc   = ctx;\n     DFBSurfaceCoreShared   *shared;\n\n     D_DEBUG_AT( PreAlloc_Bridge, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge );\n     D_ASSERT( bridge_data != NULL );\n     D_ASSERT( sc != NULL );\n     D_ASSERT( sc->shared != NULL );\n     D_ASSERT( ret_desc != NULL );\n\n     shared = sc->shared;\n\n     ret_desc->caps = CSPBCAPS_NONE;\n\n     snprintf( ret_desc->name, DFB_SURFACE_POOL_BRIDGE_DESC_NAME_LENGTH, \"PreAlloc Pool Bridge\" );\n\n     data->shared_pool   = shared->surface_pool;\n     data->prealloc_pool = shared->prealloc_pool;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\npreallocJoinPoolBridge( CoreDFB               *core,\n                        CoreSurfacePoolBridge *bridge,\n                        void                  *bridge_data,\n                        void                  *bridge_local,\n                        void                  *ctx )\n{\n     D_DEBUG_AT( PreAlloc_Bridge, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge );\n     D_ASSERT( bridge_data != NULL );\n     D_ASSERT( ctx != NULL );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\npreallocDestroyPoolBridge( CoreSurfacePoolBridge *bridge,\n                           void                  *bridge_data,\n                           void                  *bridge_local )\n{\n     D_DEBUG_AT( PreAlloc_Bridge, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\npreallocLeavePoolBridge( CoreSurfacePoolBridge *bridge,\n                         void                  *bridge_data,\n                         void                  *bridge_local )\n{\n     D_DEBUG_AT( PreAlloc_Bridge, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\npreallocCheckTransfer( CoreSurfacePoolBridge *bridge,\n                       void                  *bridge_data,\n                       void                  *bridge_local,\n                       CoreSurfaceBuffer     *buffer,\n                       CoreSurfaceAllocation *from,\n                       CoreSurfaceAllocation *to )\n{\n     preallocPoolBridgeData *data = bridge_data;\n\n     D_DEBUG_AT( PreAlloc_Bridge, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( bridge_data != NULL );\n\n     if (!Core_Resource_GetSlave( buffer->surface->object.identity )) {\n          D_DEBUG_AT( PreAlloc_Bridge, \"  -> no slave\\n\" );\n          return DFB_NOIMPL;\n     }\n\n     if (from->pool == data->prealloc_pool) {\n          D_DEBUG_AT( PreAlloc_Bridge, \"  -> from preallocated\\n\" );\n          return DFB_OK;\n     }\n\n     if (to->pool == data->prealloc_pool) {\n          D_DEBUG_AT( PreAlloc_Bridge, \"  -> to preallocated\\n\" );\n          return DFB_OK;\n     }\n\n     return DFB_UNSUPPORTED;\n}\n\nstatic DFBResult\nprealloc_transfer_locked( CoreSurface             *surface,\n                          CoreSurfacePoolTransfer *transfer,\n                          CoreSurfaceAllocation   *locked,\n                          CoreSurfaceAccessFlags   flags,\n                          CoreSlave               *slave )\n{\n     DFBResult             ret;\n     CoreSurfaceBufferLock lock;\n     int                   index;\n     int                   i, y;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     D_ASSERT( transfer != NULL );\n\n     CORE_SURFACE_ALLOCATION_ASSERT( locked );\n\n     index = dfb_surface_buffer_index( locked->buffer );\n\n     D_DEBUG_AT( PreAlloc_Bridge, \"%s()\\n\", __FUNCTION__ );\n\n     D_DEBUG_AT( PreAlloc_Bridge, \"  -> transfer locked %s Fusion ID %lu (index %d)\\n\",\n                 (flags & CSAF_WRITE) ? \"from\" : \"to\", surface->object.identity, index );\n\n     dfb_surface_buffer_lock_init( &lock, CSAID_CPU, flags );\n\n     ret = dfb_surface_pool_lock( locked->pool, locked, &lock );\n     if (ret) {\n          dfb_surface_buffer_lock_deinit( &lock );\n          return ret;\n     }\n\n     for (i = 0; i < transfer->num_rects; i++) {\n          const DFBRectangle *rect   = &transfer->rects[i];\n          int                 offset = DFB_BYTES_PER_LINE( surface->config.format, rect->x );\n          int                 length = DFB_BYTES_PER_LINE( surface->config.format, rect->w );\n\n          for (y = 0; y < rect->h; y++) {\n               if (flags & CSAF_WRITE)\n                    ret = CoreSlave_GetData( slave,\n                                             surface->config.preallocated[index].addr +\n                                             (rect->y + y) * surface->config.preallocated[index].pitch + offset, length,\n                                             lock.addr + (rect->y + y) * lock.pitch + offset );\n               else\n                    ret = CoreSlave_PutData( slave,\n                                             surface->config.preallocated[index].addr +\n                                             (rect->y + y) * surface->config.preallocated[index].pitch + offset, length,\n                                             lock.addr + (rect->y + y) * lock.pitch + offset );\n               if (ret)\n                    break;\n          }\n\n          if (ret)\n               break;\n     }\n\n     dfb_surface_pool_unlock( locked->pool, locked, &lock );\n\n     dfb_surface_buffer_lock_deinit( &lock );\n\n     return ret;\n}\n\nstatic DFBResult\nprealloc_transfer_readwrite( CoreSurface             *surface,\n                             CoreSurfacePoolTransfer *transfer,\n                             CoreSurfaceAllocation   *allocation,\n                             CoreSurfaceAccessFlags   flags,\n                             CoreSlave               *slave )\n{\n     DFBResult ret = DFB_OK;\n     int       index;\n     int       i, y;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     D_ASSERT( transfer != NULL );\n\n     CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n     index = dfb_surface_buffer_index( allocation->buffer );\n\n     D_DEBUG_AT( PreAlloc_Bridge, \"%s()\\n\", __FUNCTION__ );\n\n     D_DEBUG_AT( PreAlloc_Bridge, \"  -> transfer read/write %s Fusion ID %lu (index %d)\\n\",\n                 (flags & CSAF_WRITE) ? \"from\" : \"to\", surface->object.identity, index );\n\n     for (i = 0; i < transfer->num_rects; i++) {\n          const DFBRectangle *rect   = &transfer->rects[i];\n          int                 offset = DFB_BYTES_PER_LINE( surface->config.format, rect->x );\n          int                 length = DFB_BYTES_PER_LINE( surface->config.format, rect->w );\n          u8                 *temp   = alloca( length );\n\n          for (y = 0; y < rect->h; y++) {\n               DFBRectangle lrect = { rect->x, rect->y + y, rect->w, 1 };\n\n               if (flags & CSAF_WRITE) {\n                    ret = CoreSlave_GetData( slave,\n                                             surface->config.preallocated[index].addr +\n                                             (rect->y + y) * surface->config.preallocated[index].pitch + offset, length,\n                                             temp );\n                    if (ret)\n                         break;\n\n                    ret = dfb_surface_pool_write( allocation->pool, allocation, temp, length, &lrect );\n               }\n               else {\n                    ret = dfb_surface_pool_read( allocation->pool, allocation, temp, length, &lrect );\n                    if (ret)\n                         break;\n\n                    ret = CoreSlave_PutData( slave,\n                                             surface->config.preallocated[index].addr +\n                                             (rect->y + y) * surface->config.preallocated[index].pitch + offset, length,\n                                             temp );\n               }\n\n               if (ret)\n                    break;\n          }\n\n          if (ret)\n               break;\n     }\n\n     return ret;\n}\n\nstatic DFBResult\npreallocStartTransfer( CoreSurfacePoolBridge   *bridge,\n                       void                    *bridge_data,\n                       void                    *bridge_local,\n                       CoreSurfacePoolTransfer *transfer,\n                       void                    *transfer_data )\n{\n     DFBResult               ret   = DFB_BUG;\n     preallocPoolBridgeData *data  = bridge_data;\n     CoreSurfaceAllocation  *from  = transfer->from;\n     CoreSurfaceAllocation  *to    = transfer->to;\n     CoreSurface            *surface;\n     CoreSlave              *slave;\n\n     D_DEBUG_AT( PreAlloc_Bridge, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( bridge_data != NULL );\n     D_ASSERT( transfer != NULL );\n     D_MAGIC_ASSERT( transfer->buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( transfer->buffer->surface, CoreSurface );\n\n     surface = transfer->buffer->surface;\n\n     slave = Core_Resource_GetSlave( surface->object.identity );\n     if (!slave) {\n          D_WARN( \"no slave object for id %lu\", surface->object.identity );\n          return DFB_NOIMPL;\n     }\n\n     if (from->pool == data->prealloc_pool) {\n          if (to->pool->desc.access[CSAID_CPU] & CSAF_WRITE)\n               ret = prealloc_transfer_locked( surface, transfer, to, CSAF_WRITE, slave );\n          else\n               ret = prealloc_transfer_readwrite( surface, transfer, to, CSAF_WRITE, slave );\n     }\n     else if (to->pool == data->prealloc_pool) {\n          if (from->pool->desc.access[CSAID_CPU] & CSAF_READ)\n               ret = prealloc_transfer_locked( surface, transfer, from, CSAF_READ, slave );\n          else\n               ret = prealloc_transfer_readwrite( surface, transfer, from, CSAF_READ, slave );\n     }\n\n     return ret;\n}\n\nstatic DFBResult\npreallocFinishTransfer( CoreSurfacePoolBridge   *bridge,\n                        void                    *bridge_data,\n                        void                    *bridge_local,\n                        CoreSurfacePoolTransfer *transfer,\n                        void                    *transfer_data )\n{\n     D_DEBUG_AT( PreAlloc_Bridge, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( bridge_data != NULL );\n\n     return DFB_OK;\n}\n\nconst SurfacePoolBridgeFuncs preallocSurfacePoolBridgeFuncs = {\n     .PoolBridgeDataSize = preallocPoolBridgeDataSize,\n     .InitPoolBridge     = preallocInitPoolBridge,\n     .JoinPoolBridge     = preallocJoinPoolBridge,\n     .DestroyPoolBridge  = preallocDestroyPoolBridge,\n     .LeavePoolBridge    = preallocLeavePoolBridge,\n     .CheckTransfer      = preallocCheckTransfer,\n     .StartTransfer      = preallocStartTransfer,\n     .FinishTransfer     = preallocFinishTransfer\n};\n"
  },
  {
    "path": "src/core/screen.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/layers.h>\n#include <core/screen.h>\n#include <core/screens.h>\n\nD_DEBUG_DOMAIN( Core_Screen, \"Core/Screen\", \"DirectFB Core Screen\" );\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_screen_get_info( CoreScreen           *screen,\n                     DFBScreenID          *ret_id,\n                     DFBScreenDescription *ret_desc )\n{\n     CoreScreenShared *shared;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->shared != NULL );\n\n     shared = screen->shared;\n\n     D_DEBUG_AT( Core_Screen, \"%s() -> %u\\n\", __FUNCTION__, shared->screen_id );\n\n     if (ret_id)\n          *ret_id = shared->screen_id;\n\n     if (ret_desc)\n          *ret_desc = shared->description;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_screen_suspend( CoreScreen *screen )\n{\n     D_ASSERT( screen != NULL );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_screen_resume( CoreScreen *screen )\n{\n     D_ASSERT( screen != NULL );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_screen_set_powermode( CoreScreen         *screen,\n                          DFBScreenPowerMode  mode )\n{\n     const ScreenFuncs *funcs;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->funcs != NULL );\n\n     funcs = screen->funcs;\n\n     if (funcs->SetPowerMode)\n          return funcs->SetPowerMode( screen, screen->driver_data, screen->screen_data, mode );\n\n     return DFB_UNSUPPORTED;\n}\n\nDFBResult\ndfb_screen_wait_vsync( CoreScreen *screen )\n{\n     const ScreenFuncs *funcs;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->funcs != NULL );\n\n     funcs = screen->funcs;\n\n     if (funcs->WaitVSync)\n          return funcs->WaitVSync( screen, screen->driver_data, screen->screen_data );\n\n     return DFB_UNSUPPORTED;\n}\n\nDFBResult\ndfb_screen_get_vsync_count( CoreScreen    *screen,\n                            unsigned long *ret_count )\n{\n     const ScreenFuncs *funcs;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->funcs != NULL );\n     D_ASSERT( ret_count != NULL );\n\n     funcs = screen->funcs;\n\n     if (funcs->GetVSyncCount)\n          return funcs->GetVSyncCount( screen, screen->driver_data, screen->screen_data, ret_count );\n\n     return DFB_UNSUPPORTED;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_screen_get_mixer_info( CoreScreen                *screen,\n                           int                        mixer,\n                           DFBScreenMixerDescription *ret_desc )\n{\n     CoreScreenShared *shared;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->shared != NULL );\n\n     shared = screen->shared;\n\n     D_ASSERT( mixer >= 0 );\n     D_ASSERT( mixer < shared->description.mixers );\n     D_ASSERT( ret_desc != NULL );\n\n     /* Return mixer description. */\n     *ret_desc = shared->mixers[mixer].description;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_screen_get_mixer_config( CoreScreen           *screen,\n                             int                   mixer,\n                             DFBScreenMixerConfig *ret_config )\n{\n     CoreScreenShared *shared;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->shared != NULL );\n\n     shared = screen->shared;\n\n     D_ASSERT( mixer >= 0 );\n     D_ASSERT( mixer < shared->description.mixers );\n     D_ASSERT( ret_config != NULL );\n\n     /* Return current mixer configuration. */\n     *ret_config = shared->mixers[mixer].configuration;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_screen_test_mixer_config( CoreScreen                 *screen,\n                              int                         mixer,\n                              const DFBScreenMixerConfig *config,\n                              DFBScreenMixerConfigFlags  *ret_failed )\n{\n     DFBResult                  ret;\n     CoreScreenShared          *shared;\n     const ScreenFuncs         *funcs;\n     DFBScreenMixerConfigFlags  failed = DSMCONF_NONE;\n\n     D_UNUSED_P( shared );\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->shared != NULL );\n     D_ASSERT( screen->funcs != NULL );\n     D_ASSERT( screen->funcs->TestMixerConfig != NULL );\n\n     shared = screen->shared;\n     funcs  = screen->funcs;\n\n     D_ASSERT( mixer >= 0 );\n     D_ASSERT( mixer < shared->description.mixers );\n     D_ASSERT( config != NULL );\n     D_ASSERT( config->flags == shared->mixers[mixer].configuration.flags );\n\n     /* Test the mixer configuration. */\n     ret = funcs->TestMixerConfig( screen, screen->driver_data, screen->screen_data, mixer, config, &failed );\n\n     D_ASSUME( (ret == DFB_OK && !failed) || (ret != DFB_OK) );\n\n     if (ret_failed)\n          *ret_failed = failed;\n\n     return ret;\n}\n\nDFBResult\ndfb_screen_set_mixer_config( CoreScreen                 *screen,\n                             int                         mixer,\n                             const DFBScreenMixerConfig *config )\n{\n     DFBResult                  ret;\n     CoreScreenShared          *shared;\n     const ScreenFuncs         *funcs;\n     DFBScreenMixerConfigFlags  failed = DSOCONF_NONE;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->shared != NULL );\n     D_ASSERT( screen->funcs != NULL );\n     D_ASSERT( screen->funcs->TestMixerConfig != NULL );\n     D_ASSERT( screen->funcs->SetMixerConfig != NULL );\n\n     shared = screen->shared;\n     funcs  = screen->funcs;\n\n     D_ASSERT( mixer >= 0 );\n     D_ASSERT( mixer < shared->description.mixers );\n     D_ASSERT( config != NULL );\n     D_ASSERT( config->flags == shared->mixers[mixer].configuration.flags );\n\n     /* Test configuration first. */\n     ret = funcs->TestMixerConfig( screen, screen->driver_data, screen->screen_data, mixer, config, &failed );\n\n     D_ASSUME( (ret == DFB_OK && !failed) || (ret != DFB_OK && failed) );\n\n     if (ret)\n          return ret;\n\n     /* Set configuration afterwards. */\n     ret = funcs->SetMixerConfig( screen, screen->driver_data, screen->screen_data, mixer, config );\n     if (ret)\n          return ret;\n\n     /* Store current configuration. */\n     shared->mixers[mixer].configuration = *config;\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_screen_get_encoder_info( CoreScreen                  *screen,\n                             int                          encoder,\n                             DFBScreenEncoderDescription *ret_desc )\n{\n     CoreScreenShared *shared;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->shared != NULL );\n\n     shared = screen->shared;\n\n     D_ASSERT( encoder >= 0 );\n     D_ASSERT( encoder < shared->description.encoders );\n     D_ASSERT( ret_desc != NULL );\n\n     /* Return encoder description. */\n     *ret_desc = shared->encoders[encoder].description;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_screen_get_encoder_config( CoreScreen             *screen,\n                               int                     encoder,\n                               DFBScreenEncoderConfig *ret_config )\n{\n     CoreScreenShared *shared;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->shared != NULL );\n\n     shared = screen->shared;\n\n     D_ASSERT( encoder >= 0 );\n     D_ASSERT( encoder < shared->description.encoders );\n     D_ASSERT( ret_config != NULL );\n\n     /* Return current encoder configuration. */\n     *ret_config = shared->encoders[encoder].configuration;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_screen_test_encoder_config( CoreScreen                   *screen,\n                                int                           encoder,\n                                const DFBScreenEncoderConfig *config,\n                                DFBScreenEncoderConfigFlags  *ret_failed )\n{\n     DFBResult                    ret;\n     CoreScreenShared            *shared;\n     const ScreenFuncs           *funcs;\n     DFBScreenEncoderConfigFlags  failed = DSECONF_NONE;\n\n     D_UNUSED_P( shared );\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->shared != NULL );\n     D_ASSERT( screen->funcs != NULL );\n     D_ASSERT( screen->funcs->TestEncoderConfig != NULL );\n\n     shared = screen->shared;\n     funcs  = screen->funcs;\n\n     D_ASSERT( encoder >= 0 );\n     D_ASSERT( encoder < shared->description.encoders );\n     D_ASSERT( config != NULL );\n     D_ASSERT( config->flags == shared->encoders[encoder].configuration.flags );\n\n     /* Test the encoder configuration. */\n     ret = funcs->TestEncoderConfig( screen, screen->driver_data, screen->screen_data, encoder, config, &failed );\n\n     D_ASSUME( (ret == DFB_OK && !failed) || (ret != DFB_OK && failed) );\n\n     if (ret_failed)\n          *ret_failed = failed;\n\n     return ret;\n}\n\nDFBResult\ndfb_screen_set_encoder_config( CoreScreen                   *screen,\n                               int                           encoder,\n                               const DFBScreenEncoderConfig *config )\n{\n     DFBResult                    ret;\n     CoreScreenShared            *shared;\n     const ScreenFuncs           *funcs;\n     DFBScreenEncoderConfigFlags  failed = DSECONF_NONE;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->shared != NULL );\n     D_ASSERT( screen->funcs != NULL );\n     D_ASSERT( screen->funcs->TestEncoderConfig != NULL );\n     D_ASSERT( screen->funcs->SetEncoderConfig != NULL );\n\n     shared = screen->shared;\n     funcs  = screen->funcs;\n\n     D_ASSERT( encoder >= 0 );\n     D_ASSERT( encoder < shared->description.encoders );\n     D_ASSERT( config != NULL );\n     D_ASSERT( config->flags == shared->encoders[encoder].configuration.flags );\n\n     /* Test configuration first. */\n     ret = funcs->TestEncoderConfig( screen, screen->driver_data, screen->screen_data, encoder, config, &failed );\n\n     D_ASSUME( (ret == DFB_OK && !failed) || (ret != DFB_OK && failed) );\n\n     if (ret)\n          return ret;\n\n     /* Set configuration afterwards. */\n     ret = funcs->SetEncoderConfig( screen, screen->driver_data, screen->screen_data, encoder, config );\n     if (ret)\n          return ret;\n\n     /* Store current configuration. */\n     shared->encoders[encoder].configuration = *config;\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_screen_get_output_info( CoreScreen                 *screen,\n                            int                         output,\n                            DFBScreenOutputDescription *ret_desc )\n{\n     CoreScreenShared *shared;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->shared != NULL );\n\n     shared = screen->shared;\n\n     D_ASSERT( output >= 0 );\n     D_ASSERT( output < shared->description.outputs );\n     D_ASSERT( ret_desc != NULL );\n\n     /* Return output description. */\n     *ret_desc = shared->outputs[output].description;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_screen_get_output_config( CoreScreen            *screen,\n                              int                    output,\n                              DFBScreenOutputConfig *ret_config )\n{\n     CoreScreenShared *shared;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->shared != NULL );\n\n     shared = screen->shared;\n\n     D_ASSERT( output >= 0 );\n     D_ASSERT( output < shared->description.outputs );\n     D_ASSERT( ret_config != NULL );\n\n     /* Return current output configuration. */\n     *ret_config = shared->outputs[output].configuration;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_screen_test_output_config( CoreScreen                  *screen,\n                               int                          output,\n                               const DFBScreenOutputConfig *config,\n                               DFBScreenOutputConfigFlags  *ret_failed )\n{\n     DFBResult                   ret;\n     CoreScreenShared           *shared;\n     const ScreenFuncs          *funcs;\n     DFBScreenOutputConfigFlags  failed = DSOCONF_NONE;\n\n     D_UNUSED_P( shared );\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->shared != NULL );\n     D_ASSERT( screen->funcs != NULL );\n     D_ASSERT( screen->funcs->TestOutputConfig != NULL );\n\n     shared = screen->shared;\n     funcs  = screen->funcs;\n\n     D_ASSERT( output >= 0 );\n     D_ASSERT( output < shared->description.outputs );\n     D_ASSERT( config != NULL );\n     D_ASSERT( config->flags == shared->outputs[output].configuration.flags );\n\n     /* Test the output configuration. */\n     ret = funcs->TestOutputConfig( screen, screen->driver_data, screen->screen_data, output, config, &failed );\n\n     D_ASSUME( (ret == DFB_OK && !failed) || (ret != DFB_OK && failed) );\n\n     if (ret_failed)\n          *ret_failed = failed;\n\n     return ret;\n}\n\nDFBResult\ndfb_screen_set_output_config( CoreScreen                  *screen,\n                              int                          output,\n                              const DFBScreenOutputConfig *config )\n{\n     DFBResult                   ret;\n     CoreScreenShared           *shared;\n     const ScreenFuncs          *funcs;\n     DFBScreenOutputConfigFlags  failed = DSOCONF_NONE;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->shared != NULL );\n     D_ASSERT( screen->funcs != NULL );\n     D_ASSERT( screen->funcs->TestOutputConfig != NULL );\n     D_ASSERT( screen->funcs->SetOutputConfig != NULL );\n\n     shared = screen->shared;\n     funcs  = screen->funcs;\n\n     D_ASSERT( output >= 0 );\n     D_ASSERT( output < shared->description.outputs );\n     D_ASSERT( config != NULL );\n     D_ASSERT( config->flags == shared->outputs[output].configuration.flags );\n\n     /* Test configuration first. */\n     ret = funcs->TestOutputConfig( screen, screen->driver_data, screen->screen_data, output, config, &failed );\n\n     D_ASSUME( (ret == DFB_OK && !failed) || (ret != DFB_OK && failed) );\n\n     if (ret)\n          return ret;\n\n     /* Set configuration afterwards. */\n     ret = funcs->SetOutputConfig( screen, screen->driver_data, screen->screen_data, output, config );\n     if (ret)\n          return ret;\n\n     /* Store current configuration. */\n     shared->outputs[output].configuration = *config;\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_screen_get_screen_size( CoreScreen *screen,\n                            int        *ret_width,\n                            int        *ret_height )\n{\n     const ScreenFuncs *funcs;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->funcs != NULL );\n     D_ASSERT( screen->funcs->GetScreenSize != NULL );\n     D_ASSERT( ret_width != NULL );\n     D_ASSERT( ret_height != NULL );\n\n     funcs = screen->funcs;\n\n     return funcs->GetScreenSize( screen, screen->driver_data, screen->screen_data, ret_width, ret_height );\n}\n\nDFBResult\ndfb_screen_get_layer_dimension( CoreScreen *screen,\n                                CoreLayer  *layer,\n                                int        *ret_width,\n                                int        *ret_height )\n{\n     int                i;\n     DFBResult          ret = DFB_UNSUPPORTED;\n     CoreScreenShared  *shared;\n     const ScreenFuncs *funcs;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->shared != NULL );\n     D_ASSERT( screen->funcs != NULL );\n     D_ASSERT( layer != NULL );\n     D_ASSERT( ret_width != NULL );\n     D_ASSERT( ret_height != NULL );\n\n     shared = screen->shared;\n     funcs  = screen->funcs;\n\n     if (funcs->GetMixerState) {\n          for (i = 0; i < shared->description.mixers; i++) {\n               const DFBScreenMixerConfig *config = &shared->mixers[i].configuration;\n\n               if ((config->flags & DSMCONF_LAYERS) &&\n                   DFB_DISPLAYLAYER_IDS_HAVE( config->layers, dfb_layer_id( layer ) )) {\n                    CoreMixerState state;\n\n                    ret = funcs->GetMixerState( screen, screen->driver_data, screen->screen_data, i, &state );\n                    if (ret == DFB_OK) {\n                         if (state.flags & CMSF_DIMENSION) {\n                              *ret_width  = state.dimension.w;\n                              *ret_height = state.dimension.h;\n\n                              return DFB_OK;\n                         }\n\n                         ret = DFB_UNSUPPORTED;\n                    }\n               }\n          }\n\n          for (i = 0; i < shared->description.mixers; i++) {\n               const DFBScreenMixerDescription *desc = &shared->mixers[i].description;\n\n               if ((desc->caps & DSMCAPS_SUB_LAYERS) &&\n                   DFB_DISPLAYLAYER_IDS_HAVE( desc->sub_layers, dfb_layer_id( layer ) )) {\n                    CoreMixerState state;\n\n                    ret = funcs->GetMixerState( screen, screen->driver_data, screen->screen_data, i, &state );\n                    if (ret == DFB_OK) {\n                         if (state.flags & CMSF_DIMENSION) {\n                              *ret_width  = state.dimension.w;\n                              *ret_height = state.dimension.h;\n\n                              return DFB_OK;\n                         }\n\n                         ret = DFB_UNSUPPORTED;\n                    }\n               }\n          }\n     }\n\n     if (funcs->GetScreenSize)\n          ret = funcs->GetScreenSize( screen, screen->driver_data, screen->screen_data, ret_width, ret_height );\n\n     return ret;\n}\n\nDFBResult\ndfb_screen_get_frame_interval( CoreScreen *screen,\n                               long long  *ret_micros )\n{\n     CoreScreenShared *shared;\n     long long         interval = dfb_config->screen_frame_interval;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->shared != NULL );\n     D_ASSERT( screen->funcs != NULL );\n\n     shared = screen->shared;\n\n     if (shared->description.encoders) {\n          const DFBScreenEncoderConfig *config = &shared->encoders[0].configuration;\n\n          if (config->flags & DSECONF_FREQUENCY) {\n               switch (config->frequency) {\n                    case DSEF_25HZ:\n                         interval = 1000000000LL / 25000LL;\n                         break;\n\n                    case DSEF_29_97HZ:\n                         interval = 1000000000LL / 29970LL;\n                         break;\n\n                    case DSEF_50HZ:\n                         interval = 1000000000LL / 50000LL;\n                         break;\n\n                    case DSEF_59_94HZ:\n                         interval = 1000000000LL / 59940LL;\n                         break;\n\n                    case DSEF_60HZ:\n                         interval = 1000000000LL / 60000LL;\n                         break;\n\n                    case DSEF_75HZ:\n                         interval = 1000000000LL / 75000LL;\n                         break;\n\n                    case DSEF_30HZ:\n                         interval = 1000000000LL / 30000LL;\n                         break;\n\n                    case DSEF_24HZ:\n                         interval = 1000000000LL / 24000LL;\n                         break;\n\n                    case DSEF_23_976HZ:\n                         interval = 1000000000LL / 23976LL;\n                         break;\n\n                    default:\n                         break;\n               }\n          }\n     }\n\n     *ret_micros = interval;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_screen_get_rotation( CoreScreen *screen,\n                         int        *ret_rotation )\n{\n     const ScreenFuncs *funcs;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->funcs != NULL );\n     D_ASSERT( ret_rotation != NULL );\n\n     funcs = screen->funcs;\n\n     if (!funcs->GetScreenRotation) {\n          *ret_rotation = 0;\n          return DFB_OK;\n     }\n\n     return funcs->GetScreenRotation( screen, screen->driver_data, screen->screen_data, ret_rotation );\n}\n"
  },
  {
    "path": "src/core/screen.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__SCREEN_H__\n#define __CORE__SCREEN_H__\n\n#include <core/coretypes.h>\n\n/**********************************************************************************************************************/\n\n/*\n * Misc.\n */\n\nDFBResult dfb_screen_get_info           ( CoreScreen                   *screen,\n                                          DFBScreenID                  *ret_id,\n                                          DFBScreenDescription         *ret_desc );\n\nDFBResult dfb_screen_suspend            ( CoreScreen                   *screen );\n\nDFBResult dfb_screen_resume             ( CoreScreen                   *screen );\n\nDFBResult dfb_screen_set_powermode      ( CoreScreen                   *screen,\n                                          DFBScreenPowerMode            mode );\n\nDFBResult dfb_screen_wait_vsync         ( CoreScreen                   *screen );\n\nDFBResult dfb_screen_get_vsync_count    ( CoreScreen                   *screen,\n                                          unsigned long                *ret_count );\n\n/*\n * Mixers.\n */\n\nDFBResult dfb_screen_get_mixer_info     ( CoreScreen                   *screen,\n                                          int                           mixer,\n                                          DFBScreenMixerDescription    *ret_desc );\n\nDFBResult dfb_screen_get_mixer_config   ( CoreScreen                   *screen,\n                                          int                           mixer,\n                                          DFBScreenMixerConfig         *ret_config );\n\nDFBResult dfb_screen_test_mixer_config  ( CoreScreen                   *screen,\n                                          int                           mixer,\n                                          const DFBScreenMixerConfig   *config,\n                                          DFBScreenMixerConfigFlags    *ret_failed );\n\nDFBResult dfb_screen_set_mixer_config   ( CoreScreen                   *screen,\n                                          int                           mixer,\n                                          const DFBScreenMixerConfig   *config );\n\n/*\n * Encoders.\n */\n\nDFBResult dfb_screen_get_encoder_info   ( CoreScreen                   *screen,\n                                          int                           encoder,\n                                          DFBScreenEncoderDescription  *ret_desc );\n\nDFBResult dfb_screen_get_encoder_config ( CoreScreen                   *screen,\n                                          int                           encoder,\n                                          DFBScreenEncoderConfig       *ret_config );\n\nDFBResult dfb_screen_test_encoder_config( CoreScreen                   *screen,\n                                          int                           encoder,\n                                          const DFBScreenEncoderConfig *config,\n                                          DFBScreenEncoderConfigFlags  *ret_failed );\n\nDFBResult dfb_screen_set_encoder_config ( CoreScreen                   *screen,\n                                          int                           encoder,\n                                          const DFBScreenEncoderConfig *config );\n\n/*\n * Outputs.\n */\n\nDFBResult dfb_screen_get_output_info    ( CoreScreen                   *screen,\n                                          int                           output,\n                                          DFBScreenOutputDescription   *ret_desc );\n\nDFBResult dfb_screen_get_output_config  ( CoreScreen                   *screen,\n                                          int                           output,\n                                          DFBScreenOutputConfig        *ret_config );\n\nDFBResult dfb_screen_test_output_config ( CoreScreen                   *screen,\n                                          int                           output,\n                                          const DFBScreenOutputConfig  *config,\n                                          DFBScreenOutputConfigFlags   *ret_failed );\n\nDFBResult dfb_screen_set_output_config  ( CoreScreen                   *screen,\n                                          int                           output,\n                                          const DFBScreenOutputConfig  *config );\n\n/*\n * Screen configuration.\n */\n\nDFBResult dfb_screen_get_screen_size    ( CoreScreen                   *screen,\n                                          int                          *ret_width,\n                                          int                          *ret_height );\n\nDFBResult dfb_screen_get_layer_dimension( CoreScreen                   *screen,\n                                          CoreLayer                    *layer,\n                                          int                          *ret_width,\n                                          int                          *ret_height );\n\nDFBResult dfb_screen_get_frame_interval ( CoreScreen                   *screen,\n                                          long long                    *ret_micros );\n\nDFBResult dfb_screen_get_rotation       ( CoreScreen                   *screen,\n                                          int                          *ret_rotation );\n\n#endif\n"
  },
  {
    "path": "src/core/screens.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreScreen.h>\n#include <core/core.h>\n#include <core/core_parts.h>\n#include <core/layers.h>\n#include <core/screen.h>\n#include <core/screens.h>\n#include <direct/memcpy.h>\n#include <fusion/conf.h>\n#include <fusion/shmalloc.h>\n\nD_DEBUG_DOMAIN( Core_Screens, \"Core/Screens\", \"DirectFB Core Screens\" );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int               magic;\n\n     int               num;\n     CoreScreenShared *screens[MAX_SCREENS];\n} DFBScreenCoreShared;\n\ntypedef struct {\n     int                  magic;\n\n     CoreDFB             *core;\n\n     DFBScreenCoreShared *shared;\n} DFBScreenCore;\n\nDFB_CORE_PART( screen_core, ScreenCore );\n\n/**********************************************************************************************************************/\n\nstatic int         num_screens = 0;\nstatic CoreScreen *screens[MAX_SCREENS];\n\nstatic DFBResult\ndfb_screen_core_initialize( CoreDFB             *core,\n                            DFBScreenCore       *data,\n                            DFBScreenCoreShared *shared )\n{\n     DFBResult            ret;\n     FusionSHMPoolShared *pool;\n     int                  i;\n\n     D_DEBUG_AT( Core_Screens, \"%s( %p, %p, %p )\\n\", __FUNCTION__, core, data, shared );\n\n     D_ASSERT( data != NULL );\n     D_ASSERT( shared != NULL );\n\n     data->core   = core;\n     data->shared = shared;\n\n     pool = dfb_core_shmpool( core );\n\n     /* Initialize all registered screens. */\n     for (i = 0; i < num_screens; i++) {\n          CoreScreen           *screen = screens[i];\n          CoreScreenShared     *sshared;\n          const ScreenFuncs    *funcs  = screen->funcs;\n          DFBScreenDescription  desc   = { .caps = DSCCAPS_NONE };\n          char                  buf[24];\n\n          /* Allocate shared data. */\n          sshared = SHCALLOC( pool, 1, sizeof(CoreScreenShared) );\n\n          /* Assign ID (zero based index). */\n          sshared->screen_id = i;\n\n          snprintf( buf, sizeof(buf), \"Screen %d\", i );\n\n          /* Initialize the lock. */\n          if (fusion_skirmish_init2( &sshared->lock, buf, dfb_core_world( core ), fusion_config->secure_fusion )) {\n               SHFREE( pool, sshared );\n               return DFB_FUSION;\n          }\n\n          /* Allocate driver's screen data. */\n          if (funcs->ScreenDataSize) {\n               int size = funcs->ScreenDataSize();\n\n               if (size > 0) {\n                    sshared->screen_data = SHCALLOC( pool, 1, size );\n                    if (!sshared->screen_data) {\n                         fusion_skirmish_destroy( &sshared->lock );\n                         SHFREE( pool, sshared );\n                         return D_OOSHM();\n                    }\n               }\n          }\n\n          /* Initialize the screen and get the screen description. */\n          ret = funcs->InitScreen( screen, screen->driver_data, sshared->screen_data, &desc );\n          if (ret) {\n               D_ERROR( \"Core/Screens: Failed to initialize screen %u!\\n\", sshared->screen_id );\n\n               fusion_skirmish_destroy( &sshared->lock );\n\n               if (sshared->screen_data)\n                    SHFREE( pool, sshared->screen_data );\n\n               SHFREE( pool, sshared );\n\n               return ret;\n          }\n\n          D_ASSUME( desc.mixers  > 0 || !(desc.caps & DSCCAPS_MIXERS) );\n          D_ASSUME( desc.mixers == 0 ||  (desc.caps & DSCCAPS_MIXERS) );\n          D_ASSUME( desc.encoders  > 0 || !(desc.caps & DSCCAPS_ENCODERS) );\n          D_ASSUME( desc.encoders == 0 ||  (desc.caps & DSCCAPS_ENCODERS) );\n          D_ASSUME( desc.outputs  > 0 || !(desc.caps & DSCCAPS_OUTPUTS) );\n          D_ASSUME( desc.outputs == 0 ||  (desc.caps & DSCCAPS_OUTPUTS) );\n\n          D_ASSERT( desc.mixers >= 0 );\n          D_ASSERT( desc.mixers <= 32 );\n          D_ASSERT( desc.encoders >= 0 );\n          D_ASSERT( desc.encoders <= 32 );\n          D_ASSERT( desc.outputs >= 0 );\n          D_ASSERT( desc.outputs <= 32 );\n\n          /* Store description in sshared memory. */\n          sshared->description = desc;\n\n          /* Initialize mixers. */\n          if (sshared->description.mixers) {\n               int mixer;\n\n               D_ASSERT( funcs->InitMixer != NULL );\n               D_ASSERT( funcs->SetMixerConfig != NULL );\n\n               sshared->mixers = SHCALLOC( pool, sshared->description.mixers, sizeof(CoreScreenMixer) );\n\n               for (mixer = 0; mixer < sshared->description.mixers; mixer++) {\n                    funcs->InitMixer( screen, screen->driver_data, sshared->screen_data, mixer,\n                                      &sshared->mixers[mixer].description,\n                                      &sshared->mixers[mixer].configuration );\n\n                    funcs->SetMixerConfig( screen, screen->driver_data, sshared->screen_data, mixer,\n                                           &sshared->mixers[mixer].configuration );\n               }\n          }\n\n          /* Initialize encoders. */\n          if (sshared->description.encoders) {\n               int encoder;\n\n               D_ASSERT( funcs->InitEncoder != NULL );\n               D_ASSERT( funcs->SetEncoderConfig != NULL );\n\n               sshared->encoders = SHCALLOC( pool, sshared->description.encoders, sizeof(CoreScreenEncoder) );\n\n               for (encoder = 0; encoder < sshared->description.encoders; encoder++) {\n                    funcs->InitEncoder( screen, screen->driver_data, sshared->screen_data, encoder,\n                                        &sshared->encoders[encoder].description,\n                                        &sshared->encoders[encoder].configuration );\n\n                    funcs->SetEncoderConfig( screen, screen->driver_data, sshared->screen_data, encoder,\n                                             &sshared->encoders[encoder].configuration );\n               }\n          }\n\n          /* Initialize outputs. */\n          if (sshared->description.outputs) {\n               int output;\n\n               D_ASSERT( funcs->InitOutput != NULL );\n               D_ASSERT( funcs->SetOutputConfig != NULL );\n\n               sshared->outputs = SHCALLOC( pool, sshared->description.outputs, sizeof(CoreScreenOutput) );\n\n               for (output = 0; output < sshared->description.outputs; output++) {\n                    funcs->InitOutput( screen, screen->driver_data, sshared->screen_data, output,\n                                       &sshared->outputs[output].description,\n                                       &sshared->outputs[output].configuration );\n\n                    funcs->SetOutputConfig( screen, screen->driver_data, sshared->screen_data, output,\n                                            &sshared->outputs[output].configuration );\n               }\n          }\n\n          /* Make a copy for faster access. */\n          screen->screen_data = sshared->screen_data;\n\n          /* Store pointer to shared data and core. */\n          screen->shared = sshared;\n          screen->core   = core;\n\n          CoreScreen_Init_Dispatch( core, screen, &sshared->call );\n\n          fusion_call_add_permissions( &sshared->call, 0, FUSION_CALL_PERMIT_EXECUTE );\n\n          /* Add the screen to the shared list. */\n          shared->screens[shared->num++] = sshared;\n     }\n\n     D_MAGIC_SET( data, DFBScreenCore );\n     D_MAGIC_SET( shared, DFBScreenCoreShared );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_screen_core_join( CoreDFB             *core,\n                      DFBScreenCore       *data,\n                      DFBScreenCoreShared *shared )\n{\n     int i;\n\n     D_DEBUG_AT( Core_Screens, \"%s( %p, %p, %p )\\n\", __FUNCTION__, core, data, shared );\n\n     D_ASSERT( data != NULL );\n     D_MAGIC_ASSERT( shared, DFBScreenCoreShared );\n\n     data->core   = core;\n     data->shared = shared;\n\n     if (num_screens != shared->num) {\n          D_ERROR( \"Core/Screens: Number of screens does not match!\\n\" );\n          return DFB_BUG;\n     }\n\n     for (i = 0; i < num_screens; i++) {\n          CoreScreen       *screen  = screens[i];\n          CoreScreenShared *sshared = shared->screens[i];\n\n          /* Make a copy for faster access. */\n          screen->screen_data = sshared->screen_data;\n\n          /* Store pointer to shared data and core. */\n          screen->shared = sshared;\n          screen->core   = core;\n     }\n\n     D_MAGIC_SET( data, DFBScreenCore );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_screen_core_shutdown( DFBScreenCore *data,\n                          bool           emergency )\n{\n     DFBScreenCoreShared *shared;\n     FusionSHMPoolShared *pool;\n     int                  i;\n\n     D_UNUSED_P( shared );\n\n     D_DEBUG_AT( Core_Screens, \"%s( %p, %semergency )\\n\", __FUNCTION__, data, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( data, DFBScreenCore );\n     D_MAGIC_ASSERT( data->shared, DFBScreenCoreShared );\n\n     shared = data->shared;\n\n     pool = dfb_core_shmpool( data->core );\n\n     /* Begin with the most recently added screen. */\n     for (i = num_screens - 1; i >= 0; i--) {\n          CoreScreen        *screen  = screens[i];\n          CoreScreenShared  *sshared = screen->shared;\n          const ScreenFuncs *funcs   = screen->funcs;\n\n          /* Shut the screen down. */\n          if (funcs->ShutdownScreen)\n               if (funcs->ShutdownScreen( screen, screen->driver_data, sshared->screen_data ))\n                    D_ERROR( \"Core/Screens: Failed to shutdown screen %u!\\n\", sshared->screen_id );\n\n          CoreScreen_Deinit_Dispatch( &sshared->call );\n\n          /* Deinitialize the lock. */\n          fusion_skirmish_destroy( &sshared->lock );\n\n          /* Free the driver's screen data. */\n          if (sshared->screen_data)\n               SHFREE( pool, sshared->screen_data );\n\n          /* Free mixer data. */\n          if (sshared->mixers)\n               SHFREE( pool, sshared->mixers );\n\n          /* Free encoder data. */\n          if (sshared->encoders)\n               SHFREE( pool, sshared->encoders );\n\n          /* Free output data. */\n          if (sshared->outputs)\n               SHFREE( pool, sshared->outputs );\n\n          /* Free the shared screen data. */\n          SHFREE( pool, sshared );\n\n          /* Free the local screen data. */\n          D_FREE( screen );\n     }\n\n     num_screens  = 0;\n\n     D_MAGIC_CLEAR( data );\n     D_MAGIC_CLEAR( shared );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_screen_core_leave( DFBScreenCore *data,\n                       bool           emergency )\n{\n     int i;\n\n     D_DEBUG_AT( Core_Screens, \"%s( %p, %semergency )\\n\", __FUNCTION__, data, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( data, DFBScreenCore );\n     D_MAGIC_ASSERT( data->shared, DFBScreenCoreShared );\n\n     /* Deinitialize all local stuff only. */\n     for (i = 0; i < num_screens; i++) {\n          CoreScreen *screen = screens[i];\n\n          /* Free local screen data. */\n          D_FREE( screen );\n     }\n\n     num_screens  = 0;\n\n     D_MAGIC_CLEAR( data );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_screen_core_suspend( DFBScreenCore *data )\n{\n     int i;\n\n     D_DEBUG_AT( Core_Screens, \"%s( %p )\\n\", __FUNCTION__, data );\n\n     D_MAGIC_ASSERT( data, DFBScreenCore );\n     D_MAGIC_ASSERT( data->shared, DFBScreenCoreShared );\n\n     for (i = num_screens - 1; i >= 0; i--)\n          dfb_screen_suspend( screens[i] );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_screen_core_resume( DFBScreenCore *data )\n{\n     int i;\n\n     D_DEBUG_AT( Core_Screens, \"%s( %p )\\n\", __FUNCTION__, data );\n\n     D_MAGIC_ASSERT( data, DFBScreenCore );\n     D_MAGIC_ASSERT( data->shared, DFBScreenCoreShared );\n\n     for (i = 0; i < num_screens; i++)\n          dfb_screen_resume( screens[i] );\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nCoreScreen *\ndfb_screens_register( void              *driver_data,\n                      const ScreenFuncs *funcs )\n{\n     CoreScreen *screen;\n\n     D_ASSERT( funcs != NULL );\n\n     if (num_screens == MAX_SCREENS) {\n          D_ERROR( \"Core/Screens: Maximum number of screens reached!\\n\" );\n          return NULL;\n     }\n\n     /* Allocate local data. */\n     screen = D_CALLOC( 1, sizeof(CoreScreen) );\n\n     /* Assign local pointers. */\n     screen->driver_data = driver_data;\n     screen->funcs       = funcs;\n\n     /* Add it to the local list. */\n     screens[num_screens++] = screen;\n\n     return screen;\n}\n\ntypedef void (*AnyFunc)( void );\n\nCoreScreen *\ndfb_screens_hook_primary( void         *driver_data,\n                          ScreenFuncs  *funcs,\n                          ScreenFuncs  *primary_funcs,\n                          void        **primary_driver_data )\n{\n     int         i;\n     int         entries;\n     CoreScreen *primary = screens[0];\n\n     D_ASSERT( primary != NULL );\n     D_ASSERT( funcs != NULL );\n\n     /* Copy content of original function table. */\n     if (primary_funcs)\n          direct_memcpy( primary_funcs, primary->funcs, sizeof(ScreenFuncs) );\n\n     /* Copy pointer to original driver data. */\n     if (primary_driver_data)\n          *primary_driver_data = primary->driver_data;\n\n     /* Replace all entries in the old table that aren't NULL in the new one. */\n     entries = sizeof(ScreenFuncs) / sizeof(void (*)( void ));\n     for (i = 0; i < entries; i++) {\n          AnyFunc *newfuncs = (AnyFunc*) funcs;\n          AnyFunc *oldfuncs = (AnyFunc*) primary->funcs;\n\n          if (newfuncs[i])\n               oldfuncs[i] = newfuncs[i];\n     }\n\n     /* Replace device and driver data pointer. */\n     primary->driver_data = driver_data;\n\n     return primary;\n}\n\nvoid\ndfb_screens_enumerate( CoreScreenCallback  callback,\n                       void               *ctx )\n{\n     int i;\n\n     D_ASSERT( callback != NULL );\n\n     for (i = 0; i < num_screens; i++) {\n          if (callback( screens[i], ctx ) == DFENUM_CANCEL)\n               break;\n     }\n}\n\nunsigned int\ndfb_screens_num()\n{\n     return num_screens;\n}\n\nCoreScreen *\ndfb_screen_at( DFBScreenID screen_id )\n{\n     D_ASSERT( screen_id >= 0 );\n     D_ASSERT( screen_id < num_screens );\n\n     return screens[screen_id];\n}\n\nCoreScreen *\ndfb_screen_at_translated( DFBScreenID screen_id )\n{\n     CoreScreen *primary;\n\n     D_ASSERT( screen_id >= 0 );\n     D_ASSERT( screen_id < num_screens );\n\n     if (dfb_config->primary_layer > 0) {\n          primary = dfb_layer_at_translated( DLID_PRIMARY )->screen ;\n\n          if (screen_id == DSCID_PRIMARY)\n               return primary;\n\n          if (screen_id == primary->shared->screen_id)\n               return dfb_screen_at( DSCID_PRIMARY );\n     }\n\n     return dfb_screen_at( screen_id );\n}\n\nDFBScreenID\ndfb_screen_id( const CoreScreen *screen )\n{\n     CoreScreenShared *shared;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->shared != NULL );\n\n     shared = screen->shared;\n\n     return shared->screen_id;\n}\n\nDFBScreenID\ndfb_screen_id_translated( const CoreScreen *screen )\n{\n     CoreScreenShared *shared;\n     CoreScreen       *primary;\n\n     D_ASSERT( screen != NULL );\n     D_ASSERT( screen->shared != NULL );\n\n     shared = screen->shared;\n\n     if (dfb_config->primary_layer > 0) {\n          primary = dfb_layer_at_translated( DLID_PRIMARY )->screen;\n\n          if (shared->screen_id == DSCID_PRIMARY)\n               return primary->shared->screen_id;\n\n          if (shared->screen_id == primary->shared->screen_id)\n               return DSCID_PRIMARY;\n     }\n\n     return shared->screen_id;\n}\n"
  },
  {
    "path": "src/core/screens.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__SCREENS_H__\n#define __CORE__SCREENS_H__\n\n#include <core/coretypes.h>\n#include <fusion/call.h>\n#include <fusion/lock.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CMSF_NONE      = 0x00000000, /* none of these */\n\n     CMSF_DIMENSION = 0x00000001, /* dimension is set */\n\n     CMSF_ALL       = 0x00000001, /* all of these */\n} CoreMixerStateFlags;\n\ntypedef struct {\n     CoreMixerStateFlags flags;\n\n     DFBDimension        dimension;\n} CoreMixerState;\n\ntypedef struct {\n     /*\n      * Return size of screen data (shared memory).\n      */\n     int       (*ScreenDataSize)   ( void );\n\n     /*\n      * Called once by the master to initialize screen data and reset hardware.\n      * Return screen description.\n      */\n     DFBResult (*InitScreen)       ( CoreScreen                   *screen,\n                                     void                         *driver_data,\n                                     void                         *screen_data,\n                                     DFBScreenDescription         *description );\n\n     /*\n      * Called once by the master to shutdown the screen.\n      * Use this function to free any resources that were taken during init.\n      */\n     DFBResult (*ShutdownScreen)   ( CoreScreen                   *screen,\n                                     void                         *driver_data,\n                                     void                         *screen_data );\n\n     /*\n      * Called once by the master for each mixer.\n      * Driver fills description and default config.\n      */\n     DFBResult (*InitMixer)        ( CoreScreen                   *screen,\n                                     void                         *driver_data,\n                                     void                         *screen_data,\n                                     int                           mixer,\n                                     DFBScreenMixerDescription    *description,\n                                     DFBScreenMixerConfig         *config );\n\n     /*\n      * Called once by the master for each encoder.\n      * Driver fills description and default config.\n      */\n     DFBResult (*InitEncoder)      ( CoreScreen                   *screen,\n                                     void                         *driver_data,\n                                     void                         *screen_data,\n                                     int                           encoder,\n                                     DFBScreenEncoderDescription  *description,\n                                     DFBScreenEncoderConfig       *config );\n\n     /*\n      * Called once by the master for each output.\n      * Driver fills description and default config.\n      */\n     DFBResult (*InitOutput)       ( CoreScreen                   *screen,\n                                     void                         *driver_data,\n                                     void                         *screen_data,\n                                     int                           output,\n                                     DFBScreenOutputDescription   *description,\n                                     DFBScreenOutputConfig        *config );\n\n     /*\n      * Switch between \"on\", \"standby\", \"suspend\" and \"off\".\n      */\n     DFBResult (*SetPowerMode)     ( CoreScreen                   *screen,\n                                     void                         *driver_data,\n                                     void                         *screen_data,\n                                     DFBScreenPowerMode            mode );\n\n     /*\n      * Wait for the vertical retrace.\n      */\n     DFBResult (*WaitVSync)        ( CoreScreen                   *screen,\n                                     void                         *driver_data,\n                                     void                         *screen_data );\n\n     /*\n      * Test if mixer configuration is supported.\n      */\n     DFBResult (*TestMixerConfig)  ( CoreScreen                   *screen,\n                                     void                         *driver_data,\n                                     void                         *screen_data,\n                                     int                           mixer,\n                                     const DFBScreenMixerConfig   *config,\n                                     DFBScreenMixerConfigFlags    *ret_failed );\n\n     /*\n      * Set new mixer configuration.\n      */\n     DFBResult (*SetMixerConfig)   ( CoreScreen                   *screen,\n                                     void                         *driver_data,\n                                     void                         *screen_data,\n                                     int                           mixer,\n                                     const DFBScreenMixerConfig   *config );\n\n     /*\n      * Test if encoder configuration is supported.\n      */\n     DFBResult (*TestEncoderConfig)( CoreScreen                   *screen,\n                                     void                         *driver_data,\n                                     void                         *screen_data,\n                                     int                           encoder,\n                                     const DFBScreenEncoderConfig *config,\n                                     DFBScreenEncoderConfigFlags  *ret_failed );\n\n     /*\n      * Set new encoder configuration.\n      */\n     DFBResult (*SetEncoderConfig) ( CoreScreen                   *screen,\n                                     void                         *driver_data,\n                                     void                         *screen_data,\n                                     int                           encoder,\n                                     const DFBScreenEncoderConfig *config );\n\n     /*\n      * Test if output configuration is supported.\n      */\n     DFBResult (*TestOutputConfig) ( CoreScreen                   *screen,\n                                     void                         *driver_data,\n                                     void                         *screen_data,\n                                     int                           output,\n                                     const DFBScreenOutputConfig  *config,\n                                     DFBScreenOutputConfigFlags   *ret_failed );\n\n     /*\n      * Set new output configuration.\n      */\n     DFBResult (*SetOutputConfig)  ( CoreScreen                   *screen,\n                                     void                         *driver_data,\n                                     void                         *screen_data,\n                                     int                           output,\n                                     const DFBScreenOutputConfig  *config );\n\n     /*\n      * Return the screen size, e.g. as a basis for positioning a layer.\n      */\n     DFBResult (*GetScreenSize)    ( CoreScreen                   *screen,\n                                     void                         *driver_data,\n                                     void                         *screen_data,\n                                     int                          *ret_width,\n                                     int                          *ret_height );\n\n     /*\n      * Return the mixer state.\n      */\n     DFBResult (*GetMixerState)    ( CoreScreen                   *screen,\n                                     void                         *driver_data,\n                                     void                         *screen_data,\n                                     int                           mixer,\n                                     CoreMixerState               *ret_state );\n\n     /*\n      * Return vertical retrace count.\n      */\n     DFBResult (*GetVSyncCount)    ( CoreScreen                   *screen,\n                                     void                         *driver_data,\n                                     void                         *screen_data,\n                                     unsigned long                *ret_count );\n\n     /*\n      * Return the physical screen rotation.\n      */\n     DFBResult (*GetScreenRotation)( CoreScreen                   *screen,\n                                     void                         *driver_data,\n                                     void                         *screen_data,\n                                     int                          *ret_rotation );\n} ScreenFuncs;\n\ntypedef struct {\n     DFBScreenMixerDescription description;\n     DFBScreenMixerConfig      configuration;\n} CoreScreenMixer;\n\ntypedef struct {\n     DFBScreenEncoderDescription description;\n     DFBScreenEncoderConfig      configuration;\n} CoreScreenEncoder;\n\ntypedef struct {\n     DFBScreenOutputDescription  description;\n     DFBScreenOutputConfig       configuration;\n} CoreScreenOutput;\n\ntypedef struct {\n     DFBScreenID           screen_id;\n\n     DFBScreenDescription  description;\n\n     CoreScreenMixer      *mixers;\n     CoreScreenEncoder    *encoders;\n     CoreScreenOutput     *outputs;\n\n     void                 *screen_data; /* local data (impl) */\n\n     FusionSkirmish        lock;\n\n     FusionCall            call;        /* dispatch */\n} CoreScreenShared;\n\nstruct __DFB_CoreScreen {\n     CoreScreenShared  *shared;\n\n     CoreDFB           *core;\n\n     const ScreenFuncs *funcs;\n\n     void              *driver_data;\n     void              *screen_data; /* copy of shared->screen_data */\n};\n\n/**********************************************************************************************************************/\n\ntypedef DFBEnumerationResult (*CoreScreenCallback)( CoreScreen *screen, void *ctx );\n\n/**********************************************************************************************************************/\n\n/*\n * Add a screen to a graphics device by pointing to a table containing driver functions.\n * The supplied 'driver_data' will be passed to these functions.\n */\nCoreScreen   *dfb_screens_register    ( void                *driver_data,\n                                        const ScreenFuncs   *funcs );\n\n/*\n * Replace functions of the primary screen implementation by passing an alternative driver function table.\n * All non-NULL functions in the new table replace the functions in the original function table.\n * The original function table is written to 'primary_funcs' before to allow drivers to use existing functionality\n * from the original implementation.\n */\nCoreScreen   *dfb_screens_hook_primary( void                *driver_data,\n                                        ScreenFuncs         *funcs,\n                                        ScreenFuncs         *primary_funcs,\n                                        void               **primary_driver_data );\n\n/*\n * Enumerate all registered screens by invoking the callback for each screen.\n */\nvoid          dfb_screens_enumerate   ( CoreScreenCallback   callback,\n                                        void                *ctx );\n\n/*\n * Return the number of screens.\n */\nunsigned int  dfb_screens_num         ( void );\n\n/*\n * Return the screen with the specified ID.\n */\nCoreScreen   *dfb_screen_at           ( DFBScreenID          screen_id );\n\n/*\n * Return the (translated) screen with the specified ID.\n */\nCoreScreen   *dfb_screen_at_translated( DFBScreenID          screen_id );\n\n/*\n * Return the ID of the specified screen.\n */\nDFBScreenID   dfb_screen_id           ( const CoreScreen    *screen );\n\n/*\n * Return the (translated) ID of the specified screen.\n */\nDFBScreenID   dfb_screen_id_translated( const CoreScreen    *screen );\n\n#endif\n"
  },
  {
    "path": "src/core/shared_secure_surface_pool.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core.h>\n#include <core/surface_allocation.h>\n#include <core/surface_buffer.h>\n#include <core/surface_pool.h>\n#include <core/system.h>\n#include <direct/filesystem.h>\n#include <fusion/conf.h>\n#include <fusion/fusion.h>\n\nD_DEBUG_DOMAIN( Core_SharedSecure, \"Core/SharedSecure\", \"DirectFB Core Shared Secure Surface Pool\" );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     char tmpfs_dir[FUSION_SHM_TMPFS_PATH_NAME_LEN + 20];\n} SharedPoolData;\n\ntypedef struct {\n     CoreDFB     *core;\n     FusionWorld *world;\n} SharedPoolLocalData;\n\ntypedef struct {\n     int           pitch;\n     int           size;\n     DFBSurfaceID  surface_id;\n     void         *master_map;\n} SharedAllocationData;\n\n/**********************************************************************************************************************/\n\nstatic int\nsharedSecurePoolDataSize( void )\n{\n     return sizeof(SharedPoolData);\n}\n\nstatic int\nsharedSecurePoolLocalDataSize( void )\n{\n     return sizeof(SharedPoolLocalData);\n}\n\nstatic int\nsharedSecureAllocationDataSize( void )\n{\n     return sizeof(SharedAllocationData);\n}\n\nstatic DFBResult\nsharedSecureInitPool( CoreDFB                    *core,\n                      CoreSurfacePool            *pool,\n                      void                       *pool_data,\n                      void                       *pool_local,\n                      void                       *system_data,\n                      CoreSurfacePoolDescription *ret_desc )\n{\n     DirectResult         ret;\n     DirectDir            dir;\n     DirectEntry          entry;\n     SharedPoolData      *data  = pool_data;\n     SharedPoolLocalData *local = pool_local;\n\n     D_DEBUG_AT( Core_SharedSecure, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_ASSERT( ret_desc != NULL );\n\n     ret_desc->caps              = CSPCAPS_VIRTUAL;\n     ret_desc->access[CSAID_CPU] = CSAF_READ | CSAF_WRITE | CSAF_SHARED;\n     ret_desc->types             = CSTF_LAYER | CSTF_WINDOW | CSTF_CURSOR | CSTF_FONT | CSTF_SHARED | CSTF_INTERNAL;\n     ret_desc->priority          = (dfb_system_caps() & CSCAPS_PREFER_SHM) ? CSPP_PREFERED : CSPP_DEFAULT;\n\n     if (dfb_system_caps() & CSCAPS_SYSMEM_EXTERNAL)\n          ret_desc->types |= CSTF_EXTERNAL;\n\n     snprintf( ret_desc->name, DFB_SURFACE_POOL_DESC_NAME_LENGTH, \"Shared Secure Memory\" );\n\n     local->core  = core;\n     local->world = dfb_core_world( core );\n\n     snprintf( data->tmpfs_dir, sizeof(data->tmpfs_dir), \"%s/dfb.%d\",\n               fusion_get_tmpfs( local->world ), fusion_world_index( local->world ) );\n\n     ret = direct_dir_create( data->tmpfs_dir, 0750 );\n     if (ret) {\n          if (ret != DR_BUSY) {\n               D_DERROR( ret, \"Core/SharedSecure: Could not create '%s'!\\n\", data->tmpfs_dir );\n               return DFB_IO;\n          }\n\n          D_DEBUG_AT( Core_SharedSecure, \"  -> %s exists, cleaning up\\n\", data->tmpfs_dir );\n\n          ret = direct_dir_open ( &dir, data->tmpfs_dir );\n          if (ret) {\n               D_DERROR( ret, \"Core/SharedSecure: Could not open '%s'!\\n\", data->tmpfs_dir );\n               return DFB_IO;\n          }\n\n          while (direct_dir_read( &dir, &entry ) == DR_OK) {\n               char buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 20 + 256];\n\n               if (!strcmp( entry.name, \".\" ) || !strcmp( entry.name, \"..\" ))\n                    continue;\n\n               snprintf( buf, sizeof(buf), \"%s/%s\", data->tmpfs_dir, entry.name );\n\n               ret = direct_unlink( buf );\n               if (ret) {\n                    D_DERROR( ret, \"Core/SharedSecure: Could not remove '%s'!\\n\", buf );\n                    direct_dir_close( &dir );\n                    return DFB_IO;\n               }\n          }\n\n          direct_dir_close( &dir );\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsharedSecureDestroyPool( CoreSurfacePool *pool,\n                         void            *pool_data,\n                         void            *pool_local )\n{\n     DirectResult    ret;\n     SharedPoolData *data = pool_data;\n\n     D_DEBUG_AT( Core_SharedSecure, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n     ret = direct_dir_remove( data->tmpfs_dir );\n     if (ret)\n          D_DERROR( ret, \"Core/SharedSecure: Could not remove '%s'!\\n\", data->tmpfs_dir );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsharedSecureAllocateBuffer( CoreSurfacePool       *pool,\n                            void                  *pool_data,\n                            void                  *pool_local,\n                            CoreSurfaceBuffer     *buffer,\n                            CoreSurfaceAllocation *allocation,\n                            void                  *alloc_data )\n{\n     DirectResult          ret;\n     CoreSurface          *surface;\n     SharedPoolData       *data  = pool_data;\n     SharedAllocationData *alloc = alloc_data;\n     char                  buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 99];\n     DirectFile            fd;\n\n     D_DEBUG_AT( Core_SharedSecure, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n\n     surface = buffer->surface;\n\n     alloc->surface_id = surface->object.id;\n\n     dfb_surface_calc_buffer_size( surface, 8, 0, &alloc->pitch, &alloc->size );\n\n     snprintf( buf, sizeof(buf), \"%s/surface_0x%08x_shared_allocation_%p\", data->tmpfs_dir, alloc->surface_id, alloc );\n\n     ret = direct_file_open( &fd, buf, O_RDWR | O_CREAT | O_EXCL, 0660 );\n     if (ret) {\n          D_DERROR( ret, \"Core/SharedSecure: Could not create '%s'!\\n\", buf );\n          return DFB_IO;\n     }\n\n     if (fusion_config->shmfile_gid != -1) {\n          if (direct_file_chown( &fd, -1, fusion_config->shmfile_gid ))\n               D_WARN( \"changing owner on %s failed... continuing on.\", buf );\n     }\n\n     direct_file_chmod( &fd, 0660 );\n\n     if (direct_file_truncate( &fd, alloc->size )) {\n          D_DERROR( ret, \"Core/SharedSecure: Setting file size for '%s' to %d failed!\\n\", buf, alloc->size );\n          ret = direct_unlink( buf );\n          if (ret)\n               D_DERROR( ret, \"Core/SharedSecure: Could not remove '%s'!\\n\", buf );\n          return DFB_IO;\n     }\n\n     ret = direct_file_map( &fd, NULL, 0, alloc->size, DFP_READ | DFP_WRITE, &alloc->master_map );\n\n     direct_file_close( &fd );\n\n     if (ret) {\n          D_DERROR( ret, \"Core/SharedSecure: Could not mmap '%s'!\\n\", buf );\n\n          ret = direct_unlink( buf );\n          if (ret)\n               D_DERROR( ret, \"Core/SharedSecure: Could not remove '%s'!\\n\", buf );\n\n          return DFB_IO;\n     }\n\n     allocation->flags = CSALF_VOLATILE;\n     allocation->size  = alloc->size;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsharedSecureDeallocateBuffer( CoreSurfacePool       *pool,\n                              void                  *pool_data,\n                              void                  *pool_local,\n                              CoreSurfaceBuffer     *buffer,\n                              CoreSurfaceAllocation *allocation,\n                              void                  *alloc_data )\n{\n     DirectResult          ret;\n     SharedPoolData       *data  = pool_data;\n     SharedAllocationData *alloc = alloc_data;\n     char                  buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 99];\n\n     D_DEBUG_AT( Core_SharedSecure, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n     snprintf( buf, sizeof(buf), \"%s/surface_0x%08x_shared_allocation_%p\", data->tmpfs_dir, alloc->surface_id, alloc );\n\n     direct_file_unmap( alloc->master_map, alloc->size );\n\n     ret = direct_unlink( buf );\n     if (ret) {\n          D_DERROR( ret, \"Core/SharedSecure: Could not remove '%s'!\\n\", buf );\n          return DFB_IO;\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsharedSecureLock( CoreSurfacePool       *pool,\n                  void                  *pool_data,\n                  void                  *pool_local,\n                  CoreSurfaceAllocation *allocation,\n                  void                  *alloc_data,\n                  CoreSurfaceBufferLock *lock )\n{\n     DirectResult          ret;\n     SharedPoolData       *data  = pool_data;\n     SharedAllocationData *alloc = alloc_data;\n     char                  buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 99];\n     DirectFile            fd;\n\n     D_DEBUG_AT( Core_SharedSecure, \"%s() <- size %d\\n\", __FUNCTION__, alloc->size );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );\n\n     if (dfb_core_is_master( core_dfb )) {\n          lock->addr = alloc->master_map;\n     }\n     else {\n          snprintf( buf, sizeof(buf), \"%s/surface_0x%08x_shared_allocation_%p\",\n                    data->tmpfs_dir, alloc->surface_id, alloc );\n\n          ret = direct_file_open( &fd, buf, O_RDWR, 0 );\n          if (ret) {\n               D_DERROR( ret, \"Core/SharedSecure: Could not open '%s'!\\n\", buf );\n               return DFB_IO;\n          }\n\n          ret = direct_file_map( &fd, NULL, 0, alloc->size, DFP_READ | DFP_WRITE, &lock->handle );\n\n          lock->addr = lock->handle;\n\n          D_DEBUG_AT( Core_SharedSecure, \"  -> mapped to %p\\n\", lock->addr );\n\n          direct_file_close( &fd );\n\n          if (ret) {\n               D_DERROR( ret, \"Core/SharedSecure: Could not mmap '%s'!\\n\", buf );\n               return DFB_IO;\n          }\n     }\n\n     lock->pitch = alloc->pitch;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsharedSecureUnlock( CoreSurfacePool       *pool,\n                    void                  *pool_data,\n                    void                  *pool_local,\n                    CoreSurfaceAllocation *allocation,\n                    void                  *alloc_data,\n                    CoreSurfaceBufferLock *lock )\n{\n     SharedAllocationData *alloc = alloc_data;\n\n     D_DEBUG_AT( Core_SharedSecure, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );\n\n     if (!dfb_core_is_master( core_dfb ))\n          direct_file_unmap( lock->handle, alloc->size );\n\n     return DFB_OK;\n}\n\nconst SurfacePoolFuncs sharedSecureSurfacePoolFuncs = {\n     .PoolDataSize       = sharedSecurePoolDataSize,\n     .PoolLocalDataSize  = sharedSecurePoolLocalDataSize,\n     .AllocationDataSize = sharedSecureAllocationDataSize,\n     .InitPool           = sharedSecureInitPool,\n     .DestroyPool        = sharedSecureDestroyPool,\n     .AllocateBuffer     = sharedSecureAllocateBuffer,\n     .DeallocateBuffer   = sharedSecureDeallocateBuffer,\n     .Lock               = sharedSecureLock,\n     .Unlock             = sharedSecureUnlock\n};\n"
  },
  {
    "path": "src/core/shared_surface_pool.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core.h>\n#include <core/surface_allocation.h>\n#include <core/surface_buffer.h>\n#include <core/surface_pool.h>\n#include <core/system.h>\n#include <fusion/conf.h>\n#include <fusion/shmalloc.h>\n#include <fusion/shm/pool.h>\n\nD_DEBUG_DOMAIN( Core_Shared, \"Core/Shared\", \"DirectFB Core Shared Surface Pool\" );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     FusionSHMPoolShared *shmpool;\n} SharedPoolData;\n\ntypedef struct {\n     CoreDFB     *core;\n     FusionWorld *world;\n} SharedPoolLocalData;\n\ntypedef struct {\n     void *addr;\n     void *aligned_addr;\n     int   pitch;\n     int   size;\n} SharedAllocationData;\n\n/**********************************************************************************************************************/\n\nstatic int\nsharedPoolDataSize( void )\n{\n     return sizeof(SharedPoolData);\n}\n\nstatic int\nsharedPoolLocalDataSize( void )\n{\n     return sizeof(SharedPoolLocalData);\n}\n\nstatic int\nsharedAllocationDataSize( void )\n{\n     return sizeof(SharedAllocationData);\n}\n\nstatic DFBResult\nsharedInitPool( CoreDFB                    *core,\n                CoreSurfacePool            *pool,\n                void                       *pool_data,\n                void                       *pool_local,\n                void                       *system_data,\n                CoreSurfacePoolDescription *ret_desc )\n{\n     DFBResult            ret;\n     SharedPoolData      *data  = pool_data;\n     SharedPoolLocalData *local = pool_local;\n\n     D_DEBUG_AT( Core_Shared, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_ASSERT( ret_desc != NULL );\n\n     local->core  = core;\n     local->world = dfb_core_world( core );\n\n     ret = fusion_shm_pool_create( local->world, \"Surface Memory Pool\", dfb_config->surface_shmpool_size,\n                                   fusion_config->debugshm, &data->shmpool );\n     if (ret)\n          return ret;\n\n     ret_desc->caps              = CSPCAPS_VIRTUAL;\n     ret_desc->access[CSAID_CPU] = CSAF_READ | CSAF_WRITE | CSAF_SHARED;\n     ret_desc->types             = CSTF_LAYER | CSTF_WINDOW | CSTF_CURSOR | CSTF_FONT | CSTF_SHARED | CSTF_INTERNAL;\n     ret_desc->priority          = (dfb_system_caps() & CSCAPS_PREFER_SHM) ? CSPP_PREFERED : CSPP_DEFAULT;\n\n     if (dfb_system_caps() & CSCAPS_SYSMEM_EXTERNAL)\n          ret_desc->types |= CSTF_EXTERNAL;\n\n     snprintf( ret_desc->name, DFB_SURFACE_POOL_DESC_NAME_LENGTH, \"Shared Memory\" );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsharedDestroyPool( CoreSurfacePool *pool,\n                   void            *pool_data,\n                   void            *pool_local )\n{\n     SharedPoolData      *data  = pool_data;\n     SharedPoolLocalData *local = pool_local;\n\n     D_DEBUG_AT( Core_Shared, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n     fusion_shm_pool_destroy( local->world, data->shmpool );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsharedAllocateBuffer( CoreSurfacePool       *pool,\n                      void                  *pool_data,\n                      void                  *pool_local,\n                      CoreSurfaceBuffer     *buffer,\n                      CoreSurfaceAllocation *allocation,\n                      void                  *alloc_data )\n{\n     CoreSurface          *surface;\n     SharedPoolData       *data  = pool_data;\n     SharedAllocationData *alloc = alloc_data;\n\n     D_DEBUG_AT( Core_Shared, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n\n     surface = buffer->surface;\n\n     /* Create aligned shared system surface buffer if both base address and pitch are non-zero. */\n     if (dfb_config->system_surface_align_base && dfb_config->system_surface_align_pitch) {\n          /* Make sure base address and pitch are a positive power of two. */\n          D_ASSERT( dfb_config->system_surface_align_base >= 2 );\n          D_ASSERT( !(dfb_config->system_surface_align_base & (dfb_config->system_surface_align_base - 1)) );\n          D_ASSERT( dfb_config->system_surface_align_pitch >= 2 );\n          D_ASSERT( !(dfb_config->system_surface_align_pitch & (dfb_config->system_surface_align_pitch - 1)) );\n\n          dfb_surface_calc_buffer_size( surface, dfb_config->system_surface_align_pitch, 0,\n                                        &alloc->pitch, &alloc->size );\n\n          alloc->addr = SHMALLOC( data->shmpool, alloc->size + dfb_config->system_surface_align_base );\n          if (!alloc->addr)\n               return D_OOSHM();\n\n          /* Calculate the aligned address. */\n          unsigned long addr           = (unsigned long) alloc->addr;\n          unsigned long aligned_offset = dfb_config->system_surface_align_base -\n                                         (addr % dfb_config->system_surface_align_base );\n\n          alloc->aligned_addr = (void*) (addr + aligned_offset);\n     }\n     /* Create un-aligned shared system surface buffer. */\n     else {\n          dfb_surface_calc_buffer_size( surface, 8, 0, &alloc->pitch, &alloc->size );\n\n          alloc->addr = SHMALLOC( data->shmpool, alloc->size );\n          if (!alloc->addr)\n               return D_OOSHM();\n\n          alloc->aligned_addr = NULL;\n     }\n\n     allocation->flags = CSALF_VOLATILE;\n     allocation->size  = alloc->size;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsharedDeallocateBuffer( CoreSurfacePool       *pool,\n                        void                  *pool_data,\n                        void                  *pool_local,\n                        CoreSurfaceBuffer     *buffer,\n                        CoreSurfaceAllocation *allocation,\n                        void                  *alloc_data )\n{\n     SharedPoolData       *data  = pool_data;\n     SharedAllocationData *alloc = alloc_data;\n\n     D_DEBUG_AT( Core_Shared, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n     SHFREE( data->shmpool, alloc->addr );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsharedLock( CoreSurfacePool       *pool,\n            void                  *pool_data,\n            void                  *pool_local,\n            CoreSurfaceAllocation *allocation,\n            void                  *alloc_data,\n            CoreSurfaceBufferLock *lock )\n{\n     SharedAllocationData *alloc = alloc_data;\n\n     D_DEBUG_AT( Core_Shared, \"%s() <- size %d\\n\", __FUNCTION__, alloc->size );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );\n\n     /* Provide aligned address if one's available, otherwise the un-aligned one. */\n     if (alloc->aligned_addr)\n          lock->addr = alloc->aligned_addr;\n     else\n          lock->addr = alloc->addr;\n\n     lock->pitch = alloc->pitch;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsharedUnlock( CoreSurfacePool       *pool,\n              void                  *pool_data,\n              void                  *pool_local,\n              CoreSurfaceAllocation *allocation,\n              void                  *alloc_data,\n              CoreSurfaceBufferLock *lock )\n{\n     D_DEBUG_AT( Core_Shared, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );\n\n     return DFB_OK;\n}\n\nconst SurfacePoolFuncs sharedSurfacePoolFuncs = {\n     .PoolDataSize       = sharedPoolDataSize,\n     .PoolLocalDataSize  = sharedPoolLocalDataSize,\n     .AllocationDataSize = sharedAllocationDataSize,\n     .InitPool           = sharedInitPool,\n     .DestroyPool        = sharedDestroyPool,\n     .AllocateBuffer     = sharedAllocateBuffer,\n     .DeallocateBuffer   = sharedDeallocateBuffer,\n     .Lock               = sharedLock,\n     .Unlock             = sharedUnlock\n};\n"
  },
  {
    "path": "src/core/state.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core.h>\n#include <core/palette.h>\n#include <core/state.h>\n#include <direct/memcpy.h>\n\nD_DEBUG_DOMAIN( Core_GfxState, \"Core/GfxState\", \"DirectFB Core Gfx State\" );\n\n/**********************************************************************************************************************/\n\nstatic __inline__ void\nvalidate_clip( CardState *state,\n               int        xmax,\n               int        ymax,\n               bool       warn )\n{\n     D_DEBUG_AT( Core_GfxState, \"%s( %p, %d, %d, %d )\\n\", __FUNCTION__, state, xmax, ymax, warn );\n\n     D_MAGIC_ASSERT( state, CardState );\n     DFB_REGION_ASSERT( &state->clip );\n     D_ASSERT( xmax >= 0 );\n     D_ASSERT( ymax >= 0 );\n     D_ASSERT( state->clip.x1 <= state->clip.x2 );\n     D_ASSERT( state->clip.y1 <= state->clip.y2 );\n\n     if (state->clip.x1 <= xmax &&\n         state->clip.y1 <= ymax &&\n         state->clip.x2 <= xmax &&\n         state->clip.y2 <= ymax)\n          return;\n\n     if (warn)\n          D_WARN( \"clip %4d,%4d-%4dx%4d invalid, adjusting to fit %dx%d\",\n                  DFB_RECTANGLE_VALS_FROM_REGION( &state->clip ), xmax + 1, ymax + 1 );\n\n     if (state->clip.x1 > xmax)\n          state->clip.x1 = xmax;\n\n     if (state->clip.y1 > ymax)\n          state->clip.y1 = ymax;\n\n     if (state->clip.x2 > xmax)\n          state->clip.x2 = xmax;\n\n     if (state->clip.y2 > ymax)\n          state->clip.y2 = ymax;\n\n     state->modified |= SMF_CLIP;\n}\n\n/**********************************************************************************************************************/\n\nint\ndfb_state_init( CardState *state,\n                CoreDFB   *core )\n{\n     D_ASSERT( state != NULL );\n\n     memset( state, 0, sizeof(CardState) );\n\n     state->core           = core;\n     state->fusion_id      = fusion_id( dfb_core_world( core ) );\n     state->modified       = SMF_ALL;\n     state->src_blend      = DSBF_SRCALPHA;\n     state->dst_blend      = DSBF_INVSRCALPHA;\n     state->render_options = dfb_config->render_options;\n\n     state->matrix[0] = 0x10000;\n     state->matrix[1] = 0x00000;\n     state->matrix[2] = 0x00000;\n     state->matrix[3] = 0x00000;\n     state->matrix[4] = 0x10000;\n     state->matrix[5] = 0x00000;\n     state->matrix[6] = 0x00000;\n     state->matrix[7] = 0x00000;\n     state->matrix[8] = 0x10000;\n     state->affine_matrix = DFB_TRUE;\n\n     state->from     = DSBR_FRONT;\n     state->from_eye = DSSE_LEFT;\n     state->to       = DSBR_BACK;\n     state->to_eye   = DSSE_LEFT;\n\n     state->src_colormatrix[0]  = 0x10000;\n     state->src_colormatrix[1]  = 0x00000;\n     state->src_colormatrix[2]  = 0x00000;\n     state->src_colormatrix[3]  = 0x00000;\n\n     state->src_colormatrix[4]  = 0x00000;\n     state->src_colormatrix[5]  = 0x10000;\n     state->src_colormatrix[6]  = 0x00000;\n     state->src_colormatrix[7]  = 0x00000;\n\n     state->src_colormatrix[8]  = 0x00000;\n     state->src_colormatrix[9]  = 0x00000;\n     state->src_colormatrix[10] = 0x10000;\n     state->src_colormatrix[11] = 0x00000;\n\n     state->src_convolution.kernel[4] = 0x10000;\n     state->src_convolution.scale     = 0x10000;\n\n     direct_recursive_mutex_init( &state->lock );\n\n     direct_serial_init( &state->dst_serial );\n     direct_serial_init( &state->src_serial );\n     direct_serial_init( &state->src_mask_serial );\n     direct_serial_init( &state->src2_serial );\n\n     D_MAGIC_SET( state, CardState );\n\n     state->gfxcard_data = NULL;\n     dfb_gfxcard_state_init( state );\n\n     return 0;\n}\n\nvoid\ndfb_state_destroy( CardState *state )\n{\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( state->destination == NULL );\n     D_ASSERT( state->source == NULL );\n     D_ASSERT( state->source2 == NULL );\n     D_ASSERT( state->source_mask == NULL );\n\n     if (!dfb_config->startstop)\n          D_ASSUME( !(state->flags & CSF_DRAWING) );\n\n     dfb_gfxcard_state_destroy( state );\n\n     state->gfxcard_data = NULL;\n\n     D_MAGIC_CLEAR( state );\n\n     direct_serial_deinit( &state->dst_serial );\n     direct_serial_deinit( &state->src_serial );\n     direct_serial_deinit( &state->src_mask_serial );\n     direct_serial_deinit( &state->src2_serial );\n\n     if (state->num_translation) {\n          D_ASSERT( state->index_translation != NULL );\n\n          D_FREE( state->index_translation );\n     }\n     else\n          D_ASSERT( state->index_translation == NULL );\n\n     direct_mutex_deinit( &state->lock );\n}\n\nDFBResult\ndfb_state_set_destination( CardState   *state,\n                           CoreSurface *destination )\n{\n     D_MAGIC_ASSERT( state, CardState );\n\n     dfb_state_lock( state );\n\n     if (!dfb_config->startstop)\n          D_ASSUME( !(state->flags & CSF_DRAWING) );\n\n     if (state->destination != destination) {\n          if (destination) {\n               if (dfb_surface_ref( destination )) {\n                    D_WARN( \"could not ref() destination\" );\n                    dfb_state_unlock( state );\n                    return DFB_DEAD;\n               }\n\n               validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, false );\n          }\n\n          if (state->destination) {\n               D_ASSERT( D_FLAGS_IS_SET( state->flags, CSF_DESTINATION ) );\n\n               dfb_surface_unref( state->destination );\n          }\n\n          state->destination  = destination;\n          state->modified    |= SMF_DESTINATION;\n\n          if (destination) {\n               direct_serial_copy( &state->dst_serial, &destination->serial );\n\n               D_FLAGS_SET( state->flags, CSF_DESTINATION );\n          }\n          else\n               D_FLAGS_CLEAR( state->flags, CSF_DESTINATION );\n     }\n\n     dfb_state_unlock( state );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_state_set_destination_2( CardState   *state,\n                             CoreSurface *destination,\n                             u32          flip_count )\n{\n     D_MAGIC_ASSERT( state, CardState );\n\n     dfb_state_lock( state );\n\n     if (!dfb_config->startstop)\n          D_ASSUME( !(state->flags & CSF_DRAWING) );\n\n     if (state->destination != destination) {\n          if (destination) {\n               if (dfb_surface_ref( destination )) {\n                    D_WARN( \"could not ref() destination\" );\n                    dfb_state_unlock( state );\n                    return DFB_DEAD;\n               }\n\n               validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, false );\n          }\n\n          if (state->destination) {\n               D_ASSERT( D_FLAGS_IS_SET( state->flags, CSF_DESTINATION ) );\n\n               dfb_surface_unref( state->destination );\n          }\n\n          if (destination) {\n               direct_serial_copy( &state->dst_serial, &destination->serial );\n\n               D_FLAGS_SET( state->flags, CSF_DESTINATION );\n          }\n          else\n               D_FLAGS_CLEAR( state->flags, CSF_DESTINATION );\n\n          state->destination  = destination;\n          state->modified    |= SMF_DESTINATION;\n     }\n\n     if (state->destination_flip_count != flip_count || !state->destination_flip_count_used) {\n          state->destination_flip_count      = flip_count;\n          state->destination_flip_count_used = true;\n\n          state->destination  = destination;\n          state->modified    |= SMF_DESTINATION;\n     }\n\n     dfb_state_unlock( state );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_state_set_source( CardState   *state,\n                      CoreSurface *source )\n{\n     D_MAGIC_ASSERT( state, CardState );\n\n     dfb_state_lock( state );\n\n     if (state->source != source) {\n          if (source && dfb_surface_ref( source )) {\n               D_WARN( \"could not ref() source\" );\n               dfb_state_unlock( state );\n               return DFB_DEAD;\n          }\n\n          if (state->source) {\n               D_ASSERT( D_FLAGS_IS_SET( state->flags, CSF_SOURCE ) );\n\n               dfb_surface_unref( state->source );\n          }\n\n          state->source    = source;\n          state->modified |= SMF_SOURCE;\n\n          if (source) {\n               direct_serial_copy( &state->src_serial, &source->serial );\n\n               D_FLAGS_SET( state->flags, CSF_SOURCE );\n          }\n          else\n               D_FLAGS_CLEAR( state->flags, CSF_SOURCE );\n     }\n\n     dfb_state_unlock( state );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_state_set_source_2( CardState   *state,\n                        CoreSurface *source,\n                        u32          flip_count )\n{\n     D_MAGIC_ASSERT( state, CardState );\n\n     dfb_state_lock( state );\n\n     if (state->source != source) {\n          if (source && dfb_surface_ref( source )) {\n               D_WARN( \"could not ref() source\" );\n               dfb_state_unlock( state );\n               return DFB_DEAD;\n          }\n\n          if (state->source) {\n               D_ASSERT( D_FLAGS_IS_SET( state->flags, CSF_SOURCE ) );\n\n               dfb_surface_unref( state->source );\n          }\n\n          state->source    = source;\n          state->modified |= SMF_SOURCE;\n\n          if (source) {\n               direct_serial_copy( &state->src_serial, &source->serial );\n\n               D_FLAGS_SET( state->flags, CSF_SOURCE );\n          }\n          else\n               D_FLAGS_CLEAR( state->flags, CSF_SOURCE );\n     }\n\n     if (state->source_flip_count != flip_count || !state->source_flip_count_used) {\n          state->source_flip_count      = flip_count;\n          state->source_flip_count_used = true;\n\n          state->source    = source;\n          state->modified |= SMF_SOURCE;\n     }\n\n     dfb_state_unlock( state );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_state_set_source2( CardState   *state,\n                       CoreSurface *source2 )\n{\n     D_MAGIC_ASSERT( state, CardState );\n\n     dfb_state_lock( state );\n\n     if (state->source2 != source2) {\n          if (source2 && dfb_surface_ref( source2 )) {\n               D_WARN( \"could not ref() source2\" );\n               dfb_state_unlock( state );\n               return DFB_DEAD;\n          }\n\n          if (state->source2) {\n               D_ASSERT( D_FLAGS_IS_SET( state->flags, CSF_SOURCE2 ) );\n\n               dfb_surface_unref( state->source2 );\n          }\n\n          state->source2   = source2;\n          state->modified |= SMF_SOURCE2;\n\n          if (source2) {\n               direct_serial_copy( &state->src2_serial, &source2->serial );\n\n               D_FLAGS_SET( state->flags, CSF_SOURCE2 );\n          }\n          else\n               D_FLAGS_CLEAR( state->flags, CSF_SOURCE2 );\n     }\n\n     dfb_state_unlock( state );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_state_set_source_mask( CardState   *state,\n                           CoreSurface *source_mask )\n{\n     D_MAGIC_ASSERT( state, CardState );\n\n     dfb_state_lock( state );\n\n     if (state->source_mask != source_mask) {\n          if (source_mask && dfb_surface_ref( source_mask )) {\n               D_WARN( \"could not ref() source mask\" );\n               dfb_state_unlock( state );\n               return DFB_DEAD;\n          }\n\n          if (state->source_mask) {\n               D_ASSERT( D_FLAGS_IS_SET( state->flags, CSF_SOURCE_MASK ) );\n\n               dfb_surface_unref( state->source_mask );\n          }\n\n          state->source_mask  = source_mask;\n          state->modified    |= SMF_SOURCE_MASK;\n\n          if (source_mask) {\n               direct_serial_copy( &state->src_mask_serial, &source_mask->serial );\n\n               D_FLAGS_SET( state->flags, CSF_SOURCE_MASK );\n          }\n          else\n               D_FLAGS_CLEAR( state->flags, CSF_SOURCE_MASK );\n     }\n\n     dfb_state_unlock( state );\n\n     return DFB_OK;\n}\n\nvoid\ndfb_state_update( CardState *state,\n                  bool       update_sources )\n{\n     CoreSurface *destination;\n\n     D_MAGIC_ASSERT( state, CardState );\n     DFB_REGION_ASSERT( &state->clip );\n\n     destination = state->destination;\n\n     if (D_FLAGS_IS_SET( state->flags, CSF_DESTINATION )) {\n          D_ASSERT( destination != NULL );\n\n          if (direct_serial_update( &state->dst_serial, &destination->serial )) {\n               validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, true );\n\n               state->modified |= SMF_DESTINATION;\n          }\n     }\n     else if (destination)\n          validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, true );\n\n     if (update_sources && D_FLAGS_IS_SET( state->flags, CSF_SOURCE )) {\n          CoreSurface *source = state->source;\n\n          D_ASSERT( source != NULL );\n\n          if (direct_serial_update( &state->src_serial, &source->serial ))\n               state->modified |= SMF_SOURCE;\n     }\n\n     if (update_sources && D_FLAGS_IS_SET( state->flags, CSF_SOURCE_MASK )) {\n          CoreSurface *source_mask = state->source_mask;\n\n          D_ASSERT( source_mask != NULL );\n\n          if (direct_serial_update( &state->src_mask_serial, &source_mask->serial ))\n               state->modified |= SMF_SOURCE_MASK;\n     }\n\n     if (update_sources && D_FLAGS_IS_SET( state->flags, CSF_SOURCE2 )) {\n          CoreSurface *source2 = state->source2;\n\n          D_ASSERT( source2 != NULL );\n\n          if (direct_serial_update( &state->src2_serial, &source2->serial ))\n               state->modified |= SMF_SOURCE2;\n     }\n}\n\nvoid\ndfb_state_update_destination( CardState *state )\n{\n     CoreSurface *destination;\n\n     D_DEBUG_AT( Core_GfxState, \"%s( %p )\\n\", __FUNCTION__, state );\n\n     D_MAGIC_ASSERT( state, CardState );\n     DFB_REGION_ASSERT( &state->clip );\n\n     destination = state->destination;\n\n     if (D_FLAGS_IS_SET( state->flags, CSF_DESTINATION )) {\n          D_DEBUG_AT( Core_GfxState, \"  -> CSF_DESTINATION is set\\n\" );\n\n          D_ASSERT( destination != NULL );\n\n          if (direct_serial_update( &state->dst_serial, &destination->serial )) {\n               D_DEBUG_AT( Core_GfxState, \"  -> serial is updated\\n\" );\n\n               validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, true );\n\n               state->modified |= SMF_DESTINATION;\n          }\n     }\n     else if (destination)\n          validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, true );\n}\n\nvoid\ndfb_state_update_sources( CardState      *state,\n                          CardStateFlags  flags )\n{\n     D_DEBUG_AT( Core_GfxState, \"%s( %p )\\n\", __FUNCTION__, state );\n\n     D_MAGIC_ASSERT( state, CardState );\n     DFB_REGION_ASSERT( &state->clip );\n\n     if (D_FLAGS_IS_SET( state->flags & flags, CSF_SOURCE )) {\n          CoreSurface *source = state->source;\n\n          D_ASSERT( source != NULL );\n\n          if (direct_serial_update( &state->src_serial, &source->serial ))\n               state->modified |= SMF_SOURCE;\n     }\n\n     if (D_FLAGS_IS_SET( state->flags & flags, CSF_SOURCE_MASK )) {\n          CoreSurface *source_mask = state->source_mask;\n\n          D_ASSERT( source_mask != NULL );\n\n          if (direct_serial_update( &state->src_mask_serial, &source_mask->serial ))\n               state->modified |= SMF_SOURCE_MASK;\n     }\n\n     if (D_FLAGS_IS_SET( state->flags & flags, CSF_SOURCE2 )) {\n          CoreSurface *source2 = state->source2;\n\n          D_ASSERT( source2 != NULL );\n\n          if (direct_serial_update( &state->src2_serial, &source2->serial ))\n               state->modified |= SMF_SOURCE2;\n     }\n}\n\nDFBResult\ndfb_state_set_index_translation( CardState *state,\n                                 const int *indices,\n                                 int        num_indices )\n{\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( indices != NULL || num_indices == 0 );\n\n     dfb_state_lock( state );\n\n     if (state->num_translation != num_indices) {\n          int *new_trans = D_REALLOC( state->index_translation, num_indices * sizeof(int) );\n\n          D_ASSERT( num_indices || new_trans == NULL );\n\n          if (num_indices && !new_trans) {\n               dfb_state_unlock( state );\n               return D_OOM();\n          }\n\n          state->index_translation = new_trans;\n          state->num_translation   = num_indices;\n     }\n\n     if (num_indices)\n          direct_memcpy( state->index_translation, indices, num_indices * sizeof(int) );\n\n     state->modified |= SMF_INDEX_TRANSLATION;\n\n     dfb_state_unlock( state );\n\n     return DFB_OK;\n}\n\nvoid\ndfb_state_set_matrix( CardState *state,\n                      const s32 *matrix )\n{\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( matrix != NULL );\n\n     if (memcmp( state->matrix, matrix, sizeof(state->matrix) )) {\n          direct_memcpy( state->matrix, matrix, sizeof(state->matrix) );\n\n          state->affine_matrix = (matrix[6] == 0x00000 && matrix[7] == 0x00000 && matrix[8] == 0x10000);\n\n          state->modified |= SMF_MATRIX;\n     }\n}\n\nvoid\ndfb_state_set_src_colormatrix( CardState *state,\n                               const s32 *matrix )\n{\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( matrix != NULL );\n\n     if (memcmp( state->src_colormatrix, matrix, sizeof(state->src_colormatrix) )) {\n          direct_memcpy( state->src_colormatrix, matrix, sizeof(state->src_colormatrix) );\n\n          state->modified |= SMF_SRC_COLORMATRIX;\n     }\n}\n\nvoid\ndfb_state_set_src_convolution( CardState                  *state,\n                               const DFBConvolutionFilter *filter )\n{\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( filter != NULL );\n\n     if (memcmp( &state->src_convolution, filter, sizeof(state->src_convolution) )) {\n          direct_memcpy( &state->src_convolution, filter, sizeof(state->src_convolution) );\n\n          state->modified |= SMF_SRC_CONVOLUTION;\n     }\n}\n\nvoid\ndfb_state_set_color_or_index( CardState      *state,\n                              const DFBColor *color,\n                              int             index )\n{\n     CoreSurface *destination;\n     CorePalette *palette = NULL;\n\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( color != NULL );\n\n     destination = state->destination;\n     if (destination)\n          palette = destination->palette;\n\n     if (index < 0) {\n          D_ASSERT( color != NULL );\n\n          if (palette)\n               dfb_state_set_color_index( state,\n                                          dfb_palette_search( palette, color->r, color->g, color->b, color->a ) );\n\n          dfb_state_set_color( state, color );\n     }\n     else {\n          dfb_state_set_color_index( state, index );\n\n          if (palette) {\n               D_ASSERT( palette->num_entries > 0 );\n               D_ASSUME( palette->num_entries > index );\n\n               dfb_state_set_color( state, &palette->entries[index % palette->num_entries] );\n          }\n     }\n}\n\nDFBResult\ndfb_state_get_acceleration_mask( CardState           *state,\n                                 DFBAccelerationMask *ret_accel )\n{\n    DFBAccelerationMask mask = DFXL_NONE;\n\n    D_MAGIC_ASSERT( state, CardState );\n    D_ASSERT( ret_accel != NULL );\n\n    dfb_state_lock( state );\n\n    /* Check drawing functions. */\n\n    if (dfb_gfxcard_state_check( state, DFXL_FILLRECTANGLE ))\n         D_FLAGS_SET( mask, DFXL_FILLRECTANGLE );\n\n    if (dfb_gfxcard_state_check( state, DFXL_DRAWRECTANGLE ))\n         D_FLAGS_SET( mask, DFXL_DRAWRECTANGLE );\n\n    if (dfb_gfxcard_state_check( state, DFXL_DRAWLINE ))\n         D_FLAGS_SET( mask, DFXL_DRAWLINE );\n\n    if (dfb_gfxcard_state_check( state, DFXL_FILLTRIANGLE ))\n         D_FLAGS_SET( mask, DFXL_FILLTRIANGLE );\n\n    if (dfb_gfxcard_state_check( state, DFXL_FILLTRAPEZOID ))\n         D_FLAGS_SET( mask, DFXL_FILLTRAPEZOID );\n\n    /* Check blitting functions. */\n\n    if (state->source) {\n         if (dfb_gfxcard_state_check( state, DFXL_BLIT ))\n              D_FLAGS_SET( mask, DFXL_BLIT );\n\n         if (dfb_gfxcard_state_check( state, DFXL_STRETCHBLIT ))\n              D_FLAGS_SET( mask, DFXL_STRETCHBLIT );\n\n         if (dfb_gfxcard_state_check( state, DFXL_TEXTRIANGLES ))\n              D_FLAGS_SET( mask, DFXL_TEXTRIANGLES );\n    }\n\n    if (state->source2) {\n         if (dfb_gfxcard_state_check( state, DFXL_BLIT2 ))\n              D_FLAGS_SET( mask, DFXL_BLIT2 );\n    }\n\n    dfb_state_unlock( state );\n\n    *ret_accel = mask;\n\n    return DFB_OK;\n}\n"
  },
  {
    "path": "src/core/state.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__STATE_H__\n#define __CORE__STATE_H__\n\n#include <core/gfxcard.h>\n#include <core/surface_buffer.h>\n#include <directfb_util.h>\n#include <misc/conf.h>\n\n/**********************************************************************************************************************/\n\n/*\n * Maximum number of color ids.\n */\n#define DFB_COLOR_IDS_MAX 8\n\ntypedef enum {\n     CSF_NONE               = 0x00000000, /* none of these */\n\n     CSF_DESTINATION        = 0x00000001, /* destination is set using dfb_state_set_destination() */\n     CSF_SOURCE             = 0x00000002, /* source is set using dfb_state_set_source() */\n     CSF_SOURCE_MASK        = 0x00000008, /* source mask is set using dfb_state_set_source_mask() */\n\n     CSF_SOURCE_LOCKED      = 0x00000010, /* source surface is locked */\n     CSF_SOURCE_MASK_LOCKED = 0x00000020, /* source mask surface is locked */\n\n     CSF_SOURCE2            = 0x00000100, /* source2 is set using dfb_state_set_source2() */\n     CSF_SOURCE2_LOCKED     = 0x00000200, /* source2 surface is locked */\n\n     CSF_DRAWING            = 0x00010000, /* something has been rendered with this state, this is cleared by flushing\n                                             the state, e.g. upon flip */\n\n     CSF_ALL                = 0x0001033B  /* all of these */\n} CardStateFlags;\n\ntypedef enum {\n     SMF_NONE                  = 0x00000000,\n\n     SMF_DRAWING_FLAGS         = 0x00000001,\n     SMF_BLITTING_FLAGS        = 0x00000002,\n     SMF_CLIP                  = 0x00000004,\n     SMF_COLOR                 = 0x00000008,\n     SMF_SRC_BLEND             = 0x00000010,\n     SMF_DST_BLEND             = 0x00000020,\n     SMF_SRC_COLORKEY          = 0x00000040,\n     SMF_DST_COLORKEY          = 0x00000080,\n     SMF_DESTINATION           = 0x00000100,\n     SMF_SOURCE                = 0x00000200,\n     SMF_SOURCE_MASK           = 0x00000400,\n     SMF_SOURCE_MASK_VALS      = 0x00000800,\n     SMF_INDEX_TRANSLATION     = 0x00001000,\n     SMF_COLORKEY              = 0x00002000,\n\n     SMF_SRC_COLORMATRIX       = 0x00008000,\n     SMF_RENDER_OPTIONS        = 0x00010000,\n     SMF_MATRIX                = 0x00020000,\n     SMF_SRC_COLORKEY_EXTENDED = 0x00040000,\n     SMF_DST_COLORKEY_EXTENDED = 0x00080000,\n\n     SMF_SOURCE2               = 0x00100000,\n     SMF_SRC_CONVOLUTION       = 0x00200000,\n\n     SMF_FROM                  = 0x10000000,\n     SMF_TO                    = 0x20000000,\n\n     SMF_ALL                   = 0x303FBFFF\n} StateModificationFlags;\n\nstruct __DFB_CardState {\n     /* graphics card state */\n\n     int                      magic;\n\n     CoreDFB                 *core;                             /* core instance */\n     FusionID                 fusion_id;                        /* fusion id */\n\n     DirectMutex              lock;                             /* lock for state handling */\n\n     CardStateFlags           flags;                            /* flags defining the state */\n\n     StateModificationFlags   modified;                         /* indicate which fields have been modified, these flags\n                                                                   will be cleared by the gfx drivers */\n     StateModificationFlags   mod_hw;                           /* modification flags for drivers. */\n\n     /* values forming the state for graphics operations */\n\n     DFBSurfaceDrawingFlags   drawingflags;                     /* drawing flags */\n     DFBSurfaceBlittingFlags  blittingflags;                    /* blitting flags */\n\n     DFBRegion                clip;                             /* clipping rectangle */\n     DFBColor                 color;                            /* color for drawing or modulation */\n     unsigned int             color_index;                      /* index to color in palette */\n     DFBSurfaceBlendFunction  src_blend;                        /* blend function for source */\n     DFBSurfaceBlendFunction  dst_blend;                        /* blend function for destination */\n     u32                      src_colorkey;                     /* colorkey for source */\n     u32                      dst_colorkey;                     /* colorkey for destination */\n\n     CoreSurface             *destination;                      /* destination surface */\n     CoreSurface             *source;                           /* source surface */\n     CoreSurfaceBuffer       *source_buffer;                    /* source surface */\n\n     DirectSerial             dst_serial;                       /* last destination surface serial */\n     DirectSerial             src_serial;                       /* last source surface serial */\n\n     int                     *index_translation;                /* translation table used for fast indexed to indexed\n                                                                   pixel format conversion */\n     int                      num_translation;                  /* translation table size */\n\n     /* hardware abstraction and state handling helpers */\n\n     DFBAccelerationMask      accel;                            /* remember checked commands if they are accelerated */\n     DFBAccelerationMask      checked;                          /* commands for which a state has been checked */\n     DFBAccelerationMask      set;                              /* commands for which a state is valid */\n     DFBAccelerationMask      disabled;                         /* commands which are disabled temporarily */\n     CoreGraphicsSerial       serial;                           /* hardware serial of the last operation */\n\n     /* from/to buffers */\n\n     DFBSurfaceBufferRole     from;                             /* usually DSBR_FRONT */\n     DFBSurfaceStereoEye      from_eye;                         /* usually DSSE_LEFT */\n     DFBSurfaceBufferRole     to;                               /* usually DSBR_BACK */\n     DFBSurfaceStereoEye      to_eye;                           /* usually DSSE_LEFT */\n\n     /* read/write locks during operation */\n\n     CoreSurfaceBufferLock    dst;                              /* destination read/write lock */\n     CoreSurfaceBufferLock    src;                              /* source read/write lock */\n\n     /* software driver */\n\n     GenefxState             *gfxs;                             /* state of the virtual graphics processing unit */\n\n     /* extended state */\n\n     DFBSurfaceRenderOptions  render_options;                   /* options for drawing and blitting operations */\n\n     DFBColorKey              colorkey;                         /* key for color key protection */\n\n     s32                      matrix[9];                        /* transformation matrix for DSRO_MATRIX */\n     DFBBoolean               affine_matrix;                    /* true if affine transformation */\n\n     CoreSurface             *source_mask;                      /* source mask surface */\n     CoreSurfaceBufferLock    src_mask;                         /* source mask surface lock */\n     DirectSerial             src_mask_serial;                  /* last source mask surface serial */\n     DFBPoint                 src_mask_offset;                  /* relative or absolute coordinates */\n     DFBSurfaceMaskFlags      src_mask_flags;                   /* controls coordinate mode and more */\n\n     CoreSurface             *source2;                          /* source2 surface */\n     DirectSerial             src2_serial;                      /* last source2 surface serial */\n     CoreSurfaceBufferLock    src2;                             /* source2 surface lock */\n\n     DFBColor                 colors[DFB_COLOR_IDS_MAX];        /* colors for drawing or modulation */\n     unsigned int             color_indices[DFB_COLOR_IDS_MAX]; /* indices to colors in palette */\n\n     DFBColorKeyExtended      src_colorkey_extended;            /* extended colorkey for source */\n     DFBColorKeyExtended      dst_colorkey_extended;            /* extended colorkey for destination */\n\n     s32                      src_colormatrix[12];              /* transformation matrix for DSBLIT_SRC_COLORMATRIX */\n\n     DFBConvolutionFilter     src_convolution;                  /* 3x3 kernel, scale and bias */\n\n     void                    *gfxcard_data;                     /* gfx driver specific state data */\n\n     u32                      source_flip_count;                /* source flip count */\n     bool                     source_flip_count_used;           /* source flip count used */\n\n     void                    *client;                           /* state client */\n\n     u32                      destination_flip_count;           /* destination flip count */\n     bool                     destination_flip_count_used;      /* destination flip count used */\n};\n\n/**********************************************************************************************************************/\n\nint       dfb_state_init                 ( CardState                  *state,\n                                           CoreDFB                    *core );\n\nvoid      dfb_state_destroy              ( CardState                  *state );\n\nDFBResult dfb_state_set_destination      ( CardState                  *state,\n                                           CoreSurface                *destination );\n\nDFBResult dfb_state_set_destination_2    ( CardState                  *state,\n                                           CoreSurface                *destination,\n                                           u32                         flip_count );\n\nDFBResult dfb_state_set_source           ( CardState                  *state,\n                                           CoreSurface                *source );\n\nDFBResult dfb_state_set_source_2         ( CardState                  *state,\n                                           CoreSurface                *source,\n                                           u32                         flip_count );\n\nDFBResult dfb_state_set_source2          ( CardState                  *state,\n                                           CoreSurface                *source2 );\n\nDFBResult dfb_state_set_source_mask      ( CardState                  *state,\n                                           CoreSurface                *source_mask );\n\nvoid      dfb_state_update               ( CardState                  *state,\n                                           bool                        update_source );\n\nvoid      dfb_state_update_destination   ( CardState                  *state );\n\nvoid      dfb_state_update_sources       ( CardState                  *state,\n                                           CardStateFlags              flags );\n\nDFBResult dfb_state_set_index_translation( CardState                  *state,\n                                           const int                  *indices,\n                                           int                         num_indices );\n\nvoid      dfb_state_set_matrix           ( CardState                  *state,\n                                           const s32                  *matrix );\n\nvoid      dfb_state_set_src_colormatrix  ( CardState                  *state,\n                                           const s32                  *matrix );\n\nvoid      dfb_state_set_src_convolution  ( CardState                  *state,\n                                           const DFBConvolutionFilter *filter );\n\n/*\n * Multifunctional color configuration function. Always tries to set both color and index.\n *\n * If color index is -1, color is used and searched in palette of destination surface if present.\n * If color index is valid the color is looked up in palette if present.\n */\nvoid      dfb_state_set_color_or_index   ( CardState                  *state,\n                                           const DFBColor             *color,\n                                           int                         index );\n\n/*\n * Return the mask of accelerated functions.\n */\nDFBResult dfb_state_get_acceleration_mask( CardState                  *state,\n                                           DFBAccelerationMask        *ret_accel );\n\n/**********************************************************************************************************************/\n\nstatic __inline__ void\ndfb_state_lock( CardState *state )\n{\n     D_MAGIC_ASSERT( state, CardState );\n\n     DFB_REGION_ASSERT( &state->clip );\n\n     direct_mutex_lock( &state->lock );\n}\n\nstatic __inline__ void\ndfb_state_start_drawing( CardState *state )\n{\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( state->destination != NULL );\n\n     if (dfb_config->startstop) {\n          if (!(state->flags & CSF_DRAWING)) {\n               dfb_gfxcard_start_drawing( state );\n\n               state->flags = state->flags | CSF_DRAWING;\n          }\n     }\n}\n\nstatic __inline__ void\ndfb_state_stop_drawing( CardState *state )\n{\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( state->destination != NULL );\n\n     if (dfb_config->startstop) {\n          if (state->flags & CSF_DRAWING) {\n               dfb_gfxcard_stop_drawing( state );\n\n               state->flags = state->flags & ~CSF_DRAWING;\n          }\n     }\n}\n\nstatic __inline__ void\ndfb_state_unlock( CardState *state )\n{\n     D_MAGIC_ASSERT( state, CardState );\n\n     DFB_REGION_ASSERT( &state->clip );\n\n     direct_mutex_unlock( &state->lock );\n}\n\nstatic __inline__ void\ndfb_state_set_from( CardState            *state,\n                    DFBSurfaceBufferRole  role,\n                    DFBSurfaceStereoEye   eye )\n{\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( role == DSBR_FRONT || role == DSBR_BACK || role == DSBR_IDLE );\n     D_ASSERT( eye == DSSE_LEFT || eye == DSSE_RIGHT );\n\n     if (state->from != role || state->from_eye != eye) {\n          state->from     = role;\n          state->from_eye = eye;\n          state->modified = state->modified | SMF_SOURCE | SMF_SOURCE2 | SMF_SOURCE_MASK | SMF_FROM;\n     }\n}\n\nstatic __inline__ void\ndfb_state_set_to( CardState            *state,\n                  DFBSurfaceBufferRole  role,\n                  DFBSurfaceStereoEye   eye )\n{\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( role == DSBR_FRONT || role == DSBR_BACK || role == DSBR_IDLE );\n     D_ASSERT( eye == DSSE_LEFT || eye == DSSE_RIGHT );\n\n     if (state->to != role || state->to_eye != eye) {\n          state->to       = role;\n          state->to_eye   = eye;\n          state->modified = state->modified | SMF_DESTINATION | SMF_TO;\n     }\n}\n\nstatic __inline__ void\ndfb_state_set_clip( CardState       *state,\n                    const DFBRegion *clip )\n{\n     D_MAGIC_ASSERT( state, CardState );\n     DFB_REGION_ASSERT( clip );\n\n     if (!DFB_REGION_EQUAL( state->clip, *clip )) {\n          state->clip     = *clip;\n          state->modified = state->modified | SMF_CLIP;\n     }\n}\n\nstatic __inline__ void\ndfb_state_set_color( CardState      *state,\n                     const DFBColor *color )\n{\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( color != NULL );\n\n     if (!DFB_COLOR_EQUAL( state->color, *color )) {\n          state->color    = *color;\n          state->modified = state->modified | SMF_COLOR;\n     }\n}\n\nstatic __inline__ void\ndfb_state_set_colorkey( CardState         *state,\n                        const DFBColorKey *key )\n{\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( key != NULL );\n\n     if (!DFB_COLORKEY_EQUAL( state->colorkey, *key )) {\n          state->colorkey = *key;\n          state->modified = state->modified | SMF_COLORKEY;\n     }\n}\n\nstatic __inline__ void\ndfb_state_set_source_mask_vals( CardState           *state,\n                                const DFBPoint      *offset,\n                                DFBSurfaceMaskFlags  flags )\n{\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( offset != NULL );\n     D_FLAGS_ASSERT( flags, DSMF_ALL );\n\n     if (!DFB_POINT_EQUAL( state->src_mask_offset, *offset ) || state->src_mask_flags != flags) {\n          state->src_mask_offset = *offset;\n          state->src_mask_flags  = flags;\n\n          state->modified = state->modified | SMF_SOURCE_MASK_VALS;\n     }\n}\n\nstatic __inline__ void\ndfb_state_set_src_colorkey_extended( CardState                 *state,\n                                     const DFBColorKeyExtended *key )\n{\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( key != NULL );\n\n     if (state->src_colorkey_extended.polarity != key->polarity             ||\n         !DFB_COLOR_EQUAL( state->src_colorkey_extended.lower, key->lower ) ||\n         !DFB_COLOR_EQUAL( state->src_colorkey_extended.upper, key->upper )) {\n          state->src_colorkey_extended = *key;\n          state->modified              = state->modified | SMF_SRC_COLORKEY_EXTENDED;\n     }\n}\n\nstatic __inline__ void\ndfb_state_set_dst_colorkey_extended( CardState                 *state,\n                                     const DFBColorKeyExtended *key )\n{\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( key != NULL );\n\n     if (state->dst_colorkey_extended.polarity != key->polarity             ||\n         !DFB_COLOR_EQUAL( state->dst_colorkey_extended.lower, key->lower ) ||\n         !DFB_COLOR_EQUAL( state->dst_colorkey_extended.upper, key->upper )) {\n          state->dst_colorkey_extended = *key;\n          state->modified              = state->modified | SMF_DST_COLORKEY_EXTENDED;\n     }\n}\n\n#define _dfb_state_set_checked(member,flag,state,value)       \\\ndo {                                                          \\\n     D_MAGIC_ASSERT( state, CardState );                      \\\n                                                              \\\n     if ((value) != (state)->member) {                        \\\n          (state)->member   = (value);                        \\\n          (state)->modified = (state)->modified | SMF_##flag; \\\n     }                                                        \\\n} while (0)\n\n#define dfb_state_set_drawing_flags(state,flags)  _dfb_state_set_checked( drawingflags,   DRAWING_FLAGS,  state, flags )\n\n#define dfb_state_set_blitting_flags(state,flags) _dfb_state_set_checked( blittingflags,  BLITTING_FLAGS, state, flags )\n\n#define dfb_state_set_color_index(state,index)    _dfb_state_set_checked( color_index,    COLOR,          state, index )\n\n#define dfb_state_set_src_blend(state,blend)      _dfb_state_set_checked( src_blend,      SRC_BLEND,      state, blend )\n\n#define dfb_state_set_dst_blend(state,blend)      _dfb_state_set_checked( dst_blend,      DST_BLEND,      state, blend )\n\n#define dfb_state_set_src_colorkey(state,key)     _dfb_state_set_checked( src_colorkey,   SRC_COLORKEY,   state, key )\n\n#define dfb_state_set_dst_colorkey(state,key)     _dfb_state_set_checked( dst_colorkey,   DST_COLORKEY,   state, key )\n\n#define dfb_state_set_render_options(state,opts)  _dfb_state_set_checked( render_options, RENDER_OPTIONS, state, opts )\n\n#endif\n"
  },
  {
    "path": "src/core/surface.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreDFB.h>\n#include <core/CoreSurface.h>\n#include <core/core.h>\n#include <core/layer_region.h>\n#include <core/palette.h>\n#include <core/surface.h>\n#include <core/surface_allocation.h>\n#include <core/surface_buffer.h>\n#include <core/surface_client.h>\n#include <core/surface_pool.h>\n#include <core/windowstack.h>\n#include <direct/filesystem.h>\n#include <direct/memcpy.h>\n#include <directfb_util.h>\n#include <fusion/conf.h>\n#include <fusion/hash.h>\n#include <fusion/shmalloc.h>\n#include <gfx/convert.h>\n#include <gfx/util.h>\n\nD_DEBUG_DOMAIN( Core_Surface,         \"Core/Surface\",         \"DirectFB Core Surface\" );\nD_DEBUG_DOMAIN( Core_Surface_Updates, \"Core/Surface/Updates\", \"DirectFB Core Surface Updates\" );\n\n/**********************************************************************************************************************/\n\nstatic __inline__ void\ndfb_surface_set_stereo_eye( CoreSurface         *surface,\n                            DFBSurfaceStereoEye  eye )\n{\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     D_ASSERT( eye & (DSSE_LEFT | DSSE_RIGHT) );\n\n     if (eye & DSSE_LEFT)\n          surface->buffers = surface->left_buffers;\n     else\n          surface->buffers = surface->right_buffers;\n}\n\nstatic __inline__ DFBSurfaceStereoEye\ndfb_surface_get_stereo_eye( CoreSurface *surface )\n{\n     D_MAGIC_ASSERT( surface, CoreSurface );\n\n     if (surface->buffers == surface->left_buffers)\n          return DSSE_LEFT;\n     else\n          return DSSE_RIGHT;\n}\n\nstatic void\nkeep_frame( CoreSurface *surface )\n{\n     CoreSurfaceBuffer *buffer = surface->left_buffers[surface->buffer_indices[surface->flips % surface->num_buffers]];\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p )\\n\", __FUNCTION__, surface );\n\n     D_DEBUG_AT( Core_Surface, \"  -> buffer %p\\n\", buffer );\n\n     if (!buffer->busy++) {\n          CoreSurfaceBuffer *old = NULL;\n\n          fusion_hash_replace( surface->frames, (void*)(long) (surface->flips * 2), buffer, NULL,\n                               (void**) &old );\n\n          D_ASSERT( old == NULL );\n     }\n\n     if (surface->config.caps & DSCAPS_STEREO) {\n          buffer = surface->right_buffers[surface->buffer_indices[surface->flips % surface->num_buffers]];\n\n          D_DEBUG_AT( Core_Surface, \"  -> buffer %p\\n\", buffer );\n\n          if (!buffer->busy++) {\n               CoreSurfaceBuffer *old = NULL;\n\n               fusion_hash_replace( surface->frames, (void*)(long) (surface->flips * 2 + 1), buffer, NULL,\n                                    (void**) &old );\n\n               D_ASSERT( old == NULL );\n          }\n     }\n}\n\nstatic void\nrelease_frame( CoreSurface *surface,\n               u32          flip_count )\n{\n     CoreSurfaceBuffer *buffer;\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p, flip_count %u )\\n\", __FUNCTION__, surface, flip_count );\n\n     buffer = fusion_hash_lookup( surface->frames, (void*)(long) (flip_count * 2) );\n     if (buffer) {\n          D_DEBUG_AT( Core_Surface, \"  -> buffer %p\\n\", buffer );\n\n          if (buffer->busy-- == 1 && (buffer->flags & CSBF_DECOUPLE))\n               dfb_surface_buffer_decouple( buffer );\n\n          fusion_hash_remove( surface->frames, (void*)(long) (flip_count * 2), NULL, NULL );\n     }\n\n     buffer = fusion_hash_lookup( surface->frames, (void*)(long) (flip_count * 2 + 1) );\n     if (buffer) {\n          D_DEBUG_AT( Core_Surface, \"  -> buffer %p\\n\", buffer );\n\n          if (buffer->busy-- == 1 && (buffer->flags & CSBF_DECOUPLE))\n               dfb_surface_buffer_decouple( buffer );\n\n          fusion_hash_remove( surface->frames, (void*)(long) (flip_count * 2 + 1), NULL, NULL );\n     }\n}\n\n/**********************************************************************************************************************/\n\nstatic const ReactionFunc dfb_surface_globals[] = {\n     _dfb_layer_region_surface_listener,\n     _dfb_windowstack_background_image_listener,\n     NULL\n};\n\nstatic bool\nsurface_destructor_buffers_iterator( FusionHash *hash,\n                                     void       *key,\n                                     void       *value,\n                                     void       *ctx )\n{\n     CoreSurface       *surface = ctx;\n     CoreSurfaceBuffer *buffer  = value;\n     int                i;\n\n     buffer->busy = 0;\n\n     dfb_surface_buffer_decouple( buffer );\n\n     for (i = 0; i < surface->num_buffers; i++) {\n          if (surface->buffers[i] == buffer)\n               surface->buffers[i] = NULL;\n     }\n\n     fusion_hash_remove( surface->frames, key, NULL, NULL );\n\n     return true;\n}\n\nstatic void\nsurface_destructor( FusionObject *object,\n                    bool          zombie,\n                    void         *ctx )\n{\n     int                  i;\n     int                  num_eyes;\n     DFBSurfaceStereoEye  eye;\n     CoreSurface         *surface = (CoreSurface*) object;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n\n     D_DEBUG_AT( Core_Surface, \"Destroying surface %p (%dx%d%s)\\n\",\n                 surface, surface->config.size.w, surface->config.size.h, zombie ? \" ZOMBIE\" : \"\" );\n\n     Core_Resource_RemoveSurface( surface );\n\n     CoreSurface_Deinit_Dispatch( &surface->call );\n\n     dfb_surface_lock( surface );\n\n     surface->state |= CSSF_DESTROYED;\n\n     /* Announce surface destruction. */\n     dfb_surface_notify( surface, CSNF_DESTROY );\n\n     dfb_surface_dispatch_event( surface, DSEVT_DESTROYED );\n\n     /* Unlink palette. */\n     if (surface->palette) {\n          dfb_palette_detach_global( surface->palette, &surface->palette_reaction );\n          dfb_palette_unlink( &surface->palette );\n     }\n\n     while (fusion_hash_size( surface->frames ) > 0)\n          fusion_hash_iterate( surface->frames, surface_destructor_buffers_iterator, surface );\n\n     /* Destroy the surface buffers. */\n     num_eyes = surface->config.caps & DSCAPS_STEREO ? 2 : 1;\n     for (eye = DSSE_LEFT; num_eyes > 0; num_eyes--, eye = DSSE_RIGHT) {\n          dfb_surface_set_stereo_eye( surface, eye );\n          for (i = 0; i < surface->num_buffers; i++) {\n               if (surface->buffers[i]) {\n                    dfb_surface_buffer_decouple( surface->buffers[i] );\n                    surface->buffers[i] = NULL;\n               }\n          }\n     }\n\n     dfb_surface_set_stereo_eye( surface, DSSE_LEFT );\n\n     /* Release the system driver specific surface data. */\n     if (surface->data) {\n          SHFREE( surface->shmpool, surface->data );\n          surface->data = NULL;\n     }\n\n     direct_serial_deinit( &surface->serial );\n     direct_serial_deinit( &surface->config_serial );\n\n     dfb_surface_unlock( surface );\n\n     fusion_vector_destroy( &surface->clients );\n\n     fusion_skirmish_destroy( &surface->lock );\n\n     fusion_hash_destroy( surface->frames );\n\n     D_MAGIC_CLEAR( surface );\n\n     /* Destroy the object. */\n     fusion_object_destroy( object );\n}\n\nFusionObjectPool *\ndfb_surface_pool_create( const FusionWorld *world )\n{\n     FusionObjectPool *pool;\n\n     pool = fusion_object_pool_create( \"Surface Pool\",\n                                       sizeof(CoreSurface), sizeof(CoreSurfaceNotification),\n                                       surface_destructor, NULL, world );\n\n     return pool;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_surface_create( CoreDFB                  *core,\n                    const CoreSurfaceConfig  *config,\n                    CoreSurfaceTypeFlags      type,\n                    unsigned long             resource_id,\n                    CorePalette              *palette,\n                    CoreSurface             **ret_surface )\n{\n     DFBResult            ret = DFB_BUG;\n     int                  i;\n     int                  buffers;\n     CoreSurface         *surface;\n     char                 buf[64];\n     int                  num_eyes;\n     DFBSurfaceStereoEye  eye;\n\n     D_ASSERT( core != NULL );\n     D_FLAGS_ASSERT( type, CSTF_ALL );\n     D_MAGIC_ASSERT_IF( palette, CorePalette );\n     D_ASSERT( ret_surface != NULL );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p, %p, %p )\\n\", __FUNCTION__, core, config, ret_surface );\n\n     /* Create the surface object. */\n     surface = dfb_core_create_surface( core );\n     if (!surface)\n          return DFB_FUSION;\n\n     surface->data = NULL;\n\n     if (config) {\n          D_FLAGS_ASSERT( config->flags, CSCONF_ALL );\n\n          surface->config.flags = config->flags;\n\n          if (config->flags & CSCONF_SIZE) {\n               D_DEBUG_AT( Core_Surface, \"  -> %dx%d\\n\", config->size.w, config->size.h );\n\n               surface->config.size = config->size;\n          }\n\n          if (config->flags & CSCONF_FORMAT) {\n               D_DEBUG_AT( Core_Surface, \"  -> %s\\n\", dfb_pixelformat_name( config->format ) );\n\n               surface->config.format = config->format;\n          }\n\n          if (config->flags & CSCONF_COLORSPACE) {\n               D_DEBUG_AT( Core_Surface, \"  -> %s\\n\", dfb_colorspace_name( config->colorspace ) );\n\n               surface->config.colorspace = config->colorspace;\n          }\n\n          if (config->flags & CSCONF_CAPS) {\n               D_DEBUG_AT( Core_Surface, \"  -> caps 0x%08x\\n\", config->caps );\n\n               surface->config.caps = config->caps & ~DSCAPS_ROTATED;\n          }\n\n          if (config->flags & CSCONF_PREALLOCATED) {\n               D_DEBUG_AT( Core_Surface, \"  -> prealloc %p [%u]\\n\",\n                           config->preallocated[0].addr, config->preallocated[0].pitch );\n\n               direct_memcpy( surface->config.preallocated, config->preallocated, sizeof(config->preallocated) );\n\n               surface->config.preallocated_pool_id = config->preallocated_pool_id;\n\n               type |= CSTF_PREALLOCATED;\n          }\n     }\n\n     if (surface->config.caps & DSCAPS_SYSTEMONLY)\n          surface->type = (type & ~CSTF_EXTERNAL) | CSTF_INTERNAL;\n     else if (surface->config.caps & DSCAPS_VIDEOONLY)\n          surface->type = (type & ~CSTF_INTERNAL) | CSTF_EXTERNAL;\n     else\n          surface->type = type & ~(CSTF_INTERNAL | CSTF_EXTERNAL);\n\n     if (surface->config.caps & DSCAPS_SHARED)\n          surface->type |= CSTF_SHARED;\n\n     surface->resource_id = resource_id;\n\n     if (surface->config.caps & DSCAPS_TRIPLE)\n          buffers = 3;\n     else if (surface->config.caps & DSCAPS_DOUBLE)\n          buffers = 2;\n     else {\n          buffers = 1;\n\n          surface->config.caps &= ~DSCAPS_ROTATED;\n     }\n\n     surface->notifications = CSNF_ALL & ~CSNF_FLIP;\n\n     surface->alpha_ramp[0] = 0x00;\n     surface->alpha_ramp[1] = 0x55;\n     surface->alpha_ramp[2] = 0xaa;\n     surface->alpha_ramp[3] = 0xff;\n\n     if (surface->config.caps & DSCAPS_STATIC_ALLOC)\n          surface->config.min_size = surface->config.size;\n\n     surface->shmpool = dfb_core_shmpool( core );\n\n     direct_serial_init( &surface->serial );\n     direct_serial_init( &surface->config_serial );\n     direct_serial_increase( &surface->config_serial );\n\n     fusion_vector_init( &surface->clients, 2, surface->shmpool );\n\n     snprintf( buf, sizeof(buf), \"Surface %dx%d %s %s\", surface->config.size.w, surface->config.size.h,\n               dfb_pixelformat_name( surface->config.format ), dfb_colorspace_name( surface->config.colorspace ) );\n\n     fusion_ref_set_name( &surface->object.ref, buf );\n\n     fusion_skirmish_init2( &surface->lock, buf, dfb_core_world( core ), fusion_config->secure_fusion );\n\n     fusion_reactor_direct( surface->object.reactor, false );\n\n     fusion_hash_create( surface->shmpool, HASH_INT, HASH_PTR, 7, &surface->frames );\n\n     D_MAGIC_SET( surface, CoreSurface );\n\n     if (dfb_config->warn.flags & DCWF_CREATE_SURFACE                         &&\n         dfb_config->warn.create_surface.min_size.w <= surface->config.size.w &&\n         dfb_config->warn.create_surface.min_size.h <= surface->config.size.h)\n          D_WARN( \"create-surface %4dx%4d %6s, buffers %d, caps 0x%08x, type 0x%08x\",\n                  surface->config.size.w, surface->config.size.h, dfb_pixelformat_name( surface->config.format ),\n                  buffers, surface->config.caps, surface->type );\n\n     if (palette) {\n          dfb_surface_set_palette( surface, palette );\n     }\n     else if (DFB_PIXELFORMAT_IS_INDEXED( surface->config.format )) {\n          ret = dfb_surface_init_palette( core, surface );\n          if (ret)\n               goto error;\n     }\n\n     dfb_surface_lock( surface );\n\n     /* Create the surface buffers. */\n     num_eyes = config->caps & DSCAPS_STEREO ? 2 : 1;\n     for (eye = DSSE_LEFT; num_eyes > 0; num_eyes--, eye = DSSE_RIGHT) {\n          dfb_surface_set_stereo_eye( surface, eye );\n          for (i = 0; i < buffers; i++) {\n               ret = dfb_surface_buffer_create( core, surface, (eye == DSSE_RIGHT) ? CSBF_RIGHT : CSBF_NONE, i,\n                                                &surface->buffers[i] );\n               if (ret) {\n                    D_DERROR( ret, \"Core/Surface: Error creating surface buffer!\\n\" );\n                    dfb_surface_unlock( surface );\n                    goto error;\n               }\n\n               dfb_surface_buffer_globalize( surface->buffers[i] );\n\n               if (eye == DSSE_LEFT)\n                    surface->num_buffers++;\n\n               switch (i) {\n                    case 0:\n                         surface->buffer_indices[DSBR_FRONT] = i;\n                    case 1:\n                         surface->buffer_indices[DSBR_BACK] = i;\n                    case 2:\n                         surface->buffer_indices[DSBR_IDLE] = i;\n               }\n          }\n     }\n     dfb_surface_set_stereo_eye( surface, DSSE_LEFT );\n\n     dfb_surface_unlock( surface );\n\n     CoreSurface_Init_Dispatch( core, surface, &surface->call );\n\n     /* Activate the object. */\n     fusion_object_activate( &surface->object );\n\n     if (dfb_config->surface_clear)\n          dfb_surface_clear_buffers( surface );\n\n     /* Return the new surface. */\n     *ret_surface = surface;\n\n     D_DEBUG_AT( Core_Surface, \"  -> %p\\n\", surface );\n\n     return DFB_OK;\n\nerror:\n     num_eyes = config->caps & DSCAPS_STEREO ? 2 : 1;\n     for (eye = DSSE_LEFT; num_eyes > 0; num_eyes--, eye = DSSE_RIGHT) {\n          dfb_surface_set_stereo_eye( surface, eye );\n          for (i = 0; i < MAX_SURFACE_BUFFERS; i++) {\n               if (surface->buffers[i]) {\n                    dfb_surface_buffer_decouple( surface->buffers[i] );\n                    surface->buffers[i] = NULL;\n               }\n          }\n     }\n     dfb_surface_set_stereo_eye( surface, DSSE_LEFT );\n\n     /* Release the system driver specific surface data. */\n     if (surface->data) {\n         SHFREE( surface->shmpool, surface->data );\n         surface->data = NULL;\n     }\n\n     fusion_skirmish_destroy( &surface->lock );\n\n     direct_serial_deinit( &surface->serial );\n     direct_serial_deinit( &surface->config_serial );\n\n     fusion_hash_destroy( surface->frames );\n\n     D_MAGIC_CLEAR( surface );\n\n     fusion_object_destroy( &surface->object );\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_create_simple ( CoreDFB                 *core,\n                            int                      width,\n                            int                      height,\n                            DFBSurfacePixelFormat    format,\n                            DFBSurfaceColorSpace     colorspace,\n                            DFBSurfaceCapabilities   caps,\n                            CoreSurfaceTypeFlags     type,\n                            unsigned long            resource_id,\n                            CorePalette             *palette,\n                            CoreSurface            **ret_surface )\n{\n     CoreSurfaceConfig surface_config;\n\n     D_ASSERT( core != NULL );\n     D_ASSERT( ret_surface != NULL );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p, %dx%d %s, %p )\\n\", __FUNCTION__,\n                 core, width, height, dfb_pixelformat_name( format ), ret_surface );\n\n     surface_config.flags      = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_COLORSPACE | CSCONF_CAPS;\n     surface_config.size.w     = width;\n     surface_config.size.h     = height;\n     surface_config.format     = format;\n     surface_config.colorspace = colorspace;\n     surface_config.caps       = caps;\n\n     return CoreDFB_CreateSurface( core, &surface_config, type, resource_id, palette, ret_surface );\n}\n\nDFBResult\ndfb_surface_init_palette( CoreDFB     *core,\n                          CoreSurface *surface )\n{\n     DFBResult    ret;\n     CorePalette *palette;\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p, %p )\\n\", __FUNCTION__, core, surface );\n\n     ret = dfb_palette_create( core, 1 << DFB_COLOR_BITS_PER_PIXEL( surface->config.format ),\n                               surface->config.colorspace, &palette );\n     if (ret) {\n          D_DERROR( ret, \"Core/Surface: Error creating palette!\\n\" );\n          return ret;\n     }\n\n     switch (surface->config.format) {\n          case DSPF_LUT8:\n               dfb_palette_generate_rgb332_map( palette );\n               break;\n\n          case DSPF_ALUT44:\n               dfb_palette_generate_rgb121_map( palette );\n               break;\n\n          default:\n               break;\n     }\n\n     dfb_surface_set_palette( surface, palette );\n\n     dfb_palette_unref( palette );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_notify( CoreSurface                  *surface,\n                    CoreSurfaceNotificationFlags  flags )\n{\n     DFBResult               ret;\n     CoreSurfaceNotification notification;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     FUSION_SKIRMISH_ASSERT( &surface->lock );\n     D_FLAGS_ASSERT( flags, CSNF_ALL );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p [%u] )\\n\", __FUNCTION__, surface, surface->object.id );\n\n     direct_serial_increase( &surface->serial );\n\n     if (!(surface->state & CSSF_DESTROYED)) {\n          if (!(surface->notifications & flags))\n               return DFB_OK;\n     }\n\n     notification.flags   = flags;\n     notification.surface = surface;\n\n     ret = dfb_surface_dispatch( surface, &notification, dfb_surface_globals );\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_notify_display( CoreSurface       *surface,\n                            CoreSurfaceBuffer *buffer )\n{\n     DFBResult ret;\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n\n     ret = dfb_surface_notify_display2( surface, dfb_surface_buffer_index( buffer ) );\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_notify_display2( CoreSurface *surface,\n                             int          index )\n{\n     DFBResult               ret;\n     CoreSurfaceNotification notification;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     D_ASSERT( index >= 0 );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p, %d )\\n\", __FUNCTION__, surface, index );\n\n     notification.flags   = CSNF_DISPLAY;\n     notification.surface = surface;\n     notification.index   = index;\n\n     ret = dfb_surface_dispatch( surface, &notification, dfb_surface_globals );\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_notify_frame( CoreSurface  *surface,\n                          unsigned int  flip_count )\n{\n     DFBResult               ret;\n     CoreSurfaceNotification notification;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     FUSION_SKIRMISH_ASSERT( &surface->lock );\n\n     D_DEBUG_AT( Core_Surface_Updates, \"%s( %p, count %u )\\n\", __FUNCTION__, surface, flip_count );\n\n     direct_serial_increase( &surface->serial );\n\n     notification.flags      = CSNF_FRAME;\n     notification.surface    = surface;\n     notification.flip_count = flip_count;\n\n     ret = dfb_surface_dispatch_channel( surface, CSCH_FRAME, &notification, sizeof(notification),\n                                         dfb_surface_globals );\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_pool_notify( CoreSurface                  *surface,\n                         CoreSurfaceBuffer            *buffer,\n                         CoreSurfaceAllocation        *allocation,\n                         CoreSurfaceNotificationFlags  flags )\n{\n     DFBResult               ret;\n     CoreSurfaceNotification notification;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     FUSION_SKIRMISH_ASSERT( &surface->lock );\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_ASSERT( buffer->surface == surface );\n     CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n     D_ASSERT( allocation->buffer == buffer );\n     D_FLAGS_ASSERT( flags, CSNF_ALL );\n     D_ASSERT( flags == CSNF_BUFFER_ALLOCATION_DESTROY );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p [%u] )\\n\", __FUNCTION__, surface, surface->object.id );\n\n     if (!(surface->state & CSSF_DESTROYED)) {\n          if (!(surface->notifications & flags))\n               return DFB_OK;\n     }\n\n     /* Prepares and sends a notification message that a change is about to happen to the specified surface buffer\n        pool allocation. The notification message will be received by all pocesses that have listeners attached to\n        the associated CoreSurface's reactor. A copy of all the data needed by the listeners is done in order to wait\n        for all the listeners to complete before the buffer allocation is destroyed along with all of its underlying\n        data structures. */\n\n     notification.flags             = flags;\n     notification.surface           = surface;\n     notification.buffer_no_access  = buffer;\n     notification.surface_data      = surface->data;\n     notification.surface_object_id = surface->object.id;\n\n     D_DEBUG_AT( Core_Surface, \"  -> notifying of surface buffer allocation destruction\\n\" );\n\n     ret = dfb_surface_dispatch( surface, &notification, dfb_surface_globals );\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_flip( CoreSurface *surface, bool swap )\n{\n     DFBResult ret;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p, %sswap )\\n\", __FUNCTION__, surface, swap ? \"\" : \"no \" );\n\n     ret = dfb_surface_flip_buffers( surface, swap );\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_flip_buffers( CoreSurface *surface, bool swap )\n{\n     unsigned int back, front;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     FUSION_SKIRMISH_ASSERT( &surface->lock );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p, %sswap )\\n\", __FUNCTION__, surface, swap ? \"\" : \"no \" );\n\n     if (surface->num_buffers == 0)\n          return DFB_SUSPENDED;\n\n     back  = (surface->flips + DSBR_BACK)  % surface->num_buffers;\n     front = (surface->flips + DSBR_FRONT) % surface->num_buffers;\n\n     D_ASSERT( surface->buffer_indices[back]  < surface->num_buffers );\n     D_ASSERT( surface->buffer_indices[front] < surface->num_buffers );\n\n     if (surface->buffers[surface->buffer_indices[back]]->policy !=\n         surface->buffers[surface->buffer_indices[front]]->policy ||\n         (surface->config.caps & DSCAPS_ROTATED))\n          return DFB_UNSUPPORTED;\n\n     if (swap) {\n          int tmp = surface->buffer_indices[back];\n          surface->buffer_indices[back]  = surface->buffer_indices[front];\n          surface->buffer_indices[front] = tmp;\n     }\n     else\n          surface->flips++;\n\n     D_DEBUG_AT( Core_Surface, \"  -> flips %u\\n\", surface->flips );\n\n     dfb_surface_notify( surface, CSNF_FLIP );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_dispatch_event( CoreSurface         *surface,\n                            DFBSurfaceEventType  type )\n{\n     DFBResult       ret;\n     DFBSurfaceEvent event;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n\n     event.clazz      = DFEC_SURFACE;\n     event.type       = type;\n     event.surface_id = surface->object.id;\n     event.time_stamp = direct_clock_get_time( DIRECT_CLOCK_MONOTONIC );\n\n     ret = dfb_surface_dispatch_channel( surface, CSCH_EVENT, &event, sizeof(DFBSurfaceEvent), NULL );\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_dispatch_update( CoreSurface         *surface,\n                             const DFBRegion     *update,\n                             const DFBRegion     *update_right,\n                             long long            timestamp,\n                             DFBSurfaceFlipFlags  flags )\n{\n     DFBResult       ret;\n     DFBSurfaceEvent event;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     FUSION_SKIRMISH_ASSERT( &surface->lock );\n\n     D_DEBUG_AT( Core_Surface_Updates, \"%s( %p [%u], %p / %p, timestamp %lld )\\n\", __FUNCTION__,\n                 surface, surface->object.id, update, update_right, timestamp );\n\n     event.clazz      = DFEC_SURFACE;\n     event.type       = DSEVT_UPDATE;\n     event.surface_id = surface->object.id;\n     event.flip_count = surface->flips;\n     event.flip_flags = flags;\n     event.time_stamp = timestamp ?: direct_clock_get_time( DIRECT_CLOCK_MONOTONIC );\n\n     surface->last_frame_time = event.time_stamp;\n\n     D_DEBUG_AT( Core_Surface_Updates, \"  -> flip count %u\\n\", event.flip_count );\n\n     if (update) {\n          D_DEBUG_AT( Core_Surface_Updates, \"  -> updated %4d,%4d-%4dx%4d (left)\\n\",\n                      DFB_RECTANGLE_VALS_FROM_REGION( update ) );\n\n          event.update = *update;\n     }\n     else {\n          event.update.x1 = 0;\n          event.update.y1 = 0;\n          event.update.x2 = surface->config.size.w - 1;\n          event.update.y2 = surface->config.size.h - 1;\n     }\n\n     if (update_right) {\n          D_DEBUG_AT( Core_Surface_Updates, \"  -> updated %4d,%4d-%4dx%4d (right)\\n\",\n                      DFB_RECTANGLE_VALS_FROM_REGION( update_right ) );\n\n          event.update_right = *update_right;\n     }\n     else {\n          event.update_right.x1 = 0;\n          event.update_right.y1 = 0;\n          event.update_right.x2 = surface->config.size.w - 1;\n          event.update_right.y2 = surface->config.size.h - 1;\n     }\n\n     ret = dfb_surface_dispatch_channel( surface, CSCH_EVENT, &event, sizeof(DFBSurfaceEvent), NULL );\n     if (ret)\n          return ret;\n\n     D_DEBUG_AT( Core_Surface_Updates, \"  -> clients %d\\n\", fusion_vector_size( &surface->clients ) );\n\n     if (fusion_vector_is_empty( &surface->clients )) {\n          surface->flips_acked = surface->flips;\n\n          dfb_surface_notify_frame( surface, surface->flips_acked );\n     }\n     else\n          keep_frame( surface );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_check_acks( CoreSurface *surface )\n{\n     int                i;\n     CoreSurfaceClient *client;\n     u32                count;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     FUSION_SKIRMISH_ASSERT( &surface->lock );\n\n     D_DEBUG_AT( Core_Surface_Updates, \"%s( %p [%u] )\\n\", __FUNCTION__, surface, surface->object.id );\n\n     count = surface->flips;\n\n     fusion_vector_foreach (client, i, surface->clients) {\n          D_DEBUG_AT( Core_Surface_Updates, \"  -> client %p [%u] (acked %u)\\n\",\n                      client, client->object.id, client->flip_count );\n\n          if (client->flip_count < count)\n               count = client->flip_count;\n     }\n\n     D_DEBUG_AT( Core_Surface_Updates, \"  -> lowest count %u (acked %u)\\n\", count, surface->flips_acked );\n\n     if (count > surface->flips_acked) {\n          for (; surface->flips_acked < count; surface->flips_acked++)\n               release_frame( surface, surface->flips_acked );\n\n          dfb_surface_notify_frame( surface, surface->flips_acked );\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_reconfig( CoreSurface             *surface,\n                      const CoreSurfaceConfig *config )\n{\n     DFBResult           ret;\n     int                 i;\n     int                 buffers;\n     int                 num_eyes;\n     DFBSurfaceStereoEye eye;\n     CoreSurfaceConfig   new_config;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     D_ASSERT( config != NULL );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p, %dx%d %s -> %dx%d %s )\\n\", __FUNCTION__, surface,\n                 surface->config.size.w, surface->config.size.h, dfb_pixelformat_name( surface->config.format ),\n                 (config->flags & CSCONF_SIZE)   ? config->size.w : surface->config.size.w,\n                 (config->flags & CSCONF_SIZE)   ? config->size.h : surface->config.size.h,\n                 (config->flags & CSCONF_FORMAT) ? dfb_pixelformat_name( config->format ) :\n                                                   dfb_pixelformat_name( surface->config.format ) );\n\n     if (config->flags & CSCONF_PREALLOCATED)\n          return DFB_UNSUPPORTED;\n\n     if (fusion_skirmish_prevail( &surface->lock ))\n          return DFB_FUSION;\n\n     if (surface->type & CSTF_PREALLOCATED) {\n          fusion_skirmish_dismiss( &surface->lock );\n          return DFB_UNSUPPORTED;\n     }\n\n     if ((config->flags == CSCONF_SIZE ||\n         ((config->flags == (CSCONF_SIZE | CSCONF_FORMAT)) && (config->format == surface->config.format))) &&\n         config->size.w <= surface->config.min_size.w                                                      &&\n         config->size.h <= surface->config.min_size.h) {\n          surface->config.size = config->size;\n\n          direct_serial_increase( &surface->config_serial );\n\n          fusion_skirmish_dismiss( &surface->lock );\n\n          return DFB_OK;\n     }\n\n     new_config = surface->config;\n\n     if (config->flags & CSCONF_SIZE)\n          new_config.size = config->size;\n\n     if (config->flags & CSCONF_FORMAT)\n          new_config.format = config->format;\n\n     if (config->flags & CSCONF_COLORSPACE)\n          new_config.colorspace = config->colorspace;\n\n     if (config->flags & CSCONF_CAPS)\n          new_config.caps = config->caps & ~DSCAPS_ROTATED;\n\n     if (new_config.caps & DSCAPS_SYSTEMONLY)\n          surface->type = (surface->type & ~CSTF_EXTERNAL) | CSTF_INTERNAL;\n     else if (new_config.caps & DSCAPS_VIDEOONLY)\n          surface->type = (surface->type & ~CSTF_INTERNAL) | CSTF_EXTERNAL;\n     else\n          surface->type = surface->type & ~(CSTF_INTERNAL | CSTF_EXTERNAL);\n\n     if (new_config.caps & DSCAPS_TRIPLE)\n          buffers = 3;\n     else if (new_config.caps & DSCAPS_DOUBLE)\n          buffers = 2;\n     else {\n          buffers = 1;\n\n          new_config.caps &= ~DSCAPS_ROTATED;\n     }\n\n     ret = Core_Resource_CheckSurfaceUpdate( surface, &new_config );\n     if (ret)\n          return ret;\n\n     direct_serial_increase( &surface->config_serial );\n\n     /* Destroy the surface buffers. */\n     num_eyes = surface->config.caps & DSCAPS_STEREO ? 2 : 1;\n     for (eye = DSSE_LEFT; num_eyes > 0; num_eyes--, eye = DSSE_RIGHT) {\n          dfb_surface_set_stereo_eye( surface, eye );\n          for (i = 0; i < surface->num_buffers; i++) {\n               if (surface->buffers[i]) {\n                    dfb_surface_buffer_decouple( surface->buffers[i] );\n                    surface->buffers[i] = NULL;\n               }\n          }\n     }\n     dfb_surface_set_stereo_eye( surface, DSSE_LEFT );\n\n     surface->num_buffers = 0;\n     surface->flips++;\n\n     Core_Resource_UpdateSurface( surface, &new_config );\n\n     surface->config = new_config;\n\n     /* Recreate the surface buffers. */\n     num_eyes = new_config.caps & DSCAPS_STEREO ? 2 : 1;\n     for (eye = DSSE_LEFT; num_eyes > 0; num_eyes--, eye = DSSE_RIGHT) {\n          dfb_surface_set_stereo_eye( surface, eye );\n          for (i = 0; i < buffers; i++) {\n               CoreSurfaceBuffer *buffer;\n\n               ret = dfb_surface_buffer_create( core_dfb, surface, (eye == DSSE_RIGHT) ? CSBF_RIGHT : CSBF_NONE, i,\n                                                &buffer );\n               if (ret) {\n                    D_DERROR( ret, \"Core/Surface: Error creating surface buffer!\\n\" );\n                    goto error;\n               }\n\n               dfb_surface_buffer_globalize( buffer );\n\n               surface->buffers[i] = buffer;\n               if (eye == DSSE_LEFT)\n                    surface->num_buffers++;\n\n               switch (i) {\n                    case 0:\n                         surface->buffer_indices[DSBR_FRONT] = i;\n                    case 1:\n                         surface->buffer_indices[DSBR_BACK] = i;\n                    case 2:\n                         surface->buffer_indices[DSBR_IDLE] = i;\n               }\n          }\n     }\n     dfb_surface_set_stereo_eye( surface, DSSE_LEFT );\n\n     while (fusion_hash_size( surface->frames ) > 0)\n          fusion_hash_iterate( surface->frames, surface_destructor_buffers_iterator, surface );\n\n     dfb_surface_notify( surface, CSNF_SIZEFORMAT );\n\n     if (dfb_config->surface_clear)\n          dfb_surface_clear_buffers( surface );\n\n     fusion_skirmish_dismiss( &surface->lock );\n\n     return DFB_OK;\n\nerror:\n     D_UNIMPLEMENTED();\n\n     fusion_skirmish_dismiss( &surface->lock );\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_reformat( CoreSurface           *surface,\n                      int                    width,\n                      int                    height,\n                      DFBSurfacePixelFormat  format )\n{\n     CoreSurfaceConfig config;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     D_ASSERT( width > 0 );\n     D_ASSERT( height > 0 );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p )\\n\", __FUNCTION__, surface );\n\n     config.flags  = CSCONF_SIZE | CSCONF_FORMAT;\n     config.size.w = width;\n     config.size.h = height;\n     config.format = format;\n\n     return dfb_surface_reconfig( surface, &config );\n}\n\nDFBResult\ndfb_surface_destroy_buffers( CoreSurface *surface )\n{\n     int                 i;\n     int                 num_eyes;\n     DFBSurfaceStereoEye eye;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p )\\n\", __FUNCTION__, surface );\n\n     if (fusion_skirmish_prevail( &surface->lock ))\n          return DFB_FUSION;\n\n     if (surface->type & CSTF_PREALLOCATED) {\n          fusion_skirmish_dismiss( &surface->lock );\n          return DFB_UNSUPPORTED;\n     }\n\n     /* Destroy the surface buffers. */\n     num_eyes = surface->config.caps & DSCAPS_STEREO ? 2 : 1;\n     for (eye = DSSE_LEFT; num_eyes > 0; num_eyes--, eye = DSSE_RIGHT) {\n          dfb_surface_set_stereo_eye( surface, eye );\n          for (i = 0; i < surface->num_buffers; i++) {\n               if (surface->buffers[i]) {\n                    dfb_surface_buffer_decouple( surface->buffers[i] );\n                    surface->buffers[i] = NULL;\n               }\n          }\n     }\n     dfb_surface_set_stereo_eye( surface, DSSE_LEFT );\n\n     surface->num_buffers = 0;\n\n     fusion_skirmish_dismiss( &surface->lock );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_deallocate_buffers( CoreSurface *surface )\n{\n     int                 i;\n     int                 num_eyes;\n     DFBSurfaceStereoEye eye;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p )\\n\", __FUNCTION__, surface );\n\n     if (fusion_skirmish_prevail( &surface->lock ))\n          return DFB_FUSION;\n\n     if (surface->type & CSTF_PREALLOCATED) {\n          fusion_skirmish_dismiss( &surface->lock );\n          return DFB_UNSUPPORTED;\n     }\n\n     /* Deallocate the surface buffers. */\n     num_eyes = surface->config.caps & DSCAPS_STEREO ? 2 : 1;\n     for (eye = DSSE_LEFT; num_eyes > 0; num_eyes--, eye = DSSE_RIGHT) {\n          dfb_surface_set_stereo_eye( surface, eye );\n          for (i = 0; i < surface->num_buffers; i++)\n               dfb_surface_buffer_deallocate( surface->buffers[i] );\n     }\n     dfb_surface_set_stereo_eye( surface, DSSE_LEFT );\n\n     fusion_skirmish_dismiss( &surface->lock );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_destroy( CoreSurface *surface )\n{\n     D_MAGIC_ASSERT( surface, CoreSurface );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p )\\n\", __FUNCTION__, surface );\n\n     if (fusion_skirmish_prevail( &surface->lock ))\n          return DFB_FUSION;\n\n\n     dfb_surface_deallocate_buffers( surface );\n\n     surface->state |= CSSF_DESTROYED;\n\n     fusion_skirmish_dismiss( &surface->lock );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_lock_buffer( CoreSurface            *surface,\n                         DFBSurfaceBufferRole    role,\n                         CoreSurfaceAccessorID   accessor,\n                         CoreSurfaceAccessFlags  access,\n                         CoreSurfaceBufferLock  *ret_lock )\n{\n     DFBResult              ret;\n     CoreSurfaceAllocation *allocation;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p, accessor 0x%02x, access 0x%02x, role %u) <- %dx%d %s\\n\",\n                 __FUNCTION__, surface, accessor, access, role,\n                 surface->config.size.w, surface->config.size.h, dfb_pixelformat_name( surface->config.format ) );\n\n     ret = CoreSurface_PreLockBuffer2( surface, role, dfb_surface_get_stereo_eye( surface ), accessor, access,\n                                       true, &allocation );\n     if (ret)\n          return ret;\n\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n\n     D_DEBUG_AT( Core_Surface, \"  -> PreLockBuffer returned allocation %p (%s)\\n\",\n                 allocation, allocation->pool->desc.name );\n\n     /* Lock the allocation. */\n     dfb_surface_buffer_lock_init( ret_lock, accessor, access );\n\n     ret = dfb_surface_pool_lock( allocation->pool, allocation, ret_lock );\n     if (ret) {\n          D_DERROR( ret, \"Core/Surface: Locking allocation in '%s' failed!\\n\", allocation->pool->desc.name );\n          dfb_surface_buffer_lock_deinit( ret_lock );\n          dfb_surface_allocation_unref( allocation );\n          return ret;\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_lock_buffer2( CoreSurface            *surface,\n                          DFBSurfaceBufferRole    role,\n                          u32                     flip_count,\n                          DFBSurfaceStereoEye     eye,\n                          CoreSurfaceAccessorID   accessor,\n                          CoreSurfaceAccessFlags  access,\n                          CoreSurfaceBufferLock  *ret_lock )\n{\n     DFBResult              ret;\n     CoreSurfaceAllocation *allocation;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p, accessor 0x%02x, access 0x%02x, role %u, count %u, eye %u ) <- %dx%d %s\\n\",\n                 __FUNCTION__, surface, accessor, access, role, flip_count, eye,\n                 surface->config.size.w, surface->config.size.h, dfb_pixelformat_name( surface->config.format ) );\n\n     ret = CoreSurface_PreLockBuffer3( surface, role, flip_count, eye, accessor, access, true, &allocation );\n     if (ret)\n          return ret;\n\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n\n     D_DEBUG_AT( Core_Surface, \"  -> PreLockBuffer returned allocation %p (%s)\\n\",\n                 allocation, allocation->pool->desc.name );\n\n     /* Lock the allocation. */\n     dfb_surface_buffer_lock_init( ret_lock, accessor, access );\n\n     ret = dfb_surface_pool_lock( allocation->pool, allocation, ret_lock );\n     if (ret) {\n          D_DERROR( ret, \"Core/Surface: Locking allocation in '%s' failed!\\n\", allocation->pool->desc.name );\n          dfb_surface_buffer_lock_deinit( ret_lock );\n          dfb_surface_allocation_unref( allocation );\n          return ret;\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_unlock_buffer( CoreSurface           *surface,\n                           CoreSurfaceBufferLock *lock )\n{\n     DFBResult ret;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p )\\n\", __FUNCTION__, surface );\n\n     ret = dfb_surface_buffer_unlock( lock );\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_read_buffer( CoreSurface          *surface,\n                         DFBSurfaceBufferRole  role,\n                         void                 *destination,\n                         int                   pitch,\n                         const DFBRectangle   *rect )\n{\n     DFBResult              ret;\n     int                    y;\n     int                    bytes;\n     DFBRectangle           rectangle;\n     DFBSurfacePixelFormat  format;\n     CoreSurfaceAllocation *allocation;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     D_ASSERT( destination != NULL );\n     D_ASSERT( pitch > 0 );\n     DFB_RECTANGLE_ASSERT_IF( rect );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p, %p, %d )\\n\", __FUNCTION__, surface, destination, pitch );\n\n     /* Determine area. */\n     rectangle.x = 0;\n     rectangle.y = 0;\n     rectangle.w = surface->config.size.w;\n     rectangle.h = surface->config.size.h;\n\n     if (rect && (!dfb_rectangle_intersect( &rectangle, rect ) || !DFB_RECTANGLE_EQUAL( rectangle, *rect )))\n          return DFB_INVAREA;\n\n     /* Calculate bytes per read line. */\n     format = surface->config.format;\n     bytes  = DFB_BYTES_PER_LINE( format, rectangle.w );\n\n     D_DEBUG_AT( Core_Surface, \"  -> %4d,%4d-%4dx%4d (%s)\\n\",\n                 DFB_RECTANGLE_VALS( &rectangle ), dfb_pixelformat_name( format ) );\n\n     ret = CoreSurface_PreLockBuffer2( surface, role, dfb_surface_get_stereo_eye( surface ), CSAID_CPU, CSAF_READ,\n                                       false, &allocation );\n     if (ret == DFB_NOALLOCATION) {\n          for (y = 0; y < rectangle.h; y++) {\n               memset( destination, 0, bytes );\n\n               destination += pitch;\n          }\n\n          return DFB_OK;\n     }\n\n     if (ret)\n          return ret;\n\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n\n     D_DEBUG_AT( Core_Surface, \"  -> PreLockBuffer returned allocation %p (%s)\\n\",\n                 allocation, allocation->pool->desc.name );\n\n     /* Try reading from allocation directly... */\n     ret = dfb_surface_pool_read( allocation->pool, allocation, destination, pitch, &rectangle );\n     if (ret) {\n          /* ...otherwise use fallback method via locking if possible. */\n          if (allocation->access[CSAID_CPU] & CSAF_READ) {\n               CoreSurfaceBufferLock lock;\n\n               /* Lock the allocation. */\n               dfb_surface_buffer_lock_init( &lock, CSAID_CPU, CSAF_READ );\n\n               ret = dfb_surface_pool_lock( allocation->pool, allocation, &lock );\n               if (ret) {\n                    D_DERROR( ret, \"Core/Surface: Locking allocation in '%s' failed!\\n\", allocation->pool->desc.name );\n                    dfb_surface_buffer_lock_deinit( &lock );\n                    dfb_surface_allocation_unref( allocation );\n                    return ret;\n               }\n\n               /* Move to start of read. */\n               lock.addr += DFB_BYTES_PER_LINE( format, rectangle.x ) + rectangle.y * lock.pitch;\n\n               /* Copy the data. */\n               for (y = 0; y < rectangle.h; y++) {\n                    direct_memcpy( destination, lock.addr, bytes );\n\n                    destination += pitch;\n                    lock.addr   += lock.pitch;\n               }\n\n               /* Unlock the allocation. */\n               ret = dfb_surface_pool_unlock( allocation->pool, allocation, &lock );\n               if (ret)\n                    D_DERROR( ret, \"Core/Surface: Unlocking allocation in '%s' failed!\\n\",\n                              allocation->pool->desc.name );\n\n               dfb_surface_buffer_lock_deinit( &lock );\n          }\n     }\n\n     dfb_surface_allocation_unref( allocation );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_write_buffer( CoreSurface          *surface,\n                          DFBSurfaceBufferRole  role,\n                          const void           *source,\n                          int                   pitch,\n                          const DFBRectangle   *rect )\n{\n     DFBResult              ret;\n     DFBRectangle           rectangle;\n     CoreSurfaceAllocation *allocation;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     D_ASSERT( pitch > 0 || source == NULL );\n     DFB_RECTANGLE_ASSERT_IF( rect );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p, %p, %d )\\n\", __FUNCTION__, surface, source, pitch );\n\n     /* Determine area. */\n     rectangle.x = 0;\n     rectangle.y = 0;\n     rectangle.w = surface->config.size.w;\n     rectangle.h = surface->config.size.h;\n\n     if (rect) {\n          if (!dfb_rectangle_intersect( &rectangle, rect )) {\n               D_DEBUG_AT( Core_Surface, \"  -> no intersection!\\n\" );\n               return DFB_INVAREA;\n          }\n\n          if (!DFB_RECTANGLE_EQUAL( rectangle, *rect )) {\n               D_DEBUG_AT( Core_Surface, \"  -> got clipped to %4d,%4d-%4dx%4d!\\n\", DFB_RECTANGLE_VALS( &rectangle ) );\n               return DFB_INVAREA;\n          }\n     }\n\n     D_DEBUG_AT( Core_Surface, \"  -> %4d,%4d-%4dx%4d (%s)\\n\",\n                 DFB_RECTANGLE_VALS( &rectangle ), dfb_pixelformat_name( surface->config.format ) );\n\n     ret = CoreSurface_PreLockBuffer2( surface, role, dfb_surface_get_stereo_eye( surface ), CSAID_CPU, CSAF_WRITE,\n                                       false, &allocation );\n     if (ret)\n          return ret;\n\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n\n     D_DEBUG_AT( Core_Surface, \"  -> PreLockBuffer returned allocation %p (%s)\\n\", allocation,\n                 allocation->pool->desc.name );\n\n     /* Try writing to allocation directly... */\n     ret = source ? dfb_surface_pool_write( allocation->pool, allocation, source, pitch, &rectangle ) : DFB_UNSUPPORTED;\n     if (ret) {\n          /* ...otherwise use fallback method via locking if possible. */\n          if (allocation->access[CSAID_CPU] & CSAF_WRITE) {\n               int                   y;\n               int                   bytes;\n               DFBSurfacePixelFormat format;\n               CoreSurfaceBufferLock lock;\n\n               /* Calculate bytes per written line. */\n               format = surface->config.format;\n               bytes  = DFB_BYTES_PER_LINE( format, rectangle.w );\n\n               /* Lock the allocation. */\n               dfb_surface_buffer_lock_init( &lock, CSAID_CPU, CSAF_WRITE );\n\n               ret = dfb_surface_pool_lock( allocation->pool, allocation, &lock );\n               if (ret) {\n                    D_DERROR( ret, \"Core/Surface: Locking allocation in '%s' failed!\\n\", allocation->pool->desc.name );\n                    dfb_surface_buffer_lock_deinit( &lock );\n                    dfb_surface_allocation_unref( allocation );\n                    return ret;\n               }\n\n               /* Move to start of write. */\n               lock.addr += DFB_BYTES_PER_LINE( format, rectangle.x ) + rectangle.y * lock.pitch;\n\n               /* Copy the data. */\n               for (y = 0; y < rectangle.h; y++) {\n                    if (source) {\n                         direct_memcpy( lock.addr, source, bytes );\n\n                         source += pitch;\n                    }\n                    else\n                         memset( lock.addr, 0, bytes );\n\n                    lock.addr += lock.pitch;\n               }\n\n               /* Unlock the allocation. */\n               ret = dfb_surface_pool_unlock( allocation->pool, allocation, &lock );\n               if (ret)\n                    D_DERROR( ret, \"Core/Surface: Unlocking allocation in '%s' failed!\\n\",\n                              allocation->pool->desc.name );\n\n               dfb_surface_buffer_lock_deinit( &lock );\n          }\n     }\n\n     dfb_surface_allocation_unref( allocation );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_clear_buffers( CoreSurface *surface )\n{\n     D_MAGIC_ASSERT( surface, CoreSurface );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p )\\n\", __FUNCTION__, surface );\n\n     if (surface->num_buffers == 0)\n          return DFB_SUSPENDED;\n\n     if (fusion_skirmish_prevail( &surface->lock ))\n          return DFB_FUSION;\n\n     dfb_gfx_clear( surface, DSBR_FRONT );\n\n     if (surface->config.caps & DSCAPS_FLIPPING)\n          dfb_gfx_clear( surface, DSBR_BACK );\n\n     if (surface->config.caps & DSCAPS_TRIPLE)\n          dfb_gfx_clear( surface, DSBR_IDLE );\n\n     fusion_skirmish_dismiss( &surface->lock );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_dump_buffer( CoreSurface          *surface,\n                         DFBSurfaceBufferRole  role,\n                         const char           *path,\n                         const char           *prefix )\n{\n     DFBResult          ret;\n     CoreSurfaceBuffer *buffer;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     D_ASSERT( path != NULL );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p )\\n\", __FUNCTION__, surface );\n\n     if (fusion_skirmish_prevail( &surface->lock ))\n          return DFB_FUSION;\n\n     if (surface->num_buffers == 0) {\n          fusion_skirmish_dismiss( &surface->lock );\n          return DFB_SUSPENDED;\n     }\n\n     buffer = dfb_surface_get_buffer( surface, role );\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n\n     ret = buffer->allocs.count ? dfb_surface_buffer_dump( buffer, path, prefix ) : DFB_BUFFEREMPTY;\n\n     fusion_skirmish_dismiss( &surface->lock );\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_dump_buffer2( CoreSurface          *surface,\n                          DFBSurfaceBufferRole  role,\n                          DFBSurfaceStereoEye   eye,\n                          const char           *path,\n                          const char           *prefix )\n{\n     DFBResult              ret;\n     int                    num  = -1;\n     int                    i, n;\n     int                    len = (path ? strlen( path ) : 0) + (prefix ? strlen( prefix ) : 0) + 40;\n     char                   filename[len];\n     char                   head[30];\n     bool                   rgb = false;\n     bool                   alpha = false;\n     size_t                 bytes;\n     CorePalette           *palette = NULL;\n     CoreSurfaceAllocation *allocation;\n     CoreSurfaceBufferLock  lock;\n     DirectFile             fd_p, fd_g;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     D_ASSERT( path != NULL );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p )\\n\", __FUNCTION__, surface );\n\n     ret = CoreSurface_PreLockBuffer2( surface, role, eye, CSAID_CPU, CSAF_READ, true, &allocation );\n     if (ret)\n          return ret;\n\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n\n     D_DEBUG_AT( Core_Surface, \"  -> PreLockBuffer returned allocation %p (%s)\\n\",\n                 allocation, allocation->pool->desc.name );\n\n     /* Lock the allocation. */\n     dfb_surface_buffer_lock_init( &lock, CSAID_CPU, CSAF_READ );\n\n     ret = dfb_surface_pool_lock( allocation->pool, allocation, &lock );\n     if (ret) {\n          D_DERROR( ret, \"Core/Surface: Locking allocation in '%s' failed!\\n\", allocation->pool->desc.name );\n          dfb_surface_buffer_lock_deinit( &lock );\n          dfb_surface_allocation_unref( allocation );\n          return ret;\n     }\n\n     /* Check pixel format. */\n     switch (lock.buffer->config.format) {\n          case DSPF_LUT8:\n               palette = surface->palette;\n\n               if (!palette) {\n                    D_BUG( \"no palette\" );\n                    dfb_surface_buffer_unlock( &lock );\n                    return DFB_BUG;\n               }\n\n               if (dfb_palette_ref( palette )) {\n                    dfb_surface_buffer_unlock( &lock );\n                    return DFB_FUSION;\n               }\n\n               rgb = true;\n               /* fall through */\n\n          case DSPF_A8:\n               alpha = true;\n               break;\n\n          case DSPF_ARGB:\n          case DSPF_ABGR:\n          case DSPF_ARGB1555:\n          case DSPF_RGBA5551:\n          case DSPF_ARGB2554:\n          case DSPF_ARGB4444:\n          case DSPF_AiRGB:\n          case DSPF_ARGB8565:\n          case DSPF_AYUV:\n          case DSPF_AVYU:\n               alpha = true;\n               /* fall through */\n\n          case DSPF_RGB332:\n          case DSPF_RGB444:\n          case DSPF_RGB555:\n          case DSPF_BGR555:\n          case DSPF_RGB16:\n          case DSPF_RGB24:\n          case DSPF_BGR24:\n          case DSPF_RGB32:\n          case DSPF_YUY2:\n          case DSPF_UYVY:\n          case DSPF_VYU:\n          case DSPF_I420:\n          case DSPF_YV12:\n          case DSPF_NV12:\n          case DSPF_NV21:\n          case DSPF_Y42B:\n          case DSPF_YV16:\n          case DSPF_NV16:\n          case DSPF_NV61:\n          case DSPF_Y444:\n          case DSPF_YV24:\n          case DSPF_NV24:\n          case DSPF_NV42:\n               rgb = true;\n               break;\n\n          default:\n               D_ERROR( \"Core/Surface: Surface dump for format '%s' is not implemented!\\n\",\n                        dfb_pixelformat_name( lock.buffer->config.format ) );\n               dfb_surface_buffer_unlock( &lock );\n               return DFB_UNSUPPORTED;\n     }\n\n     if (prefix) {\n          /* Find the lowest unused index. */\n          while (++num < 10000) {\n               snprintf( filename, len, \"%s/%s_%04d.ppm\", path, prefix, num );\n\n               ret = direct_access( filename, F_OK );\n               if (ret) {\n                    snprintf( filename, len, \"%s/%s_%04d.pgm\", path, prefix, num );\n                    ret = direct_access( filename, F_OK );\n                    if (ret)\n                         break;\n               }\n          }\n\n          if (num == 10000) {\n               D_ERROR( \"Core/Surface: Could not find an unused index for surface dump!\\n\" );\n               dfb_surface_buffer_unlock( &lock );\n               if (palette)\n                    dfb_palette_unref( palette );\n               return DFB_FAILURE;\n          }\n     }\n\n     /* Create a file with the found index. */\n     if (rgb) {\n          if (prefix)\n               snprintf( filename, len, \"%s/%s_%04d.ppm\", path, prefix, num );\n          else\n               snprintf( filename, len, \"%s.ppm\", path );\n\n          ret = direct_file_open( &fd_p, filename, O_EXCL | O_CREAT | O_WRONLY, 0644 );\n          if (ret) {\n               D_DERROR( ret, \"Core/Surface: Could not open '%s'!\\n\", filename );\n               dfb_surface_buffer_unlock( &lock );\n               if (palette)\n                    dfb_palette_unref( palette );\n               return ret;\n          }\n     }\n\n     /* Create a graymap for the alpha channel using the found index. */\n     if (alpha) {\n          if (prefix)\n               snprintf( filename, len, \"%s/%s_%04d.pgm\", path, prefix, num );\n          else\n               snprintf( filename, len, \"%s.pgm\", path );\n\n          ret = direct_file_open( &fd_g, filename, O_EXCL | O_CREAT | O_WRONLY, 0644 );\n          if (ret) {\n               D_DERROR( ret, \"Core/Surface: Could not open '%s'!\\n\", filename );\n\n               dfb_surface_buffer_unlock( &lock );\n               if (palette)\n                    dfb_palette_unref( palette );\n\n               if (rgb) {\n                    direct_file_close( &fd_p );\n                    if (prefix)\n                         snprintf( filename, len, \"%s/%s_%04d.ppm\", path, prefix, num );\n                    else\n                         snprintf( filename, len, \"%s.ppm\", path );\n                    direct_unlink( filename );\n               }\n\n               return ret;\n          }\n     }\n\n     if (rgb) {\n          /* Write the pixmap header. */\n          snprintf( head, sizeof(head), \"P6\\n%d %d\\n255\\n\", surface->config.size.w, surface->config.size.h );\n          direct_file_write( &fd_p, head, strlen( head ), &bytes );\n     }\n\n     /* Write the graymap header. */\n     if (alpha) {\n          snprintf( head, sizeof(head), \"P5\\n%d %d\\n255\\n\", surface->config.size.w, surface->config.size.h );\n          direct_file_write( &fd_g, head, strlen( head ), &bytes );\n     }\n\n     /* Write the pixmap (and graymap) data. */\n     for (i = 0; i < surface->config.size.h; i++) {\n          int n3;\n\n          /* Prepare one row. */\n          u8  *srces[3]   = { NULL, NULL, NULL };\n          int  pitches[3] = { 0, 0, 0 };\n          u8  *src8;\n\n          dfb_surface_get_data_offsets( &surface->config, lock.addr, lock.pitch, 0, i, 3, srces, pitches );\n          src8 = srces[0];\n\n          /* Write color buffer to pixmap file. */\n          if (rgb) {\n               u8 buf_p[surface->config.size.w*3];\n\n               if (lock.buffer->config.format == DSPF_LUT8) {\n                    for (n = 0, n3 = 0; n < surface->config.size.w; n++, n3 += 3) {\n                         buf_p[n3+0] = palette->entries[src8[n]].r;\n                         buf_p[n3+1] = palette->entries[src8[n]].g;\n                         buf_p[n3+2] = palette->entries[src8[n]].b;\n                    }\n               }\n               else\n                    dfb_convert_to_rgb24( lock.buffer->config.format, lock.buffer->config.colorspace,\n                                          srces[0], pitches[0], srces[1], pitches[1], srces[2], pitches[2],\n                                          surface->config.size.h, buf_p,\n                                          surface->config.size.w * 3, surface->config.size.w, 1 );\n\n               direct_file_write( &fd_p, buf_p, surface->config.size.w * 3, &bytes );\n          }\n\n          /* Write alpha buffer to graymap file. */\n          if (alpha) {\n               u8 buf_g[surface->config.size.w];\n\n               if (lock.buffer->config.format == DSPF_LUT8) {\n                    for (n = 0; n < surface->config.size.w; n++)\n                         buf_g[n] = palette->entries[src8[n]].a;\n               }\n               else\n                    dfb_convert_to_a8( lock.buffer->config.format, srces[0], pitches[0], surface->config.size.h, buf_g,\n                                       surface->config.size.w, surface->config.size.w, 1 );\n\n               direct_file_write( &fd_g, buf_g, surface->config.size.w, &bytes );\n          }\n     }\n\n     /* Unlock the surface buffer. */\n     dfb_surface_buffer_unlock( &lock );\n\n     /* Release the palette. */\n     if (palette)\n          dfb_palette_unref( palette );\n\n     /* Close pixmap file. */\n     if (rgb)\n          direct_file_close( &fd_p );\n\n     /* Close graymap file. */\n     if (alpha)\n          direct_file_close( &fd_g );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_dump_raw_buffer( CoreSurface          *surface,\n                             DFBSurfaceBufferRole  role,\n                             const char           *path,\n                             const char           *prefix )\n{\n     DFBResult          ret;\n     CoreSurfaceBuffer *buffer;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     D_ASSERT( path != NULL );\n     D_ASSERT( prefix != NULL );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p )\\n\", __FUNCTION__, surface );\n\n     if (surface->num_buffers == 0)\n          return DFB_SUSPENDED;\n\n     if (fusion_skirmish_prevail( &surface->lock ))\n          return DFB_FUSION;\n\n     buffer = dfb_surface_get_buffer( surface, role );\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n\n     ret = dfb_surface_buffer_dump_raw( buffer, path, prefix );\n\n     fusion_skirmish_dismiss( &surface->lock );\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_set_palette( CoreSurface *surface,\n                         CorePalette *palette )\n{\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     D_MAGIC_ASSERT_IF( palette, CorePalette );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p )\\n\", __FUNCTION__, surface );\n\n     if (fusion_skirmish_prevail( &surface->lock ))\n          return DFB_FUSION;\n\n     if (surface->palette != palette) {\n          if (surface->palette) {\n               dfb_palette_detach_global( surface->palette, &surface->palette_reaction );\n               dfb_palette_unlink( &surface->palette );\n          }\n\n          if (palette) {\n               dfb_palette_link( &surface->palette, palette );\n               dfb_palette_attach_global( palette, DFB_SURFACE_PALETTE_LISTENER, surface, &surface->palette_reaction );\n          }\n\n          dfb_surface_notify( surface, CSNF_PALETTE_CHANGE );\n     }\n\n     fusion_skirmish_dismiss( &surface->lock );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_set_field( CoreSurface *surface,\n                       int          field )\n{\n     D_MAGIC_ASSERT( surface, CoreSurface );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p )\\n\", __FUNCTION__, surface );\n\n     if (fusion_skirmish_prevail( &surface->lock ))\n          return DFB_FUSION;\n\n     surface->field = field;\n\n     dfb_surface_notify( surface, CSNF_FIELD );\n\n     fusion_skirmish_dismiss( &surface->lock );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_set_alpha_ramp( CoreSurface *surface,\n                            u8           a0,\n                            u8           a1,\n                            u8           a2,\n                            u8           a3 )\n{\n     D_MAGIC_ASSERT( surface, CoreSurface );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p )\\n\", __FUNCTION__, surface );\n\n     if (fusion_skirmish_prevail( &surface->lock ))\n          return DFB_FUSION;\n\n     surface->alpha_ramp[0] = a0;\n     surface->alpha_ramp[1] = a1;\n     surface->alpha_ramp[2] = a2;\n     surface->alpha_ramp[3] = a3;\n\n     dfb_surface_notify( surface, CSNF_ALPHA_RAMP );\n\n     fusion_skirmish_dismiss( &surface->lock );\n\n     return DFB_OK;\n}\n\nCoreSurfaceBuffer *\ndfb_surface_get_buffer( CoreSurface          *surface,\n                        DFBSurfaceBufferRole  role )\n{\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     FUSION_SKIRMISH_ASSERT( &surface->lock );\n     D_ASSERT( surface->num_buffers > 0 );\n     D_ASSERT( role == DSBR_FRONT || role == DSBR_BACK || role == DSBR_IDLE );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p )\\n\", __FUNCTION__, surface );\n\n     return surface->buffers[surface->buffer_indices[role % surface->num_buffers]];\n}\n\nCoreSurfaceBuffer *\ndfb_surface_get_buffer2( CoreSurface          *surface,\n                         DFBSurfaceBufferRole  role,\n                         DFBSurfaceStereoEye   eye )\n{\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     FUSION_SKIRMISH_ASSERT( &surface->lock );\n     D_ASSERT( surface->num_buffers > 0 );\n     D_ASSERT( role == DSBR_FRONT || role == DSBR_BACK || role == DSBR_IDLE );\n     D_ASSERT( eye == DSSE_LEFT || eye == DSSE_RIGHT );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p )\\n\", __FUNCTION__, surface );\n\n     if (eye == DSSE_LEFT)\n          return surface->left_buffers[surface->buffer_indices[role % surface->num_buffers]];\n\n     return surface->right_buffers[surface->buffer_indices[role % surface->num_buffers]];\n}\n\nCoreSurfaceBuffer *\ndfb_surface_get_buffer3( CoreSurface          *surface,\n                         DFBSurfaceBufferRole  role,\n                         DFBSurfaceStereoEye   eye,\n                         u32                   flip_count )\n{\n     CoreSurfaceBuffer *buffer;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     FUSION_SKIRMISH_ASSERT( &surface->lock );\n     D_ASSERT( surface->num_buffers > 0 );\n     D_ASSERT( role == DSBR_FRONT || role == DSBR_BACK || role == DSBR_IDLE );\n     D_ASSERT( eye == DSSE_LEFT || eye == DSSE_RIGHT );\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p, role %u, eye %u, flip_count %u )\\n\", __FUNCTION__, surface, role, eye,\n                 flip_count );\n\n     if (eye == DSSE_LEFT) {\n          buffer = fusion_hash_lookup( surface->frames, (void*)(long) ((flip_count + role) * 2) );\n\n          return buffer ?: surface->left_buffers[surface->buffer_indices[(flip_count + role) % surface->num_buffers]];\n     }\n\n     buffer = fusion_hash_lookup( surface->frames, (void*)(long) ((flip_count + role) * 2 + 1) );\n\n     return buffer ?: surface->right_buffers[surface->buffer_indices[(flip_count + role) % surface->num_buffers]];\n}\n\nReactionResult\n_dfb_surface_palette_listener( const void *msg_data,\n                               void       *ctx )\n{\n     const CorePaletteNotification *notification = msg_data;\n     CoreSurface                   *surface      = ctx;\n\n     if (notification->flags & CPNF_DESTROY)\n          return RS_REMOVE;\n\n     if (notification->flags & CPNF_ENTRIES) {\n          if (fusion_skirmish_prevail( &surface->lock ))\n               return RS_OK;\n\n          dfb_surface_notify( surface, CSNF_PALETTE_UPDATE );\n\n          fusion_skirmish_dismiss( &surface->lock );\n     }\n\n     return RS_OK;\n}\n"
  },
  {
    "path": "src/core/surface.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__SURFACE_H__\n#define __CORE__SURFACE_H__\n\n#include <core/coredefs.h>\n#include <core/coretypes.h>\n#include <direct/serial.h>\n#include <fusion/object.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CSSF_NONE      = 0x00000000, /* None of these. */\n\n     CSSF_DESTROYED = 0x00000001, /* Surface is being or has been destroyed. */\n\n     CSSF_ALL       = 0x00000001  /* All of these. */\n} CoreSurfaceStateFlags;\n\ntypedef enum {\n     CSCONF_NONE         = 0x00000000, /* none of these */\n\n     CSCONF_SIZE         = 0x00000001, /* set size */\n     CSCONF_FORMAT       = 0x00000002, /* set format */\n     CSCONF_CAPS         = 0x00000004, /* set capabilities */\n     CSCONF_COLORSPACE   = 0x00000008, /* set color space */\n     CSCONF_PREALLOCATED = 0x00000010, /* data has been preallocated */\n\n     CSCONF_ALL          = 0x0000001F  /* all of these */\n} CoreSurfaceConfigFlags;\n\nstruct __DFB_CoreSurfaceConfig {\n     CoreSurfaceConfigFlags  flags;\n\n     DFBDimension            size;\n     DFBSurfacePixelFormat   format;\n     DFBSurfaceColorSpace    colorspace;\n     DFBSurfaceCapabilities  caps;\n\n     struct {\n          void              *addr;\n          unsigned long      phys;\n          unsigned long      offset;\n          unsigned int       pitch;\n          void              *handle;\n     } preallocated[MAX_SURFACE_BUFFERS];\n\n     CoreSurfacePoolID       preallocated_pool_id;\n\n     DFBDimension            min_size;\n     DFBSurfaceHintFlags     hints;\n};\n\ntypedef enum {\n     CSTF_NONE         = 0x00000000, /* none of these */\n\n     CSTF_LAYER        = 0x00000001, /* surface for layer */\n     CSTF_WINDOW       = 0x00000002, /* surface for window */\n     CSTF_CURSOR       = 0x00000004, /* surface for cursor */\n     CSTF_FONT         = 0x00000008, /* surface for font */\n     CSTF_SHARED       = 0x00000010, /* accessable by other processes */\n\n     CSTF_INTERNAL     = 0x00000100, /* system memory */\n     CSTF_EXTERNAL     = 0x00000200, /* video memory */\n     CSTF_PREALLOCATED = 0x00000400, /* preallocated memory */\n\n     CSTF_ALL          = 0x0000071F  /* all of these */\n} CoreSurfaceTypeFlags;\n\ntypedef enum {\n     CSNF_NONE                      = 0x00000000, /* none of these */\n\n     CSNF_SIZEFORMAT                = 0x00000001, /* width, height, format */\n\n     CSNF_DESTROY                   = 0x00000008, /* surface is about to be destroyed */\n     CSNF_FLIP                      = 0x00000010, /* surface buffer pointer swapped */\n     CSNF_FIELD                     = 0x00000020, /* active (displayed) field switched */\n     CSNF_PALETTE_CHANGE            = 0x00000040, /* another palette has been set */\n     CSNF_PALETTE_UPDATE            = 0x00000080, /* current palette has been altered */\n     CSNF_ALPHA_RAMP                = 0x00000100, /* alpha ramp was modified */\n     CSNF_DISPLAY                   = 0x00000200, /* surface buffer displayed */\n     CSNF_FRAME                     = 0x00000400, /* flip count ack */\n     CSNF_BUFFER_ALLOCATION_DESTROY = 0x00000800, /* buffer allocation about to be destroyed */\n\n     CSNF_ALL                       = 0x00000FF9  /* all of these */\n} CoreSurfaceNotificationFlags;\n\nstruct __DFB_CoreSurface\n{\n     FusionObject                   object;\n     int                            magic;\n\n     FusionSkirmish                 lock;\n\n     CoreSurfaceStateFlags          state;\n\n     CoreSurfaceConfig              config;\n     CoreSurfaceTypeFlags           type;\n     unsigned long                  resource_id;                         /* layer id, window id, or user specified */\n\n     int                            rotation;\n\n     CoreSurfaceNotificationFlags   notifications;\n\n     DirectSerial                   serial;\n\n     int                            field;\n     u8                             alpha_ramp[4];\n\n     CoreSurfaceBuffer            **buffers;\n     CoreSurfaceBuffer             *left_buffers[MAX_SURFACE_BUFFERS];\n     CoreSurfaceBuffer             *right_buffers[MAX_SURFACE_BUFFERS];\n     int                            num_buffers;\n     int                            buffer_indices[MAX_SURFACE_BUFFERS];\n\n     u32                            flips;\n\n     CorePalette                   *palette;\n     GlobalReaction                 palette_reaction;\n\n     FusionSHMPoolShared           *shmpool;\n\n     void                          *data;                                /* shared system driver-specific data */\n\n     FusionCall                     call;\n\n     FusionVector                   clients;\n     u32                            flips_acked;\n\n     DFBFrameTimeConfig             frametime_config;\n\n     long long                      last_frame_time;\n\n     FusionHash                    *frames;\n\n     DirectSerial                   config_serial;\n};\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CSAF_NONE   = 0x00000000, /* none of these */\n\n     CSAF_READ   = 0x00000001, /* accessor may read */\n     CSAF_WRITE  = 0x00000002, /* accessor may write */\n\n     CSAF_SHARED = 0x00000010, /* other processes can read/write at the same time (shared mapping) */\n\n     CSAF_ALL    = 0x00000013  /* all of these */\n} CoreSurfaceAccessFlags;\n\ntypedef enum {\n     CSCH_EVENT = 0x00000001, /* DFEC_SURFACE DFBSurfaceEvent */\n     CSCH_FRAME = 0x00000002, /* CSNF_FRAME CoreSurfaceNotification */\n} CoreSurfaceChannel;\n\ntypedef struct {\n     CoreSurfaceNotificationFlags  flags;\n     CoreSurface                  *surface;\n\n     /* The following field is used only by the CSNF_DISPLAY message. */\n     int                           index;\n\n     /* The following fields are used only by the CSNF_BUFFER_ALLOCATION_DESTROY message. */\n     CoreSurfaceBuffer            *buffer_no_access;  /* Pointer to associated CoreSurfaceBuffer being destroyed. */\n     void                         *surface_data;      /* CoreSurface's shared driver specific data. */\n     int                           surface_object_id; /* CoreSurface's Fusion ID. */\n\n     unsigned int                  flip_count;\n} CoreSurfaceNotification;\n\n/**********************************************************************************************************************/\n\n/*\n * Creates a pool of surface objects.\n */\nFusionObjectPool  *dfb_surface_pool_create       ( const FusionWorld             *world );\n\n/*\n * Generates dfb_surface_ref(), dfb_surface_attach() etc.\n */\nFUSION_OBJECT_METHODS( CoreSurface, dfb_surface )\n\ntypedef enum {\n     DFB_LAYER_REGION_SURFACE_LISTENER         = 0x00000000,\n     DFB_WINDOWSTACK_BACKGROUND_IMAGE_LISTENER = 0x00000001\n} DFB_SURFACE_GLOBALS;\n\n/**********************************************************************************************************************/\n\nDFBResult          dfb_surface_create            ( CoreDFB                       *core,\n                                                   const CoreSurfaceConfig       *config,\n                                                   CoreSurfaceTypeFlags           type,\n                                                   unsigned long                  resource_id,\n                                                   CorePalette                   *palette,\n                                                   CoreSurface                  **ret_surface );\n\nDFBResult          dfb_surface_create_simple     ( CoreDFB                       *core,\n                                                   int                            width,\n                                                   int                            height,\n                                                   DFBSurfacePixelFormat          format,\n                                                   DFBSurfaceColorSpace           colorspace,\n                                                   DFBSurfaceCapabilities         caps,\n                                                   CoreSurfaceTypeFlags           type,\n                                                   unsigned long                  resource_id,\n                                                   CorePalette                   *palette,\n                                                   CoreSurface                  **ret_surface );\n\nDFBResult          dfb_surface_init_palette      ( CoreDFB                       *core,\n                                                   CoreSurface                   *surface );\n\nDFBResult          dfb_surface_notify            ( CoreSurface                   *surface,\n                                                   CoreSurfaceNotificationFlags   flags );\n\nDFBResult          dfb_surface_notify_display    ( CoreSurface                   *surface,\n                                                  CoreSurfaceBuffer              *buffer );\n\nDFBResult          dfb_surface_notify_display2   ( CoreSurface                   *surface,\n                                                   int                            index );\n\nDFBResult          dfb_surface_notify_frame      ( CoreSurface                   *surface,\n                                                   unsigned int                   flip_count );\n\nDFBResult          dfb_surface_pool_notify       ( CoreSurface                   *surface,\n                                                   CoreSurfaceBuffer             *buffer,\n                                                   CoreSurfaceAllocation         *allocation,\n                                                   CoreSurfaceNotificationFlags   flags );\n\nDFBResult          dfb_surface_flip              ( CoreSurface                   *surface,\n                                                   bool                           swap );\n\nDFBResult          dfb_surface_flip_buffers      ( CoreSurface                   *surface,\n                                                   bool                           swap );\n\nDFBResult          dfb_surface_dispatch_event    ( CoreSurface                   *surface,\n                                                   DFBSurfaceEventType            type );\n\nDFBResult          dfb_surface_dispatch_update   ( CoreSurface                   *surface,\n                                                   const DFBRegion               *update,\n                                                   const DFBRegion               *update_right,\n                                                   long long                      timestamp,\n                                                   DFBSurfaceFlipFlags            flags );\n\nDFBResult          dfb_surface_check_acks        ( CoreSurface                   *surface );\n\nDFBResult          dfb_surface_reconfig          ( CoreSurface                   *surface,\n                                                   const CoreSurfaceConfig       *config );\n\nDFBResult          dfb_surface_reformat          ( CoreSurface                   *surface,\n                                                   int                            width,\n                                                   int                            height,\n                                                   DFBSurfacePixelFormat          format );\n\nDFBResult          dfb_surface_destroy_buffers   ( CoreSurface                   *surface );\n\nDFBResult          dfb_surface_deallocate_buffers( CoreSurface                   *surface );\n\nDFBResult          dfb_surface_destroy           ( CoreSurface                   *surface );\n\nDFBResult          dfb_surface_lock_buffer       ( CoreSurface                   *surface,\n                                                   DFBSurfaceBufferRole           role,\n                                                   CoreSurfaceAccessorID          accessor,\n                                                   CoreSurfaceAccessFlags         access,\n                                                   CoreSurfaceBufferLock         *ret_lock );\n\nDFBResult          dfb_surface_lock_buffer2      ( CoreSurface                   *surface,\n                                                   DFBSurfaceBufferRole           role,\n                                                   u32                            flip_count,\n                                                   DFBSurfaceStereoEye            eye,\n                                                   CoreSurfaceAccessorID          accessor,\n                                                   CoreSurfaceAccessFlags         access,\n                                                   CoreSurfaceBufferLock         *ret_lock );\n\nDFBResult          dfb_surface_unlock_buffer     ( CoreSurface                   *surface,\n                                                   CoreSurfaceBufferLock         *lock );\n\nDFBResult          dfb_surface_read_buffer       ( CoreSurface                   *surface,\n                                                   DFBSurfaceBufferRole           role,\n                                                   void                          *destination,\n                                                   int                            pitch,\n                                                   const DFBRectangle            *rect );\n\nDFBResult          dfb_surface_write_buffer      ( CoreSurface                   *surface,\n                                                   DFBSurfaceBufferRole           role,\n                                                   const void                    *source,\n                                                   int                            pitch,\n                                                   const DFBRectangle            *rect );\n\nDFBResult          dfb_surface_clear_buffers     ( CoreSurface                   *surface );\n\nDFBResult          dfb_surface_dump_buffer       ( CoreSurface                   *surface,\n                                                   DFBSurfaceBufferRole           role,\n                                                   const char                    *path,\n                                                   const char                    *prefix );\n\nDFBResult          dfb_surface_dump_buffer2      ( CoreSurface                   *surface,\n                                                   DFBSurfaceBufferRole           role,\n                                                   DFBSurfaceStereoEye            eye,\n                                                   const char                    *path,\n                                                   const char                    *prefix );\n\nDFBResult          dfb_surface_dump_raw_buffer   ( CoreSurface                   *surface,\n                                                   DFBSurfaceBufferRole           role,\n                                                   const char                    *path,\n                                                   const char                    *prefix );\n\nDFBResult          dfb_surface_set_palette       ( CoreSurface                   *surface,\n                                                   CorePalette                   *palette );\n\nDFBResult          dfb_surface_set_field         ( CoreSurface                   *surface,\n                                                   int                            field );\n\nDFBResult          dfb_surface_set_alpha_ramp    ( CoreSurface                   *surface,\n                                                   u8                             a0,\n                                                   u8                             a1,\n                                                   u8                             a2,\n                                                   u8                             a3 );\n\nCoreSurfaceBuffer *dfb_surface_get_buffer        ( CoreSurface                   *surface,\n                                                   DFBSurfaceBufferRole           role );\n\nCoreSurfaceBuffer *dfb_surface_get_buffer2       ( CoreSurface                   *surface,\n                                                   DFBSurfaceBufferRole           role,\n                                                   DFBSurfaceStereoEye            eye );\n\nCoreSurfaceBuffer *dfb_surface_get_buffer3       ( CoreSurface                   *surface,\n                                                   DFBSurfaceBufferRole           role,\n                                                   DFBSurfaceStereoEye            eye,\n                                                   u32                            flip_count );\n\n/*\n * Global reaction, listen to the palette's surface.\n */\n\nReactionResult    _dfb_surface_palette_listener  ( const void                    *msg_data,\n                                                   void                          *ctx );\n\n/**********************************************************************************************************************/\n\nstatic __inline__ DirectResult\ndfb_surface_lock( CoreSurface *surface )\n{\n     D_MAGIC_ASSERT( surface, CoreSurface );\n\n     return fusion_skirmish_prevail( &surface->lock );\n}\n\nstatic __inline__ DirectResult\ndfb_surface_trylock( CoreSurface *surface )\n{\n     D_MAGIC_ASSERT( surface, CoreSurface );\n\n     return fusion_skirmish_swoop( &surface->lock );\n}\n\nstatic __inline__ DirectResult\ndfb_surface_unlock( CoreSurface *surface )\n{\n     D_MAGIC_ASSERT( surface, CoreSurface );\n\n     return fusion_skirmish_dismiss( &surface->lock );\n}\n\nstatic __inline__ void\ndfb_surface_get_data_offsets( const CoreSurfaceConfig  *config,\n                              const void               *data,\n                              int                       pitch,\n                              int                       x,\n                              int                       y,\n                              unsigned int              num,\n                              u8                      **pointers,\n                              int                      *pitches )\n{\n     D_ASSERT( config != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( pitch > 0 );\n     D_ASSERT( x >= 0 );\n     D_ASSERT( x < config->size.w );\n     D_ASSERT( y >= 0 );\n     D_ASSERT( y < config->size.h );\n     D_ASSERT( !num || (num && pointers && pitches) );\n\n     if (!num)\n          return;\n\n     switch (config->format) {\n          case DSPF_NV12:\n          case DSPF_NV21:\n          case DSPF_NV16:\n          case DSPF_NV61:\n          case DSPF_NV24:\n          case DSPF_NV42:\n               if (num < 2)\n                    return;\n               break;\n\n          case DSPF_I420:\n          case DSPF_YV12:\n          case DSPF_Y42B:\n          case DSPF_YV16:\n          case DSPF_Y444:\n          case DSPF_YV24:\n               if (num < 3)\n                    return;\n               break;\n\n          default:\n               if (num < 1)\n                    return;\n               break;\n     }\n\n     if (config->caps & DSCAPS_SEPARATED) {\n          if (y & 1)\n               y += config->size.h;\n\n          y >>= 1;\n     }\n\n     switch (config->format) {\n          case DSPF_NV12:\n          case DSPF_NV21:\n               pitches[1]  = pitch;\n               pointers[1] = (u8*) data\n                             + pitch * config->size.h\n                             + pitches[1] * y / 2\n                             + DFB_BYTES_PER_LINE( config->format, x / 2 );\n               break;\n\n          case DSPF_NV16:\n          case DSPF_NV61:\n               pitches[1]  = pitch;\n               pointers[1] = (u8*) data\n                             + pitch * config->size.h\n                             + pitches[1] * y\n                             + DFB_BYTES_PER_LINE( config->format, x / 2 );\n               break;\n\n          case DSPF_NV24:\n          case DSPF_NV42:\n               pitches[1]  = pitch;\n               pointers[1] = (u8*) data\n                             + pitch * config->size.h\n                             + pitches[1] * y\n                             + DFB_BYTES_PER_LINE( config->format, x );\n               break;\n\n          case DSPF_I420:\n               pitches[1]  = pitches[2] = pitch / 2;\n               pointers[1] = (u8*) data\n                             + pitch * config->size.h\n                             + pitches[1] * y / 2\n                             + DFB_BYTES_PER_LINE( config->format, x / 2 );\n               pointers[2] = (u8*) data\n                             + pitch * config->size.h\n                             + pitches[1] * config->size.h / 2\n                             + pitches[2] * y / 2\n                             + DFB_BYTES_PER_LINE( config->format, x / 2 );\n               break;\n\n          case DSPF_YV12:\n               pitches[1]  = pitches[2] = pitch / 2;\n               pointers[2] = (u8*) data\n                             + pitch * config->size.h\n                             + pitches[2] * y / 2\n                             + DFB_BYTES_PER_LINE( config->format, x / 2 );\n               pointers[1] = (u8*) data\n                             + pitch * config->size.h\n                             + pitches[2] * config->size.h / 2\n                             + pitches[1] * y / 2\n                             + DFB_BYTES_PER_LINE( config->format, x / 2 );\n               break;\n\n          case DSPF_Y42B:\n               pitches[1]  = pitches[2] = pitch / 2;\n               pointers[1] = (u8*) data\n                             + pitch * config->size.h\n                             + pitches[1] * y\n                             + DFB_BYTES_PER_LINE( config->format, x / 2 );\n               pointers[2] = (u8*) data\n                             + pitch * config->size.h\n                             + pitches[1] * config->size.h\n                             + pitches[2] * y\n                             + DFB_BYTES_PER_LINE( config->format, x / 2 );\n               break;\n\n          case DSPF_YV16:\n               pitches[1]  = pitches[2] = pitch / 2;\n               pointers[2] = (u8*) data\n                             + pitch * config->size.h\n                             + pitches[2] * y\n                             + DFB_BYTES_PER_LINE( config->format, x / 2 );\n               pointers[1] = (u8*) data\n                             + pitch * config->size.h\n                             + pitches[2] * config->size.h\n                             + pitches[1] * y\n                             + DFB_BYTES_PER_LINE( config->format, x / 2 );\n               break;\n\n          case DSPF_Y444:\n               pitches[1]  = pitches[2] = pitch;\n               pointers[1] = (u8*) data\n                             + pitch * config->size.h\n                             + pitches[1] * y\n                             + DFB_BYTES_PER_LINE( config->format, x );\n               pointers[2] = (u8*) data\n                             + pitch * config->size.h\n                             + pitches[1] * config->size.h\n                             + pitches[2] * y\n                             + DFB_BYTES_PER_LINE( config->format, x );\n               break;\n\n          case DSPF_YV24:\n               pitches[1]  = pitches[2] = pitch;\n               pointers[2] = (u8*) data\n                             + pitch * config->size.h\n                             + pitches[2] * y\n                             + DFB_BYTES_PER_LINE( config->format, x );\n               pointers[1] = (u8*) data\n                             + pitch * config->size.h\n                             + pitches[2] * config->size.h\n                             + pitches[1] * y\n                             + DFB_BYTES_PER_LINE( config->format, x );\n               break;\n\n          default:\n               break;\n     }\n\n     pointers[0] = (u8*) data + pitch * y + DFB_BYTES_PER_LINE( config->format, x );\n     pitches[0]  = pitch;\n}\n\nstatic __inline__ void\ndfb_surface_calc_buffer_size( CoreSurface *surface,\n                              int          byte_align,\n                              int          pixel_align,\n                              int         *ret_pitch,\n                              int         *ret_size )\n{\n     DFBSurfacePixelFormat format;\n     int                   width;\n     int                   pitch;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n\n     format = surface->config.format;\n\n     width = direct_util_align( surface->config.size.w, pixel_align );\n     pitch = direct_util_align( DFB_BYTES_PER_LINE( format, width ), byte_align );\n\n     if (ret_pitch)\n          *ret_pitch = pitch;\n\n     if (ret_size)\n          *ret_size = pitch * DFB_PLANE_MULTIPLY( format, surface->config.size.h );\n}\n\n#endif\n"
  },
  {
    "path": "src/core/surface_allocation.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreSurfaceAllocation.h>\n#include <core/core.h>\n#include <core/gfxcard.h>\n#include <core/surface_allocation.h>\n#include <core/surface_buffer.h>\n#include <core/surface_pool_bridge.h>\n#include <direct/memcpy.h>\n#include <directfb_util.h>\n#include <fusion/shmalloc.h>\n\nD_DEBUG_DOMAIN( Core_SurfAllocation, \"Core/SurfAllocation\", \"DirectFB Core Surface Allocation\" );\n\n/**********************************************************************************************************************/\n\nstatic void\nsurface_allocation_destructor( FusionObject *object,\n                               bool          zombie,\n                               void         *ctx )\n{\n     CoreSurfaceAllocation *allocation = (CoreSurfaceAllocation*) object;\n\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n\n     D_DEBUG_AT( Core_SurfAllocation, \"Destroying allocation %p (%d%s)\\n\",\n                 allocation, allocation->size, zombie ? \" ZOMBIE\" : \"\" );\n\n     CoreSurfaceAllocation_Deinit_Dispatch( &allocation->call );\n\n     if (!D_FLAGS_IS_SET( allocation->flags, CSALF_INITIALIZING )) {\n          if (allocation->surface)\n               dfb_surface_lock( allocation->surface );\n\n          CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n          dfb_surface_pool_deallocate( allocation->pool, allocation );\n\n          if (allocation->surface)\n               dfb_surface_unlock( allocation->surface );\n     }\n\n     if (allocation->data)\n          SHFREE( allocation->pool->shmpool, allocation->data );\n\n     direct_serial_deinit( &allocation->serial );\n\n     D_MAGIC_CLEAR( allocation );\n\n     /* Destroy the object. */\n     fusion_object_destroy( object );\n}\n\nFusionObjectPool *\ndfb_surface_allocation_pool_create( const FusionWorld *world )\n{\n     FusionObjectPool *pool;\n\n     pool = fusion_object_pool_create( \"Surface Allocation Pool\",\n                                       sizeof(CoreSurfaceAllocation), sizeof(CoreSurfaceAllocationNotification),\n                                       surface_allocation_destructor, NULL, world );\n\n     return pool;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_surface_allocation_create( CoreDFB                *core,\n                               CoreSurfaceBuffer      *buffer,\n                               CoreSurfacePool        *pool,\n                               CoreSurfaceAllocation **ret_allocation )\n{\n     CoreSurfaceAllocation *allocation;\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n     D_ASSERT( pool != NULL );\n     D_ASSERT( ret_allocation != NULL );\n\n     D_DEBUG_AT( Core_SurfAllocation, \"%s( %dx%d %s )\\n\", __FUNCTION__,\n                 buffer->config.size.w, buffer->config.size.h, dfb_pixelformat_name( buffer->config.format ) );\n\n     /* Create the allocation object. */\n     allocation = dfb_core_create_surface_allocation( core );\n     if (!allocation)\n          return DFB_FUSION;\n\n     allocation->buffer      = buffer;\n     allocation->surface     = buffer->surface;\n     allocation->pool        = pool;\n     allocation->flags       = CSALF_INITIALIZING;\n     allocation->access      = pool->desc.access;\n     allocation->config      = buffer->config;\n     allocation->type        = buffer->type;\n     allocation->resource_id = buffer->resource_id;\n     allocation->index       = buffer->index;\n     allocation->buffer_id   = buffer->object.id;\n\n     if (pool->alloc_data_size) {\n          allocation->data = SHCALLOC( pool->shmpool, 1, pool->alloc_data_size );\n          if (!allocation->data) {\n               fusion_object_destroy( &allocation->object );\n               return D_OOSHM();\n          }\n     }\n\n     direct_serial_init( &allocation->serial );\n\n     fusion_ref_add_permissions( &allocation->object.ref, 0, FUSION_REF_PERMIT_REF_UNREF_LOCAL );\n\n     CoreSurfaceAllocation_Init_Dispatch( core, allocation, &allocation->call );\n\n     D_MAGIC_SET( allocation, CoreSurfaceAllocation );\n\n     /* Activate the object. */\n     fusion_object_activate( &allocation->object );\n\n     /* Return the new allocation. */\n     *ret_allocation = allocation;\n\n     D_DEBUG_AT( Core_SurfAllocation, \"  -> %p\\n\", allocation );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_allocation_decouple( CoreSurfaceAllocation *allocation )\n{\n     int                    i;\n     int                    locks;\n     CoreSurfaceBuffer     *buffer;\n     CoreSurfaceAllocation *alloc;\n\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( allocation->buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( allocation->surface, CoreSurface );\n     D_ASSERT( allocation->surface == allocation->buffer->surface );\n\n     D_DEBUG_AT( Core_SurfAllocation, \"%s( %p )\\n\", __FUNCTION__, allocation );\n\n     buffer = allocation->buffer;\n\n     /* Indicate that this surface buffer pool allocation is about to be destroyed. */\n     dfb_surface_pool_notify( allocation->surface, buffer, allocation, CSNF_BUFFER_ALLOCATION_DESTROY );\n\n     allocation->buffer  = NULL;\n     allocation->surface = NULL;\n\n     fusion_vector_remove( &buffer->allocs, fusion_vector_index_of( &buffer->allocs, allocation ) );\n\n     locks = dfb_surface_allocation_locks( allocation );\n     if (!locks) {\n          if (allocation->accessed[CSAID_GPU] & (CSAF_READ | CSAF_WRITE))\n               /* Wait for the operation to finish. */\n               dfb_gfxcard_wait_serial( &allocation->gfx_serial );\n\n          dfb_surface_pool_deallocate( allocation->pool, allocation );\n     }\n\n     /* Reset 'read' allocation pointer of buffer. */\n     if (buffer->read == allocation)\n          buffer->read = NULL;\n\n     /* Update 'written' allocation pointer of buffer. */\n     if (buffer->written == allocation) {\n          /* Reset pointer first. */\n          buffer->written = NULL;\n\n          /* Iterate through remaining allocations. */\n          fusion_vector_foreach (alloc, i, buffer->allocs) {\n               CORE_SURFACE_ALLOCATION_ASSERT( alloc );\n\n               /* Check if allocation is up to date and set it as 'written' allocation. */\n               if (direct_serial_check( &alloc->serial, &buffer->serial )) {\n                    buffer->written = alloc;\n                    break;\n               }\n          }\n     }\n\n     dfb_surface_allocation_unlink( &allocation );\n\n     return DFB_OK;\n}\n\nstatic void\ntransfer_buffer( const CoreSurfaceConfig *config,\n                 const char              *src,\n                 char                    *dst,\n                 int                      srcpitch,\n                 int                      dstpitch )\n{\n     int i;\n\n     D_DEBUG_AT( Core_SurfAllocation, \"%s( %p, %p [%d] -> %p [%d] ) <- %d\\n\", __FUNCTION__,\n                 config, src, srcpitch, dst, dstpitch, config->size.h );\n\n     D_ASSERT( src != NULL );\n     D_ASSERT( dst != NULL );\n     D_ASSERT( srcpitch > 0 );\n     D_ASSERT( dstpitch > 0 );\n     D_ASSERT( srcpitch >= DFB_BYTES_PER_LINE( config->format, config->size.w ) );\n     D_ASSERT( dstpitch >= DFB_BYTES_PER_LINE( config->format, config->size.w ) );\n\n     for (i = 0; i < config->size.h; i++) {\n          direct_memcpy( dst, src, DFB_BYTES_PER_LINE( config->format, config->size.w ) );\n          src += srcpitch;\n          dst += dstpitch;\n     }\n\n     switch (config->format) {\n          case DSPF_I420:\n          case DSPF_YV12:\n               for (i = 0; i < config->size.h; i++) {\n                    direct_memcpy( dst, src, DFB_BYTES_PER_LINE( config->format, config->size.w / 2 ) );\n                    src += srcpitch / 2;\n                    dst += dstpitch / 2;\n               }\n               break;\n\n          case DSPF_NV12:\n          case DSPF_NV21:\n               for (i = 0; i < config->size.h / 2; i++) {\n                    direct_memcpy( dst, src, DFB_BYTES_PER_LINE( config->format, config->size.w ) );\n                    src += srcpitch;\n                    dst += dstpitch;\n               }\n               break;\n\n          case DSPF_Y42B:\n          case DSPF_YV16:\n               for (i = 0; i < config->size.h * 2; i++) {\n                    direct_memcpy( dst, src, DFB_BYTES_PER_LINE( config->format, config->size.w / 2 ) );\n                    src += srcpitch / 2;\n                    dst += dstpitch / 2;\n               }\n               break;\n\n          case DSPF_NV16:\n          case DSPF_NV61:\n               for (i = 0; i < config->size.h; i++) {\n                    direct_memcpy( dst, src, DFB_BYTES_PER_LINE( config->format, config->size.w ) );\n                    src += srcpitch;\n                    dst += dstpitch;\n               }\n               break;\n\n          case DSPF_Y444:\n          case DSPF_YV24:\n               for (i = 0; i < config->size.h * 2; i++) {\n                    direct_memcpy( dst, src, DFB_BYTES_PER_LINE( config->format, config->size.w ) );\n                    src += srcpitch;\n                    dst += dstpitch;\n               }\n               break;\n\n          case DSPF_NV24:\n          case DSPF_NV42:\n               for (i = 0; i < config->size.h; i++) {\n                    direct_memcpy( dst, src, DFB_BYTES_PER_LINE( config->format, config->size.w * 2 ) );\n                    src += srcpitch;\n                    dst += dstpitch;\n               }\n               break;\n\n          default:\n               break;\n     }\n}\n\nstatic DFBResult\nallocation_update_copy( CoreSurfaceAllocation *allocation,\n                        CoreSurfaceAllocation *source )\n{\n     DFBResult             ret;\n     CoreSurfaceBufferLock src;\n     CoreSurfaceBufferLock dst;\n\n     D_DEBUG_AT( Core_SurfAllocation, \"%s( %p )\\n\", __FUNCTION__, allocation );\n\n     D_ASSERT( allocation != source );\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( source, CoreSurfaceAllocation );\n\n     /* Lock the source allocation. */\n     dfb_surface_buffer_lock_init( &src, CSAID_CPU, CSAF_READ );\n\n     dfb_surface_pool_prelock( source->pool, source, CSAID_CPU, CSAF_READ );\n\n     ret = dfb_surface_pool_lock( source->pool, source, &src );\n     if (ret) {\n          D_DERROR( ret, \"Core/SurfAllocation: Could not lock source for transfer!\\n\" );\n          dfb_surface_buffer_lock_deinit( &src );\n          return ret;\n     }\n\n     /* Lock the destination allocation. */\n     dfb_surface_buffer_lock_init( &dst, CSAID_CPU, CSAF_WRITE );\n\n     dfb_surface_pool_prelock( allocation->pool, allocation, CSAID_CPU, CSAF_WRITE );\n\n     allocation->accessed[CSAID_CPU] |= CSAF_WRITE;\n     source->accessed[CSAID_CPU]     |= CSAF_READ;\n\n     ret = dfb_surface_pool_lock( allocation->pool, allocation, &dst );\n     if (ret) {\n          D_DERROR( ret, \"Core/SurfAllocation: Could not lock destination for transfer!\\n\" );\n          dfb_surface_pool_unlock( source->pool, source, &src );\n          dfb_surface_buffer_lock_deinit( &dst );\n          dfb_surface_buffer_lock_deinit( &src );\n          return ret;\n     }\n\n     transfer_buffer( &allocation->config, (char*) src.addr, (char*) dst.addr, src.pitch, dst.pitch );\n\n     dfb_surface_pool_unlock( allocation->pool, allocation, &dst );\n     dfb_surface_pool_unlock( source->pool, source, &src );\n\n     dfb_surface_buffer_lock_deinit( &dst );\n     dfb_surface_buffer_lock_deinit( &src );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nallocation_update_write( CoreSurfaceAllocation *allocation,\n                         CoreSurfaceAllocation *source )\n{\n     DFBResult             ret;\n     CoreSurfaceBufferLock src;\n\n     D_DEBUG_AT( Core_SurfAllocation, \"%s( %p )\\n\", __FUNCTION__, allocation );\n\n     D_ASSERT( allocation != source );\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( source, CoreSurfaceAllocation );\n\n     /* Lock the source allocation. */\n     dfb_surface_buffer_lock_init( &src, CSAID_CPU, CSAF_READ );\n\n     dfb_surface_pool_prelock( source->pool, source, CSAID_CPU, CSAF_READ );\n\n     source->accessed[CSAID_CPU] |= source->accessed[CSAID_CPU];\n\n     ret = dfb_surface_pool_lock( source->pool, source, &src );\n     if (ret) {\n          D_DERROR( ret, \"Core/SurfAllocation: Could not lock source for transfer!\\n\" );\n          dfb_surface_buffer_lock_deinit( &src );\n          return ret;\n     }\n\n     /* Write to the destination allocation. */\n     ret = dfb_surface_pool_write( allocation->pool, allocation, (char*) src.addr, src.pitch, NULL );\n     if (ret)\n          D_DERROR( ret, \"Core/SurfAllocation: Could not write from destination allocation!\\n\" );\n\n     dfb_surface_pool_unlock( source->pool, source, &src );\n\n     dfb_surface_buffer_lock_deinit( &src );\n\n     return ret;\n}\n\nstatic DFBResult\nallocation_update_read( CoreSurfaceAllocation *allocation,\n                        CoreSurfaceAllocation *source )\n{\n     DFBResult             ret;\n     CoreSurfaceBufferLock dst;\n\n     D_DEBUG_AT( Core_SurfAllocation, \"%s( %p )\\n\", __FUNCTION__, allocation );\n\n     D_ASSERT( allocation != source );\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( source, CoreSurfaceAllocation );\n\n     /* Lock the destination allocation. */\n     dfb_surface_buffer_lock_init( &dst, CSAID_CPU, CSAF_WRITE );\n\n     dfb_surface_pool_prelock( allocation->pool, allocation, CSAID_CPU, CSAF_WRITE );\n\n     allocation->accessed[CSAID_CPU] |= CSAF_READ;\n\n     ret = dfb_surface_pool_lock( allocation->pool, allocation, &dst );\n     if (ret) {\n          D_DERROR( ret, \"Core/SurfAllocation: Could not lock destination for transfer!\\n\" );\n          dfb_surface_buffer_lock_deinit( &dst );\n          return ret;\n     }\n\n     /* Read from the source allocation. */\n     ret = dfb_surface_pool_read( source->pool, source, dst.addr, dst.pitch, NULL );\n     if (ret)\n          D_DERROR( ret, \"Core/SurfAllocation: Could not read from source allocation!\\n\" );\n\n     dfb_surface_pool_unlock( allocation->pool, allocation, &dst );\n\n     dfb_surface_buffer_lock_deinit( &dst );\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_allocation_update( CoreSurfaceAllocation  *allocation,\n                               CoreSurfaceAccessFlags  access )\n{\n     DFBResult              ret;\n     int                    i;\n     CoreSurfaceAllocation *alloc;\n     CoreSurfaceBuffer     *buffer;\n\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( allocation->buffer, CoreSurfaceBuffer );\n     D_FLAGS_ASSERT( access, CSAF_ALL );\n\n     D_DEBUG_AT( Core_SurfAllocation, \"%s( %p )\\n\", __FUNCTION__, allocation );\n\n     buffer = allocation->buffer;\n\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n     FUSION_SKIRMISH_ASSERT( &buffer->surface->lock );\n\n     if (direct_serial_update( &allocation->serial, &buffer->serial ) && buffer->written) {\n          CoreSurfaceAllocation *source = buffer->written;\n\n          D_ASSUME( allocation != source );\n\n          D_DEBUG_AT( Core_SurfAllocation, \"  -> alloc/written buffer %p/%p\\n\", allocation->buffer, source->buffer );\n\n          D_MAGIC_ASSERT( source, CoreSurfaceAllocation );\n          D_ASSERT( source->buffer == allocation->buffer );\n\n          D_DEBUG_AT( Core_SurfAllocation, \"  -> updating allocation %p from %p...\\n\", allocation, source );\n\n          ret = dfb_surface_pool_bridges_transfer( buffer, source, allocation, NULL, 0 );\n          if (ret) {\n               if ((source->access[CSAID_CPU] & CSAF_READ) && (allocation->access[CSAID_CPU] & CSAF_WRITE))\n                    ret = allocation_update_copy( allocation, source );\n               else if (source->access[CSAID_CPU] & CSAF_READ)\n                    ret = allocation_update_write( allocation, source );\n               else if (allocation->access[CSAID_CPU] & CSAF_WRITE)\n                    ret = allocation_update_read( allocation, source );\n               else {\n                    D_WARN( \"allocation update: '%s' -> '%s'\", source->pool->desc.name, allocation->pool->desc.name );\n                    D_UNIMPLEMENTED();\n                    ret = DFB_UNSUPPORTED;\n               }\n          }\n\n          if (ret) {\n               D_DERROR( ret, \"Core/SurfAllocation: Updating allocation failed!\\n\" );\n               return ret;\n          }\n     }\n\n     if (access & CSAF_WRITE) {\n          D_DEBUG_AT( Core_SurfAllocation, \"  -> increasing serial...\\n\" );\n\n          direct_serial_increase( &buffer->serial );\n\n          direct_serial_copy( &allocation->serial, &buffer->serial );\n\n          buffer->written = allocation;\n          buffer->read    = NULL;\n\n          /* Zap volatile allocations (freed when no longer up to date). */\n          fusion_vector_foreach (alloc, i, buffer->allocs) {\n               D_MAGIC_ASSERT( alloc, CoreSurfaceAllocation );\n\n               if (alloc != allocation && (alloc->flags & CSALF_VOLATILE)) {\n                    dfb_surface_allocation_decouple( alloc );\n                    i--;\n               }\n          }\n     }\n     else\n          buffer->read = allocation;\n\n     /* Zap all other allocations. */\n     if (dfb_config->thrifty_surface_buffers) {\n          buffer->written = buffer->read = allocation;\n\n          fusion_vector_foreach (alloc, i, buffer->allocs) {\n               D_MAGIC_ASSERT( alloc, CoreSurfaceAllocation );\n\n               /* Don't zap preallocated which would not really free up memory, but just loose the handle. */\n               if (alloc != allocation && !(alloc->flags & (CSALF_PREALLOCATED | CSALF_MUCKOUT))) {\n                    dfb_surface_allocation_decouple( alloc );\n                    i--;\n               }\n          }\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_allocation_dump( CoreSurfaceAllocation *allocation,\n                             const char            *directory,\n                             const char            *prefix,\n                             bool                   raw )\n{\n     DFBResult        ret = DFB_OK;\n     CoreSurfacePool *pool;\n\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( allocation->pool, CoreSurfacePool );\n     D_ASSERT( directory != NULL );\n\n     D_DEBUG_AT( Core_SurfAllocation, \"%s( %p, '%s', '%s' )\\n\", __FUNCTION__, allocation, directory, prefix );\n\n     pool = allocation->pool;\n\n     if (D_FLAGS_IS_SET( pool->desc.caps, CSPCAPS_READ )) {\n          int   pitch;\n          int   size;\n          void *buf;\n\n          dfb_surface_calc_buffer_size( allocation->surface, 4, 1, &pitch, &size );\n\n          buf = D_MALLOC( size );\n          if (!buf)\n               return D_OOM();\n\n          ret = dfb_surface_pool_read( pool, allocation, buf, pitch, NULL );\n          if (ret == DFB_OK)\n               ret = dfb_surface_buffer_dump_type_locked2( allocation->buffer, directory, prefix, raw, buf, pitch );\n\n          D_FREE( buf );\n     }\n     else {\n          CoreSurfaceBufferLock lock;\n\n          dfb_surface_buffer_lock_init( &lock, CSAID_CPU, CSAF_READ );\n\n          /* Lock the surface buffer, get the data pointer and pitch. */\n          ret = dfb_surface_pool_lock( pool, allocation, &lock );\n          if (ret) {\n               dfb_surface_buffer_lock_deinit( &lock );\n               return ret;\n          }\n\n          ret = dfb_surface_buffer_dump_type_locked( allocation->buffer, directory, prefix, raw, &lock );\n\n          /* Unlock the surface buffer. */\n          dfb_surface_pool_unlock( allocation->pool, allocation, &lock );\n\n          dfb_surface_buffer_lock_deinit( &lock );\n     }\n\n     return ret;\n}\n"
  },
  {
    "path": "src/core/surface_allocation.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__SURFACE_ALLOCATION_H__\n#define __CORE__SURFACE_ALLOCATION_H__\n\n#include <core/surface.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CSALF_NONE         = 0x00000000, /* None of these. */\n\n     CSALF_INITIALIZING = 0x00000001, /* Allocation is being initialized. */\n     CSALF_VOLATILE     = 0x00000002, /* Allocation should be freed when no longer up to date. */\n     CSALF_PREALLOCATED = 0x00000004, /* Preallocated memory, don't zap when \"thrifty-surface-buffers\" is active. */\n\n     CSALF_MUCKOUT      = 0x00001000, /* Indicates surface pool being in the progress of mucking out this and possibly\n                                         other allocations to have enough space for a new allocation to be made. */\n     CSALF_DEALLOCATED  = 0x00002000, /* Decoupled and deallocated surface buffer allocation. */\n\n     CSALF_ALL          = 0x00003007  /* All of these. */\n} CoreSurfaceAllocationFlags;\n\nstruct __DFB_CoreSurfaceAllocation {\n     FusionObject                  object;\n\n     int                           magic;\n\n     DirectSerial                  serial;              /* Equals serial of buffer if content is up to date. */\n\n     CoreSurfaceBuffer            *buffer;              /* Surface buffer owning this allocation. */\n     CoreSurface                  *surface;             /* Surface owning the buffer of this allocation. */\n     CoreSurfacePool              *pool;                /* Surface pool providing the allocation. */\n     void                         *data;                /* Pool's private data for this allocation. */\n     int                           size;                /* Amount of data used by this allocation. */\n     unsigned long                 offset;              /* Offset within address range of pool if contiguous. */\n\n     CoreSurfaceAllocationFlags    flags;               /* Configuration and state flags. */\n\n     const CoreSurfaceAccessFlags *access;              /* Possible access flags (pointer to pool description). */\n     CoreSurfaceAccessFlags        accessed[CSAID_NUM]; /* Access since last synchronization. */\n\n     CoreSurfaceConfig             config;              /* Configuration of its surface at the time of the allocation\n                                                           creation. */\n     CoreSurfaceTypeFlags          type;                /* Classification of the surface. */\n\n     unsigned long                 resource_id;         /* layer id, window id, or user specified */\n     int                           index;               /* index of surface buffer */\n\n     CoreGraphicsSerial            gfx_serial;          /* graphics serial */\n\n     FusionCall                    call;                /* dispatch */\n\n     FusionObjectID                buffer_id;           /* buffer id */\n};\n\n#if D_DEBUG_ENABLED\n#define CORE_SURFACE_ALLOCATION_ASSERT(alloc)                       \\\n     do {                                                           \\\n          D_MAGIC_ASSERT( alloc, CoreSurfaceAllocation );           \\\n          D_ASSERT( (alloc)->size >= 0 );                           \\\n          D_FLAGS_ASSERT( (alloc)->flags, CSALF_ALL );              \\\n          D_FLAGS_ASSERT( (alloc)->access[CSAID_CPU], CSAF_ALL );   \\\n          D_FLAGS_ASSERT( (alloc)->access[CSAID_GPU], CSAF_ALL );   \\\n          D_FLAGS_ASSERT( (alloc)->accessed[CSAID_CPU], CSAF_ALL ); \\\n          D_FLAGS_ASSERT( (alloc)->accessed[CSAID_GPU], CSAF_ALL ); \\\n          D_ASSUME( (alloc)->size > 0 );                            \\\n     } while (0)\n#else\n#define CORE_SURFACE_ALLOCATION_ASSERT(alloc)                       \\\n     do {                                                           \\\n     } while (0)\n#endif\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CSANF_NONE        = 0x00000000,\n\n     CSANF_DEALLOCATED = 0x00000001,\n\n     CSANF_ALL         = 0x00000001\n} CoreSurfaceAllocationNotificationFlags;\n\ntypedef struct {\n     CoreSurfaceAllocationNotificationFlags flags;\n} CoreSurfaceAllocationNotification;\n\n/**********************************************************************************************************************/\n\n/*\n * Creates a pool of surface allocation objects.\n */\nFusionObjectPool *dfb_surface_allocation_pool_create( const FusionWorld       *world );\n\n/*\n * Generates dfb_surface_allocation_ref(), dfb_surface_allocation_attach() etc.\n */\nFUSION_OBJECT_METHODS( CoreSurfaceAllocation, dfb_surface_allocation )\n\n/**********************************************************************************************************************/\n\nDFBResult         dfb_surface_allocation_create     ( CoreDFB                 *core,\n                                                      CoreSurfaceBuffer       *buffer,\n                                                      CoreSurfacePool         *pool,\n                                                      CoreSurfaceAllocation  **ret_allocation );\n\nDFBResult         dfb_surface_allocation_decouple   ( CoreSurfaceAllocation   *allocation );\n\nDFBResult         dfb_surface_allocation_update     ( CoreSurfaceAllocation   *allocation,\n                                                      CoreSurfaceAccessFlags   access );\n\nDFBResult         dfb_surface_allocation_dump       ( CoreSurfaceAllocation   *allocation,\n                                                      const char              *directory,\n                                                      const char              *prefix,\n                                                      bool                     raw );\n\n/**********************************************************************************************************************/\n\nstatic __inline__ int\ndfb_surface_allocation_locks( CoreSurfaceAllocation *allocation )\n{\n     int refs;\n\n     fusion_ref_stat( &allocation->object.ref, &refs );\n\n     D_ASSERT( refs > 0 );\n\n     return refs - 1;\n}\n\n#endif\n"
  },
  {
    "path": "src/core/surface_buffer.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreSurface.h>\n#include <core/core.h>\n#include <core/palette.h>\n#include <core/surface_allocation.h>\n#include <core/surface_buffer.h>\n#include <core/surface_pool.h>\n#include <direct/filesystem.h>\n#include <directfb_util.h>\n#include <gfx/convert.h>\n\nD_DEBUG_DOMAIN( Core_SurfBuffer, \"Core/SurfBuffer\", \"DirectFB Core Surface Buffer\" );\n\n/**********************************************************************************************************************/\n\nstatic void\nsurface_buffer_destructor( FusionObject *object,\n                           bool          zombie,\n                           void         *ctx )\n{\n     CoreSurfaceAllocation *allocation;\n     unsigned int           i;\n     CoreSurfaceBuffer     *buffer = (CoreSurfaceBuffer*) object;\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n\n     D_DEBUG_AT( Core_SurfBuffer, \"Destroying buffer %p (%dx%d%s)\\n\",\n                 buffer, buffer->config.size.w, buffer->config.size.h, zombie ? \" ZOMBIE\" : \"\" );\n\n     D_DEBUG_AT( Core_SurfBuffer, \"  -> allocs %d\\n\", buffer->allocs.count );\n\n     if (buffer->surface)\n          dfb_surface_lock( buffer->surface );\n\n     fusion_vector_foreach_reverse (allocation, i, buffer->allocs) {\n          CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n          dfb_surface_allocation_decouple( allocation );\n     }\n\n     if (buffer->surface)\n          dfb_surface_unlock( buffer->surface );\n\n     fusion_vector_destroy( &buffer->allocs );\n\n     direct_serial_deinit( &buffer->serial );\n\n     D_MAGIC_CLEAR( buffer );\n\n     /* Destroy the object. */\n     fusion_object_destroy( object );\n}\n\nFusionObjectPool *\ndfb_surface_buffer_pool_create( const FusionWorld *world )\n{\n     FusionObjectPool *pool;\n\n     pool = fusion_object_pool_create( \"Surface Buffer Pool\",\n                                       sizeof(CoreSurfaceBuffer), sizeof(CoreSurfaceBufferNotification),\n                                       surface_buffer_destructor, NULL, world );\n\n     return pool;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_surface_buffer_create( CoreDFB                 *core,\n                           CoreSurface             *surface,\n                           CoreSurfaceBufferFlags   flags,\n                           int                      index,\n                           CoreSurfaceBuffer      **ret_buffer )\n{\n     DFBResult          ret;\n     CoreSurfaceBuffer *buffer;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     D_FLAGS_ASSERT( flags, CSBF_ALL );\n     D_ASSERT( ret_buffer != NULL );\n\n     D_DEBUG_AT( Core_SurfBuffer, \"%s( %s )\\n\", __FUNCTION__, dfb_pixelformat_name( surface->config.format ) );\n\n     /* Create the buffer object. */\n     buffer = dfb_core_create_surface_buffer( core );\n     if (!buffer)\n          return DFB_FUSION;\n\n     direct_serial_init( &buffer->serial );\n     direct_serial_increase( &buffer->serial );\n\n     buffer->surface     = surface;\n     buffer->flags       = flags;\n     buffer->config      = surface->config;\n     buffer->type        = surface->type;\n     buffer->resource_id = surface->resource_id;\n     buffer->index       = index;\n\n     if (buffer->config.caps & DSCAPS_VIDEOONLY)\n          buffer->policy = CSP_VIDEOONLY;\n     else if (buffer->config.caps & DSCAPS_SYSTEMONLY)\n          buffer->policy = CSP_SYSTEMONLY;\n     else\n          buffer->policy = CSP_VIDEOLOW;\n\n     fusion_vector_init( &buffer->allocs, 2, buffer->surface->shmpool );\n\n     fusion_object_set_lock( &buffer->object, &buffer->surface->lock );\n\n     fusion_ref_add_permissions( &buffer->object.ref, 0, FUSION_REF_PERMIT_REF_UNREF_LOCAL );\n\n     D_MAGIC_SET( buffer, CoreSurfaceBuffer );\n\n     if (buffer->type & CSTF_PREALLOCATED) {\n          CoreSurfacePool       *pool;\n          CoreSurfaceAllocation *allocation;\n\n          ret = dfb_surface_pools_lookup( buffer->config.preallocated_pool_id, &pool );\n          if (ret) {\n               fusion_object_destroy( &buffer->object );\n               return ret;\n          }\n\n          ret = dfb_surface_pool_allocate( pool, buffer, NULL, 0, &allocation );\n          if (ret) {\n               fusion_object_destroy( &buffer->object );\n               return ret;\n          }\n\n          dfb_surface_allocation_update( allocation, CSAF_WRITE );\n     }\n\n     /* Activate the object. */\n     fusion_object_activate( &buffer->object );\n\n     /* Return the new buffer. */\n     *ret_buffer = buffer;\n\n     D_DEBUG_AT( Core_SurfBuffer, \"  -> %p\\n\", buffer );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_buffer_decouple( CoreSurfaceBuffer *buffer )\n{\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n\n     D_DEBUG_AT( Core_SurfBuffer, \"%s( %p )\\n\", __FUNCTION__, buffer );\n\n     buffer->flags |= CSBF_DECOUPLE;\n\n     if (!buffer->busy) {\n          dfb_surface_buffer_deallocate( buffer );\n\n          buffer->surface = NULL;\n\n          dfb_surface_buffer_unlink( &buffer );\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_buffer_deallocate( CoreSurfaceBuffer *buffer )\n{\n     CoreSurfaceAllocation *allocation;\n     int                    i;\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n\n     D_DEBUG_AT( Core_SurfBuffer, \"%s( %p ) <- %dx%d\\n\", __FUNCTION__,\n                 buffer, buffer->config.size.w, buffer->config.size.h );\n\n     fusion_vector_foreach_reverse (allocation, i, buffer->allocs) {\n           CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n           dfb_surface_allocation_decouple( allocation );\n     }\n\n     return DFB_OK;\n}\n\nCoreSurfaceAllocation *\ndfb_surface_buffer_find_allocation( CoreSurfaceBuffer      *buffer,\n                                    CoreSurfaceAccessorID   accessor,\n                                    CoreSurfaceAccessFlags  flags,\n                                    bool                    lock )\n{\n     int                    i;\n     CoreSurfaceAllocation *allocation;\n     CoreSurfaceAllocation *uptodate = NULL;\n     CoreSurfaceAllocation *outdated = NULL;\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n\n     D_DEBUG_AT( Core_SurfBuffer, \"%s( %p )\\n\", __FUNCTION__, buffer );\n\n     FUSION_SKIRMISH_ASSERT( &buffer->surface->lock );\n\n     /* For preallocated surfaces, when the client specified DSCAPS_STATIC_ALLOC, it is forced to always get the same\n        preallocated buffer again on each lock. */\n     if (buffer->type & CSTF_PREALLOCATED && buffer->config.caps & DSCAPS_STATIC_ALLOC) {\n          if (buffer->surface->object.identity == Core_GetIdentity()) {\n               D_DEBUG_AT( Core_SurfBuffer, \"  -> DSCAPS_STATIC_ALLOC, returning preallocated buffer\\n\" );\n\n               D_ASSERT( buffer->allocs.count > 0 );\n\n               allocation = buffer->allocs.elements[0];\n\n               D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n               D_ASSERT( allocation->flags & CSALF_PREALLOCATED );\n\n               /* Return if allocation has required flags. */\n               if (D_FLAGS_ARE_SET( allocation->access[accessor], flags ))\n                    return allocation;\n          }\n     }\n\n     /* Prefer allocations which are up to date. */\n     fusion_vector_foreach (allocation, i, buffer->allocs) {\n          if (lock && allocation->flags & CSALF_PREALLOCATED) {\n               if (!(allocation->access[accessor] & CSAF_SHARED)) {\n                    D_DEBUG_AT( Core_SurfBuffer,\n                                \"  -> non-shared preallocated buffer, surface identity %lu, core identity %lu\\n\",\n                                buffer->surface->object.identity, Core_GetIdentity() );\n\n                    /* If this is a non-shared preallocated allocation and the lock is not for the creator, we need to\n                       skip it and possibly allocate/update in a different pool. */\n                    if (buffer->surface->object.identity != Core_GetIdentity())\n                         continue;\n               }\n          }\n          else if (Core_GetIdentity() != FUSION_ID_MASTER && !(allocation->access[accessor] & CSAF_SHARED)) {\n               D_DEBUG_AT( Core_SurfBuffer, \"    -> refusing allocation for slave from non-shared pool!\\n\" );\n               continue;\n          }\n\n          if (direct_serial_check( &allocation->serial, &buffer->serial )) {\n               /* Return immediately if up to date allocation has required flags. */\n               if (D_FLAGS_ARE_SET( allocation->access[accessor], flags ))\n                    return allocation;\n\n               /* Remember up to date allocation in case none has supported flags. */\n               uptodate = allocation;\n          }\n          else if (D_FLAGS_ARE_SET( allocation->access[accessor], flags )) {\n               /* Remember outdated allocation which has supported flags. */\n               outdated = allocation;\n          }\n     }\n\n     /* In case of a lock the flags are mandatory and the outdated allocation has to be used. */\n     if (lock)\n          return outdated;\n\n     /* Otherwise we can still prefer the up to date allocation. */\n     return uptodate ?: outdated;\n}\n\nCoreSurfaceAllocation *\ndfb_surface_buffer_find_allocation_key( CoreSurfaceBuffer *buffer,\n                                        const char        *key )\n{\n     int                    i;\n     CoreSurfaceAllocation *allocation;\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n\n     D_DEBUG_AT( Core_SurfBuffer, \"%s( %p )\\n\", __FUNCTION__, buffer );\n\n     FUSION_SKIRMISH_ASSERT( &buffer->surface->lock );\n\n     fusion_vector_foreach (allocation, i, buffer->allocs) {\n          CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n          if (dfb_surface_pool_check_key( allocation->pool, buffer, key, 0 ) == DFB_OK)\n               return allocation;\n     }\n\n     return NULL;\n}\n\nDFBResult\ndfb_surface_buffer_lock( CoreSurfaceBuffer      *buffer,\n                         CoreSurfaceAccessorID   accessor,\n                         CoreSurfaceAccessFlags  access,\n                         CoreSurfaceBufferLock  *lock )\n{\n     DFBResult              ret;\n     CoreSurfaceAllocation *allocation;\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n     D_ASSERT( accessor >= CSAID_CPU );\n     D_FLAGS_ASSERT( access, CSAF_ALL );\n     D_ASSERT( lock != NULL );\n\n     D_DEBUG_AT( Core_SurfBuffer, \"%s( %p )\\n\", __FUNCTION__, lock );\n\n     FUSION_SKIRMISH_ASSERT( &buffer->surface->lock );\n\n     D_ASSUME( accessor < CSAID_NUM );\n\n     if (accessor >= CSAID_ANY) {\n          D_UNIMPLEMENTED();\n          return DFB_UNIMPLEMENTED;\n     }\n\n     if (accessor < 0 || accessor >= CSAID_NUM)\n          return DFB_INVARG;\n\n     if (direct_log_domain_check( &Core_SurfBuffer )) {\n          D_DEBUG_AT( Core_SurfBuffer, \"%s( %p, 0x%02x, %p ) <- %dx%d %s [%d]\\n\", __FUNCTION__, buffer, access, lock,\n                      buffer->config.size.w, buffer->config.size.h, dfb_pixelformat_name( buffer->config.format ),\n                      dfb_surface_buffer_index(buffer) );\n\n          switch (accessor) {\n               case CSAID_CPU:\n                    D_DEBUG_AT( Core_SurfBuffer, \"  -> CPU %s%s\\n\",\n                                (access & CSAF_READ) ? \"READ\" : \"\", (access & CSAF_WRITE) ? \"WRITE\" : \"\" );\n                    break;\n\n               case CSAID_GPU:\n                    D_DEBUG_AT( Core_SurfBuffer, \"  -> GPU %s%s\\n\",\n                                (access & CSAF_READ) ? \"READ\" : \"\", (access & CSAF_WRITE) ? \"WRITE\" : \"\" );\n                    break;\n\n               case CSAID_LAYER0:\n               case CSAID_LAYER1:\n               case CSAID_LAYER2:\n               case CSAID_LAYER3:\n               case CSAID_LAYER4:\n               case CSAID_LAYER5:\n               case CSAID_LAYER6:\n               case CSAID_LAYER7:\n               case CSAID_LAYER8:\n               case CSAID_LAYER9:\n               case CSAID_LAYER10:\n               case CSAID_LAYER11:\n               case CSAID_LAYER12:\n               case CSAID_LAYER13:\n               case CSAID_LAYER14:\n               case CSAID_LAYER15:\n                    D_DEBUG_AT( Core_SurfBuffer, \"  -> LAYER %u %s%s\\n\", accessor - CSAID_LAYER0,\n                                (access & CSAF_READ) ? \"READ\" : \"\", (access & CSAF_WRITE) ? \"WRITE\" : \"\" );\n                    break;\n\n               default:\n                    D_DEBUG_AT( Core_SurfBuffer, \"  -> OTHER\\n\" );\n                    break;\n          }\n\n          if (access & CSAF_SHARED)\n               D_DEBUG_AT( Core_SurfBuffer, \"  -> SHARED\\n\" );\n     }\n\n     D_DEBUG_AT( Core_SurfBuffer, \"  -> calling PreLockBuffer( %p )...\\n\", buffer );\n\n     /* Run all code that modifies shared memory in master process. */\n     ret = CoreSurface_PreLockBuffer( buffer->surface, buffer, accessor, access, &allocation );\n     if (ret)\n          return ret;\n\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n\n     D_DEBUG_AT( Core_SurfBuffer, \"  -> PreLockBuffer() returned allocation %p ('%s')\\n\",\n                 allocation, allocation->pool->desc.name );\n\n     /* Lock the allocation. */\n     dfb_surface_buffer_lock_init( lock, accessor, access );\n\n     ret = dfb_surface_pool_lock( allocation->pool, allocation, lock );\n     if (ret) {\n          D_DERROR( ret, \"Core/SurfBuffer: Locking allocation in '%s' failed!\\n\", allocation->pool->desc.name );\n          dfb_surface_buffer_lock_deinit( lock );\n          dfb_surface_allocation_unref( allocation );\n          return ret;\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_buffer_unlock( CoreSurfaceBufferLock *lock )\n{\n     DFBResult              ret;\n     CoreSurfacePool       *pool;\n     CoreSurfaceAllocation *allocation;\n\n     D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );\n\n     D_DEBUG_AT( Core_SurfBuffer, \"%s( %p )\\n\", __FUNCTION__, lock );\n\n     allocation = lock->allocation;\n\n     CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n     D_MAGIC_ASSERT( allocation->pool, CoreSurfacePool );\n\n     pool = allocation->pool;\n\n     ret = dfb_surface_pool_unlock( pool, lock->allocation, lock );\n     if (ret) {\n          D_DERROR( ret, \"Core/SurfBuffer: Unlocking allocation in '%s' failed!\\n\", pool->desc.name );\n          return ret;\n     }\n\n     dfb_surface_buffer_lock_reset( lock );\n\n     dfb_surface_buffer_lock_deinit( lock );\n\n     dfb_surface_allocation_unref( allocation );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_buffer_dump_type_locked( CoreSurfaceBuffer     *buffer,\n                                     const char            *directory,\n                                     const char            *prefix,\n                                     bool                   raw,\n                                     CoreSurfaceBufferLock *lock )\n{\n     CORE_SURFACE_BUFFER_LOCK_ASSERT( lock );\n\n     CORE_SURFACE_ALLOCATION_ASSERT( lock->allocation );\n\n     return dfb_surface_buffer_dump_type_locked2( buffer, directory, prefix, raw, lock->addr, lock->pitch );\n}\n\nDFBResult\ndfb_surface_buffer_dump_type_locked2( CoreSurfaceBuffer *buffer,\n                                      const char        *directory,\n                                      const char        *prefix,\n                                      bool               raw,\n                                      void              *addr,\n                                      int                pitch )\n{\n     DFBResult    ret;\n     int          num  = -1;\n     int          i, n;\n     int          len = (directory ? strlen( directory ) : 0) + (prefix ? strlen( prefix ) : 0) + 40;\n     char         filename[len];\n     char         head[30];\n     bool         rgb = false;\n     bool         alpha = false;\n     char         rgb_ext[4];\n     size_t       bytes;\n     CorePalette *palette = NULL;\n     DirectFile   fd_p, fd_g;\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n     D_ASSERT( directory != NULL );\n\n     D_DEBUG_AT( Core_SurfBuffer, \"%s( %p, %p, %p )\\n\", __FUNCTION__, buffer, directory, prefix );\n\n     /* Check pixel format. */\n     switch (buffer->config.format) {\n          case DSPF_LUT8:\n          case DSPF_ALUT8:\n               palette = buffer->surface->palette;\n\n               if (!palette) {\n                    D_BUG( \"no palette\" );\n                    return DFB_BUG;\n               }\n\n               if (dfb_palette_ref( palette ))\n                    return DFB_FUSION;\n\n               rgb = true;\n               /* fall through */\n\n          case DSPF_A8:\n               alpha = true;\n               break;\n\n          case DSPF_ARGB:\n          case DSPF_ABGR:\n          case DSPF_ARGB1555:\n          case DSPF_RGBA5551:\n          case DSPF_ARGB2554:\n          case DSPF_ARGB4444:\n          case DSPF_AiRGB:\n          case DSPF_ARGB8565:\n          case DSPF_AYUV:\n          case DSPF_AVYU:\n               alpha = true;\n               /* fall through */\n\n          case DSPF_RGB332:\n          case DSPF_RGB444:\n          case DSPF_RGB555:\n          case DSPF_BGR555:\n          case DSPF_RGB16:\n          case DSPF_RGB24:\n          case DSPF_BGR24:\n          case DSPF_RGB32:\n          case DSPF_YUY2:\n          case DSPF_UYVY:\n          case DSPF_VYU:\n          case DSPF_I420:\n          case DSPF_YV12:\n          case DSPF_NV12:\n          case DSPF_NV21:\n          case DSPF_Y42B:\n          case DSPF_YV16:\n          case DSPF_NV16:\n          case DSPF_NV61:\n          case DSPF_Y444:\n          case DSPF_YV24:\n          case DSPF_NV24:\n          case DSPF_NV42:\n               rgb = true;\n               break;\n\n          default:\n               D_ERROR( \"Core/SurfBuffer: Surface dump for format '%s' is not implemented!\\n\",\n                        dfb_pixelformat_name( buffer->config.format ) );\n               return DFB_UNSUPPORTED;\n     }\n\n     /* Setup the file extension depending on whether we want the output in RAW format or not. */\n     snprintf( rgb_ext, D_ARRAY_SIZE(rgb_ext), (raw == true) ? \"raw\" : \"ppm\" );\n\n     if (prefix) {\n          /* Find the lowest unused index. */\n          while (++num < 10000) {\n               snprintf( filename, len, \"%s/%s_%04d.%s\", directory, prefix, num, rgb_ext );\n\n               ret = direct_access( filename, F_OK );\n               if (ret) {\n                    snprintf( filename, len, \"%s/%s_%04d.pgm\", directory, prefix, num );\n                    ret = direct_access( filename, F_OK );\n                    if (ret)\n                         break;\n               }\n          }\n\n          if (num == 10000) {\n               D_ERROR( \"Core/SurfBuffer: Could not find an unused index for surface dump!\\n\" );\n               if (palette)\n                    dfb_palette_unref( palette );\n               return DFB_FAILURE;\n          }\n     }\n\n     /* Create a file with the found index. */\n     if (rgb) {\n          if (prefix)\n               snprintf( filename, len, \"%s/%s_%04d.%s\", directory, prefix, num, rgb_ext );\n          else\n               snprintf( filename, len, \"%s.%s\", directory, rgb_ext );\n\n          ret = direct_file_open( &fd_p, filename, O_EXCL | O_CREAT | O_WRONLY, 0644 );\n          if (ret) {\n               D_DERROR( ret, \"Core/SurfBuffer: Could not open '%s'!\\n\", filename );\n               if (palette)\n                    dfb_palette_unref( palette );\n               return ret;\n          }\n     }\n\n     /* Create a graymap for the alpha channel using the found index. */\n     if (alpha && !raw) {\n          if (prefix)\n               snprintf( filename, len, \"%s/%s_%04d.pgm\", directory, prefix, num );\n          else\n               snprintf( filename, len, \"%s.pgm\", directory );\n\n          ret = direct_file_open( &fd_g, filename, O_EXCL | O_CREAT | O_WRONLY, 0644 );\n          if (ret) {\n               D_DERROR( ret, \"Core/SurfBuffer: Could not open '%s'!\\n\", filename );\n\n               if (palette)\n                    dfb_palette_unref( palette );\n\n               if (rgb) {\n                    direct_file_close( &fd_p );\n                    snprintf( filename, len, \"%s/%s_%04d.%s\", directory, prefix, num, rgb_ext );\n                    direct_unlink( filename );\n               }\n\n               return ret;\n          }\n     }\n\n     /* Only write the header if we are not dumping a raw image. */\n     if (!raw) {\n          if (rgb) {\n               /* Write the pixmap header. */\n               snprintf( head, sizeof(head), \"P6\\n%d %d\\n255\\n\", buffer->config.size.w, buffer->config.size.h );\n               direct_file_write( &fd_p, head, strlen( head ), &bytes );\n          }\n\n          /* Write the graymap header. */\n          if (alpha) {\n               snprintf( head, sizeof(head), \"P5\\n%d %d\\n255\\n\", buffer->config.size.w, buffer->config.size.h );\n               direct_file_write( &fd_g, head, strlen( head ), &bytes );\n          }\n     }\n\n     /* Write the pixmap (and graymap) data. */\n     for (i = 0; i < buffer->config.size.h; i++) {\n          int n3;\n\n          /* Prepare one row. */\n          u8  *srces[3]   = { NULL, NULL, NULL };\n          int  pitches[3] = { 0, 0, 0 };\n          u8  *src8;\n\n          dfb_surface_get_data_offsets( &buffer->config, addr, pitch, 0, i, 3, srces, pitches );\n          src8 = srces[0];\n\n          /* Write color buffer to pixmap file. */\n          if (rgb) {\n               if (raw) {\n                    u8 buf_p[buffer->config.size.w*4];\n\n                    if (buffer->config.format == DSPF_LUT8) {\n                         for (n = 0, n3 = 0; n < buffer->config.size.w; n++, n3 += 4) {\n                              buf_p[n3+0] = palette->entries[src8[n]].r;\n                              buf_p[n3+1] = palette->entries[src8[n]].g;\n                              buf_p[n3+2] = palette->entries[src8[n]].b;\n                              buf_p[n3+3] = palette->entries[src8[n]].a;\n                         }\n                    }\n                    else\n                         dfb_convert_to_argb( buffer->config.format, buffer->config.colorspace,\n                                              srces[0], pitches[0], srces[1], pitches[1], srces[2], pitches[2],\n                                              buffer->config.size.h, (u32*) (&buf_p[0]),\n                                              buffer->config.size.w * 4, buffer->config.size.w, 1 );\n\n                    direct_file_write( &fd_p, buf_p, buffer->config.size.w * 4, &bytes );\n               }\n               else {\n                    u8 buf_p[buffer->config.size.w*3];\n\n                    if (buffer->config.format == DSPF_LUT8) {\n                         for (n = 0, n3 = 0; n < buffer->config.size.w; n++, n3 += 3) {\n                              buf_p[n3+0] = palette->entries[src8[n]].r;\n                              buf_p[n3+1] = palette->entries[src8[n]].g;\n                              buf_p[n3+2] = palette->entries[src8[n]].b;\n                         }\n                    }\n                    else\n                         dfb_convert_to_rgb24( buffer->config.format, buffer->config.colorspace,\n                                               srces[0], pitches[0], srces[1], pitches[1], srces[2], pitches[2],\n                                               buffer->config.size.h, buf_p,\n                                               buffer->config.size.w * 3, buffer->config.size.w, 1 );\n\n                    direct_file_write( &fd_p, buf_p, buffer->config.size.w * 3, &bytes );\n               }\n          }\n\n          /* Write alpha buffer to graymap file. */\n          if (alpha && !raw) {\n               u8 buf_g[buffer->config.size.w];\n\n               if (buffer->config.format == DSPF_LUT8) {\n                    for (n = 0; n < buffer->config.size.w; n++)\n                         buf_g[n] = palette->entries[src8[n]].a;\n               }\n               else\n                    dfb_convert_to_a8( buffer->config.format, srces[0], pitches[0], buffer->config.size.h, buf_g,\n                                       buffer->config.size.w, buffer->config.size.w, 1 );\n\n               direct_file_write( &fd_g, buf_g, buffer->config.size.w, &bytes );\n          }\n     }\n\n     /* Release the palette. */\n     if (palette)\n          dfb_palette_unref( palette );\n\n     /* Close pixmap file. */\n     if (rgb)\n          direct_file_close( &fd_p );\n\n     /* Close graymap file. */\n     if (alpha && !raw)\n          direct_file_close( &fd_g );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_surface_buffer_dump_type( CoreSurfaceBuffer *buffer,\n                              const char        *directory,\n                              const char        *prefix,\n                              bool               raw )\n{\n     DFBResult             ret;\n     CoreSurfaceBufferLock lock;\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_ASSERT( directory != NULL );\n\n     D_DEBUG_AT( Core_SurfBuffer, \"%s( %p, %p, %p )\\n\", __FUNCTION__, buffer, directory, prefix );\n\n     /* Lock the surface buffer, get the data pointer and pitch. */\n     ret = dfb_surface_buffer_lock( buffer, CSAID_CPU, CSAF_READ, &lock );\n     if (ret)\n          return ret;\n\n     ret = dfb_surface_buffer_dump_type_locked( buffer, directory, prefix, raw, &lock );\n\n     /* Unlock the surface buffer. */\n     dfb_surface_buffer_unlock( &lock );\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_buffer_dump( CoreSurfaceBuffer *buffer,\n                         const char        *directory,\n                         const char        *prefix )\n{\n     return dfb_surface_buffer_dump_type( buffer, directory, prefix, false );\n}\n\nDFBResult\ndfb_surface_buffer_dump_raw( CoreSurfaceBuffer *buffer,\n                             const char        *directory,\n                             const char        *prefix )\n{\n     return dfb_surface_buffer_dump_type( buffer, directory, prefix, true );\n}\n"
  },
  {
    "path": "src/core/surface_buffer.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__SURFACE_BUFFER_H__\n#define __CORE__SURFACE_BUFFER_H__\n\n#include <core/surface.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CSP_SYSTEMONLY = 0x00000000, /* Never try to swap into video memory. */\n     CSP_VIDEOLOW   = 0x00000001, /* Try to store in video memory, low priority. */\n     CSP_VIDEOHIGH  = 0x00000002, /* Try to store in video memory, high priority. */\n     CSP_VIDEOONLY  = 0x00000003  /* Always and only store in video memory. */\n} CoreSurfacePolicy;\n\ntypedef enum {\n     CSBF_NONE     = 0x00000000, /* None of these. */\n\n     CSBF_DECOUPLE = 0x00000002, /* Buffer is about to be deallocated and removed from surface. */\n     CSBF_RIGHT    = 0x00000004, /* Buffer is for right eye. */\n\n     CSBF_ALL      = 0x00000006  /* All of these. */\n} CoreSurfaceBufferFlags;\n\nstruct __DFB_CoreSurfaceBuffer {\n     FusionObject            object;\n\n     int                     magic;\n\n     DirectSerial            serial;      /* Increased when content is written. */\n     CoreSurfaceAllocation  *written;     /* Allocation with the last write access. */\n     CoreSurfaceAllocation  *read;        /* Allocation with the last read access. */\n\n     CoreSurface            *surface;     /* Surface owning this surface buffer. */\n     CoreSurfacePolicy       policy;      /* Policy of its surface. */\n\n     CoreSurfaceBufferFlags  flags;       /* Configuration and state flags. */\n\n     FusionVector            allocs;      /* Allocations within surface pools. */\n\n     CoreSurfaceConfig       config;      /* Configuration of its surface at the time of the buffer creation */\n     CoreSurfaceTypeFlags    type;        /* Classification of the surface. */\n\n     unsigned long           resource_id; /* layer id, window id, or user specified */\n     int                     index;       /* index of surface buffer */\n\n     unsigned int            busy;        /* busy buffer */\n\n     FusionObjectID          surface_id;  /* surface id */\n};\n\nstruct __DFB_CoreSurfaceBufferLock {\n     int                     magic;      /* Must be valid before calling dfb_surface_pool_lock(). */\n\n     CoreSurfaceAccessorID   accessor;   /* Accessor ID. */\n     CoreSurfaceAccessFlags  access;     /* Access flags. */\n\n     CoreSurfaceBuffer      *buffer;     /* Set by dfb_surface_pool_lock(). */\n     CoreSurfaceAllocation  *allocation; /* Allocation of a surface buffer. */\n\n     void                   *addr;       /* address of buffer */\n     unsigned long           phys;       /* physical address */\n     unsigned long           offset;     /* framebuffer offset */\n     unsigned int            pitch;      /* pitch of buffer */\n\n     void                   *handle;     /* handle */\n};\n\n#if D_DEBUG_ENABLED\n#define CORE_SURFACE_BUFFER_LOCK_ASSERT(lock)                                                                          \\\n     do {                                                                                                              \\\n          D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );                                                               \\\n          D_FLAGS_ASSERT( (lock)->access, CSAF_ALL );                                                                  \\\n          if ((lock)->allocation) {                                                                                    \\\n               D_ASSERT( (lock)->pitch > 0 || ((lock)->addr == NULL && (lock)->phys == 0) );                           \\\n               D_ASSUME( (lock)->addr != NULL || (lock)->phys != 0 || (lock)->offset != ~0 || (lock)->handle != NULL );\\\n               D_ASSUME( (lock)->offset == (lock)->allocation->offset || (lock)->offset == ~0 );                       \\\n          }                                                                                                            \\\n          else {                                                                                                       \\\n               D_ASSERT( (lock)->buffer == NULL );                                                                     \\\n               D_ASSERT( (lock)->addr == NULL );                                                                       \\\n               D_ASSERT( (lock)->phys == 0 );                                                                          \\\n               D_ASSERT( (lock)->offset == ~0 );                                                                       \\\n               D_ASSERT( (lock)->pitch == 0 );                                                                         \\\n               D_ASSERT( (lock)->handle == NULL );                                                                     \\\n          }                                                                                                            \\\n     } while (0)\n#else\n#define CORE_SURFACE_BUFFER_LOCK_ASSERT(lock)                                                                          \\\n     do {                                                                                                              \\\n     } while (0)\n#endif\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CSBNF_NONE = 0x00000000\n} CoreSurfaceBufferNotificationFlags;\n\ntypedef struct {\n     CoreSurfaceBufferNotificationFlags flags;\n} CoreSurfaceBufferNotification;\n\n/**********************************************************************************************************************/\n\n/*\n * Creates a pool of surface buffer objects.\n */\nFusionObjectPool      *dfb_surface_buffer_pool_create        ( const FusionWorld       *world );\n\n/*\n * Generates dfb_surface_buffer_ref(), dfb_surface_buffer_attach() etc.\n */\nFUSION_OBJECT_METHODS( CoreSurfaceBuffer, dfb_surface_buffer )\n\n/**********************************************************************************************************************/\n\nDFBResult              dfb_surface_buffer_create             ( CoreDFB                 *core,\n                                                               CoreSurface             *surface,\n                                                               CoreSurfaceBufferFlags   flags,\n                                                               int                      index,\n                                                               CoreSurfaceBuffer      **ret_buffer );\n\nDFBResult              dfb_surface_buffer_decouple           ( CoreSurfaceBuffer       *buffer );\n\nDFBResult              dfb_surface_buffer_deallocate         ( CoreSurfaceBuffer       *buffer );\n\nCoreSurfaceAllocation *dfb_surface_buffer_find_allocation    ( CoreSurfaceBuffer       *buffer,\n                                                               CoreSurfaceAccessorID    accessor,\n                                                               CoreSurfaceAccessFlags   flags,\n                                                               bool                     lock );\n\nCoreSurfaceAllocation *dfb_surface_buffer_find_allocation_key( CoreSurfaceBuffer       *buffer,\n                                                               const char              *key );\n\nDFBResult              dfb_surface_buffer_lock               ( CoreSurfaceBuffer       *buffer,\n                                                               CoreSurfaceAccessorID    accessor,\n                                                               CoreSurfaceAccessFlags   access,\n                                                               CoreSurfaceBufferLock   *ret_lock );\n\nDFBResult              dfb_surface_buffer_unlock             ( CoreSurfaceBufferLock   *lock );\n\nDFBResult              dfb_surface_buffer_dump_type_locked   ( CoreSurfaceBuffer       *buffer,\n                                                               const char              *directory,\n                                                               const char              *prefix,\n                                                               bool                     raw,\n                                                               CoreSurfaceBufferLock   *lock );\n\nDFBResult              dfb_surface_buffer_dump_type_locked2  ( CoreSurfaceBuffer       *buffer,\n                                                               const char              *directory,\n                                                               const char              *prefix,\n                                                               bool                     raw,\n                                                               void                    *addr,\n                                                               int                      pitch );\n\nDFBResult              dfb_surface_buffer_dump               ( CoreSurfaceBuffer       *buffer,\n                                                               const char              *directory,\n                                                               const char              *prefix );\n\nDFBResult              dfb_surface_buffer_dump_raw           ( CoreSurfaceBuffer       *buffer,\n                                                               const char              *directory,\n                                                               const char              *prefix );\n\n/**********************************************************************************************************************/\n\nstatic __inline__ void\ndfb_surface_buffer_lock_reset( CoreSurfaceBufferLock *lock )\n{\n     D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );\n\n     lock->buffer     = NULL;\n     lock->allocation = NULL;\n     lock->addr       = NULL;\n     lock->phys       = 0;\n     lock->offset     = ~0;\n     lock->pitch      = 0;\n     lock->handle     = 0;\n}\n\nstatic __inline__ void\ndfb_surface_buffer_lock_init( CoreSurfaceBufferLock  *lock,\n                              CoreSurfaceAccessorID   accessor,\n                              CoreSurfaceAccessFlags  access )\n{\n     D_MAGIC_SET_ONLY( lock, CoreSurfaceBufferLock );\n\n     lock->accessor = accessor;\n     lock->access   = access;\n\n     dfb_surface_buffer_lock_reset( lock );\n}\n\nstatic __inline__ void\ndfb_surface_buffer_lock_deinit( CoreSurfaceBufferLock *lock )\n{\n     D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );\n\n     lock->accessor = CSAID_NONE;\n     lock->access   = CSAF_NONE;\n\n     D_MAGIC_CLEAR( lock );\n}\n\nstatic __inline__ int\ndfb_surface_buffer_index( CoreSurfaceBuffer *buffer )\n{\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n\n     return buffer->index;\n}\n\n#endif\n"
  },
  {
    "path": "src/core/surface_client.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreSurfaceClient.h>\n#include <core/core.h>\n#include <core/surface.h>\n#include <core/surface_client.h>\n#include <directfb_util.h>\n\nD_DEBUG_DOMAIN( Core_SurfClient, \"Core/SurfClient\", \"DirectFB Core Surface Client\" );\n\n/**********************************************************************************************************************/\n\nstatic void\nsurface_client_destructor( FusionObject *object,\n                           bool          zombie,\n                           void         *ctx )\n{\n     CoreSurfaceClient *client = (CoreSurfaceClient*) object;\n     CoreSurface       *surface;\n     int                index;\n\n     D_MAGIC_ASSERT( client, CoreSurfaceClient );\n     D_MAGIC_ASSERT( client->surface, CoreSurface );\n\n     surface = client->surface;\n\n     D_DEBUG_AT( Core_SurfClient, \"Destroying client %p (%dx%d%s)\\n\",\n                 client, surface->config.size.w, surface->config.size.h, zombie ? \" ZOMBIE\" : \"\" );\n\n     CoreSurfaceClient_Deinit_Dispatch( &client->call );\n\n     dfb_surface_lock( surface );\n\n     index = fusion_vector_index_of( &surface->clients, client );\n\n     D_ASSERT( index >= 0 );\n\n     fusion_vector_remove( &surface->clients, index );\n\n     dfb_surface_check_acks( surface );\n\n     dfb_surface_unlock( surface );\n\n     dfb_surface_unlink( &client->surface );\n\n     D_MAGIC_CLEAR( client );\n\n     /* Destroy the object. */\n     fusion_object_destroy( object );\n}\n\nFusionObjectPool *\ndfb_surface_client_pool_create( const FusionWorld *world )\n{\n     FusionObjectPool *pool;\n\n     pool = fusion_object_pool_create( \"Surface Client Pool\",\n                                       sizeof(CoreSurfaceClient), sizeof(CoreSurfaceClientNotification),\n                                       surface_client_destructor, NULL, world );\n\n     return pool;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_surface_client_create( CoreDFB            *core,\n                           CoreSurface        *surface,\n                           CoreSurfaceClient **ret_client )\n{\n     DFBResult          ret;\n     CoreSurfaceClient *client;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n     D_ASSERT( ret_client != NULL );\n\n     D_DEBUG_AT( Core_SurfClient, \"%s( %p %dx%d %s )\\n\", __FUNCTION__, surface,\n                 surface->config.size.w, surface->config.size.h, dfb_pixelformat_name( surface->config.format ) );\n\n     /* Create the client object. */\n     client = dfb_core_create_surface_client( core );\n     if (!client)\n          return DFB_FUSION;\n\n     ret = dfb_surface_link( &client->surface, surface );\n     if (ret) {\n          fusion_object_destroy( &client->object );\n          return ret;\n     }\n\n     D_MAGIC_SET( client, CoreSurfaceClient );\n\n     CoreSurfaceClient_Init_Dispatch( core, client, &client->call );\n\n     dfb_surface_lock( surface );\n\n     client->flip_count = surface->flips;\n\n     fusion_vector_add( &surface->clients, client );\n\n     dfb_surface_unlock( surface );\n\n     /* Activate the object. */\n     fusion_object_activate( &client->object );\n\n     /* Return the new client. */\n     *ret_client = client;\n\n     D_DEBUG_AT( Core_SurfClient, \"  -> %p\\n\", client );\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/core/surface_client.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__SURFACE_CLIENT_H__\n#define __CORE__SURFACE_CLIENT_H__\n\n#include <core/coretypes.h>\n#include <fusion/object.h>\n\n/**********************************************************************************************************************/\n\nstruct __DFB_CoreSurfaceClient {\n     FusionObject             object;\n\n     int                      magic;\n\n     CoreSurface             *surface;\n\n     FusionCall               call;\n\n     u32                      flip_count;\n\n     DFBFrameTimeConfig       frametime_config;\n};\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CSCNF_NONE = 0x00000000,\n} CoreSurfaceClientNotificationFlags;\n\ntypedef struct {\n     CoreSurfaceClientNotificationFlags flags;\n} CoreSurfaceClientNotification;\n\n/**********************************************************************************************************************/\n\n/*\n * Creates a pool of surface client objects.\n */\nFusionObjectPool *dfb_surface_client_pool_create( const FusionWorld  *world );\n\n/*\n * Generates dfb_surface_client_ref(), dfb_surface_client_attach() etc.\n */\nFUSION_OBJECT_METHODS( CoreSurfaceClient, dfb_surface_client )\n\n/**********************************************************************************************************************/\n\nDFBResult         dfb_surface_client_create     ( CoreDFB            *core,\n                                                  CoreSurface        *surface,\n                                                  CoreSurfaceClient **ret_client );\n\n#endif\n"
  },
  {
    "path": "src/core/surface_core.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core_parts.h>\n#include <core/surface_allocation.h>\n#include <core/surface_buffer.h>\n#include <core/surface_core.h>\n#include <core/surface_pool_bridge.h>\n#include <direct/signals.h>\n#include <directfb_util.h>\n#include <fusion/conf.h>\n\nD_DEBUG_DOMAIN( Core_Surface, \"Core/SurfaceCore\", \"DirectFB Surface Core\" );\n\n/**********************************************************************************************************************/\n\nDFB_CORE_PART( surface_core, SurfaceCore );\n\n/**********************************************************************************************************************/\n\n#if FUSION_BUILD_MULTI\nextern const SurfacePoolFuncs       sharedSurfacePoolFuncs;\nextern const SurfacePoolFuncs       sharedSecureSurfacePoolFuncs;\n#else /* FUSION_BUILD_MULTI */\nextern const SurfacePoolFuncs       localSurfacePoolFuncs;\n#endif /* FUSION_BUILD_MULTI */\n\nextern const SurfacePoolFuncs       preallocSurfacePoolFuncs;\n\nextern const SurfacePoolBridgeFuncs preallocSurfacePoolBridgeFuncs;\n\nstatic DFBEnumerationResult\nalloc_callback( CoreSurfaceAllocation *allocation,\n                void                  *ctx )\n{\n     CoreSurfaceBuffer *buffer;\n     const char        *role     = \"???\";\n     const char        *uptodate = \" ? \";\n     int                allocs   = 0;\n\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n\n     buffer = allocation->buffer;\n     if (buffer) {\n          CoreSurface *surface;\n\n          D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n\n          surface = buffer->surface;\n          if (surface) {\n               int base;\n\n               D_MAGIC_ASSERT( surface, CoreSurface );\n\n               base = surface->flips % surface->num_buffers;\n\n               role = (buffer->index == (base + DSBR_FRONT) % surface->num_buffers) ? \"front\" :\n                      (buffer->index == (base + DSBR_BACK)  % surface->num_buffers) ? \"back\"  :\n                      (buffer->index == (base + DSBR_IDLE)  % surface->num_buffers) ? \"idle\"  : \"\";\n\n               uptodate = direct_serial_check(&allocation->serial, &buffer->serial) ? \" * \" : \"   \";\n\n               allocs = fusion_vector_size( &buffer->allocs );\n          }\n     }\n\n     printf( \"%3u \", allocation->object.id );\n\n     printf( \"%3u \", allocation->buffer_id );\n\n     printf( \"%9lu %8d  \", allocation->offset, allocation->size );\n\n     printf( \"%4d x %4d   \", allocation->config.size.w, allocation->config.size.h );\n\n     printf( \"%8s \", dfb_pixelformat_name( allocation->config.format ) );\n\n     printf( \" %-5s %s\", role, uptodate );\n\n     printf( \"%d  %2lu  \", allocs, allocation->resource_id );\n\n     if (allocation->type & CSTF_SHARED)\n          printf( \"SHARED  \" );\n     else\n          printf( \"PRIVATE \" );\n\n     if (allocation->type & CSTF_LAYER)\n          printf( \"LAYER \" );\n\n     if (allocation->type & CSTF_WINDOW)\n          printf( \"WINDOW \" );\n\n     if (allocation->type & CSTF_CURSOR)\n          printf( \"CURSOR \" );\n\n     if (allocation->type & CSTF_FONT)\n          printf( \"FONT \" );\n\n     printf( \" \" );\n\n     if (allocation->type & CSTF_INTERNAL)\n          printf( \"INTERNAL \" );\n\n     if (allocation->type & CSTF_EXTERNAL)\n          printf( \"EXTERNAL \" );\n\n     printf( \" \" );\n\n     if (allocation->config.caps & DSCAPS_SYSTEMONLY)\n          printf( \"system only  \" );\n\n     if (allocation->config.caps & DSCAPS_VIDEOONLY)\n          printf( \"video only   \" );\n\n     if (allocation->config.caps & DSCAPS_INTERLACED)\n          printf( \"interlaced   \" );\n\n     if (allocation->config.caps & DSCAPS_DOUBLE)\n          printf( \"double       \" );\n\n     if (allocation->config.caps & DSCAPS_TRIPLE)\n          printf( \"triple       \" );\n\n     if (allocation->config.caps & DSCAPS_PREMULTIPLIED)\n          printf( \"premultiplied\" );\n\n     printf( \"   ref 0x%04x\\n\", (unsigned int) allocation->object.ref.multi.id );\n\n     char buf[64];\n     snprintf( buf, sizeof(buf), \"dfb_surface_allocation_%u_%u\", allocation->object.id, allocation->buffer_id );\n\n     dfb_surface_allocation_dump( allocation, \".\", buf, false );\n\n     return DFENUM_OK;\n}\n\nstatic DFBEnumerationResult\nsurface_pool_callback( CoreSurfacePool *pool,\n                       void            *ctx )\n{\n     int length;\n\n     printf( \"\\n\" );\n     printf( \"--------------------[ Surface Buffer Allocations in %s ]--------------------%n\\n\",\n             pool->desc.name, &length );\n     printf( \"ID  BID    Offset   Length Width Height     Format  Role  Up nA ID  Usage   Type / Storage / Caps\\n\" );\n\n     while (length--)\n          putc( '-', stdout );\n\n     printf( \"\\n\" );\n\n     dfb_surface_pool_enumerate( pool, alloc_callback, NULL );\n\n     return DFENUM_OK;\n}\n\nstatic void\ndump_surface_pools( void )\n{\n     dfb_surface_pools_enumerate( surface_pool_callback, NULL );\n}\n\nstatic DirectSignalHandlerResult\ndfb_surface_core_dump_handler( int   num,\n                               void *addr,\n                               void *ctx )\n{\n     dump_surface_pools();\n\n     return DSHR_OK;\n}\n\nstatic DFBResult\ndfb_surface_core_initialize( CoreDFB              *core,\n                             DFBSurfaceCore       *data,\n                             DFBSurfaceCoreShared *shared )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p, %p, %p )\\n\", __FUNCTION__, core, data, shared );\n\n     D_ASSERT( data != NULL );\n     D_ASSERT( shared != NULL );\n\n     data->core   = core;\n     data->shared = shared;\n\n#if FUSION_BUILD_MULTI\n     if (fusion_config->secure_fusion) {\n          ret = dfb_surface_pool_initialize2( core, &sharedSecureSurfacePoolFuncs, data, &shared->surface_pool );\n          if (ret) {\n               D_DERROR( ret, \"Core/SurfaceCore: Could not register 'shared' surface pool!\\n\" );\n               return ret;\n          }\n     }\n     else {\n          ret = dfb_surface_pool_initialize2( core, &sharedSurfacePoolFuncs, data, &shared->surface_pool );\n          if (ret) {\n               D_DERROR( ret, \"Core/SurfaceCore: Could not register 'shared' surface pool!\\n\" );\n               return ret;\n          }\n     }\n#else /* FUSION_BUILD_MULTI */\n     ret = dfb_surface_pool_initialize2( core, &localSurfacePoolFuncs, data, &shared->surface_pool );\n     if (ret) {\n          D_DERROR( ret, \"Core/SurfaceCore: Could not register 'local' surface pool!\\n\" );\n          return ret;\n     }\n#endif /* FUSION_BUILD_MULTI */\n\n     ret = dfb_surface_pool_initialize2( core, &preallocSurfacePoolFuncs, data, &shared->prealloc_pool );\n     if (ret) {\n          D_DERROR( ret, \"Core/SurfaceCore: Could not register 'prealloc' surface pool!\\n\" );\n          dfb_surface_pool_destroy( shared->surface_pool );\n          return ret;\n     }\n\n     ret = dfb_surface_pool_bridge_initialize( core, &preallocSurfacePoolBridgeFuncs, data,\n                                               &shared->prealloc_pool_bridge );\n     if (ret) {\n          D_DERROR( ret, \"Core/SurfaceCore: Could not register 'prealloc' surface pool bridge!\\n\" );\n          dfb_surface_pool_destroy( shared->prealloc_pool );\n          dfb_surface_pool_destroy( shared->surface_pool );\n          return ret;\n     }\n\n     ret = direct_signal_handler_add( DIRECT_SIGNAL_DUMP_STACK, dfb_surface_core_dump_handler, data,\n                                      &data->dump_signal_handler );\n     if (ret) {\n          D_DERROR( ret, \"Core/SurfaceCore: Could not register surface core signal handler!\\n\" );\n          dfb_surface_pool_bridge_destroy( shared->prealloc_pool_bridge );\n          dfb_surface_pool_destroy( shared->prealloc_pool );\n          dfb_surface_pool_destroy( shared->surface_pool );\n          return ret;\n     }\n\n     D_MAGIC_SET( data, DFBSurfaceCore );\n     D_MAGIC_SET( shared, DFBSurfaceCoreShared );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_surface_core_join( CoreDFB              *core,\n                       DFBSurfaceCore       *data,\n                       DFBSurfaceCoreShared *shared )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p, %p, %p )\\n\", __FUNCTION__, core, data, shared );\n\n     D_ASSERT( data != NULL );\n     D_MAGIC_ASSERT( shared, DFBSurfaceCoreShared );\n\n     data->core   = core;\n     data->shared = shared;\n\n#if FUSION_BUILD_MULTI\n     if (fusion_config->secure_fusion)\n          dfb_surface_pool_join2( core, shared->surface_pool, &sharedSecureSurfacePoolFuncs, data );\n     else\n          dfb_surface_pool_join2( core, shared->surface_pool, &sharedSurfacePoolFuncs, data );\n#else /* FUSION_BUILD_MULTI */\n     dfb_surface_pool_join2( core, shared->surface_pool, &localSurfacePoolFuncs, data );\n#endif /* FUSION_BUILD_MULTI */\n\n     dfb_surface_pool_join2( core, shared->prealloc_pool, &preallocSurfacePoolFuncs, data );\n\n     dfb_surface_pool_bridge_join( core, shared->prealloc_pool_bridge, &preallocSurfacePoolBridgeFuncs, data );\n\n     ret = direct_signal_handler_add( DIRECT_SIGNAL_DUMP_STACK, dfb_surface_core_dump_handler, data,\n                                      &data->dump_signal_handler );\n     if (ret) {\n          D_DERROR( ret, \"Core/SurfaceCore: Could not register surface core signal handler!\\n\" );\n          dfb_surface_pool_bridge_leave( shared->prealloc_pool_bridge );\n          dfb_surface_pool_leave( shared->prealloc_pool );\n          dfb_surface_pool_leave( shared->surface_pool );\n          return ret;\n     }\n\n     D_MAGIC_SET( data, DFBSurfaceCore );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_surface_core_shutdown( DFBSurfaceCore *data,\n                           bool            emergency )\n{\n     DFBSurfaceCoreShared *shared;\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p, %semergency )\\n\", __FUNCTION__, data, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( data, DFBSurfaceCore );\n     D_MAGIC_ASSERT( data->shared, DFBSurfaceCoreShared );\n\n     shared = data->shared;\n\n     direct_signal_handler_remove( data->dump_signal_handler );\n\n     dfb_surface_pool_bridge_destroy( shared->prealloc_pool_bridge );\n\n     dfb_surface_pool_destroy( shared->prealloc_pool );\n\n     dfb_surface_pool_destroy( shared->surface_pool );\n\n     D_MAGIC_CLEAR( data );\n     D_MAGIC_CLEAR( shared );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_surface_core_leave( DFBSurfaceCore *data,\n                        bool            emergency )\n{\n     DFBSurfaceCoreShared *shared;\n\n     D_DEBUG_AT( Core_Surface, \"%s( %p, %semergency )\\n\", __FUNCTION__, data, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( data, DFBSurfaceCore );\n     D_MAGIC_ASSERT( data->shared, DFBSurfaceCoreShared );\n\n     shared = data->shared;\n\n     direct_signal_handler_remove( data->dump_signal_handler );\n\n     dfb_surface_pool_bridge_leave( shared->prealloc_pool_bridge );\n\n     dfb_surface_pool_leave( shared->prealloc_pool );\n\n     dfb_surface_pool_leave( shared->surface_pool );\n\n     D_MAGIC_CLEAR( data );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_surface_core_suspend( DFBSurfaceCore *data )\n{\n     D_DEBUG_AT( Core_Surface, \"%s( %p )\\n\", __FUNCTION__, data );\n\n     D_MAGIC_ASSERT( data, DFBSurfaceCore );\n     D_MAGIC_ASSERT( data->shared, DFBSurfaceCoreShared );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_surface_core_resume( DFBSurfaceCore *data )\n{\n     D_DEBUG_AT( Core_Surface, \"%s( %p )\\n\", __FUNCTION__, data );\n\n     D_MAGIC_ASSERT( data, DFBSurfaceCore );\n     D_MAGIC_ASSERT( data->shared, DFBSurfaceCoreShared );\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/core/surface_core.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__SURFACE_CORE_H__\n#define __CORE__SURFACE_CORE_H__\n\n#include <core/coretypes.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int                    magic;\n\n     CoreSurfacePool       *surface_pool;\n     CoreSurfacePool       *prealloc_pool;\n\n     CoreSurfacePoolBridge *prealloc_pool_bridge;\n} DFBSurfaceCoreShared;\n\ntypedef struct __DFB_DFBSurfaceCore {\n     int                   magic;\n\n     CoreDFB              *core;\n\n     DFBSurfaceCoreShared *shared;\n\n     DirectSignalHandler  *dump_signal_handler;\n} DFBSurfaceCore;\n\n#endif\n"
  },
  {
    "path": "src/core/surface_pool.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core.h>\n#include <core/surface_allocation.h>\n#include <core/surface_buffer.h>\n#include <core/surface_pool.h>\n#include <core/system.h>\n#include <direct/memcpy.h>\n#include <directfb_util.h>\n#include <fusion/conf.h>\n#include <fusion/shmalloc.h>\n\nD_DEBUG_DOMAIN( Core_SurfacePool,  \"Core/SurfacePool\",  \"DirectFB Core Surface Pool\" );\nD_DEBUG_DOMAIN( Core_SurfPoolLock, \"Core/SurfPoolLock\", \"DirectFB Core Surface Pool Lock\" );\n\n/**********************************************************************************************************************/\n\nstatic int                     pool_count;\nstatic const SurfacePoolFuncs *pool_funcs[MAX_SURFACE_POOLS];\nstatic void                   *pool_locals[MAX_SURFACE_POOLS];\nstatic CoreSurfacePool        *pool_array[MAX_SURFACE_POOLS];\nstatic unsigned int            pool_order[MAX_SURFACE_POOLS];\n\nstatic __inline__ const SurfacePoolFuncs *\nget_funcs( const CoreSurfacePool *pool )\n{\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_ASSERT( pool->pool_id >= 0 );\n     D_ASSERT( pool->pool_id < MAX_SURFACE_POOLS );\n     D_ASSERT( pool_funcs[pool->pool_id] != NULL );\n\n     /* Return function table of the pool. */\n     return pool_funcs[pool->pool_id];\n}\n\nstatic __inline__ void *\nget_local( const CoreSurfacePool *pool )\n{\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_ASSERT( pool->pool_id >= 0 );\n     D_ASSERT( pool->pool_id < MAX_SURFACE_POOLS );\n\n     /* Return local data of the pool. */\n     return pool_locals[pool->pool_id];\n}\n\nstatic DFBResult init_pool        ( CoreDFB *core, CoreSurfacePool *pool, const SurfacePoolFuncs *funcs, void *ctx );\nstatic void      insert_pool_local( CoreSurfacePool *pool );\nstatic void      remove_pool_local( CoreSurfacePoolID pool_id );\nstatic void      remove_allocation( CoreSurfacePool *pool, CoreSurfaceAllocation *allocation_in );\nstatic DFBResult backup_allocation( CoreSurfaceAllocation *allocation_in );\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_surface_pool_initialize( CoreDFB                 *core,\n                             const SurfacePoolFuncs  *funcs,\n                             CoreSurfacePool        **ret_pool )\n{\n     return dfb_surface_pool_initialize2( core, funcs, dfb_system_data(), ret_pool );\n}\n\nDFBResult\ndfb_surface_pool_initialize2( CoreDFB                 *core,\n                              const SurfacePoolFuncs  *funcs,\n                              void                    *ctx,\n                              CoreSurfacePool        **ret_pool )\n{\n     DFBResult            ret;\n     CoreSurfacePool     *pool;\n     FusionSHMPoolShared *shmpool;\n\n     /* Check against pool limit. */\n     if (pool_count == MAX_SURFACE_POOLS) {\n          D_ERROR( \"Core/SurfacePool: Maximum number of pools (%d) reached!\\n\", MAX_SURFACE_POOLS );\n          return DFB_LIMITEXCEEDED;\n     }\n\n     D_ASSERT( core != NULL );\n     D_ASSERT( funcs != NULL );\n     D_ASSERT( ret_pool != NULL );\n     D_ASSERT( pool_funcs[pool_count] == NULL );\n\n     D_DEBUG_AT( Core_SurfacePool, \"%s( %p )\\n\", __FUNCTION__, funcs );\n\n     shmpool = dfb_core_shmpool( core );\n\n     /* Allocate pool structure. */\n     pool = SHCALLOC( shmpool, 1, sizeof(CoreSurfacePool) );\n     if (!pool)\n          return D_OOSHM();\n\n     /* Assign a pool ID. */\n     pool->pool_id = pool_count++;\n\n     /* Remember shared memory pool. */\n     pool->shmpool = shmpool;\n\n     /* Set function table of the pool. */\n     pool_funcs[pool->pool_id] = funcs;\n\n     /* Add to global pool list. */\n     pool_array[pool->pool_id] = pool;\n\n     D_MAGIC_SET( pool, CoreSurfacePool );\n\n     ret = init_pool( core, pool, funcs, ctx );\n     if (ret) {\n          pool_funcs[pool->pool_id] = NULL;\n          pool_array[pool->pool_id] = NULL;\n          pool_count--;\n          D_MAGIC_CLEAR( pool );\n          SHFREE( shmpool, pool );\n          return ret;\n     }\n\n     /* Set default backup pool being the shared memory surface pool. */\n     if (!pool->backup && pool_count > 1)\n          pool->backup = pool_array[0];\n\n     /* Insert new pool into priority order. */\n     insert_pool_local( pool );\n\n     /* Return the new pool. */\n     *ret_pool = pool;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_pool_join( CoreDFB                *core,\n                       CoreSurfacePool        *pool,\n                       const SurfacePoolFuncs *funcs )\n{\n     return dfb_surface_pool_join2( core, pool, funcs, dfb_system_data() );\n}\n\nDFBResult\ndfb_surface_pool_join2( CoreDFB                *core,\n                        CoreSurfacePool        *pool,\n                        const SurfacePoolFuncs *funcs,\n                        void                   *ctx )\n{\n     DFBResult ret;\n\n     D_ASSERT( core != NULL );\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_ASSERT( pool->pool_id < MAX_SURFACE_POOLS );\n     D_ASSERT( pool->pool_id == pool_count );\n     D_ASSERT( pool_funcs[pool->pool_id] == NULL );\n     D_ASSERT( funcs != NULL );\n\n     D_DEBUG_AT( Core_SurfacePool, \"%s( %p [%u], %p )\\n\", __FUNCTION__, pool, pool->pool_id, funcs );\n\n     /* Enforce same order as initialization to be used during join. */\n     if (pool->pool_id != pool_count) {\n          D_ERROR( \"Core/SurfacePool: Wrong order of joining pools, got %u, should be %d!\\n\",\n                   pool->pool_id, pool_count );\n          return DFB_BUG;\n     }\n\n     /* Allocate local pool data. */\n     if (pool->pool_local_data_size && !(pool_locals[pool->pool_id] = D_CALLOC( 1, pool->pool_local_data_size )))\n         return D_OOM();\n\n     /* Set function table of the pool. */\n     pool_funcs[pool->pool_id] = funcs;\n\n     /* Add to global pool list. */\n     pool_array[pool->pool_id] = pool;\n\n     /* Adjust pool count. */\n     if (pool_count < pool->pool_id + 1)\n          pool_count = pool->pool_id + 1;\n\n     funcs = get_funcs( pool );\n\n     if (funcs->JoinPool) {\n          ret = funcs->JoinPool( core, pool, pool->data, get_local(pool), ctx );\n          if (ret) {\n               D_DERROR( ret, \"Core/SurfacePool: Joining '%s' failed!\\n\", pool->desc.name );\n\n               if (pool_locals[pool->pool_id]) {\n                    D_FREE( pool_locals[pool->pool_id] );\n                    pool_locals[pool->pool_id] = NULL;\n               }\n\n               pool_array[pool->pool_id] = NULL;\n               pool_array[pool->pool_id] = NULL;\n\n               pool_count--;\n\n               return ret;\n          }\n     }\n\n     /* Insert new pool into priority order. */\n     insert_pool_local( pool );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_pool_destroy( CoreSurfacePool *pool )\n{\n     const SurfacePoolFuncs *funcs;\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_ASSERT( pool->pool_id >= 0 );\n     D_ASSERT( pool->pool_id < MAX_SURFACE_POOLS );\n     D_ASSERT( pool_array[pool->pool_id] == pool );\n\n     D_DEBUG_AT( Core_SurfacePool, \"%s( %p [%u - %s] )\\n\", __FUNCTION__, pool, pool->pool_id, pool->desc.name );\n\n     funcs = get_funcs( pool );\n\n     if (funcs->DestroyPool)\n          funcs->DestroyPool( pool, pool->data, get_local(pool) );\n\n     /* Free shared pool data. */\n     if (pool->data)\n          SHFREE( pool->shmpool, pool->data );\n\n     /* Free local pool data and remove from lists. */\n     remove_pool_local( pool->pool_id );\n\n     fusion_skirmish_destroy( &pool->lock );\n\n     fusion_vector_destroy( &pool->allocs );\n\n     D_MAGIC_CLEAR( pool );\n\n     SHFREE( pool->shmpool, pool );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_pool_leave( CoreSurfacePool *pool )\n{\n     const SurfacePoolFuncs *funcs;\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_ASSERT( pool->pool_id >= 0 );\n     D_ASSERT( pool->pool_id < MAX_SURFACE_POOLS );\n     D_ASSERT( pool_array[pool->pool_id] == pool );\n\n     D_DEBUG_AT( Core_SurfacePool, \"%s( %p [%u - %s] )\\n\", __FUNCTION__, pool, pool->pool_id, pool->desc.name );\n\n     funcs = get_funcs( pool );\n\n     if (funcs->LeavePool)\n          funcs->LeavePool( pool, pool->data, get_local(pool) );\n\n     /* Free local pool data and remove from lists. */\n     remove_pool_local( pool->pool_id );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_pools_prealloc( const DFBSurfaceDescription *description,\n                            CoreSurfaceConfig           *config )\n{\n     DFBResult            ret;\n     int                  i;\n     CoreSurfaceTypeFlags type;\n\n     D_ASSERT( description != NULL );\n     D_ASSERT( config != NULL );\n\n     D_DEBUG_AT( Core_SurfacePool, \"%s( %p, %p )\\n\", __FUNCTION__, description, config );\n\n     type = CSTF_PREALLOCATED;\n\n     if (description->flags & DSDESC_CAPS) {\n          if (description->caps & DSCAPS_SYSTEMONLY)\n               type |= CSTF_INTERNAL;\n\n          if (description->caps & DSCAPS_VIDEOONLY)\n               type |= CSTF_EXTERNAL;\n     }\n\n     D_DEBUG_AT( Core_SurfacePool, \"  -> type 0x%03x required\\n\", type );\n\n     for (i = 0; i < pool_count; i++) {\n          CoreSurfacePool *pool;\n\n          D_ASSERT( pool_order[i] >= 0 );\n          D_ASSERT( pool_order[i] < pool_count );\n\n          pool = pool_array[pool_order[i]];\n          D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n          if (D_FLAGS_ARE_SET( pool->desc.types, type )) {\n               const SurfacePoolFuncs *funcs;\n\n               D_DEBUG_AT( Core_SurfacePool, \"  -> [%u - %s] 0x%02x 0x%03x (%u)\\n\", pool->pool_id, pool->desc.name,\n                           pool->desc.caps, pool->desc.types, pool->desc.priority );\n\n               funcs = get_funcs( pool );\n\n               if (funcs->PreAlloc) {\n                    ret = funcs->PreAlloc( pool, pool->data, get_local(pool), description, config );\n                    if (ret == DFB_OK) {\n                         config->preallocated_pool_id = pool->pool_id;\n                         return DFB_OK;\n                    }\n               }\n          }\n     }\n\n     return DFB_UNSUPPORTED;\n}\n\nDFBResult\ndfb_surface_pools_negotiate( CoreSurfaceBuffer       *buffer,\n                             CoreSurfaceAccessorID    accessor,\n                             CoreSurfaceAccessFlags   access,\n                             CoreSurfacePool        **ret_pools,\n                             unsigned int             max_pools,\n                             unsigned int            *ret_num )\n{\n     DFBResult             ret;\n     int                   i;\n     unsigned int          num = 0;\n     CoreSurface          *surface;\n     CoreSurfaceTypeFlags  type;\n     unsigned int          free_count = 0;\n     CoreSurfacePool      *free_pools[pool_count];\n     unsigned int          oom_count = 0;\n     CoreSurfacePool      *oom_pools[pool_count];\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n     D_ASSERT( accessor >= CSAID_CPU );\n     D_ASSERT( ret_pools != NULL );\n     D_ASSERT( max_pools > 0 );\n     D_ASSERT( ret_num != NULL );\n\n     surface = buffer->surface;\n\n     FUSION_SKIRMISH_ASSERT( &surface->lock );\n\n     D_DEBUG_AT( Core_SurfacePool, \"%s( %p [%s], 0x%02x, 0x%02x, max %u )\\n\", __FUNCTION__,\n                 buffer, dfb_pixelformat_name( surface->config.format ), accessor, access, max_pools );\n\n     D_ASSUME( accessor < CSAID_NUM );\n\n     if (accessor >= CSAID_ANY) {\n          D_UNIMPLEMENTED();\n          return DFB_UNIMPLEMENTED;\n     }\n\n     if (accessor < 0 || accessor >= CSAID_NUM)\n          return DFB_INVARG;\n\n     type = surface->type & ~(CSTF_INTERNAL | CSTF_EXTERNAL);\n\n     switch (buffer->policy) {\n          case CSP_SYSTEMONLY:\n               type |= CSTF_INTERNAL;\n               break;\n\n          case CSP_VIDEOONLY:\n               type |= CSTF_EXTERNAL;\n               break;\n\n          default:\n               break;\n     }\n\n     D_DEBUG_AT( Core_SurfacePool, \"  -> 0x%02x 0x%03x required\\n\", access, type );\n\n     if (access & CSAF_READ)\n          D_DEBUG_AT( Core_SurfacePool, \"  -> READ\\n\" );\n\n     if (access & CSAF_WRITE)\n          D_DEBUG_AT( Core_SurfacePool, \"  -> WRITE\\n\" );\n\n     if (access & CSAF_SHARED)\n          D_DEBUG_AT( Core_SurfacePool, \"  -> SHARED\\n\" );\n\n     if (type & CSTF_LAYER)\n          D_DEBUG_AT( Core_SurfacePool, \"  -> LAYER\\n\" );\n\n     if (type & CSTF_WINDOW)\n          D_DEBUG_AT( Core_SurfacePool, \"  -> WINDOW\\n\" );\n\n     if (type & CSTF_CURSOR)\n          D_DEBUG_AT( Core_SurfacePool, \"  -> CURSOR\\n\" );\n\n     if (type & CSTF_FONT)\n          D_DEBUG_AT( Core_SurfacePool, \"  -> FONT\\n\" );\n\n     if (type & CSTF_SHARED)\n          D_DEBUG_AT( Core_SurfacePool, \"  -> SHARED\\n\" );\n\n     if (type & CSTF_INTERNAL)\n          D_DEBUG_AT( Core_SurfacePool, \"  -> INTERNAL\\n\" );\n\n     if (type & CSTF_EXTERNAL)\n          D_DEBUG_AT( Core_SurfacePool, \"  -> EXTERNAL\\n\" );\n\n     if (type & CSTF_PREALLOCATED)\n          D_DEBUG_AT( Core_SurfacePool, \"  -> PREALLOCATED\\n\" );\n\n     for (i = 0; i < pool_count; i++) {\n          CoreSurfacePool *pool;\n\n          D_ASSERT( pool_order[i] >= 0 );\n          D_ASSERT( pool_order[i] < pool_count );\n\n          pool = pool_array[pool_order[i]];\n\n          D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n          D_DEBUG_AT( Core_SurfacePool, \"  -> [%u - %s] 0x%02x 0x%03x (%u), 0x%02x\\n\", pool->pool_id, pool->desc.name,\n                      pool->desc.caps, pool->desc.types, pool->desc.priority, pool->desc.access[accessor] );\n\n          if (Core_GetIdentity() != FUSION_ID_MASTER && !(pool->desc.access[accessor] & CSAF_SHARED)) {\n               D_DEBUG_AT( Core_SurfacePool, \"    -> refusing allocation for slave in non-shared pool!\\n\" );\n               continue;\n          }\n\n          if (D_FLAGS_ARE_SET( pool->desc.access[accessor], access ) &&\n              D_FLAGS_ARE_SET( pool->desc.types, type & ~CSTF_PREALLOCATED )) {\n               const SurfacePoolFuncs *funcs;\n\n               D_DEBUG_AT( Core_SurfacePool, \"  -> [%u - %s] 0x%02x 0x%03x (%u)\\n\", pool->pool_id, pool->desc.name,\n                           pool->desc.caps, pool->desc.types, pool->desc.priority );\n\n               funcs = get_funcs( pool );\n\n               ret = funcs->TestConfig ?\n                     funcs->TestConfig( pool, pool->data, get_local(pool), buffer, &surface->config ) : DFB_OK;\n\n               switch (ret) {\n                    case DFB_OK:\n                         D_DEBUG_AT( Core_SurfacePool, \"    => OK\\n\" );\n                         free_pools[free_count++] = pool;\n                         break;\n\n                    case DFB_NOVIDEOMEMORY:\n                         D_DEBUG_AT( Core_SurfacePool, \"    => OUT OF MEMORY\\n\" );\n                         oom_pools[oom_count++] = pool;\n                         break;\n\n                    default:\n                         D_DEBUG_AT( Core_SurfacePool, \"    => %s\\n\", DirectFBErrorString( ret ) );\n                         continue;\n               }\n          }\n     }\n\n     D_DEBUG_AT( Core_SurfacePool, \"  -> %u pools available\\n\", free_count );\n     D_DEBUG_AT( Core_SurfacePool, \"  -> %u pools out of memory\\n\", oom_count );\n\n     for (i = 0; i < free_count && num < max_pools; i++)\n          ret_pools[num++] = free_pools[i];\n\n     for (i = 0; i < oom_count && num < max_pools; i++)\n          ret_pools[num++] = oom_pools[i];\n\n     *ret_num = num;\n\n     return free_count ? DFB_OK : oom_count ? DFB_NOVIDEOMEMORY : DFB_UNSUPPORTED;\n}\n\nDFBResult\ndfb_surface_pools_enumerate( CoreSurfacePoolCallback  callback,\n                             void                    *ctx )\n{\n     int i;\n\n     D_ASSERT( callback != NULL );\n\n     D_DEBUG_AT( Core_SurfacePool, \"%s( %p, %p )\\n\", __FUNCTION__, callback, ctx );\n\n     for (i = 0; i < pool_count; i++) {\n          CoreSurfacePool *pool = pool_array[i];\n\n          D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n          if (callback( pool, ctx ) == DFENUM_CANCEL)\n               break;\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_pools_lookup( CoreSurfacePoolID   pool_id,\n                          CoreSurfacePool   **ret_pool )\n{\n     int i;\n\n     D_ASSERT( ret_pool != NULL );\n\n     D_DEBUG_AT( Core_SurfacePool, \"%s( [%u], %p )\\n\", __FUNCTION__, pool_id, ret_pool );\n\n     for (i = 0; i < pool_count; i++) {\n          CoreSurfacePool *pool = pool_array[i];\n\n          D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n          if (pool->pool_id == pool_id) {\n               *ret_pool = pool;\n               return DFB_OK;\n          }\n     }\n\n     return DFB_IDNOTFOUND;\n}\n\nDFBResult\ndfb_surface_pools_allocate( CoreSurfaceBuffer       *buffer,\n                            CoreSurfaceAccessorID    accessor,\n                            CoreSurfaceAccessFlags   access,\n                            CoreSurfaceAllocation  **ret_allocation )\n{\n     DFBResult              ret;\n     int                    i;\n     CoreSurface           *surface;\n     CoreSurfaceAllocation *allocation = NULL;\n     CoreSurfacePool       *pools[pool_count];\n     unsigned int           num_pools;\n\n     D_UNUSED_P( surface );\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n     D_ASSERT( accessor >= CSAID_CPU );\n     D_FLAGS_ASSERT( access, CSAF_ALL );\n     D_ASSERT( ret_allocation != NULL );\n\n     surface = buffer->surface;\n\n     FUSION_SKIRMISH_ASSERT( &surface->lock );\n\n     D_DEBUG_AT( Core_SurfacePool, \"%s( %p, 0x%x )\\n\", __FUNCTION__, buffer, access );\n\n     D_DEBUG_AT( Core_SurfacePool, \"  -> %dx%d %s - %s%s%s%s%s%s%s%s\\n\",\n                 surface->config.size.w, surface->config.size.h, dfb_pixelformat_name( surface->config.format ),\n                 (surface->type & CSTF_SHARED)       ? \"SHARED\"        : \"PRIVATE\",\n                 (surface->type & CSTF_LAYER)        ? \" LAYER\"        : \"\",\n                 (surface->type & CSTF_WINDOW)       ? \" WINDOW\"       : \"\",\n                 (surface->type & CSTF_CURSOR)       ? \" CURSOR\"       : \"\",\n                 (surface->type & CSTF_FONT)         ? \" FONT\"         : \"\",\n                 (surface->type & CSTF_INTERNAL)     ? \" INTERNAL\"     : \"\",\n                 (surface->type & CSTF_EXTERNAL)     ? \" EXTERNAL\"     : \"\",\n                 (surface->type & CSTF_PREALLOCATED) ? \" PREALLOCATED\" : \"\" );\n\n     D_ASSUME( accessor < CSAID_NUM );\n\n     if (accessor >= CSAID_ANY) {\n          D_UNIMPLEMENTED();\n          return DFB_UNIMPLEMENTED;\n     }\n\n     if (accessor < 0 || accessor >= CSAID_NUM)\n          return DFB_INVARG;\n\n     /* Build a list of possible pools being free or out of memory. */\n     ret = dfb_surface_pools_negotiate( buffer, accessor, access, pools, pool_count, &num_pools );\n     if (ret && ret != DFB_NOVIDEOMEMORY) {\n          D_DEBUG_AT( Core_SurfacePool, \"  -> negotiation failed!\\n\" );\n          return ret;\n     }\n\n     /* Try to do the allocation in one of the pools. */\n     for (i = 0; i < num_pools; i++) {\n          CoreSurfacePool *pool = pools[i];\n\n          D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n          ret = dfb_surface_pool_allocate( pool, buffer, NULL, 0, &allocation );\n\n          if (ret == DFB_OK)\n               break;\n\n          /* When an error other than out of memory happens. */\n          if (ret != DFB_NOVIDEOMEMORY) {\n               D_DEBUG_AT( Core_SurfacePool, \"  -> allocation in '%s' failed!\\n\", pool->desc.name );\n\n               /* Forget about the pool for now. */\n               pools[i] = NULL;\n          }\n     }\n\n     /* Check if none of the pools could do the allocation. */\n     if (!allocation) {\n          /* Try to find a pool with older allocations to muck out. */\n          for (i = 0; i < num_pools; i++) {\n               CoreSurfacePool *pool = pools[i];\n\n               /* Pools with non-oom errors were sorted out above. */\n               if (!pool)\n                    continue;\n\n               D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n               ret = dfb_surface_pool_displace( pool, buffer, &allocation );\n\n               if (ret == DFB_OK)\n                    break;\n          }\n     }\n\n     if (!allocation) {\n          D_DEBUG_AT( Core_SurfacePool, \"  -> allocation failed!\\n\" );\n          return DFB_FAILURE;\n     }\n\n     CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n     D_DEBUG_AT( Core_SurfacePool, \"  -> %p\\n\", allocation );\n\n     *ret_allocation = allocation;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_pools_allocate_key( CoreSurfaceBuffer      *buffer,\n                                const char             *key,\n                                u64                     handle,\n                                CoreSurfaceAllocation **ret_allocation )\n{\n     DFBResult              ret;\n     int                    i;\n     CoreSurface           *surface;\n     CoreSurfaceAllocation *allocation = NULL;\n\n     D_UNUSED_P( surface );\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n     D_ASSERT( key != NULL );\n     D_ASSERT( ret_allocation != NULL );\n\n     surface = buffer->surface;\n\n     FUSION_SKIRMISH_ASSERT( &surface->lock );\n\n     D_DEBUG_AT( Core_SurfacePool, \"%s( %p, key '%s', handle 0x%08llx )\\n\", __FUNCTION__,\n                 buffer, key, (unsigned long long) handle );\n\n     for (i = 0; i < pool_count; i++) {\n          CoreSurfacePool *pool;\n\n          D_ASSERT( pool_order[i] >= 0 );\n          D_ASSERT( pool_order[i] < pool_count );\n\n          pool = pool_array[pool_order[i]];\n\n          D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n          if (D_FLAGS_ARE_SET( pool->desc.types,\n                               buffer->type & ~(CSTF_PREALLOCATED | CSTF_INTERNAL | CSTF_EXTERNAL) )) {\n               D_DEBUG_AT( Core_SurfacePool, \"  -> [%u - %s] 0x%02x 0x%03x (%u)\\n\", pool->pool_id, pool->desc.name,\n                           pool->desc.caps, pool->desc.types, pool->desc.priority );\n\n               ret = dfb_surface_pool_check_key( pool, buffer, key, handle );\n               if (ret == DFB_OK)\n                    break;\n          }\n     }\n\n     if (i < pool_count) {\n          CoreSurfacePool *pool;\n\n          pool = pool_array[pool_order[i]];\n\n          D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n          ret = dfb_surface_pool_allocate( pool, buffer, key, handle, &allocation );\n          if (ret) {\n               D_DEBUG_AT( Core_SurfacePool, \"  -> dfb_surface_pool_allocate() failed\\n\" );\n          }\n          else {\n               D_DEBUG_AT( Core_SurfacePool, \"  -> %p\\n\", allocation );\n\n               CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n               *ret_allocation = allocation;\n          }\n     }\n     else {\n          D_DEBUG_AT( Core_SurfacePool, \"  -> no pool found for key!\\n\" );\n\n          ret = DFB_UNSUPPORTED;\n     }\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_pool_check_key( CoreSurfacePool   *pool,\n                            CoreSurfaceBuffer *buffer,\n                            const char        *key,\n                            u64                handle )\n{\n     DFBResult               ret = DFB_UNSUPPORTED;\n     const SurfacePoolFuncs *funcs;\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_ASSERT( key != NULL );\n\n     D_DEBUG_AT( Core_SurfacePool, \"%s( %p, %p, key '%s', handle 0x%08llx )\\n\", __FUNCTION__,\n                 pool, buffer, key, (unsigned long long) handle );\n\n     funcs = get_funcs( pool );\n\n     if (funcs->CheckKey) {\n          ret = funcs->CheckKey( pool, pool->data, get_local(pool), buffer, key, handle );\n\n          D_DEBUG_AT( Core_SurfacePool, \"  -> %s\\n\", DirectFBErrorString( ret ) );\n     }\n     else\n          D_DEBUG_AT( Core_SurfacePool, \"  -> no support for keys!\\n\" );\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_pool_allocate( CoreSurfacePool        *pool,\n                           CoreSurfaceBuffer      *buffer,\n                           const char             *key,\n                           u64                     handle,\n                           CoreSurfaceAllocation **ret_allocation )\n{\n     DFBResult               ret;\n     CoreSurface            *surface;\n     CoreSurfaceAllocation  *allocation = NULL;\n     const SurfacePoolFuncs *funcs;\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n     D_ASSERT( ret_allocation != NULL );\n\n     surface = buffer->surface;\n\n     FUSION_SKIRMISH_ASSERT( &surface->lock );\n\n     D_DEBUG_AT( Core_SurfacePool, \"%s( %p [%u - %s], %p )\\n\", __FUNCTION__,\n                 pool, pool->pool_id, pool->desc.name, buffer );\n\n     funcs = get_funcs( pool );\n\n     ret = dfb_surface_allocation_create( core_dfb, buffer, pool, &allocation );\n     if (ret)\n          return ret;\n\n     if (fusion_skirmish_prevail( &pool->lock )) {\n          ret = DFB_FUSION;\n          goto error;\n     }\n\n     if (dfb_config->warn.flags & DCWF_ALLOCATE_BUFFER                         &&\n         dfb_config->warn.allocate_buffer.min_size.w <= surface->config.size.w &&\n         dfb_config->warn.allocate_buffer.min_size.h <= surface->config.size.h)\n          D_WARN( \"allocate-buffer %4dx%4d %6s, surface-caps 0x%08x, key '%s'\",\n                  surface->config.size.w, surface->config.size.h, dfb_pixelformat_name( buffer->config.format ),\n                  surface->config.caps, key ?: \"(none)\" );\n\n     if (key) {\n          D_ASSERT( funcs->AllocateKey != NULL );\n\n          ret = funcs->AllocateKey( pool, pool->data, get_local(pool), buffer, key, handle, allocation,\n                                    allocation->data );\n     }\n     else {\n          D_ASSERT( funcs->AllocateBuffer != NULL );\n\n          ret = funcs->AllocateBuffer( pool, pool->data, get_local(pool), buffer, allocation,\n                                       allocation->data );\n     }\n\n     if (ret) {\n          allocation->flags |= CSALF_DEALLOCATED;\n          fusion_skirmish_dismiss( &pool->lock );\n          goto error;\n     }\n\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n\n     D_DEBUG_AT( Core_SurfacePool, \"  -> %p\\n\", allocation );\n\n     D_FLAGS_CLEAR( allocation->flags, CSALF_INITIALIZING );\n\n     fusion_vector_add( &buffer->allocs, allocation );\n     fusion_vector_add( &pool->allocs, allocation );\n\n     /* Mark the CoreSurfaceAllocation as having been read and written to by the CPU because it is possible that\n        the CPU cache after the allocation has some data due to a read/write performed as part of allocation. */\n     allocation->accessed[CSAID_CPU] |= CSAF_READ | CSAF_WRITE;\n\n     dfb_surface_allocation_globalize( allocation );\n\n     fusion_skirmish_dismiss( &pool->lock );\n\n     CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n     *ret_allocation = allocation;\n\n     return DFB_OK;\n\nerror:\n     dfb_surface_allocation_unref( allocation );\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_pool_deallocate( CoreSurfacePool       *pool,\n                             CoreSurfaceAllocation *allocation )\n{\n     DFBResult               ret;\n     const SurfacePoolFuncs *funcs;\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n     D_DEBUG_AT( Core_SurfacePool, \"%s( %p [%u - %s], %p )\\n\", __FUNCTION__,\n                 pool, pool->pool_id, pool->desc.name, allocation );\n\n     CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n     D_ASSERT( pool == allocation->pool );\n\n     if (allocation->flags & CSALF_DEALLOCATED) {\n          D_DEBUG_AT( Core_SurfacePool, \"  -> already deallocated\\n\" );\n          return DFB_OK;\n     }\n\n     funcs = get_funcs( pool );\n\n     D_ASSERT( funcs->DeallocateBuffer != NULL );\n\n     if (fusion_skirmish_prevail( &pool->lock ))\n          return DFB_FUSION;\n\n     ret = funcs->DeallocateBuffer( pool, pool->data, get_local(pool), allocation->buffer, allocation,\n                                    allocation->data );\n     if (ret) {\n          D_DERROR( ret, \"Core/SurfacePool: Could not deallocate buffer!\\n\" );\n          fusion_skirmish_dismiss( &pool->lock );\n          return ret;\n     }\n\n     remove_allocation( pool, allocation );\n\n     allocation->flags |= CSALF_DEALLOCATED;\n\n     CoreSurfaceAllocationNotification notification;\n     notification.flags = CSANF_DEALLOCATED;\n     dfb_surface_allocation_dispatch( allocation, &notification, NULL );\n\n     fusion_skirmish_dismiss( &pool->lock );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_pool_displace( CoreSurfacePool        *pool,\n                           CoreSurfaceBuffer      *buffer,\n                           CoreSurfaceAllocation **ret_allocation )\n{\n     DFBResult               ret, ret_lock = DFB_OK;\n     int                     i, retries = 3;\n     CoreSurface            *surface;\n     CoreSurfaceAllocation  *allocation;\n     const SurfacePoolFuncs *funcs;\n\n     D_UNUSED_P( surface );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n     D_ASSERT( ret_allocation != NULL );\n\n     surface = buffer->surface;\n\n     FUSION_SKIRMISH_ASSERT( &surface->lock );\n\n     D_DEBUG_AT( Core_SurfacePool, \"%s( %p [%u - %s], %p )\\n\", __FUNCTION__,\n                 pool, pool->pool_id, pool->desc.name, buffer );\n\n     funcs = get_funcs( pool );\n\n     if (fusion_skirmish_prevail( &pool->lock ))\n          return DFB_FUSION;\n\n     /* Check for integrated method to muck out older allocations for a new one. */\n     if (funcs->MuckOut) {\n          ret = funcs->MuckOut( pool, pool->data, get_local(pool), buffer );\n          if (ret) {\n               fusion_skirmish_dismiss( &pool->lock );\n               return ret;\n          }\n     }\n     else {\n          D_UNIMPLEMENTED();\n     }\n\nretry:\n     fusion_vector_foreach (allocation, i, pool->allocs) {\n          CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n          if (allocation->flags & CSALF_MUCKOUT) {\n               CoreSurface       *alloc_surface;\n               CoreSurfaceBuffer *alloc_buffer;\n\n               alloc_buffer = allocation->buffer;\n\n               D_MAGIC_ASSERT( alloc_buffer, CoreSurfaceBuffer );\n\n               alloc_surface = alloc_buffer->surface;\n\n               D_MAGIC_ASSERT( alloc_surface, CoreSurface );\n\n               D_DEBUG_AT( Core_SurfacePool, \"  <= %p %5dk, %lu\\n\",\n                           allocation, allocation->size / 1024, allocation->offset );\n\n               ret = dfb_surface_trylock( alloc_surface );\n               if (ret) {\n                    D_WARN( \"could not lock surface (%s)\", DirectFBErrorString( ret ) );\n                    ret_lock = ret;\n                    continue;\n               }\n\n               /* Ensure mucked out allocation is backed up to another pool. */\n               ret = backup_allocation( allocation );\n               if (ret) {\n                    D_WARN( \"could not backup allocation (%s)\", DirectFBErrorString( ret ) );\n                    dfb_surface_unlock( alloc_surface );\n                    goto error;\n               }\n\n               /* Deallocate mucked out allocation. */\n               dfb_surface_allocation_decouple( allocation );\n               i--;\n\n               dfb_surface_unlock( alloc_surface );\n          }\n     }\n\n     if (ret_lock) {\n          if (retries--)\n               goto retry;\n\n          ret = DFB_LOCKED;\n\n          goto error;\n     }\n     else\n          ret = dfb_surface_pool_allocate( pool, buffer, NULL, 0, ret_allocation );\n\n     fusion_skirmish_dismiss( &pool->lock );\n\n     return ret;\n\nerror:\n     fusion_vector_foreach (allocation, i, pool->allocs) {\n          CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n          if (allocation->flags & CSALF_MUCKOUT)\n               allocation->flags &= ~CSALF_MUCKOUT;\n     }\n\n     fusion_skirmish_dismiss( &pool->lock );\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_pool_prelock( CoreSurfacePool        *pool,\n                          CoreSurfaceAllocation  *allocation,\n                          CoreSurfaceAccessorID   accessor,\n                          CoreSurfaceAccessFlags  access )\n{\n     DFBResult               ret;\n     const SurfacePoolFuncs *funcs;\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n     D_DEBUG_AT( Core_SurfPoolLock, \"%s( %p [%u - %s], %p )\\n\", __FUNCTION__,\n                 pool, pool->pool_id, pool->desc.name, allocation );\n\n     CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n     D_ASSERT( pool == allocation->pool );\n\n     funcs = get_funcs( pool );\n\n     if (funcs->PreLock) {\n          ret = funcs->PreLock( pool, pool->data, get_local(pool), allocation, allocation->data, accessor, access );\n          if (ret) {\n               D_DERROR( ret, \"Core/SurfacePool: Could not prelock allocation!\\n\" );\n               return ret;\n          }\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_pool_lock( CoreSurfacePool       *pool,\n                       CoreSurfaceAllocation *allocation,\n                       CoreSurfaceBufferLock *lock )\n{\n     DFBResult               ret;\n     const SurfacePoolFuncs *funcs;\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n     D_DEBUG_AT( Core_SurfPoolLock, \"%s( %p [%u - %s], %p )\\n\", __FUNCTION__,\n                 pool, pool->pool_id, pool->desc.name, allocation );\n\n     CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n     D_ASSERT( pool == allocation->pool );\n\n     CORE_SURFACE_BUFFER_LOCK_ASSERT( lock );\n\n     D_ASSERT( lock->buffer == NULL );\n\n     funcs = get_funcs( pool );\n\n     D_ASSERT( funcs->Lock != NULL );\n\n     lock->allocation = allocation;\n     lock->buffer     = allocation->buffer;\n\n     ret = funcs->Lock( pool, pool->data, get_local(pool), allocation, allocation->data, lock );\n     if (ret) {\n          D_DERROR( ret, \"Core/SurfacePool: Could not lock allocation!\\n\" );\n          dfb_surface_buffer_lock_reset( lock );\n          return ret;\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_pool_unlock( CoreSurfacePool       *pool,\n                         CoreSurfaceAllocation *allocation,\n                         CoreSurfaceBufferLock *lock )\n{\n     DFBResult               ret;\n     const SurfacePoolFuncs *funcs;\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n     D_DEBUG_AT( Core_SurfPoolLock, \"%s( %p [%u - %s], %p )\\n\", __FUNCTION__,\n                 pool, pool->pool_id, pool->desc.name, allocation );\n\n     CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n     D_ASSERT( pool == allocation->pool );\n\n     CORE_SURFACE_BUFFER_LOCK_ASSERT( lock );\n\n     D_ASSERT( lock->allocation == allocation );\n\n     funcs = get_funcs( pool );\n\n     D_ASSERT( funcs->Unlock != NULL );\n\n     ret = funcs->Unlock( pool, pool->data, get_local(pool), allocation, allocation->data, lock );\n     if (ret) {\n          D_DERROR( ret, \"Core/SurfacePool: Could not unlock allocation!\\n\" );\n          return ret;\n     }\n\n     dfb_surface_buffer_lock_reset( lock );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_pool_read( CoreSurfacePool       *pool,\n                       CoreSurfaceAllocation *allocation,\n                       void                  *data,\n                       int                    pitch,\n                       const DFBRectangle    *rect )\n{\n     DFBResult               ret;\n     const SurfacePoolFuncs *funcs;\n     CoreSurface            *surface;\n     DFBRectangle            area;\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n     D_DEBUG_AT( Core_SurfPoolLock, \"%s( %p [%u - %s], %p )\\n\", __FUNCTION__,\n                 pool, pool->pool_id, pool->desc.name, allocation );\n\n     CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n     D_ASSERT( pool == allocation->pool );\n     D_ASSERT( data != NULL );\n     D_ASSERT( pitch >= 0 );\n     DFB_RECTANGLE_ASSERT_IF( rect );\n\n     funcs = get_funcs( pool );\n\n     D_ASSERT( funcs != NULL );\n\n     if (!funcs->Read)\n          return DFB_UNSUPPORTED;\n\n     surface = allocation->surface;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n\n     area.x = 0;\n     area.y = 0;\n     area.w = surface->config.size.w;\n     area.h = surface->config.size.h;\n\n     if (rect && !dfb_rectangle_intersect( &area, rect ))\n          return DFB_INVAREA;\n\n     ret = funcs->Read( pool, pool->data, get_local(pool), allocation, allocation->data, data, pitch, &area );\n     if (ret)\n          D_DERROR( ret, \"Core/SurfacePool: Could not read from allocation!\\n\" );\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_pool_write( CoreSurfacePool       *pool,\n                        CoreSurfaceAllocation *allocation,\n                        const void            *data,\n                        int                    pitch,\n                        const DFBRectangle    *rect )\n{\n     DFBResult               ret;\n     const SurfacePoolFuncs *funcs;\n     CoreSurface            *surface;\n     DFBRectangle            area;\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n     D_DEBUG_AT( Core_SurfPoolLock, \"%s( %p [%u - %s], %p )\\n\", __FUNCTION__,\n                 pool, pool->pool_id, pool->desc.name, allocation );\n\n     CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n     D_ASSERT( pool == allocation->pool );\n     D_ASSERT( data != NULL );\n     D_ASSERT( pitch >= 0 );\n     DFB_RECTANGLE_ASSERT_IF( rect );\n\n     funcs = get_funcs( pool );\n\n     if (!funcs->Write)\n          return DFB_UNSUPPORTED;\n\n     surface = allocation->surface;\n\n     D_MAGIC_ASSERT( surface, CoreSurface );\n\n     area.x = 0;\n     area.y = 0;\n     area.w = surface->config.size.w;\n     area.h = surface->config.size.h;\n\n     if (rect && !dfb_rectangle_intersect( &area, rect ))\n          return DFB_INVAREA;\n\n     ret = funcs->Write( pool, pool->data, get_local(pool), allocation, allocation->data, data, pitch, &area );\n     if (ret)\n          D_DERROR( ret, \"Core/SurfacePool: Could not write to allocation!\\n\" );\n\n     return ret;\n}\n\nDFBResult\ndfb_surface_pool_enumerate ( CoreSurfacePool          *pool,\n                             CoreSurfaceAllocCallback  callback,\n                             void                     *ctx )\n{\n     int                    i;\n     CoreSurfaceAllocation *allocation;\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_ASSERT( callback != NULL );\n\n     D_DEBUG_AT( Core_SurfacePool, \"%s( %p, %p, %p )\\n\", __FUNCTION__, pool, callback, ctx );\n\n     fusion_vector_foreach (allocation, i, pool->allocs) {\n          if (callback( allocation, ctx ) == DFENUM_CANCEL)\n               break;\n     }\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic DFBResult\ninit_pool( CoreDFB                *core,\n           CoreSurfacePool        *pool,\n           const SurfacePoolFuncs *funcs,\n           void                   *ctx )\n{\n     DFBResult ret;\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_ASSERT( funcs != NULL );\n     D_ASSERT( funcs->InitPool != NULL );\n\n     D_DEBUG_AT( Core_SurfacePool, \"%s( %p, %p )\\n\", __FUNCTION__, pool, funcs );\n\n     if (funcs->PoolDataSize)\n          pool->pool_data_size = funcs->PoolDataSize();\n\n     if (funcs->PoolLocalDataSize)\n          pool->pool_local_data_size = funcs->PoolLocalDataSize();\n\n     if (funcs->AllocationDataSize)\n          pool->alloc_data_size = funcs->AllocationDataSize();\n\n     /* Allocate shared pool data. */\n     if (pool->pool_data_size) {\n          pool->data = SHCALLOC( pool->shmpool, 1, pool->pool_data_size );\n          if (!pool->data)\n               return D_OOSHM();\n     }\n\n     /* Allocate local pool data. */\n     if (pool->pool_local_data_size && !(pool_locals[pool->pool_id] = D_CALLOC( 1, pool->pool_local_data_size ))) {\n          SHFREE( pool->shmpool, pool->data );\n          return D_OOM();\n     }\n\n     fusion_vector_init( &pool->allocs, 4, pool->shmpool );\n\n     ret = funcs->InitPool( core, pool, pool->data, get_local(pool), ctx, &pool->desc );\n     if (ret) {\n          D_DERROR( ret, \"Core/SurfacePool: Initializing '%s' failed!\\n\", pool->desc.name );\n\n          if (pool_locals[pool->pool_id]) {\n               D_FREE( pool_locals[pool->pool_id] );\n               pool_locals[pool->pool_id] = NULL;\n          }\n          if (pool->data) {\n               SHFREE( pool->shmpool, pool->data );\n               pool->data = NULL;\n          }\n          return ret;\n     }\n\n     pool->desc.caps &= ~(CSPCAPS_READ | CSPCAPS_WRITE);\n\n     if (funcs->Read)\n          pool->desc.caps |= CSPCAPS_READ;\n\n     if (funcs->Write)\n          pool->desc.caps |= CSPCAPS_WRITE;\n\n     fusion_skirmish_init2( &pool->lock, pool->desc.name, dfb_core_world( core ), fusion_config->secure_fusion );\n\n     return DFB_OK;\n}\n\nstatic void\ninsert_pool_local( CoreSurfacePool *pool )\n{\n     int i, n;\n\n     for (i = 0; i < pool_count - 1; i++) {\n          D_ASSERT( pool_order[i] >= 0 );\n          D_ASSERT( pool_order[i] < pool_count - 1 );\n\n          D_MAGIC_ASSERT( pool_array[pool_order[i]], CoreSurfacePool );\n\n          if (pool_array[pool_order[i]]->desc.priority < pool->desc.priority)\n               break;\n     }\n\n     for (n = pool_count - 1; n > i; n--) {\n          D_ASSERT( pool_order[n-1] >= 0 );\n          D_ASSERT( pool_order[n-1] < pool_count - 1 );\n\n          D_MAGIC_ASSERT( pool_array[pool_order[n-1]], CoreSurfacePool );\n\n          pool_order[n] = pool_order[n-1];\n     }\n\n     pool_order[n] = pool_count - 1;\n\n     for (i = 0; i < pool_count; i++) {\n          D_DEBUG_AT( Core_SurfacePool, \"  %c> [%d] %p - '%s' [%u] (%u), %p\\n\",\n                      (i == n) ? '=' : '-', i, pool_array[pool_order[i]], pool_array[pool_order[i]]->desc.name,\n                      pool_array[pool_order[i]]->pool_id, pool_array[pool_order[i]]->desc.priority,\n                      pool_funcs[pool_order[i]] );\n\n          D_ASSERT( pool_order[i] == pool_array[pool_order[i]]->pool_id );\n     }\n}\n\nstatic void\nremove_pool_local( CoreSurfacePoolID pool_id )\n{\n     int i;\n\n     /* Free local pool data. */\n     if (pool_locals[pool_id]) {\n          D_FREE( pool_locals[pool_id] );\n          pool_locals[pool_id] = NULL;\n     }\n\n     /* Erase entries of the pool. */\n     pool_array[pool_id] = NULL;\n     pool_funcs[pool_id] = NULL;\n\n     while (pool_count > 0 && !pool_array[pool_count-1]) {\n          pool_count--;\n\n          for (i = 0; i < pool_count; i++) {\n               if (pool_order[i] == pool_count) {\n                    direct_memmove( &pool_order[i], &pool_order[i+1], sizeof(pool_order[0]) * (pool_count - i) );\n                    break;\n               }\n          }\n     }\n}\n\nstatic void\nremove_allocation( CoreSurfacePool       *pool,\n                   CoreSurfaceAllocation *allocation_in )\n{\n     int                    index_pool;\n     CoreSurfaceAllocation *allocation = allocation_in;\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n\n     D_DEBUG_AT( Core_SurfacePool, \"%s( %p )\\n\", __FUNCTION__, allocation );\n\n     CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n     D_ASSERT( pool == allocation->pool );\n\n     FUSION_SKIRMISH_ASSERT( &pool->lock );\n\n     /* Lookup indices within vectors. */\n     index_pool = fusion_vector_index_of( &pool->allocs, allocation );\n\n     D_ASSERT( index_pool >= 0 );\n\n     /* Remove allocation from buffer and pool. */\n     fusion_vector_remove( &pool->allocs, index_pool );\n}\n\nstatic DFBResult\nbackup_allocation( CoreSurfaceAllocation *allocation_in )\n{\n     DFBResult              ret = DFB_OK;\n     int                    i;\n     CoreSurface           *surface;\n     CoreSurfaceAllocation *allocation = allocation_in;\n     CoreSurfacePool       *pool;\n     CoreSurfaceBuffer     *buffer;\n\n     D_UNUSED_P( surface );\n\n     D_DEBUG_AT( Core_SurfacePool, \"%s( %p )\\n\", __FUNCTION__, allocation );\n\n     CORE_SURFACE_ALLOCATION_ASSERT( allocation );\n\n     D_MAGIC_ASSERT( allocation->pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( allocation->buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( allocation->buffer->surface, CoreSurface );\n\n     pool    = allocation->pool;\n     buffer  = allocation->buffer;\n     surface = buffer->surface;\n\n     FUSION_SKIRMISH_ASSERT( &pool->lock );\n     FUSION_SKIRMISH_ASSERT( &surface->lock );\n\n     /* Check if allocation is the only up to date (requiring a backup). */\n     if (direct_serial_check( &allocation->serial, &buffer->serial )) {\n          CoreSurfacePool *backup_pool = pool->backup;\n\n          /* First check if any of the existing allocations is up to date. */\n          fusion_vector_foreach (allocation, i, buffer->allocs) {\n               D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n               D_MAGIC_ASSERT( allocation->pool, CoreSurfacePool );\n\n               if (allocation->pool != pool && direct_serial_check( &allocation->serial, &buffer->serial )) {\n                    D_DEBUG_AT( Core_SurfacePool, \"  -> up to date in '%s'\\n\", allocation->pool->desc.name );\n                    return DFB_OK;\n               }\n          }\n\n          /* Try to update one of the existing allocations. */\n          fusion_vector_foreach (allocation, i, buffer->allocs) {\n               D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n               D_MAGIC_ASSERT( allocation->pool, CoreSurfacePool );\n\n               if (allocation->pool != pool && dfb_surface_allocation_update( allocation, CSAF_NONE ) == DFB_OK) {\n                    D_DEBUG_AT( Core_SurfacePool, \"  -> updated in '%s'\\n\", allocation->pool->desc.name );\n                    return DFB_OK;\n               }\n          }\n\n          /* Try the designated backup pool. */\n          if (backup_pool) {\n               D_MAGIC_ASSERT( backup_pool, CoreSurfacePool );\n\n               D_DEBUG_AT( Core_SurfacePool, \"  -> allocating in '%s'\\n\", backup_pool->desc.name );\n\n               /* Allocate in backup pool. */\n               ret = dfb_surface_pool_allocate( backup_pool, buffer, NULL, 0, &allocation );\n               if (ret == DFB_OK) {\n                    /* Update new allocation. */\n                    ret = dfb_surface_allocation_update( allocation, CSAF_NONE );\n                    if (ret) {\n                         D_DEBUG_AT( Core_SurfacePool, \"  -> update failed!\\n\" );\n                         dfb_surface_allocation_decouple( allocation );\n                    }\n                    else\n                         return DFB_OK;\n               }\n               else\n                    D_DEBUG_AT( Core_SurfacePool, \"  -> allocation failed!\\n\" );\n          }\n     }\n     else\n          D_DEBUG_AT( Core_SurfacePool, \"  -> not up to date anyhow\\n\" );\n\n     return ret;\n}\n"
  },
  {
    "path": "src/core/surface_pool.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__SURFACE_POOL_H__\n#define __CORE__SURFACE_POOL_H__\n\n#include <core/surface.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CSPCAPS_NONE     = 0x00000000, /* none of these */\n\n     CSPCAPS_PHYSICAL = 0x00000001, /* pool provides physical address to buffer */\n     CSPCAPS_VIRTUAL  = 0x00000002, /* pool provides virtual address to buffer */\n     CSPCAPS_READ     = 0x00000004, /* pool provides Read() function (set automatically) */\n     CSPCAPS_WRITE    = 0x00000008, /* pool provides Write() function (set automatically) */\n\n     CSPCAPS_ALL      = 0x0000000F  /* all of these */\n} CoreSurfacePoolCapabilities;\n\ntypedef enum {\n     CSPP_DEFAULT  = 0x00000000,\n     CSPP_PREFERED = 0x00000001,\n     CSPP_ULTIMATE = 0x00000002\n} CoreSurfacePoolPriority;\n\n#define DFB_SURFACE_POOL_DESC_NAME_LENGTH 44\n\ntypedef struct {\n     CoreSurfacePoolCapabilities caps;\n     CoreSurfaceAccessFlags      access[CSAID_NUM];\n     CoreSurfaceTypeFlags        types;\n     CoreSurfacePoolPriority     priority;\n     char                        name[DFB_SURFACE_POOL_DESC_NAME_LENGTH];\n} CoreSurfacePoolDescription;\n\ntypedef struct {\n     int       (*PoolDataSize)      ( void );\n     int       (*PoolLocalDataSize) ( void );\n     int       (*AllocationDataSize)( void );\n\n     /*\n      * Pool init/destroy.\n      */\n\n     DFBResult (*InitPool)          ( CoreDFB                     *core,\n                                      CoreSurfacePool             *pool,\n                                      void                        *pool_data,\n                                      void                        *pool_local,\n                                      void                        *system_data,\n                                      CoreSurfacePoolDescription  *ret_desc );\n\n     DFBResult (*JoinPool)          ( CoreDFB                     *core,\n                                      CoreSurfacePool             *pool,\n                                      void                        *pool_data,\n                                      void                        *pool_local,\n                                      void                        *system_data );\n\n     DFBResult (*DestroyPool)       ( CoreSurfacePool             *pool,\n                                      void                        *pool_data,\n                                      void                        *pool_local );\n\n     DFBResult (*LeavePool)         ( CoreSurfacePool             *pool,\n                                      void                        *pool_data,\n                                      void                        *pool_local );\n\n     DFBResult (*TestConfig)        ( CoreSurfacePool             *pool,\n                                      void                        *pool_data,\n                                      void                        *pool_local,\n                                      CoreSurfaceBuffer           *buffer,\n                                      const CoreSurfaceConfig     *config );\n\n     /*\n      * Buffer management.\n      */\n\n     DFBResult (*AllocateBuffer)    ( CoreSurfacePool             *pool,\n                                      void                        *pool_data,\n                                      void                        *pool_local,\n                                      CoreSurfaceBuffer           *buffer,\n                                      CoreSurfaceAllocation       *allocation,\n                                      void                        *alloc_data );\n\n     DFBResult (*DeallocateBuffer)  ( CoreSurfacePool             *pool,\n                                      void                        *pool_data,\n                                      void                        *pool_local,\n                                      CoreSurfaceBuffer           *buffer,\n                                      CoreSurfaceAllocation       *allocation,\n                                      void                        *alloc_data );\n\n     /*\n      * Locking.\n      */\n\n     DFBResult (*Lock)              ( CoreSurfacePool             *pool,\n                                      void                        *pool_data,\n                                      void                        *pool_local,\n                                      CoreSurfaceAllocation       *allocation,\n                                      void                        *alloc_data,\n                                      CoreSurfaceBufferLock       *lock );\n\n     DFBResult (*Unlock)            ( CoreSurfacePool             *pool,\n                                      void                        *pool_data,\n                                      void                        *pool_local,\n                                      CoreSurfaceAllocation       *allocation,\n                                      void                        *alloc_data,\n                                      CoreSurfaceBufferLock       *lock );\n\n     /*\n      * Read/Write.\n      */\n\n     DFBResult (*Read)              ( CoreSurfacePool             *pool,\n                                      void                        *pool_data,\n                                      void                        *pool_local,\n                                      CoreSurfaceAllocation       *allocation,\n                                      void                        *alloc_data,\n                                      void                        *destination,\n                                      int                          pitch,\n                                      const DFBRectangle          *rect );\n\n     DFBResult (*Write)             ( CoreSurfacePool             *pool,\n                                      void                        *pool_data,\n                                      void                        *pool_local,\n                                      CoreSurfaceAllocation       *allocation,\n                                      void                        *alloc_data,\n                                      const void                  *source,\n                                      int                          pitch,\n                                      const DFBRectangle          *rect );\n\n     /*\n      * Muck out.\n      */\n     DFBResult (*MuckOut)           ( CoreSurfacePool             *pool,\n                                      void                        *pool_data,\n                                      void                        *pool_local,\n                                      CoreSurfaceBuffer           *buffer );\n\n     /*\n      * Manage interlocks.\n      */\n     DFBResult (*PreLock)           ( CoreSurfacePool             *pool,\n                                      void                        *pool_data,\n                                      void                        *pool_local,\n                                      CoreSurfaceAllocation       *allocation,\n                                      void                        *alloc_data,\n                                      CoreSurfaceAccessorID        accessor,\n                                      CoreSurfaceAccessFlags       access );\n\n     /*\n      * Handle preallocation.\n      * The surface pool checks the description and extracts/generates information for the surface configuration, to be\n      * later used in the AllocateBuffer() function.\n      */\n     DFBResult (*PreAlloc)          ( CoreSurfacePool             *pool,\n                                      void                        *pool_data,\n                                      void                        *pool_local,\n                                      const DFBSurfaceDescription *description,\n                                      CoreSurfaceConfig           *config );\n\n     /*\n      * Keys.\n      */\n\n     DFBResult (*CheckKey)          ( CoreSurfacePool             *pool,\n                                      void                        *pool_data,\n                                      void                        *pool_local,\n                                      CoreSurfaceBuffer           *buffer,\n                                      const char                  *key,\n                                      u64                          handle );\n\n     DFBResult (*AllocateKey)       ( CoreSurfacePool             *pool,\n                                      void                        *pool_data,\n                                      void                        *pool_local,\n                                      CoreSurfaceBuffer           *buffer,\n                                      const char                  *key,\n                                      u64                          handle,\n                                      CoreSurfaceAllocation       *allocation,\n                                      void                        *alloc_data );\n} SurfacePoolFuncs;\n\nstruct __DFB_CoreSurfacePool {\n     int                         magic;\n\n     FusionSkirmish              lock;\n\n     CoreSurfacePoolID           pool_id;\n\n     CoreSurfacePoolDescription  desc;\n\n     int                         pool_data_size;\n     int                         pool_local_data_size;\n     int                         alloc_data_size;\n\n     void                       *data;\n\n     FusionVector                allocs;\n\n     FusionSHMPoolShared        *shmpool;\n\n     CoreSurfacePool            *backup;\n};\n\n/**********************************************************************************************************************/\n\ntypedef DFBEnumerationResult (*CoreSurfacePoolCallback) ( CoreSurfacePool *pool, void *ctx );\n\ntypedef DFBEnumerationResult (*CoreSurfaceAllocCallback)( CoreSurfaceAllocation *allocation, void *ctx );\n\n/**********************************************************************************************************************/\n\nDFBResult dfb_surface_pool_initialize   ( CoreDFB                      *core,\n                                          const SurfacePoolFuncs       *funcs,\n                                          CoreSurfacePool             **ret_pool );\n\nDFBResult dfb_surface_pool_initialize2  ( CoreDFB                      *core,\n                                          const SurfacePoolFuncs       *funcs,\n                                          void                         *ctx,\n                                          CoreSurfacePool             **ret_pool );\n\nDFBResult dfb_surface_pool_join         ( CoreDFB                      *core,\n                                          CoreSurfacePool              *pool,\n                                          const SurfacePoolFuncs       *funcs );\n\nDFBResult dfb_surface_pool_join2        ( CoreDFB                      *core,\n                                          CoreSurfacePool              *pool,\n                                          const SurfacePoolFuncs       *funcs,\n                                          void                         *ctx );\n\nDFBResult dfb_surface_pool_destroy      ( CoreSurfacePool              *pool );\n\nDFBResult dfb_surface_pool_leave        ( CoreSurfacePool              *pool );\n\nDFBResult dfb_surface_pools_prealloc    ( const DFBSurfaceDescription  *description,\n                                          CoreSurfaceConfig            *config );\n\nDFBResult dfb_surface_pools_negotiate   ( CoreSurfaceBuffer            *buffer,\n                                          CoreSurfaceAccessorID         accessor,\n                                          CoreSurfaceAccessFlags        access,\n                                          CoreSurfacePool             **ret_pools,\n                                          unsigned int                  max_pools,\n                                          unsigned int                 *ret_num );\n\nDFBResult dfb_surface_pools_enumerate   ( CoreSurfacePoolCallback       callback,\n                                          void                         *ctx );\n\nDFBResult dfb_surface_pools_lookup      ( CoreSurfacePoolID             pool_id,\n                                          CoreSurfacePool             **ret_pool );\n\nDFBResult dfb_surface_pools_allocate    ( CoreSurfaceBuffer            *buffer,\n                                          CoreSurfaceAccessorID         accessor,\n                                          CoreSurfaceAccessFlags        access,\n                                          CoreSurfaceAllocation       **ret_allocation );\n\nDFBResult dfb_surface_pools_allocate_key( CoreSurfaceBuffer            *buffer,\n                                          const char                   *key,\n                                          u64                           handle,\n                                          CoreSurfaceAllocation       **ret_allocation );\n\nDFBResult dfb_surface_pool_check_key    ( CoreSurfacePool              *pool,\n                                          CoreSurfaceBuffer            *buffer,\n                                          const char                   *key,\n                                          u64                           handle );\n\nDFBResult dfb_surface_pool_allocate     ( CoreSurfacePool              *pool,\n                                          CoreSurfaceBuffer            *buffer,\n                                          const char                   *key,\n                                          u64                           handle,\n                                          CoreSurfaceAllocation       **ret_allocation );\n\nDFBResult dfb_surface_pool_deallocate   ( CoreSurfacePool              *pool,\n                                          CoreSurfaceAllocation        *allocation );\n\nDFBResult dfb_surface_pool_displace     ( CoreSurfacePool              *pool,\n                                          CoreSurfaceBuffer            *buffer,\n                                          CoreSurfaceAllocation       **ret_allocation );\n\nDFBResult dfb_surface_pool_prelock      ( CoreSurfacePool              *pool,\n                                          CoreSurfaceAllocation        *allocation,\n                                          CoreSurfaceAccessorID         accessor,\n                                          CoreSurfaceAccessFlags        access );\n\nDFBResult dfb_surface_pool_lock         ( CoreSurfacePool              *pool,\n                                          CoreSurfaceAllocation        *allocation,\n                                          CoreSurfaceBufferLock        *lock );\n\nDFBResult dfb_surface_pool_unlock       ( CoreSurfacePool              *pool,\n                                          CoreSurfaceAllocation        *allocation,\n                                          CoreSurfaceBufferLock        *lock );\n\nDFBResult dfb_surface_pool_read         ( CoreSurfacePool              *pool,\n                                          CoreSurfaceAllocation        *allocation,\n                                          void                         *data,\n                                          int                           pitch,\n                                          const DFBRectangle           *rect );\n\nDFBResult dfb_surface_pool_write        ( CoreSurfacePool              *pool,\n                                          CoreSurfaceAllocation        *allocation,\n                                          const void                   *data,\n                                          int                           pitch,\n                                          const DFBRectangle           *rect );\n\nDFBResult dfb_surface_pool_enumerate    ( CoreSurfacePool              *pool,\n                                          CoreSurfaceAllocCallback      callback,\n                                          void                         *ctx );\n\n#endif\n"
  },
  {
    "path": "src/core/surface_pool_bridge.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core.h>\n#include <core/surface_allocation.h>\n#include <core/surface_buffer.h>\n#include <core/surface_pool_bridge.h>\n#include <direct/memcpy.h>\n#include <directfb_util.h>\n#include <fusion/conf.h>\n#include <fusion/shmalloc.h>\n\nD_DEBUG_DOMAIN( Core_SurfPoolBridge, \"Core/SurfPoolBridge\", \"DirectFB Core Surface Pool Bridge\" );\n\n/**********************************************************************************************************************/\n\nstatic int                           bridge_count;\nstatic const SurfacePoolBridgeFuncs *bridge_funcs[MAX_SURFACE_POOL_BRIDGES];\nstatic void                         *bridge_locals[MAX_SURFACE_POOL_BRIDGES];\nstatic CoreSurfacePoolBridge        *bridge_array[MAX_SURFACE_POOL_BRIDGES];\nstatic unsigned int                  bridge_order[MAX_SURFACE_POOLS];\n\nstatic __inline__ const SurfacePoolBridgeFuncs *\nget_funcs( const CoreSurfacePoolBridge *bridge )\n{\n     D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge );\n     D_ASSERT( bridge->bridge_id >= 0 );\n     D_ASSERT( bridge->bridge_id < MAX_SURFACE_POOL_BRIDGES );\n     D_ASSERT( bridge_funcs[bridge->bridge_id] != NULL );\n\n     /* Return function table of the bridge. */\n     return bridge_funcs[bridge->bridge_id];\n}\n\nstatic __inline__ void *\nget_local( const CoreSurfacePoolBridge *bridge )\n{\n     D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge );\n     D_ASSERT( bridge->bridge_id >= 0 );\n     D_ASSERT( bridge->bridge_id < MAX_SURFACE_POOL_BRIDGES );\n\n     /* Return local data of the bridge. */\n     return bridge_locals[bridge->bridge_id];\n}\n\nstatic DFBResult init_bridge        ( CoreDFB                      *core,\n                                      CoreSurfacePoolBridge        *bridge,\n                                      const SurfacePoolBridgeFuncs *funcs,\n                                      void                         *ctx );\nstatic void      insert_bridge_local( CoreSurfacePoolBridge        *bridge );\nstatic void      remove_bridge_local( CoreSurfacePoolBridgeID       bridge_id );\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_surface_pool_bridge_initialize( CoreDFB                       *core,\n                                    const SurfacePoolBridgeFuncs  *funcs,\n                                    void                          *ctx,\n                                    CoreSurfacePoolBridge        **ret_bridge )\n{\n     DFBResult              ret;\n     CoreSurfacePoolBridge *bridge;\n     FusionSHMPoolShared   *shmpool;\n\n     D_ASSERT( core != NULL );\n     D_ASSERT( bridge_funcs[bridge_count] == NULL );\n     D_ASSERT( funcs != NULL );\n     D_ASSERT( ret_bridge != NULL );\n\n     D_DEBUG_AT( Core_SurfPoolBridge, \"%s( %p, %p )\\n\", __FUNCTION__, funcs, ctx );\n\n     /* Check against bridge limit. */\n     if (bridge_count == MAX_SURFACE_POOL_BRIDGES) {\n          D_ERROR( \"Core/SurfacePoolBridge: Maximum number of bridges (%d) reached!\\n\", MAX_SURFACE_POOL_BRIDGES );\n          return DFB_LIMITEXCEEDED;\n     }\n\n     shmpool = dfb_core_shmpool( core );\n\n     /* Allocate bridge structure. */\n     bridge = SHCALLOC( shmpool, 1, sizeof(CoreSurfacePoolBridge) );\n     if (!bridge)\n          return D_OOSHM();\n\n     /* Assign a bridge ID. */\n     bridge->bridge_id = bridge_count++;\n\n     /* Remember shared memory pool. */\n     bridge->shmpool = shmpool;\n\n     /* Set function table of the bridge. */\n     bridge_funcs[bridge->bridge_id] = funcs;\n\n     /* Add to global bridge list. */\n     bridge_array[bridge->bridge_id] = bridge;\n\n     D_MAGIC_SET( bridge, CoreSurfacePoolBridge );\n\n     ret = init_bridge( core, bridge, funcs, ctx );\n     if (ret) {\n          bridge_funcs[bridge->bridge_id] = NULL;\n          bridge_array[bridge->bridge_id] = NULL;\n          bridge_count--;\n          D_MAGIC_CLEAR( bridge );\n          SHFREE( shmpool, bridge );\n          return ret;\n     }\n\n     /* Insert new bridge into priority order. */\n     insert_bridge_local( bridge );\n\n     /* Return the new bridge. */\n     *ret_bridge = bridge;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_pool_bridge_join( CoreDFB                      *core,\n                              CoreSurfacePoolBridge        *bridge,\n                              const SurfacePoolBridgeFuncs *funcs,\n                              void                         *ctx )\n{\n     DFBResult ret;\n\n     D_ASSERT( core != NULL );\n     D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge );\n     D_ASSERT( bridge->bridge_id < MAX_SURFACE_POOL_BRIDGES );\n     D_ASSERT( bridge->bridge_id == bridge_count );\n     D_ASSERT( bridge_funcs[bridge->bridge_id] == NULL );\n     D_ASSERT( funcs != NULL );\n\n     D_DEBUG_AT( Core_SurfPoolBridge, \"%s( %p [%u - %s], %p, %p )\\n\", __FUNCTION__,\n                 bridge, bridge->bridge_id, bridge->desc.name, funcs, ctx );\n\n     /* Enforce same order as initialization to be used during join. */\n     if (bridge->bridge_id != bridge_count) {\n          D_ERROR( \"Core/SurfacePoolBridge: Wrong order of joining bridges, got %u, should be %d!\\n\",\n                   bridge->bridge_id, bridge_count );\n          return DFB_BUG;\n     }\n\n     /* Allocate local bridge data. */\n     if (bridge->bridge_local_data_size &&\n         !(bridge_locals[bridge->bridge_id] = D_CALLOC( 1, bridge->bridge_local_data_size )))\n         return D_OOM();\n\n     /* Set function table of the bridge. */\n     bridge_funcs[bridge->bridge_id] = funcs;\n\n     /* Add to global bridge list. */\n     bridge_array[bridge->bridge_id] = bridge;\n\n     /* Adjust bridge count. */\n     if (bridge_count < bridge->bridge_id + 1)\n          bridge_count = bridge->bridge_id + 1;\n\n     funcs = get_funcs( bridge );\n\n     if (funcs->JoinPoolBridge) {\n          ret = funcs->JoinPoolBridge( core, bridge, bridge->data, get_local(bridge), ctx );\n          if (ret) {\n               D_DERROR( ret, \"Core/SurfacePoolBridge: Joining '%s' failed!\\n\", bridge->desc.name );\n\n               if (bridge_locals[bridge->bridge_id]) {\n                    D_FREE( bridge_locals[bridge->bridge_id] );\n                    bridge_locals[bridge->bridge_id] = NULL;\n               }\n\n               bridge_array[bridge->bridge_id] = NULL;\n               bridge_funcs[bridge->bridge_id] = NULL;\n\n               bridge_count--;\n\n               return ret;\n          }\n     }\n\n     /* Insert new bridge into priority order. */\n     insert_bridge_local( bridge );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_pool_bridge_destroy( CoreSurfacePoolBridge *bridge )\n{\n     const SurfacePoolBridgeFuncs *funcs;\n\n     D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge );\n     D_ASSERT( bridge->bridge_id >= 0 );\n     D_ASSERT( bridge->bridge_id < MAX_SURFACE_POOL_BRIDGES );\n     D_ASSERT( bridge_array[bridge->bridge_id] == bridge );\n\n     D_DEBUG_AT( Core_SurfPoolBridge, \"%s( %p [%u - %s] )\\n\", __FUNCTION__,\n                 bridge, bridge->bridge_id, bridge->desc.name );\n\n     funcs = get_funcs( bridge );\n\n     if (funcs->DestroyPoolBridge)\n          funcs->DestroyPoolBridge( bridge, bridge->data, get_local(bridge) );\n\n     /* Free shared bridge data. */\n     if (bridge->data)\n          SHFREE( bridge->shmpool, bridge->data );\n\n     /* Free local pool data and remove from lists. */\n     remove_bridge_local( bridge->bridge_id );\n\n     fusion_skirmish_destroy( &bridge->lock );\n\n     D_MAGIC_CLEAR( bridge );\n\n     SHFREE( bridge->shmpool, bridge );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_pool_bridge_leave( CoreSurfacePoolBridge *bridge )\n{\n     const SurfacePoolBridgeFuncs *funcs;\n\n     D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge );\n     D_ASSERT( bridge->bridge_id >= 0 );\n     D_ASSERT( bridge->bridge_id < MAX_SURFACE_POOL_BRIDGES );\n     D_ASSERT( bridge_array[bridge->bridge_id] == bridge );\n\n     D_DEBUG_AT( Core_SurfPoolBridge, \"%s( %p [%u - %s] )\\n\", __FUNCTION__,\n                 bridge, bridge->bridge_id, bridge->desc.name );\n\n     funcs = get_funcs( bridge );\n\n     if (funcs->LeavePoolBridge)\n          funcs->LeavePoolBridge( bridge, bridge->data, get_local(bridge) );\n\n     /* Free local pool data and remove from lists. */\n     remove_bridge_local( bridge->bridge_id );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_surface_pool_bridges_enumerate( CoreSurfacePoolBridgeCallback  callback,\n                                    void                          *ctx )\n{\n     int i;\n\n     D_ASSERT( callback != NULL );\n\n     D_DEBUG_AT( Core_SurfPoolBridge, \"%s( %p, %p )\\n\", __FUNCTION__, callback, ctx );\n\n     for (i = 0; i < bridge_count; i++) {\n          CoreSurfacePoolBridge *bridge = bridge_array[i];\n\n          D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge );\n\n          if (callback( bridge, ctx ) == DFENUM_CANCEL)\n               break;\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nallocate_transfer( CoreSurfacePoolBridge    *bridge,\n                   CoreSurfaceBuffer        *buffer,\n                   CoreSurfaceAllocation    *from,\n                   CoreSurfaceAllocation    *to,\n                   const DFBRectangle       *rects,\n                   unsigned int              num_rects,\n                   CoreSurfacePoolTransfer **ret_transfer )\n{\n     CoreSurfacePoolTransfer *transfer;\n     unsigned int             alloc_size;\n\n     D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge );\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n\n     CORE_SURFACE_ALLOCATION_ASSERT( from );\n     CORE_SURFACE_ALLOCATION_ASSERT( to );\n\n     D_ASSERT( rects != NULL );\n     D_ASSERT( num_rects > 0 );\n     D_ASSERT( ret_transfer != NULL );\n\n     alloc_size = sizeof(CoreSurfacePoolTransfer) + num_rects * sizeof(DFBRectangle) + bridge->transfer_data_size;\n\n     transfer = SHCALLOC( bridge->shmpool, 1, alloc_size );\n     if (!transfer)\n          return D_OOSHM();\n\n     transfer->bridge = bridge;\n     transfer->buffer = buffer;\n     transfer->from   = from;\n     transfer->to     = to;\n     transfer->rects  = (DFBRectangle*) (transfer + 1);\n\n     if (bridge->transfer_data_size)\n          transfer->data = transfer->rects + num_rects;\n\n     transfer->num_rects = num_rects;\n\n     direct_memcpy( transfer->rects, rects, num_rects * sizeof(DFBRectangle) );\n\n     D_MAGIC_SET( transfer, CoreSurfacePoolTransfer );\n\n     *ret_transfer = transfer;\n\n     return DFB_OK;\n}\n\nstatic void\ndeallocate_transfer( CoreSurfacePoolTransfer *transfer )\n{\n     CoreSurfacePoolBridge *bridge;\n\n     D_MAGIC_ASSERT( transfer, CoreSurfacePoolTransfer );\n     D_MAGIC_ASSERT( transfer->bridge, CoreSurfacePoolBridge );\n\n     bridge = transfer->bridge;\n\n     D_MAGIC_CLEAR( transfer );\n\n     SHFREE( bridge->shmpool, transfer );\n}\n\nDFBResult\ndfb_surface_pool_bridges_transfer( CoreSurfaceBuffer     *buffer,\n                                   CoreSurfaceAllocation *from,\n                                   CoreSurfaceAllocation *to,\n                                   const DFBRectangle    *rects,\n                                   unsigned int           num_rects )\n{\n     DFBResult                     ret;\n     int                           i;\n     DFBRectangle                  rect;\n     CoreSurfacePoolBridge        *bridge = NULL;\n     const SurfacePoolBridgeFuncs *funcs;\n     CoreSurfacePoolTransfer      *transfer = NULL;\n\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n\n     CORE_SURFACE_ALLOCATION_ASSERT( from );\n     CORE_SURFACE_ALLOCATION_ASSERT( to );\n\n     D_ASSERT( rects != NULL || num_rects == 0 );\n     D_ASSERT( num_rects > 0 || rects == NULL );\n\n     D_DEBUG_AT( Core_SurfPoolBridge, \"%s( %p, %dx%d %s, %p -> %p, %u rects )\\n\", __FUNCTION__,\n                 buffer, buffer->config.size.w, buffer->config.size.h,\n                 dfb_pixelformat_name( buffer->surface->config.format ), from, to, num_rects );\n\n     if (!rects) {\n          rect.x = rect.y = 0;\n          rect.w = buffer->config.size.w;\n          rect.h = buffer->config.size.h;\n\n          rects = &rect;\n          num_rects = 1;\n     }\n\n     for (i = 0; i < bridge_count; i++) {\n          D_ASSERT( bridge_order[i] >= 0 );\n          D_ASSERT( bridge_order[i] < bridge_count );\n\n          bridge = bridge_array[bridge_order[i]];\n\n          D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge );\n\n          funcs = get_funcs( bridge );\n\n          D_ASSERT( funcs->CheckTransfer != NULL );\n\n          ret = funcs->CheckTransfer( bridge, bridge->data, get_local(bridge), buffer, from, to );\n          if (ret)\n               bridge = NULL;\n          else\n               break;\n     }\n\n     if (!bridge)\n          return DFB_UNSUPPORTED;\n\n     D_DEBUG_AT( Core_SurfPoolBridge, \"  -> using '%s'\\n\", bridge->desc.name );\n\n     ret = allocate_transfer( bridge, buffer, from, to, rects, num_rects, &transfer );\n     if (ret)\n          return ret;\n\n     D_ASSERT( funcs->StartTransfer != NULL );\n\n     D_DEBUG_AT( Core_SurfPoolBridge, \"  -> start...\\n\" );\n\n     #if defined(__GNUC__) && __GNUC__ >= 10\n     #pragma GCC diagnostic push\n     #pragma GCC diagnostic ignored \"-Wanalyzer-null-dereference\"\n     #endif\n     ret = funcs->StartTransfer( bridge, bridge->data, get_local(bridge), transfer, transfer->data );\n     #if defined __GNUC__ && __GNUC__ >= 10\n     #pragma GCC diagnostic pop\n     #endif\n\n     if (ret) {\n          D_DERROR( ret, \"Core/SurfacePoolBridge: Starting transfer via '%s' failed!\\n\", bridge->desc.name );\n     }\n     else if (funcs->FinishTransfer) {\n          D_DEBUG_AT( Core_SurfPoolBridge, \"  -> finish...\\n\" );\n\n          ret = funcs->FinishTransfer( bridge, bridge->data, get_local(bridge), transfer, transfer->data );\n          if (ret)\n               D_DERROR( ret, \"Core/SurfacePoolBridge: Finishing transfer via '%s' failed!\\n\", bridge->desc.name );\n     }\n\n     deallocate_transfer( transfer );\n\n     return ret;\n}\n\n/**********************************************************************************************************************/\n\nstatic DFBResult\ninit_bridge( CoreDFB                      *core,\n             CoreSurfacePoolBridge        *bridge,\n             const SurfacePoolBridgeFuncs *funcs,\n             void                         *ctx )\n{\n     DFBResult ret;\n\n     D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge );\n     D_ASSERT( funcs != NULL );\n     D_ASSERT( funcs->InitPoolBridge != NULL );\n\n     D_DEBUG_AT( Core_SurfPoolBridge, \"%s( %p, %p )\\n\", __FUNCTION__, bridge, funcs );\n\n     if (funcs->PoolBridgeDataSize)\n          bridge->bridge_data_size = funcs->PoolBridgeDataSize();\n\n     if (funcs->PoolBridgeLocalDataSize)\n          bridge->bridge_local_data_size = funcs->PoolBridgeLocalDataSize();\n\n     if (funcs->PoolTransferDataSize)\n          bridge->transfer_data_size = funcs->PoolTransferDataSize();\n\n     /* Allocate shared bridge data. */\n     if (bridge->bridge_data_size) {\n          bridge->data = SHCALLOC( bridge->shmpool, 1, bridge->bridge_data_size );\n          if (!bridge->data)\n               return D_OOSHM();\n     }\n\n     /* Allocate local bridge data. */\n     if (bridge->bridge_local_data_size &&\n         !(bridge_locals[bridge->bridge_id] = D_CALLOC( 1, bridge->bridge_local_data_size ))) {\n          SHFREE( bridge->shmpool, bridge->data );\n          return D_OOM();\n     }\n\n     ret = funcs->InitPoolBridge( core, bridge, bridge->data, get_local(bridge), ctx, &bridge->desc );\n     if (ret) {\n          D_DERROR( ret, \"Core/SurfacePoolBridge: Initializing '%s' failed!\\n\", bridge->desc.name );\n\n          if (bridge_locals[bridge->bridge_id]) {\n               D_FREE( bridge_locals[bridge->bridge_id] );\n               bridge_locals[bridge->bridge_id] = NULL;\n          }\n\n          if (bridge->data) {\n               SHFREE( bridge->shmpool, bridge->data );\n               bridge->data = NULL;\n          }\n\n          return ret;\n     }\n\n     fusion_skirmish_init2( &bridge->lock, bridge->desc.name, dfb_core_world( core ), fusion_config->secure_fusion );\n\n     return DFB_OK;\n}\n\nstatic void\ninsert_bridge_local( CoreSurfacePoolBridge *bridge )\n{\n     int i, n;\n\n     for (i = 0; i < bridge_count - 1; i++) {\n          D_ASSERT( bridge_order[i] >= 0 );\n          D_ASSERT( bridge_order[i] < bridge_count - 1 );\n\n          D_MAGIC_ASSERT( bridge_array[bridge_order[i]], CoreSurfacePoolBridge );\n\n          if (bridge_array[bridge_order[i]]->desc.priority < bridge->desc.priority)\n               break;\n     }\n\n     for (n = bridge_count - 1; n > i; n--) {\n          D_ASSERT( bridge_order[n-1] >= 0 );\n          D_ASSERT( bridge_order[n-1] < bridge_count - 1 );\n\n          D_MAGIC_ASSERT( bridge_array[bridge_order[n-1]], CoreSurfacePoolBridge );\n\n          bridge_order[n] = bridge_order[n-1];\n     }\n\n     bridge_order[n] = bridge_count - 1;\n\n     for (i = 0; i < bridge_count; i++) {\n          D_DEBUG_AT( Core_SurfPoolBridge, \"  %c> [%d] %p [%u - %s] (%u), %p\\n\",\n                      (i == n) ? '=' : '-', i, bridge_array[bridge_order[i]],\n                      bridge_array[bridge_order[i]]->bridge_id, bridge_array[bridge_order[i]]->desc.name,\n                      bridge_array[bridge_order[i]]->desc.priority, bridge_funcs[bridge_order[i]] );\n\n          D_ASSERT( bridge_order[i] == bridge_array[bridge_order[i]]->bridge_id );\n     }\n}\n\nstatic void\nremove_bridge_local( CoreSurfacePoolBridgeID bridge_id )\n{\n     int i;\n\n     /* Free local bridge data. */\n     if (bridge_locals[bridge_id]) {\n          D_FREE( bridge_locals[bridge_id] );\n          bridge_locals[bridge_id] = NULL;\n     }\n\n     /* Erase entries of the bridge. */\n     bridge_array[bridge_id] = NULL;\n     bridge_funcs[bridge_id] = NULL;\n\n     while (bridge_count > 0 && !bridge_array[bridge_count-1]) {\n          bridge_count--;\n\n          for (i = 0; i < bridge_count; i++) {\n               if (bridge_order[i] == bridge_count) {\n                    direct_memmove( &bridge_order[i], &bridge_order[i+1],\n                                    sizeof(bridge_order[0]) * (bridge_count - i) );\n                    break;\n               }\n          }\n     }\n}\n"
  },
  {
    "path": "src/core/surface_pool_bridge.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__SURFACE_POOL_BRIDGE_H__\n#define __CORE__SURFACE_POOL_BRIDGE_H__\n\n#include <core/surface_pool.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CSPBCAPS_NONE = 0x00000000, /* none of these */\n\n     CSPBCAPS_ALL  = 0x00000000  /* all of these */\n} CoreSurfacePoolBridgeCapabilities;\n\n#define DFB_SURFACE_POOL_BRIDGE_DESC_NAME_LENGTH  44\n\ntypedef struct {\n     CoreSurfacePoolBridgeCapabilities caps;\n     char                              name[DFB_SURFACE_POOL_BRIDGE_DESC_NAME_LENGTH];\n     CoreSurfacePoolPriority           priority;\n} CoreSurfacePoolBridgeDescription;\n\ntypedef struct {\n     DirectLink             link;\n\n     int                    magic;\n\n     CoreSurfacePoolBridge *bridge;\n\n     CoreSurfaceBuffer     *buffer;\n     CoreSurfaceAllocation *from;\n     CoreSurfaceAllocation *to;\n\n     DFBRectangle          *rects;\n     unsigned int           num_rects;\n\n     void                  *data;\n} CoreSurfacePoolTransfer;\n\ntypedef struct {\n     int       (*PoolBridgeDataSize)     ( void );\n     int       (*PoolBridgeLocalDataSize)( void );\n     int       (*PoolTransferDataSize)   ( void );\n\n     /*\n      * Bridge init/destroy.\n      */\n\n     DFBResult (*InitPoolBridge)         ( CoreDFB                          *core,\n                                           CoreSurfacePoolBridge            *bridge,\n                                           void                             *bridge_data,\n                                           void                             *bridge_local,\n                                           void                             *ctx,\n                                           CoreSurfacePoolBridgeDescription *ret_desc );\n\n     DFBResult (*JoinPoolBridge)         ( CoreDFB                          *core,\n                                           CoreSurfacePoolBridge            *bridge,\n                                           void                             *bridge_data,\n                                           void                             *bridge_local,\n                                           void                             *ctx );\n\n     DFBResult (*DestroyPoolBridge)      ( CoreSurfacePoolBridge            *bridge,\n                                           void                             *bridge_data,\n                                           void                             *bridge_local );\n\n     DFBResult (*LeavePoolBridge)        ( CoreSurfacePoolBridge            *bridge,\n                                           void                             *bridge_data,\n                                           void                             *bridge_local );\n\n\n     /*\n      * Probe.\n      */\n     DFBResult (*CheckTransfer)          ( CoreSurfacePoolBridge            *bridge,\n                                           void                             *bridge_data,\n                                           void                             *bridge_local,\n                                           CoreSurfaceBuffer                *buffer,\n                                           CoreSurfaceAllocation            *from,\n                                           CoreSurfaceAllocation            *to );\n\n     /*\n      * Transfer.\n      */\n\n     DFBResult (*StartTransfer)          ( CoreSurfacePoolBridge            *bridge,\n                                           void                             *bridge_data,\n                                           void                             *bridge_local,\n                                           CoreSurfacePoolTransfer          *transfer,\n                                           void                             *transfer_data );\n\n     DFBResult (*FinishTransfer)         ( CoreSurfacePoolBridge            *bridge,\n                                           void                             *bridge_data,\n                                           void                             *bridge_local,\n                                           CoreSurfacePoolTransfer          *transfer,\n                                           void                             *transfer_data );\n} SurfacePoolBridgeFuncs;\n\nstruct __DFB_CoreSurfacePoolBridge {\n     int                               magic;\n\n     FusionSkirmish                    lock;\n\n     CoreSurfacePoolBridgeID           bridge_id;\n\n     CoreSurfacePoolBridgeDescription  desc;\n\n     int                               bridge_data_size;\n     int                               bridge_local_data_size;\n     int                               transfer_data_size;\n\n     void                             *data;\n\n     FusionSHMPoolShared              *shmpool;\n\n     DirectLink                       *transfers;\n};\n\n/**********************************************************************************************************************/\n\ntypedef DFBEnumerationResult (*CoreSurfacePoolBridgeCallback)( CoreSurfacePoolBridge *bridge, void *ctx );\n\n/**********************************************************************************************************************/\n\nDFBResult dfb_surface_pool_bridge_initialize( CoreDFB                        *core,\n                                              const SurfacePoolBridgeFuncs   *funcs,\n                                              void                           *ctx,\n                                              CoreSurfacePoolBridge         **ret_bridge );\n\nDFBResult dfb_surface_pool_bridge_join      ( CoreDFB                        *core,\n                                              CoreSurfacePoolBridge          *pool,\n                                              const SurfacePoolBridgeFuncs   *funcs,\n                                              void                           *ctx );\n\nDFBResult dfb_surface_pool_bridge_destroy   ( CoreSurfacePoolBridge          *bridge );\n\nDFBResult dfb_surface_pool_bridge_leave     ( CoreSurfacePoolBridge          *bridge );\n\nDFBResult dfb_surface_pool_bridges_enumerate( CoreSurfacePoolBridgeCallback   callback,\n                                              void                           *ctx );\n\nDFBResult dfb_surface_pool_bridges_transfer ( CoreSurfaceBuffer              *buffer,\n                                              CoreSurfaceAllocation          *from,\n                                              CoreSurfaceAllocation          *to,\n                                              const DFBRectangle             *rects,\n                                              unsigned int                    num_rects );\n\n#endif\n"
  },
  {
    "path": "src/core/system.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core_parts.h>\n#include <core/system.h>\n#include <direct/util.h>\n#include <misc/conf.h>\n\nD_DEBUG_DOMAIN( Core_System, \"Core/System\", \"DirectFB Core System\" );\n\nDEFINE_MODULE_DIRECTORY( dfb_core_systems, \"systems\", DFB_CORE_SYSTEM_ABI_VERSION );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int            magic;\n\n     CoreSystemInfo system_info;\n} DFBSystemCoreShared;\n\ntypedef struct {\n     int                  magic;\n\n     CoreDFB             *core;\n\n     DFBSystemCoreShared *shared;\n} DFBSystemCore;\n\nDFB_CORE_PART( system_core, SystemCore );\n\n/**********************************************************************************************************************/\n\nstatic CoreSystemInfo         system_info;\nstatic DirectModuleEntry     *system_module = NULL;\nstatic const CoreSystemFuncs *system_funcs  = NULL;\nstatic void                  *system_data   = NULL;\n\nstatic DFBResult\ndfb_system_core_initialize( CoreDFB             *core,\n                            DFBSystemCore       *data,\n                            DFBSystemCoreShared *shared )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_System, \"%s( %p, %p, %p )\\n\", __FUNCTION__, core, data, shared );\n\n     D_ASSERT( data != NULL );\n     D_ASSERT( shared != NULL );\n\n     data->core   = core;\n     data->shared = shared;\n\n     shared->system_info = system_info;\n\n     /* Initialize system module. */\n     ret = system_funcs->Initialize( core, &system_data );\n     if (ret)\n          return ret;\n\n     D_MAGIC_SET( data, DFBSystemCore );\n     D_MAGIC_SET( shared, DFBSystemCoreShared );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_system_core_join( CoreDFB             *core,\n                      DFBSystemCore       *data,\n                      DFBSystemCoreShared *shared )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_System, \"%s( %p, %p, %p )\\n\", __FUNCTION__, core, data, shared );\n\n     D_ASSERT( data != NULL );\n     D_MAGIC_ASSERT( shared, DFBSystemCoreShared );\n\n     data->core   = core;\n     data->shared = shared;\n\n     if (strcmp( shared->system_info.name, system_info.name )) {\n          D_ERROR( \"Core/System: Running system '%s' doesn't match system '%s'!\\n\",\n                    shared->system_info.name, system_info.name );\n\n          return DFB_UNSUPPORTED;\n     }\n\n     if (shared->system_info.version.major != system_info.version.major ||\n         shared->system_info.version.minor != system_info.version.minor) {\n          D_ERROR( \"Core/System: Running system version '%d.%d' doesn't match version '%d.%d'!\\n\",\n                    shared->system_info.version.major, shared->system_info.version.minor,\n                    system_info.version.major, system_info.version.minor );\n\n          return DFB_UNSUPPORTED;\n     }\n\n     /* Join system module. */\n     ret = system_funcs->Join( core, &system_data );\n     if (ret)\n          return ret;\n\n     D_MAGIC_SET( data, DFBSystemCore );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_system_core_shutdown( DFBSystemCore *data,\n                          bool           emergency )\n{\n     DFBResult            ret;\n     DFBSystemCoreShared *shared;\n\n     D_UNUSED_P( shared );\n\n     D_DEBUG_AT( Core_System, \"%s( %p, %semergency )\\n\", __FUNCTION__, data, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( data, DFBSystemCore );\n     D_MAGIC_ASSERT( data->shared, DFBSystemCoreShared );\n\n     shared = data->shared;\n\n     /* Shutdown system module. */\n     ret = system_funcs->Shutdown( emergency );\n\n     /* Unload the module. */\n     direct_module_unref( system_module );\n\n     D_MAGIC_CLEAR( data );\n     D_MAGIC_CLEAR( shared );\n\n     system_data   = NULL;\n     system_funcs  = NULL;\n     system_module = NULL;\n\n     return ret;\n}\n\nstatic DFBResult\ndfb_system_core_leave( DFBSystemCore *data,\n                       bool           emergency )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_System, \"%s( %p, %semergency )\\n\", __FUNCTION__, data, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( data, DFBSystemCore );\n     D_MAGIC_ASSERT( data->shared, DFBSystemCoreShared );\n\n     ret = system_funcs->Leave( emergency );\n\n     /* Unload the module. */\n     direct_module_unref( system_module );\n\n     D_MAGIC_CLEAR( data );\n\n     system_data   = NULL;\n     system_funcs  = NULL;\n     system_module = NULL;\n\n     return ret;\n}\n\nstatic DFBResult\ndfb_system_core_suspend( DFBSystemCore *data )\n{\n     D_DEBUG_AT( Core_System, \"%s( %p )\\n\", __FUNCTION__, data );\n\n     D_MAGIC_ASSERT( data, DFBSystemCore );\n     D_MAGIC_ASSERT( data->shared, DFBSystemCoreShared );\n\n     system_funcs->Suspend();\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_system_core_resume( DFBSystemCore *data )\n{\n     D_DEBUG_AT( Core_System, \"%s( %p )\\n\", __FUNCTION__, data );\n\n     D_MAGIC_ASSERT( data, DFBSystemCore );\n     D_MAGIC_ASSERT( data->shared, DFBSystemCoreShared );\n\n     system_funcs->Resume();\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_system_lookup()\n{\n     DirectModuleEntry *module;\n\n     D_DEBUG_AT( Core_System, \"%p()\\n\", __FUNCTION__ );\n\n     direct_modules_explore_directory( &dfb_core_systems );\n\n     direct_list_foreach (module, dfb_core_systems.entries) {\n          const CoreSystemFuncs *funcs;\n\n          D_DEBUG_AT( Core_System, \"module %p\\n\", module );\n          D_DEBUG_AT( Core_System, \"  name     '%s'\\n\", module->name );\n          D_DEBUG_AT( Core_System, \"  refs      %d\\n\",  module->refs );\n          D_DEBUG_AT( Core_System, \"  loaded    %d\\n\",  module->loaded );\n          D_DEBUG_AT( Core_System, \"  disabled  %d\\n\",  module->disabled );\n          D_DEBUG_AT( Core_System, \"  dynamic   %d\\n\",  module->dynamic );\n          D_DEBUG_AT( Core_System, \"  file     '%s'\\n\", module->file );\n\n          funcs = direct_module_ref( module );\n          if (!funcs)\n               continue;\n\n          if (!system_module || (!dfb_config->system || !strcasecmp( dfb_config->system, module->name ))) {\n               if (system_module)\n                    direct_module_unref( system_module );\n\n               system_module = module;\n               system_funcs  = funcs;\n\n               memset( &system_info, 0, sizeof(system_info) );\n\n               funcs->GetSystemInfo( &system_info );\n          }\n          else\n               direct_module_unref( module );\n     }\n\n     if (!system_module) {\n          D_ERROR( \"Core/System: No system found!\\n\" );\n          return DFB_NOIMPL;\n     }\n\n     return DFB_OK;\n}\n\nCoreSystemCapabilities\ndfb_system_caps()\n{\n     return system_info.caps;\n}\n\nvoid *\ndfb_system_data()\n{\n     return system_data;\n}\n\nVideoMode *\ndfb_system_modes()\n{\n     D_ASSERT( system_funcs != NULL );\n\n     return system_funcs->GetModes();\n}\n\nVideoMode *\ndfb_system_current_mode()\n{\n     D_ASSERT( system_funcs != NULL );\n\n     return system_funcs->GetCurrentMode();\n}\n\nDFBResult\ndfb_system_thread_init()\n{\n     D_ASSERT( system_funcs != NULL );\n\n     return system_funcs->ThreadInit();\n}\n\nbool\ndfb_system_input_filter( CoreInputDevice *device,\n                         DFBInputEvent   *event )\n{\n     D_ASSERT( system_funcs != NULL );\n\n     return system_funcs->InputFilter( device, event );\n}\n\nvolatile void *\ndfb_system_map_mmio( unsigned int offset,\n                     int          length )\n{\n     D_ASSERT( system_funcs != NULL );\n\n     return system_funcs->MapMMIO( offset, length );\n}\n\nvoid\ndfb_system_unmap_mmio( volatile void *addr,\n                       int            length )\n{\n     D_ASSERT( system_funcs != NULL );\n\n     system_funcs->UnmapMMIO( addr, length );\n}\n\nunsigned int\ndfb_system_get_accelerator()\n{\n     D_ASSERT( system_funcs != NULL );\n\n     return system_funcs->GetAccelerator();\n}\n\nunsigned long\ndfb_system_video_memory_physical( unsigned int offset )\n{\n     D_ASSERT( system_funcs != NULL );\n\n     return system_funcs->VideoMemoryPhysical( offset );\n}\n\nvoid *\ndfb_system_video_memory_virtual( unsigned int offset )\n{\n     D_ASSERT( system_funcs != NULL );\n\n     return system_funcs->VideoMemoryVirtual( offset );\n}\n\nunsigned int\ndfb_system_videoram_length()\n{\n     D_ASSERT( system_funcs != NULL );\n\n     return system_funcs->VideoRamLength();\n}\n\nvoid\ndfb_system_get_busid( int *ret_bus,\n                      int *ret_dev,\n                      int *ret_func )\n{\n     int bus = -1, dev = -1, func = -1;\n\n     D_ASSERT( system_funcs != NULL );\n\n     system_funcs->GetBusID( &bus, &dev, &func );\n\n     if (ret_bus)\n          *ret_bus = bus;\n     if (ret_dev)\n          *ret_dev = dev;\n     if (ret_func)\n          *ret_func = func;\n}\n\nvoid\ndfb_system_get_deviceid( unsigned int *ret_vendor_id,\n                         unsigned int *ret_device_id )\n{\n     unsigned int vendor_id = 0, device_id = 0;\n\n     D_ASSERT( system_funcs != NULL );\n\n     system_funcs->GetDeviceID( &vendor_id, &device_id );\n\n     if (ret_vendor_id)\n          *ret_vendor_id = vendor_id;\n\n     if (ret_device_id)\n          *ret_device_id = device_id;\n}\n"
  },
  {
    "path": "src/core/system.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__SYSTEM_H__\n#define __CORE__SYSTEM_H__\n\n#include <core/coretypes.h>\n#include <core/video_mode.h>\n#include <direct/modules.h>\n\nDECLARE_MODULE_DIRECTORY( dfb_core_systems );\n\n/**********************************************************************************************************************/\n\n#define DFB_CORE_SYSTEM_ABI_VERSION          10\n\n#define DFB_CORE_SYSTEM_INFO_NAME_LENGTH     60\n#define DFB_CORE_SYSTEM_INFO_VENDOR_LENGTH   80\n#define DFB_CORE_SYSTEM_INFO_URL_LENGTH     120\n#define DFB_CORE_SYSTEM_INFO_LICENSE_LENGTH  40\n\ntypedef struct {\n     int major; /* major version */\n     int minor; /* minor version */\n} CoreSystemVersion;\n\ntypedef enum {\n     CSCAPS_NONE            = 0x00000000, /* None of these. */\n\n     CSCAPS_ACCELERATION    = 0x00000001, /* HW acceleration supported, so probe graphics drivers. */\n     CSCAPS_PREFER_SHM      = 0x00000002, /* Prefer shared memory surface pool over local memory pool. */\n     CSCAPS_SECURE_FUSION   = 0x00000004, /* Fusion needs to be in secure fusion mode. */\n     CSCAPS_ALWAYS_INDIRECT = 0x00000008, /* All calls need to be indirect. */\n     CSCAPS_SYSMEM_EXTERNAL = 0x00000010, /* Make system memory surface pools have CSTF_EXTERNAL support. */\n\n     CSCAPS_NOTIFY_DISPLAY  = 0x00000040, /* Call dfb_surface_notify_display2() when appropriate. */\n\n     CSCAPS_ALL             = 0x0000005F  /* All of these. */\n} CoreSystemCapabilities;\n\ntypedef struct {\n     CoreSystemVersion      version;\n\n     CoreSystemCapabilities caps;\n\n     char                   name[DFB_CORE_SYSTEM_INFO_NAME_LENGTH];       /* Name of system driver */\n     char                   vendor[DFB_CORE_SYSTEM_INFO_VENDOR_LENGTH];   /* Vendor (or author) of the driver */\n     char                   url[DFB_CORE_SYSTEM_INFO_URL_LENGTH];         /* URL for driver updates */\n     char                   license[DFB_CORE_SYSTEM_INFO_LICENSE_LENGTH]; /* License, e.g. 'LGPL' or 'proprietary' */\n} CoreSystemInfo;\n\ntypedef struct {\n     void           (*GetSystemInfo)      ( CoreSystemInfo   *info );\n\n     DFBResult      (*Initialize)         ( CoreDFB          *core,\n                                            void            **data );\n\n     DFBResult      (*Join)               ( CoreDFB          *core,\n                                            void            **data );\n\n     DFBResult      (*Shutdown)           ( bool              emergency );\n\n     DFBResult      (*Leave)              ( bool              emergency );\n\n     DFBResult      (*Suspend)            ( void );\n\n     DFBResult      (*Resume)             ( void );\n\n     VideoMode     *(*GetModes)           ( void );\n\n     VideoMode     *(*GetCurrentMode)     ( void );\n\n     /*\n      * Called at the beginning of a new thread.\n      */\n     DFBResult      (*ThreadInit)         ( void );\n\n     /*\n      * Called upon incoming input events.\n      * Return true to drop the event, e.g. after doing special handling of it.\n      */\n     bool           (*InputFilter)        ( CoreInputDevice  *device,\n                                            DFBInputEvent    *event );\n\n     /*\n      * Graphics drivers call this function to get access to MMIO regions:\n      *   'offset': offset from MMIO base (default offset is 0)\n      *   'length': length of mapped region (-1 uses default length)\n      * Returns the virtual address or NULL if mapping failed.\n      */\n     volatile void *(*MapMMIO)            ( unsigned int      offset,\n                                            int               length );\n\n     /*\n      * Graphics drivers call this function to unmap MMIO regions:\n      *   'addr':   virtual address of mapped region\n      *   'length': length of mapped region (-1 uses default length)\n      */\n     void           (*UnmapMMIO)          ( volatile void    *addr,\n                                            int               length );\n\n     unsigned int   (*GetAccelerator)     ( void );\n\n     unsigned long  (*VideoMemoryPhysical)( unsigned int      offset );\n\n     void          *(*VideoMemoryVirtual) ( unsigned int      offset );\n\n     unsigned int   (*VideoRamLength)     ( void );\n\n     void           (*GetBusID)           ( int              *ret_bus,\n                                            int              *ret_dev,\n                                            int              *ret_func );\n\n     void           (*GetDeviceID)        ( unsigned int     *ret_vendor_id,\n                                            unsigned int     *ret_device_id );\n} CoreSystemFuncs;\n\n/**********************************************************************************************************************/\n\nDFBResult               dfb_system_lookup               ( void );\n\nCoreSystemCapabilities  dfb_system_caps                 ( void );\n\nvoid                   *dfb_system_data                 ( void );\n\nVideoMode              *dfb_system_modes                ( void );\n\nVideoMode              *dfb_system_current_mode         ( void );\n\nDFBResult               dfb_system_thread_init          ( void );\n\nbool                    dfb_system_input_filter         ( CoreInputDevice *device,\n                                                          DFBInputEvent   *event );\n\nvolatile void          *dfb_system_map_mmio             ( unsigned int     offset,\n                                                          int              length );\n\nvoid                    dfb_system_unmap_mmio           ( volatile void   *addr,\n                                                          int              length );\n\nunsigned int            dfb_system_get_accelerator      ( void );\n\nunsigned long           dfb_system_video_memory_physical( unsigned int     offset );\n\nvoid                   *dfb_system_video_memory_virtual ( unsigned int     offset );\n\nunsigned int            dfb_system_videoram_length      ( void );\n\nvoid                    dfb_system_get_busid            ( int             *ret_bus,\n                                                          int             *ret_dev,\n                                                          int             *ret_func );\n\nvoid                    dfb_system_get_deviceid         ( unsigned int    *ret_vendor_id,\n                                                          unsigned int    *ret_device_id );\n\n#endif\n"
  },
  {
    "path": "src/core/video_mode.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__VIDEO_MODE_H__\n#define __CORE__VIDEO_MODE_H__\n\n/**********************************************************************************************************************/\n\ntypedef struct _VideoMode {\n     int                xres;\n     int                yres;\n     int                bpp;\n\n     int                pixclock;\n     int                left_margin;\n     int                right_margin;\n     int                upper_margin;\n     int                lower_margin;\n     int                hsync_len;\n     int                vsync_len;\n     int                hsync_high;\n     int                vsync_high;\n     int                csync_high;\n\n     int                laced;\n     int                doubled;\n\n     int                sync_on_green;\n     int                external_sync;\n     int                broadcast;\n\n     struct _VideoMode *next;\n} VideoMode;\n\n#endif\n"
  },
  {
    "path": "src/core/windows.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreSurface.h>\n#include <core/CoreSurfaceClient.h>\n#include <core/CoreWindow.h>\n#include <core/core.h>\n#include <core/layers.h>\n#include <core/layer_context.h>\n#include <core/surface_client.h>\n#include <core/windows.h>\n#include <core/windowstack.h>\n#include <core/wm.h>\n#include <fusion/shmalloc.h>\n\nD_DEBUG_DOMAIN( Core_Windows,        \"Core/Windows\",        \"DirectFB Core Windows\" );\nD_DEBUG_DOMAIN( Core_Windows_Events, \"Core/Windows/Events\", \"DirectFB Core Windows Events\" );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     DirectLink  link;\n\n     CoreWindow *window;\n     int         x;\n     int         y;\n} BoundWindow;\n\nstatic const ReactionFunc dfb_window_globals[] = {\n     NULL\n};\n\n/**********************************************************************************************************************/\n\nstatic void\nwindow_destructor( FusionObject *object,\n                   bool          zombie,\n                   void         *ctx )\n{\n     CoreWindow      *window = (CoreWindow*) object;\n     CoreWindowStack *stack  = window->stack;\n\n     D_ASSUME( window->stack != NULL );\n\n     D_DEBUG_AT( Core_Windows, \"Destroying window %p (%4d,%4d-%4dx%4d%s)\\n\",\n                 window, DFB_RECTANGLE_VALS( &window->config.bounds ), zombie ? \" ZOMBIE\" : \"\" );\n\n     if (!stack) {\n          /* Destroy the object. */\n          fusion_object_destroy( object );\n          return;\n     }\n\n     CoreWindow_Deinit_Dispatch( &window->call );\n\n     dfb_windowstack_lock( stack );\n\n     dfb_window_destroy( window );\n\n     if (window->cursor.surface)\n          dfb_surface_unlink( &window->cursor.surface );\n\n     if (window->caps & DWCAPS_SUBWINDOW) {\n          int         index;\n          CoreWindow *toplevel;\n\n          toplevel = window->toplevel;\n          D_ASSERT( toplevel != NULL );\n\n          index = fusion_vector_index_of( &toplevel->subwindows, window );\n          D_ASSERT( index >= 0 );\n\n          fusion_vector_remove( &toplevel->subwindows, index );\n\n          window->toplevel = NULL;\n     }\n     else {\n          CoreWindow *sub;\n          int         i;\n\n          fusion_vector_foreach (sub, i, window->subwindows) {\n               sub->toplevel = NULL;\n          }\n\n          fusion_vector_destroy( &window->subwindows );\n     }\n\n     dfb_windowstack_unlock( stack );\n\n     /* Unlink the primary region of the context. */\n     if (window->primary_region)\n          dfb_layer_region_unlink( &window->primary_region );\n\n     D_MAGIC_CLEAR( window );\n\n     /* Destroy the object. */\n     fusion_object_destroy( object );\n}\n\nFusionObjectPool *\ndfb_window_pool_create( const FusionWorld *world )\n{\n     FusionObjectPool *pool;\n\n     pool = fusion_object_pool_create( \"Window Pool\",\n                                       sizeof(CoreWindow), sizeof(DFBWindowEvent),\n                                       window_destructor, NULL, world );\n\n     return pool;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_window_create_region( CoreWindow              *window,\n                          CoreLayerContext        *context,\n                          CoreSurface             *window_surface,\n                          DFBSurfacePixelFormat    format,\n                          DFBSurfaceColorSpace     colorspace,\n                          DFBSurfaceCapabilities   surface_caps,\n                          CoreLayerRegion        **ret_region,\n                          CoreSurface            **ret_surface )\n{\n     DFBResult              ret;\n     CoreLayerRegionConfig  config;\n     CoreLayerRegion       *region;\n     CoreSurface           *surface = window_surface;\n     CoreSurfaceConfig      scon;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( context != NULL );\n     D_ASSERT( ret_region != NULL );\n     D_ASSERT( ret_surface != NULL );\n\n     memset( &config, 0, sizeof(CoreLayerRegionConfig) );\n\n     config.width         = window->config.bounds.w;\n     config.height        = window->config.bounds.h;\n     config.format        = format;\n     config.colorspace    = colorspace;\n     config.options       = context->config.options & DLOP_FLICKER_FILTERING;\n     config.source        = (DFBRectangle) { 0, 0, config.width, config.height };\n     config.dest          = window->config.bounds;\n     config.opacity       = 0;\n     config.alpha_ramp[0] = 0x00;\n     config.alpha_ramp[1] = 0x55;\n     config.alpha_ramp[2] = 0xaa;\n     config.alpha_ramp[3] = 0xff;\n\n     if (surface_caps & DSCAPS_DOUBLE)\n          config.buffermode = DLBM_BACKVIDEO;\n     else if (surface_caps & DSCAPS_TRIPLE)\n          config.buffermode = DLBM_TRIPLE;\n     else\n          config.buffermode = DLBM_FRONTONLY;\n\n     if (((context->config.options & DLOP_ALPHACHANNEL) || (window->config.options & DWOP_ALPHACHANNEL)) &&\n         DFB_PIXELFORMAT_HAS_ALPHA( format ))\n          config.options |= DLOP_ALPHACHANNEL;\n\n     config.options |= DLOP_OPACITY;\n\n     config.surface_caps = surface_caps & (DSCAPS_INTERLACED | DSCAPS_SEPARATED  | DSCAPS_PREMULTIPLIED);\n\n     ret = dfb_layer_region_create( context, &region );\n     if (ret)\n          return ret;\n\n     region->config.keep_buffers = true;\n\n     do {\n          ret = dfb_layer_region_set_configuration( region, &config, CLRCF_ALL );\n          if (ret) {\n               if (config.options & DLOP_OPACITY)\n                    config.options &= ~DLOP_OPACITY;\n               else if (config.options & DLOP_ALPHACHANNEL)\n                    config.options = (config.options & ~DLOP_ALPHACHANNEL) | DLOP_OPACITY;\n               else {\n                    D_DERROR( ret, \"Core/Windows: Unable to set region configuration!\\n\" );\n                    dfb_layer_region_unref( region );\n                    return ret;\n               }\n          }\n     } while (ret);\n\n     if (!surface) {\n          scon.flags      = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_COLORSPACE | CSCONF_CAPS;\n          scon.size.w     = config.width;\n          scon.size.h     = config.height;\n          scon.format     = format;\n          scon.colorspace = colorspace;\n          scon.caps       = surface_caps | DSCAPS_VIDEOONLY;\n\n          ret = dfb_surface_create( core_dfb, &scon, CSTF_SHARED | CSTF_LAYER, context->layer_id, NULL, &surface );\n          if (ret) {\n               dfb_layer_region_unref( region );\n               return ret;\n          }\n     }\n\n     ret = dfb_layer_region_set_surface( region, surface, false );\n     if (ret) {\n          dfb_surface_unref( surface );\n          dfb_layer_region_unref( region );\n          return ret;\n     }\n\n     if (!window_surface) {\n          ret = dfb_layer_region_enable( region );\n          if (ret) {\n               dfb_surface_unref( surface );\n               dfb_layer_region_unref( region );\n               return ret;\n          }\n     }\n\n     *ret_region  = region;\n     *ret_surface = surface;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ninit_subwindow( CoreWindow      *window,\n                CoreWindowStack *stack,\n                DFBWindowID      toplevel_id )\n{\n     DFBResult   ret;\n     CoreWindow *toplevel;\n\n     /* Lookup top level window. */\n     ret = dfb_wm_window_lookup( stack, toplevel_id, &toplevel );\n     if (ret)\n          return ret;\n\n     /* Make sure chosen top level window is not a sub window. */\n     if (toplevel->caps & DWCAPS_SUBWINDOW) {\n          D_ASSERT( toplevel->toplevel != NULL );\n          D_ASSERT( toplevel->toplevel_id != 0 );\n\n          return DFB_INVARG;\n     }\n     else {\n          D_ASSERT( toplevel->toplevel == NULL );\n          D_ASSERT( toplevel->toplevel_id == 0 );\n     }\n\n     /* Link top level window into sub window structure. */\n     window->toplevel = toplevel;\n     if (ret)\n          return ret;\n\n     /* Add window to sub window list of top level window. */\n     ret = fusion_vector_add( &toplevel->subwindows, window );\n     if (ret) {\n          dfb_window_unlink( &window->toplevel );\n          return ret;\n     }\n\n     return DFB_OK;\n}\n\nstatic ReactionResult\nwindow_surface_react( const void *msg_data,\n                      void       *ctx )\n{\n     const DFBSurfaceEvent *evt    = msg_data;\n     CoreWindow            *window = ctx;\n\n     D_DEBUG_AT( Core_Windows, \"%s( %p ) <- type %06x\\n\", __FUNCTION__, evt, evt->type );\n     D_DEBUG_AT( Core_Windows, \"  -> surface id %u\\n\", evt->surface_id );\n\n     if (evt->type == DSEVT_UPDATE) {\n          D_DEBUG_AT( Core_Windows, \"  -> updated %4d,%4d-%4dx%4d (left)\\n\",\n                      DFB_RECTANGLE_VALS_FROM_REGION( &evt->update ) );\n          D_DEBUG_AT( Core_Windows, \"  -> updated %4d,%4d-%4dx%4d (right)\\n\",\n                      DFB_RECTANGLE_VALS_FROM_REGION( &evt->update_right ) );\n          D_DEBUG_AT( Core_Windows, \"  -> flip count %u\\n\", evt->flip_count );\n          D_DEBUG_AT( Core_Windows, \"  -> time stamp %lld\\n\", evt->time_stamp );\n          D_DEBUG_AT( Core_Windows, \"  -> window %p\\n\", window );\n\n          if (direct_log_domain_check( &Core_Windows )) {\n               dfb_surface_lock( window->surface );\n               CoreSurfaceBuffer *buffer;\n               D_UNUSED_P( buffer );\n               buffer = dfb_surface_get_buffer3( window->surface, DSBR_FRONT, DSSE_LEFT, evt->flip_count );\n               D_DEBUG_AT( Core_Windows, \"  -> buffer %p\\n\", buffer );\n               dfb_surface_unlock( window->surface );\n          }\n\n          /* Lock the window stack. */\n          if (dfb_windowstack_lock( window->stack ))\n               return RS_OK;\n\n          /* Never call WM after destroying the window. */\n          if (DFB_WINDOW_DESTROYED( window )) {\n               dfb_windowstack_unlock( window->stack );\n               return RS_OK;\n          }\n\n          window->surface_flip_count = evt->flip_count;\n\n          if (!dfb_config->single_window || fusion_vector_size( &window->stack->visible_windows ) != 1) {\n               D_DEBUG_AT( Core_Windows, \"  -> dispatching update to window manager\\n\" );\n\n               dfb_wm_update_window( window, &evt->update, &evt->update_right, DSFLIP_NONE );\n          }\n\n          CoreSurfaceClient_FrameAck( window->surface_client, evt->flip_count );\n\n          /* Unlock the window stack. */\n          dfb_windowstack_unlock( window->stack );\n     }\n     else if (evt->type == DSEVT_DESTROYED)\n          return RS_REMOVE;\n\n     return RS_OK;\n}\n\nDFBResult\ndfb_window_create( CoreWindowStack             *stack,\n                   const DFBWindowDescription  *desc,\n                   CoreWindow                 **ret_window )\n{\n     DFBResult               ret;\n     CoreSurface            *surface;\n     DFBWindowSurfacePolicy  policy = DWSP_SYSTEMONLY;\n     CoreLayer              *layer;\n     CoreLayerContext       *context;\n     CoreWindow             *window;\n     CardCapabilities        card_caps;\n     CoreWindowConfig        config;\n     DFBWindowCapabilities   caps;\n     DFBSurfaceCapabilities  surface_caps;\n     DFBSurfacePixelFormat   pixelformat;\n     DFBSurfaceColorSpace    colorspace;\n     DFBWindowID             toplevel_id;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( stack->context != NULL );\n     D_ASSERT( desc != NULL );\n     D_ASSERT( desc->width > 0 );\n     D_ASSERT( desc->height > 0 );\n     D_ASSERT( ret_window != NULL );\n\n     D_DEBUG_AT( Core_Windows, \"%s( %p )\\n\", __FUNCTION__, stack );\n\n     if (desc->width > 4096 || desc->height > 4096) {\n          D_DEBUG_AT( Core_Windows, \"  -> limit exceeded (%dx%d / 4096x4096)\\n\", desc->width, desc->height );\n          return DFB_LIMITEXCEEDED;\n     }\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack )) {\n          D_DEBUG_AT( Core_Windows, \"  -> window stack lock failed!\\n\" );\n          return DFB_FUSION;\n     }\n\n     context = stack->context;\n     layer   = dfb_layer_at( context->layer_id );\n\n     D_DEBUG_AT( Core_Windows, \"  -> caps 0x%08x\\n\", desc->caps );\n\n     caps         = desc->caps;\n     pixelformat  = desc->pixelformat;\n     colorspace   = desc->colorspace;\n     surface_caps = desc->surface_caps & (DSCAPS_INTERLACED   | DSCAPS_SEPARATED     | DSCAPS_DOUBLE |\n                                          DSCAPS_STATIC_ALLOC | DSCAPS_PREMULTIPLIED | DSCAPS_TRIPLE |\n                                          DSCAPS_SYSTEMONLY   | DSCAPS_VIDEOONLY     | DSCAPS_DEPTH  | DSCAPS_GL );\n     toplevel_id  = (desc->flags & DWDESC_TOPLEVEL_ID) ? desc->toplevel_id : 0;\n\n     if (toplevel_id != 0)\n          caps |= DWCAPS_SUBWINDOW;\n     else\n          caps &= ~DWCAPS_SUBWINDOW;\n\n     if (caps & DWCAPS_STEREO)\n          surface_caps |= DSCAPS_STEREO;\n\n     if (!dfb_config->translucent_windows) {\n          caps &= ~DWCAPS_ALPHACHANNEL;\n     }\n\n     /* Choose pixel format. */\n     if (caps & DWCAPS_ALPHACHANNEL) {\n          if (pixelformat == DSPF_UNKNOWN) {\n               if (context->config.flags & DLCONF_PIXELFORMAT)\n                    pixelformat = context->config.pixelformat;\n\n               if (!DFB_PIXELFORMAT_HAS_ALPHA( pixelformat ))\n                    pixelformat = DSPF_ARGB;\n          }\n          else if (!DFB_PIXELFORMAT_HAS_ALPHA( pixelformat )) {\n               D_DEBUG_AT( Core_Windows, \"  -> pixelformat '%s' has no alpha!\\n\", dfb_pixelformat_name( pixelformat ) );\n               dfb_windowstack_unlock( stack );\n               return DFB_INVARG;\n          }\n     }\n     else if (pixelformat == DSPF_UNKNOWN) {\n          if (context->config.flags & DLCONF_PIXELFORMAT)\n               pixelformat = context->config.pixelformat;\n          else {\n               D_WARN( \"layer config has no pixel format, using RGB16\" );\n               pixelformat = DSPF_RGB16;\n          }\n     }\n\n     /* Set the color space. */\n     if (colorspace == DSCS_UNKNOWN) {\n          colorspace = DFB_COLORSPACE_DEFAULT( pixelformat );\n     }\n     else if (!DFB_COLORSPACE_IS_COMPATIBLE( colorspace, pixelformat )) {\n          D_DEBUG_AT( Core_Windows, \"  -> colorspace '%s' is not compatible with pixelformat '%s'!\\n\",\n                      dfb_colorspace_name(colorspace), dfb_pixelformat_name( pixelformat ) );\n          dfb_windowstack_unlock( stack );\n          return DFB_INVARG;\n     }\n\n     /* Choose window surface policy. */\n     if ((surface_caps & DSCAPS_VIDEOONLY) || (context->config.buffermode == DLBM_WINDOWS)) {\n          policy = DWSP_VIDEOONLY;\n     }\n     else if (!(surface_caps & DSCAPS_SYSTEMONLY) && context->config.buffermode != DLBM_BACKSYSTEM) {\n          /* Use the explicitly specified policy. */\n          if (dfb_config->window_policy != -1) {\n               policy = dfb_config->window_policy;\n          }\n          else {\n               /* Examine the hardware capabilities. */\n               dfb_gfxcard_get_capabilities( &card_caps );\n\n               if (card_caps.accel & DFXL_BLIT) {\n                    if ((card_caps.blitting & DSBLIT_BLEND_ALPHACHANNEL) || !(caps & DWCAPS_ALPHACHANNEL))\n                         policy = DWSP_VIDEOHIGH;\n               }\n          }\n     }\n\n     dfb_surface_caps_apply_policy( policy, &surface_caps );\n\n     if (caps & DWCAPS_DOUBLEBUFFER) {\n          if (!(surface_caps & DSCAPS_TRIPLE))\n               surface_caps |= DSCAPS_DOUBLE;\n     }\n\n     memset( &config, 0, sizeof(CoreWindowConfig) );\n\n     config.bounds.x = desc->posx;\n     config.bounds.y = desc->posy;\n     config.bounds.w = desc->width;\n     config.bounds.h = desc->height;\n     config.stacking = (desc->flags & DWDESC_STACKING) ? desc->stacking : DWSC_MIDDLE;\n     config.events   = DWET_ALL & ~DWET_UPDATE;\n\n     /* Auto enable blending for ARGB only, not indexed. */\n     if ((caps & DWCAPS_ALPHACHANNEL) &&\n          DFB_PIXELFORMAT_HAS_ALPHA( pixelformat ) &&\n         !DFB_PIXELFORMAT_IS_INDEXED( pixelformat ))\n          config.options |= DWOP_ALPHACHANNEL;\n\n     /* Override automatic settings. */\n     if (desc->flags & DWDESC_OPTIONS)\n          config.options = desc->options;\n\n     /* Create the window object. */\n     window = dfb_core_create_window( layer->core );\n     if (!window) {\n          D_DEBUG_AT( Core_Windows, \"  -> core window create failed!\\n\" );\n          dfb_windowstack_unlock( stack );\n          return DFB_FUSION;\n     }\n\n     window->id                  = ++stack->id_pool;\n     window->caps                = caps | DWCAPS_NOFOCUS;\n     window->requested_caps      = caps;\n     window->stack               = stack;\n     window->config              = config;\n     window->config.association  = (desc->flags & DWDESC_PARENT) ? desc->parent_id : 0;\n     window->config.cursor_flags = DWCF_INVISIBLE;\n     window->toplevel_id         = toplevel_id;\n     window->policy              = policy;\n\n     if (desc->flags & DWDESC_RESOURCE_ID)\n          window->resource_id = desc->resource_id;\n\n     D_MAGIC_SET( window, CoreWindow );\n\n     ret = dfb_wm_preconfigure_window( stack, window );\n     if (ret) {\n          D_DEBUG_AT( Core_Windows, \"  -> window preconfigure failed!\\n\" );\n          D_MAGIC_CLEAR( window );\n          fusion_object_destroy( &window->object );\n          dfb_windowstack_unlock( stack );\n          return ret;\n     }\n\n     /* Window manager may have changed values. */\n     config = window->config;\n     caps   = window->caps;\n\n     /* Initialize sub window. */\n     if (caps & DWCAPS_SUBWINDOW) {\n          ret = init_subwindow( window, stack, toplevel_id );\n          if (ret) {\n               D_DEBUG_AT( Core_Windows, \"  -> sub window init failed!\\n\" );\n               D_MAGIC_CLEAR( window );\n               fusion_object_destroy( &window->object );\n               dfb_windowstack_unlock( stack );\n               return ret;\n          }\n     }\n     else {\n          /* Initialize top level window. */\n          fusion_vector_init( &window->subwindows, 3, stack->shmpool );\n\n          /* In case window manager forbids sub window request, clear the toplevel window ID. */\n          window->toplevel_id = 0;\n     }\n\n     if (dfb_config->warn.flags & DCWF_CREATE_WINDOW)\n          D_WARN( \"create-window %4dx%4d %6s, caps 0x%08x, surface-caps 0x%08x, ID %u\",\n                  window->config.bounds.w, window->config.bounds.h, dfb_pixelformat_name( pixelformat ), window->caps,\n                  surface_caps, window->id );\n\n     /* Create the window's surface using the layer's palette if possible. */\n     if (!(caps & (DWCAPS_INPUTONLY | DWCAPS_COLOR))) {\n          if (context->config.buffermode == DLBM_WINDOWS) {\n               CoreLayerRegion *region = NULL;\n\n               /* Create a region for the window. */\n               ret = dfb_window_create_region( window, context, NULL, pixelformat, colorspace, surface_caps,\n                                               &region, &surface );\n               if (ret) {\n                    D_DEBUG_AT( Core_Windows, \"  -> region create failed!\\n\" );\n                    D_MAGIC_CLEAR( window );\n                    fusion_object_destroy( &window->object );\n                    dfb_windowstack_unlock( stack );\n                    return ret;\n               }\n\n               /* Link the region into the window structure. */\n               dfb_layer_region_link( &window->region, region );\n               dfb_layer_region_unref( region );\n\n               /* Link the surface into the window structure. */\n               dfb_surface_link( &window->surface, surface );\n               dfb_surface_unref( surface );\n          }\n          else {\n               CoreLayerRegion *region;\n\n               /* Get the primary region of the layer context. */\n               ret = dfb_layer_context_get_primary_region( context, true, &region );\n               if (ret) {\n                    D_DEBUG_AT( Core_Windows, \"  -> primary region get failed!\\n\" );\n                    D_MAGIC_CLEAR( window );\n                    fusion_object_destroy( &window->object );\n                    dfb_windowstack_unlock( stack );\n                    return ret;\n               }\n\n               /* Link the primary region into the window structure. */\n               dfb_layer_region_link( &window->primary_region, region );\n               dfb_layer_region_unref( region );\n\n               D_DEBUG_AT( Core_Windows, \"  -> %dx%d %s %s\\n\", window->config.bounds.w, window->config.bounds.h,\n                           dfb_pixelformat_name( pixelformat ), (policy == DWSP_VIDEOONLY)  ?  \"VIDEOONLY\" :\n                           (policy == DWSP_SYSTEMONLY) ? \"SYSTEMONLY\" : \"AUTO VIDEO\" );\n\n               /* Give the window manager a chance to provide its own surface. */\n               if (!window->surface) {\n                    /* Create the surface for the window. */\n                    ret = dfb_surface_create_simple( layer->core, config.bounds.w, config.bounds.h, pixelformat,\n                                                     colorspace, surface_caps, CSTF_SHARED | CSTF_WINDOW,\n                                                     desc->flags & DWDESC_RESOURCE_ID ? desc->resource_id : window->id,\n                                                     region->surface ? region->surface->palette : NULL, &surface );\n                    if (ret) {\n                         D_DEBUG_AT( Core_Windows, \"  -> surface create failed!\\n\" );\n                         D_DERROR( ret, \"Core/Windows: Failed to create window surface!\\n\" );\n                         D_MAGIC_CLEAR( window );\n                         dfb_layer_region_unlink( &window->primary_region );\n                         fusion_object_destroy( &window->object );\n                         dfb_windowstack_unlock( stack );\n                         return ret;\n                    }\n\n                    /* Link the surface into the window structure. */\n                    dfb_surface_link( &window->surface, surface );\n                    dfb_surface_unref( surface );\n               }\n\n               /* Create the surface client. */\n               ret = CoreSurface_CreateClient( window->surface, &window->surface_client );\n               if (ret) {\n                    D_WARN( \"failed to create surface client\" );\n                    return ret;\n               }\n\n               /* Attach the surface event listener. */\n               dfb_surface_attach_channel( window->surface, CSCH_EVENT, window_surface_react, window,\n                                           &window->surface_event_reaction );\n          }\n     }\n     else\n          D_DEBUG_AT( Core_Windows, \"  -> %dx%d => INPUTONLY\\n\", window->config.bounds.w, window->config.bounds.h );\n\n     D_DEBUG_AT( Core_Windows, \"  -> %p\\n\", window );\n\n     /* Pass the new window to the window manager. */\n     ret = dfb_wm_add_window( stack, window );\n     if (ret) {\n          D_DEBUG_AT( Core_Windows, \"  -> window add failed!\\n\" );\n          D_DERROR( ret, \"Core/Windows: Failed to add window to manager!\\n\" );\n\n          D_MAGIC_CLEAR( window );\n\n          if (window->surface)\n               dfb_surface_unlink( &window->surface );\n\n          if (window->primary_region)\n               dfb_layer_region_unlink( &window->primary_region );\n\n          if (window->region)\n               dfb_layer_region_unlink( &window->region );\n\n          fusion_object_destroy( &window->object );\n          dfb_windowstack_unlock( stack );\n          return ret;\n     }\n\n     /* Indicate that initialization is complete. */\n     D_FLAGS_SET( window->flags, CWF_INITIALIZED );\n\n     CoreWindow_Init_Dispatch( layer->core, window, &window->call );\n\n     /* Activate the object. */\n     fusion_object_activate( &window->object );\n\n     fusion_reactor_direct( window->object.reactor, true );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     /* Return the new window. */\n     *ret_window = window;\n\n     D_DEBUG_AT( Core_Windows, \"  -> %p\\n\", window );\n\n     return DFB_OK;;\n}\n\nvoid\ndfb_window_destroy( CoreWindow *window )\n{\n     int              i;\n     DFBWindowEvent   evt;\n     CoreWindowStack *stack;\n     BoundWindow     *bound, *next;\n     CoreWindow      *subwindow;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n     D_ASSERT( DFB_WINDOW_INITIALIZED( window ) );\n\n     D_ASSUME( window->stack != NULL );\n\n     D_DEBUG_AT( Core_Windows, \"%s( %p ) <- %4d,%4d-%4dx%4d\\n\", __FUNCTION__,\n                 window, DFB_RECTANGLE_VALS( &window->config.bounds ) );\n\n     stack = window->stack;\n     if (!stack)\n          return;\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return;\n\n     /* Destroy sub windows first. */\n     fusion_vector_foreach_reverse (subwindow, i, window->subwindows) {\n          D_ASSERT( subwindow != NULL );\n          D_ASSERT( DFB_WINDOW_INITIALIZED( subwindow ) );\n\n          dfb_window_destroy( subwindow );\n     }\n\n     /* Avoid multiple destructions. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          D_DEBUG_AT( Core_Windows, \"  -> %p already destroyed\\n\", window );\n          dfb_windowstack_unlock( stack );\n          return;\n     }\n\n     /* Unbind bound windows. */\n     direct_list_foreach_safe (bound, next, window->bound_windows) {\n          direct_list_remove( &window->bound_windows, &bound->link );\n\n          bound->window->boundto = NULL;\n\n          SHFREE( stack->shmpool, bound );\n     }\n\n     /* Unbind this window. */\n     if (window->boundto)\n          dfb_window_unbind( window->boundto, window );\n\n     /* Make sure the window is no longer visible. */\n     dfb_window_set_opacity( window, 0 );\n\n     /* Stop managing the window. */\n     dfb_wm_remove_window( stack, window );\n\n     /* Indicate destruction. */\n     D_FLAGS_SET( window->flags, CWF_DESTROYED );\n\n     /* Hardware allocated. */\n     if (window->region) {\n          /* Disable region (removing it from hardware). */\n          dfb_layer_region_disable( window->region );\n\n          /* Unlink from structure. */\n          dfb_layer_region_unlink( &window->region );\n     }\n\n     /* Unlink the window's surface. */\n     if (window->surface) {\n          dfb_surface_client_unref( window->surface_client );\n\n          /* Detach the surface event listener. */\n          dfb_surface_detach( window->surface, &window->surface_event_reaction );\n\n          dfb_surface_destroy_buffers( window->surface );\n          dfb_surface_unlink( &window->surface );\n     }\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     /* Notify listeners. */\n     evt.type = DWET_DESTROYED;\n     dfb_window_post_event( window, &evt );\n}\n\nDFBResult\ndfb_window_change_stacking( CoreWindow             *window,\n                            DFBWindowStackingClass  stacking )\n{\n     DFBResult         ret;\n     CoreWindowStack  *stack;\n     CoreLayerContext *context;\n     CoreWindowConfig  config;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n     D_ASSERT( window->stack != NULL );\n     D_ASSERT( window->stack->context != NULL );\n\n     stack   = window->stack;\n     context = stack->context;\n\n     if (!(dfb_config->layers[context->layer_id].stacking & (1 << stacking))) {\n          D_ERROR( \"Core/Windows: Cannot change the stacking class!\\n\" );\n          return DFB_INVARG;\n     }\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     config.stacking = stacking;\n\n     /* Let the window manager do its work. */\n     ret = dfb_wm_set_window_config( window, &config, DWCONF_STACKING );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_set_type_hint( CoreWindow        *window,\n                          DFBWindowTypeHint  type_hint )\n{\n     DFBResult         ret;\n     CoreWindowStack  *stack;\n     CoreWindowConfig  config;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n     D_ASSERT( window->stack != NULL );\n\n     stack = window->stack;\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     config.type_hint = type_hint;\n\n     /* Let the window manager do its work. */\n     ret = dfb_wm_set_window_config( window, &config, DWCONF_TYPE_HINT );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_change_hint_flags( CoreWindow         *window,\n                              DFBWindowHintFlags  clear,\n                              DFBWindowHintFlags  set )\n{\n     DFBResult         ret;\n     CoreWindowStack  *stack;\n     CoreWindowConfig  config;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n     D_ASSERT( window->stack != NULL );\n\n     stack = window->stack;\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     config.hint_flags = (window->config.hint_flags & ~clear) | set;\n\n     /* Let the window manager do its work. */\n     ret = dfb_wm_set_window_config( window, &config, DWCONF_HINT_FLAGS );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_raise( CoreWindow *window )\n{\n     DFBResult        ret;\n     CoreWindowStack *stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n     D_ASSERT( window->stack != NULL );\n\n     stack = window->stack;\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     /* Let the window manager do its work. */\n     ret = dfb_wm_restack_window( window, window, 1 );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_lower( CoreWindow *window )\n{\n     DFBResult        ret;\n     CoreWindowStack *stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n     D_ASSERT( window->stack != NULL );\n\n     stack = window->stack;\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     /* Let the window manager do its work. */\n     ret = dfb_wm_restack_window( window, window, -1 );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_raisetotop( CoreWindow *window )\n{\n     DFBResult        ret;\n     CoreWindowStack *stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n     D_ASSERT( window->stack != NULL );\n\n     stack = window->stack;\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     /* Let the window manager do its work. */\n     ret = dfb_wm_restack_window( window, NULL, 1 );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_lowertobottom( CoreWindow *window )\n{\n     DFBResult        ret;\n     CoreWindowStack *stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n     D_ASSERT( window->stack != NULL );\n\n     stack = window->stack;\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     /* Let the window manager do its work. */\n     ret = dfb_wm_restack_window( window, NULL, 0 );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_putatop( CoreWindow *window,\n                    CoreWindow *lower )\n{\n     DFBResult        ret;\n     CoreWindowStack *stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n     D_ASSERT( window->stack != NULL );\n\n     stack = window->stack;\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     /* Let the window manager do its work. */\n     ret = dfb_wm_restack_window( window, lower, 1 );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_putbelow( CoreWindow *window,\n                     CoreWindow *upper )\n{\n     DFBResult        ret;\n     CoreWindowStack *stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n     D_ASSERT( window->stack != NULL );\n\n     stack = window->stack;\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     /* Let the window manager do its work. */\n     ret = dfb_wm_restack_window( window, upper, -1 );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_set_config( CoreWindow             *window,\n                       const CoreWindowConfig *config,\n                       DFBWindowConfigFlags    flags )\n{\n     DFBResult        ret;\n     CoreWindowStack *stack = window->stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     ret = dfb_wm_set_window_config( window, config, flags );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_set_cursor_shape( CoreWindow   *window,\n                             CoreSurface  *shape,\n                             int           hot_x,\n                             int           hot_y )\n{\n     DFBResult        ret;\n     CoreWindowStack *stack = window->stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     window->cursor.hot_x = hot_x;\n     window->cursor.hot_y = hot_y;\n\n     if (window->cursor.surface)\n          dfb_surface_unlink( &window->cursor.surface );\n\n     if (shape) {\n          ret = dfb_surface_link( &window->cursor.surface, shape );\n          if (ret == DFB_OK) {\n               if (window->flags & CWF_FOCUSED)\n                    dfb_windowstack_cursor_set_shape( stack, shape, hot_x, hot_y );\n          }\n     }\n     else\n          ret = DFB_OK;\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nstatic DFBResult\nmove_window( CoreWindow *window,\n             int         x,\n             int         y )\n{\n     DFBResult         ret;\n     CoreWindowConfig  config;\n     BoundWindow      *bound;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n\n     config.bounds.x = x;\n     config.bounds.y = y;\n\n     ret = dfb_wm_set_window_config( window, &config, DWCONF_POSITION );\n     if (ret)\n          return ret;\n\n     direct_list_foreach (bound, window->bound_windows) {\n          move_window( bound->window, window->config.bounds.x + bound->x, window->config.bounds.y + bound->y );\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_window_move( CoreWindow *window,\n                 int         x,\n                 int         y,\n                 bool        relative )\n{\n     DFBResult        ret;\n     CoreWindowStack *stack = window->stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     if (window->boundto) {\n          dfb_windowstack_unlock( stack );\n          return DFB_UNSUPPORTED;\n     }\n\n     if (relative) {\n          x += window->config.bounds.x;\n          y += window->config.bounds.y;\n     }\n\n     if (x == window->config.bounds.x && y == window->config.bounds.y) {\n          dfb_windowstack_unlock( stack );\n          return DFB_OK;\n     }\n\n     ret = move_window( window, x, y );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_set_bounds( CoreWindow *window,\n                       int         x,\n                       int         y,\n                       int         width,\n                       int         height )\n{\n     DFBResult         ret;\n     CoreWindowConfig  config;\n     CoreWindowStack  *stack = window->stack;\n     int               old_x;\n     int               old_y;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     old_x = window->config.bounds.x;\n     old_y = window->config.bounds.y;\n\n     if (window->boundto) {\n          if (old_x != x || old_y != y) {\n               dfb_windowstack_unlock( stack );\n               return DFB_UNSUPPORTED;\n          }\n     }\n\n     config.bounds.x = x;\n     config.bounds.y = y;\n     config.bounds.w = width;\n     config.bounds.h = height;\n\n     if (window->config.bounds.x == x     && window->config.bounds.y == y &&\n         window->config.bounds.w == width && window->config.bounds.h == height) {\n          dfb_windowstack_unlock( stack );\n          return DFB_OK;\n     }\n\n     ret = dfb_wm_set_window_config( window, &config, DWCONF_POSITION | DWCONF_SIZE );\n     if (ret) {\n          dfb_windowstack_unlock( stack );\n          return ret;\n     }\n\n     if (old_x != x || old_y != y) {\n          BoundWindow *bound;\n\n          direct_list_foreach (bound, window->bound_windows) {\n               move_window( bound->window, window->config.bounds.x + bound->x, window->config.bounds.y + bound->y );\n          }\n     }\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_window_resize( CoreWindow *window,\n                   int         width,\n                   int         height )\n{\n     DFBResult         ret;\n     CoreWindowConfig  config;\n     CoreWindowStack  *stack = window->stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n     D_ASSERT( width > 0 );\n     D_ASSERT( height > 0 );\n\n     if (width > 4096 || height > 4096)\n          return DFB_LIMITEXCEEDED;\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     if (window->config.bounds.w == width && window->config.bounds.h == height) {\n          dfb_windowstack_unlock( stack );\n          return DFB_OK;\n     }\n\n     config.bounds.w = width;\n     config.bounds.h = height;\n\n     ret = dfb_wm_set_window_config( window, &config, DWCONF_SIZE );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_bind( CoreWindow *window,\n                 CoreWindow *source,\n                 int         x,\n                 int         y )\n{\n     DFBResult        ret;\n     CoreWindowStack *stack = window->stack;\n     BoundWindow     *bound;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n\n     if (window == source)\n          return DFB_UNSUPPORTED;\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     if (DFB_WINDOW_DESTROYED( source )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     bound = SHCALLOC( stack->shmpool, 1, sizeof(BoundWindow) );\n     if (!bound) {\n          dfb_windowstack_unlock( stack );\n          return DFB_NOSHAREDMEMORY;\n     }\n\n     if (source->boundto)\n          dfb_window_unbind( source->boundto, source );\n\n     ret = move_window( source, window->config.bounds.x + x, window->config.bounds.y + y );\n     if (ret) {\n          SHFREE( stack->shmpool, bound );\n          dfb_windowstack_unlock( stack );\n          return ret;\n     }\n\n     bound->window = source;\n     bound->x      = x;\n     bound->y      = y;\n\n     direct_list_append( &window->bound_windows, &bound->link );\n\n     source->boundto = window;\n\n     dfb_windowstack_unlock( stack );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_window_unbind( CoreWindow *window,\n                   CoreWindow *source )\n{\n     CoreWindowStack *stack = window->stack;\n     BoundWindow     *bound;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     if (DFB_WINDOW_DESTROYED( source )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     if (source->boundto != window) {\n          dfb_windowstack_unlock( stack );\n          return DFB_UNSUPPORTED;\n     }\n\n     direct_list_foreach (bound, window->bound_windows) {\n          if (bound->window == source) {\n               direct_list_remove( &window->bound_windows, &bound->link );\n\n               bound->window->boundto = NULL;\n\n               SHFREE( stack->shmpool, bound );\n\n               break;\n          }\n     }\n\n     if (!bound)\n          D_BUG( \"window not found\" );\n\n     dfb_windowstack_unlock( stack );\n\n     return bound ? DFB_OK : DFB_ITEMNOTFOUND;\n}\n\nDFBResult\ndfb_window_set_color( CoreWindow *window,\n                      DFBColor    color )\n{\n     DFBResult         ret;\n     DFBColor          cc;\n     CoreWindowConfig  config;\n     CoreWindowStack  *stack = window->stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     cc = window->config.color;\n     if ((cc.a == color.a) && (cc.r == color.r) && (cc.g == color.g) && (cc.b == color.b)) {\n          dfb_windowstack_unlock( stack );\n          return DFB_OK;\n     }\n\n     config.color = color;\n\n     ret = dfb_wm_set_window_config( window, &config, DWCONF_COLOR );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_set_colorkey( CoreWindow *window,\n                         u32         color_key )\n{\n     DFBResult         ret;\n     CoreWindowConfig  config;\n     CoreWindowStack  *stack = window->stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     if (window->config.color_key == color_key) {\n          dfb_windowstack_unlock( stack );\n          return DFB_OK;\n     }\n\n     config.color_key = color_key;\n\n     ret = dfb_wm_set_window_config( window, &config, DWCONF_COLOR_KEY );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_set_opacity( CoreWindow *window,\n                        u8          opacity )\n{\n     DFBResult         ret;\n     CoreWindowConfig  config;\n     CoreWindowStack  *stack = window->stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     if (window->config.opacity == opacity) {\n          dfb_windowstack_unlock( stack );\n          return DFB_OK;\n     }\n\n     config.opacity = opacity;\n\n     ret = dfb_wm_set_window_config( window, &config, DWCONF_OPACITY );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_change_options( CoreWindow       *window,\n                           DFBWindowOptions  disable,\n                           DFBWindowOptions  enable )\n{\n     DFBResult         ret;\n     CoreWindowConfig  config;\n     CoreWindowStack  *stack = window->stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n\n     D_ASSUME( disable | enable );\n\n     if (!disable && !enable)\n          return DFB_OK;\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     config.options = (window->config.options & ~disable) | enable;\n\n     ret = dfb_wm_set_window_config( window, &config, DWCONF_OPTIONS );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_set_opaque( CoreWindow      *window,\n                       const DFBRegion *region )\n{\n     DFBResult         ret;\n     CoreWindowConfig  config;\n     CoreWindowStack  *stack = window->stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n     DFB_REGION_ASSERT_IF( region );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     config.opaque.x1 = 0;\n     config.opaque.y1 = 0;\n     config.opaque.x2 = window->config.bounds.w - 1;\n     config.opaque.y2 = window->config.bounds.h - 1;\n\n     if (region && !dfb_region_region_intersect( &config.opaque, region ))\n          ret = DFB_INVAREA;\n     else\n          ret = dfb_wm_set_window_config( window, &config, DWCONF_OPAQUE );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_change_events( CoreWindow         *window,\n                          DFBWindowEventType  disable,\n                          DFBWindowEventType  enable )\n{\n     DFBResult         ret;\n     CoreWindowConfig  config;\n     CoreWindowStack  *stack = window->stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n\n     D_ASSUME( disable | enable );\n\n     if (!disable && !enable)\n          return DFB_OK;\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     config.events = (window->config.events & ~disable) | enable;\n\n     ret = dfb_wm_set_window_config( window, &config, DWCONF_EVENTS );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_set_key_selection( CoreWindow                    *window,\n                              DFBWindowKeySelection          selection,\n                              const DFBInputDeviceKeySymbol *keys,\n                              unsigned int                   num_keys )\n{\n     DFBResult         ret;\n     CoreWindowConfig  config;\n     CoreWindowStack  *stack = window->stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n     D_ASSERT( selection == DWKS_ALL || selection == DWKS_NONE || selection == DWKS_LIST );\n     D_ASSERT( keys != NULL || selection != DWKS_LIST );\n     D_ASSERT( num_keys > 0 || selection != DWKS_LIST );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     config.key_selection = selection;\n     config.keys          = (DFBInputDeviceKeySymbol*) keys;\n     config.num_keys      = num_keys;\n\n     ret = dfb_wm_set_window_config( window, &config, DWCONF_KEY_SELECTION );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_change_grab( CoreWindow       *window,\n                        CoreWMGrabTarget  target,\n                        bool              grab )\n{\n     DFBResult        ret;\n     CoreWMGrab       wmgrab;\n     CoreWindowStack *stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n\n     stack = window->stack;\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     wmgrab.target = target;\n\n     if (grab)\n         ret = dfb_wm_grab( window, &wmgrab );\n     else\n         ret = dfb_wm_ungrab( window, &wmgrab );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_grab_key( CoreWindow                 *window,\n                     DFBInputDeviceKeySymbol     symbol,\n                     DFBInputDeviceModifierMask  modifiers )\n{\n     DFBResult        ret;\n     CoreWMGrab       grab;\n     CoreWindowStack *stack = window->stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     grab.target    = CWMGT_KEY;\n     grab.symbol    = symbol;\n     grab.modifiers = modifiers;\n\n     ret = dfb_wm_grab( window, &grab );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_ungrab_key( CoreWindow                 *window,\n                       DFBInputDeviceKeySymbol     symbol,\n                       DFBInputDeviceModifierMask  modifiers )\n{\n     DFBResult        ret;\n     CoreWMGrab       grab;\n     CoreWindowStack *stack = window->stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     grab.target    = CWMGT_KEY;\n     grab.symbol    = symbol;\n     grab.modifiers = modifiers;\n\n     ret = dfb_wm_ungrab( window, &grab );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nstatic bool\ncore_window_filter( CoreWindow           *window,\n                    const DFBWindowEvent *event )\n{\n     D_MAGIC_ASSERT( window, CoreWindow );\n\n     switch (event->type) {\n          case DWET_GOTFOCUS:\n               D_FLAGS_SET( window->flags, CWF_FOCUSED );\n               break;\n\n          case DWET_LOSTFOCUS:\n               D_FLAGS_CLEAR( window->flags, CWF_FOCUSED );\n               break;\n\n          case DWET_ENTER:\n               D_FLAGS_SET( window->flags, CWF_ENTERED );\n               break;\n\n          case DWET_LEAVE:\n               D_FLAGS_CLEAR( window->flags, CWF_ENTERED );\n               break;\n\n          default:\n               break;\n     }\n\n     return false;\n}\n\nvoid\ndfb_window_post_event( CoreWindow     *window,\n                       DFBWindowEvent *event )\n{\n     D_MAGIC_ASSERT( window, CoreWindow );\n     D_ASSERT( event != NULL );\n\n     D_ASSUME( !DFB_WINDOW_DESTROYED( window ) || event->type == DWET_DESTROYED );\n\n     switch (event->type) {\n          case DWET_BUTTONDOWN:\n          case DWET_BUTTONUP:\n               D_DEBUG_AT( Core_Windows_Events, \"%s( %p [%u] )\\n\", __FUNCTION__, window, window->object.id );\n               D_DEBUG_AT( Core_Windows_Events, \"  -> TYPE    0x%08x\\n\", event->type );\n               D_DEBUG_AT( Core_Windows_Events, \"  -> BUTTON%s\\n\", event->type == DWET_BUTTONDOWN ? \"DOWN\" : \"UP\" );\n               D_DEBUG_AT( Core_Windows_Events, \"      => button  %u\\n\", event->button );\n               D_DEBUG_AT( Core_Windows_Events, \"      => x, y    %d,%d\\n\", event->x, event->y );\n               D_DEBUG_AT( Core_Windows_Events, \"      => cx, cy  %d,%d\\n\", event->cx, event->cy );\n               break;\n\n          default:\n               break;\n     }\n\n     if (!(event->type & window->config.events))\n          return;\n\n     long long timestamp_us = direct_clock_get_abs_micros();\n\n     event->clazz             = DFEC_WINDOW;\n     event->window_id         = window->id;\n     event->timestamp.tv_sec  = timestamp_us / 1000000;\n     event->timestamp.tv_usec = timestamp_us % 1000000;\n\n     if (!core_window_filter( window, event ))\n          dfb_window_dispatch( window, event, dfb_window_globals );\n}\n\nDFBResult\ndfb_window_send_configuration( CoreWindow *window )\n{\n     DFBWindowEvent event;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n\n     D_ASSUME( !DFB_WINDOW_DESTROYED( window ) );\n\n     event.type = DWET_POSITION_SIZE;\n     event.x    = window->config.bounds.x;\n     event.y    = window->config.bounds.y;\n     event.w    = window->config.bounds.w;\n     event.h    = window->config.bounds.h;\n\n     dfb_window_post_event( window, &event );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_window_request_focus( CoreWindow *window )\n{\n     DFBResult        ret;\n     CoreWindowStack *stack = window->stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     ret = dfb_wm_request_focus( window );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_window_set_rotation( CoreWindow *window,\n                         int         rotation )\n{\n     DFBResult        ret;\n     CoreWindowStack *stack = window->stack;\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n     D_MAGIC_ASSERT( window->stack, CoreWindowStack );\n\n     stack = window->stack;\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Never call WM after destroying the window. */\n     if (DFB_WINDOW_DESTROYED( window )) {\n          dfb_windowstack_unlock( stack );\n          return DFB_DESTROYED;\n     }\n\n     /* Do nothing if the rotation didn't change. */\n     if (window->config.rotation != rotation) {\n          CoreWindowConfig config;\n\n          switch (rotation) {\n               case 0:\n               case 90:\n               case 180:\n               case 270:\n                    config.rotation = rotation;\n                    dfb_wm_set_window_config( window, &config, DWCONF_ROTATION );\n                    break;\n\n               default:\n                    ret = DFB_UNSUPPORTED;\n          }\n     }\n     else\n          ret = DFB_OK;\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n"
  },
  {
    "path": "src/core/windows.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__WINDOWS_H__\n#define __CORE__WINDOWS_H__\n\n#include <core/coretypes.h>\n#include <directfb_windows.h>\n#include <fusion/object.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CWF_NONE        = 0x00000000,\n\n     CWF_INITIALIZED = 0x00000001,\n     CWF_FOCUSED     = 0x00000002,\n     CWF_ENTERED     = 0x00000004,\n     CWF_DESTROYED   = 0x00000008,\n     CWF_INSERTED    = 0x00000010,\n\n     CWF_ALL         = 0x0000001F\n} CoreWindowFlags;\n\n#define DFB_WINDOW_INITIALIZED(w) ((w)->flags & CWF_INITIALIZED)\n#define DFB_WINDOW_FOCUSED(w)     ((w)->flags & CWF_FOCUSED)\n#define DFB_WINDOW_ENTERED(w)     ((w)->flags & CWF_ENTERED)\n#define DFB_WINDOW_DESTROYED(w)   ((w)->flags & CWF_DESTROYED)\n#define DFB_WINDOW_INSERTED(w)    ((w)->flags & CWF_INSERTED)\n\nstruct __DFB_CoreWindowConfig {\n     DFBRectangle             bounds;\n     int                      opacity;\n     DFBWindowStackingClass   stacking;\n     DFBWindowOptions         options;\n     DFBWindowEventType       events;\n     DFBColor                 color;\n     u32                      color_key;\n     DFBRegion                opaque;\n     int                      z;\n     DFBWindowKeySelection    key_selection;\n     DFBInputDeviceKeySymbol *keys;\n     unsigned int             num_keys;\n     DFBWindowGeometry        src_geometry;\n     DFBWindowGeometry        dst_geometry;\n     int                      rotation;\n     DFBWindowID              association;\n     unsigned long            application_id;\n     DFBWindowCursorFlags     cursor_flags;\n     DFBDimension             cursor_resolution;\n     DFBWindowTypeHint        type_hint;\n     DFBWindowHintFlags       hint_flags;\n};\n\nstruct __DFB_CoreWindow {\n     FusionObject            object;\n\n     int                     magic;\n\n     DFBWindowID             id;                     /* window id */\n\n     CoreWindowFlags         flags;                  /* state flags */\n\n     DFBWindowCapabilities   caps;                   /* window capabilities, to enable blending etc. */\n\n     CoreWindowConfig        config;                 /* current window configuration. */\n\n     CoreSurface            *surface;                /* backing store surface */\n\n     CoreWindowStack        *stack;                  /* window stack the window belongs */\n\n     CoreLayerRegion        *primary_region;         /* default region of context */\n\n     CoreLayerRegion        *region;                 /* hardware allocated window */\n\n     void                   *window_data;            /* private data of window manager */\n\n     DirectLink             *bound_windows;          /* list of bound windows */\n     CoreWindow             *boundto;                /* window to which this window is bound (window binding) */\n\n     DFBWindowID             toplevel_id;            /* toplevel window id, in case of a sub window */\n     CoreWindow             *toplevel;               /* top level window */\n     FusionVector            subwindows;             /* list of sub windows (only valid for top level windows) */\n\n     CoreWindow             *subfocus;               /* which of the sub windows has the focus */\n\n     unsigned long           resource_id;            /* resource id */\n\n     FusionCall              call;                   /* dispatch */\n\n     struct {\n          int                hot_x;                  /* x position of cursor hot spot */\n          int                hot_y;                  /* y position of cursor hot spot */\n          CoreSurface       *surface;                /* cursor shape surface */\n     } cursor;\n\n     DFBWindowCapabilities   requested_caps;         /* original caps from application upon window creation */\n\n     CoreSurfaceClient      *surface_client;         /* surface client */\n     Reaction                surface_event_reaction; /* surface event reaction for CSCH_EVENT */\n     u32                     surface_flip_count;     /* surface flip count */\n\n     DFBWindowSurfacePolicy  policy;                 /* window surface swapping policy */\n};\n\n/**********************************************************************************************************************/\n\n#define TRANSLUCENT_WINDOW(w) ((w)->config.opacity < 0xff || \\\n                               (w)->config.options & (DWOP_ALPHACHANNEL | DWOP_COLORKEYING))\n\n#define VISIBLE_WINDOW(w)     (!((w)->caps & DWCAPS_INPUTONLY) && \\\n                               (w)->config.opacity > 0 && !DFB_WINDOW_DESTROYED((w)))\n\n/**********************************************************************************************************************/\n\n/*\n * Creates a pool of window objects.\n */\nFusionObjectPool *dfb_window_pool_create       ( const FusionWorld              *world );\n\n/*\n * Generates dfb_window_ref(), dfb_window_attach() etc.\n */\nFUSION_OBJECT_METHODS( CoreWindow, dfb_window )\n\n/**********************************************************************************************************************/\n\n/*\n * Create a region and configure it optionally using the passed window_surface.\n */\nDFBResult         dfb_window_create_region     ( CoreWindow                     *window,\n                                                 CoreLayerContext               *context,\n                                                 CoreSurface                    *window_surface,\n                                                 DFBSurfacePixelFormat           format,\n                                                 DFBSurfaceColorSpace            colorspace,\n                                                 DFBSurfaceCapabilities          surface_caps,\n                                                 CoreLayerRegion               **ret_region,\n                                                 CoreSurface                   **ret_surface );\n\n/*\n * Create a window on a given stack.\n */\nDFBResult         dfb_window_create            ( CoreWindowStack                *stack,\n                                                 const DFBWindowDescription     *desc,\n                                                 CoreWindow                    **ret_window );\n\n/*\n * Deinitialize a window and remove it from the window stack.\n */\nvoid              dfb_window_destroy           ( CoreWindow                     *window );\n\n/*\n * Change stacking class.\n */\nDFBResult         dfb_window_change_stacking   ( CoreWindow                     *window,\n                                                 DFBWindowStackingClass          stacking );\n\n/*\n * Set window type hint.\n */\nDFBResult         dfb_window_set_type_hint     ( CoreWindow                     *window,\n                                                 DFBWindowTypeHint               type_hint );\n\n/*\n * Change window hint flags.\n */\nDFBResult         dfb_window_change_hint_flags ( CoreWindow                     *window,\n                                                 DFBWindowHintFlags              clear,\n                                                 DFBWindowHintFlags              set );\n\n/*\n * Move a window up one step in window stack.\n */\nDFBResult         dfb_window_raise             ( CoreWindow                     *window );\n\n/*\n * Move a window down one step in window stack.\n */\nDFBResult         dfb_window_lower             ( CoreWindow                     *window );\n\n/*\n * Make a window the first (topmost) window in the window stack.\n */\nDFBResult         dfb_window_raisetotop        ( CoreWindow                     *window );\n\n/*\n * Make a window the last (downmost) window in the window stack.\n */\nDFBResult         dfb_window_lowertobottom     ( CoreWindow                     *window );\n\n/*\n * Stack a window on top of another one.\n */\nDFBResult         dfb_window_putatop           ( CoreWindow                     *window,\n                                                 CoreWindow                     *lower );\n\n/*\n * Stack a window below another one.\n */\nDFBResult         dfb_window_putbelow          ( CoreWindow                     *window,\n                                                 CoreWindow                     *upper );\n\n/*\n * Change window configuration.\n */\nDFBResult         dfb_window_set_config        ( CoreWindow                     *window,\n                                                 const CoreWindowConfig         *config,\n                                                 DFBWindowConfigFlags            flags );\n\n/*\n * Change window cursor.\n */\nDFBResult         dfb_window_set_cursor_shape  ( CoreWindow                     *window,\n                                                 CoreSurface                    *shape,\n                                                 int                             hot_x,\n                                                 int                             hot_y );\n\n/*\n * Move a window relative to its current position.\n */\nDFBResult         dfb_window_move              ( CoreWindow                     *window,\n                                                 int                             x,\n                                                 int                             y,\n                                                 bool                            relative );\n\n/*\n * Set window position and size.\n */\nDFBResult         dfb_window_set_bounds        ( CoreWindow                     *window,\n                                                 int                             x,\n                                                 int                             y,\n                                                 int                             width,\n                                                 int                             height );\n\n/*\n * Resize a window.\n */\nDFBResult         dfb_window_resize            ( CoreWindow                     *window,\n                                                 int                             width,\n                                                 int                             height );\n\n/*\n * Bind a window to this window.\n */\nDFBResult         dfb_window_bind              ( CoreWindow                     *window,\n                                                 CoreWindow                     *source,\n                                                 int                             x,\n                                                 int                             y );\n\n/*\n * Unbind a window from this window.\n */\nDFBResult         dfb_window_unbind            ( CoreWindow                     *window,\n                                                 CoreWindow                     *source );\n\n/*\n * Set window color.\n */\nDFBResult         dfb_window_set_color         ( CoreWindow                     *window,\n                                                 DFBColor                        color );\n\n/*\n * Set window color key.\n */\nDFBResult         dfb_window_set_colorkey      ( CoreWindow                     *window,\n                                                 u32                             color_key );\n\n/*\n * Set window global alpha factor.\n */\nDFBResult         dfb_window_set_opacity       ( CoreWindow                     *window,\n                                                 u8                              opacity );\n\n/*\n * Set window options.\n */\nDFBResult         dfb_window_change_options    ( CoreWindow                     *window,\n                                                 DFBWindowOptions                disable,\n                                                 DFBWindowOptions                enable );\n\n/*\n * Disable alpha channel blending for one region of a window.\n */\nDFBResult         dfb_window_set_opaque        ( CoreWindow                     *window,\n                                                 const DFBRegion                *region );\n\n/*\n * Manipulate the window event mask.\n */\nDFBResult         dfb_window_change_events     ( CoreWindow                     *window,\n                                                 DFBWindowEventType              disable,\n                                                 DFBWindowEventType              enable );\n\n/*\n * Select a mode for filtering keys on a focused window.\n */\nDFBResult         dfb_window_set_key_selection ( CoreWindow                     *window,\n                                                 DFBWindowKeySelection           selection,\n                                                 const DFBInputDeviceKeySymbol  *keys,\n                                                 unsigned int                    num_keys );\n\n/*\n * Enable/disable a grabbing target of a window.\n */\nDFBResult         dfb_window_change_grab       ( CoreWindow                     *window,\n                                                 CoreWMGrabTarget                target,\n                                                 bool                            grab );\n\n/*\n * Grab a specific key for this window.\n */\nDFBResult         dfb_window_grab_key          ( CoreWindow                     *window,\n                                                 DFBInputDeviceKeySymbol         symbol,\n                                                 DFBInputDeviceModifierMask      modifiers );\n\n/*\n * Ungrab a specific key for this window.\n */\nDFBResult         dfb_window_ungrab_key        ( CoreWindow                     *window,\n                                                 DFBInputDeviceKeySymbol         symbol,\n                                                 DFBInputDeviceModifierMask      modifiers );\n\n/*\n * Post an event.\n */\nvoid              dfb_window_post_event        ( CoreWindow                     *window,\n                                                 DFBWindowEvent                 *event );\n\n/*\n * Post a DWET_POSITION_SIZE event to request configuration.\n */\nDFBResult         dfb_window_send_configuration( CoreWindow                     *window );\n\n/*\n * Request a window to gain focus.\n */\nDFBResult         dfb_window_request_focus     ( CoreWindow                     *window );\n\n/*\n * Set window rotation.\n */\nDFBResult         dfb_window_set_rotation      ( CoreWindow                     *window,\n                                                 int                             rotation );\n\n/**********************************************************************************************************************/\n\nstatic __inline__ void\ndfb_surface_caps_apply_policy( DFBWindowSurfacePolicy  policy,\n                               DFBSurfaceCapabilities *caps )\n{\n     switch (policy) {\n          case DWSP_SYSTEMONLY:\n               *caps = (DFBSurfaceCapabilities) ((*caps & ~DSCAPS_VIDEOONLY) | DSCAPS_SYSTEMONLY);\n               break;\n\n          case DWSP_VIDEOONLY:\n               *caps = (DFBSurfaceCapabilities) ((*caps & ~DSCAPS_SYSTEMONLY) | DSCAPS_VIDEOONLY);\n               break;\n\n          default:\n               *caps = (DFBSurfaceCapabilities) (*caps & ~(DSCAPS_SYSTEMONLY | DSCAPS_VIDEOONLY));\n               break;\n     }\n}\n\n#endif\n"
  },
  {
    "path": "src/core/windowstack.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <config.h>\n#include <core/CoreWindowStack.h>\n#include <core/core.h>\n#include <core/cursor.h>\n#include <core/input.h>\n#include <core/layers.h>\n#include <core/layer_context.h>\n#include <core/windows.h>\n#include <core/windowstack.h>\n#include <core/wm.h>\n#include <direct/memcpy.h>\n#include <fusion/shmalloc.h>\n#include <gfx/util.h>\n\nD_DEBUG_DOMAIN( Core_WindowStack, \"Core/WindowStack\", \"DirectFB Core WindowStack\" );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     DirectLink  link;\n     void       *ctx;\n} Stack_Container;\n\ntypedef struct {\n     DirectLink       link;\n\n     DFBInputDeviceID id;\n     Reaction         reaction;\n} StackDevice;\n\nstatic DirectLink  *stack_containers      = NULL;\nstatic DirectMutex  stack_containers_lock = DIRECT_MUTEX_INITIALIZER();\n\nstatic void\nstack_containers_add( CoreWindowStack *stack )\n{\n     Stack_Container *container;\n\n     D_DEBUG_AT( Core_WindowStack, \"%s()\\n\", __FUNCTION__ );\n\n     direct_mutex_lock( &stack_containers_lock );\n\n     container = D_CALLOC( 1, sizeof(Stack_Container) );\n     if (!container) {\n          D_OOM();\n     }\n\n     container->ctx = stack;\n\n     direct_list_append( &stack_containers, &container->link );\n\n     direct_mutex_unlock( &stack_containers_lock );\n}\n\nstatic void\nstack_containers_remove( CoreWindowStack *stack )\n{\n     Stack_Container *container, *next;\n\n     D_DEBUG_AT( Core_WindowStack, \"%s()\\n\", __FUNCTION__ );\n\n     direct_mutex_lock( &stack_containers_lock );\n\n     direct_list_foreach_safe (container, next, stack_containers) {\n          if (stack == container->ctx) {\n               direct_list_remove( &stack_containers, &container->link );\n               D_FREE( container );\n          }\n     }\n\n     direct_mutex_unlock( &stack_containers_lock );\n}\n\nstatic DFBEnumerationResult\nstack_attach_device( CoreInputDevice *device,\n                     void            *ctx )\n{\n     StackDevice     *dev;\n     CoreWindowStack *stack = ctx;\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n\n     dev = SHCALLOC( stack->shmpool, 1, sizeof(StackDevice) );\n     if (!dev) {\n          D_ERROR( \"Core/WindowStack: Could not allocate \"_ZU\" bytes!\\n\", sizeof(StackDevice) );\n          return DFENUM_CANCEL;\n     }\n\n     dev->id = dfb_input_device_id( device );\n\n     direct_list_prepend( &stack->devices, &dev->link );\n\n     dfb_input_attach( device, _dfb_windowstack_inputdevice_listener, ctx, &dev->reaction );\n\n     return DFENUM_OK;\n}\n\nvoid\nstack_containers_attach_device( CoreInputDevice *device )\n{\n     Stack_Container *stack_container;\n\n     D_DEBUG_AT( Core_WindowStack, \"%s()\\n\", __FUNCTION__ );\n\n     direct_mutex_lock( &stack_containers_lock );\n\n     direct_list_foreach (stack_container, stack_containers) {\n          stack_attach_device( device, stack_container->ctx );\n     }\n\n     direct_mutex_unlock( &stack_containers_lock );\n}\n\nstatic DFBEnumerationResult\nstack_detach_device( CoreInputDevice *device,\n                     void            *ctx )\n{\n     DirectLink      *link;\n     CoreWindowStack *stack = ctx;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( device != NULL );\n\n     link = stack->devices;\n\n     while (link) {\n          DirectLink  *next = link->next;\n          StackDevice *dev  = (StackDevice*) link;\n\n          if (dfb_input_device_id( device ) == dev->id) {\n               direct_list_remove( &stack->devices, &dev->link );\n\n               dfb_input_detach( device, &dev->reaction );\n\n               SHFREE( stack->shmpool, dev );\n\n               return DFENUM_OK;\n          }\n\n          link = next;\n     }\n\n     return DFENUM_CANCEL;\n}\n\nvoid\nstack_containers_detach_device( CoreInputDevice *device )\n{\n     Stack_Container *stack_container;\n\n     D_DEBUG_AT( Core_WindowStack, \"%s()\\n\", __FUNCTION__ );\n\n     direct_mutex_lock( &stack_containers_lock );\n\n     direct_list_foreach (stack_container, stack_containers) {\n          stack_detach_device( device, stack_container->ctx );\n     }\n\n     direct_mutex_unlock( &stack_containers_lock );\n}\n\n/**********************************************************************************************************************/\n\nCoreWindowStack*\ndfb_windowstack_create( CoreLayerContext *context )\n{\n     DFBResult               ret;\n     CoreWindowStack        *stack;\n     CoreLayer              *layer;\n     DFBWindowSurfacePolicy  policy = DWSP_SYSTEMONLY;\n\n     D_DEBUG_AT( Core_WindowStack, \"%s( %p )\\n\", __FUNCTION__, context );\n\n     D_ASSERT( context != NULL );\n\n     layer = dfb_layer_at( context->layer_id );\n\n     /* Allocate window stack data (completely shared). */\n     stack = SHCALLOC( context->shmpool, 1, sizeof(CoreWindowStack) );\n     if (!stack) {\n          D_OOSHM();\n          return NULL;\n     }\n\n     stack->shmpool = context->shmpool;\n\n     /* Store context which we belong to. */\n     stack->context = context;\n\n     /* Set default acceleration. */\n     stack->cursor.numerator   = 2;\n     stack->cursor.denominator = 1;\n     stack->cursor.threshold   = 4;\n\n     /* Choose cursor surface policy. */\n     if (context->config.buffermode != DLBM_BACKSYSTEM) {\n          CardCapabilities card_caps;\n\n          /* Use the explicitly specified policy. */\n          if (dfb_config->window_policy != -1)\n               policy = dfb_config->window_policy;\n          else {\n               /* Examine the hardware capabilities. */\n               dfb_gfxcard_get_capabilities( &card_caps );\n\n               if (card_caps.accel & DFXL_BLIT && card_caps.blitting & DSBLIT_BLEND_ALPHACHANNEL)\n                    policy = DWSP_VIDEOHIGH;\n          }\n     }\n\n     stack->cursor.policy = policy;\n\n     /* Set default background mode. */\n     stack->bg.mode        = DLBM_DONTCARE;\n     stack->bg.color_index = -1;\n\n     D_MAGIC_SET( stack, CoreWindowStack );\n\n     /* Initialize window manager */\n     ret = dfb_wm_init_stack( stack );\n     if (ret) {\n          D_MAGIC_CLEAR( stack );\n          SHFREE( context->shmpool, stack );\n          return NULL;\n     }\n\n     if (dfb_config->single_window)\n          fusion_vector_init( &stack->visible_windows, 23, stack->shmpool );\n\n     /* Attach to all input devices. */\n     dfb_input_enumerate_devices( stack_attach_device, stack, DICAPS_ALL );\n\n     stack_containers_add( stack );\n\n     CoreWindowStack_Init_Dispatch( layer->core, stack, &stack->call );\n\n     D_DEBUG_AT( Core_WindowStack, \"  -> %p\\n\", stack );\n\n     return stack;\n}\n\nvoid\ndfb_windowstack_detach_devices( CoreWindowStack *stack )\n{\n     DirectLink *link;\n\n     D_DEBUG_AT( Core_WindowStack, \"%s( %p )\\n\", __FUNCTION__, stack );\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n\n     stack_containers_remove( stack );\n\n     link = stack->devices;\n\n     while (link) {\n          DirectLink  *next   = link->next;\n          StackDevice *device = (StackDevice*) link;\n\n          dfb_input_detach( dfb_input_device_at( device->id ), &device->reaction );\n\n          SHFREE( stack->shmpool, device );\n\n          link = next;\n     }\n}\n\nvoid\ndfb_windowstack_destroy( CoreWindowStack *stack )\n{\n     D_DEBUG_AT( Core_WindowStack, \"%s( %p )\\n\", __FUNCTION__, stack );\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n\n     /* Unlink cursor surface. */\n     if (stack->cursor.surface)\n          dfb_surface_unlink( &stack->cursor.surface );\n\n     /* Shutdown window manager. */\n     if (stack->flags & CWSF_INITIALIZED)\n          dfb_wm_close_stack( stack );\n\n     /* Detach listener from background surface and unlink it. */\n     if (stack->bg.image) {\n          dfb_surface_detach_global( stack->bg.image, &stack->bg.image_reaction );\n\n          dfb_surface_unlink( &stack->bg.image );\n     }\n\n     CoreWindowStack_Deinit_Dispatch( &stack->call );\n\n     /* Deallocate shared stack data. */\n     if (stack->stack_data) {\n          SHFREE( stack->shmpool, stack->stack_data );\n          stack->stack_data = NULL;\n     }\n\n     D_MAGIC_CLEAR( stack );\n\n     /* Free stack data. */\n     SHFREE( stack->shmpool, stack );\n}\n\nvoid\ndfb_windowstack_resize( CoreWindowStack *stack,\n                        int              width,\n                        int              height,\n                        int              rotation )\n{\n     D_DEBUG_AT( Core_WindowStack, \"%s( %p, %dx%d, %d )\\n\", __FUNCTION__, stack, width, height, rotation );\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return;\n\n     /* Store the width and height of the stack. */\n     stack->width    = width;\n     stack->height   = height;\n\n     /* Store the rotation of the stack. */\n     stack->rotation = rotation;\n\n     switch (stack->rotation) {\n          default:\n               D_BUG( \"invalid rotation %d\", stack->rotation );\n          case 0:\n               stack->rotated_blit   = DSBLIT_NOFX;\n               stack->rotated_width  = stack->width;\n               stack->rotated_height = stack->height;\n               break;\n\n          case 90:\n               stack->rotated_blit   = DSBLIT_ROTATE90;\n               stack->rotated_width  = stack->height;\n               stack->rotated_height = stack->width;\n               break;\n\n          case 180:\n               stack->rotated_blit   = DSBLIT_ROTATE180;\n               stack->rotated_width  = stack->width;\n               stack->rotated_height = stack->height;\n               break;\n\n          case 270:\n               stack->rotated_blit   = DSBLIT_ROTATE270;\n               stack->rotated_width  = stack->height;\n               stack->rotated_height = stack->width;\n               break;\n     }\n\n     /* Setup new cursor clipping region. */\n     stack->cursor.region.x1 = 0;\n     stack->cursor.region.y1 = 0;\n     stack->cursor.region.x2 = width - 1;\n     stack->cursor.region.y2 = height - 1;\n\n     /* Notify the window manager. */\n     dfb_wm_resize_stack( stack, width, height );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n}\n\nDirectResult\ndfb_windowstack_lock( CoreWindowStack *stack )\n{\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( stack->context != NULL );\n\n     return dfb_layer_context_lock( stack->context );\n}\n\nDirectResult\ndfb_windowstack_unlock( CoreWindowStack *stack )\n{\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( stack->context != NULL );\n\n     return dfb_layer_context_unlock( stack->context );\n}\n\nDFBResult\ndfb_windowstack_repaint_all( CoreWindowStack *stack )\n{\n     DFBResult ret;\n     DFBRegion region;\n\n     D_DEBUG_AT( Core_WindowStack, \"%s( %p )\\n\", __FUNCTION__, stack );\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     region.x1 = 0;\n     region.y1 = 0;\n     region.x2 = stack->rotated_width  - 1;\n     region.y2 = stack->rotated_height - 1;\n\n     ret = dfb_wm_update_stack( stack, &region, 0 );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return ret;\n}\n\nDFBResult\ndfb_windowstack_set_background_mode ( CoreWindowStack               *stack,\n                                      DFBDisplayLayerBackgroundMode  mode )\n{\n     D_DEBUG_AT( Core_WindowStack, \"%s( %p, %u )\\n\", __FUNCTION__, stack, mode );\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Nothing to do if mode is the same. */\n     if (mode != stack->bg.mode) {\n          /* A surface is required for DLBM_IMAGE and DLBM_TILE modes. */\n          if ((mode == DLBM_IMAGE || mode == DLBM_TILE) && !stack->bg.image) {\n               dfb_windowstack_unlock( stack );\n               return DFB_MISSINGIMAGE;\n          }\n\n          /* Set new mode. */\n          stack->bg.mode = mode;\n\n          /* Force an update of the window stack. */\n          if (mode != DLBM_DONTCARE)\n               dfb_windowstack_repaint_all( stack );\n     }\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_windowstack_set_background_image( CoreWindowStack *stack,\n                                      CoreSurface     *image )\n{\n     D_DEBUG_AT( Core_WindowStack, \"%s( %p, %p )\\n\", __FUNCTION__, stack, image );\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( image != NULL );\n\n     if (!(image->type & CSTF_SHARED))\n          return DFB_INVARG;\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Nothing to do if image is the same. */\n     if (stack->bg.image != image) {\n          /* Detach listener from old surface and unlink it. */\n          if (stack->bg.image) {\n               dfb_surface_detach_global( stack->bg.image, &stack->bg.image_reaction );\n\n               dfb_surface_unlink( &stack->bg.image );\n          }\n\n          /* Link surface object. */\n          dfb_surface_link( &stack->bg.image, image );\n\n          /* Attach listener to new surface. */\n          dfb_surface_attach_global( image, DFB_WINDOWSTACK_BACKGROUND_IMAGE_LISTENER, stack,\n                                     &stack->bg.image_reaction );\n     }\n\n     /* Force an update of the window stack. */\n     if (stack->bg.mode == DLBM_IMAGE || stack->bg.mode == DLBM_TILE)\n          dfb_windowstack_repaint_all( stack );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_windowstack_set_background_color( CoreWindowStack *stack,\n                                      const DFBColor  *color )\n{\n     D_DEBUG_AT( Core_WindowStack, \"%s( %p )\\n\", __FUNCTION__, stack );\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( color != NULL );\n\n     D_DEBUG_AT( Core_WindowStack, \"  -> 0x%02x%02x%02x%02x\\n\", color->a, color->r, color->g, color->b );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Nothing to do if color is the same. */\n     if (!DFB_COLOR_EQUAL( stack->bg.color, *color )) {\n          /* Set new color. */\n          stack->bg.color = *color;\n\n          /* Force an update of the window stack. */\n          if (stack->bg.mode == DLBM_COLOR)\n               dfb_windowstack_repaint_all( stack );\n     }\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_windowstack_set_background_color_index( CoreWindowStack *stack,\n                                            int              index )\n{\n     D_DEBUG_AT( Core_WindowStack, \"%s( %p, %d )\\n\", __FUNCTION__, stack, index );\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     /* Nothing to do if color is the same. */\n     if (stack->bg.color_index != index) {\n          /* Set new color index. */\n          stack->bg.color_index = index;\n\n          /* Force an update of the window stack. */\n          if (stack->bg.mode == DLBM_COLOR)\n               dfb_windowstack_repaint_all( stack );\n     }\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ncreate_cursor_surface( CoreWindowStack *stack,\n                       int              width,\n                       int              height )\n{\n     DFBResult               ret;\n     CoreSurface            *surface;\n     CoreLayer              *layer;\n     CoreLayerContext       *context;\n     DFBSurfaceCapabilities  surface_caps = DSCAPS_PREMULTIPLIED;\n\n     D_DEBUG_AT( Core_WindowStack, \"%s( %p, %dx%d )\\n\", __FUNCTION__, stack, width, height );\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( stack->context != NULL );\n     D_ASSERT( stack->cursor.surface == NULL );\n\n     context = stack->context;\n\n     layer = dfb_layer_at( context->layer_id );\n\n     D_ASSERT( layer != NULL );\n\n     stack->cursor.x       = stack->width  / 2;\n     stack->cursor.y       = stack->height / 2;\n     stack->cursor.hot.x   = 0;\n     stack->cursor.hot.y   = 0;\n     stack->cursor.size.w  = width;\n     stack->cursor.size.h  = height;\n     stack->cursor.opacity = 0xff;\n\n     if (context->config.buffermode == DLBM_WINDOWS)\n          D_WARN( \"cursor not yet visible with DLBM_WINDOWS\" );\n\n     if (dfb_config->cursor_videoonly)\n          surface_caps |= DSCAPS_VIDEOONLY;\n\n     dfb_surface_caps_apply_policy( stack->cursor.policy, &surface_caps );\n\n     /* Create the cursor surface. */\n     ret = dfb_surface_create_simple( layer->core, width, height, DSPF_ARGB, DSCS_RGB, surface_caps,\n                                      CSTF_SHARED | CSTF_CURSOR, dfb_config->cursor_resource_id, NULL, &surface );\n     if (ret) {\n          D_ERROR( \"Core/WindowStack: Failed to create surface for software cursor!\\n\" );\n          return ret;\n     }\n\n     dfb_surface_globalize( surface );\n\n     stack->cursor.surface = surface;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nload_default_cursor( CoreWindowStack *stack )\n{\n     DFBResult              ret;\n     int                    i, j;\n     CoreSurfaceBufferLock  lock;\n     void                  *data;\n     u32                   *tmp_data;\n\n     D_DEBUG_AT( Core_WindowStack, \"%s( %p )\\n\", __FUNCTION__, stack );\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n\n     if (!stack->cursor.surface) {\n          /* Create the cursor surface for the default shape. */\n          ret = create_cursor_surface( stack, 40, 40 );\n          if (ret)\n               return ret;\n     }\n     else {\n          stack->cursor.hot.x  = 0;\n          stack->cursor.hot.y  = 0;\n          stack->cursor.size.w = 40;\n          stack->cursor.size.h = 40;\n     }\n\n     /* Lock the cursor surface. */\n     ret = dfb_surface_lock_buffer( stack->cursor.surface, DSBR_BACK, CSAID_CPU, CSAF_WRITE, &lock );\n     if (ret) {\n          D_ERROR( \"Core/WindowStack: cannot lock the cursor surface!\\n\" );\n          return ret;\n     }\n\n     data = lock.addr;\n\n     /* Fill the cursor surface. */\n     direct_memcpy( data, cursor_data, 40 * lock.pitch );\n\n     for (i = 0; i < 40; i++) {\n#ifdef WORDS_BIGENDIAN\n          j = MIN( 40, lock.pitch / 4 );\n          tmp_data = data;\n\n          while (j--) {\n               *tmp_data = (*tmp_data & 0xff000000) >> 24 |\n                           (*tmp_data & 0x00ff0000) >>  8 |\n                           (*tmp_data & 0x0000ff00) <<  8 |\n                           (*tmp_data & 0x000000ff) << 24;\n               ++tmp_data;\n          }\n#endif\n          j = MIN( 40, lock.pitch / 4 );\n          tmp_data = data;\n\n          while (j--) {\n               u32 s = *tmp_data;\n               u32 a = (s >> 24) + 1;\n\n               *tmp_data = ((((s & 0x00ff00ff) * a) >> 8) & 0x00ff00ff) |\n                           ((((s & 0x0000ff00) * a) >> 8) & 0x0000ff00) |\n                              (s & 0xff000000);\n               ++tmp_data;\n          }\n\n          data += lock.pitch;\n     }\n\n     dfb_surface_unlock_buffer( stack->cursor.surface, &lock );\n\n     return ret;\n}\n\nDFBResult\ndfb_windowstack_cursor_enable( CoreWindowStack *stack,\n                               bool             enable )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( Core_WindowStack, \"%s( %p, %s )\\n\", __FUNCTION__, stack, enable ? \"enable\" : \"disable\" );\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     stack->cursor.set = true;\n\n     if (dfb_config->no_cursor || stack->cursor.enabled == enable) {\n          dfb_windowstack_unlock( stack );\n          return DFB_OK;\n     }\n\n     if (enable && !stack->cursor.surface) {\n          ret = load_default_cursor( stack );\n          if (ret) {\n               dfb_windowstack_unlock( stack );\n               return ret;\n          }\n     }\n\n     /* Keep state. */\n     stack->cursor.enabled = enable;\n\n     /* Notify WM. */\n     dfb_wm_update_cursor( stack, enable ? CCUF_ENABLE : CCUF_DISABLE );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_windowstack_cursor_set_opacity( CoreWindowStack *stack,\n                                    u8               opacity )\n{\n     D_DEBUG_AT( Core_WindowStack, \"%s( %p, 0x%02x )\\n\", __FUNCTION__, stack, opacity );\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     if (stack->cursor.opacity != opacity) {\n          /* Set new opacity. */\n          stack->cursor.opacity = opacity;\n\n          /* Notify WM. */\n          if (stack->cursor.enabled)\n               dfb_wm_update_cursor( stack, CCUF_OPACITY );\n     }\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_windowstack_cursor_set_shape( CoreWindowStack *stack,\n                                  CoreSurface     *shape,\n                                  int              hot_x,\n                                  int              hot_y )\n{\n     DFBResult             ret;\n     CoreCursorUpdateFlags flags = CCUF_SHAPE;\n\n     D_DEBUG_AT( Core_WindowStack, \"%s( %p, %p, %d, %d )\\n\", __FUNCTION__, stack, shape, hot_x, hot_y );\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n\n     if (dfb_config->no_cursor)\n          return DFB_OK;\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     if (!shape) {\n          if (stack->cursor.surface && (stack->cursor.size.w != 40 || stack->cursor.size.h != 40)) {\n               /* Resize the cursor surface to the size of the default shape. */\n               dfb_surface_reformat( stack->cursor.surface, 40, 40, DSPF_ARGB );\n\n               /* Notify about new size. */\n               flags |= CCUF_SIZE;\n          }\n     }\n     else if (!stack->cursor.surface) {\n          D_DEBUG_AT( Core_WindowStack, \"  -> size %dx%d\\n\", shape->config.size.w, shape->config.size.h );\n\n          D_ASSUME( !stack->cursor.enabled );\n\n          /* Create the cursor surface for the shape. */\n          ret = create_cursor_surface( stack, shape->config.size.w, shape->config.size.h );\n          if (ret) {\n               dfb_windowstack_unlock( stack );\n               return ret;\n          }\n     }\n     else if (stack->cursor.size.w != shape->config.size.w || stack->cursor.size.h != shape->config.size.h) {\n          D_DEBUG_AT( Core_WindowStack, \"  -> new size %dx%d\\n\", shape->config.size.w, shape->config.size.h );\n\n          /* Resize the cursor surface to the size of shape. */\n          dfb_surface_reformat( stack->cursor.surface, shape->config.size.w, shape->config.size.h, DSPF_ARGB );\n\n          stack->cursor.size.w = shape->config.size.w;\n          stack->cursor.size.h = shape->config.size.h;\n\n          /* Notify about new size. */\n          flags |= CCUF_SIZE;\n     }\n\n     if (stack->cursor.hot.x != hot_x || stack->cursor.hot.y != hot_y) {\n          stack->cursor.hot.x = hot_x;\n          stack->cursor.hot.y = hot_y;\n\n          /* Notify about new position. */\n          flags |= CCUF_POSITION;\n     }\n\n     if (!shape) {\n          /* Create the cursor surface if necessary and fill it with the default shape. */\n          load_default_cursor( stack );\n     }\n     else {\n          /* Copy the content of the new shape. */\n          dfb_gfx_copy_stereo( shape, DSSE_LEFT, stack->cursor.surface, DSSE_LEFT, NULL, 0, 0, false );\n\n          stack->cursor.surface->config.caps = (stack->cursor.surface->config.caps & ~DSCAPS_PREMULTIPLIED) |\n                                               (shape->config.caps & DSCAPS_PREMULTIPLIED);\n     }\n\n     /* Notify WM. */\n     if (stack->cursor.enabled)\n          dfb_wm_update_cursor( stack, flags );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_windowstack_cursor_warp( CoreWindowStack *stack,\n                             int              x,\n                             int              y )\n{\n     D_DEBUG_AT( Core_WindowStack, \"%s( %p, %d, %d )\\n\", __FUNCTION__, stack, x, y );\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     if (x < 0)\n          x = 0;\n     else if (x > stack->width - 1)\n          x = stack->width - 1;\n\n     if (y < 0)\n          y = 0;\n     else if (y > stack->height - 1)\n          y = stack->height - 1;\n\n     if (stack->cursor.x != x || stack->cursor.y != y) {\n          stack->cursor.x = x;\n          stack->cursor.y = y;\n\n          /* Notify WM. */\n          if (stack->cursor.enabled)\n               dfb_wm_update_cursor( stack, CCUF_POSITION );\n     }\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_windowstack_cursor_set_acceleration( CoreWindowStack *stack,\n                                         int              numerator,\n                                         int              denominator,\n                                         int              threshold )\n{\n     D_DEBUG_AT( Core_WindowStack, \"%s( %p, %d, %d, %d )\\n\", __FUNCTION__, stack, numerator, denominator, threshold );\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     stack->cursor.numerator   = numerator;\n     stack->cursor.denominator = denominator;\n     stack->cursor.threshold   = threshold;\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_windowstack_get_cursor_position( CoreWindowStack *stack,\n                                     int             *ret_x,\n                                     int             *ret_y )\n{\n     D_DEBUG_AT( Core_WindowStack, \"%s( %p, %p, %p )\\n\", __FUNCTION__, stack, ret_x, ret_y );\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n\n     D_ASSUME( ret_x != NULL || ret_y != NULL );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return DFB_FUSION;\n\n     if (ret_x)\n          *ret_x = stack->cursor.x;\n\n     if (ret_y)\n          *ret_y = stack->cursor.y;\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     return DFB_OK;\n}\n\nstatic void\nWindowStack_Input_Flush( CoreWindowStack *stack )\n{\n     if (!stack->motion_x.type && !stack->motion_y.type)\n          return;\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack ))\n          return;\n\n     /* Call the window manager to dispatch the event. */\n     if (dfb_layer_context_active( stack->context )) {\n          if (stack->motion_x.type && stack->motion_y.type)\n               stack->motion_x.flags |= DIEF_FOLLOW;\n\n          if (stack->motion_x.type)\n               dfb_wm_process_input( stack, &stack->motion_x );\n\n          if (stack->motion_y.type)\n               dfb_wm_process_input( stack, &stack->motion_y );\n     }\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     stack->motion_x.type = DIET_UNKNOWN;\n     stack->motion_y.type = DIET_UNKNOWN;\n\n     stack->motion_cleanup = NULL;\n     stack->motion_ts      = 0;\n}\n\nstatic void\nWindowStack_Input_AddAbsolute( CoreWindowStack     *stack,\n                               DFBInputEvent       *target,\n                               const DFBInputEvent *event )\n{\n     *target = *event;\n\n     target->flags &= ~DIEF_FOLLOW;\n}\n\nstatic void\nWindowStack_Input_AddRelative( CoreWindowStack     *stack,\n                               DFBInputEvent       *target,\n                               const DFBInputEvent *event )\n{\n     int axisrel = 0;\n\n     if (target->type)\n          axisrel = target->axisrel;\n\n     *target = *event;\n\n     target->axisrel += axisrel;\n     target->flags   &= ~DIEF_FOLLOW;\n}\n\nstatic void\nWindowStack_Input_Add( CoreWindowStack     *stack,\n                       const DFBInputEvent *event )\n{\n     long long ts = direct_clock_get_time( DIRECT_CLOCK_MONOTONIC );\n\n     if ((stack->motion_x.type && stack->motion_x.device_id != event->device_id) ||\n         (stack->motion_y.type && stack->motion_y.device_id != event->device_id) ||\n         ts - stack->motion_ts > 10000)\n          WindowStack_Input_Flush( stack );\n\n     if (!stack->motion_ts)\n          stack->motion_ts = ts;\n\n     switch (event->type) {\n          case DIET_AXISMOTION:\n               switch (event->axis) {\n                    case DIAI_X:\n                         if (event->flags & DIEF_AXISABS)\n                              WindowStack_Input_AddAbsolute( stack, &stack->motion_x, event );\n                         else\n                              WindowStack_Input_AddRelative( stack, &stack->motion_x, event );\n                         break;\n\n                    case DIAI_Y:\n                         if (event->flags & DIEF_AXISABS)\n                              WindowStack_Input_AddAbsolute( stack, &stack->motion_y, event );\n                         else\n                              WindowStack_Input_AddRelative( stack, &stack->motion_y, event );\n                         break;\n\n                    default:\n                         break;\n               }\n               break;\n\n          default:\n               break;\n     }\n}\n\nstatic void\nWindowStack_Input_DispatchCleanup( void *ctx )\n{\n     CoreWindowStack *stack = ctx;\n\n     WindowStack_Input_Flush( stack );\n\n     /* Decrease the layer context's reference count. */\n     dfb_layer_context_unref( stack->context );\n}\n\nReactionResult\n_dfb_windowstack_inputdevice_listener( const void *msg_data,\n                                       void       *ctx )\n{\n     DFBResult            ret;\n     const DFBInputEvent *event = msg_data;\n     CoreWindowStack     *stack = ctx;\n     int                  num = 0;\n\n     /* Dynamically increase/decrease the ref to the layer context when using the layer context.\n        This will prevent the layer context from being destroyed when it is being used. */\n\n     D_DEBUG_AT( Core_WindowStack, \"%s( %p, %p )\\n\", __FUNCTION__, event, stack );\n\n     D_ASSERT( event != NULL );\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n\n     /* Make sure the layer context's reference count is non-zero. If it is, return early and indicate that the listener\n        should be removed. In this scenario, this prevents the object_reference_watcher() from being called more than\n        once triggered by the reference count changing from 1 to 0 again. */\n     if (dfb_layer_context_ref_stat( stack->context, &num ) || num == 0)\n          return RS_REMOVE;\n\n     /* Increase the layer context's reference count. */\n     if (dfb_layer_context_ref( stack->context ))\n          return RS_REMOVE;\n\n     switch (event->type) {\n          case DIET_AXISMOTION:\n               switch (event->axis) {\n                    case DIAI_X:\n                    case DIAI_Y:\n                         WindowStack_Input_Add( stack, event );\n\n                         if (!stack->motion_cleanup) {\n                              ret = fusion_dispatch_cleanup_add( dfb_core_world( core_dfb ),\n                                                                 WindowStack_Input_DispatchCleanup, stack,\n                                                                 &stack->motion_cleanup );\n                              if (ret) {\n                                   D_DERROR( ret, \"Core/WindowStack: Failed to add dispatch cleanup!\\n\" );\n                                   dfb_layer_context_unref( stack->context );\n                                   return RS_OK;\n                              }\n                         }\n                         else\n                              dfb_layer_context_unref( stack->context );\n                         return RS_OK;\n\n                    default:\n                         break;\n               }\n               break;\n\n          default:\n               break;\n     }\n\n     WindowStack_Input_Flush( stack );\n\n     /* Lock the window stack. */\n     if (dfb_windowstack_lock( stack )) {\n          dfb_layer_context_unref( stack->context );\n          return RS_REMOVE;\n     }\n\n     /* Call the window manager to dispatch the event. */\n     if (dfb_layer_context_active( stack->context ))\n          dfb_wm_process_input( stack, event );\n\n     /* Unlock the window stack. */\n     dfb_windowstack_unlock( stack );\n\n     /* Decrease the layer context's reference count. */\n     if (!stack->motion_cleanup)\n          dfb_layer_context_unref( stack->context );\n\n     return RS_OK;\n}\n\nReactionResult\n_dfb_windowstack_background_image_listener( const void *msg_data,\n                                            void       *ctx )\n{\n     const CoreSurfaceNotification *notification = msg_data;\n     CoreWindowStack               *stack        = ctx;\n\n     D_DEBUG_AT( Core_WindowStack, \"%s( %p, %p )\\n\", __FUNCTION__, notification, stack );\n\n     D_ASSERT( notification != NULL );\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n\n     if (notification->flags & CSNF_DESTROY) {\n          D_ERROR( \"Core/WindowStack: Surface for background vanished!\\n\" );\n          return RS_REMOVE;\n     }\n\n     if (notification->flags & (CSNF_FLIP | CSNF_SIZEFORMAT))\n          dfb_windowstack_repaint_all( stack );\n\n     return RS_OK;\n}\n"
  },
  {
    "path": "src/core/windowstack.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__WINDOWSTACK_H__\n#define __CORE__WINDOWSTACK_H__\n\n#include <core/coretypes.h>\n#include <fusion/call.h>\n#include <fusion/fusion.h>\n#include <fusion/reactor.h>\n#include <fusion/vector.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     CWSF_NONE        = 0x00000000,\n\n     CWSF_INITIALIZED = 0x00000001,\n     CWSF_ACTIVATED   = 0x00000002,\n\n     CWSF_ALL         = 0x00000003\n} CoreWindowStackFlags;\n\nstruct __DFB_CoreWindowStack {\n     DirectLink                          link;\n\n     int                                 magic;\n\n     CoreLayerContext                   *context;         /* layer context */\n\n     int                                 width;           /* stack width */\n     int                                 height;          /* stack height */\n     int                                 rotation;        /* stack rotation */\n     int                                 rotated_width;   /* stack rotated width */\n     int                                 rotated_height;  /* stack rotated height */\n     DFBSurfaceBlittingFlags             rotated_blit;    /* stack rotated blitting flag */\n\n     DFBWindowID                         id_pool;         /* window id pool */\n\n     struct {\n          int                            enabled;         /* cursor enabled */\n          int                            x, y;            /* cursor position */\n          DFBDimension                   size;            /* cursor shape size */\n          DFBPoint                       hot;             /* cursor hot spot */\n          CoreSurface                   *surface;         /* cursor shape */\n          u8                             opacity;         /* cursor opacity */\n          DFBRegion                      region;          /* cursor is clipped by this region */\n\n          int                            numerator;       /* cursor acceleration factor numerator */\n          int                            denominator;     /* cursor acceleration factor denominator */\n          int                            threshold;       /* cursor acceleration threshold */\n\n          bool                           set;             /* cursor enable/disable has been called at least one time */\n\n          DFBWindowSurfacePolicy         policy;          /* cursor surface policy */\n     } cursor;\n\n     struct {\n          DFBDisplayLayerBackgroundMode  mode;            /* background handling mode */\n\n          DFBColor                       color;           /* color for solid background mode */\n          int                            color_index;     /* color index for solid background mode */\n\n          CoreSurface                   *image;           /* surface for background image mode */\n          GlobalReaction                 image_reaction;  /* global reaction for background image */\n     } bg;\n\n     DirectLink                         *devices;         /* input devices attached to the stack */\n\n     bool                                hw_mode;         /* recompositing is done by hardware */\n\n     void                               *stack_data;      /* private data of window manager */\n\n     FusionSHMPoolShared                *shmpool;         /* shared memory pool */\n\n     CoreWindowStackFlags                flags;           /* state flags */\n\n     FusionCall                          call;            /* dispatch */\n\n     FusionDispatchCleanup              *motion_cleanup;  /* motion input dispatch cleanup */\n     DFBInputEvent                       motion_x;        /* x motion */\n     DFBInputEvent                       motion_y;        /* y motion */\n     long long                           motion_ts;       /* micros */\n\n     FusionVector                        visible_windows; /* list of visible windows */\n};\n\n/**********************************************************************************************************************/\n\n/*\n * Create a window stack, initialize it and attach input devices for input events.\n */\nCoreWindowStack *dfb_windowstack_create                  ( CoreLayerContext              *context );\n\n/*\n * Detach input devices.\n */\nvoid             dfb_windowstack_detach_devices          ( CoreWindowStack               *stack );\n\n/*\n * Destroy a window stack.\n */\nvoid             dfb_windowstack_destroy                 ( CoreWindowStack               *stack );\n\n/*\n * Resize a window stack.\n */\nvoid             dfb_windowstack_resize                  ( CoreWindowStack               *stack,\n                                                           int                            width,\n                                                           int                            height,\n                                                           int                            rotation );\n\n/*\n * Prohibit access to the window stack data (wait until stack is accessible).\n */\nDirectResult     dfb_windowstack_lock                    ( CoreWindowStack               *stack );\n\n/*\n * Allow access to the window stack data.\n */\nDirectResult     dfb_windowstack_unlock                  ( CoreWindowStack               *stack );\n\n/*\n * Repaints all window on a window stack.\n */\nDFBResult dfb_windowstack_repaint_all                    ( CoreWindowStack               *stack );\n\n/*\n * Background handling.\n */\n\nDFBResult dfb_windowstack_set_background_mode            ( CoreWindowStack               *stack,\n                                                           DFBDisplayLayerBackgroundMode  mode );\n\nDFBResult dfb_windowstack_set_background_image           ( CoreWindowStack               *stack,\n                                                           CoreSurface                   *image );\n\nDFBResult dfb_windowstack_set_background_color           ( CoreWindowStack               *stack,\n                                                           const DFBColor                *color );\n\nDFBResult dfb_windowstack_set_background_color_index     ( CoreWindowStack               *stack,\n                                                           int                            index );\n\n/*\n * Cursor control.\n */\n\nDFBResult dfb_windowstack_cursor_enable                  ( CoreWindowStack               *stack,\n                                                           bool                           enable );\n\nDFBResult dfb_windowstack_cursor_set_opacity             ( CoreWindowStack               *stack,\n                                                           u8                             opacity );\n\nDFBResult dfb_windowstack_cursor_set_shape               ( CoreWindowStack               *stack,\n                                                           CoreSurface                   *shape,\n                                                           int                            hot_x,\n                                                           int                            hot_y );\n\nDFBResult dfb_windowstack_cursor_warp                    ( CoreWindowStack               *stack,\n                                                           int                            x,\n                                                           int                            y );\n\nDFBResult dfb_windowstack_cursor_set_acceleration        ( CoreWindowStack               *stack,\n                                                           int                            numerator,\n                                                           int                            denominator,\n                                                           int                            threshold );\n\nDFBResult dfb_windowstack_get_cursor_position            ( CoreWindowStack               *stack,\n                                                           int                           *ret_x,\n                                                           int                           *ret_y );\n\n/*\n * Global reaction, listen to input device events.\n */\nReactionResult _dfb_windowstack_inputdevice_listener     ( const void                    *msg_data,\n                                                           void                          *ctx );\n\n/*\n * Global reaction, listen to the background image.\n */\nReactionResult _dfb_windowstack_background_image_listener( const void                    *msg_data,\n                                                           void                          *ctx );\n\n#endif\n"
  },
  {
    "path": "src/core/wm.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core.h>\n#include <core/core_parts.h>\n#include <core/layer_context.h>\n#include <core/surface.h>\n#include <core/windows.h>\n#include <core/windowstack.h>\n#include <core/wm.h>\n#include <directfb_util.h>\n#include <fusion/shmalloc.h>\n\nD_DEBUG_DOMAIN( Core_WM, \"Core/WM\", \"DirectFB Core WM\" );\n\nDEFINE_MODULE_DIRECTORY( dfb_wm_modules, \"wm\", DFB_CORE_WM_ABI_VERSION );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int                  magic;\n\n     int                  abi;\n\n     char                *name;\n     CoreWMInfo           info;\n     void                *data;\n\n     FusionSHMPoolShared *shmpool;\n\n     FusionReactor       *reactor;\n} DFBWMCoreShared;\n\ntypedef struct {\n     int                magic;\n\n     CoreDFB           *core;\n\n     DFBWMCoreShared   *shared;\n\n     DirectModuleEntry *module;\n     const CoreWMFuncs *funcs;\n     void              *data;\n} DFBWMCore;\n\nDFB_CORE_PART( wm_core, WMCore );\n\n/**********************************************************************************************************************/\n\nstatic DFBWMCore       *wm_local  = NULL;\nstatic DFBWMCoreShared *wm_shared = NULL;\n\nstatic DFBResult\nload_module( const char *name )\n{\n     DirectModuleEntry *module;\n\n     D_ASSERT( wm_local != NULL );\n\n     direct_modules_explore_directory( &dfb_wm_modules );\n\n     direct_list_foreach (module, dfb_wm_modules.entries) {\n          const CoreWMFuncs *funcs;\n\n          funcs = direct_module_ref( module );\n          if (!funcs)\n               continue;\n\n          if (!name || !strcasecmp( name, module->name )) {\n               if (wm_local->module)\n                    direct_module_unref( wm_local->module );\n\n               wm_local->module = module;\n               wm_local->funcs  = funcs;\n          }\n          else\n               direct_module_unref( module );\n     }\n\n     if (!wm_local->module) {\n          if (name)\n               D_ERROR( \"Core/WM: Window manager module '%s' not found!\\n\", name );\n          else\n               D_ERROR( \"Core/WM: No window manager module found!\\n\" );\n\n          return DFB_NOIMPL;\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndfb_wm_core_initialize( CoreDFB         *core,\n                        DFBWMCore       *data,\n                        DFBWMCoreShared *shared )\n{\n     DFBResult          ret;\n     const CoreWMFuncs *funcs;\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %p, %p )\\n\", __FUNCTION__, core, data, shared );\n\n     D_ASSERT( data != NULL );\n     D_ASSERT( shared != NULL );\n\n     data->core   = core;\n     data->shared = shared;\n\n     wm_local  = data;\n     wm_shared = shared;\n\n     wm_shared->shmpool = dfb_core_shmpool( core );\n\n     /* Set ABI version for the session. */\n     wm_shared->abi = DFB_CORE_WM_ABI_VERSION;\n\n     /* Load the module. */\n     ret = load_module( dfb_config->wm );\n     if (ret)\n          goto error;\n\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->GetWMInfo != NULL );\n     D_ASSERT( wm_local->funcs->Initialize != NULL );\n\n     funcs = wm_local->funcs;\n\n     /* Query module information. */\n     funcs->GetWMInfo( &wm_shared->info );\n\n     D_INFO( \"DirectFB/Core/WM: %s %d.%d (%s)\\n\", wm_shared->info.name,\n             wm_shared->info.version.major, wm_shared->info.version.minor, wm_shared->info.vendor );\n\n     /* Store module name in shared memory. */\n     wm_shared->name = SHSTRDUP( wm_shared->shmpool, wm_local->module->name );\n     if (!wm_shared->name) {\n          ret = D_OOSHM();\n          goto error;\n     }\n\n     /* Allocate shared window manager data. */\n     if (wm_shared->info.wm_shared_size) {\n          wm_shared->data = SHCALLOC( wm_shared->shmpool, 1, wm_shared->info.wm_shared_size );\n          if (!wm_shared->data) {\n               ret = D_OOSHM();\n               goto error;\n          }\n     }\n\n     /* Allocate local window manager data. */\n     if (wm_shared->info.wm_data_size) {\n          wm_local->data = D_CALLOC( 1, wm_shared->info.wm_data_size );\n          if (!wm_local->data) {\n               ret = D_OOM();\n               goto error;\n          }\n     }\n\n     wm_shared->reactor = fusion_reactor_new( 0, \"WM\", dfb_core_world( core ) );\n\n     fusion_reactor_direct( wm_shared->reactor, false );\n     fusion_reactor_add_permissions( wm_shared->reactor, 0, FUSION_REACTOR_PERMIT_ATTACH_DETACH );\n\n     /* Initialize window manager. */\n     ret = funcs->Initialize( core, wm_local->data, wm_shared->data );\n     if (ret) {\n          D_DERROR( ret, \"Core/WM: Could not initialize window manager!\\n\" );\n          goto error;\n     }\n\n     D_MAGIC_SET( data, DFBWMCore );\n     D_MAGIC_SET( wm_shared, DFBWMCoreShared );\n\n     return DFB_OK;\n\nerror:\n     if (wm_local->data)\n          D_FREE( wm_local->data );\n\n     if (wm_shared->data)\n          SHFREE( wm_shared->shmpool, wm_shared->data );\n\n     if (wm_shared->name)\n          SHFREE( wm_shared->shmpool, wm_shared->name );\n\n     wm_local = NULL;\n     wm_shared = NULL;\n\n     return ret;\n}\n\nstatic DFBResult\ndfb_wm_core_join( CoreDFB         *core,\n                  DFBWMCore       *data,\n                  DFBWMCoreShared *shared )\n{\n     DFBResult          ret;\n     CoreWMInfo         info;\n     const CoreWMFuncs *funcs;\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %p, %p )\\n\", __FUNCTION__, core, data, shared );\n\n     D_ASSERT( data != NULL );\n     D_MAGIC_ASSERT( shared, DFBWMCoreShared );\n\n     data->core   = core;\n     data->shared = shared;\n\n     wm_local  = data;\n     wm_shared = shared;\n\n     /* Check binary version numbers. */\n     if (wm_shared->abi != DFB_CORE_WM_ABI_VERSION) {\n          D_ERROR( \"Core/WM: ABI version of running WM module (%d) doesn't match %d!\\n\",\n                   wm_shared->abi, DFB_CORE_WM_ABI_VERSION );\n          ret = DFB_VERSIONMISMATCH;\n          goto error;\n     }\n\n     /* Load the module that is used by the running session. */\n     ret = load_module( wm_shared->name );\n     if (ret)\n          goto error;\n\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->GetWMInfo != NULL );\n     D_ASSERT( wm_local->funcs->Join != NULL );\n\n     funcs = wm_local->funcs;\n\n     /* Query module information. */\n     funcs->GetWMInfo( &info );\n\n     if (wm_shared->info.version.major != info.version.major || wm_shared->info.version.minor != info.version.minor) {\n          D_ERROR( \"Core/WM: Running WM module version '%d.%d' doesn't match version '%d.%d'!\\n\",\n                    wm_shared->info.version.major, wm_shared->info.version.minor,\n                    info.version.major, info.version.minor );\n          ret = DFB_VERSIONMISMATCH;\n          goto error;\n     }\n\n     /* Allocate window manager data. */\n     if (wm_shared->info.wm_data_size) {\n          wm_local->data = D_CALLOC( 1, wm_shared->info.wm_data_size );\n          if (!wm_local->data) {\n               ret = D_OOM();\n               goto error;\n          }\n     }\n\n     /* Join window manager. */\n     ret = funcs->Join( core, wm_local->data, wm_shared->data );\n     if (ret) {\n          D_DERROR( ret, \"Core/WM: Could not join window manager!\\n\" );\n          goto error;\n     }\n\n     D_MAGIC_SET( data, DFBWMCore );\n\n     return DFB_OK;\n\nerror:\n     if (wm_local->data)\n          D_FREE( wm_local->data );\n\n     wm_local = NULL;\n     wm_shared = NULL;\n\n     return ret;\n}\n\nstatic DFBResult\ndfb_wm_core_shutdown( DFBWMCore *data,\n                      bool       emergency )\n{\n     DFBResult          ret;\n     const CoreWMFuncs *funcs;\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %semergency )\\n\", __FUNCTION__, data, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( data, DFBWMCore );\n     D_MAGIC_ASSERT( data->shared, DFBWMCoreShared );\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->Shutdown != NULL );\n     D_ASSERT( wm_shared == data->shared );\n\n     funcs = wm_local->funcs;\n\n     fusion_reactor_destroy( wm_shared->reactor );\n\n     /* Shutdown window manager. */\n     ret = funcs->Shutdown( emergency, wm_local->data, wm_shared->data );\n\n     /* Unload the module. */\n     direct_module_unref( wm_local->module );\n\n#if !FUSION_BUILD_MULTI\n     fusion_reactor_free( wm_shared->reactor );\n#endif /* FUSION_BUILD_MULTI */\n\n     fusion_reactor_free( wm_shared->reactor );\n\n     /* Deallocate local window manager data. */\n     if (wm_local->data)\n          D_FREE( wm_local->data );\n\n     /* Deallocate shared window manager data. */\n     if (wm_shared->data)\n          SHFREE( wm_shared->shmpool, wm_shared->data );\n\n     /* Free module name in shared memory. */\n     SHFREE( wm_shared->shmpool, wm_shared->name );\n\n     D_MAGIC_CLEAR( data );\n     D_MAGIC_CLEAR( wm_shared );\n\n     wm_local = NULL;\n     wm_shared = NULL;\n\n     return ret;\n}\n\nstatic DFBResult\ndfb_wm_core_leave( DFBWMCore *data,\n                    bool      emergency )\n{\n     DFBResult          ret;\n     const CoreWMFuncs *funcs;\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %semergency )\\n\", __FUNCTION__, data, emergency ? \"\" : \"no \" );\n\n     D_MAGIC_ASSERT( data, DFBWMCore );\n     D_MAGIC_ASSERT( data->shared, DFBWMCoreShared );\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->Leave != NULL );\n     D_ASSERT( wm_shared != NULL );\n\n     funcs = wm_local->funcs;\n\n     /* Leave window manager. */\n     ret = funcs->Leave( emergency, wm_local->data, wm_shared->data );\n\n     /* Unload the module. */\n     direct_module_unref( wm_local->module );\n\n     /* Deallocate local window manager data. */\n     if (wm_local->data)\n          D_FREE( wm_local->data );\n\n     wm_local = NULL;\n     wm_shared = NULL;\n\n     D_MAGIC_CLEAR( data );\n\n     return ret;\n}\n\nstatic DFBResult\ndfb_wm_core_suspend( DFBWMCore *data )\n{\n     const CoreWMFuncs *funcs;\n\n     D_DEBUG_AT( Core_WM, \"%s( %p )\\n\", __FUNCTION__, data );\n\n     D_MAGIC_ASSERT( data, DFBWMCore );\n     D_MAGIC_ASSERT( data->shared, DFBWMCoreShared );\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->Suspend != NULL );\n     D_ASSERT( wm_shared != NULL );\n\n     funcs = wm_local->funcs;\n\n     return funcs->Suspend( wm_local->data, wm_shared->data );\n}\n\nstatic DFBResult\ndfb_wm_core_resume( DFBWMCore *data )\n{\n     const CoreWMFuncs *funcs;\n\n     D_DEBUG_AT( Core_WM, \"%s( %p )\\n\", __FUNCTION__, data );\n\n     D_MAGIC_ASSERT( data, DFBWMCore );\n     D_MAGIC_ASSERT( data->shared, DFBWMCoreShared );\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->Resume != NULL );\n     D_ASSERT( wm_shared != NULL );\n\n     funcs = wm_local->funcs;\n\n     return funcs->Resume( wm_local->data, wm_shared->data );\n}\n\n/**********************************************************************************************************************/\n\nstatic bool\ndfb_wm_layer_context_callback( FusionObjectPool *pool,\n                               FusionObject     *object,\n                               void             *ctx )\n{\n     CoreLayerContext     *context = (CoreLayerContext*) object;\n     CoreWindowStackFlags  flags   = (CoreWindowStackFlags)(long) ctx;\n\n     D_DEBUG_AT( Core_WM, \"  -> ref context %p...\\n\", context );\n\n     dfb_layer_context_ref( context );\n\n     dfb_layer_context_lock( context );\n\n     if (context->stack) {\n          if ((context->stack->flags & CWSF_ACTIVATED) & flags)\n               dfb_wm_set_active( context->stack, false );\n\n          if ((context->stack->flags & CWSF_INITIALIZED) & flags)\n               dfb_wm_close_stack( context->stack );\n     }\n\n     dfb_layer_context_unlock( context );\n\n     D_DEBUG_AT( Core_WM, \"  -> unref context %p...\\n\", context );\n\n     dfb_layer_context_unref( context );\n\n     return true;\n}\n\nDFBResult\ndfb_wm_deactivate_all_stacks( void *data )\n{\n     DFBWMCore *local = data;\n\n     D_DEBUG_AT( Core_WM, \"%s( %p )\\n\", __FUNCTION__, local );\n\n     D_MAGIC_ASSERT( local, DFBWMCore );\n     D_MAGIC_ASSERT( local->shared, DFBWMCoreShared );\n\n     dfb_core_enum_layer_contexts( local->core, dfb_wm_layer_context_callback, (void*)(long) CWSF_ACTIVATED );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_wm_close_all_stacks( void *data )\n{\n     DFBWMCore *local = data;\n\n     D_DEBUG_AT( Core_WM, \"%s( %p )\\n\", __FUNCTION__, local );\n\n     D_MAGIC_ASSERT( local, DFBWMCore );\n     D_MAGIC_ASSERT( local->shared, DFBWMCoreShared );\n\n     dfb_core_enum_layer_contexts( local->core, dfb_wm_layer_context_callback, (void*)(long) CWSF_INITIALIZED );\n\n     return DFB_OK;\n}\n\ntypedef struct {\n     ReactionFunc        func;\n     void               *ctx;\n     Reaction           *reaction;\n} AttachContext;\n\nstatic void\nconvert_config( DFBWindowConfig        *config,\n                const CoreWindowConfig *from )\n{\n     config->bounds            = from->bounds;\n     config->opacity           = from->opacity;\n     config->stacking          = from->stacking;\n     config->options           = from->options;\n     config->events            = from->events;\n     config->association       = from->association;\n     config->color_key         = from->color_key;\n     config->opaque            = from->opaque;\n     config->color             = from->color;\n     config->key_selection     = DWKS_ALL;\n     config->cursor_flags      = from->cursor_flags;\n     config->cursor_resolution = from->cursor_resolution;\n     config->src_geometry      = from->src_geometry;\n     config->dst_geometry      = from->dst_geometry;\n     config->rotation          = from->rotation;\n     config->application_id    = from->application_id;\n     config->stereo_depth      = from->z;\n}\n\nstatic void\nconvert_state( DFBWindowState  *state,\n               CoreWindowFlags  flags )\n{\n     state->flags = DWSTATE_NONE;\n\n     if (flags & CWF_INSERTED)\n          state->flags |= DWSTATE_INSERTED;\n\n     if (flags & CWF_FOCUSED)\n          state->flags |= DWSTATE_FOCUSED;\n\n     if (flags & CWF_ENTERED)\n          state->flags |= DWSTATE_ENTERED;\n}\n\nstatic DFBEnumerationResult\nwm_window_attach_callback( CoreWindow *window,\n                           void       *ctx )\n{\n     AttachContext *attach_ctx = ctx;\n\n     CoreWM_WindowAdd add;\n\n     memset( &add, 0, sizeof(add ) );\n\n     add.info.window_id   = window->id;\n     add.info.caps        = window->caps;\n     add.info.resource_id = window->resource_id;\n\n     convert_config( &add.info.config, &window->config );\n\n     convert_state( &add.info.state, window->flags );\n\n     attach_ctx->func( &add, attach_ctx->ctx );\n\n     return DFENUM_OK;\n}\n\nstatic bool\ndfb_wm_layer_context_WINDOW_ADD_callback( FusionObjectPool *pool,\n                                          FusionObject     *object,\n                                          void             *ctx )\n{\n     DFBResult         ret;\n     AttachContext    *attach_ctx = ctx;\n     CoreLayerContext *context    = (CoreLayerContext*) object;\n\n     dfb_layer_context_lock( context );\n\n     if (context->stack) {\n          ret = dfb_wm_enum_windows( context->stack, wm_window_attach_callback, attach_ctx );\n          if (ret)\n               D_DERROR( ret, \"Core/WM: Could not enumerate windows\" );\n\n          ret = fusion_reactor_attach_channel( wm_shared->reactor, CORE_WM_WINDOW_ADD,\n                                               attach_ctx->func, attach_ctx->ctx, attach_ctx->reaction );\n          if (ret)\n               D_DERROR( ret, \"Core/WM: Could not attach to reactor\" );\n     }\n\n     dfb_layer_context_unlock( context );\n\n     return true;\n}\n\nDFBResult\ndfb_wm_attach( CoreDFB      *core,\n               int           channel,\n               ReactionFunc  func,\n               void         *ctx,\n               Reaction     *reaction )\n{\n     D_ASSERT( wm_shared != NULL );\n\n     if (channel == CORE_WM_WINDOW_ADD) {\n          AttachContext attach_ctx = { func, ctx, reaction };\n\n          if (dfb_core_is_master( core ))\n               dfb_core_enum_layer_contexts( core, dfb_wm_layer_context_WINDOW_ADD_callback, &attach_ctx );\n     }\n\n     return fusion_reactor_attach_channel( wm_shared->reactor, channel, func, ctx, reaction );\n}\n\nDFBResult\ndfb_wm_detach( CoreDFB  *core,\n               Reaction *reaction )\n{\n     D_ASSERT( wm_shared != NULL );\n\n     return fusion_reactor_detach( wm_shared->reactor, reaction );\n}\n\nstatic DFBResult\ndfb_wm_dispatch( CoreDFB    *core,\n                 int         channel,\n                 const void *data,\n                 int         size )\n{\n     D_ASSERT( wm_shared != NULL );\n\n     return fusion_reactor_dispatch_channel( wm_shared->reactor, channel, data, size, true, NULL );\n}\n\nDFBResult\ndfb_wm_dispatch_WindowAdd( CoreDFB    *core,\n                           CoreWindow *window )\n{\n     pid_t            pid = 0;\n     CoreWM_WindowAdd add;\n\n     fusion_get_fusionee_pid( core->world, window->object.identity, &pid );\n\n     add.info.window_id   = window->id;\n     add.info.caps        = window->caps;\n     add.info.resource_id = window->resource_id;\n     add.info.process_id  = pid;\n     add.info.instance_id = window->object.identity;\n\n     convert_config( &add.info.config, &window->config );\n\n     convert_state( &add.info.state, window->flags );\n\n     return dfb_wm_dispatch( core, CORE_WM_WINDOW_ADD, &add, sizeof(add) );\n}\n\nDFBResult\ndfb_wm_dispatch_WindowRemove( CoreDFB    *core,\n                              CoreWindow *window )\n{\n     CoreWM_WindowRemove remove;\n\n     remove.window_id = window->id;\n\n     return dfb_wm_dispatch( core, CORE_WM_WINDOW_REMOVE, &remove, sizeof(remove) );\n}\n\nDFBResult\ndfb_wm_dispatch_WindowConfig( CoreDFB              *core,\n                              CoreWindow           *window,\n                              DFBWindowConfigFlags  flags )\n{\n     CoreWM_WindowConfig config;\n\n     config.window_id = window->id;\n     config.flags     = flags;\n\n     convert_config( &config.config, &window->config );\n\n     return dfb_wm_dispatch( core, CORE_WM_WINDOW_CONFIG, &config, sizeof(config) );\n}\n\nDFBResult\ndfb_wm_dispatch_WindowState( CoreDFB    *core,\n                             CoreWindow *window )\n{\n     CoreWM_WindowState state;\n\n     state.window_id = window->id;\n\n     convert_state( &state.state, window->flags );\n\n     return dfb_wm_dispatch( core, CORE_WM_WINDOW_STATE, &state, sizeof(state) );\n}\n\nDFBResult\ndfb_wm_dispatch_WindowRestack( CoreDFB      *core,\n                               CoreWindow   *window,\n                               unsigned int  index )\n{\n     CoreWM_WindowRestack restack;\n\n     restack.window_id = window->id;\n     restack.index     = index;\n\n     return dfb_wm_dispatch( core, CORE_WM_WINDOW_RESTACK, &restack, sizeof(restack) );\n}\n\nDFBResult\ndfb_wm_dispatch_WindowFocus( CoreDFB    *core,\n                             CoreWindow *window )\n{\n     CoreWM_WindowFocus focus;\n\n     focus.window_id = window->id;\n\n     return dfb_wm_dispatch( core, CORE_WM_WINDOW_FOCUS, &focus, sizeof(focus) );\n}\n\nvoid *\ndfb_wm_get_data()\n{\n     D_ASSERT( wm_local != NULL );\n\n     return wm_local->data;\n}\n\nDFBResult\ndfb_wm_post_init( CoreDFB *core )\n{\n     const CoreWMFuncs *funcs;\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->PostInit != NULL );\n     D_ASSERT( wm_shared != NULL );\n\n     funcs = wm_local->funcs;\n\n     return funcs->PostInit( wm_local->data, wm_shared->data );\n}\n\nDFBResult\ndfb_wm_init_stack( CoreWindowStack *stack )\n{\n     DFBResult          ret;\n     const CoreWMFuncs *funcs;\n\n     D_DEBUG_AT( Core_WM, \"%s( %p )\\n\", __FUNCTION__, stack );\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->InitStack != NULL );\n     D_ASSERT( wm_shared != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( !(stack->flags & CWSF_INITIALIZED) );\n\n     D_MAGIC_ASSERT( stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &stack->context->lock );\n\n     /* Allocate shared stack data. */\n     if (wm_shared->info.stack_data_size) {\n          if (stack->stack_data)\n               SHFREE( stack->shmpool, stack->stack_data );\n\n          stack->stack_data = SHCALLOC( stack->shmpool, 1, wm_shared->info.stack_data_size );\n          if (!stack->stack_data) {\n               return D_OOSHM();\n          }\n     }\n\n     /* Window manager specific initialization. */\n     ret = funcs->InitStack( stack, wm_local->data, stack->stack_data );\n     if (ret) {\n          if (stack->stack_data) {\n               SHFREE( wm_shared->shmpool, stack->stack_data );\n               stack->stack_data = NULL;\n          }\n\n          return ret;\n     }\n\n     stack->flags |= CWSF_INITIALIZED;\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_wm_close_stack( CoreWindowStack *stack )\n{\n     const CoreWMFuncs *funcs;\n\n     D_DEBUG_AT( Core_WM, \"%s( %p )\\n\", __FUNCTION__, stack );\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->CloseStack != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n\n     D_ASSUME( stack->flags & CWSF_INITIALIZED );\n\n     if (!(stack->flags & CWSF_INITIALIZED)) {\n          D_ASSUME( !(stack->flags & CWSF_ACTIVATED) );\n          return DFB_OK;\n     }\n\n     D_MAGIC_ASSERT( stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &stack->context->lock );\n\n     /* Deactivate before deinitialization. */\n     if (stack->flags & CWSF_ACTIVATED)\n          dfb_wm_set_active( stack, false );\n\n     /* Clear flag and remove stack first, because CloseStack() may cause the stack to be destroyed. */\n     stack->flags &= ~CWSF_INITIALIZED;\n\n     /* Window manager specific deinitialization. */\n     return funcs->CloseStack( stack, wm_local->data, stack->stack_data );\n}\n\nDFBResult\ndfb_wm_set_active( CoreWindowStack *stack,\n                   bool             active )\n{\n     DFBResult          ret;\n     const CoreWMFuncs *funcs;\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %sactive )\\n\", __FUNCTION__, stack, active ? \"\" : \"in\" );\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->SetActive != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( stack->flags & CWSF_INITIALIZED );\n\n     D_MAGIC_ASSERT( stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &stack->context->lock );\n\n     if (active) {\n          D_ASSUME( !(stack->flags & CWSF_ACTIVATED) );\n\n          if (stack->flags & CWSF_ACTIVATED)\n               return DFB_OK;\n\n          ret = funcs->SetActive( stack, wm_local->data, stack->stack_data, true );\n\n          stack->flags |= CWSF_ACTIVATED;\n     }\n     else {\n          D_ASSUME( stack->flags & CWSF_ACTIVATED );\n\n          if (!(stack->flags & CWSF_ACTIVATED))\n               return DFB_OK;\n\n          ret = funcs->SetActive( stack, wm_local->data, stack->stack_data, false );\n\n          stack->flags &= ~CWSF_ACTIVATED;\n     }\n\n     return ret;\n}\n\nDFBResult\ndfb_wm_resize_stack( CoreWindowStack *stack,\n                     int              width,\n                     int              height )\n{\n     const CoreWMFuncs *funcs;\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %dx%d )\\n\", __FUNCTION__, stack, width, height );\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->ResizeStack != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( stack->flags & CWSF_INITIALIZED );\n\n     D_MAGIC_ASSERT( stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &stack->context->lock );\n\n     /* Notify window manager about the new size. */\n     return funcs->ResizeStack( stack, wm_local->data, stack->stack_data, width, height );\n}\n\nDFBResult\ndfb_wm_process_input( CoreWindowStack     *stack,\n                      const DFBInputEvent *event )\n{\n     const CoreWMFuncs *funcs;\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %p )\\n\", __FUNCTION__, stack, event );\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->ProcessInput != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( stack->flags & CWSF_INITIALIZED );\n\n     D_MAGIC_ASSERT( stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &stack->context->lock );\n\n     D_ASSERT( event != NULL );\n\n     /* Dispatch input event via window manager. */\n     return funcs->ProcessInput( stack, wm_local->data, stack->stack_data, event );\n}\n\nDFBResult\ndfb_wm_flush_keys( CoreWindowStack *stack )\n{\n     const CoreWMFuncs *funcs;\n\n     D_DEBUG_AT( Core_WM, \"%s( %p )\\n\", __FUNCTION__, stack );\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->FlushKeys != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( stack->flags & CWSF_INITIALIZED );\n\n     D_MAGIC_ASSERT( stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &stack->context->lock );\n\n     return funcs->FlushKeys( stack, wm_local->data, stack->stack_data );\n}\n\nDFBResult\ndfb_wm_window_at( CoreWindowStack  *stack,\n                  int               x,\n                  int               y,\n                  CoreWindow      **ret_window )\n{\n     const CoreWMFuncs *funcs;\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %d,%d )\\n\", __FUNCTION__, stack, x, y );\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->WindowAt != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( stack->flags & CWSF_INITIALIZED );\n\n     D_MAGIC_ASSERT( stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &stack->context->lock );\n\n     D_ASSERT( ret_window != NULL );\n\n     return funcs->WindowAt( stack, wm_local->data, stack->stack_data, x, y, ret_window );\n}\n\nDFBResult\ndfb_wm_window_lookup( CoreWindowStack  *stack,\n                      DFBWindowID       window_id,\n                      CoreWindow      **ret_window )\n{\n     const CoreWMFuncs *funcs;\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %u )\\n\", __FUNCTION__, stack, window_id );\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->WindowLookup != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( stack->flags & CWSF_INITIALIZED );\n\n     D_MAGIC_ASSERT( stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &stack->context->lock );\n\n     D_ASSERT( ret_window != NULL );\n\n     return funcs->WindowLookup( stack, wm_local->data, stack->stack_data, window_id, ret_window );\n}\n\nDFBResult\ndfb_wm_enum_windows( CoreWindowStack      *stack,\n                     CoreWMWindowCallback  callback,\n                     void                 *callback_ctx )\n{\n     const CoreWMFuncs *funcs;\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %p, %p )\\n\", __FUNCTION__, stack, callback, callback_ctx );\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->EnumWindows != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( stack->flags & CWSF_INITIALIZED );\n\n     D_MAGIC_ASSERT( stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &stack->context->lock );\n\n     D_ASSERT( callback != NULL );\n\n     return funcs->EnumWindows( stack, wm_local->data, stack->stack_data, callback, callback_ctx );\n}\n\nDFBResult\ndfb_wm_get_insets( CoreWindowStack *stack,\n                   CoreWindow      *window,\n                   DFBInsets       *ret_insets )\n{\n     const CoreWMFuncs *funcs;\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->GetInsets != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( stack->flags & CWSF_INITIALIZED );\n\n     D_MAGIC_ASSERT( stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &stack->context->lock );\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( ret_insets != NULL );\n\n     return funcs->GetInsets( stack, window, ret_insets );\n}\n\nDFBResult\ndfb_wm_preconfigure_window( CoreWindowStack *stack,\n                            CoreWindow      *window )\n{\n     DFBResult          ret;\n     void              *window_data = NULL;\n     const CoreWMFuncs *funcs;\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->PreConfigureWindow != NULL );\n     D_ASSERT( wm_shared != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( stack->flags & CWSF_INITIALIZED );\n\n     D_MAGIC_ASSERT( stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &stack->context->lock );\n\n     D_ASSERT( window != NULL );\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %p, %4d,%4d-%4dx%4d )\\n\", __FUNCTION__,\n                 stack, window, DFB_RECTANGLE_VALS( &window->config.bounds ) );\n\n     /* Allocate shared window data. */\n     if (wm_shared->info.window_data_size) {\n          window_data = SHCALLOC( wm_shared->shmpool, 1, wm_shared->info.window_data_size );\n          if (!window_data) {\n               return D_OOSHM();\n          }\n     }\n\n     /* Keep shared window data. */\n     window->window_data = window_data;\n\n     /* Tell window manager about the new window. */\n     ret = funcs->PreConfigureWindow( stack, wm_local->data, stack->stack_data, window, window_data );\n     if (ret) {\n          if (window_data) {\n               SHFREE( wm_shared->shmpool, window_data );\n               window->window_data = NULL;\n          }\n\n          return ret;\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_wm_add_window( CoreWindowStack *stack,\n                   CoreWindow      *window )\n{\n     DFBResult          ret;\n     const CoreWMFuncs *funcs;\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->AddWindow != NULL );\n     D_ASSERT( wm_shared != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( stack->flags & CWSF_INITIALIZED );\n\n     D_MAGIC_ASSERT( stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &stack->context->lock );\n\n     D_ASSERT( window != NULL );\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %p, %4d,%4d-%4dx%4d )\\n\", __FUNCTION__,\n                 stack, window, DFB_RECTANGLE_VALS( &window->config.bounds ) );\n\n     /* Tell window manager about the new window. */\n     ret = funcs->AddWindow( stack, wm_local->data, stack->stack_data, window, window->window_data );\n     if (ret) {\n          if (window->window_data)\n               SHFREE( wm_shared->shmpool, window->window_data );\n          return ret;\n     }\n     return DFB_OK;\n}\n\nDFBResult\ndfb_wm_remove_window( CoreWindowStack *stack,\n                      CoreWindow      *window )\n{\n     DFBResult          ret;\n     const CoreWMFuncs *funcs;\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->RemoveWindow != NULL );\n     D_ASSERT( wm_shared != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( stack->flags & CWSF_INITIALIZED );\n\n     D_MAGIC_ASSERT( stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &stack->context->lock );\n\n     D_ASSERT( window != NULL );\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %p, %4d,%4d-%4dx%4d )\\n\", __FUNCTION__,\n                 stack, window, DFB_RECTANGLE_VALS( &window->config.bounds ) );\n\n     /* Remove window from window manager. */\n     ret = funcs->RemoveWindow( stack, wm_local->data, stack->stack_data, window, window->window_data );\n\n     /* Deallocate shared stack data. */\n     if (window->window_data) {\n          SHFREE( wm_shared->shmpool, window->window_data );\n          window->window_data = NULL;\n     }\n\n     return ret;\n}\n\nDFBResult\ndfb_wm_set_window_property( CoreWindowStack  *stack,\n                            CoreWindow       *window,\n                            const char       *key,\n                            void             *value,\n                            void            **ret_old_value )\n{\n     const CoreWMFuncs *funcs;\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->SetWindowProperty != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( stack->flags & CWSF_INITIALIZED );\n\n     D_MAGIC_ASSERT( stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &stack->context->lock );\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( key != NULL );\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %p, %4d,%4d-%4dx%4d, '%s' = %p )\\n\", __FUNCTION__,\n                 stack, window, DFB_RECTANGLE_VALS( &window->config.bounds ), key, value );\n\n     return funcs->SetWindowProperty( stack, wm_local->data, stack->stack_data, window, window->window_data, key, value,\n                                      ret_old_value );\n}\n\nDFBResult\ndfb_wm_get_window_property( CoreWindowStack  *stack,\n                            CoreWindow       *window,\n                            const char       *key,\n                            void            **ret_value )\n{\n     const CoreWMFuncs *funcs;\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->GetWindowProperty != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( stack->flags & CWSF_INITIALIZED );\n\n     D_MAGIC_ASSERT( stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &stack->context->lock );\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( key != NULL );\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %p, %4d,%4d-%4dx%4d, '%s' )\\n\", __FUNCTION__,\n                 stack, window, DFB_RECTANGLE_VALS( &window->config.bounds ), key );\n\n     return funcs->GetWindowProperty( stack, wm_local->data, stack->stack_data, window, window->window_data, key,\n                                      ret_value );\n}\n\nDFBResult\ndfb_wm_remove_window_property( CoreWindowStack  *stack,\n                               CoreWindow       *window,\n                               const char       *key,\n                               void            **ret_value )\n{\n     DFBResult          ret;\n     const CoreWMFuncs *funcs;\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->RemoveWindowProperty != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( stack->flags & CWSF_INITIALIZED );\n\n     D_MAGIC_ASSERT( stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &stack->context->lock );\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( key != NULL );\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %p, %4d,%4d-%4dx%4d, '%s' )\\n\", __FUNCTION__,\n                 stack, window, DFB_RECTANGLE_VALS( &window->config.bounds ), key );\n\n     ret = funcs->RemoveWindowProperty( stack, wm_local->data, stack->stack_data, window, window->window_data, key,\n                                        ret_value );\n\n     return ret;\n}\n\nstatic void\napply_geometry( const DFBWindowGeometry *geometry,\n                const DFBRegion         *clip,\n                const DFBWindowGeometry *parent,\n                DFBRectangle            *ret_rect )\n{\n     int width, height;\n\n     D_ASSERT( geometry != NULL );\n     DFB_REGION_ASSERT( clip );\n     D_ASSERT( ret_rect != NULL );\n\n     if (!geometry)\n          return;\n\n     width  = clip->x2 - clip->x1 + 1;\n     height = clip->y2 - clip->y1 + 1;\n\n     switch (geometry->mode) {\n          case DWGM_DEFAULT:\n               D_DEBUG_AT( Core_WM, \"  -- DEFAULT\\n\" );\n               *ret_rect = DFB_RECTANGLE_INIT_FROM_REGION( clip );\n               D_DEBUG_AT( Core_WM, \"    -> [%4d,%4d-%4dx%4d]\\n\", DFB_RECTANGLE_VALS( ret_rect ) );\n               return;\n\n          case DWGM_FOLLOW:\n               D_ASSERT( parent != NULL );\n               D_DEBUG_AT( Core_WM, \"  -- FOLLOW\\n\" );\n               apply_geometry( parent, clip, NULL, ret_rect );\n               break;\n\n          case DWGM_RECTANGLE:\n               D_DEBUG_AT( Core_WM, \"  -- RECTANGLE [%4d,%4d-%4dx%4d]\\n\", DFB_RECTANGLE_VALS( &geometry->rectangle ) );\n               *ret_rect = geometry->rectangle;\n               ret_rect->x += clip->x1;\n               ret_rect->y += clip->y1;\n               break;\n\n          case DWGM_LOCATION:\n               D_DEBUG_AT( Core_WM, \"  -- LOCATION [%.3f,%.3f-%.3fx%.3f]\\n\",\n                           geometry->location.x, geometry->location.y, geometry->location.w, geometry->location.h );\n               ret_rect->x = (int) (geometry->location.x * width  + 0.5f) + clip->x1;\n               ret_rect->y = (int) (geometry->location.y * height + 0.5f) + clip->y1;\n               ret_rect->w = (int) (geometry->location.w * width  + 0.5f);\n               ret_rect->h = (int) (geometry->location.h * height + 0.5f);\n               break;\n\n          default:\n               D_BUG( \"invalid geometry mode %u\", geometry->mode );\n               return;\n     }\n\n     D_DEBUG_AT( Core_WM, \"  -> %4d,%4d-%4dx%4d / clip %4d,%4d-%4dx%4d\\n\",\n                 DFB_RECTANGLE_VALS( ret_rect ), DFB_RECTANGLE_VALS_FROM_REGION( clip ) );\n\n     if (!dfb_rectangle_intersect_by_region( ret_rect, clip )) {\n          D_WARN( \"invalid geometry\" );\n          dfb_rectangle_from_region( ret_rect, clip );\n     }\n\n     D_DEBUG_AT( Core_WM, \"  -> %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS( ret_rect ) );\n}\n\nDFBResult\ndfb_wm_set_window_config( CoreWindow             *window,\n                          const CoreWindowConfig *config,\n                          DFBWindowConfigFlags    flags )\n{\n     const CoreWMFuncs *funcs;\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->SetWindowConfig != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_ASSERT( window != NULL );\n     D_MAGIC_ASSERT( window->stack, CoreWindowStack );\n\n     D_MAGIC_ASSERT( window->stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &window->stack->context->lock );\n\n     D_ASSERT( config != NULL );\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %4d,%4d-%4dx%4d, %p, 0x%x )\\n\", __FUNCTION__,\n                 window, DFB_RECTANGLE_VALS( &window->config.bounds ), config, flags );\n\n     if (dfb_config->single_window) {\n          bool        single_add = false;\n          bool        single_remove = false;\n          bool        single_update = false;\n          CoreWindow *config_window = window;\n\n          if (flags & DWCONF_OPACITY) {\n               if (config->opacity != 0) {\n                    if (window->config.opacity == 0) {\n                         if (fusion_vector_size( &window->stack->visible_windows ) == 0) {\n                              single_add = true;\n                              single_update = true;\n                         }\n                         else if (fusion_vector_size( &window->stack->visible_windows ) == 1) {\n                              config_window = fusion_vector_at( &window->stack->visible_windows, 0 );\n                              single_remove = true;\n                         }\n                         fusion_vector_add( &window->stack->visible_windows, window );\n                    }\n               }\n               else if (window->config.opacity != 0) {\n                    if (fusion_vector_size( &window->stack->visible_windows ) == 2) {\n                         single_add = true;\n                         single_update = true;\n                    }\n                    else if (fusion_vector_size( &window->stack->visible_windows ) == 1) {\n                         config_window = fusion_vector_at( &window->stack->visible_windows, 0 );\n                         single_remove = true;\n                    }\n\n                    int idx = fusion_vector_index_of( &window->stack->visible_windows, window );\n                    D_ASSERT( idx >= 0 );\n                    fusion_vector_remove( &window->stack->visible_windows, idx );\n               }\n          }\n\n          if (fusion_vector_size( &window->stack->visible_windows ) == 1)\n               single_update = true;\n\n          if (single_remove) {\n               D_DEBUG_AT( Core_WM, \"  -> single window optimisation: removing window %p\\n\", config_window );\n\n               dfb_layer_region_disable( config_window->region );\n               dfb_layer_region_enable( config_window->stack->context->primary.region );\n               dfb_windowstack_repaint_all( config_window->stack );\n          }\n          else {\n               if (single_add) {\n                    D_DEBUG_AT( Core_WM, \"  -> single window optimisation: adding window %p\\n\", config_window );\n\n                    if (!config_window->region) {\n                         DFBResult        ret;\n                         CoreLayerRegion *region = NULL;\n                         CoreSurface     *surface = config_window->surface;\n\n                         /* Create a region for the window. */\n                         ret = dfb_window_create_region( config_window, config_window->stack->context, surface,\n                                                         surface->config.format, surface->config.colorspace,\n                                                         surface->config.caps & (DSCAPS_INTERLACED | DSCAPS_SEPARATED |\n                                                                                 DSCAPS_PREMULTIPLIED | DSCAPS_DEPTH  |\n                                                                                 DSCAPS_SYSTEMONLY | DSCAPS_VIDEOONLY |\n                                                                                 DSCAPS_STATIC_ALLOC | DSCAPS_TRIPLE  |\n                                                                                 DSCAPS_GL),\n                                                         &region, &surface );\n                         if (ret) {\n                              D_DEBUG_AT( Core_WM, \"  -> region create failed!\\n\" );\n\n                              int idx = fusion_vector_index_of( &config_window->stack->visible_windows, config_window );\n                              D_ASSERT( idx >= 0 );\n                              fusion_vector_remove( &config_window->stack->visible_windows, idx );\n                         }\n                         else {\n                              D_ASSERT( config_window->surface == surface );\n\n                              /* Link the region into the window structure. */\n                              dfb_layer_region_link( &config_window->region, region );\n                              dfb_layer_region_unref( region );\n\n                              /* Link the surface into the window structure. */\n                              dfb_surface_link( &config_window->surface, surface );\n                              dfb_surface_unref( surface );\n                         }\n                    }\n\n                    if (config_window->region) {\n                         if (config_window->stack->context->primary.region->state & CLRSF_ENABLED)\n                              dfb_layer_region_disable( config_window->stack->context->primary.region );\n\n                         dfb_layer_region_enable( config_window->region );\n                    }\n               }\n\n               if (single_update) {\n                    CoreLayerRegionConfig      region_config = config_window->region->config;\n                    CoreLayerRegionConfigFlags region_flags  = CLRCF_NONE;\n\n                    D_DEBUG_AT( Core_WM, \"  -> single window optimisation: updating window %p\\n\", config_window );\n\n                    if (flags & DWCONF_OPACITY) {\n                         region_flags |= CLRCF_OPACITY;\n\n                         region_config.opacity = config->opacity;\n                    }\n\n                    if (flags & DWCONF_POSITION) {\n                         region_flags |= CLRCF_DEST;\n\n                         region_config.dest.x = config->bounds.x;\n                         region_config.dest.y = config->bounds.y;\n                    }\n\n                    if (flags & DWCONF_SIZE) {\n                         region_flags |= (CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_DEST);\n\n                         region_config.width  = config_window->surface->config.size.w;\n                         region_config.height = config_window->surface->config.size.h;\n\n                         region_config.dest.w = config->bounds.w;\n                         region_config.dest.h = config->bounds.h;\n                    }\n\n                    if (flags & DWCONF_DST_GEOMETRY) {\n                         DFBRegion clip = DFB_REGION_INIT_FROM_RECTANGLE( &config->bounds );\n\n                         region_flags |= CLRCF_DEST;\n                         apply_geometry( &config->dst_geometry, &clip, NULL, &region_config.dest );\n                    }\n\n                    if (flags & DWCONF_SRC_GEOMETRY) {\n                         DFBRegion clip = { 0, 0,\n                                            config_window->surface->config.size.w - 1,\n                                            config_window->surface->config.size.h - 1 };\n\n                         region_flags |= CLRCF_SOURCE;\n                         apply_geometry( &config->src_geometry, &clip, NULL, &region_config.source );\n                    }\n\n                    if (region_flags != CLRCF_NONE)\n                         dfb_layer_region_set_configuration( config_window->region, &region_config, region_flags );\n               }\n          }\n     }\n\n     return funcs->SetWindowConfig( window, wm_local->data, window->window_data, config, flags );\n}\n\nDFBResult\ndfb_wm_restack_window( CoreWindow *window,\n                       CoreWindow *relative,\n                       int         relation )\n{\n     const CoreWMFuncs *funcs;\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->RestackWindow != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_ASSERT( window != NULL );\n     D_MAGIC_ASSERT( window->stack, CoreWindowStack );\n\n     D_MAGIC_ASSERT( window->stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &window->stack->context->lock );\n\n     D_ASSERT( relative == NULL || relative == window || relation != 0 );\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %4d,%4d-%4dx%4d, %p, %d )\\n\", __FUNCTION__,\n                 window, DFB_RECTANGLE_VALS( &window->config.bounds ), relative, relation );\n\n     return funcs->RestackWindow( window, wm_local->data, window->window_data, relative,\n                                  relative ? relative->window_data : NULL, relation );\n}\n\nDFBResult\ndfb_wm_grab( CoreWindow *window,\n             CoreWMGrab *grab )\n{\n     const CoreWMFuncs *funcs;\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->Grab != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_ASSERT( window != NULL );\n     D_MAGIC_ASSERT( window->stack, CoreWindowStack );\n\n     D_MAGIC_ASSERT( window->stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &window->stack->context->lock );\n\n     D_ASSERT( grab != NULL );\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %4d,%4d-%4dx%4d, %u )\\n\", __FUNCTION__,\n                 window, DFB_RECTANGLE_VALS( &window->config.bounds ), grab->target );\n\n     return funcs->Grab( window, wm_local->data, window->window_data, grab );\n}\n\nDFBResult\ndfb_wm_ungrab( CoreWindow *window,\n               CoreWMGrab *grab )\n{\n     const CoreWMFuncs *funcs;\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->Ungrab != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_ASSERT( window != NULL );\n     D_MAGIC_ASSERT( window->stack, CoreWindowStack );\n\n     D_MAGIC_ASSERT( window->stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &window->stack->context->lock );\n\n     D_ASSERT( grab != NULL );\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %4d,%4d-%4dx%4d, %u )\\n\", __FUNCTION__,\n                 window, DFB_RECTANGLE_VALS( &window->config.bounds ), grab->target );\n\n     return funcs->Ungrab( window, wm_local->data, window->window_data, grab );\n}\n\nDFBResult\ndfb_wm_request_focus( CoreWindow *window )\n{\n     const CoreWMFuncs *funcs;\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->RequestFocus != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_ASSERT( window != NULL );\n     D_MAGIC_ASSERT( window->stack, CoreWindowStack );\n\n     D_MAGIC_ASSERT( window->stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &window->stack->context->lock );\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %4d,%4d-%4dx%4d )\\n\", __FUNCTION__,\n                 window, DFB_RECTANGLE_VALS( &window->config.bounds ) );\n\n     return funcs->RequestFocus( window, wm_local->data, window->window_data );\n}\n\nDFBResult\ndfb_wm_begin_updates( CoreWindow      *window,\n                      const DFBRegion *update )\n{\n     const CoreWMFuncs *funcs;\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->BeginUpdates != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_ASSERT( window != NULL );\n     D_MAGIC_ASSERT( window->stack, CoreWindowStack );\n\n     D_MAGIC_ASSERT( window->stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &window->stack->context->lock );\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %4d,%4d-%4dx%4d )\\n\", __FUNCTION__,\n                 window, DFB_RECTANGLE_VALS( &window->config.bounds ) );\n\n     return funcs->BeginUpdates( window, wm_local->data, window->window_data, update );\n}\n\nDFBResult\ndfb_wm_set_cursor_position( CoreWindow *window,\n                            int         x,\n                            int         y )\n{\n     const CoreWMFuncs *funcs;\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->SetCursorPosition != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_ASSERT( window != NULL );\n     D_MAGIC_ASSERT( window->stack, CoreWindowStack );\n\n     D_MAGIC_ASSERT( window->stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &window->stack->context->lock );\n\n     D_DEBUG_AT( Core_WM, \"%s( %p %4d,%4d )\\n\", __FUNCTION__, window, x, y );\n\n     return funcs->SetCursorPosition( window, wm_local->data, window->window_data, x, y );\n}\n\nDFBResult\ndfb_wm_update_stack( CoreWindowStack     *stack,\n                     const DFBRegion     *region,\n                     DFBSurfaceFlipFlags  flags )\n{\n     const CoreWMFuncs *funcs;\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->UpdateStack != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( stack->flags & CWSF_INITIALIZED );\n\n     D_MAGIC_ASSERT( stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &stack->context->lock );\n\n     DFB_REGION_ASSERT( region );\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %4d,%4d-%4dx%4d, 0x%x )\\n\", __FUNCTION__,\n                 stack, DFB_RECTANGLE_VALS_FROM_REGION( region ), flags );\n\n     return funcs->UpdateStack( stack, wm_local->data, stack->stack_data, region, flags );\n}\n\nDFBResult\ndfb_wm_update_window( CoreWindow          *window,\n                      const DFBRegion     *left_region,\n                      const DFBRegion     *right_region,\n                      DFBSurfaceFlipFlags  flags )\n{\n     bool               stereo;\n     const CoreWMFuncs *funcs;\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->UpdateWindow != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_ASSERT( window != NULL );\n     D_MAGIC_ASSERT( window->stack, CoreWindowStack );\n\n     D_MAGIC_ASSERT( window->stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &window->stack->context->lock );\n\n     DFB_REGION_ASSERT_IF( left_region );\n     DFB_REGION_ASSERT_IF( right_region );\n\n     stereo = window->caps & DWCAPS_STEREO;\n\n     D_DEBUG_AT( Core_WM, \"%s( %p, %u, %4d,%4d-%4dx%4d )\\n\", __FUNCTION__,\n                 window, window->object.id, DFB_RECTANGLE_VALS( &window->config.bounds ) );\n\n     if (left_region)\n          D_DEBUG_AT( Core_WM, \"  -> %s[%4d,%4d-%4dx%4d]\\n\",\n                      stereo ? \"Left: \" : \"\", DFB_RECTANGLE_VALS_FROM_REGION( left_region ) );\n\n     if (right_region && stereo)\n          D_DEBUG_AT( Core_WM, \"  -> Right: [%4d,%4d-%4dx%4d]\\n\",\n                      DFB_RECTANGLE_VALS_FROM_REGION( right_region ) );\n\n     D_DEBUG_AT( Core_WM, \"  -> flags: 0x%04x\\n\", flags );\n\n     return funcs->UpdateWindow( window, wm_local->data, window->window_data, left_region, right_region, flags );\n}\n\nDFBResult\ndfb_wm_update_cursor( CoreWindowStack       *stack,\n                      CoreCursorUpdateFlags  flags )\n{\n     const CoreWMFuncs *funcs;\n\n     D_ASSERT( wm_local != NULL );\n     D_ASSERT( wm_local->funcs != NULL );\n     D_ASSERT( wm_local->funcs->UpdateCursor != NULL );\n\n     funcs = wm_local->funcs;\n\n     D_MAGIC_ASSERT( stack, CoreWindowStack );\n     D_ASSERT( stack->flags & CWSF_INITIALIZED );\n\n     D_MAGIC_ASSERT( stack->context, CoreLayerContext );\n     FUSION_SKIRMISH_ASSERT( &stack->context->lock );\n\n     D_FLAGS_ASSERT( flags, CCUF_ALL );\n\n     if (dfb_config->no_cursor)\n          return DFB_OK;\n\n     return funcs->UpdateCursor( stack, wm_local->data, stack->stack_data, flags );\n}\n"
  },
  {
    "path": "src/core/wm.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__WM_H__\n#define __CORE__WM_H__\n\n#include <core/coretypes.h>\n#include <direct/modules.h>\n#include <directfb_windows.h>\n#include <fusion/reactor.h>\n\nDECLARE_MODULE_DIRECTORY( dfb_wm_modules );\n\n/**********************************************************************************************************************/\n\n#define DFB_CORE_WM_ABI_VERSION          10\n\n#define DFB_CORE_WM_INFO_NAME_LENGTH     60\n#define DFB_CORE_WM_INFO_VENDOR_LENGTH   80\n#define DFB_CORE_WM_INFO_URL_LENGTH     120\n#define DFB_CORE_WM_INFO_LICENSE_LENGTH  40\n\ntypedef struct {\n     int major; /* major version */\n     int minor; /* minor version */\n} CoreWMVersion;\n\ntypedef struct {\n     CoreWMVersion version;\n\n     char          name[DFB_CORE_WM_INFO_NAME_LENGTH];       /* Name of WM module */\n     char          vendor[DFB_CORE_WM_INFO_VENDOR_LENGTH];   /* Vendor (or author) of the module */\n     char          url[DFB_CORE_WM_INFO_URL_LENGTH];         /* URL for module updates */\n     char          license[DFB_CORE_WM_INFO_LICENSE_LENGTH]; /* License, e.g. 'LGPL' or 'proprietary' */\n\n     unsigned int  wm_data_size;                             /* WM local data size to allocate */\n     unsigned int  wm_shared_size;                           /* WM shared data size to allocate */\n     unsigned int  stack_data_size;                          /* WM shared stack data size to allocate */\n     unsigned int  window_data_size;                         /* WM shared window data size to allocate */\n} CoreWMInfo;\n\ntypedef struct {\n     CoreWMGrabTarget           target;\n\n     DFBInputDeviceKeySymbol    symbol;\n     DFBInputDeviceModifierMask modifiers;\n} CoreWMGrab;\n\ntypedef enum {\n     CCUF_NONE     = 0x00000000,\n\n     CCUF_ENABLE   = 0x00000001,\n     CCUF_DISABLE  = 0x00000002,\n\n     CCUF_POSITION = 0x00000010,\n     CCUF_SIZE     = 0x00000020,\n     CCUF_SHAPE    = 0x00000040,\n     CCUF_OPACITY  = 0x00000080,\n\n     CCUF_ALL      = 0x000000F3\n} CoreCursorUpdateFlags;\n\ntypedef DFBEnumerationResult (*CoreWMWindowCallback)( CoreWindow *window, void *ctx );\n\ntypedef struct {\n     void      (*GetWMInfo)          ( CoreWMInfo              *info );\n\n     DFBResult (*Initialize)         ( CoreDFB                 *core,\n                                       void                    *wm_data,\n                                       void                    *shared_data );\n\n     DFBResult (*Join)               ( CoreDFB                 *core,\n                                       void                    *wm_data,\n                                       void                    *shared_data );\n\n     DFBResult (*Shutdown)           ( bool                     emergency,\n                                       void                    *wm_data,\n                                       void                    *shared_data );\n\n     DFBResult (*Leave)              ( bool                     emergency,\n                                       void                    *wm_data,\n                                       void                    *shared_data );\n\n     DFBResult (*Suspend)            ( void                    *wm_data,\n                                       void                    *shared_data );\n\n     DFBResult (*Resume)             ( void                    *wm_data,\n                                       void                    *shared_data );\n\n     DFBResult (*PostInit)           ( void                    *wm_data,\n                                       void                    *shared_data );\n\n     DFBResult (*InitStack)          ( CoreWindowStack         *stack,\n                                       void                    *wm_data,\n                                       void                    *stack_data );\n\n     DFBResult (*CloseStack)         ( CoreWindowStack         *stack,\n                                       void                    *wm_data,\n                                       void                    *stack_data );\n\n     DFBResult (*SetActive)          ( CoreWindowStack         *stack,\n                                       void                    *wm_data,\n                                       void                    *stack_data,\n                                       bool                     active );\n\n     DFBResult (*ResizeStack)        ( CoreWindowStack         *stack,\n                                       void                    *wm_data,\n                                       void                    *stack_data,\n                                       int                      width,\n                                       int                      height );\n\n     DFBResult (*ProcessInput)       ( CoreWindowStack         *stack,\n                                       void                    *wm_data,\n                                       void                    *stack_data,\n                                       const DFBInputEvent     *event );\n\n     DFBResult (*FlushKeys)          ( CoreWindowStack         *stack,\n                                       void                    *wm_data,\n                                       void                    *stack_data );\n\n     DFBResult (*WindowAt)           ( CoreWindowStack         *stack,\n                                       void                    *wm_data,\n                                       void                    *stack_data,\n                                       int                      x,\n                                       int                      y,\n                                       CoreWindow             **ret_window );\n\n     DFBResult (*WindowLookup)       ( CoreWindowStack         *stack,\n                                       void                    *wm_data,\n                                       void                    *stack_data,\n                                       DFBWindowID              window_id,\n                                       CoreWindow             **ret_window );\n\n     DFBResult (*EnumWindows)        ( CoreWindowStack         *stack,\n                                       void                    *wm_data,\n                                       void                    *stack_data,\n                                       CoreWMWindowCallback     callback,\n                                       void                    *callback_ctx );\n\n    DFBResult (*SetWindowProperty)   ( CoreWindowStack         *stack,\n                                       void                    *wm_data,\n                                       void                    *stack_data,\n                                       CoreWindow              *window,\n                                       void                    *window_data,\n                                       const char              *key,\n                                       void                    *value,\n                                       void                   **old_value );\n\n    DFBResult (*GetWindowProperty)   ( CoreWindowStack         *stack,\n                                       void                    *wm_data,\n                                       void                    *stack_data,\n                                       CoreWindow              *window,\n                                       void                    *window_data,\n                                       const char              *key,\n                                       void                   **value );\n\n    DFBResult (*RemoveWindowProperty)( CoreWindowStack         *stack,\n                                       void                    *wm_data,\n                                       void                    *stack_data,\n                                       CoreWindow              *window,\n                                       void                    *window_data,\n                                       const char              *key,\n                                       void                   **value );\n\n     DFBResult (*GetInsets)          ( CoreWindowStack         *stack,\n                                       CoreWindow              *window,\n                                       DFBInsets               *insets );\n\n     DFBResult (*PreConfigureWindow) ( CoreWindowStack         *stack,\n                                       void                    *wm_data,\n                                       void                    *stack_data,\n                                       CoreWindow              *window,\n                                       void                    *window_data );\n\n     DFBResult (*AddWindow)          ( CoreWindowStack         *stack,\n                                       void                    *wm_data,\n                                       void                    *stack_data,\n                                       CoreWindow              *window,\n                                       void                    *window_data );\n\n     DFBResult (*RemoveWindow)       ( CoreWindowStack         *stack,\n                                       void                    *wm_data,\n                                       void                    *stack_data,\n                                       CoreWindow              *window,\n                                       void                    *window_data );\n\n     DFBResult (*SetWindowConfig)    ( CoreWindow              *window,\n                                       void                    *wm_data,\n                                       void                    *window_data,\n                                       const CoreWindowConfig  *config,\n                                       DFBWindowConfigFlags     flags );\n\n     DFBResult (*RestackWindow)      ( CoreWindow              *window,\n                                       void                    *wm_data,\n                                       void                    *window_data,\n                                       CoreWindow              *relative,\n                                       void                    *relative_data,\n                                       int                      relation );\n\n     DFBResult (*Grab)               ( CoreWindow              *window,\n                                       void                    *wm_data,\n                                       void                    *window_data,\n                                       CoreWMGrab              *grab );\n\n     DFBResult (*Ungrab)             ( CoreWindow              *window,\n                                       void                    *wm_data,\n                                       void                    *window_data,\n                                       CoreWMGrab              *grab );\n\n     DFBResult (*RequestFocus)       ( CoreWindow              *window,\n                                       void                    *wm_data,\n                                       void                    *window_data );\n\n     DFBResult (*BeginUpdates)       ( CoreWindow              *window,\n                                       void                    *wm_data,\n                                       void                    *window_data,\n                                       const DFBRegion         *update );\n\n     DFBResult (*SetCursorPosition)  ( CoreWindow              *window,\n                                       void                    *wm_data,\n                                       void                    *window_data,\n                                       int                      x,\n                                       int                      y );\n\n     DFBResult (*UpdateStack)        ( CoreWindowStack         *stack,\n                                       void                    *wm_data,\n                                       void                    *stack_data,\n                                       const DFBRegion         *region,\n                                       DFBSurfaceFlipFlags      flags );\n\n     DFBResult (*UpdateWindow)       ( CoreWindow              *window,\n                                       void                    *wm_data,\n                                       void                    *window_data,\n                                       const DFBRegion         *left_region,\n                                       const DFBRegion         *right_region,\n                                       DFBSurfaceFlipFlags      flags );\n\n     DFBResult (*UpdateCursor)       ( CoreWindowStack         *stack,\n                                       void                    *wm_data,\n                                       void                    *stack_data,\n                                       CoreCursorUpdateFlags    flags );\n} CoreWMFuncs;\n\ntypedef enum {\n     CORE_WM_WINDOW_ADD     = 0x00000001,\n     CORE_WM_WINDOW_REMOVE  = 0x00000002,\n     CORE_WM_WINDOW_CONFIG  = 0x00000003,\n     CORE_WM_WINDOW_STATE   = 0x00000004,\n     CORE_WM_WINDOW_RESTACK = 0x00000005,\n     CORE_WM_WINDOW_FOCUS   = 0x00000006,\n     CORE_WM_NUM_CHANNELS   = 0x00000007\n} CoreWMChannels;\n\ntypedef struct {\n     DFBWindowInfo        info;\n} CoreWM_WindowAdd;\n\ntypedef struct {\n     DFBWindowID          window_id;\n} CoreWM_WindowRemove;\n\ntypedef struct {\n     DFBWindowID          window_id;\n     DFBWindowConfig      config;\n     DFBWindowConfigFlags flags;\n} CoreWM_WindowConfig;\n\ntypedef struct {\n     DFBWindowID          window_id;\n     DFBWindowState       state;\n} CoreWM_WindowState;\n\ntypedef struct {\n     DFBWindowID          window_id;\n     unsigned int         index;\n} CoreWM_WindowRestack;\n\ntypedef struct {\n     DFBWindowID          window_id;\n} CoreWM_WindowFocus;\n\n/**********************************************************************************************************************/\n\nDFBResult dfb_wm_deactivate_all_stacks ( void                    *data );\n\nDFBResult dfb_wm_close_all_stacks      ( void                    *data );\n\nDFBResult dfb_wm_attach                ( CoreDFB                 *core,\n                                         int                      channel,\n                                         ReactionFunc             func,\n                                         void                    *ctx,\n                                         Reaction                *reaction );\n\nDFBResult dfb_wm_detach                ( CoreDFB                 *core,\n                                         Reaction                *reaction );\n\nDFBResult dfb_wm_dispatch_WindowAdd    ( CoreDFB                 *core,\n                                         CoreWindow              *window );\n\nDFBResult dfb_wm_dispatch_WindowRemove ( CoreDFB                 *core,\n                                         CoreWindow              *window );\n\nDFBResult dfb_wm_dispatch_WindowConfig ( CoreDFB                 *core,\n                                         CoreWindow              *window,\n                                         DFBWindowConfigFlags     flags );\n\nDFBResult dfb_wm_dispatch_WindowState  ( CoreDFB                 *core,\n                                         CoreWindow              *window );\n\nDFBResult dfb_wm_dispatch_WindowRestack( CoreDFB                 *core,\n                                         CoreWindow              *window,\n                                         unsigned int             index );\n\nDFBResult dfb_wm_dispatch_WindowFocus  ( CoreDFB                 *core,\n                                         CoreWindow              *window );\n\nvoid *dfb_wm_get_data                  ( void );\n\nDFBResult dfb_wm_post_init             ( CoreDFB                 *core );\n\nDFBResult dfb_wm_init_stack            ( CoreWindowStack         *stack );\n\nDFBResult dfb_wm_close_stack           ( CoreWindowStack         *stack );\n\nDFBResult dfb_wm_set_active            ( CoreWindowStack         *stack,\n                                         bool                     active );\n\nDFBResult dfb_wm_resize_stack          ( CoreWindowStack         *stack,\n                                         int                      width,\n                                         int                      height );\n\nDFBResult dfb_wm_process_input         ( CoreWindowStack         *stack,\n                                         const DFBInputEvent     *event );\n\nDFBResult dfb_wm_flush_keys            ( CoreWindowStack         *stack );\n\nDFBResult dfb_wm_window_at             ( CoreWindowStack         *stack,\n                                         int                      x,\n                                         int                      y,\n                                         CoreWindow             **ret_window );\n\nDFBResult dfb_wm_window_lookup         ( CoreWindowStack         *stack,\n                                         DFBWindowID              window_id,\n                                         CoreWindow             **ret_window );\n\nDFBResult dfb_wm_enum_windows          ( CoreWindowStack         *stack,\n                                         CoreWMWindowCallback     callback,\n                                         void                    *callback_ctx );\n\nDFBResult dfb_wm_get_insets            ( CoreWindowStack         *stack,\n                                         CoreWindow              *window,\n                                         DFBInsets               *ret_insets );\n\nDFBResult dfb_wm_preconfigure_window   ( CoreWindowStack         *stack,\n                                         CoreWindow              *window );\n\nDFBResult dfb_wm_add_window            ( CoreWindowStack         *stack,\n                                         CoreWindow              *window );\n\nDFBResult dfb_wm_remove_window         ( CoreWindowStack         *stack,\n                                         CoreWindow              *window );\n\nDFBResult dfb_wm_set_window_property   ( CoreWindowStack         *stack,\n                                         CoreWindow              *window,\n                                         const char              *key,\n                                         void                    *value,\n                                         void                   **ret_old_value );\n\nDFBResult dfb_wm_get_window_property   ( CoreWindowStack         *stack,\n                                         CoreWindow              *window,\n                                         const char              *key,\n                                         void                   **ret_value );\n\nDFBResult dfb_wm_remove_window_property( CoreWindowStack         *stack,\n                                         CoreWindow              *window,\n                                         const char              *key,\n                                         void                   **ret_value );\n\nDFBResult dfb_wm_set_window_config     ( CoreWindow              *window,\n                                         const CoreWindowConfig  *config,\n                                         DFBWindowConfigFlags     flags );\n\nDFBResult dfb_wm_restack_window        ( CoreWindow              *window,\n                                         CoreWindow              *relative,\n                                         int                      relation );\n\nDFBResult dfb_wm_grab                  ( CoreWindow              *window,\n                                         CoreWMGrab              *grab );\n\nDFBResult dfb_wm_ungrab                ( CoreWindow              *window,\n                                         CoreWMGrab              *grab );\n\nDFBResult dfb_wm_request_focus         ( CoreWindow              *window );\n\nDFBResult dfb_wm_begin_updates         ( CoreWindow              *window,\n                                         const DFBRegion         *update );\n\nDFBResult dfb_wm_set_cursor_position   ( CoreWindow              *window,\n                                         int                      x,\n                                         int                      y );\n\nDFBResult dfb_wm_update_stack          ( CoreWindowStack         *stack,\n                                         const DFBRegion         *region,\n                                         DFBSurfaceFlipFlags      flags );\n\nDFBResult dfb_wm_update_window         ( CoreWindow              *window,\n                                         const DFBRegion         *left_region,\n                                         const DFBRegion         *right_region,\n                                         DFBSurfaceFlipFlags      flags );\n\nDFBResult dfb_wm_update_cursor         ( CoreWindowStack         *stack,\n                                         CoreCursorUpdateFlags    flags );\n\n#endif\n"
  },
  {
    "path": "src/core/wm_module.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __CORE__WM_MODULE_H__\n#define __CORE__WM_MODULE_H__\n\n#include <core/wm.h>\n\n/**********************************************************************************************************************/\n\nstatic void      wm_get_info              ( CoreWMInfo              *info );\n\nstatic DFBResult wm_initialize            ( CoreDFB                 *core,\n                                            void                    *wm_data,\n                                            void                    *shared_data );\n\nstatic DFBResult wm_join                  ( CoreDFB                 *core,\n                                            void                    *wm_data,\n                                            void                    *shared_data );\n\nstatic DFBResult wm_shutdown              ( bool                     emergency,\n                                            void                    *wm_data,\n                                            void                    *shared_data );\n\nstatic DFBResult wm_leave                 ( bool                     emergency,\n                                            void                    *wm_data,\n                                            void                    *shared_data );\n\nstatic DFBResult wm_suspend               ( void                    *wm_data,\n                                            void                    *shared_data );\n\nstatic DFBResult wm_resume                ( void                    *wm_data,\n                                            void                    *shared_data );\n\nstatic DFBResult wm_post_init             ( void                    *wm_data,\n                                            void                    *shared_data );\n\nstatic DFBResult wm_init_stack            ( CoreWindowStack         *stack,\n                                            void                    *wm_data,\n                                            void                    *stack_data );\n\nstatic DFBResult wm_close_stack           ( CoreWindowStack         *stack,\n                                            void                    *wm_data,\n                                            void                    *stack_data );\n\nstatic DFBResult wm_set_active            ( CoreWindowStack         *stack,\n                                            void                    *wm_data,\n                                            void                    *stack_data,\n                                            bool                     active );\n\nstatic DFBResult wm_resize_stack          ( CoreWindowStack         *stack,\n                                            void                    *wm_data,\n                                            void                    *stack_data,\n                                            int                      width,\n                                            int                      height );\n\nstatic DFBResult wm_process_input         ( CoreWindowStack         *stack,\n                                            void                    *wm_data,\n                                            void                    *stack_data,\n                                            const DFBInputEvent     *event );\n\nstatic DFBResult wm_flush_keys            ( CoreWindowStack         *stack,\n                                            void                    *wm_data,\n                                            void                    *stack_data );\n\nstatic DFBResult wm_window_at             ( CoreWindowStack         *stack,\n                                            void                    *wm_data,\n                                            void                    *stack_data,\n                                            int                      x,\n                                            int                      y,\n                                            CoreWindow             **ret_window );\n\nstatic DFBResult wm_window_lookup         ( CoreWindowStack         *stack,\n                                            void                    *wm_data,\n                                            void                    *stack_data,\n                                            DFBWindowID              window_id,\n                                            CoreWindow             **ret_window );\n\nstatic DFBResult wm_enum_windows          ( CoreWindowStack         *stack,\n                                            void                    *wm_data,\n                                            void                    *stack_data,\n                                            CoreWMWindowCallback     callback,\n                                            void                    *callback_ctx );\n\nstatic DFBResult wm_get_insets            ( CoreWindowStack         *stack,\n                                            CoreWindow              *window,\n                                            DFBInsets               *insets );\n\nstatic DFBResult wm_preconfigure_window   ( CoreWindowStack         *stack,\n                                            void                    *wm_data,\n                                            void                    *stack_data,\n                                            CoreWindow              *window,\n                                            void                    *window_data );\n\nstatic DFBResult wm_set_window_property   ( CoreWindowStack         *stack,\n                                            void                    *wm_data,\n                                            void                    *stack_data,\n                                            CoreWindow              *window,\n                                            void                    *window_data,\n                                            const char              *key,\n                                            void                    *value,\n                                            void                   **ret_old_value );\n\nstatic DFBResult wm_get_window_property   ( CoreWindowStack         *stack,\n                                            void                    *wm_data,\n                                            void                    *stack_data,\n                                            CoreWindow              *window,\n                                            void                    *window_data,\n                                            const char              *key,\n                                            void                   **ret_value );\n\nstatic DFBResult wm_remove_window_property( CoreWindowStack         *stack,\n                                            void                    *wm_data,\n                                            void                    *stack_data,\n                                            CoreWindow              *window,\n                                            void                    *window_data,\n                                            const char              *key,\n                                            void                   **ret_value );\n\nstatic DFBResult wm_add_window            ( CoreWindowStack         *stack,\n                                            void                    *wm_data,\n                                            void                    *stack_data,\n                                            CoreWindow              *window,\n                                            void                    *window_data );\n\nstatic DFBResult wm_remove_window         ( CoreWindowStack         *stack,\n                                            void                    *wm_data,\n                                            void                    *stack_data,\n                                            CoreWindow              *window,\n                                            void                    *window_data );\n\nstatic DFBResult wm_set_window_config     ( CoreWindow              *window,\n                                            void                    *wm_data,\n                                            void                    *window_data,\n                                            const CoreWindowConfig  *config,\n                                            DFBWindowConfigFlags     flags );\n\nstatic DFBResult wm_restack_window        ( CoreWindow              *window,\n                                            void                    *wm_data,\n                                            void                    *window_data,\n                                            CoreWindow              *relative,\n                                            void                    *relative_data,\n                                            int                      relation );\n\nstatic DFBResult wm_grab                  ( CoreWindow              *window,\n                                            void                    *wm_data,\n                                            void                    *window_data,\n                                            CoreWMGrab              *grab );\n\nstatic DFBResult wm_ungrab                ( CoreWindow              *window,\n                                            void                    *wm_data,\n                                            void                    *window_data,\n                                            CoreWMGrab              *grab );\n\nstatic DFBResult wm_request_focus         ( CoreWindow              *window,\n                                            void                    *wm_data,\n                                            void                    *window_data );\n\nstatic DFBResult wm_begin_updates         ( CoreWindow              *window,\n                                            void                    *wm_data,\n                                            void                    *window_data,\n                                            const DFBRegion         *update );\n\nstatic DFBResult wm_set_cursor_position   ( CoreWindow              *window,\n                                            void                    *wm_data,\n                                            void                    *window_data,\n                                            int                      x,\n                                            int                      y );\n\nstatic DFBResult wm_update_stack          ( CoreWindowStack         *stack,\n                                            void                    *wm_data,\n                                            void                    *stack_data,\n                                            const DFBRegion         *region,\n                                            DFBSurfaceFlipFlags      flags );\n\nstatic DFBResult wm_update_window         ( CoreWindow              *window,\n                                            void                    *wm_data,\n                                            void                    *window_data,\n                                            const DFBRegion         *left_region,\n                                            const DFBRegion         *right_region,\n                                            DFBSurfaceFlipFlags      flags );\n\nstatic DFBResult wm_update_cursor         ( CoreWindowStack         *stack,\n                                            void                    *wm_data,\n                                            void                    *stack_data,\n                                            CoreCursorUpdateFlags    flags );\n\nstatic CoreWMFuncs wm_funcs = {\n     .GetWMInfo            = wm_get_info,\n     .Initialize           = wm_initialize,\n     .Join                 = wm_join,\n     .Shutdown             = wm_shutdown,\n     .Leave                = wm_leave,\n     .Suspend              = wm_suspend,\n     .Resume               = wm_resume,\n     .PostInit             = wm_post_init,\n     .InitStack            = wm_init_stack,\n     .CloseStack           = wm_close_stack,\n     .SetActive            = wm_set_active,\n     .ResizeStack          = wm_resize_stack,\n     .ProcessInput         = wm_process_input,\n     .FlushKeys            = wm_flush_keys,\n     .WindowAt             = wm_window_at,\n     .WindowLookup         = wm_window_lookup,\n     .EnumWindows          = wm_enum_windows,\n     .GetInsets            = wm_get_insets,\n     .PreConfigureWindow   = wm_preconfigure_window,\n     .SetWindowProperty    = wm_set_window_property,\n     .GetWindowProperty    = wm_get_window_property,\n     .RemoveWindowProperty = wm_remove_window_property,\n     .AddWindow            = wm_add_window,\n     .RemoveWindow         = wm_remove_window,\n     .SetWindowConfig      = wm_set_window_config,\n     .RestackWindow        = wm_restack_window,\n     .Grab                 = wm_grab,\n     .Ungrab               = wm_ungrab,\n     .RequestFocus         = wm_request_focus,\n     .BeginUpdates         = wm_begin_updates,\n     .SetCursorPosition    = wm_set_cursor_position,\n     .UpdateStack          = wm_update_stack,\n     .UpdateWindow         = wm_update_window,\n     .UpdateCursor         = wm_update_cursor\n};\n\n#define DFB_WINDOW_MANAGER(shortname)                  \\\n                                                       \\\n__dfb_constructor__                                    \\\nvoid                                                   \\\ndirectfb_##shortname##_ctor( void )                    \\\n{                                                      \\\n     direct_modules_register( &dfb_wm_modules,         \\\n                              DFB_CORE_WM_ABI_VERSION, \\\n                              #shortname,              \\\n                              &wm_funcs );             \\\n}\n\n#endif\n"
  },
  {
    "path": "src/directfb.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/direct.h>\n#include <direct/log.h>\n#include <direct/result.h>\n#include <direct/thread.h>\n#include <directfb_version.h>\n#include <idirectfb.h>\n#include <misc/conf.h>\n\nD_DEBUG_DOMAIN( DirectFB_Main, \"DirectFB/Main\", \"DirectFB Main Functions\" );\n\n/**********************************************************************************************************************/\n\nIDirectFB *idirectfb_singleton = NULL;\n\nstatic DirectMutex idirectfb_lock;\nstatic DirectOnce  idirectfb_init_once = DIRECT_ONCE_INIT();\n\nconst unsigned int directfb_major_version = DIRECTFB_MAJOR_VERSION;\nconst unsigned int directfb_minor_version = DIRECTFB_MINOR_VERSION;\nconst unsigned int directfb_micro_version = DIRECTFB_MICRO_VERSION;\n\n#if !DIRECT_BUILD_CTORS\nvoid __D_init_all( void );\nvoid __Fusion_init_all( void );\nvoid __DFB_init_all( void );\n#endif\n\n/**********************************************************************************************************************/\n\nconst char *\nDirectFBCheckVersion( unsigned int required_major,\n                      unsigned int required_minor,\n                      unsigned int required_micro )\n{\n     if (required_major > DIRECTFB_MAJOR_VERSION)\n          return \"DirectFB version too old (major mismatch)\";\n     if (required_major < DIRECTFB_MAJOR_VERSION)\n          return \"DirectFB version too new (major mismatch)\";\n     if (required_minor > DIRECTFB_MINOR_VERSION)\n          return \"DirectFB version too old (minor mismatch)\";\n     if (required_minor < DIRECTFB_MINOR_VERSION)\n          return \"DirectFB version too new (minor mismatch)\";\n     if (required_micro > DIRECTFB_MICRO_VERSION)\n          return \"DirectFB version too old (micro mismatch)\";\n\n     return NULL;\n}\n\nconst char *\nDirectFBUsageString()\n{\n     return dfb_config_usage;\n}\n\nDFBResult\nDirectFBInit( int   *argc,\n              char **argv[] )\n{\n     DFBResult ret;\n\n#if !DIRECT_BUILD_CTORS\n     if (!dfb_config) {\n          __D_init_all();\n          __Fusion_init_all();\n          __DFB_init_all();\n     }\n#endif\n\n     ret = dfb_config_init( argc, argv );\n     if (ret)\n          return ret;\n\n     return DFB_OK;\n}\n\nDFBResult\nDirectFBSetOption( const char *name,\n                   const char *value )\n{\n     DFBResult ret;\n\n     D_DEBUG_AT( DirectFB_Main, \"%s( '%s', '%s' )\\n\", __FUNCTION__, name, value );\n\n     if (!dfb_config) {\n          D_ERROR( \"DirectFB/Main: DirectFBInit() has to be called before DirectFBSetOption()!\\n\" );\n          return DFB_INIT;\n     }\n\n     if (!name)\n          return DFB_INVARG;\n\n     ret = dfb_config_set( name, value );\n     if (ret)\n          return ret;\n\n     return DFB_OK;\n}\n\nstatic void\ninit_once( void )\n{\n     direct_recursive_mutex_init( &idirectfb_lock );\n}\n\nDFBResult\nDirectFBCreate( IDirectFB **ret_interface )\n{\n     DFBResult  ret;\n     IDirectFB *dfb;\n\n     D_DEBUG_AT( DirectFB_Main, \"%s( %p )\\n\", __FUNCTION__, ret_interface );\n\n     if (!dfb_config) {\n          D_ERROR( \"DirectFB/Main: DirectFBInit() has to be called before DirectFBCreate()!\\n\" );\n          return DFB_INIT;\n     }\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     if (idirectfb_singleton) {\n          D_DEBUG_AT( DirectFB_Main, \"  -> using singleton %p\\n\", idirectfb_singleton );\n\n          idirectfb_singleton->AddRef( idirectfb_singleton );\n\n          *ret_interface = idirectfb_singleton;\n\n          return DFB_OK;\n     }\n\n     direct_initialize();\n\n     if (!(direct_config->quiet & DMT_BANNER) && dfb_config->banner) {\n          direct_log_printf( NULL,\n                             \"\\n\"\n                             \"   ~~~~~~~~~~~~~~~~~~~~~~~~~~| DirectFB %d.%d.%d %s |~~~~~~~~~~~~~~~~~~~~~~~~~~\\n\"\n                             \"        (c) 2017-2025  DirectFB2 Open Source Project (fork of DirectFB)\\n\"\n                             \"        (c) 2012-2016  DirectFB integrated media GmbH\\n\"\n                             \"        (c) 2001-2016  The world wide DirectFB Open Source Community\\n\"\n                             \"        (c) 2000-2004  Convergence (integrated media) GmbH\\n\"\n                             \"      ----------------------------------------------------------------\\n\"\n                             \"\\n\",\n                             DIRECTFB_MAJOR_VERSION, DIRECTFB_MINOR_VERSION, DIRECTFB_MICRO_VERSION,\n                             DIRECTFB_VERSION_VENDOR );\n     }\n\n     direct_once( &idirectfb_init_once, init_once );\n\n     direct_mutex_lock( &idirectfb_lock );\n\n     if (idirectfb_singleton) {\n          D_DEBUG_AT( DirectFB_Main, \"  -> using (new) singleton %p\\n\", idirectfb_singleton );\n\n          idirectfb_singleton->AddRef( idirectfb_singleton );\n\n          *ret_interface = idirectfb_singleton;\n\n          direct_mutex_unlock( &idirectfb_lock );\n\n          return DFB_OK;\n     }\n\n     DIRECT_ALLOCATE_INTERFACE( dfb, IDirectFB );\n\n     D_DEBUG_AT( DirectFB_Main, \"  -> setting singleton to %p (was %p)\\n\", dfb, idirectfb_singleton );\n\n     idirectfb_singleton = dfb;\n\n     ret = IDirectFB_Construct( dfb );\n     if (ret) {\n          D_DEBUG_AT( DirectFB_Main, \"  -> resetting singleton to NULL!\\n\" );\n          idirectfb_singleton = NULL;\n          direct_mutex_unlock( &idirectfb_lock );\n          return ret;\n     }\n\n     direct_mutex_unlock( &idirectfb_lock );\n\n     ret = IDirectFB_WaitInitialised( dfb );\n     if (ret) {\n          idirectfb_singleton = NULL;\n          dfb->Release( dfb );\n          return ret;\n     }\n\n     D_DEBUG_AT( DirectFB_Main, \"  -> done\\n\" );\n\n     *ret_interface = dfb;\n\n     return DFB_OK;\n}\n\nDFBResult\nDirectFBError( const char *msg,\n               DFBResult   result )\n{\n     if (msg)\n          direct_log_printf( NULL, \"(!) DirectFBError [%s]: %s\\n\", msg, DirectFBErrorString( result ) );\n     else\n          direct_log_printf( NULL, \"(!) DirectFBError: %s\\n\", DirectFBErrorString( result ) );\n\n     return result;\n}\n\nconst char *\nDirectFBErrorString( DFBResult result )\n{\n     return DirectResultString( result );\n}\n\nDFBResult\nDirectFBErrorFatal( const char *msg,\n                    DFBResult   result )\n{\n     DirectFBError( msg, result );\n\n     exit( result );\n}\n"
  },
  {
    "path": "src/directfb_result.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/result.h>\n#include <direct/util.h>\n#include <directfb.h>\n\n/**********************************************************************************************************************/\n\nstatic const char       *DFBResult__strings[DFB__RESULT_END - DFB__RESULT_BASE];\n\nstatic DirectResultType  DFBResult__type = {\n     0, 0, DFB__RESULT_BASE, DFBResult__strings, D_ARRAY_SIZE(DFBResult__strings)\n};\n\nvoid\nDFBResult__init( void )\n{\n     DFBResult__strings[0] = \"DFBResult\";\n\n     DFBResult__strings[D_RESULT_INDEX(DFB_NOVIDEOMEMORY)] = \"There's not enough video memory.\";\n     DFBResult__strings[D_RESULT_INDEX(DFB_MISSINGFONT)] = \"No font has been set.\";\n     DFBResult__strings[D_RESULT_INDEX(DFB_MISSINGIMAGE)] = \"No image has been set.\";\n     DFBResult__strings[D_RESULT_INDEX(DFB_NOALLOCATION)] = \"No allocation.\";\n     DFBResult__strings[D_RESULT_INDEX(DFB_NOBUFFER)] = \"No buffer.\";\n\n     DirectResultTypeRegister( &DFBResult__type );\n}\n\nvoid\nDFBResult__deinit( void )\n{\n     DirectResultTypeUnregister( &DFBResult__type );\n}\n"
  },
  {
    "path": "src/directfb_result.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DIRECTFB_RESULT_H__\n#define __DIRECTFB_RESULT_H__\n\n/**********************************************************************************************************************/\n\nvoid DFBResult__init  ( void );\nvoid DFBResult__deinit( void );\n\n#endif\n"
  },
  {
    "path": "src/display/idirectfbdisplaylayer.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreLayer.h>\n#include <core/CoreLayerContext.h>\n#include <core/CoreLayerRegion.h>\n#include <core/CoreSurface.h>\n#include <core/CoreWindowStack.h>\n#include <core/layers.h>\n#include <core/layer_context.h>\n#include <core/layer_control.h>\n#include <display/idirectfbdisplaylayer.h>\n#include <display/idirectfbscreen.h>\n#include <display/idirectfbsurface.h>\n#include <display/idirectfbsurface_layer.h>\n#include <windows/idirectfbwindow.h>\n\nD_DEBUG_DOMAIN( Layer, \"IDirectFBDisplayLayer\", \"IDirectFBDisplayLayer Interface\" );\n\n/**********************************************************************************************************************/\n\n/*\n * private data struct of IDirectFBDisplayLayer\n */\ntypedef struct {\n     int                              ref;              /* reference counter */\n\n     DFBDisplayLayerDescription       desc;             /* description of the layer's caps */\n\n     DFBDisplayLayerCooperativeLevel  level;            /* current cooperative level */\n\n     CoreScreen                      *screen;           /* layer's screen */\n     CoreLayer                       *layer;            /* the layer object */\n     CoreLayerContext                *context;          /* shared or exclusive context */\n     CoreLayerRegion                 *region;           /* primary region of the context */\n     CoreWindowStack                 *stack;            /* stack of shared context */\n\n     DFBBoolean                       switch_exclusive; /* switch to exclusive context after creation */\n\n     CoreDFB                         *core;\n     IDirectFB                       *idirectfb;\n} IDirectFBDisplayLayer_data;\n\n/**********************************************************************************************************************/\n\nstatic void\nIDirectFBDisplayLayer_Destruct( IDirectFBDisplayLayer *thiz )\n{\n     IDirectFBDisplayLayer_data *data = thiz->priv;\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     D_DEBUG_AT( Layer, \"  -> unref region...\\n\" );\n\n     dfb_layer_region_unref( data->region );\n\n     D_DEBUG_AT( Layer, \"  -> unref context...\\n\" );\n\n     dfb_layer_context_unref( data->context );\n\n     DIRECT_DEALLOCATE_INTERFACE( thiz );\n\n     D_DEBUG_AT( Layer, \"  -> done\\n\" );\n}\n\nstatic DirectResult\nIDirectFBDisplayLayer_AddRef( IDirectFBDisplayLayer *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref++;\n\n     return DFB_OK;\n}\n\nstatic DirectResult\nIDirectFBDisplayLayer_Release( IDirectFBDisplayLayer *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->ref == 0)\n          IDirectFBDisplayLayer_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_GetID( IDirectFBDisplayLayer *thiz,\n                             DFBDisplayLayerID     *ret_layer_id )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_layer_id)\n          return DFB_INVARG;\n\n     *ret_layer_id = dfb_layer_id_translated( data->layer );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_GetDescription( IDirectFBDisplayLayer      *thiz,\n                                      DFBDisplayLayerDescription *ret_desc )\n{\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_desc)\n          return DFB_INVARG;\n\n     *ret_desc = data->desc;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_GetSourceDescriptions( IDirectFBDisplayLayer            *thiz,\n                                             DFBDisplayLayerSourceDescription *ret_descriptions )\n{\n     int i;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_descriptions)\n          return DFB_INVARG;\n\n     if (!D_FLAGS_IS_SET( data->desc.caps, DLCAPS_SOURCES ))\n          return DFB_UNSUPPORTED;\n\n     for (i = 0; i < data->desc.sources; i++)\n          dfb_layer_get_source_info( data->layer, i, &ret_descriptions[i] );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_GetCurrentOutputField( IDirectFBDisplayLayer *thiz,\n                                             int                   *ret_field )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return CoreLayer_GetCurrentOutputField( data->layer, ret_field );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_GetSurface( IDirectFBDisplayLayer  *thiz,\n                                  IDirectFBSurface      **ret_interface )\n{\n     DFBResult              ret;\n     CoreLayerRegion       *region;\n     IDirectFBSurface      *iface;\n     IDirectFBSurface_data *surface_data;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     if (data->level == DLSCL_SHARED) {\n          D_WARN( \"letting unprivileged GetSurface() call pass until cooperative level handling is finished\" );\n     }\n\n     ret = CoreLayerContext_GetPrimaryRegion( data->context, true, &region );\n     if (ret)\n          return ret;\n\n     DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBSurface );\n\n     ret = IDirectFBSurface_Layer_Construct( iface, NULL, NULL, NULL, region, DSCAPS_NONE, data->core,\n                                             data->idirectfb );\n\n     surface_data = iface->priv;\n     if (!surface_data)\n          return DFB_DEAD;\n\n     /* Only perform single buffered clearing using a background when configured to do so and when the display layer\n        region is frozen. */\n     if (region->config.buffermode == DLBM_FRONTONLY && data->level != DLSCL_SHARED &&\n         D_FLAGS_IS_SET( region->state, CLRSF_FROZEN )) {\n          /* If a window stack is available, give it the opportunity to render the background (optionally based on\n             configuration) and flip the display layer so it is visible.\n             Otherwise, just directly flip the display layer and make it visible. */\n          if (data->stack) {\n               CoreWindowStack_RepaintAll( data->stack );\n          }\n          else {\n               CoreSurface_Flip2( surface_data->surface, DFB_FALSE, NULL, NULL, DSFLIP_NONE, -1 );\n          }\n     }\n\n     *ret_interface = ret ? NULL : iface;\n\n     dfb_layer_region_unref( region );\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_GetScreen( IDirectFBDisplayLayer  *thiz,\n                                 IDirectFBScreen       **ret_interface )\n{\n     DFBResult        ret;\n     IDirectFBScreen *iface;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBScreen );\n\n     ret = IDirectFBScreen_Construct( iface, data->screen );\n\n     *ret_interface = ret ? NULL : iface;\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetCooperativeLevel( IDirectFBDisplayLayer           *thiz,\n                                           DFBDisplayLayerCooperativeLevel  level )\n{\n     DFBResult         ret;\n     CoreLayerContext *context;\n     CoreLayerRegion  *region;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->level == level)\n          return DFB_OK;\n\n     switch (level) {\n          case DLSCL_SHARED:\n          case DLSCL_ADMINISTRATIVE:\n               if (data->level == DLSCL_EXCLUSIVE) {\n                    ret = CoreLayer_GetPrimaryContext( data->layer, false, &context );\n                    if (ret)\n                         return ret;\n\n                    ret = CoreLayerContext_GetPrimaryRegion( context, true, &region );\n                    if (ret) {\n                         dfb_layer_context_unref( context );\n                         return ret;\n                    }\n\n                    dfb_layer_region_unref( data->region );\n                    dfb_layer_context_unref( data->context );\n\n                    data->context = context;\n                    data->region  = region;\n                    data->stack   = dfb_layer_context_windowstack( data->context );\n               }\n\n               break;\n\n          case DLSCL_EXCLUSIVE:\n               ret = CoreLayer_CreateContext( data->layer, &context );\n               if (ret)\n                    return ret;\n\n               if (data->switch_exclusive) {\n                    ret = CoreLayer_ActivateContext( data->layer, context );\n                    if (ret) {\n                         dfb_layer_context_unref( context );\n                         return ret;\n                    }\n               }\n\n               ret = CoreLayerContext_GetPrimaryRegion( context, true, &region );\n               if (ret) {\n                    dfb_layer_context_unref( context );\n                    return ret;\n               }\n\n               dfb_layer_region_unref( data->region );\n               dfb_layer_context_unref( data->context );\n\n               data->context = context;\n               data->region  = region;\n               data->stack   = dfb_layer_context_windowstack( data->context );\n\n               break;\n\n          default:\n               return DFB_INVARG;\n     }\n\n     data->level = level;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_GetConfiguration( IDirectFBDisplayLayer *thiz,\n                                        DFBDisplayLayerConfig *ret_config )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_config)\n          return DFB_INVARG;\n\n     return dfb_layer_context_get_configuration( data->context, ret_config );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_TestConfiguration( IDirectFBDisplayLayer       *thiz,\n                                         const DFBDisplayLayerConfig *config,\n                                         DFBDisplayLayerConfigFlags  *ret_failed )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!config)\n          return DFB_INVARG;\n\n     if (((config->flags & DLCONF_WIDTH) && (config->width < 0)) ||\n         ((config->flags & DLCONF_HEIGHT) && (config->height < 0)))\n          return DFB_INVARG;\n\n     return CoreLayerContext_TestConfiguration( data->context, config, ret_failed );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetConfiguration( IDirectFBDisplayLayer       *thiz,\n                                        const DFBDisplayLayerConfig *config )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!config)\n          return DFB_INVARG;\n\n     if (((config->flags & DLCONF_WIDTH) && (config->width < 0)) ||\n         ((config->flags & DLCONF_HEIGHT) && (config->height < 0)))\n          return DFB_INVARG;\n\n     switch (data->level) {\n          case DLSCL_EXCLUSIVE:\n          case DLSCL_ADMINISTRATIVE:\n               return CoreLayerContext_SetConfiguration( data->context, config );\n\n          default:\n               break;\n     }\n\n     return DFB_ACCESSDENIED;\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetScreenLocation( IDirectFBDisplayLayer *thiz,\n                                         float                  x,\n                                         float                  y,\n                                         float                  width,\n                                         float                  height )\n{\n     DFBLocation location = { x, y, width, height };\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!D_FLAGS_IS_SET( data->desc.caps, DLCAPS_SCREEN_LOCATION ))\n          return DFB_UNSUPPORTED;\n\n     if (width <= 0 || height <= 0)\n          return DFB_INVARG;\n\n     if (data->level == DLSCL_SHARED)\n          return DFB_ACCESSDENIED;\n\n     return CoreLayerContext_SetScreenLocation( data->context, &location );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetScreenPosition( IDirectFBDisplayLayer *thiz,\n                                         int                    x,\n                                         int                    y )\n{\n     DFBPoint position;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p, %d,%d )\\n\", __FUNCTION__, thiz, x, y );\n\n     if (!D_FLAGS_IS_SET( data->desc.caps, DLCAPS_SCREEN_POSITION ))\n          return DFB_UNSUPPORTED;\n\n     if (data->level == DLSCL_SHARED)\n          return DFB_ACCESSDENIED;\n\n     position.x = x;\n     position.y = y;\n\n     return CoreLayerContext_SetScreenPosition( data->context, &position );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetScreenRectangle( IDirectFBDisplayLayer *thiz,\n                                          int                    x,\n                                          int                    y,\n                                          int                    width,\n                                          int                    height )\n{\n     DFBRectangle rect = { x, y, width, height };\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!D_FLAGS_IS_SET( data->desc.caps, DLCAPS_SCREEN_LOCATION ))\n          return DFB_UNSUPPORTED;\n\n     if (width <= 0 || height <= 0)\n          return DFB_INVARG;\n\n     if (data->level == DLSCL_SHARED)\n          return DFB_ACCESSDENIED;\n\n     return CoreLayerContext_SetScreenRectangle( data->context, &rect );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_GetStereoDepth( IDirectFBDisplayLayer *thiz,\n                                      bool                  *follow_video,\n                                      int                   *ret_z )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!(data->context->config.options & DLOP_LR_MONO) && !(data->context->config.options & DLOP_STEREO))\n          return DFB_INVARG;\n\n     if (!ret_z || !follow_video)\n          return DFB_INVARG;\n\n     return dfb_layer_context_get_stereo_depth( data->context, follow_video, ret_z );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetStereoDepth( IDirectFBDisplayLayer *thiz,\n                                      bool                   follow_video,\n                                      int                    z )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!follow_video && (z < -DLSO_FIXED_LIMIT || z > DLSO_FIXED_LIMIT))\n          return DFB_INVARG;\n\n     if (!(data->context->config.options & DLOP_LR_MONO) && !(data->context->config.options & DLOP_STEREO))\n          return DFB_INVARG;\n\n     if (data->level == DLSCL_SHARED)\n          return DFB_ACCESSDENIED;\n\n     return CoreLayerContext_SetStereoDepth( data->context, follow_video, z );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetOpacity( IDirectFBDisplayLayer *thiz,\n                                  u8                     opacity )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->level == DLSCL_SHARED)\n          return DFB_ACCESSDENIED;\n\n     return CoreLayerContext_SetOpacity( data->context, opacity );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetSourceRectangle( IDirectFBDisplayLayer *thiz,\n                                          int                    x,\n                                          int                    y,\n                                          int                    width,\n                                          int                    height )\n{\n     DFBRectangle source = { x, y, width, height };\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (x < 0 || y < 0 || width <= 0 || height <= 0)\n          return DFB_INVARG;\n\n     if (data->level == DLSCL_SHARED)\n          return DFB_ACCESSDENIED;\n\n     return CoreLayerContext_SetSourceRectangle( data->context, &source );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetFieldParity( IDirectFBDisplayLayer *thiz,\n                                      int                    field )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->level != DLSCL_EXCLUSIVE)\n          return DFB_ACCESSDENIED;\n\n     return CoreLayerContext_SetFieldParity( data->context, field );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetClipRegions( IDirectFBDisplayLayer *thiz,\n                                      const DFBRegion       *regions,\n                                      int                    num_regions,\n                                      DFBBoolean             positive )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!regions || num_regions < 1)\n          return DFB_INVARG;\n\n     if (num_regions > data->desc.clip_regions)\n          return DFB_UNSUPPORTED;\n\n     if (data->level != DLSCL_EXCLUSIVE)\n          return DFB_ACCESSDENIED;\n\n     return CoreLayerContext_SetClipRegions( data->context, regions, num_regions, positive );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetSrcColorKey( IDirectFBDisplayLayer *thiz,\n                                      u8                     r,\n                                      u8                     g,\n                                      u8                     b )\n{\n     DFBColorKey key;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->level == DLSCL_SHARED)\n          return DFB_ACCESSDENIED;\n\n     key.r     = r;\n     key.g     = g;\n     key.b     = b;\n     key.index = -1;\n\n     return CoreLayerContext_SetSrcColorKey( data->context, &key );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetDstColorKey( IDirectFBDisplayLayer *thiz,\n                                      u8                     r,\n                                      u8                     g,\n                                      u8                     b )\n{\n     DFBColorKey key;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->level == DLSCL_SHARED)\n          return DFB_ACCESSDENIED;\n\n     key.r     = r;\n     key.g     = g;\n     key.b     = b;\n     key.index = -1;\n\n     return CoreLayerContext_SetDstColorKey( data->context, &key );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_GetLevel( IDirectFBDisplayLayer *thiz,\n                                int                   *ret_level )\n{\n     DFBResult ret;\n     int       lvl;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_level)\n          return DFB_INVARG;\n\n     ret = dfb_layer_get_level( data->layer, &lvl );\n     if (ret)\n          return ret;\n\n     *ret_level = lvl;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetLevel( IDirectFBDisplayLayer *thiz,\n                                int                    level )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!D_FLAGS_IS_SET( data->desc.caps, DLCAPS_LEVELS ))\n          return DFB_UNSUPPORTED;\n\n     if (data->level == DLSCL_SHARED)\n          return DFB_ACCESSDENIED;\n\n     return CoreLayer_SetLevel( data->layer, level );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetBackgroundMode( IDirectFBDisplayLayer         *thiz,\n                                         DFBDisplayLayerBackgroundMode  mode )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->level == DLSCL_SHARED)\n          return DFB_ACCESSDENIED;\n\n     switch (mode) {\n          case DLBM_DONTCARE:\n          case DLBM_COLOR:\n          case DLBM_IMAGE:\n          case DLBM_TILE:\n               break;\n\n          default:\n               return DFB_INVARG;\n     }\n\n     if (!data->stack)\n          return DFB_OK;\n\n     return CoreWindowStack_BackgroundSetMode( data->stack, mode );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetBackgroundImage( IDirectFBDisplayLayer *thiz,\n                                          IDirectFBSurface      *surface )\n{\n     IDirectFBSurface_data *surface_data;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!surface)\n          return DFB_INVARG;\n\n     if (data->level == DLSCL_SHARED)\n          return DFB_ACCESSDENIED;\n\n     surface_data = surface->priv;\n     if (!surface_data)\n          return DFB_DEAD;\n\n     if (!surface_data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->stack)\n          return DFB_OK;\n\n     CoreGraphicsStateClient_Flush( &surface_data->state_client );\n\n     return CoreWindowStack_BackgroundSetImage( data->stack, surface_data->surface );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetBackgroundColor( IDirectFBDisplayLayer *thiz,\n                                          u8                     r,\n                                          u8                     g,\n                                          u8                     b,\n                                          u8                     a )\n{\n     DFBColor color = { a, r, g, b };\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->level == DLSCL_SHARED)\n          return DFB_ACCESSDENIED;\n\n     if (!data->stack)\n          return DFB_OK;\n\n     return CoreWindowStack_BackgroundSetColor( data->stack, &color );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_GetColorAdjustment( IDirectFBDisplayLayer *thiz,\n                                          DFBColorAdjustment    *ret_adj )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_adj)\n          return DFB_INVARG;\n\n     return dfb_layer_context_get_coloradjustment( data->context, ret_adj );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetColorAdjustment( IDirectFBDisplayLayer    *thiz,\n                                          const DFBColorAdjustment *adj )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!adj || (adj->flags & ~DCAF_ALL))\n          return DFB_INVARG;\n\n     if (data->level == DLSCL_SHARED)\n          return DFB_ACCESSDENIED;\n\n     if (!adj->flags)\n          return DFB_OK;\n\n     return CoreLayerContext_SetColorAdjustment( data->context, adj );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_CreateWindow( IDirectFBDisplayLayer       *thiz,\n                                    const DFBWindowDescription  *desc,\n                                    IDirectFBWindow            **ret_interface )\n{\n     CoreWindow           *window;\n     DFBResult             ret;\n     DFBWindowDescription  wd;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     memset( &wd, 0, sizeof(wd) );\n\n     wd.flags  = DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_POSX | DWDESC_POSY;\n     wd.width  = (desc->flags & DWDESC_WIDTH)  ? desc->width  : 480;\n     wd.height = (desc->flags & DWDESC_HEIGHT) ? desc->height : 300;\n     wd.posx   = (desc->flags & DWDESC_POSX)   ? desc->posx   : 100;\n     wd.posy   = (desc->flags & DWDESC_POSY)   ? desc->posy   : 100;\n\n     D_DEBUG_AT( Layer, \"%s( %p ) <- %4d,%4d-%4dx%4d )\\n\", __FUNCTION__, thiz, wd.posx, wd.posy, wd.width, wd.height );\n\n     if (wd.width < 1 || wd.width > 4096 || wd.height < 1 || wd.height > 4096)\n          return DFB_INVARG;\n\n     if (desc->flags & DWDESC_CAPS) {\n          if ((desc->caps & ~DWCAPS_ALL) || !ret_interface)\n               return DFB_INVARG;\n\n          wd.flags |= DWDESC_CAPS;\n          wd.caps   = desc->caps;\n     }\n\n     if (desc->flags & DWDESC_PIXELFORMAT) {\n          wd.flags       |= DWDESC_PIXELFORMAT;\n          wd.pixelformat  = desc->pixelformat;\n     }\n\n     if (desc->flags & DWDESC_COLORSPACE) {\n          wd.flags      |= DWDESC_COLORSPACE;\n          wd.colorspace  = desc->colorspace;\n     }\n\n     if (desc->flags & DWDESC_SURFACE_CAPS) {\n          wd.flags        |= DWDESC_SURFACE_CAPS;\n          wd.surface_caps  = desc->surface_caps;\n     }\n\n     if (desc->flags & DWDESC_PARENT) {\n          wd.flags     |= DWDESC_PARENT;\n          wd.parent_id  = desc->parent_id;\n     }\n\n     if (desc->flags & DWDESC_OPTIONS) {\n          wd.flags   |= DWDESC_OPTIONS;\n          wd.options  = desc->options;\n     }\n\n     if (desc->flags & DWDESC_STACKING) {\n          wd.flags    |= DWDESC_STACKING;\n          wd.stacking  = desc->stacking;\n     }\n\n     if (desc->flags & DWDESC_RESOURCE_ID) {\n          wd.flags       |= DWDESC_RESOURCE_ID;\n          wd.resource_id  = desc->resource_id;\n     }\n\n     if (desc->flags & DWDESC_TOPLEVEL_ID) {\n          wd.flags       |= DWDESC_TOPLEVEL_ID;\n          wd.toplevel_id  = desc->toplevel_id;\n     }\n\n     ret = CoreLayerContext_CreateWindow( data->context, &wd, &window );\n     if (ret)\n          return ret;\n\n     DIRECT_ALLOCATE_INTERFACE( *ret_interface, IDirectFBWindow );\n\n     return IDirectFBWindow_Construct( *ret_interface, window, data->layer, data->core, data->idirectfb, true );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_GetWindow( IDirectFBDisplayLayer  *thiz,\n                                 DFBWindowID             window_id,\n                                 IDirectFBWindow       **ret_interface )\n{\n     DFBResult   ret;\n     CoreWindow *window;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p, id %u )\\n\", __FUNCTION__, thiz, window_id );\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     /* IDirectFBWindow_Construct won't ref it, so we don't unref it */\n     ret = CoreLayerContext_FindWindow( data->context, window_id, &window );\n     if (ret)\n          return ret;\n\n     DIRECT_ALLOCATE_INTERFACE( *ret_interface, IDirectFBWindow );\n\n     return IDirectFBWindow_Construct( *ret_interface, window, data->layer, data->core, data->idirectfb, false );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_EnableCursor( IDirectFBDisplayLayer *thiz,\n                                    int                    enable )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->level == DLSCL_SHARED)\n          return DFB_ACCESSDENIED;\n\n     if (!data->stack)\n          return DFB_OK;\n\n     return CoreWindowStack_CursorEnable( data->stack, enable );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_GetCursorPosition( IDirectFBDisplayLayer *thiz,\n                                         int                   *ret_x,\n                                         int                   *ret_y )\n{\n     DFBResult ret;\n     DFBPoint  point;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_x && !ret_y)\n          return DFB_INVARG;\n\n     if (!data->stack)\n          return DFB_ACCESSDENIED;\n\n     ret = CoreWindowStack_CursorGetPosition( data->stack, &point );\n     if (ret)\n          return ret;\n\n     if (ret_x)\n          *ret_x = point.x;\n\n     if (ret_y)\n          *ret_y = point.y;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_WarpCursor( IDirectFBDisplayLayer *thiz,\n                                  int                    x,\n                                  int                    y )\n{\n     DFBPoint point = { x, y };\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->level == DLSCL_SHARED)\n          return DFB_ACCESSDENIED;\n\n     if (!data->stack)\n          return DFB_OK;\n\n     return CoreWindowStack_CursorWarp( data->stack, &point );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetCursorAcceleration( IDirectFBDisplayLayer *thiz,\n                                             int                    numerator,\n                                             int                    denominator,\n                                             int                    threshold )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (numerator < 0 || denominator < 1 || threshold < 0)\n          return DFB_INVARG;\n\n     if (data->level == DLSCL_SHARED)\n          return DFB_ACCESSDENIED;\n\n     if (!data->stack)\n          return DFB_OK;\n\n     return CoreWindowStack_CursorSetAcceleration( data->stack, numerator, denominator, threshold );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetCursorShape( IDirectFBDisplayLayer *thiz,\n                                      IDirectFBSurface      *shape,\n                                      int                    hot_x,\n                                      int                    hot_y )\n{\n     DFBPoint hotspot;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->level == DLSCL_SHARED)\n          return DFB_ACCESSDENIED;\n\n     if (!data->stack)\n          return DFB_OK;\n\n     if (shape) {\n          IDirectFBSurface_data *shape_data = shape->priv;\n\n          if (!shape_data)\n               return DFB_DEAD;\n\n          if (!shape_data->surface)\n               return DFB_DESTROYED;\n\n          if (hot_x < 0                                    || hot_y < 0 ||\n              hot_x >= shape_data->surface->config.size.w  || hot_y >= shape_data->surface->config.size.h)\n               return DFB_INVARG;\n\n          hotspot.x = hot_x;\n          hotspot.y = hot_y;\n\n          return CoreWindowStack_CursorSetShape( data->stack, shape_data->surface, &hotspot );\n     }\n     else {\n          hotspot.x = 0;\n          hotspot.y = 0;\n\n          return CoreWindowStack_CursorSetShape( data->stack, NULL, &hotspot );\n     }\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetCursorOpacity( IDirectFBDisplayLayer *thiz,\n                                        u8                     opacity )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->level == DLSCL_SHARED)\n          return DFB_ACCESSDENIED;\n\n     if (!data->stack)\n          return DFB_OK;\n\n     return CoreWindowStack_CursorSetOpacity( data->stack, opacity );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_WaitForSync( IDirectFBDisplayLayer *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return CoreLayer_WaitVSync( data->layer );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SwitchContext( IDirectFBDisplayLayer *thiz,\n                                     DFBBoolean             exclusive )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!exclusive && data->level == DLSCL_EXCLUSIVE) {\n          DFBResult         ret;\n          CoreLayerContext *context;\n\n          ret = CoreLayer_GetPrimaryContext( data->layer, false, &context );\n          if (ret)\n               return ret;\n\n          CoreLayer_ActivateContext( data->layer, context );\n\n          dfb_layer_context_unref( context );\n     }\n     else\n          CoreLayer_ActivateContext( data->layer, data->context );\n\n     data->switch_exclusive = exclusive;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetRotation( IDirectFBDisplayLayer *thiz,\n                                   int                    rotation )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->level == DLSCL_SHARED)\n          return DFB_ACCESSDENIED;\n\n     return CoreLayerContext_SetRotation( data->context, rotation );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_GetRotation( IDirectFBDisplayLayer *thiz,\n                                   int                   *ret_rotation )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_rotation)\n          return DFB_INVARG;\n\n     *ret_rotation = data->context->rotation;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_GetWindowByResourceID( IDirectFBDisplayLayer  *thiz,\n                                             unsigned long           resource_id,\n                                             IDirectFBWindow       **ret_interface )\n{\n     DFBResult   ret;\n     CoreWindow *window;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     ret = CoreLayerContext_FindWindowByResourceID( data->context, resource_id, &window );\n     if (ret)\n          return ret;\n\n     DIRECT_ALLOCATE_INTERFACE( *ret_interface, IDirectFBWindow );\n\n     return IDirectFBWindow_Construct( *ret_interface, window, data->layer, data->core, data->idirectfb, false );\n}\n\nstatic DFBResult\nIDirectFBDisplayLayer_SetSurface( IDirectFBDisplayLayer *thiz,\n                                  IDirectFBSurface      *surface )\n{\n     IDirectFBSurface_data *surface_data;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!surface)\n          return DFB_INVARG;\n\n     if (data->level != DLSCL_EXCLUSIVE)\n          return DFB_ACCESSDENIED;\n\n     surface_data = surface->priv;\n     if (!surface_data)\n          return DFB_DEAD;\n\n     return CoreLayerRegion_SetSurface( data->region, surface_data->surface );\n}\n\nDFBResult\nIDirectFBDisplayLayer_Construct( IDirectFBDisplayLayer *thiz,\n                                 CoreLayer             *layer,\n                                 CoreDFB               *core,\n                                 IDirectFB             *idirectfb )\n{\n     DFBResult         ret;\n     CoreLayerContext *context;\n     CoreLayerRegion  *region;\n\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBDisplayLayer )\n\n     D_DEBUG_AT( Layer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     ret = CoreLayer_GetPrimaryContext( layer, true, &context );\n     if (ret) {\n          DIRECT_DEALLOCATE_INTERFACE( thiz )\n          return ret;\n     }\n\n     ret = CoreLayerContext_GetPrimaryRegion( context, true, &region );\n     if (ret) {\n          dfb_layer_context_unref( context );\n          DIRECT_DEALLOCATE_INTERFACE( thiz )\n          return ret;\n     }\n\n     data->ref              = 1;\n     data->layer            = layer;\n     data->core             = core;\n     data->idirectfb        = idirectfb;\n     data->screen           = layer->screen;\n     data->context          = context;\n     data->region           = region;\n     data->stack            = dfb_layer_context_windowstack( context );\n     data->switch_exclusive = DFB_TRUE;\n\n     dfb_layer_get_description( data->layer, &data->desc );\n\n     thiz->AddRef                = IDirectFBDisplayLayer_AddRef;\n     thiz->Release               = IDirectFBDisplayLayer_Release;\n     thiz->GetID                 = IDirectFBDisplayLayer_GetID;\n     thiz->GetDescription        = IDirectFBDisplayLayer_GetDescription;\n     thiz->GetSourceDescriptions = IDirectFBDisplayLayer_GetSourceDescriptions;\n     thiz->GetCurrentOutputField = IDirectFBDisplayLayer_GetCurrentOutputField;\n     thiz->GetSurface            = IDirectFBDisplayLayer_GetSurface;\n     thiz->GetScreen             = IDirectFBDisplayLayer_GetScreen;\n     thiz->SetCooperativeLevel   = IDirectFBDisplayLayer_SetCooperativeLevel;\n     thiz->GetConfiguration      = IDirectFBDisplayLayer_GetConfiguration;\n     thiz->TestConfiguration     = IDirectFBDisplayLayer_TestConfiguration;\n     thiz->SetConfiguration      = IDirectFBDisplayLayer_SetConfiguration;\n     thiz->SetScreenLocation     = IDirectFBDisplayLayer_SetScreenLocation;\n     thiz->SetScreenPosition     = IDirectFBDisplayLayer_SetScreenPosition;\n     thiz->SetScreenRectangle    = IDirectFBDisplayLayer_SetScreenRectangle;\n     thiz->GetStereoDepth        = IDirectFBDisplayLayer_GetStereoDepth;\n     thiz->SetStereoDepth        = IDirectFBDisplayLayer_SetStereoDepth;\n     thiz->SetOpacity            = IDirectFBDisplayLayer_SetOpacity;\n     thiz->SetSourceRectangle    = IDirectFBDisplayLayer_SetSourceRectangle;\n     thiz->SetFieldParity        = IDirectFBDisplayLayer_SetFieldParity;\n     thiz->SetClipRegions        = IDirectFBDisplayLayer_SetClipRegions;\n     thiz->SetSrcColorKey        = IDirectFBDisplayLayer_SetSrcColorKey;\n     thiz->SetDstColorKey        = IDirectFBDisplayLayer_SetDstColorKey;\n     thiz->GetLevel              = IDirectFBDisplayLayer_GetLevel;\n     thiz->SetLevel              = IDirectFBDisplayLayer_SetLevel;\n     thiz->SetBackgroundMode     = IDirectFBDisplayLayer_SetBackgroundMode;\n     thiz->SetBackgroundImage    = IDirectFBDisplayLayer_SetBackgroundImage;\n     thiz->SetBackgroundColor    = IDirectFBDisplayLayer_SetBackgroundColor;\n     thiz->GetColorAdjustment    = IDirectFBDisplayLayer_GetColorAdjustment;\n     thiz->SetColorAdjustment    = IDirectFBDisplayLayer_SetColorAdjustment;\n     thiz->CreateWindow          = IDirectFBDisplayLayer_CreateWindow;\n     thiz->GetWindow             = IDirectFBDisplayLayer_GetWindow;\n     thiz->EnableCursor          = IDirectFBDisplayLayer_EnableCursor;\n     thiz->GetCursorPosition     = IDirectFBDisplayLayer_GetCursorPosition;\n     thiz->WarpCursor            = IDirectFBDisplayLayer_WarpCursor;\n     thiz->SetCursorAcceleration = IDirectFBDisplayLayer_SetCursorAcceleration;\n     thiz->SetCursorShape        = IDirectFBDisplayLayer_SetCursorShape;\n     thiz->SetCursorOpacity      = IDirectFBDisplayLayer_SetCursorOpacity;\n     thiz->WaitForSync           = IDirectFBDisplayLayer_WaitForSync;\n     thiz->SwitchContext         = IDirectFBDisplayLayer_SwitchContext;\n     thiz->SetRotation           = IDirectFBDisplayLayer_SetRotation;\n     thiz->GetRotation           = IDirectFBDisplayLayer_GetRotation;\n     thiz->GetWindowByResourceID = IDirectFBDisplayLayer_GetWindowByResourceID;\n     thiz->SetSurface            = IDirectFBDisplayLayer_SetSurface;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/display/idirectfbdisplaylayer.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DISPLAY__IDIRECTFBDISPLAYLAYER_H__\n#define __DISPLAY__IDIRECTFBDISPLAYLAYER_H__\n\n#include <core/coretypes.h>\n\n/*\n * initializes interface struct and private data\n */\nDFBResult IDirectFBDisplayLayer_Construct( IDirectFBDisplayLayer *thiz,\n                                           CoreLayer             *layer,\n                                           CoreDFB               *core,\n                                           IDirectFB             *idirectfb );\n\n#endif\n"
  },
  {
    "path": "src/display/idirectfbpalette.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreDFB.h>\n#include <core/CorePalette.h>\n#include <core/palette.h>\n#include <direct/memcpy.h>\n#include <display/idirectfbpalette.h>\n#include <gfx/convert.h>\n\nD_DEBUG_DOMAIN( Palette, \"IDirectFBPalette\", \"IDirectFBPalette Interface\" );\n\n/**********************************************************************************************************************/\n\nstatic void\nIDirectFBPalette_Destruct( IDirectFBPalette *thiz )\n{\n     IDirectFBPalette_data *data = thiz->priv;\n\n     D_DEBUG_AT( Palette, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->palette)\n          dfb_palette_unref( data->palette );\n\n     DIRECT_DEALLOCATE_INTERFACE( thiz );\n}\n\nstatic DirectResult\nIDirectFBPalette_AddRef( IDirectFBPalette *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBPalette )\n\n     D_DEBUG_AT( Palette, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref++;\n\n     return DFB_OK;\n}\n\nstatic DirectResult\nIDirectFBPalette_Release( IDirectFBPalette *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBPalette )\n\n     D_DEBUG_AT( Palette, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->ref == 0)\n          IDirectFBPalette_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBPalette_GetCapabilities( IDirectFBPalette       *thiz,\n                                  DFBPaletteCapabilities *ret_caps )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBPalette )\n\n     D_DEBUG_AT( Palette, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->palette)\n          return DFB_DESTROYED;\n\n     if (!ret_caps)\n          return DFB_INVARG;\n\n     *ret_caps = DPCAPS_NONE;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBPalette_GetSize( IDirectFBPalette *thiz,\n                          unsigned int     *ret_size )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBPalette )\n\n     D_DEBUG_AT( Palette, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->palette)\n          return DFB_DESTROYED;\n\n     if (!ret_size)\n          return DFB_INVARG;\n\n     *ret_size = data->palette->num_entries;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBPalette_SetEntries( IDirectFBPalette *thiz,\n                             const DFBColor   *entries,\n                             unsigned int      num_entries,\n                             unsigned int      offset )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBPalette )\n\n     D_DEBUG_AT( Palette, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->palette)\n          return DFB_DESTROYED;\n\n     if (!entries || offset + num_entries > data->palette->num_entries)\n          return DFB_INVARG;\n\n     return CorePalette_SetEntries( data->palette, entries, num_entries, offset );\n}\n\nstatic DFBResult\nIDirectFBPalette_GetEntries( IDirectFBPalette *thiz,\n                             DFBColor         *ret_entries,\n                             unsigned int      num_entries,\n                             unsigned int      offset )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBPalette )\n\n     D_DEBUG_AT( Palette, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->palette)\n          return DFB_DESTROYED;\n\n     if (!ret_entries || offset + num_entries > data->palette->num_entries)\n          return DFB_INVARG;\n\n     direct_memcpy( ret_entries, data->palette->entries + offset, num_entries * sizeof(DFBColor) );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBPalette_FindBestMatch( IDirectFBPalette *thiz,\n                                u8                r,\n                                u8                g,\n                                u8                b,\n                                u8                a,\n                                unsigned int     *ret_index )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBPalette )\n\n     D_DEBUG_AT( Palette, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_index)\n          return DFB_INVARG;\n\n     if (!data->palette)\n          return DFB_DESTROYED;\n\n     *ret_index = dfb_palette_search( data->palette, r, g, b, a );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBPalette_CreateCopy( IDirectFBPalette  *thiz,\n                             IDirectFBPalette **ret_interface )\n{\n     DFBResult         ret;\n     IDirectFBPalette *iface;\n     CorePalette      *palette = NULL;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBPalette )\n\n     D_DEBUG_AT( Palette, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->palette)\n          return DFB_DESTROYED;\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     ret = CoreDFB_CreatePalette( data->core, data->palette->num_entries, data->palette->colorspace, &palette );\n     if (ret)\n          return ret;\n\n     CorePalette_SetEntries( palette, data->palette->entries, palette->num_entries, 0 );\n\n     DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBPalette );\n\n     ret = IDirectFBPalette_Construct( iface, palette, data->core );\n\n     dfb_palette_unref( palette );\n\n     if (ret == DFB_OK)\n          *ret_interface = iface;\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBPalette_SetEntriesYUV( IDirectFBPalette  *thiz,\n                                const DFBColorYUV *entries,\n                                unsigned int       num_entries,\n                                unsigned int       offset )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBPalette )\n\n     D_DEBUG_AT( Palette, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->palette)\n          return DFB_DESTROYED;\n\n     if (!entries || offset + num_entries > data->palette->num_entries)\n          return DFB_INVARG;\n\n     return CorePalette_SetEntriesYUV( data->palette, entries, num_entries, offset );\n}\n\nstatic DFBResult\nIDirectFBPalette_GetEntriesYUV( IDirectFBPalette *thiz,\n                                DFBColorYUV      *ret_entries,\n                                unsigned int      num_entries,\n                                unsigned int      offset )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBPalette )\n\n     D_DEBUG_AT( Palette, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->palette)\n          return DFB_DESTROYED;\n\n     if (!ret_entries || offset + num_entries > data->palette->num_entries)\n          return DFB_INVARG;\n\n     direct_memcpy( ret_entries, data->palette->entries_yuv + offset, num_entries * sizeof(DFBColorYUV) );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBPalette_FindBestMatchYUV( IDirectFBPalette *thiz,\n                                   u8                y,\n                                   u8                u,\n                                   u8                v,\n                                   u8                a,\n                                   unsigned int     *ret_index )\n{\n     int r, g, b;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBPalette )\n\n     D_DEBUG_AT( Palette, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_index)\n          return DFB_INVARG;\n\n     if (!data->palette)\n          return DFB_DESTROYED;\n\n     if (data->palette->colorspace == DSCS_BT601)\n          YCBCR_TO_RGB_BT601( y, u, v, r, g, b );\n     else if (data->palette->colorspace == DSCS_RGB || data->palette->colorspace == DSCS_BT709)\n          YCBCR_TO_RGB_BT709( y, u, v, r, g, b );\n     else if (data->palette->colorspace == DSCS_BT2020)\n          YCBCR_TO_RGB_BT2020( y, u, v, r, g, b );\n     else\n          r = g = b = 0;\n\n     *ret_index = dfb_palette_search( data->palette, r, g, b, a );\n\n     return DFB_OK;\n}\n\nDFBResult\nIDirectFBPalette_Construct( IDirectFBPalette *thiz,\n                            CorePalette      *palette,\n                            CoreDFB          *core )\n{\n     DFBResult ret;\n\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBPalette )\n\n     D_DEBUG_AT( Palette, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     ret = dfb_palette_ref( palette );\n     if (ret) {\n          DIRECT_DEALLOCATE_INTERFACE( thiz );\n          return ret;\n     }\n\n     data->ref     = 1;\n     data->palette = palette;\n     data->core    = core;\n\n     thiz->AddRef           = IDirectFBPalette_AddRef;\n     thiz->Release          = IDirectFBPalette_Release;\n     thiz->GetCapabilities  = IDirectFBPalette_GetCapabilities;\n     thiz->GetSize          = IDirectFBPalette_GetSize;\n     thiz->SetEntries       = IDirectFBPalette_SetEntries;\n     thiz->GetEntries       = IDirectFBPalette_GetEntries;\n     thiz->FindBestMatch    = IDirectFBPalette_FindBestMatch;\n     thiz->CreateCopy       = IDirectFBPalette_CreateCopy;\n     thiz->SetEntriesYUV    = IDirectFBPalette_SetEntriesYUV;\n     thiz->GetEntriesYUV    = IDirectFBPalette_GetEntriesYUV;\n     thiz->FindBestMatchYUV = IDirectFBPalette_FindBestMatchYUV;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/display/idirectfbpalette.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DISPLAY__IDIRECTFBPALETTE_H__\n#define __DISPLAY__IDIRECTFBPALETTE_H__\n\n#include <core/coretypes.h>\n\n/*\n * private data struct of IDirectFBPalette\n */\ntypedef struct {\n     int          ref;     /* reference counter */\n\n     CorePalette *palette; /* the palette object */\n\n     CoreDFB     *core;\n} IDirectFBPalette_data;\n\n/*\n * initializes interface struct and private data\n */\nDFBResult IDirectFBPalette_Construct( IDirectFBPalette *thiz,\n                                      CorePalette      *palette,\n                                      CoreDFB          *core );\n\n#endif\n"
  },
  {
    "path": "src/display/idirectfbscreen.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreScreen.h>\n#include <core/layers.h>\n#include <core/screen.h>\n#include <core/screens.h>\n#include <display/idirectfbscreen.h>\n\nD_DEBUG_DOMAIN( Screen, \"IDirectFBScreen\", \"IDirectFBScreen Interface\" );\n\n/**********************************************************************************************************************/\n\n/*\n * private data struct of IDirectFBScreen\n */\ntypedef struct {\n     int                   ref;    /* reference counter */\n\n     CoreScreen           *screen; /* the screen object */\n\n     DFBScreenID           id;     /* screen id */\n     DFBScreenDescription  desc;   /* description of the display encoder capabilities */\n} IDirectFBScreen_data;\n\nstatic DFBResult PatchMixerConfig  ( DFBScreenMixerConfig   *patched, const DFBScreenMixerConfig   *patch );\nstatic DFBResult PatchEncoderConfig( DFBScreenEncoderConfig *patched, const DFBScreenEncoderConfig *patch );\nstatic DFBResult PatchOutputConfig ( DFBScreenOutputConfig  *patched, const DFBScreenOutputConfig  *patch );\n\ntypedef struct {\n     CoreScreen              *screen;\n     DFBDisplayLayerCallback  callback;\n     void                    *callback_ctx;\n} EnumDisplayLayers_Context;\n\nstatic DFBEnumerationResult EnumDisplayLayers_Callback( CoreLayer *layer, void *ctx );\n\n/**********************************************************************************************************************/\n\nstatic void\nIDirectFBScreen_Destruct( IDirectFBScreen *thiz )\n{\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     DIRECT_DEALLOCATE_INTERFACE( thiz );\n}\n\nstatic DirectResult\nIDirectFBScreen_AddRef( IDirectFBScreen *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref++;\n\n     return DFB_OK;\n}\n\nstatic DirectResult\nIDirectFBScreen_Release( IDirectFBScreen *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->ref == 0)\n          IDirectFBScreen_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBScreen_GetID( IDirectFBScreen *thiz,\n                       DFBScreenID     *ret_screen_id )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_screen_id)\n          return DFB_INVARG;\n\n     *ret_screen_id = data->id;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBScreen_GetDescription( IDirectFBScreen      *thiz,\n                                DFBScreenDescription *ret_desc )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_desc)\n          return DFB_INVARG;\n\n     *ret_desc = data->desc;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBScreen_GetSize( IDirectFBScreen *thiz,\n                         int             *ret_width,\n                         int             *ret_height )\n{\n     DFBResult    ret;\n     DFBDimension size;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_width && !ret_height)\n          return DFB_INVARG;\n\n     ret = CoreScreen_GetScreenSize( data->screen, &size );\n     if (ret)\n          return ret;\n\n     if (ret_width)\n          *ret_width = size.w;\n\n     if (ret_height)\n          *ret_height = size.h;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBScreen_EnumDisplayLayers( IDirectFBScreen         *thiz,\n                                   DFBDisplayLayerCallback  callback,\n                                   void                    *callbackdata )\n{\n     EnumDisplayLayers_Context context;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!callback)\n          return DFB_INVARG;\n\n     context.screen       = data->screen;\n     context.callback     = callback;\n     context.callback_ctx = callbackdata;\n\n     dfb_layers_enumerate( EnumDisplayLayers_Callback, &context );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBScreen_SetPowerMode( IDirectFBScreen    *thiz,\n                              DFBScreenPowerMode  mode )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     switch (mode) {\n          case DSPM_ON:\n          case DSPM_STANDBY:\n          case DSPM_SUSPEND:\n          case DSPM_OFF:\n               break;\n\n          default:\n               return DFB_INVARG;\n     }\n\n     return CoreScreen_SetPowerMode( data->screen, mode );\n}\n\nstatic DFBResult\nIDirectFBScreen_WaitForSync( IDirectFBScreen *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return CoreScreen_WaitVSync( data->screen );\n}\n\nstatic DFBResult\nIDirectFBScreen_GetMixerDescriptions( IDirectFBScreen           *thiz,\n                                      DFBScreenMixerDescription *ret_descriptions )\n{\n     int i;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_descriptions)\n          return DFB_INVARG;\n\n     if (!(data->desc.caps & DSCCAPS_MIXERS))\n          return DFB_UNSUPPORTED;\n\n     for (i = 0; i < data->desc.mixers; i++)\n          dfb_screen_get_mixer_info( data->screen, i, &ret_descriptions[i] );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBScreen_GetMixerConfiguration( IDirectFBScreen      *thiz,\n                                       int                   mixer,\n                                       DFBScreenMixerConfig *ret_config )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_config)\n          return DFB_INVARG;\n\n     if (!(data->desc.caps & DSCCAPS_MIXERS))\n          return DFB_UNSUPPORTED;\n\n     if (mixer < 0 || mixer >= data->desc.mixers)\n          return DFB_INVARG;\n\n     return dfb_screen_get_mixer_config( data->screen, mixer, ret_config );\n}\n\nstatic DFBResult\nIDirectFBScreen_TestMixerConfiguration( IDirectFBScreen            *thiz,\n                                        int                         mixer,\n                                        const DFBScreenMixerConfig *config,\n                                        DFBScreenMixerConfigFlags  *ret_failed )\n{\n     DFBResult            ret;\n     DFBScreenMixerConfig patched;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!config || (config->flags & ~DSMCONF_ALL))\n          return DFB_INVARG;\n\n     if (!(data->desc.caps & DSCCAPS_MIXERS))\n          return DFB_UNSUPPORTED;\n\n     if (mixer < 0 || mixer >= data->desc.mixers)\n          return DFB_INVARG;\n\n     /* Get the current configuration. */\n     ret = dfb_screen_get_mixer_config( data->screen, mixer, &patched );\n     if (ret)\n          return ret;\n\n     /* Patch the configuration. */\n     ret = PatchMixerConfig( &patched, config );\n     if (ret)\n          return ret;\n\n     /* Test the patched configuration. */\n     return CoreScreen_TestMixerConfig( data->screen, mixer, &patched, ret_failed );\n}\n\nstatic DFBResult\nIDirectFBScreen_SetMixerConfiguration( IDirectFBScreen            *thiz,\n                                       int                         mixer,\n                                       const DFBScreenMixerConfig *config )\n{\n     DFBResult            ret;\n     DFBScreenMixerConfig patched;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!config || (config->flags & ~DSMCONF_ALL))\n          return DFB_INVARG;\n\n     if (!(data->desc.caps & DSCCAPS_MIXERS))\n          return DFB_UNSUPPORTED;\n\n     if (mixer < 0 || mixer >= data->desc.mixers)\n          return DFB_INVARG;\n\n     /* Get the current configuration. */\n     ret = dfb_screen_get_mixer_config( data->screen, mixer, &patched );\n     if (ret)\n          return ret;\n\n     /* Patch the configuration. */\n     ret = PatchMixerConfig( &patched, config );\n     if (ret)\n          return ret;\n\n     /* Set the patched configuration. */\n     return CoreScreen_SetMixerConfig( data->screen, mixer, &patched );\n}\n\nstatic DFBResult\nIDirectFBScreen_GetEncoderDescriptions( IDirectFBScreen             *thiz,\n                                        DFBScreenEncoderDescription *ret_descriptions )\n{\n     int i;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_descriptions)\n          return DFB_INVARG;\n\n     if (!(data->desc.caps & DSCCAPS_ENCODERS))\n          return DFB_UNSUPPORTED;\n\n     for (i = 0; i < data->desc.encoders; i++)\n          dfb_screen_get_encoder_info( data->screen, i, &ret_descriptions[i] );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBScreen_GetEncoderConfiguration( IDirectFBScreen        *thiz,\n                                         int                     encoder,\n                                         DFBScreenEncoderConfig *ret_config )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_config)\n          return DFB_INVARG;\n\n     if (!(data->desc.caps & DSCCAPS_ENCODERS))\n          return DFB_UNSUPPORTED;\n\n     if (encoder < 0 || encoder >= data->desc.encoders)\n          return DFB_INVARG;\n\n     return dfb_screen_get_encoder_config( data->screen, encoder, ret_config );\n}\n\nstatic DFBResult\nIDirectFBScreen_TestEncoderConfiguration( IDirectFBScreen              *thiz,\n                                          int                           encoder,\n                                          const DFBScreenEncoderConfig *config,\n                                          DFBScreenEncoderConfigFlags  *ret_failed )\n{\n     DFBResult              ret;\n     DFBScreenEncoderConfig patched;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!config || (config->flags & ~DSECONF_ALL))\n          return DFB_INVARG;\n\n     if (!(data->desc.caps & DSCCAPS_ENCODERS))\n          return DFB_UNSUPPORTED;\n\n     if (encoder < 0 || encoder >= data->desc.encoders)\n          return DFB_INVARG;\n\n     /* Get the current configuration. */\n     ret = dfb_screen_get_encoder_config( data->screen, encoder, &patched );\n     if (ret)\n          return ret;\n\n     /* Patch the configuration. */\n     ret = PatchEncoderConfig( &patched, config );\n     if (ret)\n          return ret;\n\n     /* Test the patched configuration. */\n     return CoreScreen_TestEncoderConfig( data->screen, encoder, &patched, ret_failed );\n}\n\nstatic DFBResult\nIDirectFBScreen_SetEncoderConfiguration( IDirectFBScreen              *thiz,\n                                         int                           encoder,\n                                         const DFBScreenEncoderConfig *config )\n{\n     DFBResult              ret;\n     DFBScreenEncoderConfig patched;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!config || (config->flags & ~DSECONF_ALL))\n          return DFB_INVARG;\n\n     if (!(data->desc.caps & DSCCAPS_ENCODERS))\n          return DFB_UNSUPPORTED;\n\n     if (encoder < 0 || encoder >= data->desc.encoders)\n          return DFB_INVARG;\n\n     /* Get the current configuration. */\n     ret = dfb_screen_get_encoder_config( data->screen, encoder, &patched );\n     if (ret)\n          return ret;\n\n     /* Patch the configuration. */\n     ret = PatchEncoderConfig( &patched, config );\n     if (ret)\n          return ret;\n\n     /* Set the patched configuration. */\n     return CoreScreen_SetEncoderConfig( data->screen, encoder, &patched );\n}\n\nstatic DFBResult\nIDirectFBScreen_GetOutputDescriptions( IDirectFBScreen            *thiz,\n                                       DFBScreenOutputDescription *ret_descriptions )\n{\n     int i;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_descriptions)\n          return DFB_INVARG;\n\n     if (!(data->desc.caps & DSCCAPS_OUTPUTS))\n          return DFB_UNSUPPORTED;\n\n     for (i = 0; i < data->desc.outputs; i++)\n          dfb_screen_get_output_info( data->screen, i, &ret_descriptions[i] );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBScreen_GetOutputConfiguration( IDirectFBScreen       *thiz,\n                                        int                    output,\n                                        DFBScreenOutputConfig *ret_config )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_config)\n          return DFB_INVARG;\n\n     if (!(data->desc.caps & DSCCAPS_OUTPUTS))\n          return DFB_UNSUPPORTED;\n\n     if (output < 0 || output >= data->desc.outputs)\n          return DFB_INVARG;\n\n     return dfb_screen_get_output_config( data->screen, output, ret_config );\n}\n\nstatic DFBResult\nIDirectFBScreen_TestOutputConfiguration( IDirectFBScreen             *thiz,\n                                         int                          output,\n                                         const DFBScreenOutputConfig *config,\n                                         DFBScreenOutputConfigFlags  *ret_failed )\n{\n     DFBResult             ret;\n     DFBScreenOutputConfig patched;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!config || (config->flags & ~DSOCONF_ALL))\n          return DFB_INVARG;\n\n     if (!(data->desc.caps & DSCCAPS_OUTPUTS))\n          return DFB_UNSUPPORTED;\n\n     if (output < 0 || output >= data->desc.outputs)\n          return DFB_INVARG;\n\n     /* Get the current configuration. */\n     ret = dfb_screen_get_output_config( data->screen, output, &patched );\n     if (ret)\n          return ret;\n\n     /* Patch the configuration. */\n     ret = PatchOutputConfig( &patched, config );\n     if (ret)\n          return ret;\n\n     /* Test the patched configuration. */\n     return CoreScreen_TestOutputConfig( data->screen, output, &patched, ret_failed );\n}\n\nstatic DFBResult\nIDirectFBScreen_SetOutputConfiguration( IDirectFBScreen             *thiz,\n                                        int                          output,\n                                        const DFBScreenOutputConfig *config )\n{\n     DFBResult             ret;\n     DFBScreenOutputConfig patched;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!config || (config->flags & ~DSOCONF_ALL))\n          return DFB_INVARG;\n\n     if (!(data->desc.caps & DSCCAPS_OUTPUTS))\n          return DFB_UNSUPPORTED;\n\n     if (output < 0 || output >= data->desc.outputs)\n          return DFB_INVARG;\n\n     /* Get the current configuration. */\n     ret = dfb_screen_get_output_config( data->screen, output, &patched );\n     if (ret)\n          return ret;\n\n     /* Patch the configuration. */\n     ret = PatchOutputConfig( &patched, config );\n     if (ret)\n          return ret;\n\n     /* Set the patched configuration. */\n     return CoreScreen_SetOutputConfig( data->screen, output, &patched );\n}\n\nstatic DFBResult\nIDirectFBScreen_GetVSyncCount( IDirectFBScreen *thiz,\n                               unsigned long   *ret_count )\n{\n     DFBResult ret;\n     u64       count;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     D_ASSERT( ret_count != NULL );\n\n     ret = CoreScreen_GetVSyncCount( data->screen, &count );\n     if (ret)\n          return ret;\n\n     *ret_count = count;\n\n     return DFB_OK;\n}\n\nDFBResult\nIDirectFBScreen_Construct( IDirectFBScreen *thiz,\n                           CoreScreen      *screen )\n{\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBScreen )\n\n     D_DEBUG_AT( Screen, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref    = 1;\n     data->screen = screen;\n     data->id     = dfb_screen_id_translated( screen );\n\n     dfb_screen_get_info( screen, NULL, &data->desc );\n\n     thiz->AddRef                   = IDirectFBScreen_AddRef;\n     thiz->Release                  = IDirectFBScreen_Release;\n     thiz->GetID                    = IDirectFBScreen_GetID;\n     thiz->GetDescription           = IDirectFBScreen_GetDescription;\n     thiz->GetSize                  = IDirectFBScreen_GetSize;\n     thiz->EnumDisplayLayers        = IDirectFBScreen_EnumDisplayLayers;\n     thiz->SetPowerMode             = IDirectFBScreen_SetPowerMode;\n     thiz->WaitForSync              = IDirectFBScreen_WaitForSync;\n     thiz->GetMixerDescriptions     = IDirectFBScreen_GetMixerDescriptions;\n     thiz->GetMixerConfiguration    = IDirectFBScreen_GetMixerConfiguration;\n     thiz->TestMixerConfiguration   = IDirectFBScreen_TestMixerConfiguration;\n     thiz->SetMixerConfiguration    = IDirectFBScreen_SetMixerConfiguration;\n     thiz->GetEncoderDescriptions   = IDirectFBScreen_GetEncoderDescriptions;\n     thiz->GetEncoderConfiguration  = IDirectFBScreen_GetEncoderConfiguration;\n     thiz->TestEncoderConfiguration = IDirectFBScreen_TestEncoderConfiguration;\n     thiz->SetEncoderConfiguration  = IDirectFBScreen_SetEncoderConfiguration;\n     thiz->GetOutputDescriptions    = IDirectFBScreen_GetOutputDescriptions;\n     thiz->GetOutputConfiguration   = IDirectFBScreen_GetOutputConfiguration;\n     thiz->TestOutputConfiguration  = IDirectFBScreen_TestOutputConfiguration;\n     thiz->SetOutputConfiguration   = IDirectFBScreen_SetOutputConfiguration;\n     thiz->GetVSyncCount            = IDirectFBScreen_GetVSyncCount;\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic DFBResult\nPatchMixerConfig( DFBScreenMixerConfig       *patched,\n                  const DFBScreenMixerConfig *patch )\n{\n     /* Check for unsupported flags. */\n     if (patch->flags & ~patched->flags)\n          return DFB_UNSUPPORTED;\n\n     if (patch->flags & DSMCONF_TREE)\n          patched->tree = patch->tree;\n\n     if (patch->flags & DSMCONF_LEVEL)\n          patched->level = patch->level;\n\n     if (patch->flags & DSMCONF_LAYERS)\n          patched->layers = patch->layers;\n\n     if (patch->flags & DSMCONF_BACKGROUND)\n          patched->background = patch->background;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nPatchEncoderConfig( DFBScreenEncoderConfig       *patched,\n                    const DFBScreenEncoderConfig *patch )\n{\n     /* Check for unsupported flags. */\n     if (patch->flags & ~patched->flags)\n          return DFB_UNSUPPORTED;\n\n     if (patch->flags & DSECONF_RESOLUTION)\n          patched->resolution = patch->resolution;\n\n     if (patch->flags & DSECONF_FREQUENCY)\n          patched->frequency = patch->frequency;\n\n     /* If you have set a DSECONF_TV_STANDARD, this will override the resolution and frequency chosen above.*/\n     if (patch->flags & DSECONF_TV_STANDARD) {\n          patched->tv_standard = patch->tv_standard;\n          switch (patched->tv_standard) {\n               case DSETV_PAL:\n               case DSETV_PAL_BG:\n               case DSETV_PAL_I:\n               case DSETV_PAL_N:\n               case DSETV_PAL_NC:\n                    patched->resolution = DSOR_720_576;\n                    patched->frequency = DSEF_50HZ;\n                    break;\n\n               case DSETV_PAL_60:\n               case DSETV_PAL_M:\n                    patched->resolution = DSOR_720_480;\n                    patched->frequency = DSEF_59_94HZ;\n                    break;\n\n               case DSETV_SECAM:\n                    patched->resolution = DSOR_720_576;\n                    patched->frequency = DSEF_50HZ;\n                    break;\n\n               case DSETV_NTSC:\n               case DSETV_NTSC_M_JPN:\n               case DSETV_NTSC_443:\n                    patched->resolution = DSOR_720_480;\n                    patched->frequency = DSEF_59_94HZ;\n                    break;\n\n               default:\n                    break;\n          }\n     }\n\n     if (patch->flags & DSECONF_TEST_PICTURE)\n          patched->test_picture = patch->test_picture;\n\n     if (patch->flags & DSECONF_MIXER)\n          patched->mixer = patch->mixer;\n\n     if (patch->flags & DSECONF_OUT_SIGNALS)\n          patched->out_signals = patch->out_signals;\n\n     if (patch->flags & DSECONF_SCANMODE)\n          patched->scanmode = patch->scanmode;\n\n     if (patch->flags & DSECONF_TEST_COLOR)\n          patched->test_color = patch->test_color;\n\n     if (patch->flags & DSECONF_ADJUSTMENT)\n          patched->adjustment = patch->adjustment;\n\n     if (patch->flags & DSECONF_CONNECTORS)\n          patched->out_connectors = patch->out_connectors;\n\n     if (patch->flags & DSECONF_SLOW_BLANKING)\n          patched->slow_blanking = patch->slow_blanking;\n\n     if (patch->flags & DSECONF_FRAMING)\n          patched->framing = patch->framing;\n\n     if (patch->flags & DSECONF_ASPECT_RATIO)\n          patched->aspect_ratio = patch->aspect_ratio;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nPatchOutputConfig( DFBScreenOutputConfig       *patched,\n                   const DFBScreenOutputConfig *patch )\n{\n     /* Check for unsupported flags. */\n     if (patch->flags & ~patched->flags)\n          return DFB_UNSUPPORTED;\n\n     if (patch->flags & DSOCONF_ENCODER)\n          patched->encoder = patch->encoder;\n\n     if (patch->flags & DSOCONF_SIGNALS)\n          patched->out_signals = patch->out_signals;\n\n     if (patch->flags & DSOCONF_CONNECTORS)\n          patched->out_connectors = patch->out_connectors;\n\n     if (patch->flags & DSOCONF_SLOW_BLANKING)\n          patched->slow_blanking = patch->slow_blanking;\n\n     if (patch->flags & DSOCONF_RESOLUTION)\n          patched->resolution = patch->resolution;\n\n     return DFB_OK;\n}\n\nstatic DFBEnumerationResult\nEnumDisplayLayers_Callback( CoreLayer *layer,\n                            void      *ctx )\n{\n     DFBDisplayLayerDescription  desc;\n     DFBDisplayLayerID           id;\n     EnumDisplayLayers_Context  *context = ctx;\n\n     if (layer->screen != context->screen)\n          return DFENUM_OK;\n\n     id = dfb_layer_id_translated( layer );\n\n     if (dfb_config->primary_only && id != DLID_PRIMARY)\n          return DFENUM_OK;\n\n     dfb_layer_get_description( layer, &desc );\n\n     return context->callback( id, desc, context->callback_ctx );\n}\n"
  },
  {
    "path": "src/display/idirectfbscreen.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DISPLAY__IDIRECTFBSCREEN_H__\n#define __DISPLAY__IDIRECTFBSCREEN_H__\n\n#include <core/coretypes.h>\n\n/*\n * initializes interface struct and private data\n */\nDFBResult IDirectFBScreen_Construct( IDirectFBScreen *thiz,\n                                     CoreScreen      *screen );\n\n#endif\n"
  },
  {
    "path": "src/display/idirectfbsurface.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreDFB.h>\n#include <core/CoreSurface.h>\n#include <core/CoreSurfaceClient.h>\n#include <core/core.h>\n#include <core/fonts.h>\n#include <core/palette.h>\n#include <core/surface_allocation.h>\n#include <core/surface_client.h>\n#include <core/surface_pool.h>\n#include <direct/memcpy.h>\n#include <direct/thread.h>\n#include <display/idirectfbpalette.h>\n#include <display/idirectfbsurface.h>\n#include <display/idirectfbsurfaceallocation.h>\n#include <gfx/convert.h>\n#include <input/idirectfbeventbuffer.h>\n#include <media/idirectfbfont.h>\n\nD_DEBUG_DOMAIN( Surface,         \"IDirectFBSurface\",         \"IDirectFBSurface Interface\" );\nD_DEBUG_DOMAIN( Surface_Updates, \"IDirectFBSurface/Updates\", \"IDirectFBSurface Interface Updates\" );\n\n/**********************************************************************************************************************/\n\nstatic DFBResult\nregister_prealloc( IDirectFBSurface_data *data )\n{\n     DFBResult    ret;\n     unsigned int i;\n\n     if (data->surface->config.caps & DSCAPS_TRIPLE)\n          data->memory_permissions_count = 3;\n     else if (data->surface->config.caps & DSCAPS_DOUBLE)\n          data->memory_permissions_count = 2;\n     else\n          data->memory_permissions_count = 1;\n\n     for (i = 0; i < data->memory_permissions_count; i++) {\n          ret = dfb_core_memory_permissions_add( data->core, CMPF_READ | CMPF_WRITE,\n                                                 data->surface->config.preallocated[i].addr,\n                                                 data->surface->config.preallocated[i].pitch *\n                                                 DFB_PLANE_MULTIPLY( data->surface->config.format,\n                                                                     data->surface->config.size.h ),\n                                                 &data->memory_permissions[i] );\n          if (ret)\n               goto error;\n     }\n\n     return DFB_OK;\n\nerror:\n     for (--i; i >= 0; i--)\n          dfb_core_memory_permissions_remove( data->core, data->memory_permissions[i] );\n\n     data->memory_permissions_count = 0;\n\n     return ret;\n}\n\nstatic DFBResult\nunregister_prealloc( IDirectFBSurface_data *data )\n{\n     unsigned int i;\n\n     for (i = 0; i < data->memory_permissions_count; i++)\n          dfb_core_memory_permissions_remove( data->core, data->memory_permissions[i] );\n\n     data->memory_permissions_count = 0;\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nvoid\nIDirectFBSurface_Destruct( IDirectFBSurface *thiz )\n{\n     IDirectFBSurface_data *data = thiz->priv;\n     IDirectFBSurface      *parent;\n     unsigned int           i;\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     direct_mutex_lock( &data->children_lock );\n\n     while (data->children_free) {\n          IDirectFBSurface_data *child_data;\n          IDirectFBSurface      *child;\n\n          child_data = (IDirectFBSurface_data*) data->children_free;\n\n          direct_list_remove( &data->children_free, &child_data->link );\n\n          direct_mutex_unlock( &data->children_lock );\n\n          child = child_data->thiz;\n\n          child->Release( child );\n\n          direct_mutex_lock( &data->children_lock );\n     }\n\n     direct_mutex_unlock( &data->children_lock );\n\n     if (data->memory_permissions_count) {\n          CoreDFB_WaitIdle( data->core );\n\n          unregister_prealloc( data );\n     }\n     else\n          CoreGraphicsStateClient_Flush( &data->state_client );\n\n     if (data->surface_client)\n          dfb_surface_client_unref( data->surface_client );\n\n     parent = data->parent;\n     if (parent) {\n          IDirectFBSurface_data *parent_data;\n\n          D_MAGIC_ASSERT( parent, DirectInterface );\n\n          parent_data = parent->priv;\n\n          D_ASSERT( parent_data != NULL );\n\n          direct_mutex_lock( &parent_data->children_lock );\n\n          direct_list_remove( &parent_data->children_data, &data->link );\n\n          direct_mutex_unlock( &parent_data->children_lock );\n     }\n\n     if (data->surface) {\n          dfb_surface_detach( data->surface, &data->reaction );\n          dfb_surface_detach( data->surface, &data->reaction_frame );\n     }\n\n     CoreGraphicsStateClient_Deinit( &data->state_client );\n\n     dfb_state_stop_drawing( &data->state );\n\n     dfb_state_set_destination( &data->state, NULL );\n     dfb_state_set_source( &data->state, NULL );\n     dfb_state_set_source_mask( &data->state, NULL );\n     dfb_state_set_source2( &data->state, NULL );\n\n     dfb_state_destroy( &data->state );\n\n     if (data->font)\n          data->font->Release( data->font );\n\n     if (data->surface) {\n          if (data->locked)\n               dfb_surface_unlock_buffer( data->surface, &data->lock );\n\n          dfb_surface_unref( data->surface );\n     }\n\n     for (i = 0; i < data->local_buffer_count; i++) {\n          if (data->allocations[i]) {\n               dfb_surface_allocation_unref( data->allocations[i] );\n               data->allocations[i] = NULL;\n          }\n     }\n\n     direct_mutex_deinit( &data->children_lock );\n\n     direct_waitqueue_deinit( &data->back_buffer_wq );\n     direct_mutex_deinit( &data->back_buffer_lock );\n\n     direct_mutex_deinit( &data->surface_client_lock );\n\n     DIRECT_DEALLOCATE_INTERFACE( thiz );\n\n     if (parent)\n          parent->Release( parent );\n}\n\nstatic DirectResult\nIDirectFBSurface_AddRef( IDirectFBSurface *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref++;\n\n     return DFB_OK;\n}\n\nstatic DirectResult\nIDirectFBSurface_Release( IDirectFBSurface *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->ref == 1 && data->parent && dfb_config->subsurface_caching) {\n          IDirectFBSurface_data *parent_data;\n\n          D_MAGIC_ASSERT( data->parent, DirectInterface );\n\n          parent_data = data->parent->priv;\n\n          D_ASSERT( parent_data != NULL );\n\n          direct_mutex_lock( &parent_data->children_lock );\n\n          direct_list_remove( &parent_data->children_data, &data->link );\n          direct_list_append( &parent_data->children_free, &data->link );\n\n          direct_mutex_unlock( &parent_data->children_lock );\n     }\n\n     if (--data->ref == 0)\n          IDirectFBSurface_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_GetCapabilities( IDirectFBSurface       *thiz,\n                                  DFBSurfaceCapabilities *ret_caps )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_caps)\n          return DFB_INVARG;\n\n     *ret_caps = data->caps;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_GetPosition( IDirectFBSurface *thiz,\n                              int              *ret_x,\n                              int              *ret_y )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_x && !ret_y)\n          return DFB_INVARG;\n\n     if (ret_x)\n          *ret_x = data->area.wanted.x;\n\n     if (ret_y)\n          *ret_y = data->area.wanted.y;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_GetSize( IDirectFBSurface *thiz,\n                          int              *ret_width,\n                          int              *ret_height )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_width && !ret_height)\n          return DFB_INVARG;\n\n     if (ret_width)\n          *ret_width = data->area.wanted.w;\n\n     if (ret_height)\n          *ret_height = data->area.wanted.h;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_GetVisibleRectangle( IDirectFBSurface *thiz,\n                                      DFBRectangle     *ret_rect )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_rect)\n          return DFB_INVARG;\n\n     ret_rect->x = data->area.current.x - data->area.wanted.x;\n     ret_rect->y = data->area.current.y - data->area.wanted.y;\n     ret_rect->w = data->area.current.w;\n     ret_rect->h = data->area.current.h;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_GetPixelFormat( IDirectFBSurface      *thiz,\n                                 DFBSurfacePixelFormat *ret_pixelformat )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!ret_pixelformat)\n          return DFB_INVARG;\n\n     *ret_pixelformat = data->surface->config.format;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_GetColorSpace( IDirectFBSurface     *thiz,\n                                DFBSurfaceColorSpace *ret_colorspace )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!ret_colorspace)\n          return DFB_INVARG;\n\n     *ret_colorspace = data->surface->config.colorspace;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_GetAccelerationMask( IDirectFBSurface    *thiz,\n                                      IDirectFBSurface    *source,\n                                      DFBAccelerationMask *ret_mask )\n{\n     DFBResult           ret;\n     DFBAccelerationMask mask;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!ret_mask)\n          return DFB_INVARG;\n\n     if (source) {\n          IDirectFBSurface_data *src_data = source->priv;\n\n          dfb_state_set_source( &data->state, src_data->surface );\n          dfb_state_set_source2( &data->state, data->surface );\n     }\n\n     ret = CoreGraphicsStateClient_GetAccelerationMask( &data->state_client, &mask );\n     if (ret)\n          return ret;\n\n     /* Check text rendering function. */\n     if (data->font) {\n          IDirectFBFont_data *font_data = data->font->priv;\n\n          if (dfb_gfxcard_drawstring_check_state( font_data->font, &data->state, &data->state_client, DSTF_NONE ))\n               mask |= DFXL_DRAWSTRING;\n     }\n\n     *ret_mask = mask;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_GetPalette( IDirectFBSurface  *thiz,\n                             IDirectFBPalette **ret_interface )\n{\n     DFBResult         ret;\n     CorePalette      *palette;\n     IDirectFBPalette *iface;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->surface->palette)\n          return DFB_UNSUPPORTED;\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     ret = CoreSurface_GetPalette( data->surface, &palette );\n     if (ret)\n          return ret;\n\n     DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBPalette );\n\n     ret = IDirectFBPalette_Construct( iface, palette, data->core );\n     if (ret)\n          goto out;\n\n     *ret_interface = iface;\n\nout:\n     dfb_palette_unref( palette );\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetPalette( IDirectFBSurface *thiz,\n                             IDirectFBPalette *palette )\n{\n     IDirectFBPalette_data *palette_data;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!palette)\n          return DFB_INVARG;\n\n     if (!DFB_PIXELFORMAT_IS_INDEXED( data->surface->config.format ))\n          return DFB_UNSUPPORTED;\n\n     palette_data = palette->priv;\n     if (!palette_data)\n          return DFB_DEAD;\n\n     if (!palette_data->palette)\n          return DFB_DESTROYED;\n\n     CoreSurface_SetPalette( data->surface, palette_data->palette );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetAlphaRamp( IDirectFBSurface *thiz,\n                               u8                a0,\n                               u8                a1,\n                               u8                a2,\n                               u8                a3 )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     CoreSurface_SetAlphaRamp( data->surface, a0, a1, a2, a3 );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_GetStereoEye( IDirectFBSurface    *thiz,\n                               DFBSurfaceStereoEye *ret_eye )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %p )\\n\", __FUNCTION__, thiz, ret_eye );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!(data->surface->config.caps & DSCAPS_STEREO))\n          return DFB_UNSUPPORTED;\n\n     *ret_eye = data->src_eye;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetStereoEye( IDirectFBSurface    *thiz,\n                               DFBSurfaceStereoEye  eye )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %u )\\n\", __FUNCTION__, thiz, eye );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!(data->surface->config.caps & DSCAPS_STEREO))\n          return DFB_UNSUPPORTED;\n\n     dfb_state_set_to( &data->state, DSBR_BACK, eye );\n\n     data->src_eye = eye;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_Lock( IDirectFBSurface     *thiz,\n                       DFBSurfaceLockFlags   flags,\n                       void                **ret_ptr,\n                       int                  *ret_pitch )\n{\n     DFBResult              ret;\n     long long              ts, ts2;\n     DFBSurfaceBufferRole   role   = DSBR_FRONT;\n     CoreSurfaceAccessFlags access = CSAF_NONE;\n\n     D_UNUSED_P( ts );\n     D_UNUSED_P( ts2 );\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (!flags || !ret_ptr || !ret_pitch)\n          return DFB_INVARG;\n\n     if (flags & DSLF_READ)\n          access |= CSAF_READ;\n\n     if (flags & DSLF_WRITE) {\n          access |= CSAF_WRITE;\n          role = DSBR_BACK;\n     }\n\n     CoreGraphicsStateClient_Flush( &data->state_client );\n\n     if (direct_log_domain_check( &Surface ))\n          ts = direct_clock_get_time( DIRECT_CLOCK_MONOTONIC );\n\n     unsigned int           index      = (data->local_flip_count + role) % data->local_buffer_count;\n     CoreSurfaceAllocation *allocation = data->allocations[index];\n\n     if (allocation) {\n          D_DEBUG_AT( Surface, \"  -> having allocation %p\\n\", allocation );\n\n          if (!allocation->buffer || !direct_serial_check( &allocation->serial, &allocation->buffer->serial )) {\n               D_DEBUG_AT( Surface, \"    -> outdated!\\n\" );\n\n               dfb_surface_allocation_ref( allocation );\n\n               data->allocations[index] = allocation = NULL;\n          }\n     }\n\n     if (!allocation) {\n          D_DEBUG_AT( Surface, \"  -> getting allocation from %p\\n\", data->surface );\n\n          ret = CoreSurface_PreLockBuffer3( data->surface, role, data->local_flip_count, data->src_eye, CSAID_CPU,\n                                            access, true, &allocation );\n          if (ret)\n               return ret;\n\n          data->allocations[index] = allocation;\n     }\n\n     ret = dfb_surface_allocation_ref( allocation );\n     if (ret) {\n          D_DERROR( ret, \"IDirectFBSurface: Ref'ing allocation in '%s' failed!\\n\", allocation->pool->desc.name );\n          return ret;\n     }\n\n     /* Lock the allocation. */\n     dfb_surface_buffer_lock_init( &data->lock, CSAID_CPU, access );\n\n     D_DEBUG_AT( Surface, \"  -> locking %p\\n\", allocation );\n\n     ret = dfb_surface_pool_lock( allocation->pool, allocation, &data->lock );\n     if (ret) {\n          D_DERROR( ret, \"IDirectFBSurface: Locking allocation in '%s' failed!\\n\", allocation->pool->desc.name );\n          dfb_surface_buffer_lock_deinit( &data->lock );\n          return ret;\n     }\n\n     if (direct_log_domain_check( &Surface )) {\n          ts2 = direct_clock_get_time( DIRECT_CLOCK_MONOTONIC );\n          D_DEBUG_AT( Surface, \"  -> locking took %lld us\\n\", ts2 - ts );\n     }\n\n     data->locked = true;\n\n     *ret_ptr   = data->lock.addr + data->lock.pitch * data->area.current.y +\n                  DFB_BYTES_PER_LINE( data->surface->config.format, data->area.current.x );\n     *ret_pitch = data->lock.pitch;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_GetFramebufferOffset( IDirectFBSurface *thiz,\n                                       int              *offset )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->locked)\n          return DFB_ACCESSDENIED;\n\n     if (!data->lock.phys) {\n          /* The surface is probably in a system buffer if there's no physical address. */\n          return DFB_UNSUPPORTED;\n     }\n\n     if (!offset)\n          return DFB_INVARG;\n\n     *offset = data->lock.offset;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_Unlock( IDirectFBSurface *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (data->locked) {\n          dfb_surface_unlock_buffer( data->surface, &data->lock );\n\n          data->locked = false;\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nIDirectFBSurface_Flip( IDirectFBSurface    *thiz,\n                       const DFBRegion     *region,\n                       DFBSurfaceFlipFlags  flags )\n{\n     DFBResult ret = DFB_OK;\n     DFBRegion reg;\n     bool      dispatched = false;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %p, 0x%08x )\\n\", __FUNCTION__, thiz, region, flags );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!data->area.current.w || !data->area.current.h ||\n         (region && (region->x1 > region->x2 || region->y1 > region->y2)))\n          return DFB_INVAREA;\n\n     if (data->flip_func)\n          return data->flip_func( data->flip_func_ctx );\n\n     IDirectFBSurface_StopAll( data );\n\n     if (data->parent) {\n          IDirectFBSurface_data *parent_data;\n\n          parent_data = data->parent->priv;\n          if (!parent_data)\n               return DFB_DEAD;\n\n          if (parent_data) {\n               /* Signal end of sequence of operations. */\n               dfb_state_lock( &parent_data->state );\n               dfb_state_stop_drawing( &parent_data->state );\n               dfb_state_unlock( &parent_data->state );\n          }\n     }\n\n     dfb_region_from_rectangle( &reg, &data->area.current );\n\n     if (region) {\n          DFBRegion clip = DFB_REGION_INIT_TRANSLATED( region, data->area.wanted.x, data->area.wanted.y );\n\n          if (!dfb_region_region_intersect( &reg, &clip ))\n               return DFB_INVAREA;\n     }\n\n     D_DEBUG_AT( Surface, \"  -> flip %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS_FROM_REGION( &reg ) );\n\n     CoreGraphicsStateClient_Flush( &data->state_client );\n\n     if (dfb_config->force_frametime && !data->current_frame_time)\n          thiz->GetFrameTime( thiz, &data->current_frame_time );\n\n     if (data->surface->config.caps & DSCAPS_FLIPPING) {\n          if ((flags & DSFLIP_SWAP) ||\n              (!(flags & DSFLIP_BLIT) &&\n               reg.x1 == 0                                && reg.y1 == 0 &&\n               reg.x2 == data->surface->config.size.w - 1 && reg.y2 == data->surface->config.size.h - 1)) {\n               if (!(flags & DSFLIP_UPDATE))\n                    ++data->local_flip_count;\n\n               dfb_state_set_destination_2( &data->state, data->surface, data->local_flip_count );\n\n               ret = CoreSurface_DispatchUpdate( data->surface, DFB_FALSE, &reg, NULL, flags,\n                                                 data->current_frame_time, data->local_flip_count );\n               dispatched = true;\n          }\n     }\n\n     if (!dispatched)\n          ret = CoreSurface_Flip2( data->surface, DFB_FALSE, &reg, NULL, flags, data->current_frame_time );\n\n     data->current_frame_time = 0;\n\n     if (ret)\n          return ret;\n\n     if (!(flags & DSFLIP_NOWAIT))\n          IDirectFBSurface_WaitForBackBuffer( data );\n\n     return DFB_OK;\n}\n\nDFBResult\nIDirectFBSurface_FlipStereo( IDirectFBSurface    *thiz,\n                             const DFBRegion     *left_region,\n                             const DFBRegion     *right_region,\n                             DFBSurfaceFlipFlags  flags )\n{\n     DFBResult ret = DFB_OK;\n     DFBRegion l_reg, r_reg;\n     bool      dispatched = false;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %p, %p, 0x%08x )\\n\", __FUNCTION__, thiz, left_region, right_region, flags );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!(data->surface->config.caps & DSCAPS_STEREO))\n          return DFB_UNSUPPORTED;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!data->area.current.w || !data->area.current.h ||\n         (left_region  && (left_region->x1 > left_region->x2   || left_region->y1 > left_region->y2)) ||\n         (right_region && (right_region->x1 > right_region->x2 || right_region->y1 > right_region->y2)))\n          return DFB_INVAREA;\n\n     IDirectFBSurface_StopAll( data );\n\n     if (data->parent) {\n          IDirectFBSurface_data *parent_data;\n\n          parent_data = data->parent->priv;\n          if (!parent_data)\n               return DFB_DEAD;\n\n          if (parent_data) {\n               /* Signal end of sequence of operations. */\n               dfb_state_lock( &parent_data->state );\n               dfb_state_stop_drawing( &parent_data->state );\n               dfb_state_unlock( &parent_data->state );\n          }\n     }\n\n     dfb_region_from_rectangle( &l_reg, &data->area.current );\n     dfb_region_from_rectangle( &r_reg, &data->area.current );\n\n     if (left_region) {\n          DFBRegion clip = DFB_REGION_INIT_TRANSLATED( left_region, data->area.wanted.x, data->area.wanted.y );\n\n          if (!dfb_region_region_intersect( &l_reg, &clip ))\n               return DFB_INVAREA;\n     }\n\n     if (right_region) {\n          DFBRegion clip = DFB_REGION_INIT_TRANSLATED( right_region, data->area.wanted.x, data->area.wanted.y );\n\n          if (!dfb_region_region_intersect( &r_reg, &clip ))\n               return DFB_INVAREA;\n     }\n\n     D_DEBUG_AT( Surface, \"  -> flip stereo left: %4d,%4d-%4dx%4d right: %4d,%4d-%4dx%4d\\n\",\n                 DFB_RECTANGLE_VALS_FROM_REGION( &l_reg ), DFB_RECTANGLE_VALS_FROM_REGION( &r_reg ) );\n\n     CoreGraphicsStateClient_Flush( &data->state_client );\n\n     if (dfb_config->force_frametime && !data->current_frame_time)\n          thiz->GetFrameTime( thiz, &data->current_frame_time );\n\n     if (data->surface->config.caps & DSCAPS_FLIPPING) {\n          if ((flags & DSFLIP_SWAP) ||\n              (!(flags & DSFLIP_BLIT) &&\n               l_reg.x1 == 0                                && l_reg.y1 == 0                                &&\n               l_reg.x2 == data->surface->config.size.w - 1 && l_reg.y2 == data->surface->config.size.h - 1 &&\n               r_reg.x1 == 0                                && r_reg.y1 == 0                                &&\n               r_reg.x2 == data->surface->config.size.w - 1 && r_reg.y2 == data->surface->config.size.h - 1)) {\n               if (!(flags & DSFLIP_UPDATE))\n                    ++data->local_flip_count;\n\n               ret = CoreSurface_DispatchUpdate( data->surface, DFB_FALSE, &l_reg, &r_reg, flags,\n                                                 data->current_frame_time, data->local_flip_count );\n               dispatched = true;\n          }\n     }\n\n     if (!dispatched)\n          ret = CoreSurface_Flip2( data->surface, DFB_FALSE, &l_reg, &r_reg, flags, data->current_frame_time );\n\n     dfb_state_set_destination_2( &data->state, data->surface, data->local_flip_count );\n\n     data->current_frame_time = 0;\n\n     if (ret)\n          return ret;\n\n     if (!(flags & DSFLIP_NOWAIT))\n          IDirectFBSurface_WaitForBackBuffer( data );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetField( IDirectFBSurface *thiz,\n                           int               field )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!(data->surface->config.caps & DSCAPS_INTERLACED))\n          return DFB_UNSUPPORTED;\n\n     if (field < 0 || field > 1)\n          return DFB_INVARG;\n\n     CoreSurface_SetField( data->surface, field );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_Clear( IDirectFBSurface *thiz,\n                        u8                r,\n                        u8                g,\n                        u8                b,\n                        u8                a )\n{\n     DFBColor                old_color;\n     unsigned int            old_index;\n     DFBSurfaceDrawingFlags  old_flags;\n     DFBSurfaceRenderOptions old_options;\n     DFBColor                color = { a, r, g, b };\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, 0x%08x )\\n\", __FUNCTION__, thiz, (unsigned int) PIXEL_ARGB( a, r, g, b ) );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     /* Save current color and drawing flags. */\n     old_color   = data->state.color;\n     old_index   = data->state.color_index;\n     old_flags   = data->state.drawingflags;\n     old_options = data->state.render_options;\n\n     /* Set drawing flags. */\n     dfb_state_set_drawing_flags( &data->state, DSDRAW_NOFX );\n\n     /* Set render options. */\n     dfb_state_set_render_options( &data->state, DSRO_NONE );\n\n     /* Set color. */\n     if (DFB_PIXELFORMAT_IS_INDEXED( data->surface->config.format ))\n          dfb_state_set_color_index( &data->state, dfb_palette_search( data->surface->palette, r, g, b, a ) );\n\n     dfb_state_set_color( &data->state, &color );\n\n     /* Fill the visible rectangle. */\n     CoreGraphicsStateClient_FillRectangles( &data->state_client, &data->area.current, 1 );\n\n     /* Restore drawing flags. */\n     dfb_state_set_drawing_flags( &data->state, old_flags );\n\n     /* Restore render options. */\n     dfb_state_set_render_options( &data->state, old_options );\n\n     /* Restore color. */\n     if (DFB_PIXELFORMAT_IS_INDEXED( data->surface->config.format ))\n          dfb_state_set_color_index( &data->state, old_index );\n\n     dfb_state_set_color( &data->state, &old_color );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetClip( IDirectFBSurface *thiz,\n                          const DFBRegion  *clip )\n{\n     DFBRegion newclip;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %p )\\n\", __FUNCTION__, thiz, clip );\n\n     D_DEBUG_AT( Surface, \"  <- %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS( &data->area.wanted ) );\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (clip) {\n          newclip = DFB_REGION_INIT_TRANSLATED( clip, data->area.wanted.x, data->area.wanted.y );\n\n          D_DEBUG_AT( Surface, \"  <- %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS_FROM_REGION( &newclip ) );\n\n          if (!dfb_unsafe_region_rectangle_intersect( &newclip, &data->area.wanted ))\n               return DFB_INVARG;\n\n          D_DEBUG_AT( Surface, \"  -> %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS_FROM_REGION( &newclip ) );\n\n          data->clip_set    = true;\n          data->clip_wanted = newclip;\n\n          if (!dfb_region_rectangle_intersect( &newclip, &data->area.current ))\n               return DFB_INVAREA;\n     }\n     else {\n          dfb_region_from_rectangle( &newclip, &data->area.current );\n          data->clip_set = false;\n     }\n\n     D_DEBUG_AT( Surface, \"  -> clip %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS_FROM_REGION( &newclip ) );\n\n     dfb_state_set_clip( &data->state, &newclip );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_GetClip( IDirectFBSurface *thiz,\n                          DFBRegion        *ret_clip )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (!ret_clip)\n          return DFB_INVARG;\n\n     *ret_clip = DFB_REGION_INIT_TRANSLATED( &data->state.clip, -data->area.wanted.x, -data->area.wanted.y );\n\n     D_DEBUG_AT( Surface, \"  -> %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS_FROM_REGION( ret_clip ) );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetColor( IDirectFBSurface *thiz,\n                           u8                r,\n                           u8                g,\n                           u8                b,\n                           u8                a )\n{\n     DFBColor color = { a, r, g, b };\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, color 0x%08x )\\n\", __FUNCTION__, thiz, (unsigned int) PIXEL_ARGB( a, r, g, b ) );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     dfb_state_set_color( &data->state, &color );\n\n     if (DFB_PIXELFORMAT_IS_INDEXED( data->surface->config.format ))\n          dfb_state_set_color_index( &data->state, dfb_palette_search( data->surface->palette, r, g, b, a ) );\n\n     data->state.colors[0]        = data->state.color;\n     data->state.color_indices[0] = data->state.color_index;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetColorIndex( IDirectFBSurface *thiz,\n                                unsigned int      index )\n{\n     CorePalette *palette;\n     DFBResult    ret;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, color index %3u )\\n\", __FUNCTION__, thiz, index );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!DFB_PIXELFORMAT_IS_INDEXED( data->surface->config.format ))\n          return DFB_UNSUPPORTED;\n\n     palette = data->surface->palette;\n     if (!palette)\n          return DFB_UNSUPPORTED;\n\n     if (index > palette->num_entries)\n          return DFB_INVARG;\n\n     ret = CoreGraphicsStateClient_SetColorAndIndex( &data->state_client, &palette->entries[index], index );\n     if (ret)\n          return ret;\n\n     dfb_state_set_color( &data->state, &palette->entries[index] );\n     dfb_state_set_color_index( &data->state, index );\n\n     data->state.colors[0]        = data->state.color;\n     data->state.color_indices[0] = data->state.color_index;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetSrcBlendFunction( IDirectFBSurface        *thiz,\n                                      DFBSurfaceBlendFunction  function )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %u )\\n\", __FUNCTION__, thiz, function );\n\n     switch (function) {\n          case DSBF_ZERO:\n          case DSBF_ONE:\n          case DSBF_SRCCOLOR:\n          case DSBF_INVSRCCOLOR:\n          case DSBF_SRCALPHA:\n          case DSBF_INVSRCALPHA:\n          case DSBF_DESTALPHA:\n          case DSBF_INVDESTALPHA:\n          case DSBF_DESTCOLOR:\n          case DSBF_INVDESTCOLOR:\n          case DSBF_SRCALPHASAT:\n               dfb_state_set_src_blend( &data->state, function );\n               return DFB_OK;\n\n          default:\n               break;\n     }\n\n     return DFB_INVARG;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetDstBlendFunction( IDirectFBSurface        *thiz,\n                                      DFBSurfaceBlendFunction  function )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %u )\\n\", __FUNCTION__, thiz, function );\n\n     switch (function) {\n          case DSBF_ZERO:\n          case DSBF_ONE:\n          case DSBF_SRCCOLOR:\n          case DSBF_INVSRCCOLOR:\n          case DSBF_SRCALPHA:\n          case DSBF_INVSRCALPHA:\n          case DSBF_DESTALPHA:\n          case DSBF_INVDESTALPHA:\n          case DSBF_DESTCOLOR:\n          case DSBF_INVDESTCOLOR:\n          case DSBF_SRCALPHASAT:\n               dfb_state_set_dst_blend( &data->state, function );\n               return DFB_OK;\n\n          default:\n               break;\n     }\n\n     return DFB_INVARG;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetPorterDuff( IDirectFBSurface         *thiz,\n                                DFBSurfacePorterDuffRule  rule )\n{\n     DFBSurfaceBlendFunction src;\n     DFBSurfaceBlendFunction dst;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %u )\\n\", __FUNCTION__, thiz, rule );\n\n     switch (rule) {\n          case DSPD_NONE:\n               src = DSBF_SRCALPHA;\n               dst = DSBF_INVSRCALPHA;\n               break;\n          case DSPD_CLEAR:\n               src = DSBF_ZERO;\n               dst = DSBF_ZERO;\n               break;\n          case DSPD_SRC:\n               src = DSBF_ONE;\n               dst = DSBF_ZERO;\n               break;\n          case DSPD_SRC_OVER:\n               src = DSBF_ONE;\n               dst = DSBF_INVSRCALPHA;\n               break;\n          case DSPD_DST_OVER:\n               src = DSBF_INVDESTALPHA;\n               dst = DSBF_ONE;\n               break;\n          case DSPD_SRC_IN:\n               src = DSBF_DESTALPHA;\n               dst = DSBF_ZERO;\n               break;\n          case DSPD_DST_IN:\n               src = DSBF_ZERO;\n               dst = DSBF_SRCALPHA;\n               break;\n          case DSPD_SRC_OUT:\n               src = DSBF_INVDESTALPHA;\n               dst = DSBF_ZERO;\n               break;\n          case DSPD_DST_OUT:\n               src = DSBF_ZERO;\n               dst = DSBF_INVSRCALPHA;\n               break;\n          case DSPD_SRC_ATOP:\n               src = DSBF_DESTALPHA;\n               dst = DSBF_INVSRCALPHA;\n               break;\n          case DSPD_DST_ATOP:\n               src = DSBF_INVDESTALPHA;\n               dst = DSBF_SRCALPHA;\n               break;\n          case DSPD_ADD:\n               src = DSBF_ONE;\n               dst = DSBF_ONE;\n               break;\n          case DSPD_XOR:\n               src = DSBF_INVDESTALPHA;\n               dst = DSBF_INVSRCALPHA;\n               break;\n          case DSPD_DST:\n               src = DSBF_ZERO;\n               dst = DSBF_ONE;\n               break;\n\n          default:\n               return DFB_INVARG;\n     }\n\n     dfb_state_set_src_blend( &data->state, src );\n     dfb_state_set_dst_blend( &data->state, dst );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetSrcColorKey( IDirectFBSurface *thiz,\n                                 u8                r,\n                                 u8                g,\n                                 u8                b )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     data->src_key.r = r;\n     data->src_key.g = g;\n     data->src_key.b = b;\n\n     if (DFB_PIXELFORMAT_IS_INDEXED( data->surface->config.format ))\n          data->src_key.value = dfb_palette_search( data->surface->palette, r, g, b, 0x80 );\n     else {\n          DFBColor color = { 0, r, g, b };\n\n          data->src_key.value = dfb_pixel_from_color( data->surface->config.format, data->surface->config.colorspace,\n                                                      &color );\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetSrcColorKeyIndex( IDirectFBSurface *thiz,\n                                      unsigned int      index )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!DFB_PIXELFORMAT_IS_INDEXED( data->surface->config.format ))\n          return DFB_UNSUPPORTED;\n\n     if (!data->surface->palette)\n          return DFB_UNSUPPORTED;\n\n     if (index > data->surface->palette->num_entries)\n          return DFB_INVARG;\n\n     data->src_key.r     = data->surface->palette->entries[index].r;\n     data->src_key.g     = data->surface->palette->entries[index].g;\n     data->src_key.b     = data->surface->palette->entries[index].b;\n     data->src_key.value = index;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetDstColorKey( IDirectFBSurface *thiz,\n                                 u8                r,\n                                 u8                g,\n                                 u8                b )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     data->dst_key.r = r;\n     data->dst_key.g = g;\n     data->dst_key.b = b;\n\n     if (DFB_PIXELFORMAT_IS_INDEXED( data->surface->config.format ))\n          data->dst_key.value = dfb_palette_search( data->surface->palette, r, g, b, 0x80 );\n     else {\n          DFBColor color = { 0, r, g, b };\n\n          data->dst_key.value = dfb_pixel_from_color( data->surface->config.format, data->surface->config.colorspace,\n                                                      &color );\n     }\n\n     dfb_state_set_dst_colorkey( &data->state, data->dst_key.value );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetDstColorKeyIndex( IDirectFBSurface *thiz,\n                                      unsigned int      index )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!DFB_PIXELFORMAT_IS_INDEXED( data->surface->config.format ))\n          return DFB_UNSUPPORTED;\n\n     if (!data->surface->palette)\n          return DFB_UNSUPPORTED;\n\n     if (index > data->surface->palette->num_entries)\n          return DFB_INVARG;\n\n     data->dst_key.r     = data->surface->palette->entries[index].r;\n     data->dst_key.g     = data->surface->palette->entries[index].g;\n     data->dst_key.b     = data->surface->palette->entries[index].b;\n     data->dst_key.value = index;\n\n     dfb_state_set_dst_colorkey( &data->state, data->dst_key.value );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetBlittingFlags( IDirectFBSurface        *thiz,\n                                   DFBSurfaceBlittingFlags  flags )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, 0x%08x )\\n\", __FUNCTION__, thiz, flags );\n\n     dfb_state_set_blitting_flags( &data->state, flags );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_Blit( IDirectFBSurface   *thiz,\n                       IDirectFBSurface   *source,\n                       const DFBRectangle *source_rect,\n                       int                 x,\n                       int                 y )\n{\n     DFBRectangle           srect;\n     DFBPoint               p;\n     IDirectFBSurface_data *src_data;\n     int                    dx = x;\n     int                    dy = y;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, source %p, source_rect %p, %d,%d )\\n\", __FUNCTION__,\n                 thiz, source, source_rect, dx, dy );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!source)\n          return DFB_INVARG;\n\n     src_data = source->priv;\n\n     if (!src_data->area.current.w || !src_data->area.current.h)\n          return DFB_INVAREA;\n\n     if (source_rect) {\n          D_DEBUG_AT( Surface, \"  -> [%2d] %4d,%4d-%4dx%4d <- %4d,%4d\\n\", 0,\n                      dx, dy, source_rect->w, source_rect->h, source_rect->x, source_rect->y );\n\n          if (source_rect->w < 1 || source_rect->h < 1)\n               return DFB_OK;\n\n          srect = *source_rect;\n\n          srect.x += src_data->area.wanted.x;\n          srect.y += src_data->area.wanted.y;\n\n          if (!dfb_rectangle_intersect( &srect, &src_data->area.current ))\n               return DFB_INVAREA;\n\n          dx += srect.x - (source_rect->x + src_data->area.wanted.x);\n          dy += srect.y - (source_rect->y + src_data->area.wanted.y);\n     }\n     else {\n          srect = src_data->area.current;\n\n          dx += srect.x - src_data->area.wanted.x;\n          dy += srect.y - src_data->area.wanted.y;\n     }\n\n     CoreGraphicsStateClient_Flush( &src_data->state_client );\n\n     if (src_data->surface_client) {\n          direct_mutex_lock( &data->surface_client_lock );\n\n          D_DEBUG_AT( Surface, \"  -> blit client surface (flip count %u)\\n\", src_data->surface_client_flip_count );\n\n          dfb_state_set_source_2( &data->state, src_data->surface, src_data->surface_client_flip_count );\n     }\n     else\n          dfb_state_set_source( &data->state, src_data->surface );\n\n     dfb_state_set_from( &data->state, DSBR_FRONT, src_data->src_eye );\n\n     /* Fetch the source color key from the source if necessary. */\n     if (data->state.blittingflags & DSBLIT_SRC_COLORKEY)\n          dfb_state_set_src_colorkey( &data->state, src_data->src_key.value );\n\n     p.x = data->area.wanted.x + dx;\n     p.y = data->area.wanted.y + dy;\n\n     CoreGraphicsStateClient_Blit( &data->state_client, &srect, &p, 1 );\n\n     if (src_data->surface_client)\n          direct_mutex_unlock( &data->surface_client_lock );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_TileBlit( IDirectFBSurface   *thiz,\n                           IDirectFBSurface   *source,\n                           const DFBRectangle *source_rect,\n                           int                 x,\n                           int                 y )\n{\n     DFBRectangle           srect;\n     DFBPoint               p1, p2;\n     IDirectFBSurface_data *src_data;\n     int                    dx = x;\n     int                    dy = y;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, source %p, source_rect %p, %d,%d )\\n\", __FUNCTION__,\n                 thiz, source, source_rect, dx, dy );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!source)\n          return DFB_INVARG;\n\n     src_data = source->priv;\n\n     if (!src_data->area.current.w || !src_data->area.current.h)\n          return DFB_INVAREA;\n\n     if (source_rect) {\n          D_DEBUG_AT( Surface, \"  -> [%2d] %4d,%4d-%4dx%4d <- %4d,%4d\\n\", 0,\n                      dx, dy, source_rect->w, source_rect->h, source_rect->x, source_rect->y );\n\n          if (source_rect->w < 1 || source_rect->h < 1)\n               return DFB_OK;\n\n          srect = *source_rect;\n\n          srect.x += src_data->area.wanted.x;\n          srect.y += src_data->area.wanted.y;\n\n          if (!dfb_rectangle_intersect( &srect, &src_data->area.current ))\n               return DFB_INVAREA;\n\n          dx += srect.x - (source_rect->x + src_data->area.wanted.x);\n          dy += srect.y - (source_rect->y + src_data->area.wanted.y);\n     }\n     else {\n          srect = src_data->area.current;\n\n          dx += srect.x - src_data->area.wanted.x;\n          dy += srect.y - src_data->area.wanted.y;\n     }\n\n     CoreGraphicsStateClient_Flush( &src_data->state_client );\n\n     dfb_state_set_source( &data->state, src_data->surface );\n\n     dfb_state_set_from( &data->state, DSBR_FRONT, src_data->src_eye );\n\n     /* Fetch the source color key from the source if necessary. */\n     if (data->state.blittingflags & DSBLIT_SRC_COLORKEY)\n          dfb_state_set_src_colorkey( &data->state, src_data->src_key.value );\n\n     dx %= srect.w;\n     if (dx > 0)\n          dx -= srect.w;\n\n     dy %= srect.h;\n     if (dy > 0)\n          dy -= srect.h;\n\n     dx += data->area.wanted.x;\n     dy += data->area.wanted.y;\n\n     p1.x = dx;\n     p1.y = dy;\n\n     p2.x = dx + data->area.wanted.w + srect.w - 1;\n     p2.y = dy + data->area.wanted.h + srect.h - 1;\n\n     CoreGraphicsStateClient_TileBlit( &data->state_client, &srect, &p1, &p2, 1 );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_BatchBlit( IDirectFBSurface   *thiz,\n                            IDirectFBSurface   *source,\n                            const DFBRectangle *source_rects,\n                            const DFBPoint     *dest_points,\n                            int                 num )\n{\n     int                    i, dx, dy, sx, sy;\n     DFBRectangle          *rects;\n     DFBPoint              *points;\n     IDirectFBSurface_data *src_data;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, source %p, source_rects %p, dest_points %p, num %d )\\n\", __FUNCTION__,\n                 thiz, source, source_rects, dest_points, num );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!source || !source_rects || !dest_points || num < 1)\n          return DFB_INVARG;\n\n     src_data = source->priv;\n\n     if (!src_data->area.current.w || !src_data->area.current.h) {\n          return DFB_INVAREA;\n     }\n\n     dx = data->area.wanted.x;\n     dy = data->area.wanted.y;\n\n     sx = src_data->area.wanted.x;\n     sy = src_data->area.wanted.y;\n\n     rects  = alloca( sizeof(DFBRectangle) * num );\n     points = alloca( sizeof(DFBPoint) * num );\n\n     direct_memcpy( rects, source_rects, sizeof(DFBRectangle) * num );\n     direct_memcpy( points, dest_points, sizeof(DFBPoint) * num );\n\n     for (i = 0; i < num; i++) {\n          rects[i].x += sx;\n          rects[i].y += sy;\n\n          points[i].x += dx;\n          points[i].y += dy;\n\n          if (!dfb_rectangle_intersect( &rects[i], &src_data->area.current ))\n               rects[i].w = rects[i].h = 0;\n\n          points[i].x += rects[i].x - (source_rects[i].x + sx);\n          points[i].y += rects[i].y - (source_rects[i].y + sy);\n\n          D_DEBUG_AT( Surface, \"  -> [%3d] %4d,%4d-%dx%4d -> %4d,%4d\\n\",\n                      i, DFB_RECTANGLE_VALS( &source_rects[i] ), dest_points[i].x, dest_points[i].y );\n     }\n\n     CoreGraphicsStateClient_Flush( &src_data->state_client );\n\n     dfb_state_set_source( &data->state, src_data->surface );\n\n     dfb_state_set_from( &data->state, DSBR_FRONT, src_data->src_eye );\n\n     /* Fetch the source color key from the source if necessary. */\n     if (data->state.blittingflags & DSBLIT_SRC_COLORKEY)\n          dfb_state_set_src_colorkey( &data->state, src_data->src_key.value );\n\n     CoreGraphicsStateClient_Blit( &data->state_client, rects, points, num );\n\n     return DFB_OK;\n}\n\nstatic DFBResult IDirectFBSurface_BatchStretchBlit( IDirectFBSurface   *thiz,\n                                                    IDirectFBSurface   *source,\n                                                    const DFBRectangle *source_rects,\n                                                    const DFBRectangle *dest_rects,\n                                                    int                 num );\n\nstatic DFBResult\nIDirectFBSurface_StretchBlit( IDirectFBSurface   *thiz,\n                              IDirectFBSurface   *source,\n                              const DFBRectangle *source_rect,\n                              const DFBRectangle *dest_rect )\n{\n     DFBRectangle srect, drect;\n\n     if (!source)\n          return DFB_INVARG;\n\n     if (source_rect)\n          srect = *source_rect;\n     else {\n          IDirectFBSurface_data *src_data = source->priv;\n\n          srect = (DFBRectangle) { 0, 0, src_data->area.wanted.w, src_data->area.wanted.h };\n     }\n\n     if (dest_rect)\n          drect = *dest_rect;\n     else {\n          DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n          drect = (DFBRectangle) { 0, 0, data->area.wanted.w, data->area.wanted.h };\n     }\n\n     return IDirectFBSurface_BatchStretchBlit( thiz, source, &srect, &drect, 1 );\n}\n\n#define SET_VERTEX(v,X,Y,Z,W,S,T) \\\n     do {                         \\\n          (v)->x = X;             \\\n          (v)->y = Y;             \\\n          (v)->z = Z;             \\\n          (v)->w = W;             \\\n          (v)->s = S;             \\\n          (v)->t = T;             \\\n     } while (0)\n\nstatic DFBResult\nIDirectFBSurface_TextureTriangles( IDirectFBSurface     *thiz,\n                                   IDirectFBSurface     *texture,\n                                   const DFBVertex      *vertices,\n                                   const int            *indices,\n                                   int                   num,\n                                   DFBTriangleFormation  formation )\n{\n     int                    i;\n     DFBVertex             *translated;\n     IDirectFBSurface_data *src_data;\n     bool                   src_sub;\n     float                  x0 = 0;\n     float                  y0 = 0;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!texture || !vertices || num < 3)\n          return DFB_INVARG;\n\n     src_data = texture->priv;\n\n     if ((src_sub = (src_data->caps & DSCAPS_SUBSURFACE))) {\n          D_ONCE( \"sub surface texture with repeated mapping\" );\n\n          x0 = data->area.wanted.x;\n          y0 = data->area.wanted.y;\n     }\n\n     switch (formation) {\n          case DTTF_LIST:\n               if (num % 3)\n                    return DFB_INVARG;\n               break;\n\n          case DTTF_STRIP:\n          case DTTF_FAN:\n               break;\n\n          default:\n               return DFB_INVARG;\n     }\n\n     translated = alloca( num * sizeof(DFBVertex) );\n     if (!translated)\n          return DFB_NOSYSTEMMEMORY;\n\n     if (src_sub) {\n          float oowidth  = 1.0f / src_data->surface->config.size.w;\n          float ooheight = 1.0f / src_data->surface->config.size.h;\n\n          float s0 = src_data->area.wanted.x * oowidth;\n          float t0 = src_data->area.wanted.y * ooheight;\n\n          float fs = src_data->area.wanted.w * oowidth;\n          float ft = src_data->area.wanted.h * ooheight;\n\n          for (i = 0; i < num; i++) {\n               const DFBVertex *in  = &vertices[indices ? indices[i] : i];\n               DFBVertex       *out = &translated[i];\n\n               SET_VERTEX( out, x0 + in->x, y0 + in->y, in->z, in->w, s0 + fs * in->s, t0 + ft * in->t );\n          }\n     }\n     else {\n          if (indices) {\n               for (i = 0; i < num; i++) {\n                    const DFBVertex *in  = &vertices[indices[i]];\n                    DFBVertex       *out = &translated[i];\n\n                    SET_VERTEX( out, x0 + in->x, y0 + in->y, in->z, in->w, in->s, in->t );\n               }\n          }\n          else {\n               direct_memcpy( translated, vertices, num * sizeof(DFBVertex) );\n\n               for (i = 0; i < num; i++) {\n                    translated[i].x += x0;\n                    translated[i].y += y0;\n               }\n          }\n     }\n\n     CoreGraphicsStateClient_Flush( &src_data->state_client );\n\n     dfb_state_set_source( &data->state, src_data->surface );\n\n     dfb_state_set_from( &data->state, DSBR_FRONT, src_data->src_eye );\n\n     /* Fetch the source color key from the source if necessary. */\n     if (data->state.blittingflags & DSBLIT_SRC_COLORKEY)\n          dfb_state_set_src_colorkey( &data->state, src_data->src_key.value );\n\n     CoreGraphicsStateClient_TextureTriangles( &data->state_client, translated, num, formation );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetDrawingFlags( IDirectFBSurface       *thiz,\n                                  DFBSurfaceDrawingFlags  flags )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, 0x%08x )\\n\", __FUNCTION__, thiz, flags );\n\n     dfb_state_set_drawing_flags( &data->state, flags );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_FillRectangle( IDirectFBSurface *thiz,\n                                int               x,\n                                int               y,\n                                int               w,\n                                int               h )\n{\n     DFBRectangle rect = { x, y, w, h };\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n     D_DEBUG_AT( Surface, \"  -> [%2d] %4d,%4d-%4dx%4d\\n\", 0, x, y, w, h );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (w <= 0 || h <= 0)\n          return DFB_INVARG;\n\n     rect.x += data->area.wanted.x;\n     rect.y += data->area.wanted.y;\n\n     CoreGraphicsStateClient_FillRectangles( &data->state_client, &rect, 1 );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_DrawRectangle( IDirectFBSurface *thiz,\n                                int               x,\n                                int               y,\n                                int               w,\n                                int               h )\n{\n     DFBRectangle rect = { x, y, w, h };\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n     D_DEBUG_AT( Surface, \"  -> [%2d] %4d,%4d-%4dx%4d\\n\", 0, x, y, w, h );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (w <= 0 || h <= 0)\n          return DFB_INVARG;\n\n     rect.x += data->area.wanted.x;\n     rect.y += data->area.wanted.y;\n\n     CoreGraphicsStateClient_DrawRectangles( &data->state_client, &rect, 1 );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_DrawLine( IDirectFBSurface *thiz,\n                           int               x1,\n                           int               y1,\n                           int               x2,\n                           int               y2 )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n     D_DEBUG_AT( Surface, \"  -> [%2d] %4d,%4d-%4d,%4d\\n\", 0, x1, y1, x2, y2 );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if ((x1 == x2 || y1 == y2) && !(data->state.render_options & DSRO_MATRIX)) {\n          DFBRectangle rect;\n\n          if (x1 <= x2) {\n               rect.x = x1;\n               rect.w = x2 - x1 + 1;\n          }\n          else {\n               rect.x = x2;\n               rect.w = x1 - x2 + 1;\n          }\n\n          if (y1 <= y2) {\n               rect.y = y1;\n               rect.h = y2 - y1 + 1;\n          }\n          else {\n               rect.y = y2;\n               rect.h = y1 - y2 + 1;\n          }\n\n          rect.x += data->area.wanted.x;\n          rect.y += data->area.wanted.y;\n\n          CoreGraphicsStateClient_FillRectangles( &data->state_client, &rect, 1 );\n     }\n     else {\n          DFBRegion line = { x1, y1, x2, y2 };\n\n          line.x1 += data->area.wanted.x;\n          line.x2 += data->area.wanted.x;\n          line.y1 += data->area.wanted.y;\n          line.y2 += data->area.wanted.y;\n\n          CoreGraphicsStateClient_DrawLines( &data->state_client, &line, 1 );\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_DrawLines( IDirectFBSurface *thiz,\n                            const DFBRegion  *lines,\n                            unsigned int      num_lines )\n{\n     unsigned int i;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %p [%u] )\\n\", __FUNCTION__, thiz, lines, num_lines );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!lines || !num_lines)\n          return DFB_INVARG;\n\n     /* Check if all lines are either horizontal or vertical. */\n     for (i = 0; i < num_lines; i++) {\n          if (lines[i].x1 != lines[i].x2 && lines[i].y1 != lines[i].y2)\n               break;\n     }\n\n     /* Use real line drawing. */\n     if (i < num_lines) {\n          DFBRegion *local_lines = alloca( sizeof(DFBRegion) * num_lines );\n\n          if (data->area.wanted.x || data->area.wanted.y) {\n               for (i = 0; i < num_lines; i++) {\n                    local_lines[i].x1 = lines[i].x1 + data->area.wanted.x;\n                    local_lines[i].x2 = lines[i].x2 + data->area.wanted.x;\n                    local_lines[i].y1 = lines[i].y1 + data->area.wanted.y;\n                    local_lines[i].y2 = lines[i].y2 + data->area.wanted.y;\n               }\n          }\n          else\n               /* Clipping may modify lines, so we copy them. */\n               direct_memcpy( local_lines, lines, sizeof(DFBRegion) * num_lines );\n\n          CoreGraphicsStateClient_DrawLines( &data->state_client, local_lines, num_lines );\n     }\n     /* Optimized rectangle drawing. */\n     else {\n          DFBRectangle *local_rects = alloca( sizeof(DFBRectangle) * num_lines );\n\n          for (i = 0; i < num_lines; i++) {\n               /* Vertical line. */\n               if (lines[i].x1 == lines[i].x2) {\n                    local_rects[i].x = data->area.wanted.x + lines[i].x1;\n                    local_rects[i].y = data->area.wanted.y + MIN( lines[i].y1, lines[i].y2 );\n                    local_rects[i].w = 1;\n                    local_rects[i].h = ABS( lines[i].y2 - lines[i].y1 ) + 1;\n               }\n               /* Horizontal line. */\n               else {\n                    local_rects[i].x = data->area.wanted.x + MIN( lines[i].x1, lines[i].x2 );\n                    local_rects[i].y = data->area.wanted.y + lines[i].y1;\n                    local_rects[i].w = ABS( lines[i].x2 - lines[i].x1 ) + 1;\n                    local_rects[i].h = 1;\n               }\n          }\n\n          CoreGraphicsStateClient_FillRectangles( &data->state_client, local_rects, num_lines );\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_FillTriangle( IDirectFBSurface *thiz,\n                               int               x1,\n                               int               y1,\n                               int               x2,\n                               int               y2,\n                               int               x3,\n                               int               y3 )\n{\n     DFBTriangle tri = { x1, y1, x2, y2, x3, y3 };\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n     D_DEBUG_AT( Surface, \"  -> [%2d] %4d,%4d-%4d,%4d-%4d,%4d\\n\", 0, x1, y1, x2, y2, x3, y3 );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     tri.x1 += data->area.wanted.x;\n     tri.y1 += data->area.wanted.y;\n     tri.x2 += data->area.wanted.x;\n     tri.y2 += data->area.wanted.y;\n     tri.x3 += data->area.wanted.x;\n     tri.y3 += data->area.wanted.y;\n\n     CoreGraphicsStateClient_FillTriangles( &data->state_client, &tri, 1 );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_FillRectangles( IDirectFBSurface   *thiz,\n                                 const DFBRectangle *rects,\n                                 unsigned int        num_rects )\n{\n     unsigned int i;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %p [%u] )\\n\", __FUNCTION__, thiz, rects, num_rects );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!rects || !num_rects)\n          return DFB_INVARG;\n\n     if (data->area.wanted.x || data->area.wanted.y) {\n          DFBRectangle *local_rects;\n          bool          malloced = (num_rects > 256);\n\n          if (malloced)\n               local_rects = D_MALLOC( sizeof(DFBRectangle) * num_rects );\n          else\n               local_rects = alloca( sizeof(DFBRectangle) * num_rects );\n\n          for (i = 0; i < num_rects; i++) {\n               local_rects[i].x = rects[i].x + data->area.wanted.x;\n               local_rects[i].y = rects[i].y + data->area.wanted.y;\n               local_rects[i].w = rects[i].w;\n               local_rects[i].h = rects[i].h;\n          }\n\n          for (i = 0; i < num_rects; i += 200) {\n               CoreGraphicsStateClient_FillRectangles( &data->state_client, &local_rects[i],\n                                                       MIN( 200, num_rects - i ) );\n          }\n\n          if (malloced)\n               D_FREE( local_rects );\n     }\n     else {\n          for (i = 0; i < num_rects; i += 200) {\n               CoreGraphicsStateClient_FillRectangles( &data->state_client, &rects[i],\n                                                       MIN( 200, num_rects - i ) );\n          }\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_FillSpans( IDirectFBSurface *thiz,\n                            int               y,\n                            const DFBSpan    *spans,\n                            unsigned int      num_spans )\n{\n     DFBSpan *local_spans = alloca( sizeof(DFBSpan) * num_spans );\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!spans || !num_spans)\n          return DFB_INVARG;\n\n     if (data->area.wanted.x || data->area.wanted.y) {\n          unsigned int i;\n\n          for (i = 0; i < num_spans; i++) {\n               local_spans[i].x = spans[i].x + data->area.wanted.x;\n               local_spans[i].w = spans[i].w;\n          }\n     }\n     else\n          /* Clipping may modify spans, so we copy them. */\n          direct_memcpy( local_spans, spans, sizeof(DFBSpan) * num_spans );\n\n     CoreGraphicsStateClient_FillSpans( &data->state_client, y + data->area.wanted.y, local_spans, num_spans );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_FillTriangles( IDirectFBSurface  *thiz,\n                                const DFBTriangle *tris,\n                                unsigned int       num_tris )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!tris || !num_tris)\n          return DFB_INVARG;\n\n     if (data->area.wanted.x || data->area.wanted.y) {\n          unsigned int  i;\n          DFBTriangle  *local_tris;\n          bool          malloced = (num_tris > 170);\n\n          if (malloced)\n               local_tris = D_MALLOC( sizeof(DFBTriangle) * num_tris );\n          else\n               local_tris = alloca( sizeof(DFBTriangle) * num_tris );\n\n          for (i = 0; i < num_tris; i++) {\n               local_tris[i].x1 = tris[i].x1 + data->area.wanted.x;\n               local_tris[i].y1 = tris[i].y1 + data->area.wanted.y;\n               local_tris[i].x2 = tris[i].x2 + data->area.wanted.x;\n               local_tris[i].y2 = tris[i].y2 + data->area.wanted.y;\n               local_tris[i].x3 = tris[i].x3 + data->area.wanted.x;\n               local_tris[i].y3 = tris[i].y3 + data->area.wanted.y;\n          }\n\n          CoreGraphicsStateClient_FillTriangles( &data->state_client, local_tris, num_tris );\n\n          if (malloced)\n               D_FREE( local_tris );\n     }\n     else\n          CoreGraphicsStateClient_FillTriangles( &data->state_client, tris, num_tris );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetFont( IDirectFBSurface *thiz,\n                          IDirectFBFont    *font )\n{\n     DFBResult ret;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %p )\\n\", __FUNCTION__, thiz, font );\n\n     if (data->font != font) {\n         if (font) {\n              IDirectFBFont_data *font_data;\n\n              ret = font->AddRef( font );\n              if (ret)\n                   return ret;\n\n              font_data = font->priv;\n              if (!font_data)\n                   return DFB_DEAD;\n\n              if (font_data)\n                   data->encoding = font_data->encoding;\n         }\n\n         if (data->font)\n              data->font->Release( data->font );\n\n         data->font = font;\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_GetFont( IDirectFBSurface  *thiz,\n                          IDirectFBFont    **ret_interface )\n{\n     DFBResult ret;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     if (!data->font) {\n          *ret_interface = NULL;\n          return DFB_MISSINGFONT;\n     }\n\n     ret = data->font->AddRef( data->font );\n     if (ret)\n          return ret;\n\n     *ret_interface = data->font;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_DrawString( IDirectFBSurface    *thiz,\n                             const char          *text,\n                             int                  bytes,\n                             int                  x,\n                             int                  y,\n                             DFBSurfaceTextFlags  flags )\n{\n     IDirectFBFont_data *font_data;\n     unsigned int        layers = 1;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %d, %d,%d, 0x%x )\\n\", __FUNCTION__, thiz, bytes, x, y, flags );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!data->font)\n          return DFB_MISSINGFONT;\n\n     if (!text)\n          return DFB_INVARG;\n\n     if (bytes < 0)\n          bytes = strlen( text );\n\n     if (bytes == 0)\n          return DFB_OK;\n\n     font_data = data->font->priv;\n     if (!font_data)\n          return DFB_DEAD;\n\n     if (!font_data)\n          return DFB_DESTROYED;\n\n     if (core_dfb->shutdown_running)\n          return DFB_OK;\n\n     if (flags & DSTF_OUTLINE) {\n          if (!(font_data->font->attributes & DFFA_OUTLINED))\n               return DFB_UNSUPPORTED;\n\n          layers = 2;\n     }\n\n     if (!(flags & DSTF_TOP)) {\n          x += font_data->font->ascender * font_data->font->up_unit_x;\n          y += font_data->font->ascender * font_data->font->up_unit_y;\n\n          if (flags & DSTF_BOTTOM) {\n               x -= font_data->font->descender * font_data->font->up_unit_x;\n               y -= font_data->font->descender * font_data->font->up_unit_y;\n          }\n     }\n\n     if (flags & (DSTF_RIGHT | DSTF_CENTER)) {\n          DFBResult    ret;\n          int          i, num, kx, ky;\n          int          xsize = 0;\n          int          ysize = 0;\n          unsigned int prev  = 0;\n          unsigned int indices[bytes];\n\n          dfb_font_lock( font_data->font );\n\n          /* Decode string to character indices. */\n          ret = dfb_font_decode_text( font_data->font, data->encoding, text, bytes, indices, &num );\n          if (ret) {\n               dfb_font_unlock( font_data->font );\n               return ret;\n          }\n\n          /* Calculate string width. */\n          for (i = 0; i < num; i++) {\n               unsigned int   current = indices[i];\n               CoreGlyphData *glyph;\n\n               if (dfb_font_get_glyph_data( font_data->font, current, 0, &glyph ) == DFB_OK) {\n                    xsize += glyph->xadvance;\n                    ysize += glyph->yadvance;\n\n                    if (prev && font_data->font->GetKerning &&\n                        font_data->font->GetKerning( font_data->font, prev, current, &kx, &ky ) == DFB_OK) {\n                         xsize += kx << 8;\n                         ysize += ky << 8;\n                    }\n               }\n\n               prev = current;\n          }\n\n          dfb_font_unlock( font_data->font );\n\n          /* Justify. */\n          if (flags & DSTF_RIGHT) {\n               x -= xsize >> 8;\n               y -= ysize >> 8;\n          }\n          else if (flags & DSTF_CENTER) {\n               x -= xsize >> 9;\n               y -= ysize >> 9;\n          }\n     }\n\n     dfb_gfxcard_drawstring( (const unsigned char*) text, bytes, data->encoding,\n                             data->area.wanted.x + x, data->area.wanted.y + y,\n                             font_data->font, layers, &data->state_client, flags );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_DrawGlyph( IDirectFBSurface    *thiz,\n                            unsigned int         character,\n                            int                  x,\n                            int                  y,\n                            DFBSurfaceTextFlags  flags )\n{\n     DFBResult           ret;\n     int                 l;\n     IDirectFBFont_data *font_data;\n     CoreGlyphData      *glyph[DFB_FONT_MAX_LAYERS];\n     unsigned int        index;\n     unsigned int        layers = 1;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, 0x%x, %d,%d, 0x%x )\\n\", __FUNCTION__, thiz, character, x, y, flags );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!data->font)\n          return DFB_MISSINGFONT;\n\n     if (!character)\n          return DFB_INVARG;\n\n     font_data = data->font->priv;\n     if (!font_data)\n          return DFB_DEAD;\n\n     if (!font_data)\n          return DFB_DESTROYED;\n\n     if (core_dfb->shutdown_running)\n          return DFB_OK;\n\n     if (flags & DSTF_OUTLINE) {\n          if (!(font_data->font->attributes & DFFA_OUTLINED))\n               return DFB_UNSUPPORTED;\n\n          layers = 2;\n     }\n\n     dfb_font_lock( font_data->font );\n\n     ret = dfb_font_decode_character( font_data->font, data->encoding, character, &index );\n     if (ret) {\n          dfb_font_unlock( font_data->font );\n          return ret;\n     }\n\n     for (l = 0; l < layers; l++) {\n          ret = dfb_font_get_glyph_data( font_data->font, index, l, &glyph[l] );\n          if (ret) {\n               dfb_font_unlock( font_data->font );\n               return ret;\n          }\n     }\n\n     if (!(flags & DSTF_TOP)) {\n          x += font_data->font->ascender * font_data->font->up_unit_x;\n          y += font_data->font->ascender * font_data->font->up_unit_y;\n\n          if (flags & DSTF_BOTTOM) {\n               x -= font_data->font->descender * font_data->font->up_unit_x;\n               y -= font_data->font->descender * font_data->font->up_unit_y;\n          }\n     }\n\n     if (flags & (DSTF_RIGHT | DSTF_CENTER)) {\n          if (flags & DSTF_RIGHT) {\n               x -= glyph[0]->xadvance;\n               y -= glyph[0]->yadvance;\n          }\n          else if (flags & DSTF_CENTER) {\n               x -= glyph[0]->xadvance >> 1;\n               y -= glyph[0]->yadvance >> 1;\n          }\n     }\n\n     dfb_gfxcard_drawglyph( glyph, data->area.wanted.x + x, data->area.wanted.y + y,\n                            font_data->font, layers, &data->state_client, flags );\n\n     dfb_font_unlock( font_data->font );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetEncoding( IDirectFBSurface  *thiz,\n                              DFBTextEncodingID  encoding )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %u )\\n\", __FUNCTION__, thiz, encoding );\n\n     data->encoding = encoding;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_GetSubSurface( IDirectFBSurface    *thiz,\n                                const DFBRectangle  *rect,\n                                IDirectFBSurface   **ret_interface )\n{\n     DFBResult ret;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     direct_mutex_lock( &data->children_lock );\n\n     if (data->children_free) {\n          IDirectFBSurface_data *child_data;\n\n          child_data = (IDirectFBSurface_data*) data->children_free;\n\n          direct_list_remove( &data->children_free, &child_data->link );\n          direct_list_append( &data->children_data, &child_data->link );\n\n          direct_mutex_unlock( &data->children_lock );\n\n          *ret_interface = child_data->thiz;\n\n          ret = (*ret_interface)->MakeSubSurface( *ret_interface, thiz, rect );\n          if (ret) {\n               direct_mutex_unlock( &data->children_lock );\n               return ret;\n          }\n\n          return DFB_OK;\n     }\n\n     direct_mutex_unlock( &data->children_lock );\n\n     DIRECT_ALLOCATE_INTERFACE( *ret_interface, IDirectFBSurface );\n\n     if (rect || data->limit_set) {\n          DFBRectangle wanted, granted;\n\n          /* Compute wanted rectangle. */\n          if (rect) {\n               wanted = *rect;\n\n               wanted.x += data->area.wanted.x;\n               wanted.y += data->area.wanted.y;\n\n               if (wanted.w <= 0 || wanted.h <= 0) {\n                    wanted.w = 0;\n                    wanted.h = 0;\n               }\n          }\n          else {\n               wanted = data->area.wanted;\n          }\n\n          /* Compute granted rectangle. */\n          granted = wanted;\n\n          dfb_rectangle_intersect( &granted, &data->area.granted );\n\n          ret = IDirectFBSurface_Construct( *ret_interface, thiz, &wanted, &granted, &data->area.insets, data->surface,\n                                            data->caps | DSCAPS_SUBSURFACE, data->core, data->idirectfb );\n     }\n     else {\n          ret = IDirectFBSurface_Construct( *ret_interface, thiz, NULL, NULL, &data->area.insets, data->surface,\n                                            data->caps | DSCAPS_SUBSURFACE, data->core, data->idirectfb );\n     }\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBSurface_GetGL( IDirectFBSurface  *thiz,\n                        IDirectFBGL      **ret_interface )\n{\n     DFBResult             ret;\n     DirectInterfaceFuncs *funcs = NULL;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     ret = DirectGetInterface( &funcs, \"IDirectFBGL\", NULL, DirectProbeInterface, thiz );\n     if (ret)\n          return ret;\n\n     ret = funcs->Allocate( (void**) ret_interface );\n     if (ret)\n          return ret;\n\n     ret = funcs->Construct( *ret_interface, thiz, data->idirectfb );\n     if (ret)\n          *ret_interface = NULL;\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBSurface_Dump( IDirectFBSurface *thiz,\n                       const char       *directory,\n                       const char       *prefix )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->caps & DSCAPS_SUBSURFACE) {\n          D_ONCE( \"sub surface dumping not supported\" );\n          return DFB_UNSUPPORTED;\n     }\n\n     if (!directory)\n          return DFB_INVARG;\n\n     CoreGraphicsStateClient_Flush( &data->state_client );\n\n     return dfb_surface_dump_buffer2( data->surface, DSBR_FRONT, DSSE_LEFT, directory, prefix );\n}\n\nstatic DFBResult\nIDirectFBSurface_DisableAcceleration( IDirectFBSurface    *thiz,\n                                      DFBAccelerationMask  mask )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (D_FLAGS_INVALID( mask, DFXL_ALL ))\n          return DFB_INVARG;\n\n     data->state.disabled = mask;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_ReleaseSource( IDirectFBSurface *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     dfb_state_set_source( &data->state, NULL );\n     dfb_state_set_source_mask( &data->state, NULL );\n     dfb_state_set_source2( &data->state, NULL );\n\n     CoreGraphicsStateClient_ReleaseSource( &data->state_client );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetIndexTranslation( IDirectFBSurface *thiz,\n                                      const int        *indices,\n                                      int               num_indices )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!DFB_PIXELFORMAT_IS_INDEXED( data->surface->config.format ))\n          return DFB_UNSUPPORTED;\n\n     if (!indices && num_indices > 0)\n          return DFB_INVAREA;\n\n     if (num_indices < 0 || num_indices > 256)\n          return DFB_INVARG;\n\n     return dfb_state_set_index_translation( &data->state, indices, num_indices );\n}\n\nstatic DFBResult\nIDirectFBSurface_SetRenderOptions( IDirectFBSurface        *thiz,\n                                   DFBSurfaceRenderOptions  options )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     dfb_state_set_render_options( &data->state, options );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetMatrix( IDirectFBSurface *thiz,\n                            const s32        *matrix )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %p )\\n\", __FUNCTION__, thiz, matrix );\n\n     if (!matrix)\n          return DFB_INVARG;\n\n     dfb_state_set_matrix( &data->state, matrix );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetSourceMask( IDirectFBSurface    *thiz,\n                                IDirectFBSurface    *mask,\n                                int                  x,\n                                int                  y,\n                                DFBSurfaceMaskFlags  flags )\n{\n     DFBResult              ret;\n     DFBPoint               offset = { x, y };\n     IDirectFBSurface_data *mask_data;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %p, %d,%d, 0x%04x )\\n\", __FUNCTION__, thiz, mask, x, y, flags );\n\n     if (!mask || flags & ~DSMF_ALL)\n          return DFB_INVARG;\n\n     mask_data = mask->priv;\n     if (!mask_data)\n          return DFB_DEAD;\n\n     if (!mask_data)\n          return DFB_DESTROYED;\n\n     if (!mask_data->surface)\n          return DFB_DESTROYED;\n\n     CoreGraphicsStateClient_Flush( &mask_data->state_client );\n\n     ret = dfb_state_set_source_mask( &data->state, mask_data->surface );\n     if (ret)\n          return ret;\n\n     dfb_state_set_source_mask_vals( &data->state, &offset, flags );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_MakeSubSurface( IDirectFBSurface   *thiz,\n                                 IDirectFBSurface   *from,\n                                 const DFBRectangle *rect )\n{\n     DFBRectangle           wanted, granted;\n     DFBRectangle           full_rect;\n     IDirectFBSurface_data *from_data;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!from)\n          return DFB_INVARG;\n\n     from_data = from->priv;\n     if (!from_data)\n          return DFB_DEAD;\n\n     if (!from_data)\n          return DFB_DESTROYED;\n\n     /* Check if CoreSurface is the same. */\n     if (from_data->surface != data->surface)\n          return DFB_UNSUPPORTED;\n\n     full_rect.x = 0;\n     full_rect.y = 0;\n     full_rect.w = data->surface->config.size.w;\n     full_rect.h = data->surface->config.size.h;\n\n     if (rect || from_data->limit_set) {\n          /* Compute wanted rectangle. */\n          if (rect) {\n               wanted = *rect;\n\n               wanted.x += from_data->area.wanted.x;\n               wanted.y += from_data->area.wanted.y;\n\n               if (wanted.w <= 0 || wanted.h <= 0) {\n                    wanted.w = 0;\n                    wanted.h = 0;\n               }\n          }\n          else {\n               wanted = from_data->area.wanted;\n          }\n\n          /* Compute granted rectangle. */\n          granted = wanted;\n\n          dfb_rectangle_intersect( &granted, &from_data->area.granted );\n     }\n     else {\n          wanted  = full_rect;\n          granted = full_rect;\n     }\n\n     data->caps |= DSCAPS_SUBSURFACE;\n\n     data->area.wanted  = wanted;\n     data->area.granted = granted;\n     data->area.current = data->area.granted;\n     dfb_rectangle_intersect( &data->area.current, &full_rect );\n\n     data->state.clip.x1 = data->area.current.x;\n     data->state.clip.y1 = data->area.current.y;\n     data->state.clip.x2 = data->area.current.x + (data->area.current.w ?: 1) - 1;\n     data->state.clip.y2 = data->area.current.y + (data->area.current.h ?: 1) - 1;\n\n     data->state.modified |= SMF_CLIP;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_Write( IDirectFBSurface   *thiz,\n                        const DFBRectangle *rect,\n                        const void         *ptr,\n                        int                 pitch )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %p, %p [%d] )\\n\", __FUNCTION__, thiz, rect, ptr, pitch );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!rect || !ptr || pitch < DFB_BYTES_PER_LINE(data->surface->config.format, rect->w ) )\n          return DFB_INVARG;\n\n     D_DEBUG_AT( Surface, \"  -> %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS( rect ) );\n\n     return dfb_surface_write_buffer( data->surface, DSBR_BACK, ptr, pitch, rect );\n}\n\nstatic DFBResult\nIDirectFBSurface_Read( IDirectFBSurface   *thiz,\n                       const DFBRectangle *rect,\n                       void               *ptr,\n                       int                 pitch )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %p, %p [%d] )\\n\", __FUNCTION__, thiz, rect, ptr, pitch );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!rect || !ptr || pitch < DFB_BYTES_PER_LINE(data->surface->config.format, rect->w ) )\n          return DFB_INVARG;\n\n     D_DEBUG_AT( Surface, \"  -> %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS( rect ) );\n\n     return dfb_surface_read_buffer( data->surface, DSBR_FRONT, ptr, pitch, rect );\n}\n\nstatic DFBResult\nIDirectFBSurface_SetColors( IDirectFBSurface *thiz,\n                            const DFBColorID *ids,\n                            const DFBColor   *colors,\n                            unsigned int      num )\n{\n     unsigned int i;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %p, %p, %u )\\n\", __FUNCTION__, thiz, ids, colors, num );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     for (i = 0; i < num; i++) {\n          D_DEBUG_AT( Surface, \"  -> [%u] id %u = %02x %02x %02x %02x\\n\",\n                      i, ids[i], colors[i].a, colors[i].r, colors[i].g, colors[i].b );\n\n          if (ids[i] >= DFB_COLOR_IDS_MAX)\n               return DFB_INVARG;\n\n          data->state.colors[ids[i]] = colors[i];\n\n          if (DFB_PIXELFORMAT_IS_INDEXED( data->surface->config.format ))\n               data->state.color_indices[ids[i]] = dfb_palette_search( data->surface->palette,\n                                                                       colors[i].r, colors[i].g, colors[i].b,\n                                                                       colors[i].a );\n     }\n\n     dfb_state_set_color( &data->state, &data->state.colors[0] );\n     dfb_state_set_color_index( &data->state, data->state.color_indices[0] );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_BatchBlit2( IDirectFBSurface   *thiz,\n                             IDirectFBSurface   *source,\n                             IDirectFBSurface   *source2,\n                             const DFBRectangle *source_rects,\n                             const DFBPoint     *dest_points,\n                             const DFBPoint     *source2_points,\n                             int                 num )\n{\n     int                    i, dx, dy, sx, sy, sx2, sy2;\n     DFBRectangle          *rects;\n     DFBPoint              *points;\n     DFBPoint              *points2;\n     IDirectFBSurface_data *src_data;\n     IDirectFBSurface_data *src2_data;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!source || !source2 || !source_rects || !dest_points || !source2_points || num < 1)\n          return DFB_INVARG;\n\n     src_data = source->priv;\n\n     if (!src_data->area.current.w || !src_data->area.current.h)\n          return DFB_INVAREA;\n\n     src2_data = source2->priv;\n\n     if (!src2_data->area.current.w || !src2_data->area.current.h)\n          return DFB_INVAREA;\n\n     dx = data->area.wanted.x;\n     dy = data->area.wanted.y;\n\n     sx = src_data->area.wanted.x;\n     sy = src_data->area.wanted.y;\n\n     sx2 = src2_data->area.wanted.x;\n     sy2 = src2_data->area.wanted.y;\n\n     rects   = alloca( sizeof(DFBRectangle) * num );\n     points  = alloca( sizeof(DFBPoint) * num );\n     points2 = alloca( sizeof(DFBPoint) * num );\n\n     direct_memcpy( rects, source_rects, sizeof(DFBRectangle) * num );\n     direct_memcpy( points, dest_points, sizeof(DFBPoint) * num );\n     direct_memcpy( points2, source2_points, sizeof(DFBPoint) * num );\n\n     for (i = 0; i < num; i++) {\n          DFBRectangle rect2;\n\n          rects[i].x += sx;\n          rects[i].y += sy;\n\n          points[i].x += dx;\n          points[i].y += dy;\n\n          points2[i].x += sx2;\n          points2[i].y += sy2;\n\n          if (!dfb_rectangle_intersect( &rects[i], &src_data->area.current ))\n               rects[i].w = rects[i].h = 0;\n          else {\n               points[i].x += rects[i].x - (source_rects[i].x + sx);\n               points[i].y += rects[i].y - (source_rects[i].y + sy);\n               points2[i].x += rects[i].x - (source_rects[i].x + sx);\n               points2[i].y += rects[i].y - (source_rects[i].y + sy);\n\n               rect2.x = points2[i].x;\n               rect2.y = points2[i].y;\n               rect2.w = rects[i].w;\n               rect2.h = rects[i].h;\n\n               if (!dfb_rectangle_intersect( &rect2, &src2_data->area.current ))\n                    rects[i].w = rects[i].h = 0;\n\n               points[i].x += rect2.x - points2[i].x;\n               points[i].y += rect2.y - points2[i].y;\n               points2[i].x += rect2.x - points2[i].x;\n               points2[i].y += rect2.y - points2[i].y;\n\n               rects[i].w = rect2.w;\n               rects[i].h = rect2.h;\n          }\n     }\n\n     CoreGraphicsStateClient_Flush( &src_data->state_client );\n     CoreGraphicsStateClient_Flush( &src2_data->state_client );\n\n     dfb_state_set_source( &data->state, src_data->surface );\n     dfb_state_set_source2( &data->state, src2_data->surface );\n\n     dfb_state_set_from( &data->state, DSBR_FRONT, src_data->src_eye );\n\n     /* Fetch the source color key from the source if necessary. */\n     if (data->state.blittingflags & DSBLIT_SRC_COLORKEY)\n          dfb_state_set_src_colorkey( &data->state, src_data->src_key.value );\n\n     CoreGraphicsStateClient_Blit2( &data->state_client, rects, points, points2, num );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_GetPhysicalAddress( IDirectFBSurface *thiz,\n                                     unsigned long    *addr )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->locked)\n          return DFB_ACCESSDENIED;\n\n     if (!data->lock.phys) {\n          /* The surface is probably in a system buffer if there's no physical address. */\n          return DFB_UNSUPPORTED;\n     }\n\n     if (!addr)\n          return DFB_INVARG;\n\n     *addr = data->lock.phys;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_FillTrapezoids( IDirectFBSurface   *thiz,\n                                 const DFBTrapezoid *traps,\n                                 unsigned int        num_traps )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!traps || !num_traps)\n          return DFB_INVARG;\n\n     if (data->area.wanted.x || data->area.wanted.y) {\n          unsigned int  i;\n          DFBTrapezoid *local_traps;\n          bool          malloced = (num_traps > 170);\n\n          if (malloced)\n               local_traps = D_MALLOC( sizeof(DFBTrapezoid) * num_traps );\n          else\n               local_traps = alloca( sizeof(DFBTrapezoid) * num_traps );\n\n          for (i = 0; i < num_traps; i++) {\n               local_traps[i].x1 = traps[i].x1 + data->area.wanted.x;\n               local_traps[i].y1 = traps[i].y1 + data->area.wanted.y;\n               local_traps[i].w1 = traps[i].w1;\n               local_traps[i].x2 = traps[i].x2 + data->area.wanted.x;\n               local_traps[i].y2 = traps[i].y2 + data->area.wanted.y;\n               local_traps[i].w2 = traps[i].w2;\n          }\n\n          CoreGraphicsStateClient_FillTrapezoids( &data->state_client, local_traps, num_traps );\n\n          if (malloced)\n               D_FREE( local_traps );\n     }\n     else\n          CoreGraphicsStateClient_FillTrapezoids( &data->state_client, traps, num_traps );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_FillQuadrangles( IDirectFBSurface *thiz,\n                                  const DFBPoint   *points,\n                                  unsigned int      num_points )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!points || !num_points)\n          return DFB_INVARG;\n\n     if (data->area.wanted.x || data->area.wanted.y) {\n          unsigned int  i;\n          DFBPoint     *local_points = alloca( sizeof(DFBPoint) * num_points );\n\n          for (i = 0; i < num_points; i++) {\n               local_points[i].x = points[i].x + data->area.wanted.x;\n               local_points[i].y = points[i].y + data->area.wanted.y;\n          }\n\n          CoreGraphicsStateClient_FillQuadrangles( &data->state_client, local_points, num_points );\n     }\n     else\n          CoreGraphicsStateClient_FillQuadrangles( &data->state_client, points, num_points );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetSrcColorKeyExtended( IDirectFBSurface          *thiz,\n                                         const DFBColorKeyExtended *colorkey_extended )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     dfb_state_set_src_colorkey_extended( &data->state, colorkey_extended );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetDstColorKeyExtended( IDirectFBSurface          *thiz,\n                                         const DFBColorKeyExtended *colorkey_extended )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     dfb_state_set_dst_colorkey_extended( &data->state, colorkey_extended );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_DrawMonoGlyphs( IDirectFBSurface             *thiz,\n                                 const void                   *glyphs[],\n                                 const DFBMonoGlyphAttributes *attributes,\n                                 const DFBPoint               *dest_points,\n                                 unsigned int                  num )\n{\n     int       i, dx, dy;\n     DFBPoint *points;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!glyphs || !attributes || !dest_points || num < 1)\n          return DFB_INVARG;\n\n     dx = data->area.wanted.x;\n     dy = data->area.wanted.y;\n\n     points = alloca( sizeof(DFBPoint) * num );\n\n     for (i = 0; i < num; i++) {\n          points[i].x = dest_points[i].x + dx;\n          points[i].y = dest_points[i].y + dy;\n     }\n\n     dfb_gfxcard_draw_mono_glyphs( glyphs, attributes, points, num, &data->state );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetSrcColorMatrix( IDirectFBSurface *thiz,\n                                    const s32        *matrix )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %p )\\n\", __FUNCTION__, thiz, matrix );\n\n     if (!matrix)\n          return DFB_INVARG;\n\n     dfb_state_set_src_colormatrix( &data->state, matrix );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetSrcConvolution( IDirectFBSurface           *thiz,\n                                    const DFBConvolutionFilter *filter )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %p )\\n\", __FUNCTION__, thiz, filter );\n\n     if (!filter)\n          return DFB_INVARG;\n\n     dfb_state_set_src_convolution( &data->state, filter );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_GetID( IDirectFBSurface *thiz,\n                        DFBSurfaceID     *ret_surface_id )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!ret_surface_id)\n          return DFB_INVARG;\n\n     *ret_surface_id = data->surface->object.id;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_AllowAccess( IDirectFBSurface *thiz,\n                              const char       *executable )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     return CoreDFB_AllowSurface( data->core, data->surface, executable, strlen( executable ) + 1 );\n}\n\nstatic DFBResult\nIDirectFBSurface_CreateEventBuffer( IDirectFBSurface      *thiz,\n                                    IDirectFBEventBuffer **ret_interface )\n{\n     IDirectFBEventBuffer *iface;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBEventBuffer );\n\n     IDirectFBEventBuffer_Construct( iface, NULL, NULL );\n\n     IDirectFBEventBuffer_AttachSurface( iface, data->surface );\n\n     *ret_interface = iface;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_AttachEventBuffer( IDirectFBSurface     *thiz,\n                                    IDirectFBEventBuffer *buffer )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     IDirectFBEventBuffer_AttachSurface( buffer, data->surface );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_DetachEventBuffer( IDirectFBSurface     *thiz,\n                                    IDirectFBEventBuffer *buffer )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return IDirectFBEventBuffer_DetachSurface( buffer, data->surface );\n}\n\nstatic DFBResult\nIDirectFBSurface_BatchStretchBlit( IDirectFBSurface   *thiz,\n                                   IDirectFBSurface   *source,\n                                   const DFBRectangle *source_rects,\n                                   const DFBRectangle *dest_rects,\n                                   int                 num )\n{\n     int                    i, dx, dy, sx, sy;\n     DFBRectangle          *srects, *drects;\n     IDirectFBSurface_data *src_data;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %d )\\n\", __FUNCTION__, thiz, num );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->locked)\n          return DFB_LOCKED;\n\n     if (!source || !source_rects || !dest_rects || num < 1)\n          return DFB_INVARG;\n\n     src_data = source->priv;\n\n     if (!src_data->area.current.w || !src_data->area.current.h)\n          return DFB_INVAREA;\n\n     dx = data->area.wanted.x;\n     dy = data->area.wanted.y;\n\n     sx = src_data->area.wanted.x;\n     sy = src_data->area.wanted.y;\n\n     srects = alloca( sizeof(DFBRectangle) * num );\n     drects = alloca( sizeof(DFBRectangle) * num );\n\n     direct_memcpy( srects, source_rects, sizeof(DFBRectangle) * num );\n     direct_memcpy( drects, dest_rects, sizeof(DFBRectangle) * num );\n\n     for (i = 0; i < num; ++i) {\n          DFBRectangle orig_src;\n\n          if (drects[i].w < 1 || drects[i].h < 1) {\n               drects[i].w = 0;\n               drects[i].h = 0;\n               continue;\n          }\n\n          drects[i].x += dx;\n          drects[i].y += dy;\n\n          if (srects[i].w < 1 || srects[i].h < 1)\n               return DFB_INVARG;\n\n          srects[i].x += sx;\n          srects[i].y += sy;\n\n          /* Clipping of the source rectangle must be applied to the destination. */\n          orig_src = srects[i];\n\n          if (!dfb_rectangle_intersect( &srects[i], &src_data->area.current )) {\n               srects[i].w = srects[i].h = 0;\n               drects[i].w = drects[i].h = 0;\n               continue;\n          }\n\n          if (srects[i].x != orig_src.x)\n               drects[i].x += (int) ( (srects[i].x - orig_src.x) * (drects[i].w / (float) orig_src.w) + 0.5f);\n\n          if (srects[i].y != orig_src.y)\n               drects[i].y += (int) ( (srects[i].y - orig_src.y) * (drects[i].h / (float) orig_src.h) + 0.5f);\n\n          if (srects[i].w != orig_src.w)\n               drects[i].w = D_ICEIL( drects[i].w * (srects[i].w / (float) orig_src.w) );\n\n          if (srects[i].h != orig_src.h)\n               drects[i].h = D_ICEIL( drects[i].h * (srects[i].h / (float) orig_src.h) );\n\n          D_DEBUG_AT( Surface, \"  -> [%2d] %4d,%4d-%4dx%4d <- %4d,%4d-%4dx%4d\\n\", i,\n                      drects[i].x, drects[i].y, drects[i].w, drects[i].h,\n                      srects[i].x, srects[i].y, srects[i].w, srects[i].h );\n     }\n\n     CoreGraphicsStateClient_Flush( &src_data->state_client );\n\n     dfb_state_set_source( &data->state, src_data->surface );\n\n     dfb_state_set_from( &data->state, DSBR_FRONT, src_data->src_eye );\n\n     /* Fetch the source color key from the source if necessary. */\n     if (data->state.blittingflags & DSBLIT_SRC_COLORKEY)\n          dfb_state_set_src_colorkey( &data->state, src_data->src_key.value );\n\n     CoreGraphicsStateClient_StretchBlit( &data->state_client, srects, drects, num );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_MakeClient( IDirectFBSurface *thiz )\n{\n     DFBResult ret;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p [%u] )\\n\", __FUNCTION__, data->surface, data->surface->object.id );\n\n     if (data->surface_client) {\n          D_DEBUG_AT( Surface, \"  -> already client!\\n\" );\n          return DFB_BUSY;\n     }\n\n     ret = CoreSurface_CreateClient( data->surface, &data->surface_client );\n     if (ret)\n          return ret;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_FrameAck( IDirectFBSurface *thiz,\n                           u32               flip_count )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface_Updates, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface_client)\n          return DFB_UNSUPPORTED;\n\n     direct_mutex_lock( &data->surface_client_lock );\n\n     D_DEBUG_AT( Surface_Updates, \"  -> surface %p [%u]\\n\", data->surface, data->surface->object.id );\n     D_DEBUG_AT( Surface_Updates, \"  -> flip count %u\\n\", flip_count );\n\n     data->surface_client_flip_count = flip_count;\n\n     CoreSurfaceClient_FrameAck( data->surface_client, flip_count );\n\n     direct_mutex_unlock( &data->surface_client_lock );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_DumpRaw( IDirectFBSurface *thiz,\n                          const char       *directory,\n                          const char       *prefix )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     if (!data->area.current.w || !data->area.current.h)\n          return DFB_INVAREA;\n\n     if (data->caps & DSCAPS_SUBSURFACE) {\n          D_ONCE( \"sub surface dumping not supported\" );\n          return DFB_UNSUPPORTED;\n     }\n\n     if (!directory)\n          return DFB_INVARG;\n\n     return dfb_surface_dump_raw_buffer( data->surface, DSBR_FRONT, directory, prefix );\n}\n\nstatic DFBResult\nIDirectFBSurface_GetFrameTime( IDirectFBSurface *thiz,\n                               long long        *ret_micros )\n{\n     long long now;\n     long long interval = 0;\n     long long max      = 0;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface_Updates, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->surface)\n          return DFB_DESTROYED;\n\n     interval = data->surface->frametime_config.interval;\n\n     D_DEBUG_AT( Surface_Updates, \"  -> surface interval: %lld\\n\", interval );\n\n     D_DEBUG_AT( Surface_Updates, \"  -> config flags: 0x%08x\\n\", data->frametime_config.flags );\n\n     if (data->surface->frametime_config.flags & DFTCF_MAX_ADVANCE)\n          max = data->surface->frametime_config.max_advance;\n\n     if (data->frametime_config.flags & DFTCF_INTERVAL) {\n          interval = data->frametime_config.interval;\n\n          D_DEBUG_AT( Surface_Updates, \"  -> local configured interval: %lld\\n\", interval );\n     }\n\n     if (data->frametime_config.flags & DFTCF_MAX_ADVANCE)\n          max = data->frametime_config.max_advance;\n\n     if (!interval) {\n          interval = dfb_config->screen_frame_interval;\n\n          D_DEBUG_AT( Surface_Updates, \"  -> using fallback default interval: %lld\\n\", interval );\n     }\n\n     if (!max)\n          max = dfb_config->max_frame_advance;\n\n     data->current_frame_time += interval;\n\n     now = direct_clock_get_time( DIRECT_CLOCK_MONOTONIC );\n\n     if (now > data->current_frame_time)\n          data->current_frame_time = now;\n     else if (max) {\n          while (data->current_frame_time - now > max) {\n               D_DEBUG_AT( Surface_Updates, \"  -> sleeping for %lld us...\\n\", data->current_frame_time - now - max );\n\n               direct_thread_sleep( data->current_frame_time - now - max );\n\n               now = direct_clock_get_time( DIRECT_CLOCK_MONOTONIC );\n          }\n     }\n\n     D_DEBUG_AT( Surface_Updates, \"  -> %lld, %lld ahead\\n\", data->current_frame_time, data->current_frame_time - now );\n\n     if (ret_micros)\n          *ret_micros = data->current_frame_time;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_SetFrameTimeConfig( IDirectFBSurface         *thiz,\n                                     const DFBFrameTimeConfig *config )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface_Updates, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (config) {\n          if (config->flags & DFTCF_INTERVAL)\n               D_DEBUG_AT( Surface_Updates, \"  -> interval: %lld\\n\", config->interval );\n\n          if (config->flags & DFTCF_MAX_ADVANCE)\n               D_DEBUG_AT( Surface_Updates, \"  -> max_advance: %lld\\n\", config->max_advance );\n\n          data->frametime_config = *config;\n     }\n     else\n          memset( &data->frametime_config, 0, sizeof(data->frametime_config) );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_Allocate( IDirectFBSurface            *thiz,\n                           DFBSurfaceBufferRole         role,\n                           DFBSurfaceStereoEye          eye,\n                           const char                  *key,\n                           u64                          handle,\n                           IDirectFBSurfaceAllocation **ret_interface )\n{\n     DFBResult                   ret;\n     CoreSurfaceAllocation      *allocation;\n     IDirectFBSurfaceAllocation *iface;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, role %u, eye %u, key '%s', handle 0x%08llx )\\n\", __FUNCTION__,\n                 thiz, role, eye, key, (unsigned long long) handle );\n\n     ret = CoreSurface_Allocate( data->surface, role, eye, key, strlen( key ) + 1, handle, &allocation );\n     if (ret) {\n          D_DERROR( ret,\n                    \"IDirectFBSurface: CoreSurface_Allocate( role %u, eye %u, key '%s', handle 0x%08llx ) failed!\\n\",\n                    role, eye, key, (unsigned long long) handle );\n          return ret;\n     }\n\n     DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBSurfaceAllocation );\n\n     if (iface)\n          ret = IDirectFBSurfaceAllocation_Construct( iface, allocation, thiz );\n     else\n          ret = DFB_NOSYSTEMMEMORY;\n\n     if (ret)\n          goto out;\n\n     *ret_interface = iface;\n\nout:\n     dfb_surface_allocation_unref( allocation );\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBSurface_GetAllocation( IDirectFBSurface            *thiz,\n                                DFBSurfaceBufferRole         role,\n                                DFBSurfaceStereoEye          eye,\n                                const char                  *key,\n                                IDirectFBSurfaceAllocation **ret_interface )\n{\n     DFBResult                   ret;\n     CoreSurfaceAllocation      *allocation;\n     IDirectFBSurfaceAllocation *iface;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, role %u, eye %u, key '%s' )\\n\", __FUNCTION__, thiz, role, eye, key );\n\n     ret = CoreSurface_GetAllocation( data->surface, role, eye, key, strlen( key ) + 1, &allocation );\n     if (ret) {\n          D_DERROR( ret, \"IDirectFBSurface: CoreSurface_GetAllocation( role %u, eye %u, key '%s' ) failed!\\n\",\n                    role, eye, key );\n          return ret;\n     }\n\n     DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBSurfaceAllocation );\n\n     if (iface)\n          ret = IDirectFBSurfaceAllocation_Construct( iface, allocation, thiz );\n     else\n          ret = DFB_NOSYSTEMMEMORY;\n\n     if (ret)\n          goto out;\n\n     *ret_interface = iface;\n\nout:\n     dfb_surface_allocation_unref( allocation );\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBSurface_GetAllocations( IDirectFBSurface            *thiz,\n                                 const char                  *key,\n                                 unsigned int                 max_num,\n                                 unsigned int                *ret_num,\n                                 IDirectFBSurfaceAllocation **ret_interface_left,\n                                 IDirectFBSurfaceAllocation **ret_interface_right )\n{\n     DFBResult                   ret;\n     int                         i;\n     unsigned int                num;\n     IDirectFBSurfaceAllocation *left[MAX_SURFACE_BUFFERS];\n     IDirectFBSurfaceAllocation *right[MAX_SURFACE_BUFFERS];\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p, key '%s', max %u )\\n\", __FUNCTION__, thiz, key, max_num );\n\n     if (!key || max_num < 1 || !ret_num || (!ret_interface_left && !ret_interface_right))\n          return DFB_INVARG;\n\n     num = data->surface->num_buffers;\n     if (num > max_num)\n          num = max_num;\n\n     memset( left, 0, num * sizeof(left[0]) );\n     memset( right, 0, num * sizeof(right[0]) );\n\n     for (i = 0; i < num; i++) {\n          if (ret_interface_left) {\n               ret = thiz->GetAllocation( thiz, i, DSSE_LEFT, key, &left[i] );\n               if (ret)\n                    goto error;\n          }\n\n          if (ret_interface_right) {\n               ret = thiz->GetAllocation( thiz, i, DSSE_RIGHT, key, &right[i] );\n               if (ret)\n                    goto error;\n          }\n     }\n\n     for (i = 0; i < num; i++) {\n          if (ret_interface_left)\n               ret_interface_left[i] = left[i];\n\n          if (ret_interface_right)\n               ret_interface_right[i] = right[i];\n     }\n\n     *ret_num = num;\n\n     return DFB_OK;\n\nerror:\n     for (i = num - 1; i >= 0; i--) {\n          if (right[i])\n               right[i]->Release( right[i] );\n\n          if (left[i])\n               left[i]->Release( left[i] );\n     }\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBSurface_Flush( IDirectFBSurface     *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     CoreGraphicsStateClient_Flush( &data->state_client );\n\n     return DFB_OK;\n}\n\nstatic ReactionResult\nIDirectFBSurface_React( const void *msg_data,\n                        void       *ctx )\n{\n     const CoreSurfaceNotification *notification = msg_data;\n     IDirectFBSurface              *thiz         = ctx;\n     IDirectFBSurface_data         *data         = thiz->priv;\n\n     D_DEBUG_AT( Surface, \"%s( %p, %p ) <- surface %p\\n\", __FUNCTION__, notification, thiz, data->surface );\n\n     if (notification->flags & CSNF_DESTROY) {\n          if (data->surface) {\n               D_WARN( \"surface destroyed\" );\n               data->surface = NULL;\n          }\n\n          return RS_REMOVE;\n     }\n\n     if (notification->flags & CSNF_SIZEFORMAT) {\n          unsigned int i;\n          DFBRectangle rect = { 0, 0, data->surface->config.size.w, data->surface->config.size.h };\n\n          dfb_rectangle_subtract( &rect, &data->area.insets );\n\n          if (data->limit_set) {\n               data->area.current = data->area.granted;\n\n               dfb_rectangle_intersect( &data->area.current, &rect );\n          }\n          else\n               data->area.wanted = data->area.granted = data->area.current = rect;\n\n          /* Reset clip. */\n          if (data->clip_set)\n               thiz->SetClip( thiz, &data->clip_wanted );\n          else\n               thiz->SetClip( thiz, NULL );\n\n          for (i = 0; i < data->local_buffer_count; i++) {\n               if (data->allocations[i]) {\n                    dfb_surface_allocation_unref( data->allocations[i] );\n                    data->allocations[i] = NULL;\n               }\n          }\n\n          data->local_buffer_count = data->surface->num_buffers;\n     }\n\n     return RS_OK;\n}\n\nstatic ReactionResult\nIDirectFBSurface_FrameReact( const void *msg_data,\n                             void       *ctx )\n{\n     const CoreSurfaceNotification *notification = msg_data;\n     IDirectFBSurface              *thiz         = ctx;\n     IDirectFBSurface_data         *data         = thiz->priv;\n\n     D_DEBUG_AT( Surface_Updates, \"%s( %p, %p ) <- surface %p\\n\", __FUNCTION__, notification, thiz, data->surface );\n\n     if (notification->flags & CSNF_FRAME) {\n          direct_mutex_lock( &data->back_buffer_lock );\n\n          D_DEBUG_AT( Surface_Updates, \"  -> got frame ack %u\\n\", notification->flip_count );\n\n          data->frame_ack = notification->flip_count;\n\n          if (data->local_flip_count < notification->flip_count) {\n               D_DEBUG_AT( Surface_Updates, \"  -> local count (%u) lower than frame ack (%u)\\n\",\n                           data->local_flip_count, notification->flip_count );\n\n               data->local_flip_count = notification->flip_count;\n          }\n\n          direct_waitqueue_broadcast( &data->back_buffer_wq );\n\n          direct_mutex_unlock( &data->back_buffer_lock );\n     }\n\n     return RS_OK;\n}\n\nDFBResult\nIDirectFBSurface_Construct( IDirectFBSurface       *thiz,\n                            IDirectFBSurface       *parent,\n                            DFBRectangle           *wanted,\n                            DFBRectangle           *granted,\n                            DFBInsets              *insets,\n                            CoreSurface            *surface,\n                            DFBSurfaceCapabilities  caps,\n                            CoreDFB                *core,\n                            IDirectFB              *idirectfb )\n{\n     DFBResult    ret;\n     DFBRectangle rect = { 0, 0, surface->config.size.w, surface->config.size.h };\n\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBSurface )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     ret = dfb_surface_ref( surface );\n     if (ret) {\n          DIRECT_DEALLOCATE_INTERFACE( thiz );\n          return ret;\n     }\n\n     data->ref                = 1;\n     data->thiz               = thiz;\n     data->surface            = surface;\n     data->caps               = caps | surface->config.caps;\n     data->core               = core;\n     data->idirectfb          = idirectfb;\n     data->frame_ack          = surface->flips;\n     data->src_eye            = DSSE_LEFT;\n     data->local_flip_count   = surface->flips;\n     data->local_buffer_count = surface->num_buffers;\n\n     if (parent) {\n          IDirectFBSurface_data *parent_data;\n\n          if (parent->AddRef( parent )) {\n               dfb_surface_unref( surface );\n               DIRECT_DEALLOCATE_INTERFACE( thiz );\n               return DFB_FAILURE;\n          }\n\n          parent_data = parent->priv;\n          if (!parent_data) {\n               dfb_surface_unref( surface );\n               DIRECT_DEALLOCATE_INTERFACE( thiz );\n               return DFB_DEAD;\n          }\n\n          if (!parent_data) {\n               dfb_surface_unref( surface );\n               DIRECT_DEALLOCATE_INTERFACE( thiz );\n               return DFB_DESTROYED;\n          }\n\n          direct_mutex_lock( &parent_data->children_lock );\n\n          direct_list_append( &parent_data->children_data, &data->link );\n\n          direct_mutex_unlock( &parent_data->children_lock );\n\n          data->parent = parent;\n     }\n\n     direct_mutex_init( &data->children_lock );\n\n     direct_waitqueue_init( &data->back_buffer_wq );\n     direct_mutex_init( &data->back_buffer_lock );\n\n     direct_mutex_init( &data->surface_client_lock );\n\n     /* The area insets. */\n     if (insets) {\n          data->area.insets = *insets;\n          dfb_rectangle_subtract( &rect, insets );\n     }\n\n     /* The area that was requested. */\n     if (wanted)\n          data->area.wanted = *wanted;\n     else\n          data->area.wanted = rect;\n\n     /* The area that will never be exceeded. */\n     if (granted)\n          data->area.granted = *granted;\n     else\n          data->area.granted = data->area.wanted;\n\n     /* The currently accessible rectangle. */\n     data->area.current = data->area.granted;\n     dfb_rectangle_intersect( &data->area.current, &rect );\n\n     D_DEBUG_AT( Surface, \"  -> wanted  %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS( &data->area.wanted ) );\n     D_DEBUG_AT( Surface, \"  -> granted %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS( &data->area.granted ) );\n     D_DEBUG_AT( Surface, \"  -> current %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS( &data->area.current ) );\n\n     /* Whether granted rectangle is meaningful. */\n     data->limit_set = (granted != NULL);\n\n     dfb_state_init( &data->state, core );\n     dfb_state_set_destination_2( &data->state, surface, data->local_flip_count );\n\n     data->state.clip.x1  = data->area.current.x;\n     data->state.clip.y1  = data->area.current.y;\n     data->state.clip.x2  = data->area.current.x + (data->area.current.w ?: 1) - 1;\n     data->state.clip.y2  = data->area.current.y + (data->area.current.h ?: 1) - 1;\n     data->state.modified = SMF_ALL;\n\n     ret = CoreGraphicsStateClient_Init( &data->state_client, &data->state );\n     if (ret) {\n          dfb_state_destroy( &data->state );\n          if (parent)\n               parent->Release( parent );\n          dfb_surface_unref( surface );\n          DIRECT_DEALLOCATE_INTERFACE( thiz );\n          return ret;\n     }\n\n     if (data->surface->config.flags & CSCONF_PREALLOCATED) {\n          ret = register_prealloc( data );\n          if (ret) {\n               CoreGraphicsStateClient_Deinit( &data->state_client );\n               dfb_state_destroy( &data->state );\n               if (parent)\n                    parent->Release( parent );\n               dfb_surface_unref( surface );\n               DIRECT_DEALLOCATE_INTERFACE( thiz );\n               return ret;\n          }\n     }\n\n     dfb_surface_attach( surface, IDirectFBSurface_React, thiz, &data->reaction );\n     dfb_surface_attach_channel( surface, CSCH_FRAME, IDirectFBSurface_FrameReact, thiz, &data->reaction_frame );\n\n     thiz->AddRef                 = IDirectFBSurface_AddRef;\n     thiz->Release                = IDirectFBSurface_Release;\n     thiz->GetCapabilities        = IDirectFBSurface_GetCapabilities;\n     thiz->GetPosition            = IDirectFBSurface_GetPosition;\n     thiz->GetSize                = IDirectFBSurface_GetSize;\n     thiz->GetVisibleRectangle    = IDirectFBSurface_GetVisibleRectangle;\n     thiz->GetPixelFormat         = IDirectFBSurface_GetPixelFormat;\n     thiz->GetColorSpace          = IDirectFBSurface_GetColorSpace;\n     thiz->GetAccelerationMask    = IDirectFBSurface_GetAccelerationMask;\n     thiz->GetPalette             = IDirectFBSurface_GetPalette;\n     thiz->SetPalette             = IDirectFBSurface_SetPalette;\n     thiz->SetAlphaRamp           = IDirectFBSurface_SetAlphaRamp;\n     thiz->GetStereoEye           = IDirectFBSurface_GetStereoEye;\n     thiz->SetStereoEye           = IDirectFBSurface_SetStereoEye;\n     thiz->Lock                   = IDirectFBSurface_Lock;\n     thiz->GetFramebufferOffset   = IDirectFBSurface_GetFramebufferOffset;\n     thiz->Unlock                 = IDirectFBSurface_Unlock;\n     thiz->Flip                   = IDirectFBSurface_Flip;\n     thiz->FlipStereo             = IDirectFBSurface_FlipStereo;\n     thiz->SetField               = IDirectFBSurface_SetField;\n     thiz->Clear                  = IDirectFBSurface_Clear;\n     thiz->SetClip                = IDirectFBSurface_SetClip;\n     thiz->GetClip                = IDirectFBSurface_GetClip;\n     thiz->SetColor               = IDirectFBSurface_SetColor;\n     thiz->SetColorIndex          = IDirectFBSurface_SetColorIndex;\n     thiz->SetSrcBlendFunction    = IDirectFBSurface_SetSrcBlendFunction;\n     thiz->SetDstBlendFunction    = IDirectFBSurface_SetDstBlendFunction;\n     thiz->SetPorterDuff          = IDirectFBSurface_SetPorterDuff;\n     thiz->SetSrcColorKey         = IDirectFBSurface_SetSrcColorKey;\n     thiz->SetSrcColorKeyIndex    = IDirectFBSurface_SetSrcColorKeyIndex;\n     thiz->SetDstColorKey         = IDirectFBSurface_SetDstColorKey;\n     thiz->SetDstColorKeyIndex    = IDirectFBSurface_SetDstColorKeyIndex;\n     thiz->SetBlittingFlags       = IDirectFBSurface_SetBlittingFlags;\n     thiz->Blit                   = IDirectFBSurface_Blit;\n     thiz->TileBlit               = IDirectFBSurface_TileBlit;\n     thiz->BatchBlit              = IDirectFBSurface_BatchBlit;\n     thiz->StretchBlit            = IDirectFBSurface_StretchBlit;\n     thiz->TextureTriangles       = IDirectFBSurface_TextureTriangles;\n     thiz->SetDrawingFlags        = IDirectFBSurface_SetDrawingFlags;\n     thiz->FillRectangle          = IDirectFBSurface_FillRectangle;\n     thiz->DrawRectangle          = IDirectFBSurface_DrawRectangle;\n     thiz->DrawLine               = IDirectFBSurface_DrawLine;\n     thiz->DrawLines              = IDirectFBSurface_DrawLines;\n     thiz->FillTriangle           = IDirectFBSurface_FillTriangle;\n     thiz->FillRectangles         = IDirectFBSurface_FillRectangles;\n     thiz->FillSpans              = IDirectFBSurface_FillSpans;\n     thiz->FillTriangles          = IDirectFBSurface_FillTriangles;\n     thiz->SetFont                = IDirectFBSurface_SetFont;\n     thiz->GetFont                = IDirectFBSurface_GetFont;\n     thiz->DrawString             = IDirectFBSurface_DrawString;\n     thiz->DrawGlyph              = IDirectFBSurface_DrawGlyph;\n     thiz->SetEncoding            = IDirectFBSurface_SetEncoding;\n     thiz->GetSubSurface          = IDirectFBSurface_GetSubSurface;\n     thiz->GetGL                  = IDirectFBSurface_GetGL;\n     thiz->Dump                   = IDirectFBSurface_Dump;\n     thiz->DisableAcceleration    = IDirectFBSurface_DisableAcceleration;\n     thiz->ReleaseSource          = IDirectFBSurface_ReleaseSource;\n     thiz->SetIndexTranslation    = IDirectFBSurface_SetIndexTranslation;\n     thiz->SetRenderOptions       = IDirectFBSurface_SetRenderOptions;\n     thiz->SetMatrix              = IDirectFBSurface_SetMatrix;\n     thiz->SetSourceMask          = IDirectFBSurface_SetSourceMask;\n     thiz->MakeSubSurface         = IDirectFBSurface_MakeSubSurface;\n     thiz->Write                  = IDirectFBSurface_Write;\n     thiz->Read                   = IDirectFBSurface_Read;\n     thiz->SetColors              = IDirectFBSurface_SetColors;\n     thiz->BatchBlit2             = IDirectFBSurface_BatchBlit2;\n     thiz->GetPhysicalAddress     = IDirectFBSurface_GetPhysicalAddress;\n     thiz->FillTrapezoids         = IDirectFBSurface_FillTrapezoids;\n     thiz->FillQuadrangles        = IDirectFBSurface_FillQuadrangles;\n     thiz->SetSrcColorKeyExtended = IDirectFBSurface_SetSrcColorKeyExtended;\n     thiz->SetDstColorKeyExtended = IDirectFBSurface_SetDstColorKeyExtended;\n     thiz->DrawMonoGlyphs         = IDirectFBSurface_DrawMonoGlyphs;\n     thiz->SetSrcColorMatrix      = IDirectFBSurface_SetSrcColorMatrix;\n     thiz->SetSrcConvolution      = IDirectFBSurface_SetSrcConvolution;\n     thiz->GetID                  = IDirectFBSurface_GetID;\n     thiz->AllowAccess            = IDirectFBSurface_AllowAccess;\n     thiz->CreateEventBuffer      = IDirectFBSurface_CreateEventBuffer;\n     thiz->AttachEventBuffer      = IDirectFBSurface_AttachEventBuffer;\n     thiz->DetachEventBuffer      = IDirectFBSurface_DetachEventBuffer;\n     thiz->BatchStretchBlit       = IDirectFBSurface_BatchStretchBlit;\n     thiz->MakeClient             = IDirectFBSurface_MakeClient;\n     thiz->FrameAck               = IDirectFBSurface_FrameAck;\n     thiz->DumpRaw                = IDirectFBSurface_DumpRaw;\n     thiz->GetFrameTime           = IDirectFBSurface_GetFrameTime;\n     thiz->SetFrameTimeConfig     = IDirectFBSurface_SetFrameTimeConfig;\n     thiz->Allocate               = IDirectFBSurface_Allocate;\n     thiz->GetAllocation          = IDirectFBSurface_GetAllocation;\n     thiz->GetAllocations         = IDirectFBSurface_GetAllocations;\n     thiz->Flush                  = IDirectFBSurface_Flush;\n\n     return DFB_OK;\n}\n\nvoid\nIDirectFBSurface_StopAll( IDirectFBSurface_data *data )\n{\n     if (!dfb_config->startstop)\n          return;\n\n     if (data->children_data) {\n          IDirectFBSurface_data *child;\n\n          direct_mutex_lock( &data->children_lock );\n\n          direct_list_foreach (child, data->children_data) {\n               IDirectFBSurface_StopAll( child );\n          }\n\n          direct_mutex_unlock( &data->children_lock );\n     }\n\n     /* Signal end of sequence of operations. */\n     dfb_state_lock( &data->state );\n     dfb_state_stop_drawing( &data->state );\n     dfb_state_unlock( &data->state );\n}\n\nvoid\nIDirectFBSurface_WaitForBackBuffer( IDirectFBSurface_data *data )\n{\n     D_DEBUG_AT( Surface_Updates, \"%s( %p [%u] )\\n\", __FUNCTION__, data, data->surface->object.id );\n     D_DEBUG_AT( Surface_Updates, \"  -> surface %u, notify %u\\n\", data->local_flip_count, data->frame_ack );\n\n     direct_mutex_lock( &data->back_buffer_lock );\n\n     if (data->surface->flips_acked > data->frame_ack)\n          data->frame_ack = data->surface->flips_acked;\n\n     while (data->local_flip_count - data->frame_ack >= data->local_buffer_count - 1) {\n          D_DEBUG_AT( Surface_Updates, \"  -> waiting for back buffer... (surface %u, notify %u)\\n\",\n                      data->local_flip_count, data->frame_ack );\n\n          if (data->local_buffer_count <= 1)\n               break;\n\n          direct_waitqueue_wait( &data->back_buffer_wq, &data->back_buffer_lock );\n     }\n\n     D_DEBUG_AT( Surface_Updates, \"  -> done\\n\" );\n\n     direct_mutex_unlock( &data->back_buffer_lock );\n}\n"
  },
  {
    "path": "src/display/idirectfbsurface.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DISPLAY__IDIRECTFBSURFACE_H__\n#define __DISPLAY__IDIRECTFBSURFACE_H__\n\n#include <core/CoreGraphicsStateClient.h>\n#include <core/state.h>\n\ntypedef DFBResult (*FlipFunc)( void *ctx );\n\n/*\n * private data struct of IDirectFBSurface\n */\ntypedef struct {\n     DirectLink               link;\n\n     int                      ref;                              /* reference counter */\n\n     DFBSurfaceCapabilities   caps;                             /* capabilities */\n\n     struct {\n         /* 'wanted' is passed to GetSubSurface(), it doesn't matter if it's too large or has negative starting\n            coordinates as long as it intersects with the 'granted' rectangle of the parent.\n            'wanted' should be seen as the origin for operations on that surface. Non sub surfaces have a 'wanted'\n            rectangle of '{ 0, 0, width, height }'. 'wanted' is calculated just once during surface creation. */\n         DFBRectangle         wanted;\n         /* 'granted' is the intersection of the 'wanted' rectangle and the 'granted' one of the parent. If they do not\n            intersect, DFB_INVAREA is returned. For non sub surfaces it's the same as the 'wanted' rectangle, because it\n            is the rectangle describing the whole surface. 'granted' is calculated just once during surface creation. */\n         DFBRectangle         granted;\n         /* 'current' is the intersection of the 'granted' rectangle and the surface extents. SetClip() and many other\n            functions are limited by this. This way sub surface area information is preserved during surface resizing,\n            e.g. when resizing a window. Calling SetClip() with NULL causes the clipping region to exactly cover the\n            'current' rectangle, also the flag 'clip_set' is cleared causing the clipping region to be set to the new\n            'current' after resizing. If SetClip() is called with a clipping region specified, an intersection is done\n            with the 'wanted' rectangle that is then stored in 'clip_wanted' and 'clip_set' is set. However, if there\n            is no intersection, DFB_INVARG is returned, otherwise another intersection is made with the 'current'\n            rectangle and gets applied to the surface's state.\n            Each resize, after the 'current' rectangle is updated, the clipping region is set to NULL or 'clip_wanted'\n            depending on 'clip_set'. This way even clipping regions are restored or extended automatically. It's now\n            possible to create a fullscreen primary and call SetVideoMode() with different resolutions or pixelformats\n            several times without the need for updating the primary surface by recreating it. */\n         DFBRectangle         current;\n         /* 'insets' is actually set by the window manager. */\n         DFBInsets            insets;\n     } area;\n\n     bool                     limit_set;                        /* granted rectangle set */\n\n     bool                     clip_set;                         /* fixed clip set, SetClip() called with clip != NULL */\n     DFBRegion                clip_wanted;                      /* last region passed to SetClip() intersected by\n                                                                   wanted area, only valid if clip_set != 0 */\n\n     CoreSurface             *surface;                          /* buffer to show */\n     bool                     locked;                           /* which buffer is locked */\n     CoreSurfaceBufferLock    lock;                             /* lock for allocation */\n\n     IDirectFBFont           *font;                             /* font to use */\n     CardState                state;                            /* render state to use */\n     DFBTextEncodingID        encoding;                         /* text encoding */\n\n     struct {\n          u8                  r;                                /* red component */\n          u8                  g;                                /* green component */\n          u8                  b;                                /* blue component */\n          u32                 value;                            /* r/g/b in surface's format */\n     } src_key;\n\n     struct {\n          u8                  r;                                /* red component */\n          u8                  g;                                /* green component */\n          u8                  b;                                /* blue component */\n          u32                 value;                            /* r/g/b in surface's format */\n     } dst_key;\n\n     Reaction                 reaction;                         /* surface reaction */\n     Reaction                 reaction_frame;                   /* frame reaction for CSCH_FRAME */\n\n     CoreDFB                 *core;\n     IDirectFB               *idirectfb;\n\n     IDirectFBSurface        *thiz;\n     IDirectFBSurface        *parent;\n     DirectLink              *children_data;\n     DirectLink              *children_free;\n     DirectMutex              children_lock;\n\n     CoreGraphicsStateClient  state_client;\n\n     CoreMemoryPermission    *memory_permissions[3];\n     unsigned int             memory_permissions_count;\n\n     DirectWaitQueue          back_buffer_wq;\n     DirectMutex              back_buffer_lock;\n\n     unsigned int             frame_ack;\n\n     CoreSurfaceClient       *surface_client;\n     unsigned int             surface_client_flip_count;\n     DirectMutex              surface_client_lock;\n\n     DFBSurfaceStereoEye      src_eye;\n\n     long long                current_frame_time;\n\n     DFBFrameTimeConfig       frametime_config;\n\n     unsigned int             local_flip_count;\n     unsigned int             local_buffer_count;\n\n     CoreSurfaceAllocation   *allocations[MAX_SURFACE_BUFFERS];\n\n     FlipFunc                 flip_func;\n     void                    *flip_func_ctx;\n} IDirectFBSurface_data;\n\n/*\n * initializes interface struct and private data\n */\nDFBResult IDirectFBSurface_Construct        ( IDirectFBSurface       *thiz,\n                                              IDirectFBSurface       *parent,\n                                              DFBRectangle           *req_rect,\n                                              DFBRectangle           *clip_rect,\n                                              DFBInsets              *insets,\n                                              CoreSurface            *surface,\n                                              DFBSurfaceCapabilities  caps,\n                                              CoreDFB                *core,\n                                              IDirectFB              *idirectfb );\n\n/*\n * destroys surface(s) and frees private data\n */\nvoid      IDirectFBSurface_Destruct         ( IDirectFBSurface       *thiz );\n\n/*\n * flips surface buffers\n */\nDFBResult IDirectFBSurface_Flip             ( IDirectFBSurface       *thiz,\n                                              const DFBRegion        *region,\n                                              DFBSurfaceFlipFlags     flags );\n\n/*\n * flips left and right buffers\n */\nDFBResult IDirectFBSurface_FlipStereo       ( IDirectFBSurface       *thiz,\n                                              const DFBRegion        *left_region,\n                                              const DFBRegion        *right_region,\n                                              DFBSurfaceFlipFlags     flags );\n\n/*\n * stops all drawing\n */\nvoid      IDirectFBSurface_StopAll          ( IDirectFBSurface_data  *data );\n\n/*\n * waits for the back buffer\n */\nvoid      IDirectFBSurface_WaitForBackBuffer( IDirectFBSurface_data  *data );\n\n#endif\n"
  },
  {
    "path": "src/display/idirectfbsurface_layer.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreLayerRegion.h>\n#include <core/CoreSurface.h>\n#include <core/layer_region.h>\n#include <display/idirectfbsurface.h>\n#include <display/idirectfbsurface_layer.h>\n\nD_DEBUG_DOMAIN( Surface, \"IDirectFBSurfaceL\", \"IDirectFBSurface_Layer Interface\" );\n\n/**********************************************************************************************************************/\n\n/*\n * private data struct of IDirectFBSurface_Layer\n */\ntypedef struct {\n     IDirectFBSurface_data  base;   /* base surface implementation */\n\n     CoreLayerRegion       *region; /* the region this surface belongs to */\n} IDirectFBSurface_Layer_data;\n\n/**********************************************************************************************************************/\n\nstatic void\nIDirectFBSurface_Layer_Destruct( IDirectFBSurface *thiz )\n{\n     IDirectFBSurface_Layer_data *data = thiz->priv;\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     dfb_layer_region_unref( data->region );\n\n     IDirectFBSurface_Destruct( thiz );\n}\n\nstatic DirectResult\nIDirectFBSurface_Layer_Release( IDirectFBSurface *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface_Layer )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->base.ref == 0)\n          IDirectFBSurface_Layer_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_Layer_Flip( IDirectFBSurface    *thiz,\n                             const DFBRegion     *region,\n                             DFBSurfaceFlipFlags  flags )\n{\n     DFBResult ret;\n     DFBRegion reg;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface_Layer )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %p, 0x%08x )\\n\", __FUNCTION__, thiz, region, flags );\n\n     if (!data->base.surface)\n          return DFB_DESTROYED;\n\n     if (data->base.locked)\n          return DFB_LOCKED;\n\n     if (!data->base.area.current.w || !data->base.area.current.h ||\n         (region && (region->x1 > region->x2 || region->y1 > region->y2)))\n          return DFB_INVAREA;\n\n     if (data->base.flip_func)\n          return data->base.flip_func( data->base.flip_func_ctx );\n\n     IDirectFBSurface_StopAll( &data->base );\n\n     if (data->base.parent) {\n          IDirectFBSurface_data *parent_data;\n\n          parent_data = data->base.parent->priv;\n          if (!parent_data)\n               return DFB_DEAD;\n\n          if (parent_data) {\n               /* Signal end of sequence of operations. */\n               dfb_state_lock( &parent_data->state );\n               dfb_state_stop_drawing( &parent_data->state );\n               dfb_state_unlock( &parent_data->state );\n          }\n     }\n\n     dfb_region_from_rectangle( &reg, &data->base.area.current );\n\n     if (region) {\n          DFBRegion clip = DFB_REGION_INIT_TRANSLATED( region, data->base.area.wanted.x, data->base.area.wanted.y );\n\n          if (!dfb_region_region_intersect( &reg, &clip ))\n               return DFB_INVAREA;\n     }\n\n     D_DEBUG_AT( Surface, \"  -> flip %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS_FROM_REGION( &reg ) );\n\n     CoreGraphicsStateClient_Flush( &data->base.state_client );\n\n     switch (data->region->config.buffermode) {\n          case DLBM_TRIPLE:\n          case DLBM_BACKVIDEO:\n               if ((flags & DSFLIP_SWAP) ||\n                   (!(flags & DSFLIP_BLIT) &&\n                    reg.x1 == 0                                     && reg.y1 == 0 &&\n                    reg.x2 == data->base.surface->config.size.w - 1 && reg.y2 == data->base.surface->config.size.h - 1))\n                    if (!(flags & DSFLIP_UPDATE))\n                         ++data->base.local_flip_count;\n               break;\n\n          default:\n               break;\n     }\n\n     ret = CoreSurface_Flip2( data->base.surface, DFB_FALSE, &reg, &reg, flags, data->base.current_frame_time );\n     if (ret) {\n          ret = CoreLayerRegion_FlipUpdate2( data->region, &reg, &reg, data->region->surface->flips, flags,\n                                             data->base.current_frame_time );\n          if (ret)\n               return ret;\n     }\n\n     IDirectFBSurface_WaitForBackBuffer( &data->base );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_Layer_FlipStereo( IDirectFBSurface    *thiz,\n                                   const DFBRegion     *left_region,\n                                   const DFBRegion     *right_region,\n                                   DFBSurfaceFlipFlags  flags )\n{\n     DFBResult ret;\n     DFBRegion l_reg, r_reg;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface_Layer )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %p, %p, 0x%08x )\\n\", __FUNCTION__, thiz, left_region, right_region, flags );\n\n     if (!data->base.surface)\n          return DFB_DESTROYED;\n\n     if (!(data->base.surface->config.caps & DSCAPS_STEREO))\n          return DFB_UNSUPPORTED;\n\n     if (data->base.locked)\n          return DFB_LOCKED;\n\n     if (!data->base.area.current.w || !data->base.area.current.h ||\n         (left_region && (left_region->x1 > left_region->x2 || left_region->y1 > left_region->y2)) ||\n         (right_region && (right_region->x1 > right_region->x2 || right_region->y1 > right_region->y2)))\n          return DFB_INVAREA;\n\n     IDirectFBSurface_StopAll( &data->base );\n\n     if (data->base.parent) {\n          IDirectFBSurface_data *parent_data;\n\n          parent_data = data->base.parent->priv;\n          if (!parent_data)\n               return DFB_DEAD;\n\n          if (parent_data) {\n               /* Signal end of sequence of operations. */\n               dfb_state_lock( &parent_data->state );\n               dfb_state_stop_drawing( &parent_data->state );\n               dfb_state_unlock( &parent_data->state );\n          }\n     }\n\n     dfb_region_from_rectangle( &l_reg, &data->base.area.current );\n     dfb_region_from_rectangle( &r_reg, &data->base.area.current );\n\n     if (left_region) {\n          DFBRegion clip;\n          clip = DFB_REGION_INIT_TRANSLATED( left_region, data->base.area.wanted.x, data->base.area.wanted.y );\n\n          if (!dfb_region_region_intersect( &l_reg, &clip ))\n               return DFB_INVAREA;\n     }\n     if (right_region) {\n          DFBRegion clip;\n          clip = DFB_REGION_INIT_TRANSLATED( right_region, data->base.area.wanted.x, data->base.area.wanted.y );\n\n          if (!dfb_region_region_intersect( &r_reg, &clip ))\n               return DFB_INVAREA;\n     }\n\n     D_DEBUG_AT( Surface, \"  -> flip stereo left: %4d,%4d-%4dx%4d right: %4d,%4d-%4dx%4d\\n\",\n                 DFB_RECTANGLE_VALS_FROM_REGION( &l_reg ), DFB_RECTANGLE_VALS_FROM_REGION( &r_reg ) );\n\n     CoreGraphicsStateClient_Flush( &data->base.state_client );\n\n     if (data->base.surface->config.caps & DSCAPS_FLIPPING) {\n          if ((flags & DSFLIP_SWAP) ||\n              (!(flags & DSFLIP_BLIT) &&\n               l_reg.x1 == 0                                     && l_reg.y1 == 0                                     &&\n               l_reg.x2 == data->base.surface->config.size.w - 1 && l_reg.y2 == data->base.surface->config.size.h - 1 &&\n               r_reg.x1 == 0                                     && r_reg.y1 == 0                                     &&\n               r_reg.x2 == data->base.surface->config.size.w - 1 && r_reg.y2 == data->base.surface->config.size.h - 1))\n               if (!(flags & DSFLIP_UPDATE))\n                    ++data->base.local_flip_count;\n     }\n\n     ret = CoreSurface_Flip2( data->base.surface, DFB_FALSE, &l_reg, &r_reg, flags, data->base.current_frame_time );\n     if (ret) {\n          ret = CoreLayerRegion_FlipUpdate2( data->region, &l_reg, &r_reg, data->region->surface->flips, flags,\n                                             data->base.current_frame_time );\n          if (ret)\n               return ret;\n     }\n\n     IDirectFBSurface_WaitForBackBuffer( &data->base );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_Layer_GetSubSurface( IDirectFBSurface    *thiz,\n                                      const DFBRectangle  *rect,\n                                      IDirectFBSurface   **ret_interface )\n{\n     DFBResult ret;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface_Layer )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->base.surface)\n          return DFB_DESTROYED;\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     direct_mutex_lock( &data->base.children_lock );\n\n     if (data->base.children_free) {\n          IDirectFBSurface_data *child_data;\n\n          child_data = (IDirectFBSurface_data*) data->base.children_free;\n\n          direct_list_remove( &data->base.children_free, &child_data->link );\n          direct_list_append( &data->base.children_data, &child_data->link );\n\n          direct_mutex_unlock( &data->base.children_lock );\n\n          *ret_interface = child_data->thiz;\n\n          ret = (*ret_interface)->MakeSubSurface( *ret_interface, thiz, rect );\n          if (ret) {\n               direct_mutex_unlock( &data->base.children_lock );\n               return ret;\n          }\n\n          return DFB_OK;\n     }\n\n     direct_mutex_unlock( &data->base.children_lock );\n\n     DIRECT_ALLOCATE_INTERFACE( *ret_interface, IDirectFBSurface );\n\n     if (rect || data->base.limit_set) {\n          DFBRectangle wanted, granted;\n\n          /* Compute wanted rectangle. */\n          if (rect) {\n               wanted = *rect;\n\n               wanted.x += data->base.area.wanted.x;\n               wanted.y += data->base.area.wanted.y;\n\n               if (wanted.w <= 0 || wanted.h <= 0) {\n                    wanted.w = 0;\n                    wanted.h = 0;\n               }\n          }\n          else {\n               wanted = data->base.area.wanted;\n          }\n\n          /* Compute granted rectangle. */\n          granted = wanted;\n\n          dfb_rectangle_intersect( &granted, &data->base.area.granted );\n\n          ret = IDirectFBSurface_Layer_Construct( *ret_interface, thiz, &wanted, &granted, data->region,\n                                                  data->base.caps | DSCAPS_SUBSURFACE, data->base.core,\n                                                  data->base.idirectfb );\n     }\n     else {\n          ret = IDirectFBSurface_Layer_Construct( *ret_interface, thiz, NULL, NULL, data->region,\n                                                  data->base.caps | DSCAPS_SUBSURFACE, data->base.core,\n                                                  data->base.idirectfb );\n     }\n\n     return ret;\n}\n\nDFBResult\nIDirectFBSurface_Layer_Construct( IDirectFBSurface       *thiz,\n                                  IDirectFBSurface       *parent,\n                                  DFBRectangle           *wanted,\n                                  DFBRectangle           *granted,\n                                  CoreLayerRegion        *region,\n                                  DFBSurfaceCapabilities  caps,\n                                  CoreDFB                *core,\n                                  IDirectFB              *dfb )\n{\n     DFBResult    ret;\n     CoreSurface *surface;\n\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBSurface_Layer )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     ret = dfb_layer_region_ref( region );\n     if (ret) {\n          DIRECT_DEALLOCATE_INTERFACE( thiz );\n          return ret;\n     }\n\n     ret = CoreLayerRegion_GetSurface( region, &surface );\n     if (ret) {\n          dfb_layer_region_unref( region );\n          DIRECT_DEALLOCATE_INTERFACE( thiz );\n          return ret;\n     }\n\n     ret = IDirectFBSurface_Construct( thiz, parent, wanted, granted, NULL, surface, surface->config.caps | caps, core,\n                                       dfb );\n     if (ret) {\n          dfb_surface_unref( surface );\n          dfb_layer_region_unref( region );\n          return ret;\n     }\n\n     dfb_surface_unref( surface );\n\n     data->region = region;\n\n     thiz->Release       = IDirectFBSurface_Layer_Release;\n     thiz->Flip          = IDirectFBSurface_Layer_Flip;\n     thiz->FlipStereo    = IDirectFBSurface_Layer_FlipStereo;\n     thiz->GetSubSurface = IDirectFBSurface_Layer_GetSubSurface;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/display/idirectfbsurface_layer.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DISPLAY__IDIRECTFBSURFACE_LAYER_H__\n#define __DISPLAY__IDIRECTFBSURFACE_LAYER_H__\n\n#include <core/coretypes.h>\n\n/*\n * calls base surface constructor, reallocates private data and overloads functions of the interface\n */\nDFBResult IDirectFBSurface_Layer_Construct( IDirectFBSurface       *thiz,\n                                            IDirectFBSurface       *parent,\n                                            DFBRectangle           *req_rect,\n                                            DFBRectangle           *clip_rect,\n                                            CoreLayerRegion        *region,\n                                            DFBSurfaceCapabilities  caps,\n                                            CoreDFB                *core,\n                                            IDirectFB              *idirectfb );\n\n#endif\n"
  },
  {
    "path": "src/display/idirectfbsurface_window.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreWindow.h>\n#include <core/windows.h>\n#include <direct/thread.h>\n#include <display/idirectfbsurface.h>\n#include <display/idirectfbsurface_window.h>\n\nD_DEBUG_DOMAIN( Surface, \"IDirectFBSurfaceW\", \"IDirectFBSurface_Window Interface\" );\n\n/**********************************************************************************************************************/\n\n/*\n * private data struct of IDirectFBSurface_Window\n */\ntypedef struct {\n     IDirectFBSurface_data  base;        /* base surface implementation */\n\n     CoreWindow            *window;      /* the window object */\n\n     DirectThread          *flip_thread; /* thread for non-flipping primary surfaces, to make changes visible */\n} IDirectFBSurface_Window_data;\n\n/**********************************************************************************************************************/\n\nstatic void\nIDirectFBSurface_Window_Destruct( IDirectFBSurface *thiz )\n{\n     IDirectFBSurface_Window_data *data = thiz->priv;\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->flip_thread) {\n          direct_thread_cancel( data->flip_thread );\n          direct_thread_join( data->flip_thread );\n          direct_thread_destroy( data->flip_thread );\n     }\n\n     dfb_window_unref( data->window );\n\n     IDirectFBSurface_Destruct( thiz );\n}\n\nstatic DirectResult\nIDirectFBSurface_Window_Release( IDirectFBSurface *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface_Window )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->base.ref == 0)\n          IDirectFBSurface_Window_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_Window_Flip( IDirectFBSurface    *thiz,\n                              const DFBRegion     *region,\n                              DFBSurfaceFlipFlags  flags )\n{\n     DFBResult ret;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface_Window )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %p, 0x%08x )\\n\", __FUNCTION__, thiz, region, flags );\n\n     ret = IDirectFBSurface_Flip( thiz, region, flags );\n     if (ret)\n          return ret;\n\n     if (!data->window->config.opacity && data->base.caps & DSCAPS_PRIMARY) {\n          CoreWindowConfig config = { .opacity = 0xff };\n\n          return CoreWindow_SetConfig( data->window, &config, NULL, 0, DWCONF_OPACITY );\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_Window_FlipStereo( IDirectFBSurface    *thiz,\n                                    const DFBRegion     *left_region,\n                                    const DFBRegion     *right_region,\n                                    DFBSurfaceFlipFlags  flags )\n{\n     DFBResult ret;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface_Window )\n\n     D_DEBUG_AT( Surface, \"%s( %p, %p, %p, 0x%08x )\\n\", __FUNCTION__, thiz, left_region, right_region, flags );\n\n     ret = IDirectFBSurface_FlipStereo( thiz, left_region, right_region, flags );\n     if (ret)\n          return ret;\n\n     if (!data->window->config.opacity && data->base.caps & DSCAPS_PRIMARY) {\n          CoreWindowConfig config = { .opacity = 0xff };\n\n          return CoreWindow_SetConfig( data->window, &config, NULL, 0, DWCONF_OPACITY );\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurface_Window_GetSubSurface( IDirectFBSurface    *thiz,\n                                       const DFBRectangle  *rect,\n                                       IDirectFBSurface   **ret_interface )\n{\n     DFBResult ret;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurface_Window )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->base.surface || !data->window || !data->window->surface)\n          return DFB_DESTROYED;\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     direct_mutex_lock( &data->base.children_lock );\n\n     if (data->base.children_free) {\n          IDirectFBSurface_data *child_data;\n\n          child_data = (IDirectFBSurface_data*) data->base.children_free;\n\n          direct_list_remove( &data->base.children_free, &child_data->link );\n          direct_list_append( &data->base.children_data, &child_data->link );\n\n          direct_mutex_unlock( &data->base.children_lock );\n\n          *ret_interface = child_data->thiz;\n\n          ret = (*ret_interface)->MakeSubSurface( *ret_interface, thiz, rect );\n          if (ret) {\n               direct_mutex_unlock( &data->base.children_lock );\n               return ret;\n          }\n\n          return DFB_OK;\n     }\n\n     direct_mutex_unlock( &data->base.children_lock );\n\n     DIRECT_ALLOCATE_INTERFACE( *ret_interface, IDirectFBSurface );\n\n     if (rect || data->base.limit_set) {\n          DFBRectangle wanted, granted;\n\n          /* Compute wanted rectangle. */\n          if (rect) {\n               wanted = *rect;\n\n               wanted.x += data->base.area.wanted.x;\n               wanted.y += data->base.area.wanted.y;\n\n               if (wanted.w <= 0 || wanted.h <= 0) {\n                    wanted.w = 0;\n                    wanted.h = 0;\n               }\n          }\n          else {\n               wanted = data->base.area.wanted;\n          }\n\n          /* Compute granted rectangle. */\n          granted = wanted;\n\n          dfb_rectangle_intersect( &granted, &data->base.area.granted );\n\n          ret = IDirectFBSurface_Window_Construct( *ret_interface, thiz, &wanted, &granted, data->window,\n                                                   data->base.caps | DSCAPS_SUBSURFACE, data->base.core,\n                                                   data->base.idirectfb );\n     }\n     else {\n          ret = IDirectFBSurface_Window_Construct( *ret_interface, thiz, NULL, NULL, data->window,\n                                                   data->base.caps | DSCAPS_SUBSURFACE, data->base.core,\n                                                   data->base.idirectfb );\n     }\n\n     return ret;\n}\n\nstatic void *\nIDirectFBSurface_Window_Flipping( DirectThread *thread,\n                                  void         *arg )\n{\n     IDirectFBSurface             *thiz = arg;\n     IDirectFBSurface_Window_data *data;\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     D_ASSERT( thiz != NULL );\n\n     data = thiz->priv;\n\n     D_ASSERT( data != NULL );\n\n     while (data->base.surface && data->window->surface) {\n          direct_thread_testcancel( thread );\n\n          thiz->Flip( thiz, NULL, DSFLIP_NONE );\n\n          direct_thread_sleep( 40000 );\n     }\n\n     return NULL;\n}\n\nDFBResult\nIDirectFBSurface_Window_Construct( IDirectFBSurface       *thiz,\n                                   IDirectFBSurface       *parent,\n                                   DFBRectangle           *wanted,\n                                   DFBRectangle           *granted,\n                                   CoreWindow             *window,\n                                   DFBSurfaceCapabilities  caps,\n                                   CoreDFB                *core,\n                                   IDirectFB              *dfb )\n{\n     DFBResult    ret;\n     DFBInsets    insets;\n     CoreSurface *surface;\n\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBSurface_Window )\n\n     D_DEBUG_AT( Surface, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     D_MAGIC_ASSERT( window, CoreWindow );\n\n     ret = CoreWindow_GetInsets( window, &insets );\n     if (ret) {\n          DIRECT_DEALLOCATE_INTERFACE( thiz );\n          return ret;\n     }\n\n     ret = CoreWindow_GetSurface( window, &surface );\n     if (ret) {\n          DIRECT_DEALLOCATE_INTERFACE( thiz );\n          return ret;\n     }\n\n     ret = IDirectFBSurface_Construct( thiz, parent, wanted, granted, &insets, surface, caps, core, dfb );\n\n     dfb_surface_unref( surface );\n\n     if (ret)\n          return ret;\n\n     ret = dfb_window_ref( window );\n     if (ret) {\n          IDirectFBSurface_Destruct( thiz );\n          return ret;\n     }\n\n     data->window = window;\n\n     /* Create an auto flipping thread if the application requested a (primary) surface that doesn't need to be flipped.\n        Window surfaces even need to be flipped when they are single buffered. */\n     if (!(caps & DSCAPS_FLIPPING) && !(caps & DSCAPS_SUBSURFACE)) {\n          if (dfb_config->autoflip_window)\n               data->flip_thread = direct_thread_create( DTT_DEFAULT, IDirectFBSurface_Window_Flipping, thiz,\n                                                         \"SurfWin Flipping\" );\n          else\n               D_WARN( \"non-flipping window surface and no 'autoflip-window' option used\" );\n     }\n\n     thiz->Release       = IDirectFBSurface_Window_Release;\n     thiz->Flip          = IDirectFBSurface_Window_Flip;\n     thiz->FlipStereo    = IDirectFBSurface_Window_FlipStereo;\n     thiz->GetSubSurface = IDirectFBSurface_Window_GetSubSurface;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/display/idirectfbsurface_window.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DISPLAY__IDIRECTFBSURFACE_WINDOW_H__\n#define __DISPLAY__IDIRECTFBSURFACE_WINDOW_H__\n\n#include <core/coretypes.h>\n\n/*\n * calls base surface constructor, reallocates private data and overloads functions of the interface\n */\nDFBResult IDirectFBSurface_Window_Construct( IDirectFBSurface       *thiz,\n                                             IDirectFBSurface       *parent,\n                                             DFBRectangle           *req_rect,\n                                             DFBRectangle           *clip_rect,\n                                             CoreWindow             *window,\n                                             DFBSurfaceCapabilities  caps,\n                                             CoreDFB                *core,\n                                             IDirectFB              *idirectfb );\n\n#endif\n"
  },
  {
    "path": "src/display/idirectfbsurfaceallocation.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreSurfaceAllocation.h>\n#include <core/surface_allocation.h>\n#include <core/surface_buffer.h>\n#include <core/surface_pool.h>\n#include <display/idirectfbsurfaceallocation.h>\n\nD_DEBUG_DOMAIN( SurfaceAllocation, \"IDirectFBSurfaceAllocation\", \"IDirectFBSurfaceAllocation Interface\" );\n\n/**********************************************************************************************************************/\n\n/*\n * private data struct of IDirectFBSurfaceAllocation\n */\ntypedef struct {\n     int                    ref;              /* reference counter */\n\n     CoreSurfaceAllocation *allocation;       /* the allocation object */\n\n     IDirectFBSurface      *idirectfbsurface; /* the surface interface object */\n\n     CoreSurfaceBufferLock  lock;             /* lock for the allocation */\n} IDirectFBSurfaceAllocation_data;\n\n/**********************************************************************************************************************/\n\nstatic void\nIDirectFBSurfaceAllocation_Destruct( IDirectFBSurfaceAllocation *thiz )\n{\n     IDirectFBSurfaceAllocation_data *data = thiz->priv;\n\n     D_DEBUG_AT( SurfaceAllocation, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->lock.allocation) {\n          dfb_surface_pool_unlock( data->lock.allocation->pool, data->lock.allocation, &data->lock );\n\n          dfb_surface_buffer_lock_reset( &data->lock );\n     }\n\n     if (data->allocation)\n          dfb_surface_allocation_unref( data->allocation );\n\n     dfb_surface_buffer_lock_deinit( &data->lock );\n\n     DIRECT_DEALLOCATE_INTERFACE( thiz );\n}\n\nstatic DirectResult\nIDirectFBSurfaceAllocation_AddRef( IDirectFBSurfaceAllocation *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurfaceAllocation )\n\n     D_DEBUG_AT( SurfaceAllocation, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref++;\n\n     return DFB_OK;\n}\n\nstatic DirectResult\nIDirectFBSurfaceAllocation_Release( IDirectFBSurfaceAllocation *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurfaceAllocation )\n\n     D_DEBUG_AT( SurfaceAllocation, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->ref == 0)\n          IDirectFBSurfaceAllocation_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurfaceAllocation_GetDescription( IDirectFBSurfaceAllocation *thiz,\n                                           DFBSurfaceDescription      *ret_desc )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurfaceAllocation )\n\n     D_DEBUG_AT( SurfaceAllocation, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->allocation)\n          return DFB_DESTROYED;\n\n     if (!ret_desc)\n          return DFB_INVARG;\n\n     ret_desc->flags = DSDESC_HINTS;\n     ret_desc->hints = DSHF_NONE;\n\n     if (data->allocation->type & CSTF_LAYER)\n          ret_desc->hints |= DSHF_LAYER;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurfaceAllocation_GetHandle( IDirectFBSurfaceAllocation *thiz,\n                                      u64                        *ret_handle )\n{\n     DFBResult ret;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurfaceAllocation )\n\n     D_DEBUG_AT( SurfaceAllocation, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->allocation)\n          return DFB_DESTROYED;\n\n     if (!ret_handle)\n          return DFB_INVARG;\n\n     /* Lock the allocation. */\n     if (!data->lock.allocation) {\n          ret = dfb_surface_pool_lock( data->allocation->pool, data->allocation, &data->lock );\n          if (ret) {\n               D_DERROR( ret, \"IDirectFBSurfaceAllocation: Locking allocation failed!\\n\" );\n               return ret;\n          }\n     }\n\n     *ret_handle = (u64)(long) data->lock.handle;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurfaceAllocation_GetPitch( IDirectFBSurfaceAllocation *thiz,\n                                     int                        *ret_pitch )\n{\n     DFBResult ret;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurfaceAllocation )\n\n     D_DEBUG_AT( SurfaceAllocation, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->allocation)\n          return DFB_DESTROYED;\n\n     if (!ret_pitch)\n          return DFB_INVARG;\n\n     /* Lock the allocation. */\n     if (!data->lock.allocation) {\n          ret = dfb_surface_pool_lock( data->allocation->pool, data->allocation, &data->lock );\n          if (ret) {\n               D_DERROR( ret, \"IDirectFBSurfaceAllocation: Locking allocation failed!\\n\" );\n               return ret;\n          }\n     }\n\n     *ret_pitch = data->lock.pitch;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBSurfaceAllocation_Updated( IDirectFBSurfaceAllocation *thiz,\n                                    const DFBBox               *updates,\n                                    unsigned int                num_updates )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBSurfaceAllocation )\n\n     D_DEBUG_AT( SurfaceAllocation, \"%s( %p, updates %p, num %u )\\n\", __FUNCTION__, thiz, updates, num_updates );\n\n     if (!data->allocation)\n          return DFB_DESTROYED;\n\n     if (!updates && num_updates > 0)\n          return DFB_INVARG;\n\n     return CoreSurfaceAllocation_Updated( data->allocation, updates, num_updates );\n}\n\nDFBResult\nIDirectFBSurfaceAllocation_Construct( IDirectFBSurfaceAllocation *thiz,\n                                      CoreSurfaceAllocation      *allocation,\n                                      IDirectFBSurface           *idirectfbsurface )\n{\n     DFBResult ret;\n\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBSurfaceAllocation )\n\n     D_DEBUG_AT( SurfaceAllocation, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     ret = dfb_surface_allocation_ref( allocation );\n     if (ret) {\n          DIRECT_DEALLOCATE_INTERFACE( thiz );\n          return ret;\n     }\n\n     data->ref              = 1;\n     data->allocation       = allocation;\n     data->idirectfbsurface = idirectfbsurface;\n\n     dfb_surface_buffer_lock_init( &data->lock, CSAID_CPU, CSAF_READ | CSAF_WRITE );\n\n     thiz->AddRef         = IDirectFBSurfaceAllocation_AddRef;\n     thiz->Release        = IDirectFBSurfaceAllocation_Release;\n     thiz->GetDescription = IDirectFBSurfaceAllocation_GetDescription;\n     thiz->GetHandle      = IDirectFBSurfaceAllocation_GetHandle;\n     thiz->GetPitch       = IDirectFBSurfaceAllocation_GetPitch;\n     thiz->Updated        = IDirectFBSurfaceAllocation_Updated;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/display/idirectfbsurfaceallocation.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DISPLAY__IDIRECTFBSURFACEALLOCATION_H__\n#define __DISPLAY__IDIRECTFBSURFACEALLOCATION_H__\n\n#include <core/coretypes.h>\n\n/*\n * initializes interface struct and private data\n */\nDFBResult IDirectFBSurfaceAllocation_Construct( IDirectFBSurfaceAllocation *thiz,\n                                                CoreSurfaceAllocation      *allocation,\n                                                IDirectFBSurface           *idirectfbsurface );\n\n#endif\n"
  },
  {
    "path": "src/gfx/clip.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/util.h>\n#include <directfb_util.h>\n#include <gfx/clip.h>\n\nD_DEBUG_DOMAIN( GFX_Clipping, \"GFX/Clipping\", \"DirectFB Graphics Clipping\" );\n\n/**********************************************************************************************************************/\n\n#define REGION_CODE(x,y,cx1,cx2,cy1,cy2) ( ((y) > (cy2) ? 8 : 0) | \\\n                                           ((y) < (cy1) ? 4 : 0) | \\\n                                           ((x) > (cx2) ? 2 : 0) | \\\n                                           ((x) < (cx1) ? 1 : 0) )\n\nDFBBoolean\ndfb_clip_line( const DFBRegion *clip,\n               DFBRegion       *line )\n{\n     unsigned char region_code1 = REGION_CODE( line->x1, line->y1, clip->x1, clip->x2, clip->y1, clip->y2 );\n     unsigned char region_code2 = REGION_CODE( line->x2, line->y2, clip->x1, clip->x2, clip->y1, clip->y2 );\n\n     D_DEBUG_AT( GFX_Clipping, \"%s()\\n\", __FUNCTION__ );\n\n     D_DEBUG_AT( GFX_Clipping, \"  <- %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS_FROM_REGION( clip ) );\n\n     while (region_code1 | region_code2) {\n          /* Line completely outside the clipping rectangle. */\n          if (region_code1 & region_code2)\n               return DFB_FALSE;\n\n          if (region_code1) {\n               if (region_code1 & 8) { /* divide line at bottom */\n                    line->x1 = line->x1 +(line->x2-line->x1) * (clip->y2 - line->y1) / (line->y2-line->y1);\n                    line->y1 = clip->y2;\n               }\n               else\n                    if (region_code1 & 4) { /* divide line at top */\n                    line->x1 = line->x1 +(line->x2-line->x1) * (clip->y1 - line->y1) / (line->y2-line->y1);\n                    line->y1 = clip->y1;\n               }\n               else\n                    if (region_code1 & 2) { /* divide line at right */\n                    line->y1 = line->y1 +(line->y2-line->y1) * (clip->x2 - line->x1) / (line->x2-line->x1);\n                    line->x1 = clip->x2;\n               }\n               else\n                    if (region_code1 & 1) { /* divide line at right */\n                    line->y1 = line->y1 +(line->y2-line->y1) * (clip->x1 - line->x1) / (line->x2-line->x1);\n                    line->x1 = clip->x1;\n               }\n\n               region_code1 = REGION_CODE( line->x1, line->y1, clip->x1, clip->x2, clip->y1, clip->y2 );\n          }\n          else {\n               if (region_code2 & 8) { /* divide line at bottom */\n                    line->x2 = line->x1 +(line->x2-line->x1) * (clip->y2 - line->y1) / (line->y2-line->y1);\n                    line->y2 = clip->y2;\n               }\n               else\n                    if (region_code2 & 4) { /* divide line at top */\n                    line->x2 = line->x1 +(line->x2-line->x1) * (clip->y1 - line->y1) / (line->y2-line->y1);\n                    line->y2 = clip->y1;\n               }\n               else\n                    if (region_code2 & 2) { /* divide line at right */\n                    line->y2 = line->y1 +(line->y2-line->y1) * (clip->x2 - line->x1) / (line->x2-line->x1);\n                    line->x2 = clip->x2;\n               }\n               else\n                    if (region_code2 & 1) { /* divide line at right */\n                    line->y2 = line->y1 +(line->y2-line->y1) * (clip->x1 - line->x1) / (line->x2-line->x1);\n                    line->x2 = clip->x1;\n               }\n\n               region_code2 = REGION_CODE( line->x2, line->y2, clip->x1, clip->x2, clip->y1, clip->y2 );\n          }\n     }\n\n     D_DEBUG_AT( GFX_Clipping, \"  -> %4d,%4d-%4d,%4d\\n\", DFB_LINE_VALS( line ) );\n\n     /* Successfully clipped or clipping not neccessary. */\n     return DFB_TRUE;\n}\n\nDFBBoolean\ndfb_clip_rectangle( const DFBRegion *clip,\n                    DFBRectangle    *rect )\n{\n     D_DEBUG_AT( GFX_Clipping, \"%s()\\n\", __FUNCTION__ );\n\n     D_DEBUG_AT( GFX_Clipping, \"  <- %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS_FROM_REGION( clip ) );\n\n     if ((clip->x1 >= rect->x + rect->w) || (clip->x2 < rect->x) ||\n         (clip->y1 >= rect->y + rect->h) || (clip->y2 < rect->y))\n          return DFB_FALSE;\n\n     if (clip->x1 > rect->x) {\n          rect->w += rect->x - clip->x1;\n          rect->x  = clip->x1;\n     }\n\n     if (clip->y1 > rect->y) {\n          rect->h += rect->y - clip->y1;\n          rect->y  = clip->y1;\n     }\n\n     if (clip->x2 < rect->x + rect->w - 1)\n          rect->w = clip->x2 - rect->x + 1;\n\n     if (clip->y2 < rect->y + rect->h - 1)\n          rect->h = clip->y2 - rect->y + 1;\n\n     D_DEBUG_AT( GFX_Clipping, \"  -> %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS( rect ) );\n\n     return DFB_TRUE;\n}\n\nDFBBoolean\ndfb_clip_triangle( const DFBRegion   *clip,\n                   const DFBTriangle *tri,\n                   DFBPoint           p[6],\n                   int               *num )\n{\n     DFBRegion edges[3];\n     int       num_edges;\n     int       i, n;\n     DFBPoint  p1 = { 0, 0 }, p2 = { 0, 0 };\n\n     D_DEBUG_AT( GFX_Clipping, \"%s()\\n\", __FUNCTION__ );\n\n     D_DEBUG_AT( GFX_Clipping, \"  <- %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS_FROM_REGION( clip ) );\n\n     /* Initialize edges. */\n     edges[0].x1 = tri->x1; edges[0].y1 = tri->y1;\n     edges[0].x2 = tri->x2; edges[0].y2 = tri->y2;\n     edges[1].x1 = tri->x2; edges[1].y1 = tri->y2;\n     edges[1].x2 = tri->x3; edges[1].y2 = tri->y3;\n     edges[2].x1 = tri->x3; edges[2].y1 = tri->y3;\n     edges[2].x2 = tri->x1; edges[2].y2 = tri->y1;\n     num_edges = 3;\n\n     for (i = 0; i < num_edges; i++) {\n          DFBRegion *reg = &edges[i];\n          DFBRegion  line;\n          bool       i1, i2;\n\n          /* Clip the edge to the clipping region. */\n          line = *reg;\n          if (dfb_clip_line( clip, &line )) {\n               *reg = line;\n               continue;\n          }\n\n          /* If the edge doesn't intersect clipping region, then intersect the edge with the diagonals of the clipping\n           * rectangle.\n           * If intersection point exits, add the nearest corner of the clipping region to the list of vertices. */\n\n          /* Diagonal (x1,y1) (x2,y2). */\n          line = (DFBRegion) { clip->x1, clip->y1, clip->x2, clip->y2 };\n          i1 = dfb_line_segment_intersect( &line, reg, &p1.x, &p1.y );\n          if (i1) {\n               /* Get nearest corner. */\n               if (p1.x <= clip->x1 || p1.y <= clip->y1) {\n                    p1.x = clip->x1;\n                    p1.y = clip->y1;\n               }\n               else {\n                    p1.x = clip->x2;\n                    p1.y = clip->y2;\n               }\n          }\n\n          /* Diagonal (x2,y1) (x1,y2). */\n          line = (DFBRegion) { clip->x2, clip->y1, clip->x1, clip->y2 };\n          i2 = dfb_line_segment_intersect( &line, reg, &p2.x, &p2.y );\n          if (i2) {\n               /* Get nearest corner. */\n               if (p2.x >= clip->x2 || p2.y <= clip->y1) {\n                    p2.x = clip->x2;\n                    p2.y = clip->y1;\n               }\n               else {\n                    p2.x = clip->x1;\n                    p2.y = clip->y2;\n               }\n          }\n\n          if (i1 && i2) {\n               reg->x1 = p1.x;\n               reg->y1 = p1.y;\n               reg->x2 = p2.x;\n               reg->y2 = p2.y;\n          }\n          else if (i1) {\n               reg->x1 = reg->x2 = p1.x;\n               reg->y1 = reg->y2 = p1.y;\n          }\n          else if (i2) {\n               reg->x1 = reg->x2 = p2.x;\n               reg->y1 = reg->y2 = p2.y;\n          }\n          else {\n               /* Redudant edge. */\n               memmove( reg, &edges[i+1], (num_edges - i - 1) * sizeof(DFBRegion) );\n               num_edges--;\n               i--;\n          }\n     }\n\n     if (num_edges < 1) {\n          *num = 0;\n          return DFB_FALSE;\n     }\n\n     /* Get vertices from edges. */\n     p[0].x = edges[0].x1; p[0].y = edges[0].y1;\n     n = 1;\n     if (edges[0].x2 != edges[0].x1 || edges[0].y2 != edges[0].y1) {\n          p[1].x = edges[0].x2; p[1].y = edges[0].y2;\n          n++;\n     }\n\n     for (i = 1; i < num_edges; i++) {\n          if (edges[i].x1 != p[n-1].x || edges[i].y1 != p[n-1].y) {\n               p[n].x = edges[i].x1; p[n].y = edges[i].y1;\n               n++;\n          }\n          if (edges[i].x2 != p[n-1].x || edges[i].y2 != p[n-1].y) {\n               p[n].x = edges[i].x2; p[n].y = edges[i].y2;\n               n++;\n          }\n     }\n\n     if (p[n-1].x == p[0].x && p[n-1].y == p[0].y)\n          n--;\n\n     *num = n;\n\n     D_DEBUG_AT( GFX_Clipping, \"  -> %4d,%4d-%4d,%4d-%4d,%4d\\n\", DFB_TRIANGLE_VALS( tri ) );\n\n     /* Actually fail if the number of vertices is below 3. */\n     return (n >= 3);\n}\n\nDFBEdgeFlags\ndfb_clip_edges( const DFBRegion *clip,\n                DFBRectangle    *rect )\n{\n     DFBEdgeFlags flags = DFEF_ALL;\n\n     if ((clip->x1 >= rect->x + rect->w) || (clip->x2 < rect->x) ||\n         (clip->y1 >= rect->y + rect->h) || (clip->y2 < rect->y))\n          return DFEF_NONE;\n\n     if (clip->x1 > rect->x) {\n          rect->w += rect->x - clip->x1;\n          rect->x  = clip->x1;\n\n          flags &= ~DFEF_LEFT;\n     }\n\n     if (clip->y1 > rect->y) {\n          rect->h += rect->y - clip->y1;\n          rect->y  = clip->y1;\n\n          flags &= ~DFEF_TOP;\n     }\n\n     if (clip->x2 < rect->x + rect->w - 1) {\n          rect->w = clip->x2 - rect->x + 1;\n\n          flags &= ~DFEF_RIGHT;\n     }\n\n     if (clip->y2 < rect->y + rect->h - 1) {\n          rect->h = clip->y2 - rect->y + 1;\n\n          flags &= ~DFEF_BOTTOM;\n     }\n\n     return flags;\n}\n\nvoid\ndfb_build_clipped_rectangle_outlines( DFBRectangle    *rect,\n                                      const DFBRegion *clip,\n                                      DFBRectangle    *ret_outlines,\n                                      int             *ret_num )\n{\n     DFBEdgeFlags edges = dfb_clip_edges( clip, rect );\n     int          t     = (edges & DFEF_TOP ? 1 : 0);\n     int          tb    = t + (edges & DFEF_BOTTOM ? 1 : 0);\n     int          num   = 0;\n\n     D_DEBUG_AT( GFX_Clipping, \"%s()\\n\", __FUNCTION__ );\n\n     DFB_RECTANGLE_ASSERT( rect );\n\n     D_ASSERT( ret_outlines != NULL );\n     D_ASSERT( ret_num != NULL );\n\n     if (edges & DFEF_TOP) {\n          DFBRectangle *out = &ret_outlines[num++];\n\n          out->x = rect->x;\n          out->y = rect->y;\n          out->w = rect->w;\n          out->h = 1;\n     }\n\n     if (rect->h > t) {\n          if (edges & DFEF_BOTTOM) {\n               DFBRectangle *out = &ret_outlines[num++];\n\n               out->x = rect->x;\n               out->y = rect->y + rect->h - 1;\n               out->w = rect->w;\n               out->h = 1;\n          }\n\n          if (rect->h > tb) {\n               if (edges & DFEF_LEFT) {\n                    DFBRectangle *out = &ret_outlines[num++];\n\n                    out->x = rect->x;\n                    out->y = rect->y + t;\n                    out->w = 1;\n                    out->h = rect->h - tb;\n               }\n\n               if (rect->w > 1 || !(edges & DFEF_LEFT)) {\n                    if (edges & DFEF_RIGHT) {\n                         DFBRectangle *out = &ret_outlines[num++];\n\n                         out->x = rect->x + rect->w - 1;\n                         out->y = rect->y + t;\n                         out->w = 1;\n                         out->h = rect->h - tb;\n                    }\n               }\n          }\n     }\n\n     *ret_num = num;\n}\n\nvoid\ndfb_clip_blit( const DFBRegion *clip,\n               DFBRectangle    *srect,\n               int             *dx,\n               int             *dy )\n{\n     D_DEBUG_AT( GFX_Clipping, \"%s()\\n\", __FUNCTION__ );\n\n     D_DEBUG_AT( GFX_Clipping, \"  <- %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS_FROM_REGION( clip ) );\n\n     if (clip->x1 > *dx) {\n          srect->w  = MIN( (clip->x2 - clip->x1) + 1, (*dx + srect->w) - clip->x1 );\n          srect->x += clip->x1 - *dx;\n          *dx = clip->x1;\n     }\n     else if (clip->x2 < *dx + srect->w - 1) {\n          srect->w = clip->x2 - *dx + 1;\n     }\n\n     if (clip->y1 > *dy) {\n          srect->h  = MIN( (clip->y2 - clip->y1) + 1, (*dy + srect->h) - clip->y1 );\n          srect->y += clip->y1 - *dy;\n          *dy = clip->y1;\n     }\n     else if (clip->y2 < *dy + srect->h - 1) {\n          srect->h = clip->y2 - *dy + 1;\n     }\n\n     D_DEBUG_AT( GFX_Clipping, \"  -> %4d,%4d-%4dx%4d\\n -> %4d,%4d\", DFB_RECTANGLE_VALS( srect ), *dx, *dy );\n}\n\nvoid\ndfb_clip_stretchblit( const DFBRegion *clip,\n                      DFBRectangle    *srect,\n                      DFBRectangle    *drect )\n{\n     DFBRectangle orig_dst = *drect;\n\n     D_DEBUG_AT( GFX_Clipping, \"%s()\\n\", __FUNCTION__ );\n\n     D_DEBUG_AT( GFX_Clipping, \"  <- %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS_FROM_REGION( clip ) );\n\n     dfb_clip_rectangle( clip, drect );\n\n     if (drect->x != orig_dst.x)\n          srect->x += (drect->x - orig_dst.x) * (srect->w / (float) orig_dst.w);\n\n     if (drect->y != orig_dst.y)\n          srect->y += (drect->y - orig_dst.y) * (srect->h / (float) orig_dst.h);\n\n     if (drect->w != orig_dst.w)\n          srect->w = srect->w * (drect->w / (float) orig_dst.w);\n\n     if (drect->h != orig_dst.h)\n          srect->h = srect->h * (drect->h / (float) orig_dst.h);\n\n     D_DEBUG_AT( GFX_Clipping, \"  -> %4d,%4d-%4dx%4d -> %4d,%4d-%4dx%4d\\n\",\n                 DFB_RECTANGLE_VALS( srect ), DFB_RECTANGLE_VALS( drect ) );\n}\n\nvoid\ndfb_clip_blit_flipped_rotated( const DFBRegion         *clip,\n                               DFBRectangle            *srect,\n                               DFBRectangle            *drect,\n                               DFBSurfaceBlittingFlags  flags )\n{\n\n     DFBRegion dest    = DFB_REGION_INIT_FROM_RECTANGLE( drect );\n     DFBRegion clipped = dest;\n\n     D_DEBUG_AT( GFX_Clipping, \"%s( 0x%08x )\\n\", __FUNCTION__, flags );\n\n     D_DEBUG_AT( GFX_Clipping, \"  <- %4d,%4d-%4dx%4d\\n\", DFB_RECTANGLE_VALS_FROM_REGION( clip ) );\n\n     D_ASSERT( !(flags & (DSBLIT_ROTATE270 | DSBLIT_ROTATE180)) );\n\n     if (flags & DSBLIT_ROTATE90) {\n          D_ASSERT( srect->w == drect->h );\n          D_ASSERT( srect->h == drect->w );\n     }\n     else {\n          D_ASSERT( srect->w == drect->w );\n          D_ASSERT( srect->h == drect->h );\n     }\n\n     dfb_region_region_intersect( &clipped, clip );\n     dfb_rectangle_from_region( drect, &clipped );\n\n     switch (flags & (DSBLIT_FLIP_HORIZONTAL | DSBLIT_FLIP_VERTICAL | DSBLIT_ROTATE90)) {\n          case DSBLIT_NOFX:\n               srect->x += clipped.x1 - dest.x1;\n               srect->y += clipped.y1 - dest.y1;\n               break;\n          case DSBLIT_FLIP_HORIZONTAL:\n               srect->x += dest.x2 - clipped.x2;\n               srect->y += clipped.y1 - dest.y1;\n               break;\n          case DSBLIT_FLIP_VERTICAL:\n               srect->x += clipped.x1 - dest.x1;\n               srect->y += dest.y2 - clipped.y2;\n               break;\n          case DSBLIT_ROTATE90:\n               srect->x += dest.y2 - clipped.y2;\n               srect->y += clipped.x1 - dest.x1;\n               break;\n          case (DSBLIT_FLIP_HORIZONTAL | DSBLIT_FLIP_VERTICAL): /* ROTATE180 */\n               srect->x += dest.x2 - clipped.x2;\n               srect->y += dest.y2 - clipped.y2;\n               break;\n          case (DSBLIT_ROTATE90 | DSBLIT_FLIP_VERTICAL | DSBLIT_FLIP_HORIZONTAL): /* ROTATE270 */\n               srect->x += clipped.y1 - dest.y1;\n               srect->y += dest.x2 - clipped.x2;\n               break;\n          case (DSBLIT_ROTATE90 | DSBLIT_FLIP_HORIZONTAL):\n               srect->x += clipped.y1 - dest.y1;\n               srect->y += clipped.x1 - dest.x1;\n               break;\n          case (DSBLIT_ROTATE90 | DSBLIT_FLIP_VERTICAL):\n               srect->x += dest.y2 - clipped.y2;\n               srect->y += dest.x2 - clipped.x2;\n               break;\n     }\n\n     if (flags & DSBLIT_ROTATE90) {\n          srect->w  = drect->h;\n          srect->h  = drect->w;\n     }\n     else {\n          srect->w = drect->w;\n          srect->h = drect->h;\n     }\n\n     D_DEBUG_AT( GFX_Clipping, \"  -> %4d,%4d-%4dx%4d -> %4d,%4d-%4dx%4d\\n\",\n                 DFB_RECTANGLE_VALS( srect ), DFB_RECTANGLE_VALS( drect ) );\n}\n"
  },
  {
    "path": "src/gfx/clip.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __GFX__CLIP_H__\n#define __GFX__CLIP_H__\n\n#include <core/coretypes.h>\n\n/**********************************************************************************************************************/\n\ntypedef enum {\n     DFEF_NONE   = 0x00000000,\n\n     DFEF_LEFT   = 0x00000001,\n     DFEF_RIGHT  = 0x00000002,\n     DFEF_TOP    = 0x00000004,\n     DFEF_BOTTOM = 0x00000008,\n\n     DFEF_ALL    = 0x0000000F\n} DFBEdgeFlags;\n\n/**********************************************************************************************************************/\n\n/*\n * Clip the line to the clipping region.\n * Return true if at least one pixel of the line resides in the region.\n */\nDFBBoolean   dfb_clip_line                       ( const DFBRegion         *clip,\n                                                   DFBRegion               *line );\n\n/*\n * Clip the rectangle to the clipping region.\n * Return true if there was an intersection with the clipping region.\n */\nDFBBoolean   dfb_clip_rectangle                  ( const DFBRegion         *clip,\n                                                   DFBRectangle            *rect );\n\n/*\n * Clip the triangle to the clipping region.\n * Return true if the triangle if visible within the region.\n * The vertices of the polygon resulting from intersection are returned in 'buf'. The number of vertices is at least 3.\n */\nDFBBoolean   dfb_clip_triangle                   ( const DFBRegion         *clip,\n                                                   const DFBTriangle       *tri,\n                                                   DFBPoint                 buf[6],\n                                                   int                     *num );\n\n/*\n * Clip the rectangle to the clipping region.\n * Return a flag for each edge that wasn't cut off.\n */\nDFBEdgeFlags dfb_clip_edges                      ( const DFBRegion         *clip,\n                                                   DFBRectangle            *rect );\n\n/*\n * Get the outlines of a clipped rectangle.\n */\nvoid         dfb_build_clipped_rectangle_outlines( DFBRectangle            *rect,\n                                                   const DFBRegion         *clip,\n                                                   DFBRectangle            *ret_outlines,\n                                                   int                     *ret_num );\n\n/*\n * Clip the blitting request to the clipping region. This includes adjustment of source and destination coordinates.\n */\nvoid         dfb_clip_blit                       ( const DFBRegion         *clip,\n                                                   DFBRectangle            *srect,\n                                                   int                     *dx,\n                                                   int                     *dy );\n\n/*\n * Clip the stretch blit request to the clipping region.\n * This includes adjustment of source and destination coordinates based on the scaling factor.\n */\nvoid         dfb_clip_stretchblit                ( const DFBRegion         *clip,\n                                                   DFBRectangle            *srect,\n                                                   DFBRectangle            *drect );\n\n/*\n * Clip the blitting request to the clipping region. This includes adjustment of source and destination coordinates.\n * In contrast to dfb_clip_blit() this also honors DSBLIT_ROTATE_ and DSBLIT_FLIP_ blitting flags.\n */\nvoid         dfb_clip_blit_flipped_rotated       ( const DFBRegion         *clip,\n                                                   DFBRectangle            *srect,\n                                                   DFBRectangle            *drect,\n                                                   DFBSurfaceBlittingFlags  flags );\n\n/**********************************************************************************************************************/\n\n/*\n * Check if a clip ot the rectangle is needed.\n */\nstatic __inline__ DFBBoolean\ndfb_clip_needed( const DFBRegion *clip,\n                 DFBRectangle    *rect )\n{\n     return ((clip->x1 > rect->x)               || (clip->y1 > rect->y) ||\n             (clip->x2 < rect->x + rect->w - 1) || (clip->y2 < rect->y + rect->h - 1)) ? DFB_TRUE : DFB_FALSE;\n}\n\n/*\n * Check if requested blitting lies outside of the clipping region.\n * Return true if blitting may need to be performed.\n */\nstatic __inline__ DFBBoolean\ndfb_clip_blit_precheck( const DFBRegion *clip,\n                        int              w,\n                        int              h,\n                        int              dx,\n                        int              dy )\n{\n     if (w < 1 || h < 1 || (clip->x1 >= dx + w) || (clip->x2 < dx) || (clip->y1 >= dy + h) || (clip->y2 < dy))\n          return DFB_FALSE;\n\n     return DFB_TRUE;\n}\n\n#endif\n"
  },
  {
    "path": "src/gfx/convert.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <config.h>\n#include <direct/memcpy.h>\n#include <gfx/convert.h>\n\nD_DEBUG_DOMAIN( GFX_Converter, \"GFX/Converter\", \"DirectFB Graphics Converter\" );\n\n/**********************************************************************************************************************/\n\n/* lookup tables for 2/3bit to 8bit color conversion */\nstatic const u8 lookup3to8[] = { 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff };\nstatic const u8 lookup2to8[] = { 0x00, 0x55, 0xaa, 0xff };\n\n#define EXPAND_1to8(v) ((v) ? 0xff : 0x00)\n#define EXPAND_2to8(v) lookup2to8[v]\n#define EXPAND_3to8(v) lookup3to8[v]\n#define EXPAND_4to8(v) (((v) << 4) |  (v)      )\n#define EXPAND_5to8(v) (((v) << 3) | ((v) >> 2))\n#define EXPAND_6to8(v) (((v) << 2) | ((v) >> 4))\n#define EXPAND_7to8(v) (((v) << 1) | ((v) >> 6))\n\n#define YCBCR_TO_RGB(y,cb,cr,r,g,b)           \\\n     if (colorspace == DSCS_BT601)            \\\n          YCBCR_TO_RGB_BT601(y,cb,cr,r,g,b);  \\\n     else if (colorspace == DSCS_BT709)       \\\n          YCBCR_TO_RGB_BT709(y,cb,cr,r,g,b);  \\\n     else if (colorspace == DSCS_BT2020)      \\\n          YCBCR_TO_RGB_BT2020(y,cb,cr,r,g,b); \\\n     else {                                   \\\n          r = g = b = 0;                      \\\n     }\n\n#define RGB_TO_YCBCR(r,g,b,y,cb,cr)           \\\n     if (colorspace == DSCS_BT601)            \\\n          RGB_TO_YCBCR_BT601(r,g,b,y,cb,cr);  \\\n     else if (colorspace == DSCS_BT709)       \\\n          RGB_TO_YCBCR_BT709(r,g,b,y,cb,cr);  \\\n     else if (colorspace == DSCS_BT2020)      \\\n          RGB_TO_YCBCR_BT2020(r,g,b,y,cb,cr); \\\n     else {                                   \\\n          y = 16;                             \\\n          cb = cr = 128;                      \\\n     }\n\n/**********************************************************************************************************************/\n\nvoid\ndfb_pixel_to_color( DFBSurfacePixelFormat  format,\n                    DFBSurfaceColorSpace   colorspace,\n                    unsigned long          pixel,\n                    DFBColor              *ret_color )\n{\n     D_DEBUG_AT( GFX_Converter, \"%s()\\n\", __FUNCTION__ );\n\n     if (!DFB_COLORSPACE_IS_COMPATIBLE( colorspace, format )) {\n          D_ONCE( \"incompatible colorspace\" );\n          return;\n     }\n\n     ret_color->a = 0xff;\n\n     switch (format) {\n          case DSPF_RGB332:\n               ret_color->r = EXPAND_3to8( (pixel & 0xe0) >> 5 );\n               ret_color->g = EXPAND_3to8( (pixel & 0x1c) >> 2 );\n               ret_color->b = EXPAND_2to8(  pixel & 0x03       );\n               break;\n\n          case DSPF_ARGB1555:\n               ret_color->a = EXPAND_1to8(  pixel >> 15           );\n          case DSPF_RGB555:\n               ret_color->r = EXPAND_5to8( (pixel & 0x7c00) >> 10 );\n               ret_color->g = EXPAND_5to8( (pixel & 0x03e0) >>  5 );\n               ret_color->b = EXPAND_5to8(  pixel & 0x001f        );\n               break;\n\n          case DSPF_BGR555:\n               ret_color->r = EXPAND_5to8(  pixel & 0x001f        );\n               ret_color->g = EXPAND_5to8( (pixel & 0x03e0) >>  5 );\n               ret_color->b = EXPAND_5to8( (pixel & 0x7c00) >> 10 );\n               break;\n\n          case DSPF_ARGB2554:\n               ret_color->a = EXPAND_2to8(  pixel >> 14          );\n               ret_color->r = EXPAND_5to8( (pixel & 0x3e00) >> 9 );\n               ret_color->g = EXPAND_5to8( (pixel & 0x01f0) >> 4 );\n               ret_color->b = EXPAND_4to8(  pixel & 0x000f       );\n               break;\n\n          case DSPF_ARGB4444:\n               ret_color->a = EXPAND_4to8(  pixel >> 12          );\n          case DSPF_RGB444:\n               ret_color->r = EXPAND_4to8( (pixel & 0x0f00) >> 8 );\n               ret_color->g = EXPAND_4to8( (pixel & 0x00f0) >> 4 );\n               ret_color->b = EXPAND_4to8(  pixel & 0x000f       );\n               break;\n\n          case DSPF_RGBA4444:\n               ret_color->r = EXPAND_4to8(  pixel           >> 12 );\n               ret_color->g = EXPAND_4to8( (pixel & 0x0f00) >>  8 );\n               ret_color->b = EXPAND_4to8( (pixel & 0x00f0) >>  4 );\n               ret_color->a = EXPAND_4to8(  pixel & 0x000f        );\n               break;\n\n          case DSPF_ARGB8565:\n               ret_color->a =               pixel >> 16;\n          case DSPF_RGB16:\n               ret_color->r = EXPAND_5to8( (pixel & 0xf800) >> 11 );\n               ret_color->g = EXPAND_6to8( (pixel & 0x07e0) >>  5 );\n               ret_color->b = EXPAND_5to8(  pixel & 0x001f        );\n               break;\n\n          case DSPF_ARGB1666:\n          case DSPF_ARGB6666:\n               ret_color->a = (format = DSPF_ARGB1666) ?\n                              EXPAND_1to8( (pixel & 0x040000) >> 18 ) :\n                              EXPAND_6to8( (pixel & 0xfc0000) >> 18 );\n          case DSPF_RGB18:\n               ret_color->r = EXPAND_6to8( (pixel & 0x03f000) >> 12 );\n               ret_color->g = EXPAND_6to8( (pixel & 0x000fc0) >>  6 );\n               ret_color->b = EXPAND_6to8(  pixel & 0x00003f        );\n               break;\n\n          case DSPF_ARGB:\n               ret_color->a =  pixel >> 24;\n          case DSPF_RGB24:\n          case DSPF_RGB32:\n               ret_color->r = (pixel & 0xff0000) >> 16;\n               ret_color->g = (pixel & 0x00ff00) >>  8;\n               ret_color->b =  pixel & 0x0000ff;\n               break;\n\n          case DSPF_ABGR:\n               ret_color->a =  pixel >> 24;\n          case DSPF_BGR24:\n               ret_color->b = (pixel & 0xff0000) >> 16;\n               ret_color->g = (pixel & 0x00ff00) >>  8;\n               ret_color->r =  pixel & 0x0000ff;\n               break;\n\n          case DSPF_AiRGB:\n               ret_color->a = (pixel >> 24) ^ 0xff;\n               ret_color->r = (pixel & 0xff0000) >> 16;\n               ret_color->g = (pixel & 0x00ff00) >>  8;\n               ret_color->b =  pixel & 0x0000ff;\n               break;\n\n          case DSPF_RGBA5551:\n               ret_color->a = EXPAND_1to8(  pixel & 1             );\n               ret_color->r = EXPAND_5to8( (pixel & 0xf800) >> 11 );\n               ret_color->g = EXPAND_5to8( (pixel & 0x07c0) >>  6 );\n               ret_color->b = EXPAND_5to8( (pixel & 0x003e) >>  1 );\n               break;\n\n          case DSPF_RGBAF88871:\n               ret_color->a = EXPAND_7to8( (pixel & 0x000000fe) >>  1 );\n               ret_color->r =              (pixel & 0xff000000) >> 24;\n               ret_color->g =              (pixel & 0x00ff0000) >> 16;\n               ret_color->b =              (pixel & 0x0000ff00) >>  8;\n               break;\n\n          case DSPF_AYUV:\n               ret_color->a = pixel >> 24;\n               YCBCR_TO_RGB( (pixel & 0xff0000) >> 16, (pixel & 0x00ff00) >> 8, pixel & 0x0000ff,\n                             ret_color->r, ret_color->g, ret_color->b );\n               break;\n\n          case DSPF_AVYU:\n               ret_color->a = pixel >> 24;\n          case DSPF_VYU:\n               YCBCR_TO_RGB( (pixel & 0x00ff00) >> 8, pixel & 0x0000ff, (pixel & 0xff0000) >> 16,\n                             ret_color->r, ret_color->g, ret_color->b );\n               break;\n\n          case DSPF_YUY2:\n#ifdef WORDS_BIGENDIAN\n               YCBCR_TO_RGB( (pixel & 0x00ff0000) >> 16, (pixel & 0xff000000) >> 24, (pixel & 0x0000ff00) >> 8,\n                             ret_color->r, ret_color->g, ret_color->b );\n#else\n               YCBCR_TO_RGB( (pixel & 0x00ff0000) >> 16, (pixel & 0x0000ff00) >> 8, (pixel & 0xff000000) >> 24,\n                             ret_color->r, ret_color->g, ret_color->b );\n#endif\n               break;\n\n          case DSPF_UYVY:\n#ifdef WORDS_BIGENDIAN\n               YCBCR_TO_RGB( (pixel & 0xff000000) >> 24, (pixel & 0x00ff0000) >> 16, pixel & 0x000000ff,\n                             ret_color->r, ret_color->g, ret_color->b );\n#else\n               YCBCR_TO_RGB( (pixel & 0xff000000) >> 24, pixel & 0x000000ff, (pixel & 0x00ff0000) >> 16,\n                             ret_color->r, ret_color->g, ret_color->b );\n#endif\n               break;\n\n          case DSPF_I420:\n          case DSPF_Y42B:\n          case DSPF_Y444:\n               YCBCR_TO_RGB( (pixel & 0xff0000) >> 16, (pixel & 0x00ff00) >> 8, pixel & 0x0000ff,\n                             ret_color->r, ret_color->g, ret_color->b );\n               break;\n\n          case DSPF_YV12:\n          case DSPF_YV16:\n          case DSPF_YV24:\n               YCBCR_TO_RGB( (pixel & 0xff0000) >> 16, pixel & 0x0000ff, (pixel & 0x00ff00) >> 8,\n                             ret_color->r, ret_color->g, ret_color->b );\n               break;\n\n          case DSPF_A8:\n               ret_color->a = pixel;\n               /* fall through */\n\n          default:\n               ret_color->r = 0;\n               ret_color->g = 0;\n               ret_color->b = 0;\n     }\n}\n\nunsigned long\ndfb_pixel_from_color( DFBSurfacePixelFormat  format,\n                      DFBSurfaceColorSpace   colorspace,\n                      const DFBColor        *color )\n{\n     u32 y, cb, cr;\n\n     D_DEBUG_AT( GFX_Converter, \"%s()\\n\", __FUNCTION__ );\n\n     if (!DFB_COLORSPACE_IS_COMPATIBLE( colorspace, format )) {\n          D_ONCE( \"incompatible colorspace\" );\n          return 0;\n     }\n\n     switch (format) {\n          case DSPF_RGB332:\n               return PIXEL_RGB332( color->r, color->g, color->b );\n\n          case DSPF_ARGB1555:\n               return PIXEL_ARGB1555( color->a, color->r, color->g, color->b );\n\n          case DSPF_RGB555:\n               return PIXEL_RGB555( color->r, color->g, color->b );\n\n          case DSPF_BGR555:\n               return PIXEL_BGR555( color->r, color->g, color->b );\n\n          case DSPF_ARGB2554:\n               return PIXEL_ARGB2554( color->a, color->r, color->g, color->b );\n\n          case DSPF_ARGB4444:\n               return PIXEL_ARGB4444( color->a, color->r, color->g, color->b );\n\n          case DSPF_RGB444:\n               return PIXEL_RGB444( color->r, color->g, color->b );\n\n          case DSPF_RGBA4444:\n               return PIXEL_RGBA4444( color->a, color->r, color->g, color->b );\n\n          case DSPF_ARGB8565:\n               return PIXEL_ARGB8565( color->a, color->r, color->g, color->b );\n\n          case DSPF_RGB16:\n               return PIXEL_RGB16( color->r, color->g, color->b );\n\n          case DSPF_ARGB1666:\n               return PIXEL_ARGB1666( color->a, color->r, color->g, color->b );\n\n          case DSPF_ARGB6666:\n               return PIXEL_ARGB6666( color->a, color->r, color->g, color->b );\n\n          case DSPF_RGB18:\n               return PIXEL_RGB18( color->r, color->g, color->b );\n\n          case DSPF_ARGB:\n               return PIXEL_ARGB( color->a, color->r, color->g, color->b );\n\n          case DSPF_RGB24:\n               return PIXEL_RGB32( color->r, color->g, color->b ) & 0xffffff;\n\n          case DSPF_BGR24:\n               return PIXEL_RGB32( color->b, color->g, color->r ) & 0xffffff;\n\n          case DSPF_RGB32:\n               return PIXEL_RGB32( color->r, color->g, color->b ) & 0xffffff;\n\n          case DSPF_ABGR:\n               return PIXEL_ABGR( color->a, color->r, color->g, color->b );\n\n          case DSPF_AiRGB:\n               return PIXEL_AiRGB( color->a, color->r, color->g, color->b );\n\n          case DSPF_RGBA5551:\n               return PIXEL_RGBA5551( color->a, color->r, color->g, color->b );\n\n          case DSPF_RGBAF88871:\n               return PIXEL_RGBAF88871( color->a, color->r, color->g, color->b );\n\n          case DSPF_AYUV:\n               RGB_TO_YCBCR( color->r, color->g, color->b, y, cb, cr );\n               return PIXEL_AYUV( color->a, y, cb, cr );\n\n          case DSPF_AVYU:\n               RGB_TO_YCBCR( color->r, color->g, color->b, y, cb, cr );\n               return PIXEL_AVYU( color->a, y, cb, cr );\n\n          case DSPF_VYU:\n               RGB_TO_YCBCR( color->r, color->g, color->b, y, cb, cr );\n               return PIXEL_VYU( y, cb, cr );\n\n          case DSPF_YUY2:\n               RGB_TO_YCBCR( color->r, color->g, color->b, y, cb, cr );\n#ifdef WORDS_BIGENDIAN\n               return PIXEL_YUY2_BE( y, cb, cr );\n#else\n               return PIXEL_YUY2_LE( y, cb, cr );\n#endif\n\n          case DSPF_UYVY:\n               RGB_TO_YCBCR( color->r, color->g, color->b, y, cb, cr );\n#ifdef WORDS_BIGENDIAN\n               return PIXEL_UYVY_BE( y, cb, cr );\n#else\n               return PIXEL_UYVY_LE( y, cb, cr );\n#endif\n\n          case DSPF_I420:\n          case DSPF_Y42B:\n          case DSPF_Y444:\n               RGB_TO_YCBCR( color->r, color->g, color->b, y, cb, cr );\n               return y << 16 | (cb << 8) | cr;\n\n          case DSPF_YV12:\n          case DSPF_YV16:\n          case DSPF_YV24:\n               RGB_TO_YCBCR( color->r, color->g, color->b, y, cb, cr );\n               return y << 16 | (cr << 8) | cb;\n\n          case DSPF_A8:\n               return color->a;\n\n          default:\n               if (DFB_PIXELFORMAT_IS_INDEXED( format ))\n                    D_ONCE( \"palette format\" );\n               else\n                    D_WARN( \"unknown format 0x%08x\", (unsigned int) format );\n     }\n\n     return 0x55555555;\n}\n\nvoid\ndfb_pixel_to_components( DFBSurfacePixelFormat  format,\n                         unsigned long          pixel,\n                         u8                     *a,\n                         u8                     *c2,    /* either Y or R */\n                         u8                     *c1,    /* either U or G */\n                         u8                     *c0 )   /* either V or B */\n{\n     D_DEBUG_AT( GFX_Converter, \"%s()\\n\", __FUNCTION__ );\n\n     *a = 0xff;\n\n     switch (format) {\n          case DSPF_RGB332:\n               *c2 = EXPAND_3to8( (pixel & 0xe0) >> 5 );\n               *c1 = EXPAND_3to8( (pixel & 0x1c) >> 2 );\n               *c0 = EXPAND_2to8(  pixel & 0x03       );\n               break;\n\n          case DSPF_ARGB1555:\n               *a  = EXPAND_1to8(  pixel >> 15           );\n          case DSPF_RGB555:\n               *c2 = EXPAND_5to8( (pixel & 0x7c00) >> 10 );\n               *c1 = EXPAND_5to8( (pixel & 0x03e0) >>  5 );\n               *c0 = EXPAND_5to8(  pixel & 0x001f        );\n               break;\n\n          case DSPF_BGR555:\n               *c2 = EXPAND_5to8(  pixel & 0x001f        );\n               *c1 = EXPAND_5to8( (pixel & 0x03e0) >>  5 );\n               *c0 = EXPAND_5to8( (pixel & 0x7c00) >> 10 );\n               break;\n\n          case DSPF_ARGB2554:\n               *a  = EXPAND_2to8(  pixel >> 14           );\n               *c2 = EXPAND_5to8( (pixel & 0x3e00) >>  9 );\n               *c1 = EXPAND_5to8( (pixel & 0x01f0) >>  4 );\n               *c0 = EXPAND_4to8(  pixel & 0x000f        );\n               break;\n\n          case DSPF_ARGB4444:\n               *a  = EXPAND_4to8(  pixel >> 12          );\n          case DSPF_RGB444:\n               *c2 = EXPAND_4to8( (pixel & 0x0f00) >> 8 );\n               *c1 = EXPAND_4to8( (pixel & 0x00f0) >> 4 );\n               *c0 = EXPAND_4to8( (pixel & 0x000f)      );\n               break;\n\n          case DSPF_RGBA4444:\n               *c2 = EXPAND_4to8(  pixel >> 12          );\n               *c1 = EXPAND_4to8( (pixel & 0x0f00) >> 8 );\n               *c0 = EXPAND_4to8( (pixel & 0x00f0) >> 4 );\n               *a  = EXPAND_4to8( (pixel & 0x000f)      );\n               break;\n\n          case DSPF_RGB16:\n               *c2 = EXPAND_5to8( (pixel & 0xf800) >> 11 );\n               *c1 = EXPAND_6to8( (pixel & 0x07e0) >>  5 );\n               *c0 = EXPAND_5to8(  pixel & 0x001f        );\n               break;\n\n          case DSPF_ARGB:\n               *a  =  pixel >> 24;\n          case DSPF_RGB24:\n          case DSPF_RGB32:\n               *c2 = (pixel & 0xff0000) >> 16;\n               *c1 = (pixel & 0x00ff00) >>  8;\n               *c0 =  pixel & 0x0000ff;\n               break;\n\n          case DSPF_ABGR:\n               *a  =  pixel >> 24;\n          case DSPF_BGR24:\n               *c0 = (pixel & 0xff0000) >> 16;\n               *c1 = (pixel & 0x00ff00) >>  8;\n               *c2 =  pixel & 0x0000ff;\n               break;\n\n          case DSPF_AiRGB:\n               *a  = (pixel >> 24) ^ 0xff;\n               *c2 = (pixel & 0xff0000) >> 16;\n               *c1 = (pixel & 0x00ff00) >>  8;\n               *c0 =  pixel & 0x0000ff;\n               break;\n\n          case DSPF_AYUV:\n               *a  =  pixel >> 24;\n               *c2 = (pixel & 0xff0000) >> 16;\n               *c1 = (pixel & 0x00ff00) >>  8;\n               *c0 =  pixel & 0x0000ff;\n               break;\n\n          case DSPF_YUY2:\n#ifdef WORDS_BIGENDIAN\n               *c2 =  pixel & 0xff;\n               *c1 =  pixel >> 24;\n               *c0 = (pixel & 0xff00) >> 8;\n#else\n               *c2 =  pixel & 0xff;\n               *c1 = (pixel & 0xff00) >> 8;\n               *c0 =  pixel >> 24;\n#endif\n               break;\n\n          case DSPF_UYVY:\n#ifdef WORDS_BIGENDIAN\n               *c2 = (pixel & 0xff00) >> 8;\n               *c1 = (pixel & 0xff0000) >> 16;\n               *c0 =  pixel & 0xff;\n#else\n               *c2 = (pixel & 0xff00) >> 8;\n               *c1 =  pixel & 0xff;\n               *c0 = (pixel & 0xff0000) >> 16;\n#endif\n               break;\n\n          case DSPF_I420:\n          case DSPF_YV12:\n          case DSPF_Y42B:\n          case DSPF_YV16:\n          case DSPF_Y444:\n          case DSPF_YV24:\n               *c2 =  pixel & 0xff;\n               *c1 = (pixel & 0xff00) >> 8;\n               *c0 = (pixel & 0xff0000) >> 16;\n               break;\n\n          default:\n               *c2 = 0;\n               *c1 = 0;\n               *c0 = 0;\n     }\n}\n\nvoid\ndfb_convert_to_rgb16( DFBSurfacePixelFormat  format,\n                      DFBSurfaceColorSpace   colorspace,\n                      const void            *src,\n                      int                    spitch,\n                      const void            *src_cb,\n                      int                    scbpitch,\n                      const void            *src_cr,\n                      int                    scrpitch,\n                      int                    surface_height,\n                      u16                   *dst,\n                      int                    dpitch,\n                      int                    width,\n                      int                    height )\n{\n     const int dp2 = dpitch / 2;\n     int       x;\n\n     D_DEBUG_AT( GFX_Converter, \"%s()\\n\", __FUNCTION__ );\n\n     if (!DFB_COLORSPACE_IS_COMPATIBLE( colorspace, format )) {\n          D_ONCE( \"incompatible colorspace\" );\n          return;\n     }\n\n     switch (format) {\n          case DSPF_RGB16:\n               while (height--) {\n                    direct_memcpy( dst, src, width * 2 );\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_NV16:\n               while (height--) {\n                    const u8  *src8  = src;\n                    const u16 *src16 = src + surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x], src16[x>>1] >> 8, src16[x>>1] & 0xff, r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x], src16[x>>1] & 0xff, src16[x>>1] >> 8, r, g, b );\n#endif\n\n                         dst[x] = PIXEL_RGB16( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_NV61:\n               while (height--) {\n                    const u8  *src8  = src;\n                    const u16 *src16 = src + surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x], src16[x>>1] & 0xff, src16[x>>1] >> 8, r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x], src16[x>>1] >> 8, src16[x>>1] & 0xff, r, g, b );\n#endif\n\n                         dst[x] = PIXEL_RGB16( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_NV24:\n               while (height--) {\n                    const u8  *src8  = src;\n                    const u16 *src16 = src + surface_height * spitch;\n\n                    for (x = 0 ; x < width; x++) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x], src16[x] >> 8, src16[x] & 0xff, r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x], src16[x] & 0xff, src16[x] >> 8, r, g, b );\n#endif\n\n                         dst[x] = PIXEL_RGB16( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_NV42:\n               while (height--) {\n                    const u8  *src8  = src;\n                    const u16 *src16 = src + surface_height * spitch;\n\n                    for (x = 0 ; x < width; x++) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x], src16[x] & 0xff, src16[x] >> 8, r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x], src16[x] >> 8, src16[x] & 0xff, r, g, b );\n#endif\n\n                         dst[x] = PIXEL_RGB16( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_UYVY:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x += 2) {\n                         int r, g, b;\n                         int y0, y1, cb, cr;\n\n                         y1 =  src32[x/2] >> 24;\n                         cr = (src32[x/2] >> 16) & 0xff;\n                         y0 = (src32[x/2] >>  8) & 0xff;\n                         cb =  src32[x/2]        & 0xff;\n\n                         YCBCR_TO_RGB( y0, cb, cr, r, g, b );\n                         dst[x] = PIXEL_RGB16( r, g, b );\n\n                         YCBCR_TO_RGB( y1, cb, cr, r, g, b );\n                         dst[x+1] = PIXEL_RGB16( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_RGB444:\n          case DSPF_ARGB4444:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_RGB16( EXPAND_4to8( (src16[x] & 0x0f00) >> 8 ),\n                                               EXPAND_4to8( (src16[x] & 0x00f0) >> 4 ),\n                                               EXPAND_4to8(  src16[x] & 0x000f       ) );\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_RGBA4444:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_RGB16( EXPAND_4to8( (src16[x] & 0xf000) >> 12 ),\n                                               EXPAND_4to8( (src16[x] & 0x0f00) >>  8 ),\n                                               EXPAND_4to8( (src16[x] & 0x00f0) >>  4 ) );\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_RGB555:\n          case DSPF_ARGB1555:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = ((src16[x] & 0x7c00) << 1) |\n                                  ((src16[x] & 0x03e0) << 1) |\n                                  ((src16[x] & 0x0200) >> 4) |\n                                   (src16[x] & 0x001f);\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_BGR555:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = ((src16[x] & 0x7c00) >> 10) |\n                                  ((src16[x] & 0x03e0) <<  1) |\n                                  ((src16[x] & 0x001f) << 11);\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_RGB32:\n          case DSPF_ARGB:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_RGB16( (src32[x] & 0xff0000) >> 16,\n                                               (src32[x] & 0x00ff00) >>  8,\n                                                src32[x] & 0x0000ff );\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_ABGR:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_RGB16(  src32[x] & 0x0000ff,\n                                               (src32[x] & 0x00ff00) >>  8,\n                                               (src32[x] & 0xff0000) >> 16 );\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_RGBAF88871:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_RGB16( (src32[x] & 0xff000000) >> 24,\n                                               (src32[x] & 0x00ff0000) >> 16,\n                                               (src32[x] & 0x0000ff00) >>  8 );\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_AYUV:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( (src32[x] >> 16) & 0xff, (src32[x] >> 8) & 0xff, src32[x] & 0xff, r, g, b );\n\n                         dst[x] = PIXEL_RGB16( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_AVYU:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( (src32[x] >> 8) & 0xff, src32[x] & 0xff, (src32[x] >> 16) & 0xff, r, g, b );\n\n                         dst[x] = PIXEL_RGB16( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_VYU:\n               while (height--) {\n                    const u8 *src8 = src;\n                    int       x3;\n\n                    for (x = 0, x3 = 0; x < width; x++, x3 += 3) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x3+1], src8[x3+2], src8[x3], r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x3+1], src8[x3], src8[x3+2], r, g, b );\n#endif\n\n                         dst[x] = PIXEL_RGB16( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_RGBA5551:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] =  (src16[x] & 0xf800)       |\n                                   (src16[x] & 0x07c0)       |\n                                  ((src16[x] & 0x0400) >> 5) |\n                                  ((src16[x] & 0x003e) >> 1);\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_ARGB8565:\n               ++height;\n               while (--height) {\n                    const u8 *src8 = src;\n\n                    for (x = 0; x < width; x++)\n#ifdef WORDS_BIGENDIAN\n                         dst[x] = (src8[x*3+1] << 8) | src8[x*3+2];\n#else\n                         dst[x] = (src8[x*3+1] << 8) | src8[x*3+0];\n#endif\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_I420:\n          case DSPF_YV12:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src_cb;\n                    const u8 *cr = src_cr;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( *y, *cb, *cr, r, g, b );\n\n                         ++y;\n                         cb += (x & 1);\n                         cr += (x & 1);\n\n                         dst[x] = PIXEL_RGB16( r, g, b );\n                    }\n\n                    src    += spitch;\n                    src_cb += (height % 2) ? 0 : scbpitch;\n                    src_cr += (height % 2) ? 0 : scrpitch;\n                    dst    += dp2;\n               }\n               break;\n\n          case DSPF_Y42B:\n          case DSPF_YV16:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src_cb;\n                    const u8 *cr = src_cr;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( *y, *cb, *cr, r, g, b );\n\n                         ++y;\n                         cb += (x & 1);\n                         cr += (x & 1);\n\n                         dst[x] = PIXEL_RGB16( r, g, b );\n                    }\n\n                    src    += spitch;\n                    src_cb += scbpitch;\n                    src_cr += scrpitch;\n                    dst    += dp2;\n               }\n               break;\n\n          case DSPF_Y444:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src + surface_height * spitch;\n                    const u8 *cr = src + 2 * surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( *y++, *cb++, *cr++, r, g, b );\n\n                         dst[x] = PIXEL_RGB16( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_YV24:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src + 2 * surface_height * spitch;\n                    const u8 *cr = src + surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( *y++, *cb++, *cr++, r, g, b );\n\n                         dst[x] = PIXEL_RGB16( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          default:\n               D_ONCE( \"unsupported format\" );\n     }\n}\n\nvoid\ndfb_convert_to_rgb555( DFBSurfacePixelFormat  format,\n                       DFBSurfaceColorSpace   colorspace,\n                       const void            *src,\n                       int                    spitch,\n                       const void            *src_cb,\n                       int                    scbpitch,\n                       const void            *src_cr,\n                       int                    scrpitch,\n                       int                    surface_height,\n                       u16                   *dst,\n                       int                    dpitch,\n                       int                    width,\n                       int                    height )\n{\n     const int dp2 = dpitch / 2;\n     int       x;\n\n     D_DEBUG_AT( GFX_Converter, \"%s()\\n\", __FUNCTION__ );\n\n     if (!DFB_COLORSPACE_IS_COMPATIBLE( colorspace, format )) {\n          D_ONCE( \"incompatible colorspace\" );\n          return;\n     }\n\n     switch (format) {\n          case DSPF_RGB555:\n          case DSPF_ARGB1555:\n               while (height--) {\n                    direct_memcpy( dst, src, width * 2 );\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_NV16:\n               while (height--) {\n                    const u8  *src8  = src;\n                    const u16 *src16 = src + surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x], src16[x>>1] >> 8, src16[x>>1] & 0xff, r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x], src16[x>>1] & 0xff, src16[x>>1] >> 8, r, g, b );\n#endif\n\n                         dst[x] = PIXEL_RGB555( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_NV61:\n               while (height--) {\n                    const u8  *src8  = src;\n                    const u16 *src16 = src + surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x], src16[x>>1] & 0xff, src16[x>>1] >> 8, r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x], src16[x>>1] >> 8, src16[x>>1] & 0xff, r, g, b );\n#endif\n\n                         dst[x] = PIXEL_RGB555( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_NV24:\n               while (height--) {\n                    const u8  *src8  = src;\n                    const u16 *src16 = src + surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x], src16[x] >> 8, src16[x] & 0xff, r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x], src16[x] & 0xff, src16[x] >> 8, r, g, b );\n#endif\n\n                         dst[x] = PIXEL_RGB555( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_NV42:\n               while (height--) {\n                    const u8  *src8  = src;\n                    const u16 *src16 = src + surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x], src16[x] & 0xff, src16[x] >> 8, r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x], src16[x] >> 8, src16[x] & 0xff, r, g, b );\n#endif\n\n                         dst[x] = PIXEL_RGB555( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_RGB444:\n          case DSPF_ARGB4444:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_RGB555( EXPAND_4to8( (src16[x] & 0x0f00) >> 8 ),\n                                                EXPAND_4to8( (src16[x] & 0x00f0) >> 4 ),\n                                                EXPAND_4to8(  src16[x] & 0x000f       ) );\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_RGBA4444:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_RGB555( EXPAND_4to8( (src16[x] & 0xf000) >> 12 ),\n                                                EXPAND_4to8( (src16[x] & 0x0f00) >>  8 ),\n                                                EXPAND_4to8( (src16[x] & 0x00f0) >>  4 ) );\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_RGB16:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = ((src16[x] & 0xffc0) >> 1) | (src16[x] & 0x001f);\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_BGR555:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = ((src16[x] & 0x7c00) >> 10) | (src16[x] & 0x03e0) | ((src16[x] & 0x001f) << 10);\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_RGB32:\n          case DSPF_ARGB:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_RGB555( (src32[x] & 0xff0000) >> 16,\n                                                (src32[x] & 0x00ff00) >>  8,\n                                                 src32[x] & 0x0000ff );\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_ABGR:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_RGB555(  src32[x] & 0x0000ff,\n                                                (src32[x] & 0x00ff00) >>  8,\n                                                (src32[x] & 0xff0000) >> 16);\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_RGBAF88871:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_RGB555( (src32[x] & 0xff000000) >> 24,\n                                                (src32[x] & 0x00ff0000) >> 16,\n                                                (src32[x] & 0x0000ff00) >>  8 );\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_AYUV:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( (src32[x] >> 16) & 0xff, (src32[x] >> 8) & 0xff, src32[x] & 0xff, r, g, b );\n\n                         dst[x] = PIXEL_RGB555( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_RGBA5551:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = src16[x] >> 1;\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_ARGB8565:\n               ++height;\n               while (--height) {\n                    const u8 *src8 = src;\n\n                    for (x = 0; x < width; x++) {\n                         u32 pixel = (src8[x*3+1] << 8) | src8[x*3+2];\n\n                         dst[x] = ARGB8565_TO_ARGB1555( pixel );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_AVYU:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( (src32[x] >> 8) & 0xff, src32[x] & 0xff, (src32[x] >> 16) & 0xff, r, g, b );\n\n                         dst[x] = PIXEL_RGB555( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_VYU:\n               while (height--) {\n                    const u8 *src8 = src;\n                    int       x3;\n\n                    for (x = 0, x3 = 0; x < width; x++, x3 += 3) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x3+1], src8[x3+2], src8[x3], r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x3+1], src8[x3], src8[x3+2], r, g, b );\n#endif\n\n                         dst[x] = PIXEL_RGB555( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_I420:\n          case DSPF_YV12:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src_cb;\n                    const u8 *cr = src_cr;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( *y, *cb, *cr, r, g, b );\n\n                         ++y;\n                         cb += (x & 1);\n                         cr += (x & 1);\n\n                         dst[x] = PIXEL_RGB555( r, g, b );\n                    }\n\n                    src    += spitch;\n                    src_cb += (height % 2) ? 0 : scbpitch;\n                    src_cr += (height % 2) ? 0 : scrpitch;\n                    dst    += dp2;\n               }\n               break;\n\n          case DSPF_Y42B:\n          case DSPF_YV16:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src_cb;\n                    const u8 *cr = src_cr;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( *y, *cb, *cr, r, g, b );\n\n                         ++y;\n                         cb += (x & 1);\n                         cr += (x & 1);\n\n                         dst[x] = PIXEL_RGB555( r, g, b );\n                    }\n\n                    src    += spitch;\n                    src_cb += scbpitch;\n                    src_cr += scrpitch;\n                    dst    += dp2;\n               }\n               break;\n\n          case DSPF_Y444:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src + surface_height * spitch;\n                    const u8 *cr = src + 2 * surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( *y++, *cb++, *cr++, r, g, b );\n\n                         dst[x] = PIXEL_RGB555( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          case DSPF_YV24:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src + 2 * surface_height * spitch;\n                    const u8 *cr = src + surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( *y++, *cb++, *cr++, r, g, b );\n\n                         dst[x] = PIXEL_RGB555( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp2;\n               }\n               break;\n\n          default:\n               D_ONCE( \"unsupported format\" );\n     }\n}\n\nvoid\ndfb_convert_to_rgb32( DFBSurfacePixelFormat  format,\n                      DFBSurfaceColorSpace   colorspace,\n                      const void            *src,\n                      int                    spitch,\n                      const void            *src_cb,\n                      int                    scbpitch,\n                      const void            *src_cr,\n                      int                    scrpitch,\n                      int                    surface_height,\n                      u32                   *dst,\n                      int                    dpitch,\n                      int                    width,\n                      int                    height )\n{\n     const int dp4 = dpitch / 4;\n     int       x;\n\n     D_DEBUG_AT( GFX_Converter, \"%s()\\n\", __FUNCTION__ );\n\n     if (!DFB_COLORSPACE_IS_COMPATIBLE( colorspace, format )) {\n          D_ONCE( \"incompatible colorspace\" );\n          return;\n     }\n\n     switch (format) {\n          case DSPF_RGB32:\n          case DSPF_ARGB:\n               while (height--) {\n                    direct_memcpy( dst, src, width * 4 );\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_ABGR:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_RGB32(  src32[x] & 0x0000ff,\n                                               (src32[x] & 0x00ff00) >>  8,\n                                               (src32[x] & 0xff0000) >> 16 );\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_RGB24:\n               while (height--) {\n                    const u8 *src8 = src;\n\n                    for (x = 0; x < width; x++)\n#ifdef WORDS_BIGENDIAN\n                         dst[x] = (src8[x*3+0] << 16) | (src8[x*3+1] << 8) | src8[x*3+2];\n#else\n                         dst[x] = (src8[x*3+2] << 16) | (src8[x*3+1] << 8) | src8[x*3+0];\n#endif\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_BGR24:\n               while (height--) {\n                    const u8 *src8 = src;\n\n                    for (x = 0; x < width; x++)\n#ifdef WORDS_BIGENDIAN\n                         dst[x] = (src8[x*3+2] << 16) | (src8[x*3+1] << 8) | src8[x*3+0];\n#else\n                         dst[x] = (src8[x*3+0] << 16) | (src8[x*3+1] << 8) | src8[x*3+2];\n#endif\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_AYUV:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( (src32[x] >> 16) & 0xff, (src32[x] >> 8) & 0xff, src32[x] & 0xff, r, g, b );\n\n                         dst[x] = PIXEL_RGB32( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_NV16:\n               while (height--) {\n                    const u8  *src8  = src;\n                    const u16 *src16 = src + surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x], src16[x>>1] >> 8, src16[x>>1] & 0xff, r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x], src16[x>>1] & 0xff, src16[x>>1] >> 8, r, g, b );\n#endif\n\n                         dst[x] = PIXEL_RGB32( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_NV61:\n               while (height--) {\n                    const u8  *src8  = src;\n                    const u16 *src16 = src + surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x], src16[x>>1] & 0xff, src16[x>>1] >> 8, r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x], src16[x>>1] >> 8, src16[x>>1] & 0xff, r, g, b );\n#endif\n\n                         dst[x] = PIXEL_RGB32( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_NV24:\n               while (height--) {\n                    const u8  *src8  = src;\n                    const u16 *src16 = src + surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x], src16[x] >> 8, src16[x] & 0xff, r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x], src16[x] & 0xff, src16[x] >> 8, r, g, b );\n#endif\n\n                         dst[x] = PIXEL_RGB32( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_NV42:\n               while (height--) {\n                    const u8  *src8  = src;\n                    const u16 *src16 = src + surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x], src16[x] & 0xff, src16[x] >> 8, r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x], src16[x] >> 8, src16[x] & 0xff, r, g, b );\n#endif\n\n                         dst[x] = PIXEL_RGB32( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_RGB444:\n          case DSPF_ARGB4444:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = ARGB4444_TO_RGB32( src16[x] );\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_RGBA4444:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = RGBA4444_TO_RGB32( src16[x] );\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_RGB555:\n          case DSPF_ARGB1555:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_RGB32( ((src16[x] & 0x7c00) >> 7) | ((src16[x] & 0x7000) >> 12),\n                                               ((src16[x] & 0x03e0) >> 2) | ((src16[x] & 0x0380) >>  7),\n                                               ((src16[x] & 0x001f) << 3) | ((src16[x] & 0x001c) >>  2) );\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_BGR555:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_RGB32( ((src16[x] & 0x001f) << 3) | ((src16[x] & 0x001c) >>  2),\n                                               ((src16[x] & 0x03e0) >> 2) | ((src16[x] & 0x0380) >>  7),\n                                               ((src16[x] & 0x7c00) >> 7) | ((src16[x] & 0x7000) >> 12) );\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_RGB16:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_RGB32( ((src16[x] & 0xf800) >> 8) | ((src16[x] & 0xe000) >> 13),\n                                               ((src16[x] & 0x07e0) >> 3) | ((src16[x] & 0x0600) >>  9),\n                                               ((src16[x] & 0x001f) << 3) | ((src16[x] & 0x001c) >>  2) );\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_RGBA5551:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_RGB32( ((src16[x] & 0xf800) >> 8) | ((src16[x] & 0xe000) >> 13),\n                                               ((src16[x] & 0x07c0) >> 3) | ((src16[x] & 0x0700) >>  8),\n                                               ((src16[x] & 0x003e) << 2) | ((src16[x] & 0x0038) >>  3) );\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_ARGB8565:\n               ++height;\n               while (--height) {\n                    const u8 *src8 = src;\n\n                    for (x = 0; x < width; x++) {\n                         u8 r, g, b;\n\n                         r = EXPAND_5to8(  src8[x*3+1] >> 3                       );\n                         g = EXPAND_6to8( (src8[x*3+1] << 5) | (src8[x*3+2] >> 3) );\n                         b = EXPAND_5to8(  src8[x*3+2] & 0x1f                     );\n\n                         dst[x] = PIXEL_RGB32( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_RGBAF88871:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = (src32[x] & 0xffffff00) >> 8;\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_AVYU:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( (src32[x] >> 8) & 0xff, src32[x] & 0xff, (src32[x] >> 16) & 0xff, r, g, b );\n\n                         dst[x] = PIXEL_RGB32( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_VYU:\n               while (height--) {\n                    const u8 *src8 = src;\n                    int       x3;\n\n                    for (x = 0, x3 = 0; x < width; x++, x3 += 3) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x3+1], src8[x3+2], src8[x3], r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x3+1], src8[x3], src8[x3+2], r, g, b );\n#endif\n\n                         dst[x] = PIXEL_RGB32( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_I420:\n          case DSPF_YV12:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src_cb;\n                    const u8 *cr = src_cr;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( *y, *cb, *cr, r, g, b );\n\n                         ++y;\n                         cb += (x & 1);\n                         cr += (x & 1);\n\n                         dst[x] = PIXEL_RGB32( r, g, b );\n                    }\n\n                    src    += spitch;\n                    src_cb += (height % 2) ? 0 : scbpitch;\n                    src_cr += (height % 2) ? 0 : scrpitch;\n                    dst    += dp4;\n               }\n               break;\n\n          case DSPF_Y42B:\n          case DSPF_YV16:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src_cb;\n                    const u8 *cr = src_cr;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( *y, *cb, *cr, r, g, b );\n\n                         ++y;\n                         cb += (x & 1);\n                         cr += (x & 1);\n\n                         dst[x] = PIXEL_RGB32( r, g, b );\n                    }\n\n                    src    += spitch;\n                    src_cb += scbpitch;\n                    src_cr += scrpitch;\n                    dst    += dp4;\n               }\n               break;\n\n          case DSPF_Y444:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src + surface_height * spitch;\n                    const u8 *cr = src + 2 * surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( *y++, *cb++, *cr++, r, g, b );\n\n                         dst[x] = PIXEL_RGB32( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_YV24:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src + 2 * surface_height * spitch;\n                    const u8 *cr = src + surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( *y++, *cb++, *cr++, r, g, b );\n\n                         dst[x] = PIXEL_RGB32( r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          default:\n               D_ONCE( \"unsupported format\" );\n     }\n}\n\nvoid\ndfb_convert_to_argb( DFBSurfacePixelFormat  format,\n                     DFBSurfaceColorSpace   colorspace,\n                     const void            *src,\n                     int                    spitch,\n                     const void            *src_cb,\n                     int                    scbpitch,\n                     const void            *src_cr,\n                     int                    scrpitch,\n                     int                    surface_height,\n                     u32                   *dst,\n                     int                    dpitch,\n                     int                    width,\n                     int                    height )\n{\n     const int dp4 = dpitch / 4;\n     int       x;\n\n     D_DEBUG_AT( GFX_Converter, \"%s()\\n\", __FUNCTION__ );\n\n     if (!DFB_COLORSPACE_IS_COMPATIBLE( colorspace, format )) {\n          D_ONCE( \"incompatible colorspace\" );\n          return;\n     }\n\n     switch (format) {\n          case DSPF_ARGB:\n               while (height--) {\n                    direct_memcpy( dst, src, width * 4 );\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_ABGR:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_ARGB( (src32[x] & 0xff000000) >> 24,\n                                               src32[x] & 0x000000ff,\n                                              (src32[x] & 0x0000ff00) >>  8,\n                                              (src32[x] & 0x00ff0000) >> 16 );\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_RGB32:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = src32[x] | 0xff000000;\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_RGB24:\n               while (height--) {\n                    const u8 *src8 = src;\n\n                    for (x = 0; x < width; x++)\n#ifdef WORDS_BIGENDIAN\n                         dst[x] = (src8[x*3+0] << 16) | (src8[x*3+1] << 8) | src8[x*3+2] | 0xff000000;\n#else\n                         dst[x] = (src8[x*3+2] << 16) | (src8[x*3+1] << 8) | src8[x*3+0] | 0xff000000;\n#endif\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_BGR24:\n               while (height--) {\n                    const u8 *src8 = src;\n\n                    for (x = 0; x < width; x++)\n#ifdef WORDS_BIGENDIAN\n                         dst[x] = (src8[x*3+2] << 16) | (src8[x*3+1] << 8) | src8[x*3+0] | 0xff000000;\n#else\n                         dst[x] = (src8[x*3+0] << 16) | (src8[x*3+1] << 8) | src8[x*3+1] | 0xff000000;\n#endif\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_AYUV:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( (src32[x] >> 16) & 0xff, (src32[x] >> 8) & 0xff, src32[x] & 0xff, r, g, b );\n\n                         dst[x] = PIXEL_ARGB( src32[x] >> 24, r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_NV16:\n               while (height--) {\n                    const u8  *src8  = src;\n                    const u16 *src16 = src + surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x], src16[x>>1] >> 8, src16[x>>1] & 0xff, r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x], src16[x>>1] & 0xff, src16[x>>1] >> 8, r, g, b );\n#endif\n\n                         dst[x] = PIXEL_ARGB( 0xff, r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_NV61:\n               while (height--) {\n                    const u8  *src8  = src;\n                    const u16 *src16 = src + surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x], src16[x>>1] & 0xff, src16[x>>1] >> 8, r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x], src16[x>>1] >> 8, src16[x>>1] & 0xff, r, g, b );\n#endif\n\n                         dst[x] = PIXEL_ARGB( 0xff, r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_NV24:\n               while (height--) {\n                    const u8  *src8  = src;\n                    const u16 *src16 = src + surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x], src16[x] >> 8, src16[x] & 0xff, r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x], src16[x] & 0xff, src16[x] >> 8, r, g, b );\n#endif\n\n                         dst[x] = PIXEL_ARGB( 0xff, r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_NV42:\n               while (height--) {\n                    const u8  *src8  = src;\n                    const u16 *src16 = src + surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x], src16[x] & 0xff, src16[x] >> 8, r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x], src16[x] >> 8, src16[x] & 0xff, r, g, b );\n#endif\n\n                         dst[x] = PIXEL_ARGB( 0xff, r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_ARGB4444:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = ARGB4444_TO_ARGB( src16[x] );\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_RGBA4444:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = RGBA4444_TO_ARGB( src16[x] );\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_RGB444:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_ARGB( 0xff,\n                                              ((src16[x] & 0x0f00) >> 4) | ((src16[x] & 0x0f00) >> 8),\n                                               (src16[x] & 0x00f0)       | ((src16[x] & 0x00f0) >> 4),\n                                              ((src16[x] & 0x000f) << 4) |  (src16[x] & 0x000f) );\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_ARGB1555:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_ARGB( (src16[x] & 0x8000) ? 0xff : 0x00,\n                                              ((src16[x] & 0x7c00) >> 7) | ((src16[x] & 0x7000) >> 12),\n                                              ((src16[x] & 0x03e0) >> 2) | ((src16[x] & 0x0380) >>  7),\n                                              ((src16[x] & 0x001f) << 3) | ((src16[x] & 0x001c) >>  2) );\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_RGB555:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_ARGB( 0xff,\n                                              ((src16[x] & 0x7c00) >> 7) | ((src16[x] & 0x7000) >> 12),\n                                              ((src16[x] & 0x03e0) >> 2) | ((src16[x] & 0x0380) >>  7),\n                                              ((src16[x] & 0x001f) << 3) | ((src16[x] & 0x001c) >>  2) );\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_BGR555:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_ARGB( 0xff,\n                                              ((src16[x] & 0x001f) << 3) | ((src16[x] & 0x001c) >>  2),\n                                              ((src16[x] & 0x03e0) >> 2) | ((src16[x] & 0x0380) >>  7),\n                                              ((src16[x] & 0x7c00) >> 7) | ((src16[x] & 0x7000) >> 12) );\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_RGB16:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_ARGB( 0xff,\n                                              ((src16[x] & 0xf800) >> 8) | ((src16[x] & 0xe000) >> 13),\n                                              ((src16[x] & 0x07e0) >> 3) | ((src16[x] & 0x0600) >>  9),\n                                              ((src16[x] & 0x001f) << 3) | ((src16[x] & 0x001c) >>  2) );\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_RGBA5551:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_ARGB(  (src16[x] & 0x1) ? 0xff : 0x00,\n                                              ((src16[x] & 0xf800) >> 8) | ((src16[x] & 0xe000) >> 13),\n                                              ((src16[x] & 0x07c0) >> 3) | ((src16[x] & 0x0700) >>  8),\n                                              ((src16[x] & 0x003e) << 2) | ((src16[x] & 0x0038) >>  3) );\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_ARGB8565:\n               ++height;\n               while (--height) {\n                    const u8 *src8 = src;\n\n                    for (x = 0; x < width; x++) {\n                         u8 r, g, b;\n\n                         r = EXPAND_5to8(  src8[x*3+1] >> 3                       );\n                         g = EXPAND_6to8( (src8[x*3+1] << 5) | (src8[x*3+2] >> 3) );\n                         b = EXPAND_5to8(  src8[x*3+2] & 0x1f                     );\n\n                         dst[x] = PIXEL_ARGB( src8[x*3], r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_RGBAF88871:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x++)\n                         dst[x] = PIXEL_ARGB( EXPAND_7to8( (src32[x] & 0x000000fe) >> 1 ),\n                                                           (src32[x] & 0xff000000) >> 24,\n                                                           (src32[x] & 0x00ff0000) >> 16,\n                                                           (src32[x] & 0x0000ff00) >>  8 );\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_AVYU:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( (src32[x] >> 8) & 0xff, src32[x] & 0xff, (src32[x] >> 16) & 0xff, r, g, b );\n\n                         dst[x] = PIXEL_ARGB( (src32[x] >> 24), r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_VYU:\n               while (height--) {\n                    const u8 *src8 = src;\n                    int       x3;\n\n                    for (x = 0, x3 = 0; x < width; x++, x3 += 3) {\n                         int r, g, b;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[x3+1], src8[x3+2], src8[x3], r, g, b );\n#else\n                         YCBCR_TO_RGB( src8[x3+1], src8[x3], src8[x3+2], r, g, b );\n#endif\n\n                         dst[x] = PIXEL_ARGB( 0xff, r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_I420:\n          case DSPF_YV12:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src_cb;\n                    const u8 *cr = src_cr;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( *y, *cb, *cr, r, g, b );\n\n                         ++y;\n                         cb += (x & 1);\n                         cr += (x & 1);\n\n                         dst[x] = PIXEL_ARGB( 0xff, r, g, b );\n                    }\n\n                    src    += spitch;\n                    src_cb += (height % 2) ? 0 : scbpitch;\n                    src_cr += (height % 2) ? 0 : scrpitch;\n                    dst    += dp4;\n               }\n               break;\n\n          case DSPF_Y42B:\n          case DSPF_YV16:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src_cb;\n                    const u8 *cr = src_cr;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( *y, *cb, *cr, r, g, b );\n\n                         ++y;\n                         cb += (x & 1);\n                         cr += (x & 1);\n\n                         dst[x] = PIXEL_ARGB( 0xff, r, g, b );\n                    }\n\n                    src    += spitch;\n                    src_cb += scbpitch;\n                    src_cr += scrpitch;\n                    dst    += dp4;\n               }\n               break;\n\n          case DSPF_Y444:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src + surface_height * spitch;\n                    const u8 *cr = src + 2 * surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( *y++, *cb++, *cr++, r, g, b );\n\n                         dst[x] = PIXEL_ARGB( 0xff, r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          case DSPF_YV24:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src + 2 * surface_height * spitch;\n                    const u8 *cr = src + surface_height * spitch;\n\n                    for (x = 0; x < width; x++) {\n                         int r, g, b;\n\n                         YCBCR_TO_RGB( *y++, *cb++, *cr++, r, g, b );\n\n                         dst[x] = PIXEL_ARGB( 0xff, r, g, b );\n                    }\n\n                    src += spitch;\n                    dst += dp4;\n               }\n               break;\n\n          default:\n               D_ONCE( \"unsupported format\" );\n     }\n}\n\nvoid\ndfb_convert_to_rgb24( DFBSurfacePixelFormat  format,\n                      DFBSurfaceColorSpace   colorspace,\n                      const void            *src,\n                      int                    spitch,\n                      const void            *src_cb,\n                      int                    scbpitch,\n                      const void            *src_cr,\n                      int                    scrpitch,\n                      int                    surface_height,\n                      u8                    *dst,\n                      int                    dpitch,\n                      int                    width,\n                      int                    height )\n{\n     int n, n3;\n\n     D_DEBUG_AT( GFX_Converter, \"%s()\\n\", __FUNCTION__ );\n\n     if (!DFB_COLORSPACE_IS_COMPATIBLE( colorspace, format )) {\n          D_ONCE( \"incompatible colorspace\" );\n          return;\n     }\n\n     switch (format) {\n          case DSPF_A8:\n               while (height--) {\n                    const u8 *src8 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         dst[n3+0] = src8[n];\n                         dst[n3+1] = src8[n];\n                         dst[n3+2] = src8[n];\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_AiRGB:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         dst[n3+0] = (src32[n] & 0xff0000) >> 16;\n                         dst[n3+1] = (src32[n] & 0x00ff00) >>  8;\n                         dst[n3+2] =  src32[n] & 0x0000ff;\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_ARGB:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         dst[n3+0] = (src32[n] & 0xff0000) >> 16;\n                         dst[n3+1] = (src32[n] & 0x00ff00) >>  8;\n                         dst[n3+2] =  src32[n] & 0x0000ff;\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_ABGR:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         dst[n3+0] =  src32[n] & 0x0000ff;\n                         dst[n3+1] = (src32[n] & 0x00ff00) >>  8;\n                         dst[n3+2] = (src32[n] & 0xff0000) >> 16;\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_ARGB1555:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         dst[n3+0] = (src16[n] & 0x7c00) >> 7;\n                         dst[n3+1] = (src16[n] & 0x03e0) >> 2;\n                         dst[n3+2] = (src16[n] & 0x001f) << 3;\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_RGB555:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         dst[n3+0] = (src16[n] & 0x7c00) >> 7;\n                         dst[n3+1] = (src16[n] & 0x03e0) >> 2;\n                         dst[n3+2] = (src16[n] & 0x001f) << 3;\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_BGR555:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         dst[n3+2] = (src16[n] & 0x7c00) >> 7;\n                         dst[n3+1] = (src16[n] & 0x03e0) >> 2;\n                         dst[n3+0] = (src16[n] & 0x001f) << 3;\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_ARGB2554:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         dst[n3+0] = (src16[n] & 0x3e00) >> 6;\n                         dst[n3+1] = (src16[n] & 0x01f0) >> 1;\n                         dst[n3+2] = (src16[n] & 0x000f) << 4;\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_ARGB4444:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         dst[n3+0] = (src16[n] & 0x0f00) >> 4;\n                         dst[n3+1] =  src16[n] & 0x00f0;\n                         dst[n3+2] = (src16[n] & 0x000f) << 4;\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_RGBA4444:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         dst[n3+0] = (src16[n] & 0xf000) >> 8;\n                         dst[n3+1] = (src16[n] & 0x0f00) >> 4;\n                         dst[n3+2] =  src16[n] & 0x00f0;\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_RGB444:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         dst[n3+0] = (src16[n] & 0x0f00) >> 4;\n                         dst[n3+1] =  src16[n] & 0x00f0;\n                         dst[n3+2] = (src16[n] & 0x000f) << 4;\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_RGB332:\n               while (height--) {\n                    const u8 *src8 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         dst[n3+0] = EXPAND_3to8(  src8[n] >> 5         );\n                         dst[n3+1] = EXPAND_3to8( (src8[n] >> 2) & 0x07 );\n                         dst[n3+2] = EXPAND_2to8(  src8[n] & 0x03       );\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_RGB16:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         dst[n3+0] = (src16[n] & 0xf800) >> 8;\n                         dst[n3+1] = (src16[n] & 0x07e0) >> 3;\n                         dst[n3+2] = (src16[n] & 0x001f) << 3;\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_RGB24:\n               while (height--) {\n                    const u8 *src8 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n#ifdef WORDS_BIGENDIAN\n                         dst[n3+0] = src8[n3+0];\n                         dst[n3+1] = src8[n3+1];\n                         dst[n3+2] = src8[n3+2];\n#else\n                         dst[n3+0] = src8[n3+2];\n                         dst[n3+1] = src8[n3+1];\n                         dst[n3+2] = src8[n3+0];\n#endif\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_BGR24:\n               while (height--) {\n                    const u8 *src8 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n#ifdef WORDS_BIGENDIAN\n                         dst[n3+0] = src8[n3+2];\n                         dst[n3+1] = src8[n3+1];\n                         dst[n3+2] = src8[n3+0];\n#else\n                         dst[n3+0] = src8[n3+0];\n                         dst[n3+1] = src8[n3+1];\n                         dst[n3+2] = src8[n3+2];\n#endif\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_RGB32:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         dst[n3+0] = (src32[n] & 0xff0000) >> 16;\n                         dst[n3+1] = (src32[n] & 0x00ff00) >>  8;\n                         dst[n3+2] =  src32[n] & 0x0000ff;\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_ARGB8565:\n               while (height--) {\n                    const u8 *src8 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n#ifdef WORDS_BIGENDIAN\n                         dst[n3+0] =   src8[n3+1] & 0xf8;\n                         dst[n3+1] = ((src8[n3+1] & 0x07) << 5) | ((src8[n3+2] & 0xe0) >> 3);\n                         dst[n3+2] =  (src8[n3+2] & 0x1f) << 3;\n#else\n                         dst[n3+0] =   src8[n3+1] & 0xf8;\n                         dst[n3+1] = ((src8[n3+1] & 0x07) << 5) | ((src8[n3+0] & 0xe0) >> 3);\n                         dst[n3+2] =  (src8[n3+0] & 0x1f) << 3;\n#endif\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_RGBAF88871:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         dst[n3+0] = (src32[n] & 0xff000000) >> 24;\n                         dst[n3+1] = (src32[n] & 0x00ff0000) >> 16;\n                         dst[n3+2] = (src32[n] & 0x0000ff00) >>  8;\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_AYUV:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         u32 y, cb, cr;\n\n                         y  = (src32[n] & 0xff0000) >> 16;\n                         cb = (src32[n] & 0x00ff00) >>  8;\n                         cr =  src32[n] & 0x0000ff;\n\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( y, cb, cr, dst[n3+0], dst[n3+1], dst[n3+2] );\n#else\n                         YCBCR_TO_RGB( y, cb, cr, dst[n3+2], dst[n3+1], dst[n3+0] );\n#endif\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_AVYU:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         u32 y, cb, cr;\n\n                         cr = (src32[n] & 0xff0000) >> 16;\n                         y  = (src32[n] & 0x00ff00) >>  8;\n                         cb =  src32[n] & 0x0000ff;\n\n                         YCBCR_TO_RGB( y, cb, cr, dst[n3+0], dst[n3+1], dst[n3+2] );\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_VYU:\n               while (height--) {\n                    const u8 *src8 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[n3+1], src8[n3+2], src8[n3+0], dst[n3+0], dst[n3+1], dst[n3+2] );\n#else\n                         YCBCR_TO_RGB( src8[n3+1], src8[n3+0], src8[n3+2], dst[n3+0], dst[n3+1], dst[n3+2] );\n#endif\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_YUY2:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (n = 0, n3 = 0; n < width / 2; n++, n3 += 6) {\n                         u32 y0, cb, y1, cr;\n\n                         y0 =  src32[n] & 0x000000ff;\n                         cb = (src32[n] & 0x0000ff00) >>  8;\n                         y1 = (src32[n] & 0x00ff0000) >> 16;\n                         cr = (src32[n] & 0xff000000) >> 24;\n\n                         YCBCR_TO_RGB( y0, cb, cr, dst[n3+0], dst[n3+1], dst[n3+2] );\n                         YCBCR_TO_RGB( y1, cb, cr, dst[n3+3], dst[n3+4], dst[n3+5] );\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_UYVY:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (n = 0, n3 = 0; n < width / 2; n++, n3 += 6) {\n                         u32 y0, cb, y1, cr;\n\n                         cb =  src32[n] & 0x000000ff;\n                         y0 = (src32[n] & 0x0000ff00) >>  8;\n                         cr = (src32[n] & 0x00ff0000) >> 16;\n                         y1 = (src32[n] & 0xff000000) >> 24;\n\n                         YCBCR_TO_RGB( y0, cb, cr, dst[n3+0], dst[n3+1], dst[n3+2] );\n                         YCBCR_TO_RGB( y1, cb, cr, dst[n3+3], dst[n3+4], dst[n3+5] );\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_NV16:\n               while (height--) {\n                    const u16 *cbcr = src + surface_height * spitch;\n                    const u8  *src8 = src;\n\n                    for (n = 0, n3 = 0; n < width / 2; n++, n3 += 6) {\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[n*2+0], cbcr[n] >> 8, cbcr[n] & 0xff, dst[n3+0], dst[n3+1], dst[n3+2] );\n                         YCBCR_TO_RGB( src8[n*2+1], cbcr[n] >> 8, cbcr[n] & 0xff, dst[n3+3], dst[n3+4], dst[n3+5] );\n#else\n                         YCBCR_TO_RGB( src8[n*2+0], cbcr[n] & 0xff, cbcr[n] >> 8, dst[n3+0], dst[n3+1], dst[n3+2] );\n                         YCBCR_TO_RGB( src8[n*2+1], cbcr[n] & 0xff, cbcr[n] >> 8, dst[n3+3], dst[n3+4], dst[n3+5] );\n#endif\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_NV61:\n               while (height--) {\n                    const u16 *crcb = src + surface_height * spitch;\n                    const u8  *src8 = src;\n\n                    for (n = 0, n3 = 0; n < width / 2; n++, n3 += 6) {\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[n*2+0], crcb[n] & 0xff, crcb[n] >> 8, dst[n3+0], dst[n3+1], dst[n3+2] );\n                         YCBCR_TO_RGB( src8[n*2+1], crcb[n] & 0xff, crcb[n] >> 8, dst[n3+3], dst[n3+4], dst[n3+5] );\n#else\n                         YCBCR_TO_RGB( src8[n*2+0], crcb[n] >> 8, crcb[n] & 0xff, dst[n3+0], dst[n3+1], dst[n3+2] );\n                         YCBCR_TO_RGB( src8[n*2+1], crcb[n] >> 8, crcb[n] & 0xff, dst[n3+3], dst[n3+4], dst[n3+5] );\n#endif\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_NV24:\n               while (height--) {\n                    const u16 *cbcr = src + surface_height * spitch;\n                    const u8  *src8 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[n], cbcr[n] >> 8, cbcr[n] & 0xff, dst[n3+0], dst[n3+1], dst[n3+2] );\n#else\n                         YCBCR_TO_RGB( src8[n], cbcr[n] & 0xff, cbcr[n] >> 8, dst[n3+0], dst[n3+1], dst[n3+2] );\n#endif\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_NV42:\n               while (height--) {\n                    const u16 *crcb = src + surface_height * spitch;\n                    const u8  *src8 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n#ifdef WORDS_BIGENDIAN\n                         YCBCR_TO_RGB( src8[n], crcb[n] & 0xff, crcb[n] >> 8, dst[n3+0], dst[n3+1], dst[n3+2] );\n#else\n                         YCBCR_TO_RGB( src8[n], crcb[n] >> 8, crcb[n] & 0xff, dst[n3+0], dst[n3+1], dst[n3+2] );\n#endif\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_RGBA5551:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         dst[n3+0] = ((src16[n] & 0xf800) >> 8) | ((src16[n] & 0xe000) >> 13);\n                         dst[n3+1] = ((src16[n] & 0x07c0) >> 3) | ((src16[n] & 0x0700) >>  8);\n                         dst[n3+2] = ((src16[n] & 0x003e) << 2) | ((src16[n] & 0x0038) >>  3);\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_I420:\n          case DSPF_YV12:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src_cb;\n                    const u8 *cr = src_cr;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         YCBCR_TO_RGB( *y, *cb, *cr, dst[n3+0], dst[n3+1], dst[n3+2] );\n\n                         ++y;\n                         cb += (n & 1);\n                         cr += (n & 1);\n                    }\n\n                    src    += spitch;\n                    src_cb += (height % 2) ? 0 : scbpitch;\n                    src_cr += (height % 2) ? 0 : scrpitch;\n                    dst    += dpitch;\n               }\n               break;\n\n          case DSPF_Y42B:\n          case DSPF_YV16:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src_cb;\n                    const u8 *cr = src_cr;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         YCBCR_TO_RGB( *y, *cb, *cr, dst[n3+0], dst[n3+1], dst[n3+2] );\n\n                         ++y;\n                         cb += (n & 1);\n                         cr += (n & 1);\n                    }\n\n                    src    += spitch;\n                    src_cb += scbpitch;\n                    src_cr += scrpitch;\n                    dst    += dpitch;\n               }\n               break;\n\n          case DSPF_Y444:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src + surface_height * spitch;\n                    const u8 *cr = src + 2 * surface_height * spitch;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         YCBCR_TO_RGB( *y++, *cb++, *cr++, dst[n3+0], dst[n3+1], dst[n3+2] );\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_YV24:\n               ++height;\n               while (--height) {\n                    const u8 *y  = src;\n                    const u8 *cb = src + 2 * surface_height * spitch;\n                    const u8 *cr = src + surface_height * spitch;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n                         YCBCR_TO_RGB( *y++, *cb++, *cr++, dst[n3+0], dst[n3+1], dst[n3+2] );\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          default:\n               D_ONCE( \"unsupported format\" );\n     }\n}\n\nvoid\ndfb_convert_to_a8( DFBSurfacePixelFormat  format,\n                   const void            *src,\n                   int                    spitch,\n                   int                    surface_height,\n                   u8                    *dst,\n                   int                    dpitch,\n                   int                    width,\n                   int                    height )\n{\n     int n;\n\n     D_DEBUG_AT( GFX_Converter, \"%s()\\n\", __FUNCTION__ );\n\n     switch (format) {\n          case DSPF_A8:\n               while (height--) {\n                    const u8 *src8 = src;\n\n                    direct_memcpy( dst, src8, width );\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_AiRGB:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (n = 0; n < width; n++) {\n                         dst[n] = ~(src32[n] >> 24);\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_ARGB:\n          case DSPF_ABGR:\n          case DSPF_AYUV:\n          case DSPF_AVYU:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (n = 0; n < width; n++) {\n                         dst[n] = src32[n] >> 24;\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_ARGB1555:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (n = 0; n < width; n++) {\n                         dst[n] = (src16[n] & 0x8000) ? 0xff : 0x00;\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_ARGB2554:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (n = 0; n < width; n++) {\n                         switch (src16[n] >> 14) {\n                              case 0:\n                                   dst[n] = 0x00;\n                                   break;\n                              case 1:\n                                   dst[n] = 0x55;\n                                   break;\n                              case 2:\n                                   dst[n] = 0xaa;\n                                   break;\n                              case 3:\n                                   dst[n] = 0xff;\n                                   break;\n                         }\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_ARGB4444:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (n = 0; n < width; n++) {\n                         dst[n]  = src16[n] >> 12;\n                         dst[n] |= dst[n] << 4;\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_RGBA4444:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (n = 0; n < width; n++) {\n                         dst[n] = EXPAND_4to8( src16[n] & 0xf );\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_RGBA5551:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (n = 0; n < width; n++) {\n                         dst[n] = EXPAND_1to8( src16[n] & 0x1 );\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_ARGB8565:\n               while (height--) {\n                    const u8 *src8 = src;\n                    int       n3;\n\n                    for (n = 0, n3 = 0; n < width; n++, n3 += 3) {\n#ifdef WORDS_BIGENDIAN\n                         dst[n] = src8[n3+0];\n#else\n                         dst[n] = src8[n3+2];\n#endif\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_RGBAF88871:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (n = 0; n < width; n++) {\n                         dst[n] = EXPAND_7to8( (src32[n] & 0x000000fe) >> 1 );\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          default:\n               D_ONCE( \"unsupported format\" );\n     }\n}\n\nvoid\ndfb_convert_to_a4( DFBSurfacePixelFormat  format,\n                   const void            *src,\n                   int                    spitch,\n                   int                    surface_height,\n                   u8                    *dst,\n                   int                    dpitch,\n                   int                    width,\n                   int                    height )\n{\n     const int w2 = width / 2;\n     int       x, n;\n\n     D_DEBUG_AT( GFX_Converter, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSUME( (width & 1) == 0 );\n\n     switch (format) {\n          case DSPF_A8:\n               while (height--) {\n                    const u8 *src8 = src;\n\n                    for (x = 0, n = 0; x < w2; x++, n += 2)\n                         dst[x] = (src8[n] & 0xf0) | ((src8[n+1] & 0xf0) >> 4);\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_ARGB4444:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0, n = 0; x < w2; x++, n += 2)\n                         dst[x] = ((src16[n] & 0xf000) >> 8) | (src16[n+1] >> 12);\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_RGBA4444:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0, n = 0; x < w2; x++, n += 2)\n                         dst[x] = ((src16[n] & 0x000f) << 4) | (src16[n+1] & 0x000f);\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_ARGB1555:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0, n = 0; x < w2; x++, n += 2)\n                         dst[x] = ((src16[n] & 0x8000) ? 0xf0 : 0) | ((src16[n+1] & 0x8000) ? 0x0f : 0);\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_ARGB:\n          case DSPF_ABGR:\n          case DSPF_AYUV:\n          case DSPF_AVYU:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0, n = 0; x < w2; x++, n += 2)\n                         dst[x] = ((src32[n] & 0xf0000000) >> 24) | ((src32[n+1] & 0xf0000000) >> 28);\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_RGBA5551:\n               while (height--) {\n                    const u16 *src16 = src;\n\n                    for (x = 0, n = 0; x < w2; x++, n += 2)\n                         dst[x] = ((src16[n] & 0x1) ? 0xf0 : 0) | ((src16[n+1] & 0x1) ? 0x0f : 0);\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_ARGB8565:\n               while (height--) {\n                    const u8 *src8 = src;\n\n                    for (x = 0, n = 0; x < w2; x++, n += 6) {\n#ifdef WORDS_BIGENDIAN\n                         dst[x] = (src8[n+0] & 0xf0) | (src8[n+3] & 0xf0 >> 4);\n#else\n                         dst[x] = (src8[n+2] & 0xf0) | (src8[n+5] & 0xf0 >> 4);\n#endif\n                    }\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          case DSPF_RGBAF88871:\n               while (height--) {\n                    const u32 *src32 = src;\n\n                    for (x = 0, n = 0; x < w2; x++, n += 2)\n                         dst[x] = (src32[n] & 0x000000f0) | ((src32[n+1] & 0x000000f0) >> 4);\n\n                    src += spitch;\n                    dst += dpitch;\n               }\n               break;\n\n          default:\n               if (DFB_PIXELFORMAT_HAS_ALPHA( format ))\n                    D_ONCE( \"unsupported format\" );\n     }\n}\n"
  },
  {
    "path": "src/gfx/convert.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __GFX__CONVERT_H__\n#define __GFX__CONVERT_H__\n\n#include <core/coretypes.h>\n#include <direct/util.h>\n\n/**********************************************************************************************************************/\n\n/* pixel packing */\n\n#define PIXEL_RGB332(r,g,b)       (  ((r) & 0xe0)       |    \\\n                                    (((g) & 0xe0) >> 3) |    \\\n                                    (((b) & 0xc0) >> 6) )\n\n#define PIXEL_ARGB1555(a,r,g,b)   ( (((a) & 0x80) << 8) |    \\\n                                    (((r) & 0xf8) << 7) |    \\\n                                    (((g) & 0xf8) << 2) |    \\\n                                    (((b) & 0xf8) >> 3) )\n\n#define PIXEL_RGBA5551(a,r,g,b)   ( (((a) & 0x80) >> 7) |    \\\n                                    (((r) & 0xf8) << 8) |    \\\n                                    (((g) & 0xf8) << 3) |    \\\n                                    (((b) & 0xf8) >> 2) )\n\n#define PIXEL_RGB555(r,g,b)       ( (((r) & 0xf8) << 7) |    \\\n                                    (((g) & 0xf8) << 2) |    \\\n                                    (((b) & 0xf8) >> 3) )\n\n#define PIXEL_BGR555(r,g,b)       ( (((b) & 0xf8) << 7) |    \\\n                                    (((g) & 0xf8) << 2) |    \\\n                                    (((r) & 0xf8) >> 3) )\n\n#define PIXEL_ARGB2554(a,r,g,b)   ( (((a) & 0xc0) << 8) |    \\\n                                    (((r) & 0xf8) << 6) |    \\\n                                    (((g) & 0xf8) << 1) |    \\\n                                    (((b) & 0xf0) >> 4) )\n\n#define PIXEL_ARGB4444(a,r,g,b)   ( (((a) & 0xf0) << 8) |    \\\n                                    (((r) & 0xf0) << 4) |    \\\n                                     ((g) & 0xf0)       |    \\\n                                    (((b) & 0xf0) >> 4) )\n\n#define PIXEL_RGBA4444(a,r,g,b)   ( (((r) & 0xf0) << 8) |    \\\n                                    (((g) & 0xf0) << 4) |    \\\n                                     ((b) & 0xf0)       |    \\\n                                    (((a) & 0xf0) >> 4) )\n\n#define PIXEL_RGB444(r,g,b)       ( (((r) & 0xf0) << 4) |    \\\n                                     ((g) & 0xf0)       |    \\\n                                    (((b) & 0xf0) >> 4) )\n\n#define PIXEL_RGB16(r,g,b)        ( (((r) & 0xf8) << 8) |    \\\n                                    (((g) & 0xfc) << 3) |    \\\n                                    (((b) & 0xf8) >> 3) )\n\n#define PIXEL_RGB18(r,g,b)        ( (((r) & 0xfc) << 10) |   \\\n                                    (((g) & 0xfc) <<  4) |   \\\n                                    (((b) & 0xfc) >>  2) )\n\n#define PIXEL_RGB32(r,g,b)        ( (0xff << 24) |           \\\n                                    ((r)  << 16) |           \\\n                                    ((g)  <<  8) |           \\\n                                     (b) )\n\n#define PIXEL_ARGB(a,r,g,b)       ( ((a) << 24) |            \\\n                                    ((r) << 16) |            \\\n                                    ((g) <<  8) |            \\\n                                     (b) )\n\n#define PIXEL_ABGR(a,r,g,b)       ( ((a) << 24) |            \\\n                                    ((b) << 16) |            \\\n                                    ((g) <<  8) |            \\\n                                     (r) )\n\n#define PIXEL_ARGB8565(a,r,g,b)   ( ((a) << 16) |            \\\n                                    PIXEL_RGB16( r, g, b ) )\n\n#define PIXEL_ARGB1666(a,r,g,b)   ( (((a) & 0x80) << 11) |   \\\n                                    (((r) & 0xfc) << 10) |   \\\n                                    (((g) & 0xfc) <<  4) |   \\\n                                    (((b) & 0xfc) >>  2) )\n\n#define PIXEL_ARGB6666(a,r,g,b)   ( (((a) & 0xfc) << 16) |   \\\n                                    (((r) & 0xfc) << 10) |   \\\n                                    (((g) & 0xfc) <<  4) |   \\\n                                    (((b) & 0xfc) >>  2) )\n\n#define PIXEL_AYUV(a,y,u,v)       ( ((a) << 24) |            \\\n                                    ((y) << 16) |            \\\n                                    ((u) <<  8) |            \\\n                                     (v) )\n\n#define PIXEL_AVYU(a,y,u,v)       ( ((a) << 24) |            \\\n                                    ((v) << 16) |            \\\n                                    ((y) <<  8) |            \\\n                                     (u) )\n\n#define PIXEL_AiRGB(a,r,g,b)      ( (((a) ^ 0xff) << 24) |   \\\n                                     ((r) << 16) |           \\\n                                     ((g) <<  8) |           \\\n                                      (b) )\n\n#define PIXEL_RGBAF88871(a,r,g,b) ( ((r) << 24) |            \\\n                                    ((g) << 16) |            \\\n                                    ((b) <<  8) |            \\\n                                    ((a) & ~1 ) )\n\n#define PIXEL_YUY2_BE(y,u,v)      ( ((u) << 24) |            \\\n                                    ((y) << 16) |            \\\n                                    ((v) <<  8) |            \\\n                                     (y) )\n\n#define PIXEL_UYVY_BE(y,u,v)      ( ((y) << 24) |            \\\n                                    ((u) << 16) |            \\\n                                    ((y) <<  8) |            \\\n                                     (v) )\n\n#define PIXEL_YUY2_LE(y,u,v)      ( ((v) << 24) |            \\\n                                    ((y) << 16) |            \\\n                                    ((u) <<  8) |            \\\n                                     (y) )\n\n#define PIXEL_UYVY_LE(y,u,v)      ( ((y) << 24) |            \\\n                                    ((v) << 16) |            \\\n                                    ((y) <<  8) |            \\\n                                     (u) )\n\n#define PIXEL_VYU(y,u,v)          ( ((v) << 16) |            \\\n                                    ((y) <<  8) |            \\\n                                     (u) )\n\n/* packed pixel conversions */\n\n#define ARGB1555_TO_RGB332(pixel)   ( (((pixel) & 0x7000) >> 7) |             \\\n                                      (((pixel) & 0x0380) >> 5) |             \\\n                                      (((pixel) & 0x0018) >> 3) )\n\n#define ARGB1555_TO_ARGB2554(pixel) (  ((pixel) & 0x8000) |                   \\\n                                      (((pixel) & 0x7fff) >> 1) )\n\n#define ARGB1555_TO_ARGB4444(pixel) ( (((pixel) & 0x8000) ? 0xf000 : 0 ) |    \\\n                                      (((pixel) & 0x7800) >> 3) |             \\\n                                      (((pixel) & 0x03c0) >> 2) |             \\\n                                      (((pixel) & 0x0018) >> 1) )\n\n#define ARGB1555_TO_RGBA4444(pixel) ( (((pixel) & 0x8000) ? 0x000f : 0 ) |    \\\n                                      (((pixel) & 0x7800) << 1) |             \\\n                                      (((pixel) & 0x03c0) << 2) |             \\\n                                      (((pixel) & 0x0018) << 3) )\n\n#define ARGB1555_TO_RGB16(pixel)    ( (((pixel) & 0x7c00) << 1) |             \\\n                                      (((pixel) & 0x03e0) << 1) |             \\\n                                       ((pixel) & 0x001f) )\n\n#define ARGB1555_TO_ARGB8565(pixel) ( (((pixel) & 0x8000) ? 0x00ff0000 : 0) | \\\n                                      ARGB1555_TO_RGB16( pixel ) )\n\n#define ARGB1555_TO_RGB32(pixel)    ( (((pixel) & 0x7c00) << 9) |             \\\n                                      (((pixel) & 0x03e0) << 6) |             \\\n                                      (((pixel) & 0x001f) << 3) )\n\n#define ARGB1555_TO_ARGB(pixel)     ( (((pixel) & 0x8000) ? 0xff000000 : 0) | \\\n                                      (((pixel) & 0x7c00) << 9) |             \\\n                                      (((pixel) & 0x03e0) << 6) |             \\\n                                      (((pixel) & 0x001f) << 3) )\n\n#define ARGB1555_TO_RGB555(pixel)   ( (((pixel) & 0x7c00) << 9) |             \\\n                                      (((pixel) & 0x03e0) << 6) |             \\\n                                      (((pixel) & 0x001f) << 3) )\n\n#define ARGB1555_TO_RGB444(pixel)   ( (((pixel) & 0x7800) >> 3) |             \\\n                                      (((pixel) & 0x03c0) >> 2) |             \\\n                                      (((pixel) & 0x001e) >> 1) )\n\n/* xRGB to xxRRGGBB, so xRxx left 3, xRGx left 2, xxGB left 1, xxxB */\n#define ARGB4444_TO_RGB32(pixel)    ( (((pixel) & 0x0f00) << 12) |            \\\n                                      (((pixel) & 0x0ff0) <<  8) |            \\\n                                      (((pixel) & 0x00ff) <<  4) |            \\\n                                       ((pixel) & 0x000f) )\n\n/* RGBx to xxRRGGBB, so Rxxx left 2, RGxx left 1, xGBx, xxBx right 1 */\n#define RGBA4444_TO_RGB32(pixel)    ( (((pixel) & 0xf000) << 8) |             \\\n                                      (((pixel) & 0xff00) << 4) |             \\\n                                       ((pixel) & 0x0ff0)       |             \\\n                                      (((pixel) & 0x00f0) >> 4) )\n\n/* ARGB to AARRGGBB, so Axxx left 4, ARxx left 3, xRGx left 2, xxGB left 1, xxxB */\n#define ARGB4444_TO_ARGB(pixel)     ( (((pixel) & 0xf000) << 16) |            \\\n                                      (((pixel) & 0xff00) << 12) |            \\\n                                      (((pixel) & 0x0ff0) <<  8) |            \\\n                                      (((pixel) & 0x00ff) <<  4) |            \\\n                                       ((pixel) & 0x000f) )\n\n/* RGBA to AARRGGBB, so Rxxx left 2, RGxx left 1, xGBx, xxBx right 1, A to the left */\n#define RGBA4444_TO_ARGB(pixel)     ( (((pixel) & 0x000f) << 28) |            \\\n                                      (((pixel) & 0x000f) << 24) |            \\\n                                      (((pixel) & 0xf000) <<  8) |            \\\n                                      (((pixel) & 0xff00) <<  4) |            \\\n                                       ((pixel) & 0x0ff0)        |            \\\n                                      (((pixel) & 0x00f0) >>  4) )\n\n#define RGB16_TO_RGB332(pixel)      ( (((pixel) & 0xe000) >> 8) |             \\\n                                      (((pixel) & 0x0700) >> 6) |             \\\n                                      (((pixel) & 0x0018) >> 3) )\n\n#define RGB16_TO_ARGB1555(pixel)    ( 0x8000 |                                \\\n                                      (((pixel) & 0xf800) >> 1) |             \\\n                                      (((pixel) & 0x07c0) >> 1) |             \\\n                                       ((pixel) & 0x001f) )\n\n#define RGB16_TO_ARGB2554(pixel)    ( 0xc000 |                                \\\n                                      (((pixel) & 0xf800) >> 2) |             \\\n                                      (((pixel) & 0x07c0) >> 2) |             \\\n                                      (((pixel) & 0x001f) >> 1) )\n\n#define RGB16_TO_ARGB4444(pixel)    ( 0xf000 |                                \\\n                                      (((pixel) & 0xf000) >> 4) |             \\\n                                      (((pixel) & 0x0780) >> 3) |             \\\n                                      (((pixel) & 0x001e) >> 1) )\n\n#define RGB16_TO_RGBA4444(pixel)    ( 0x000f |                                \\\n                                       ((pixel) & 0xf000)       |             \\\n                                      (((pixel) & 0x0780) << 1) |             \\\n                                      (((pixel) & 0x001e) << 3) )\n\n#define RGB16_TO_ARGB8565(pixel)    ( 0xff0000 |                              \\\n                                      ((pixel) & 0xffff) )\n\n#define RGB16_TO_RGB32(pixel)       ( (((pixel) & 0xf800) << 8) |             \\\n                                      (((pixel) & 0x07e0) << 5) |             \\\n                                      (((pixel) & 0x001f) << 3) )\n\n#define RGB16_TO_ARGB(pixel)        ( 0xff000000 |                            \\\n                                      (((pixel) & 0xf800) << 8) |             \\\n                                      (((pixel) & 0x07e0) << 5) |             \\\n                                      (((pixel) & 0x001f) << 3) )\n\n#define RGB16_TO_RGB555(pixel)      ( (((pixel) & 0xf800) >> 1) |             \\\n                                      (((pixel) & 0x07c0) >> 1) |             \\\n                                       ((pixel) & 0x001f) )\n\n#define RGB16_TO_BGR555(pixel)      ( (((pixel) & 0xf800) >> 12) |            \\\n                                      (((pixel) & 0x07c0) >>  1) |            \\\n                                      (((pixel) & 0x001f) << 10 ) )\n\n#define RGB16_TO_RGB444(pixel)      ( (((pixel) & 0xf000) >> 4) |             \\\n                                      (((pixel) & 0x0780) >> 3) |             \\\n                                      (((pixel) & 0x001f) >> 1) )\n\n#define ARGB8565_TO_RGB332(pixel)   ( RGB16_TO_RGB332( pixel ) )\n\n#define ARGB8565_TO_ARGB1555(pixel) ( (((pixel) & 0x800000) >> 16) |          \\\n                                      (((pixel) & 0x00f800) >>  1) |          \\\n                                      (((pixel) & 0x0007c0) >>  1) |          \\\n                                       ((pixel) & 0x00001f) )\n\n#define ARGB8565_TO_ARGB2554(pixel) ( (((pixel) & 0xc00000) >> 16) |          \\\n                                      (((pixel) & 0x00f800) >>  2) |          \\\n                                      (((pixel) & 0x0007c0) >>  2) |          \\\n                                      (((pixel) & 0x00001f) >>  1) )\n\n#define ARGB8565_TO_ARGB4444(pixel) ( (((pixel) & 0xf00000) >> 16) |          \\\n                                      (((pixel) & 0x00f000) >>  4) |          \\\n                                      (((pixel) & 0x000780) >>  3) |          \\\n                                      (((pixel) & 0x00001f) >>  1) )\n\n#define ARGB8565_TO_RGB16(pixel)    ( (pixel) & 0xffff )\n\n#define ARGB8565_TO_RGB32(pixel)    ( RGB16_TO_RGB32( pixel ) )\n\n#define ARGB8565_TO_ARGB(pixel)     ( (((pixel) & 0xff0000) << 8) |           \\\n                                      (((pixel) & 0x00f800) << 8) |           \\\n                                      (((pixel) & 0x0007e0) << 5) |           \\\n                                      (((pixel) & 0x00001f) << 3) )\n\n#define RGB18_TO_ARGB(pixel)        ( 0xff000000 |                            \\\n                                      (((pixel) & 0xfc00) << 10) |            \\\n                                      (((pixel) & 0x3f00) <<  4) |            \\\n                                      (((pixel) & 0x00fc) <<  2) )\n\n#define RGB32_TO_ARGB1555(pixel)    ( 0x8000 |                                \\\n                                      (((pixel) & 0xf80000) >> 9) |           \\\n                                      (((pixel) & 0x00f800) >> 6) |           \\\n                                      (((pixel) & 0x0000f8) >> 3) )\n\n#define RGB32_TO_ARGB2554(pixel)    ( 0xc000 |                                \\\n                                      (((pixel) & 0xf80000) >> 10) |          \\\n                                      (((pixel) & 0x00f800) >>  7) |          \\\n                                      (((pixel) & 0x0000f0) >>  4) )\n\n#define RGB32_TO_ARGB4444(pixel)    ( 0xf000 |                                \\\n                                      (((pixel) & 0xf00000) >> 12) |          \\\n                                      (((pixel) & 0x00f000) >>  8) |          \\\n                                      (((pixel) & 0x0000f0) >>  4) )\n\n#define RGB32_TO_RGBA4444(pixel)    ( 0x000f |                                \\\n                                      (((pixel) & 0xf00000) >> 8) |           \\\n                                      (((pixel) & 0x00f000) >> 4) |           \\\n                                       ((pixel) & 0x0000f0) )\n\n#define RGB32_TO_ARGB8565(pixel)    ( 0xff0000 | \\\n                                      (((pixel) & 0xf80000) >> 8) |           \\\n                                      (((pixel) & 0x00fc00) >> 5) |           \\\n                                      (((pixel) & 0x0000f8) >> 3) )\n\n#define RGB32_TO_ARGB1555(pixel)    ( 0x8000 | \\\n                                      (((pixel) & 0xf80000) >> 9) |           \\\n                                      (((pixel) & 0x00f800) >> 6) |           \\\n                                      (((pixel) & 0x0000f8) >> 3) )\n\n#define RGB32_TO_ARGB(pixel)        ( 0xff000000 | (pixel) )\n\n#define ARGB_TO_RGB332(pixel)       ( (((pixel) & 0x00e00000) >> 16) |        \\\n                                      (((pixel) & 0x0000e000) >> 11) |        \\\n                                      (((pixel) & 0x000000c0) >>  6) )\n\n#define ARGB_TO_ARGB1555(pixel)     ( (((pixel) & 0x80000000) >> 16) |        \\\n                                      (((pixel) & 0x00f80000) >>  9) |        \\\n                                      (((pixel) & 0x0000f800) >>  6) |        \\\n                                      (((pixel) & 0x000000f8) >>  3) )\n\n#define ARGB_TO_RGBA5551(pixel)     ( (((pixel) & 0x80000000) >> 31) |        \\\n                                      (((pixel) & 0x00f80000) >>  8) |        \\\n                                      (((pixel) & 0x0000f800) >>  5) |        \\\n                                      (((pixel) & 0x000000f8) >>  2) )\n\n#define ARGB_TO_ARGB2554(pixel)     ( (((pixel) & 0xc0000000) >> 16) |        \\\n                                      (((pixel) & 0x00f80000) >> 10) |        \\\n                                      (((pixel) & 0x0000f800) >>  7) |        \\\n                                      (((pixel) & 0x000000f0) >>  4) )\n\n#define ARGB_TO_ARGB4444(pixel)     ( (((pixel) & 0xf0000000) >> 16) |        \\\n                                      (((pixel) & 0x00f00000) >> 12) |        \\\n                                      (((pixel) & 0x0000f000) >>  8) |        \\\n                                      (((pixel) & 0x000000f0) >>  4) )\n\n#define ARGB_TO_RGBA4444(pixel)     ( (((pixel) & 0xf0000000) >> 28) |        \\\n                                      (((pixel) & 0x00f00000) >>  8) |        \\\n                                      (((pixel) & 0x0000f000) >>  4) |        \\\n                                      (((pixel) & 0x000000f0)      ) )\n\n#define ARGB_TO_ARGB1666(pixel)     ( (((pixel) & 0x80000000) >>  8) |        \\\n                                      (((pixel) & 0x00fc0000) >>  6) |        \\\n                                      (((pixel) & 0x0000fc00) >>  4) |        \\\n                                      (((pixel) & 0x000000fc) >>  2) )\n\n#define ARGB_TO_ARGB6666(pixel)     ( (((pixel) & 0xfc000000) >>  8) |        \\\n                                      (((pixel) & 0x00fc0000) >>  6) |        \\\n                                      (((pixel) & 0x0000fc00) >>  4) |        \\\n                                      (((pixel) & 0x000000fc) >>  2) )\n\n#define ARGB_TO_ARGB8565(pixel)     ( (((pixel) & 0xff000000) >> 8) |         \\\n                                      (((pixel) & 0x00f80000) >> 8) |         \\\n                                      (((pixel) & 0x0000fc00) >> 5) |         \\\n                                      (((pixel) & 0x000000f8) >> 3) )\n\n#define ARGB_TO_RGB18(pixel)        ( (((pixel) & 0x00fc0000) >> 6) |         \\\n                                      (((pixel) & 0x0000fc00) >> 4) |         \\\n                                      (((pixel) & 0x000000fc) >> 2) )\n\n#define ARGB_TO_RGB16(pixel)        ( (((pixel) & 0x00f80000) >> 8) |         \\\n                                      (((pixel) & 0x0000fc00) >> 5) |         \\\n                                      (((pixel) & 0x000000f8) >> 3) )\n\n#define ARGB_TO_RGB444(pixel)       ( (((pixel) & 0x00f00000) >> 12) |        \\\n                                      (((pixel) & 0x0000f000) >>  8) |        \\\n                                      (((pixel) & 0x000000f0) >>  4) )\n\n#define ARGB_TO_RGB555(pixel)       ( (((pixel) & 0x00f80000) >> 9) |         \\\n                                      (((pixel) & 0x0000f800) >> 6) |         \\\n                                      (((pixel) & 0x000000f8) >> 3) )\n\n#define ARGB_TO_BGR555(pixel)       ( (((pixel) & 0x00f80000) >> 19) |        \\\n                                      (((pixel) & 0x0000f800) >>  6) |        \\\n                                      (((pixel) & 0x000000f8) <<  7) )\n\n#define ARGB_TO_ABGR(pixel)         (  ((pixel) & 0xff00ff00) |               \\\n                                      (((pixel) & 0x000000ff) << 16) |        \\\n                                      (((pixel) & 0x00ff0000) >> 16) )\n\n#define ARGB_TO_RGBAF88871(pixel)   ( (((pixel) & 0x00ffffff) <<  8 ) |       \\\n                                      (((pixel) & 0xfe000000) >> 24) )\n\n/* RGB <-> YCbCr conversion */\n\n#define YCBCR_TO_RGB_BT601(y,cb,cr,r,g,b)                               \\\ndo {                                                                    \\\n     int _y  = (y)  -  16;                                              \\\n     int _cb = (cb) - 128;                                              \\\n     int _cr = (cr) - 128;                                              \\\n                                                                        \\\n     int _r = (298 * _y             + 409 * _cr + 128) >> 8;            \\\n     int _g = (298 * _y - 100 * _cb - 208 * _cr + 128) >> 8;            \\\n     int _b = (298 * _y + 516 * _cb             + 128) >> 8;            \\\n                                                                        \\\n     (r) = CLAMP( _r, 0, 255 );                                         \\\n     (g) = CLAMP( _g, 0, 255 );                                         \\\n     (b) = CLAMP( _b, 0, 255 );                                         \\\n} while (0)\n\n#define RGB_TO_YCBCR_BT601(r,g,b,y,cb,cr)                               \\\ndo {                                                                    \\\n     int _r = (r), _g = (g), _b = (b);                                  \\\n                                                                        \\\n     (y)  = (   66 * _r + 129 * _g +  25 * _b  +  16 * 256 + 128) >> 8; \\\n     (cb) = ( - 38 * _r -  74 * _g + 112 * _b  + 128 * 256 + 128) >> 8; \\\n     (cr) = (  112 * _r -  94 * _g -  18 * _b  + 128 * 256 + 128) >> 8; \\\n} while (0)\n\n#define YCBCR_TO_RGB_BT709(y,cb,cr,r,g,b)                               \\\ndo {                                                                    \\\n     int _y  = (y)  -  16;                                              \\\n     int _cb = (cb) - 128;                                              \\\n     int _cr = (cr) - 128;                                              \\\n                                                                        \\\n     int _r = (298 * _y             + 459 * _cr + 128) >> 8;            \\\n     int _g = (298 * _y -  55 * _cb - 136 * _cr + 128) >> 8;            \\\n     int _b = (298 * _y + 541 * _cb             + 128) >> 8;            \\\n                                                                        \\\n     (r) = CLAMP( _r, 0, 255 );                                         \\\n     (g) = CLAMP( _g, 0, 255 );                                         \\\n     (b) = CLAMP( _b, 0, 255 );                                         \\\n} while (0)\n\n#define RGB_TO_YCBCR_BT709(r,g,b,y,cb,cr)                               \\\ndo {                                                                    \\\n     int _r = (r), _g = (g), _b = (b);                                  \\\n                                                                        \\\n     (y)  = (   47 * _r + 157 * _g +  16 * _b  +  16 * 256 + 128) >> 8; \\\n     (cb) = ( - 26 * _r -  87 * _g + 112 * _b  + 128 * 256 + 128) >> 8; \\\n     (cr) = (  112 * _r - 102 * _g -  10 * _b  + 128 * 256 + 128) >> 8; \\\n} while (0)\n\n#define YCBCR_TO_RGB_BT2020(y,cb,cr,r,g,b)                              \\\ndo {                                                                    \\\n     int _y  = (y)  -  16;                                              \\\n     int _cb = (cb) - 128;                                              \\\n     int _cr = (cr) - 128;                                              \\\n                                                                        \\\n     int _r = (298 * _y             + 430 * _cr + 128) >> 8;            \\\n     int _g = (298 * _y -  48 * _cb - 167 * _cr + 128) >> 8;            \\\n     int _b = (298 * _y + 548 * _cb             + 128) >> 8;            \\\n                                                                        \\\n     (r) = CLAMP( _r, 0, 255 );                                         \\\n     (g) = CLAMP( _g, 0, 255 );                                         \\\n     (b) = CLAMP( _b, 0, 255 );                                         \\\n} while (0)\n\n#define RGB_TO_YCBCR_BT2020(r,g,b,y,cb,cr)                              \\\ndo {                                                                    \\\n     int _r = (r), _g = (g), _b = (b);                                  \\\n                                                                        \\\n     (y)  = (   58 * _r + 149 * _g +  13 * _b  +  16 * 256 + 128) >> 8; \\\n     (cb) = ( - 31 * _r -  81 * _g + 112 * _b  + 128 * 256 + 128) >> 8; \\\n     (cr) = (  112 * _r - 103 * _g -   9 * _b  + 128 * 256 + 128) >> 8; \\\n} while (0)\n\n/**********************************************************************************************************************/\n\nvoid          dfb_pixel_to_color     ( DFBSurfacePixelFormat  format,\n                                       DFBSurfaceColorSpace   colorspace,\n                                       unsigned long          pixel,\n                                       DFBColor              *ret_color );\n\nunsigned long dfb_pixel_from_color   ( DFBSurfacePixelFormat  format,\n                                       DFBSurfaceColorSpace   colorspace,\n                                       const DFBColor        *color );\n\nvoid          dfb_pixel_to_components( DFBSurfacePixelFormat  format,\n                                       unsigned long          pixel,\n                                       u8                     *a,\n                                       u8                     *c2,\n                                       u8                     *c1,\n                                       u8                     *c0 );\n\nvoid          dfb_convert_to_rgb16   ( DFBSurfacePixelFormat  format,\n                                       DFBSurfaceColorSpace   colorspace,\n                                       const void            *src,\n                                       int                    spitch,\n                                       const void            *src_cb,\n                                       int                    scbpitch,\n                                       const void            *src_cr,\n                                       int                    scrpitch,\n                                       int                    surface_height,\n                                       u16                   *dst,\n                                       int                    dpitch,\n                                       int                    width,\n                                       int                    height );\n\nvoid          dfb_convert_to_rgb555  ( DFBSurfacePixelFormat  format,\n                                       DFBSurfaceColorSpace   colorspace,\n                                       const void            *src,\n                                       int                    spitch,\n                                       const void            *src_cb,\n                                       int                    scbpitch,\n                                       const void            *src_cr,\n                                       int                    scrpitch,\n                                       int                    surface_height,\n                                       u16                   *dst,\n                                       int                    dpitch,\n                                       int                    width,\n                                       int                    height );\n\nvoid          dfb_convert_to_rgb32   ( DFBSurfacePixelFormat  format,\n                                       DFBSurfaceColorSpace   colorspace,\n                                       const void            *src,\n                                       int                    spitch,\n                                       const void            *src_cb,\n                                       int                    scbpitch,\n                                       const void            *src_cr,\n                                       int                    scrpitch,\n                                       int                    surface_height,\n                                       u32                   *dst,\n                                       int                    dpitch,\n                                       int                    width,\n                                       int                    height );\n\nvoid          dfb_convert_to_argb    ( DFBSurfacePixelFormat  format,\n                                       DFBSurfaceColorSpace   colorspace,\n                                       const void            *src,\n                                       int                    spitch,\n                                       const void            *src_cb,\n                                       int                    scbpitch,\n                                       const void            *src_cr,\n                                       int                    scrpitch,\n                                       int                    surface_height,\n                                       u32                   *dst,\n                                       int                    dpitch,\n                                       int                    width,\n                                       int                    height );\n\nvoid          dfb_convert_to_rgb24   ( DFBSurfacePixelFormat  format,\n                                       DFBSurfaceColorSpace   colorspace,\n                                       const void            *src,\n                                       int                    spitch,\n                                       const void            *src_cb,\n                                       int                    scbpitch,\n                                       const void            *src_cr,\n                                       int                    scrpitch,\n                                       int                    surface_height,\n                                       u8                    *dst,\n                                       int                    dpitch,\n                                       int                    width,\n                                       int                    height );\n\nvoid          dfb_convert_to_a8      ( DFBSurfacePixelFormat  format,\n                                       const void            *src,\n                                       int                    spitch,\n                                       int                    surface_height,\n                                       u8                    *dst,\n                                       int                    dpitch,\n                                       int                    width,\n                                       int                    height );\n\nvoid          dfb_convert_to_a4      ( DFBSurfacePixelFormat  format,\n                                       const void            *src,\n                                       int                    spitch,\n                                       int                    surface_height,\n                                       u8                    *dst,\n                                       int                    dpitch,\n                                       int                    width,\n                                       int                    height );\n\n/**********************************************************************************************************************/\n\nstatic __inline__ u32\ndfb_color_to_argb( const DFBColor *color )\n{\n     return (color->a << 24) | (color->r << 16) | (color->g << 8) | color->b;\n}\n\nstatic __inline__ void\ndfb_argb_to_rgb332( const u32 *src,\n                    u8        *dst,\n                    int        len )\n{\n     int i;\n\n     for (i = 0; i < len; i++) {\n          u32 argb = src[i];\n\n          dst[i] = ARGB_TO_RGB332( argb );\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_argb1555( const u32 *src,\n                      u16       *dst,\n                      int        len )\n{\n     int i;\n\n     for (i = 0; i < len; i++) {\n          u32 argb = src[i];\n\n          dst[i] = ARGB_TO_ARGB1555( argb );\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_rgba5551( const u32 *src,\n                      u16       *dst,\n                      int        len )\n{\n     int i;\n\n     for (i = 0; i < len; i++) {\n          u32 argb = src[i];\n\n          dst[i] = ARGB_TO_RGBA5551( argb );\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_argb2554( const u32 *src,\n                      u16       *dst,\n                      int        len )\n{\n     int i;\n\n     for (i = 0; i < len; i++) {\n          u32 argb = src[i];\n\n          dst[i] = ARGB_TO_ARGB2554( argb );\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_argb4444( const u32 *src,\n                      u16       *dst,\n                      int        len )\n{\n     int i;\n\n     for (i = 0; i < len; i++) {\n          u32 argb = src[i];\n\n          dst[i] = ARGB_TO_ARGB4444( argb );\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_rgba4444( const u32 *src,\n                      u16       *dst,\n                      int        len )\n{\n     int i;\n\n     for (i = 0; i < len; i++) {\n          u32 rgba = src[i];\n\n          dst[i] = ARGB_TO_RGBA4444( rgba );\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_argb1666be( const u32 *src,\n                        u8        *dst,\n                        int        len )\n{\n     int i = -1, j = -1;\n\n     while (++i < len) {\n        u32 argb = src[i];\n\n        u32 d = ARGB_TO_ARGB1666( argb );\n\n        dst[++j] = (d >> 16) & 0xff;\n        dst[++j] = (d >>  8) & 0xff;\n        dst[++j] =  d        & 0xff;\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_argb1666le( const u32 *src,\n                        u8        *dst,\n                        int        len )\n{\n     int i = -1, j = -1;\n\n     while (++i < len) {\n        u32 argb = src[i];\n\n        u32 d = ARGB_TO_ARGB1666( argb );\n\n        dst[++j] =  d        & 0xff;\n        dst[++j] = (d >>  8) & 0xff;\n        dst[++j] = (d >> 16) & 0xff;\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_argb6666be( const u32 *src,\n                        u8        *dst,\n                        int        len )\n{\n     int i = -1, j = -1;\n\n     while (++i < len) {\n        u32 argb = src[i];\n\n        u32 d = ARGB_TO_ARGB6666( argb );\n\n        dst[++j] = (d >> 16) & 0xff;\n        dst[++j] = (d >>  8) & 0xff;\n        dst[++j] =  d        & 0xff;\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_argb6666le( const u32 *src,\n                        u8        *dst,\n                        int        len )\n{\n     int i = -1, j = -1;\n\n     while (++i < len) {\n        u32 argb = src[i];\n\n        u32 d = ARGB_TO_ARGB6666( argb );\n\n        dst[++j] =  d        & 0xff;\n        dst[++j] = (d >>  8) & 0xff;\n        dst[++j] = (d >> 16) & 0xff;\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_argb8565be( const u32 *src,\n                        u8        *dst,\n                        int        len )\n{\n     int i = -1, j = -1;\n\n     while (++i < len) {\n        u32 argb = src[i];\n\n        u32 d = ARGB_TO_ARGB8565( argb );\n\n        dst[++j] = (d >> 16) & 0xff;\n        dst[++j] = (d >>  8) & 0xff;\n        dst[++j] =  d        & 0xff;\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_argb8565le( const u32 *src,\n                        u8        *dst,\n                        int        len )\n{\n     int i = -1, j = -1;\n\n     while (++i < len) {\n        u32 argb = src[i];\n\n        u32 d = ARGB_TO_ARGB8565( argb );\n\n        dst[++j] =  d        & 0xff;\n        dst[++j] = (d >>  8) & 0xff;\n        dst[++j] = (d >> 16) & 0xff;\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_rgb18be( const u32 *src,\n                     u8        *dst,\n                     int        len )\n{\n     int i = -1, j = -1;\n\n     while (++i < len) {\n        u32 argb = src[i];\n\n        u32 d = ARGB_TO_RGB18( argb );\n\n        dst[++j] = (d >> 16) & 0xff;\n        dst[++j] = (d >>  8) & 0xff;\n        dst[++j] =  d        & 0xff;\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_rgb18le( const u32 *src,\n                     u8        *dst,\n                     int        len )\n{\n     int i = -1, j = -1;\n\n     while (++i < len) {\n        u32 argb = src[i];\n\n        u32 d = ARGB_TO_RGB18( argb );\n\n        dst[++j] =  d        & 0xff;\n        dst[++j] = (d >>  8) & 0xff;\n        dst[++j] = (d >> 16) & 0xff;\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_rgb16( const u32 *src,\n                   u16       *dst,\n                   int        len )\n{\n     int i;\n\n     for (i = 0; i < len; i++) {\n          u32 argb = src[i];\n\n          dst[i] = ARGB_TO_RGB16( argb );\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_rgb444( const u32 *src,\n                    u16       *dst,\n                    int        len )\n{\n     int i;\n\n     for (i = 0; i < len; i++) {\n          u32 argb = src[i];\n\n          dst[i] = ARGB_TO_RGB444( argb );\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_rgb555( const u32 *src,\n                    u16       *dst,\n                    int        len )\n{\n     int i;\n\n     for (i = 0; i < len; i++) {\n          u32 argb = src[i];\n\n          dst[i] = ARGB_TO_RGB555( argb );\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_bgr555( const u32 *src,\n                    u16       *dst,\n                    int        len )\n{\n     int i;\n\n     for (i = 0; i < len; i++) {\n          u32 argb = src[i];\n\n          dst[i] = ARGB_TO_BGR555( argb );\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_abgr( const u32 *src,\n                  u32       *dst,\n                  int        len )\n{\n     int i;\n\n     for (i = 0; i < len; i++) {\n          u32 argb = src[i];\n\n          dst[i] = ARGB_TO_ABGR( argb );\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_rgbaf88871( const u32 *src,\n                        u32       *dst,\n                        int        len )\n{\n     int i;\n\n     for (i = 0; i < len; i++) {\n          u32 argb = src[i];\n\n          dst[i] = ARGB_TO_RGBAF88871( argb );\n     }\n}\n\nstatic __inline__ void\ndfb_argb_to_a8( const u32 *src,\n                u8        *dst,\n                int        len )\n{\n     int i;\n\n     for (i = 0; i < len; i++)\n          dst[i] = src[i] >> 24;\n}\n\n#endif\n"
  },
  {
    "path": "src/gfx/generic/duffs_device.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DUFFS_DEVICE_H__\n#define __DUFFS_DEVICE_H__\n\n#define DUFF_1()                                           \\\n               case 1:                                     \\\n                    SET_PIXEL( D[0], S[0] );\n\n#define DUFF_2()                                           \\\n               case 3:                                     \\\n                    SET_PIXEL( D[2], S[2] );               \\\n               case 2:                                     \\\n                    SET_PIXEL( D[1], S[1] );               \\\n               DUFF_1()\n\n#define DUFF_3()                                           \\\n               case 7:                                     \\\n                    SET_PIXEL( D[6], S[6] );               \\\n               case 6:                                     \\\n                    SET_PIXEL( D[5], S[5] );               \\\n               case 5:                                     \\\n                    SET_PIXEL( D[4], S[4] );               \\\n               case 4:                                     \\\n                    SET_PIXEL( D[3], S[3] );               \\\n               DUFF_2()\n\n#define DUFF_4()                                           \\\n               case 15:                                    \\\n                    SET_PIXEL( D[14], S[14] );             \\\n               case 14:                                    \\\n                    SET_PIXEL( D[13], S[13] );             \\\n               case 13:                                    \\\n                    SET_PIXEL( D[12], S[12] );             \\\n               case 12:                                    \\\n                    SET_PIXEL( D[11], S[11] );             \\\n               case 11:                                    \\\n                    SET_PIXEL( D[10], S[10] );             \\\n               case 10:                                    \\\n                    SET_PIXEL( D[9], S[9] );               \\\n               case 9:                                     \\\n                    SET_PIXEL( D[8], S[8] );               \\\n               case 8:                                     \\\n                    SET_PIXEL( D[7], S[7] );               \\\n               DUFF_3()\n\n#define SET_PIXEL_DUFFS_DEVICE_N(D,S,w,n)                  \\\ndo {                                                       \\\n     while (w) {                                           \\\n          int l = w & ((1 << n) - 1);                      \\\n          switch (l) {                                     \\\n               default:                                    \\\n                    l = (1 << n);                          \\\n                    SET_PIXEL( D[(1<<n)-1], S[(1<<n)-1] ); \\\n               DUFF_##n()                                  \\\n          }                                                \\\n          D += l;                                          \\\n          S += l;                                          \\\n          w -= l;                                          \\\n     }                                                     \\\n} while (0)\n\n#endif\n"
  },
  {
    "path": "src/gfx/generic/generic.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <config.h>\n#include <core/core.h>\n#include <core/state.h>\n#include <core/palette.h>\n#include <direct/memcpy.h>\n#include <gfx/convert.h>\n#include <gfx/generic/duffs_device.h>\n#include <gfx/generic/generic.h>\n#include <gfx/util.h>\n\n/**********************************************************************************************************************/\n\n/* lookup tables for 2/3bit to 8bit color conversion */\nstatic const u8 lookup3to8[] = { 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff };\nstatic const u8 lookup2to8[] = { 0x00, 0x55, 0xaa, 0xff };\n\n#define EXPAND_1to8(v) ((v) ? 0xff : 0x00)\n#define EXPAND_2to8(v) lookup2to8[v]\n#define EXPAND_3to8(v) lookup3to8[v]\n#define EXPAND_4to8(v) (((v) << 4) |  (v)      )\n#define EXPAND_5to8(v) (((v) << 3) | ((v) >> 2))\n#define EXPAND_6to8(v) (((v) << 2) | ((v) >> 4))\n#define EXPAND_7to8(v) (((v) << 1) | ((v) >> 6))\n\n/**********************************************************************************************************************/\n\n/* ARGB1555 / RGB555 / BGR555 / RGBA5551 */\n#define RGB_MASK 0x7fff\n#define Cop_OP_Aop_PFI(op) Cop_##op##_Aop_15\n#define Bop_PFI_OP_Aop_PFI(op) Bop_15_##op##_Aop\n#include \"template_colorkey_16.h\"\n\n/* RGB16 */\n#define RGB_MASK 0xffff\n#define Cop_OP_Aop_PFI(op) Cop_##op##_Aop_16\n#define Bop_PFI_OP_Aop_PFI(op) Bop_16_##op##_Aop\n#include \"template_colorkey_16.h\"\n\n/* RGB24 / BGR24 / VYU */\n#define RGB_MASK 0xffffff\n#define Cop_OP_Aop_PFI(op) Cop_##op##_Aop_24_24\n#define Bop_PFI_OP_Aop_PFI(op) Bop_24_24_##op##_Aop\n#include \"template_colorkey_24.h\"\n\n/* RGB32 / ARGB / ABGR / AiRGB / AYUV / AVYU */\n#define RGB_MASK 0x00ffffff\n#define Cop_OP_Aop_PFI(op) Cop_##op##_Aop_32\n#define Bop_PFI_OP_Aop_PFI(op) Bop_32_##op##_Aop\n#include \"template_colorkey_32.h\"\n\n/* ARGB2554 */\n#define RGB_MASK 0x3fff\n#define Cop_OP_Aop_PFI(op) Cop_##op##_Aop_14\n#define Bop_PFI_OP_Aop_PFI(op) Bop_14_##op##_Aop\n#include \"template_colorkey_16.h\"\n\n/* ARGB4444 / RGB444 */\n#define RGB_MASK 0x0fff\n#define Cop_OP_Aop_PFI(op) Cop_##op##_Aop_12\n#define Bop_PFI_OP_Aop_PFI(op) Bop_12_##op##_Aop\n#include \"template_colorkey_16.h\"\n\n/* RGBA4444 */\n#define RGB_MASK 0xfff0\n#define Cop_OP_Aop_PFI(op) Cop_##op##_Aop_12vv\n#define Bop_PFI_OP_Aop_PFI(op) Bop_12vv_##op##_Aop\n#include \"template_colorkey_16.h\"\n\n/* ARGB1666 / ARGB6666 / RGB18 */\n#define RGB_MASK 0x03ffff\n#define Cop_OP_Aop_PFI(op) Cop_##op##_Aop_24_18\n#define Bop_PFI_OP_Aop_PFI(op) Bop_24_18_##op##_Aop\n#include \"template_colorkey_24.h\"\n\n/* ARGB8565 */\n#define RGB_MASK 0x00ffff\n#define Cop_OP_Aop_PFI(op) Cop_##op##_Aop_24_16\n#define Bop_PFI_OP_Aop_PFI(op) Bop_24_16_##op##_Aop\n#include \"template_colorkey_24.h\"\n\n/* RGBAF88871 */\n#define RGB_MASK 0xffffff00\n#define Cop_OP_Aop_PFI(op) Cop_##op##_Aop_32_24\n#define Bop_PFI_OP_Aop_PFI(op) Bop_32_24_##op##_Aop\n#include \"template_colorkey_32.h\"\n\n/**********************************************************************************************************************/\n\n/* ARGB1555 */\n#define EXPAND_Ato8(a) EXPAND_1to8( a )\n#define EXPAND_Rto8(r) EXPAND_5to8( r )\n#define EXPAND_Gto8(g) EXPAND_5to8( g )\n#define EXPAND_Bto8(b) EXPAND_5to8( b )\n#define PIXEL_OUT(a,r,g,b) PIXEL_ARGB1555( a, r, g, b )\n#define Sop_PFI_OP_Dacc(op) Sop_argb1555_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_argb1555\n#define A_SHIFT 15\n#define R_SHIFT 10\n#define G_SHIFT 5\n#define B_SHIFT 0\n#define A_MASK 0x8000\n#define R_MASK 0x7c00\n#define G_MASK 0x03e0\n#define B_MASK 0x001f\n#include \"template_acc_16.h\"\n\n/* RGB16 */\n#define EXPAND_Ato8(a) 0xff\n#define EXPAND_Rto8(r) EXPAND_5to8( r )\n#define EXPAND_Gto8(g) EXPAND_6to8( g )\n#define EXPAND_Bto8(b) EXPAND_5to8( b )\n#define PIXEL_OUT(a,r,g,b) PIXEL_RGB16( r, g, b )\n#define Sop_PFI_OP_Dacc(op) Sop_rgb16_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_rgb16\n#define A_SHIFT 0\n#define R_SHIFT 11\n#define G_SHIFT 5\n#define B_SHIFT 0\n#define A_MASK 0\n#define R_MASK 0xf800\n#define G_MASK 0x07e0\n#define B_MASK 0x001f\n#include \"template_acc_16.h\"\n\n/* RGB24 */\n#define EXPAND_Ato8(a) 0xff\n#define EXPAND_Rto8(r) (r)\n#define EXPAND_Gto8(g) (g)\n#define EXPAND_Bto8(b) (b)\n#define PIXEL_OUT(a,r,g,b) PIXEL_RGB32( r, g, b )\n#define Sop_PFI_OP_Dacc(op) Sop_rgb24_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_rgb24\n#define A_SHIFT 0\n#define R_SHIFT 16\n#define G_SHIFT 8\n#define B_SHIFT 0\n#define A_MASK 0\n#define R_MASK 0xff0000\n#define G_MASK 0x00ff00\n#define B_MASK 0x0000ff\n#include \"template_acc_24.h\"\n\n/* BGR24 */\n#define EXPAND_Ato8(a) 0xff\n#define EXPAND_Rto8(r) (r)\n#define EXPAND_Gto8(g) (g)\n#define EXPAND_Bto8(b) (b)\n#define PIXEL_OUT(a,r,g,b) PIXEL_RGB32( b, g, r )\n#define Sop_PFI_OP_Dacc(op) Sop_bgr24_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_bgr24\n#define A_SHIFT 0\n#define B_SHIFT 16\n#define G_SHIFT 8\n#define R_SHIFT 0\n#define A_MASK 0\n#define B_MASK 0xff0000\n#define G_MASK 0x00ff00\n#define R_MASK 0x0000ff\n#include \"template_acc_24.h\"\n\n/* RGB32 */\n#define EXPAND_Ato8(a) 0xff\n#define EXPAND_Rto8(r) (r)\n#define EXPAND_Gto8(g) (g)\n#define EXPAND_Bto8(b) (b)\n#define PIXEL_OUT(a,r,g,b) PIXEL_RGB32( r, g, b )\n#define Sop_PFI_OP_Dacc(op) Sop_rgb32_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_rgb32\n#define A_SHIFT 0\n#define R_SHIFT 16\n#define G_SHIFT 8\n#define B_SHIFT 0\n#define A_MASK 0\n#define R_MASK 0x00ff0000\n#define G_MASK 0x0000ff00\n#define B_MASK 0x000000ff\n#include \"template_acc_32.h\"\n\n/* ARGB */\n#define EXPAND_Ato8(a) (a)\n#define EXPAND_Rto8(r) (r)\n#define EXPAND_Gto8(g) (g)\n#define EXPAND_Bto8(b) (b)\n#define PIXEL_OUT(a,r,g,b) PIXEL_ARGB( a, r, g, b )\n#define Sop_PFI_OP_Dacc(op) Sop_argb_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_argb\n#define A_SHIFT 24\n#define R_SHIFT 16\n#define G_SHIFT 8\n#define B_SHIFT 0\n#define A_MASK 0xff000000\n#define R_MASK 0x00ff0000\n#define G_MASK 0x0000ff00\n#define B_MASK 0x000000ff\n#include \"template_acc_32.h\"\n\n/* ABGR */\n#define EXPAND_Ato8(a) (a)\n#define EXPAND_Rto8(r) (r)\n#define EXPAND_Gto8(g) (g)\n#define EXPAND_Bto8(b) (b)\n#define PIXEL_OUT(a,r,g,b) PIXEL_ABGR( a, r, g, b )\n#define Sop_PFI_OP_Dacc(op) Sop_abgr_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_abgr\n#define A_SHIFT 24\n#define B_SHIFT 16\n#define G_SHIFT 8\n#define R_SHIFT 0\n#define A_MASK 0xff000000\n#define B_MASK 0x00ff0000\n#define G_MASK 0x0000ff00\n#define R_MASK 0x000000ff\n#include \"template_acc_32.h\"\n\n/* AiRGB */\n#define EXPAND_Ato8(a) ((a) ^ 0xff)\n#define EXPAND_Rto8(r) (r)\n#define EXPAND_Gto8(g) (g)\n#define EXPAND_Bto8(b) (b)\n#define PIXEL_OUT(a,r,g,b) PIXEL_AiRGB( a, r, g, b )\n#define Sop_PFI_OP_Dacc(op) Sop_airgb_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_airgb\n#define A_SHIFT 24\n#define R_SHIFT 16\n#define G_SHIFT 8\n#define B_SHIFT 0\n#define A_MASK 0xff000000\n#define R_MASK 0x00ff0000\n#define G_MASK 0x0000ff00\n#define B_MASK 0x000000ff\n#include \"template_acc_32.h\"\n\n/* ARGB2554 */\n#define EXPAND_Ato8(a) EXPAND_2to8( a )\n#define EXPAND_Rto8(r) EXPAND_5to8( r )\n#define EXPAND_Gto8(g) EXPAND_5to8( g )\n#define EXPAND_Bto8(b) EXPAND_4to8( b )\n#define PIXEL_OUT(a,r,g,b) PIXEL_ARGB2554( a, r, g, b )\n#define Sop_PFI_OP_Dacc(op) Sop_argb2554_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_argb2554\n#define A_SHIFT 14\n#define R_SHIFT 9\n#define G_SHIFT 4\n#define B_SHIFT 0\n#define A_MASK 0xc000\n#define R_MASK 0x3e00\n#define G_MASK 0x01f0\n#define B_MASK 0x000f\n#include \"template_acc_16.h\"\n\n/* ARGB4444 */\n#define EXPAND_Ato8(a) EXPAND_4to8( a )\n#define EXPAND_Rto8(r) EXPAND_4to8( r )\n#define EXPAND_Gto8(g) EXPAND_4to8( g )\n#define EXPAND_Bto8(b) EXPAND_4to8( b )\n#define PIXEL_OUT(a,r,g,b) PIXEL_ARGB4444( a, r, g, b )\n#define Sop_PFI_OP_Dacc(op) Sop_argb4444_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_argb4444\n#define A_SHIFT 12\n#define R_SHIFT 8\n#define G_SHIFT 4\n#define B_SHIFT 0\n#define A_MASK 0xf000\n#define R_MASK 0x0f00\n#define G_MASK 0x00f0\n#define B_MASK 0x000f\n#include \"template_acc_16.h\"\n\n/* RGBA4444 */\n#define EXPAND_Ato8(a) EXPAND_4to8( a )\n#define EXPAND_Rto8(r) EXPAND_4to8( r )\n#define EXPAND_Gto8(g) EXPAND_4to8( g )\n#define EXPAND_Bto8(b) EXPAND_4to8( b )\n#define PIXEL_OUT(a,r,g,b) PIXEL_RGBA4444( a, r, g, b )\n#define Sop_PFI_OP_Dacc(op) Sop_rgba4444_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_rgba4444\n#define A_SHIFT 0\n#define R_SHIFT 12\n#define G_SHIFT 8\n#define B_SHIFT 4\n#define A_MASK 0x000f\n#define R_MASK 0xf000\n#define G_MASK 0x0f00\n#define B_MASK 0x00f0\n#include \"template_acc_16.h\"\n\n/* ARGB1666 */\n#define EXPAND_Ato8(a) EXPAND_1to8( a )\n#define EXPAND_Rto8(r) EXPAND_6to8( r )\n#define EXPAND_Gto8(g) EXPAND_6to8( g )\n#define EXPAND_Bto8(b) EXPAND_6to8( b )\n#define PIXEL_OUT(a,r,g,b) PIXEL_ARGB1666( a, r, g, b )\n#define Sop_PFI_OP_Dacc(op) Sop_argb1666_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_argb1666\n#define A_SHIFT 18\n#define R_SHIFT 12\n#define G_SHIFT 6\n#define B_SHIFT 0\n#define A_MASK 0x040000\n#define R_MASK 0x03f000\n#define G_MASK 0x000fc0\n#define B_MASK 0x00003f\n#include \"template_acc_24.h\"\n\n/* ARGB6666 */\n#define EXPAND_Ato8(a) EXPAND_6to8( a )\n#define EXPAND_Rto8(r) EXPAND_6to8( r )\n#define EXPAND_Gto8(g) EXPAND_6to8( g )\n#define EXPAND_Bto8(b) EXPAND_6to8( b )\n#define PIXEL_OUT(a,r,g,b) PIXEL_ARGB6666( a, r, g, b )\n#define Sop_PFI_OP_Dacc(op) Sop_argb6666_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_argb6666\n#define A_SHIFT 18\n#define R_SHIFT 12\n#define G_SHIFT 6\n#define B_SHIFT 0\n#define A_MASK 0xfc0000\n#define R_MASK 0x03f000\n#define G_MASK 0x000fc0\n#define B_MASK 0x00003f\n#include \"template_acc_24.h\"\n\n/* RGB18 */\n#define EXPAND_Ato8(a) 0xff\n#define EXPAND_Rto8(r) EXPAND_6to8( r )\n#define EXPAND_Gto8(g) EXPAND_6to8( g )\n#define EXPAND_Bto8(b) EXPAND_6to8( b )\n#define PIXEL_OUT(a,r,g,b) PIXEL_RGB18( r, g, b )\n#define Sop_PFI_OP_Dacc(op) Sop_rgb18_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_rgb18\n#define A_SHIFT 0\n#define R_SHIFT 12\n#define G_SHIFT 6\n#define B_SHIFT 0\n#define A_MASK 0\n#define R_MASK 0x03f000\n#define G_MASK 0x000fc0\n#define B_MASK 0x00003f\n#include \"template_acc_24.h\"\n\n/* RGB444 */\n#define EXPAND_Ato8(a) 0xff\n#define EXPAND_Rto8(r) EXPAND_4to8( r )\n#define EXPAND_Gto8(g) EXPAND_4to8( g )\n#define EXPAND_Bto8(b) EXPAND_4to8( b )\n#define PIXEL_OUT(a,r,g,b) PIXEL_RGB444( r, g, b )\n#define Sop_PFI_OP_Dacc(op) Sop_xrgb4444_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_xrgb4444\n#define A_SHIFT 0\n#define R_SHIFT 8\n#define G_SHIFT 4\n#define B_SHIFT 0\n#define A_MASK 0\n#define R_MASK 0x0f00\n#define G_MASK 0x00f0\n#define B_MASK 0x000f\n#include \"template_acc_16.h\"\n\n/* RGB555 */\n#define EXPAND_Ato8(a) 0xff\n#define EXPAND_Rto8(r) EXPAND_5to8( r )\n#define EXPAND_Gto8(g) EXPAND_5to8( g )\n#define EXPAND_Bto8(b) EXPAND_5to8( b )\n#define PIXEL_OUT(a,r,g,b) PIXEL_RGB555( r, g, b )\n#define Sop_PFI_OP_Dacc(op) Sop_xrgb1555_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_xrgb1555\n#define A_SHIFT 0\n#define R_SHIFT 10\n#define G_SHIFT 5\n#define B_SHIFT 0\n#define A_MASK 0\n#define R_MASK 0x7c00\n#define G_MASK 0x03e0\n#define B_MASK 0x001f\n#include \"template_acc_16.h\"\n\n/* BGR555 */\n#define EXPAND_Ato8(a) 0xff\n#define EXPAND_Rto8(r) EXPAND_5to8( r )\n#define EXPAND_Gto8(g) EXPAND_5to8( g )\n#define EXPAND_Bto8(b) EXPAND_5to8( b )\n#define PIXEL_OUT(a,r,g,b) PIXEL_BGR555( r, g, b )\n#define Sop_PFI_OP_Dacc(op) Sop_xbgr1555_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_xbgr1555\n#define A_SHIFT 0\n#define B_SHIFT 10\n#define G_SHIFT 5\n#define R_SHIFT 0\n#define A_MASK 0\n#define B_MASK 0x7c00\n#define G_MASK 0x03e0\n#define R_MASK 0x001f\n#include \"template_acc_16.h\"\n\n/* RGBA5551 */\n#define EXPAND_Ato8(a) EXPAND_1to8( a )\n#define EXPAND_Rto8(r) EXPAND_5to8( r )\n#define EXPAND_Gto8(g) EXPAND_5to8( g )\n#define EXPAND_Bto8(b) EXPAND_5to8( b )\n#define PIXEL_OUT(a,r,g,b) PIXEL_RGBA5551( a, r, g, b )\n#define Sop_PFI_OP_Dacc(op) Sop_rgba5551_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_rgba5551\n#define A_SHIFT 0\n#define R_SHIFT 11\n#define G_SHIFT 6\n#define B_SHIFT 1\n#define A_MASK 0x0001\n#define R_MASK 0xf800\n#define G_MASK 0x07c0\n#define B_MASK 0x003e\n#include \"template_acc_16.h\"\n\n/* ARGB8565 */\n#define EXPAND_Ato8(a) (a)\n#define EXPAND_Rto8(r) EXPAND_5to8( r )\n#define EXPAND_Gto8(g) EXPAND_6to8( g )\n#define EXPAND_Bto8(b) EXPAND_5to8( b )\n#define PIXEL_OUT(a,r,g,b) PIXEL_ARGB8565( a, r, g, b )\n#define Sop_PFI_OP_Dacc(op) Sop_argb8565_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_argb8565\n#define A_SHIFT 16\n#define R_SHIFT 11\n#define G_SHIFT 5\n#define B_SHIFT 0\n#define A_MASK 0xff0000\n#define R_MASK 0x00f800\n#define G_MASK 0x0007e0\n#define B_MASK 0x00001f\n#include \"template_acc_24.h\"\n\n/* RGBAF88871 */\n#define EXPAND_Ato8(a) EXPAND_7to8(a)\n#define EXPAND_Rto8(r) (r)\n#define EXPAND_Gto8(g) (g)\n#define EXPAND_Bto8(b) (b)\n#define PIXEL_OUT(a,r,g,b) PIXEL_RGBAF88871( a, r, g, b )\n#define Sop_PFI_OP_Dacc(op) Sop_rgbaf88871_##op##_Dacc\n#define Sacc_OP_Aop_PFI(op) Sacc_##op##_Aop_rgbaf88871\n#define A_SHIFT 1\n#define R_SHIFT 24\n#define G_SHIFT 16\n#define B_SHIFT 8\n#define A_MASK 0x000000fe\n#define R_MASK 0xff000000\n#define G_MASK 0x00ff0000\n#define B_MASK 0x0000ff00\n#include \"template_acc_32.h\"\n\n/**********************************************************************************************************************/\n\n/* Whether pixelformat is YUV or not. */\nstatic const bool is_ycbcr[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = true,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = true,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = true,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = true,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = true,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = true,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = true,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = true,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = true,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = true,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = true,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = true,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = false,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = true,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = true,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = true,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = true,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = true,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = false,\n};\n\n/**********************************************************************************************************************\n ********************************* Cop_to_Aop_PFI *********************************************************************\n **********************************************************************************************************************/\n\nstatic void\nCop_to_Aop_16( GenefxState *gfxs )\n{\n     int  l;\n     int  w   = gfxs->length;\n     u32 *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop;\n\n     u32 DCop = ((Cop << 16) | Cop);\n\n     if (((long) D) & 2) {\n          u16* tmp = (u16*) D;\n          --w;\n          *tmp = Cop;\n          D = (u32*) (tmp + 1);\n     }\n\n     l = w >> 1;\n     while (l) {\n          *D = DCop;\n\n          ++D;\n          --l;\n     }\n\n     if (w & 1)\n          *((u16*) D) = (u16) Cop;\n}\n\nstatic void\nCop_to_Aop_24( GenefxState *gfxs )\n{\n     int  w   = gfxs->length + 1;\n     u8  *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop;\n\n     while (--w) {\n#ifdef WORDS_BIGENDIAN\n          D[0] = (Cop >> 16) & 0xff;\n          D[1] = (Cop >>  8) & 0xff;\n          D[2] =  Cop        & 0xff;\n#else\n          D[0] =  Cop        & 0xff;\n          D[1] = (Cop >>  8) & 0xff;\n          D[2] = (Cop >> 16) & 0xff;\n#endif\n\n          D += 3;\n     }\n}\n\nstatic void\nCop_to_Aop_32( GenefxState *gfxs )\n{\n     int  w   = gfxs->length;\n     u32 *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop;\n\n     while (w) {\n          if (!(w % 8)) {\n               *D++ = Cop;\n               *D++ = Cop;\n               *D++ = Cop;\n               *D++ = Cop;\n               *D++ = Cop;\n               *D++ = Cop;\n               *D++ = Cop;\n               *D++ = Cop;\n               w -= 8;\n          }\n          else if (!(w % 4)) {\n               *D++ = Cop;\n               *D++ = Cop;\n               *D++ = Cop;\n               *D++ = Cop;\n               w -= 4;\n          }\n          else if (!(w % 2)) {\n               *D++ = Cop;\n               *D++ = Cop;\n               w -= 2;\n          }\n          else {\n               *D++ = Cop;\n               --w;\n          }\n     }\n}\n\nstatic void\nCop_to_Aop_8( GenefxState *gfxs )\n{\n     memset( gfxs->Aop[0], gfxs->Cop, gfxs->length );\n}\n\nstatic void\nCop_to_Aop_yuv422( GenefxState *gfxs )\n{\n     int  l;\n     int  w   = gfxs->length;\n     u16 *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop;\n\n     if ((long) D & 2) {\n#ifdef WORDS_BIGENDIAN\n          *D++ = Cop & 0xffff;\n#else\n          *D++ = Cop >> 16;\n#endif\n          --w;\n     }\n\n     for (l = w >> 1; l--;) {\n          *((u32*) D) = Cop;\n          D += 2;\n     }\n\n     if (w & 1) {\n#ifdef WORDS_BIGENDIAN\n          *D = Cop >> 16;\n#else\n          *D = Cop & 0xffff;\n#endif\n     }\n}\n\nstatic void\nCop_to_Aop_i420( GenefxState *gfxs )\n{\n     memset( gfxs->Aop[0], gfxs->YCop, gfxs->length );\n\n     if (gfxs->AopY & 1) {\n          memset( gfxs->Aop[1], gfxs->CbCop, gfxs->length >> 1 );\n          memset( gfxs->Aop[2], gfxs->CrCop, gfxs->length >> 1 );\n     }\n}\n\nstatic void\nCop_to_Aop_nv12( GenefxState *gfxs )\n{\n     memset( gfxs->Aop[0], gfxs->YCop, gfxs->length );\n\n     if (gfxs->AopY & 1) {\n          int  w   = (gfxs->length >> 1) + 1;\n          u16 *D   =  gfxs->Aop[1];\n          u16  Cop =  gfxs->CbCop | (gfxs->CrCop << 8);\n\n          while (--w)\n               *D++ = Cop;\n     }\n}\n\nstatic void\nCop_to_Aop_nv16( GenefxState *gfxs )\n{\n     int  w   = (gfxs->length >> 1) + 1;\n     u16 *D   =  gfxs->Aop[1];\n     u16  Cop =  gfxs->CbCop | (gfxs->CrCop << 8);\n\n     memset( gfxs->Aop[0], gfxs->YCop, gfxs->length );\n\n     while (--w)\n          *D++ = Cop;\n}\n\nstatic void\nCop_to_Aop_nv21( GenefxState *gfxs )\n{\n     memset( gfxs->Aop[0], gfxs->YCop, gfxs->length );\n\n     if (gfxs->AopY & 1) {\n          int  w   = (gfxs->length >> 1) + 1;\n          u16 *D   =  gfxs->Aop[1];\n          u16  Cop =  gfxs->CrCop | (gfxs->CbCop << 8);\n\n          while (--w)\n               *D++ = Cop;\n     }\n}\n\nstatic void\nCop_to_Aop_18( GenefxState *gfxs )\n{\n     int  w   = gfxs->length + 1;\n     u8  *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop;\n\n     while (--w) {\n          D[0] = Cop;\n          D[1] = Cop >> 8;\n          D[2] = Cop >> 16;\n\n          D += 3;\n     }\n}\n\nstatic void\nCop_to_Aop_y444( GenefxState *gfxs )\n{\n     memset( gfxs->Aop[0], gfxs->YCop,  gfxs->length );\n     memset( gfxs->Aop[1], gfxs->CbCop, gfxs->length );\n     memset( gfxs->Aop[2], gfxs->CrCop, gfxs->length );\n}\n\nstatic void\nCop_to_Aop_argb8565( GenefxState *gfxs )\n{\n     int  w   = gfxs->length + 1;\n     u8  *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop;\n\n     while (--w) {\n#ifdef WORDS_BIGENDIAN\n          D[0] = (Cop >> 16) & 0xff;\n          D[1] = (Cop >>  8) & 0xff;\n          D[2] =  Cop        & 0xff;\n#else\n          D[0] =  Cop        & 0xff;\n          D[1] = (Cop >>  8) & 0xff;\n          D[2] = (Cop >> 16) & 0xff;\n#endif\n\n          D += 3;\n     }\n}\n\nstatic void\nCop_to_Aop_vyu( GenefxState *gfxs )\n{\n     int  w = gfxs->length + 1;\n     u8  *D = gfxs->Aop[0];\n\n     while (--w) {\n#ifdef WORDS_BIGENDIAN\n          D[0] = gfxs->CrCop;\n          D[1] = gfxs->YCop;\n          D[2] = gfxs->CbCop;\n#else\n          D[0] = gfxs->CbCop;\n          D[1] = gfxs->YCop;\n          D[2] = gfxs->CrCop;\n#endif\n\n          D += 3;\n     }\n}\n\nstatic void\nCop_to_Aop_y42b( GenefxState *gfxs )\n{\n     memset( gfxs->Aop[0], gfxs->YCop,  gfxs->length );\n     memset( gfxs->Aop[1], gfxs->CbCop, gfxs->length / 2 );\n     memset( gfxs->Aop[2], gfxs->CrCop, gfxs->length / 2 );\n}\n\nstatic void\nCop_to_Aop_nv61( GenefxState *gfxs )\n{\n     int  w   = (gfxs->length >> 1) + 1;\n     u16 *D   =  gfxs->Aop[1];\n     u16  Cop =  gfxs->CrCop | (gfxs->CbCop << 8);\n\n     memset( gfxs->Aop[0], gfxs->YCop, gfxs->length );\n\n     while (--w)\n          *D++ = Cop;\n}\n\nstatic void\nCop_to_Aop_nv24( GenefxState *gfxs )\n{\n     int  w   = gfxs->length + 1;\n     u16 *D   = gfxs->Aop[1];\n     u16  Cop = gfxs->CbCop | (gfxs->CrCop << 8);\n\n     memset( gfxs->Aop[0], gfxs->YCop, gfxs->length );\n\n     while (--w)\n          *D++ = Cop;\n}\n\nstatic void\nCop_to_Aop_nv42( GenefxState *gfxs )\n{\n     int  w   = gfxs->length + 1;\n     u16 *D   = gfxs->Aop[1];\n     u16  Cop = gfxs->CrCop | (gfxs->CbCop << 8);\n\n     memset( gfxs->Aop[0], gfxs->YCop, gfxs->length );\n\n     while (--w)\n          *D++ = Cop;\n}\n\nstatic GenefxFunc Cop_to_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Cop_to_Aop_16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Cop_to_Aop_16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Cop_to_Aop_24,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Cop_to_Aop_32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Cop_to_Aop_32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = Cop_to_Aop_8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = Cop_to_Aop_yuv422,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = Cop_to_Aop_8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = Cop_to_Aop_yuv422,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = Cop_to_Aop_i420,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = Cop_to_Aop_i420,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = Cop_to_Aop_8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = Cop_to_Aop_8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Cop_to_Aop_32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = Cop_to_Aop_nv12,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = Cop_to_Aop_nv16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Cop_to_Aop_16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Cop_to_Aop_16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Cop_to_Aop_16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = Cop_to_Aop_nv21,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = Cop_to_Aop_32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Cop_to_Aop_18,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Cop_to_Aop_18,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Cop_to_Aop_18,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Cop_to_Aop_16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Cop_to_Aop_16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Cop_to_Aop_16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Cop_to_Aop_16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Cop_to_Aop_y444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Cop_to_Aop_argb8565,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Cop_to_Aop_32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Cop_to_Aop_vyu,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = Cop_to_Aop_y42b,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Cop_to_Aop_32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Cop_to_Aop_32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = Cop_to_Aop_nv61,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = Cop_to_Aop_y42b,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Cop_to_Aop_y444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = Cop_to_Aop_nv24,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = Cop_to_Aop_nv42,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Cop_to_Aop_24,\n};\n\n/**********************************************************************************************************************\n ********************************* Cop_toK_Aop_PFI ********************************************************************\n **********************************************************************************************************************/\n\nstatic void\nCop_toK_Aop_8( GenefxState *gfxs )\n{\n     int  w    = gfxs->length + 1;\n     u8  *D    = gfxs->Aop[0];\n     u32  Cop  = gfxs->Cop;\n     u32  Dkey = gfxs->Dkey;\n\n     while (--w) {\n          if (Dkey == *D)\n               *D = Cop;\n\n          ++D;\n     }\n}\n\nstatic void\nCop_toK_Aop_yuv422( GenefxState *gfxs )\n{\n     int  l;\n     int  w    = gfxs->length;\n     u16 *D    = gfxs->Aop[0];\n     u32  Cop  = gfxs->Cop;\n     u32  Dkey = gfxs->Dkey;\n\n     if ((long) D & 2) {\n#ifdef WORDS_BIGENDIAN\n          if (*D == (Dkey & 0xffff))\n               *D = Cop & 0xffff;\n#else\n          if (*D == (Dkey >> 16))\n               *D = Cop >> 16;\n#endif\n\n          ++D;\n          --w;\n     }\n\n     for (l = w >> 1; l--;) {\n          if (*((u32*) D) == Dkey)\n               *((u32*) D) = Cop;\n\n          D += 2;\n     }\n\n     if (w & 1) {\n#ifdef WORDS_BIGENDIAN\n          if (*D == (Dkey >> 16))\n               *D = Cop >> 16;\n#else\n          if (*D == (Dkey & 0xffff))\n               *D = Cop & 0xffff;\n#endif\n     }\n}\n\nstatic void\nCop_toK_Aop_alut44( GenefxState *gfxs )\n{\n     int  w    = gfxs->length + 1;\n     u8  *D    = gfxs->Aop[0];\n     u32  Cop  = gfxs->Cop;\n     u32  Dkey = gfxs->Dkey;\n\n     while (--w) {\n          if (Dkey == (*D & 0x0f))\n               *D = Cop;\n\n          ++D;\n     }\n}\n\nstatic void\nCop_toK_Aop_y444( GenefxState *gfxs )\n{\n     int  w    = gfxs->length + 1;\n     u8  *Dy   = gfxs->Aop[0];\n     u8  *Du   = gfxs->Aop[1];\n     u8  *Dv   = gfxs->Aop[2];\n     u32  Cop  = gfxs->Cop;\n     u32  Dkey = gfxs->Dkey;\n\n     while (--w) {\n          u8 dy = *Dy;\n          u8 du = *Du;\n          u8 dv = *Dv;\n\n          if (Dkey == (u32) ((dy << 16) | (du << 8) | dv)) {\n               *Dy = (Cop >> 16) & 0xff;\n               *Du = (Cop >>  8) & 0xff;\n               *Dv =  Cop        & 0xff;\n          }\n\n          ++Dy; ++Du; ++Dv;\n     }\n}\n\nstatic void\nCop_toK_Aop_avyu( GenefxState *gfxs )\n{\n     int  w    = gfxs->length + 1;\n     u32 *D    = gfxs->Aop[0];\n     u32  Cop  = gfxs->Cop;\n     u32  Dkey = gfxs->Dkey;\n\n     while (--w) {\n          if ((*D & 0x00ffffff) == Dkey)\n               *D = Cop;\n\n          ++D;\n     }\n}\n\nstatic GenefxFunc Cop_toK_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Cop_toK_Aop_15,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Cop_toK_Aop_16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Cop_toK_Aop_24_24,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Cop_toK_Aop_32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Cop_toK_Aop_32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = Cop_toK_Aop_8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = Cop_toK_Aop_yuv422,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = Cop_toK_Aop_8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = Cop_toK_Aop_yuv422,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = Cop_toK_Aop_8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = Cop_toK_Aop_alut44,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Cop_toK_Aop_32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Cop_toK_Aop_14,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Cop_toK_Aop_12,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Cop_toK_Aop_12vv,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = Cop_toK_Aop_32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Cop_toK_Aop_24_18,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Cop_toK_Aop_24_18,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Cop_toK_Aop_24_18,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Cop_toK_Aop_12,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Cop_toK_Aop_15,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Cop_toK_Aop_15,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Cop_toK_Aop_15,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Cop_toK_Aop_y444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Cop_toK_Aop_24_16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Cop_toK_Aop_avyu,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Cop_toK_Aop_24_24,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Cop_toK_Aop_32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Cop_toK_Aop_32_24,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Cop_toK_Aop_y444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Cop_toK_Aop_24_24,\n};\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_to_Dacc ********************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_a8_to_Dacc( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     u8                *S = gfxs->Sop[0];\n     GenefxAccumulator *D = gfxs->Dacc;\n\n     while (--w) {\n          D->RGB.a = *S++;\n          D->RGB.r = 0xff;\n          D->RGB.g = 0xff;\n          D->RGB.b = 0xff;\n\n          ++D;\n     }\n}\n\nstatic void\nSop_yuy2_to_Dacc( GenefxState *gfxs )\n{\n     int                w = (gfxs->length >> 1) + 1;\n     u32               *S =  gfxs->Sop[0];\n     GenefxAccumulator *D =  gfxs->Dacc;\n\n     while (--w) {\n          u32 s = *S++;\n\n          D[0].YUV.a = D[1].YUV.a = 0xff;\n#ifdef WORDS_BIGENDIAN\n          D[0].YUV.y =              (s & 0x00ff0000) >> 16;\n          D[1].YUV.y =               s & 0x000000ff;\n          D[0].YUV.u = D[1].YUV.u = (s & 0xff000000) >> 24;\n          D[0].YUV.v = D[1].YUV.v = (s & 0x0000ff00) >>  8;\n#else\n          D[0].YUV.y =               s & 0x000000ff;\n          D[1].YUV.y =              (s & 0x00ff0000) >> 16;\n          D[0].YUV.u = D[1].YUV.u = (s & 0x0000ff00) >>  8;\n          D[0].YUV.v = D[1].YUV.v = (s & 0xff000000) >> 24;\n#endif\n\n          D += 2;\n     }\n\n     if (gfxs->length & 1) {\n          u16 s = *((u16*) S);\n\n          D->YUV.a = 0xff;\n          D->YUV.y = s & 0xff;\n          D->YUV.u = s >> 8;\n          D->YUV.v = 0x00;\n     }\n}\n\nstatic void\nSop_rgb332_to_Dacc( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     u8                *S = gfxs->Sop[0];\n     GenefxAccumulator *D = gfxs->Dacc;\n\n     while (--w) {\n          u8 s = *S++;\n\n          D->RGB.a = 0xff;\n          D->RGB.r = EXPAND_3to8(  s >> 5         );\n          D->RGB.g = EXPAND_3to8( (s & 0x1c) >> 2 );\n          D->RGB.b = EXPAND_2to8(  s & 0x03       );\n\n          ++D;\n     }\n}\n\nstatic void\nSop_uyvy_to_Dacc( GenefxState *gfxs )\n{\n     int                w = (gfxs->length >> 1) + 1;\n     u32               *S =  gfxs->Sop[0];\n     GenefxAccumulator *D =  gfxs->Dacc;\n\n     while (--w) {\n          u32 s = *S++;\n\n          D[0].YUV.a = D[1].YUV.a = 0xff;\n#ifdef WORDS_BIGENDIAN\n          D[0].YUV.y =              (s & 0xff000000) >> 24;\n          D[1].YUV.y =              (s & 0x0000ff00) >> 8;\n          D[0].YUV.u = D[1].YUV.u = (s & 0x00ff0000) >> 16;\n          D[0].YUV.v = D[1].YUV.v =  s & 0x000000ff;\n#else\n          D[0].YUV.y =              (s & 0x0000ff00) >> 8;\n          D[1].YUV.y =              (s & 0xff000000) >> 24;\n          D[0].YUV.u = D[1].YUV.u =  s & 0x000000ff;\n          D[0].YUV.v = D[1].YUV.v = (s & 0x00ff0000) >> 16;\n#endif\n\n          D += 2;\n     }\n\n     if (gfxs->length & 1) {\n          u16 s = *((u16*) S);\n\n          D->YUV.a = 0xff;\n          D->YUV.y = s >> 8;\n          D->YUV.u = s & 0xff;\n          D->YUV.v = 0x00;\n     }\n}\n\nstatic void\nSop_i420_to_Dacc( GenefxState *gfxs )\n{\n    int                 w  = (gfxs->length >> 1) + 1;\n     u8                *Sy =  gfxs->Sop[0];\n     u8                *Su =  gfxs->Sop[1];\n     u8                *Sv =  gfxs->Sop[2];\n     GenefxAccumulator *D  =  gfxs->Dacc;\n\n     while (--w) {\n          D[1].YUV.a = D[0].YUV.a = 0xff;\n          D[0].YUV.y = Sy[0];\n          D[1].YUV.y = Sy[1];\n          D[1].YUV.u = D[0].YUV.u = Su[0];\n          D[1].YUV.v = D[0].YUV.v = Sv[0];\n\n          Sy += 2; ++Su; ++Sv;\n          D  += 2;\n     }\n}\n\nstatic void\nSop_lut8_to_Dacc( GenefxState *gfxs )\n{\n     int                w       = gfxs->length + 1;\n     u8                *S       = gfxs->Sop[0];\n     GenefxAccumulator *D       = gfxs->Dacc;\n     DFBColor          *entries = gfxs->Slut->entries;\n\n     while (--w) {\n          u8 s = *S++;\n\n          D->RGB.a = entries[s].a;\n          D->RGB.r = entries[s].r;\n          D->RGB.g = entries[s].g;\n          D->RGB.b = entries[s].b;\n\n          ++D;\n     }\n}\n\nstatic void\nSop_alut44_to_Dacc( GenefxState *gfxs )\n{\n     int                w       = gfxs->length + 1;\n     u8                *S       = gfxs->Sop[0];\n     GenefxAccumulator *D       = gfxs->Dacc;\n     DFBColor          *entries = gfxs->Slut->entries;\n\n     while (--w) {\n          u8 s = *S++;\n\n          D->RGB.a = s & 0xf0;\n          s &= 0x0f;\n          D->RGB.r = entries[s].r;\n          D->RGB.g = entries[s].g;\n          D->RGB.b = entries[s].b;\n\n          ++D;\n     }\n}\n\nstatic void\nSop_nv12_to_Dacc( GenefxState *gfxs )\n{\n     int                w   = (gfxs->length >> 1) + 1;\n     u8                *Sy  =  gfxs->Sop[0];\n     u16               *Suv =  gfxs->Sop[1];\n     GenefxAccumulator *D   =  gfxs->Dacc;\n\n     while (--w) {\n          D[1].YUV.a = D[0].YUV.a = 0xff;\n          D[0].YUV.y = Sy[0];\n          D[1].YUV.y = Sy[1];\n          D[1].YUV.u = D[0].YUV.u = Suv[0] & 0xff;\n          D[1].YUV.v = D[0].YUV.v = Suv[0] >> 8;\n\n          Sy += 2; ++Suv;\n          D  += 2;\n     }\n}\n\nstatic void\nSop_nv21_to_Dacc( GenefxState *gfxs )\n{\n     int                w   = (gfxs->length >> 1) + 1;\n     u8                *Sy  =  gfxs->Sop[0];\n     u16               *Svu =  gfxs->Sop[1];\n     GenefxAccumulator *D   =  gfxs->Dacc;\n\n     while (--w) {\n          D[1].YUV.a = D[0].YUV.a = 0xff;\n          D[0].YUV.y = Sy[0];\n          D[1].YUV.y = Sy[1];\n          D[1].YUV.u = D[0].YUV.u = Svu[0] >> 8;\n          D[1].YUV.v = D[0].YUV.v = Svu[0] & 0xff;\n\n          Sy += 2; ++Svu;\n          D  += 2;\n     }\n}\n\nstatic void\nSop_ayuv_to_Dacc( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     u32               *S = gfxs->Sop[0];\n     GenefxAccumulator *D = gfxs->Dacc;\n\n     while (--w) {\n          u32 s = *S++;\n\n          D->YUV.a =  s >> 24;\n          D->YUV.y = (s >> 16) & 0xff;\n          D->YUV.u = (s >>  8) & 0xff;\n          D->YUV.v =  s        & 0xff;\n\n          ++D;\n     }\n}\n\nstatic void\nSop_a4_to_Dacc( GenefxState *gfxs )\n{\n     int                i, n;\n     u8                *S = gfxs->Sop[0];\n     GenefxAccumulator *D = gfxs->Dacc;\n\n     for (i = 0, n = 0; i < gfxs->length; i += 2, n++) {\n          int left  = S[n] & 0xf0;\n          int right = S[n] & 0x0f;\n\n          D[i].RGB.a = left | (left >> 4);\n          D[i].RGB.r = 0xff;\n          D[i].RGB.g = 0xff;\n          D[i].RGB.b = 0xff;\n\n          D[i+1].RGB.a = right | (right << 4);\n          D[i+1].RGB.r = 0xff;\n          D[i+1].RGB.g = 0xff;\n          D[i+1].RGB.b = 0xff;\n     }\n}\n\nstatic void\nSop_y444_to_Dacc( GenefxState *gfxs )\n{\n     int                w  = gfxs->length + 1;\n     u8                *Sy = gfxs->Sop[0];\n     u8                *Su = gfxs->Sop[1];\n     u8                *Sv = gfxs->Sop[2];\n     GenefxAccumulator *D  = gfxs->Dacc;\n\n     while (--w) {\n          D->YUV.a = 0xff;\n          D->YUV.y = *Sy++;\n          D->YUV.u = *Su++;\n          D->YUV.v = *Sv++;\n\n          ++D;\n     }\n}\n\nstatic void\nSop_avyu_to_Dacc( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     u32               *S = gfxs->Sop[0];\n     GenefxAccumulator *D = gfxs->Dacc;\n\n     while (--w) {\n          u32 s = *S++;\n\n          D->YUV.a =  s >> 24;\n          D->YUV.v = (s >> 16) & 0xff;\n          D->YUV.y = (s >>  8) & 0xff;\n          D->YUV.u =  s        & 0xff;\n\n          ++D;\n     }\n}\n\nstatic void\nSop_vyu_to_Dacc( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     u8                *S = gfxs->Sop[0];\n     GenefxAccumulator *D = gfxs->Dacc;\n\n     while (--w) {\n#ifdef WORDS_BIGENDIAN\n          D->YUV.a = 0xff;\n          D->YUV.v = S[0];\n          D->YUV.y = S[1];\n          D->YUV.u = S[2];\n#else\n          D->YUV.a = 0xff;\n          D->YUV.v = S[2];\n          D->YUV.y = S[1];\n          D->YUV.u = S[0];\n#endif\n\n          S += 3;\n          ++D;\n     }\n}\n\nstatic void\nSop_nv24_to_Dacc( GenefxState *gfxs )\n{\n     int                w   = gfxs->length + 1;\n     u8                *Sy  = gfxs->Sop[0];\n     u16               *Suv = gfxs->Sop[1];\n     GenefxAccumulator *D   = gfxs->Dacc;\n\n     while (--w) {\n          D[0].YUV.a = 0xff;\n          D[0].YUV.y = *Sy++;\n          D[0].YUV.u = Suv[0] & 0xff;\n          D[0].YUV.v = Suv[0] >> 8;\n\n          ++Suv;\n          D++;\n     }\n}\n\nstatic void\nSop_nv42_to_Dacc( GenefxState *gfxs )\n{\n     int                w   = gfxs->length + 1;\n     u8                *Sy  = gfxs->Sop[0];\n     u16               *Svu = gfxs->Sop[1];\n     GenefxAccumulator *D   = gfxs->Dacc;\n\n     while (--w) {\n          D[0].YUV.a = 0xff;\n          D[0].YUV.y = *Sy++;\n          D[0].YUV.u = Svu[0] >> 8;\n          D[0].YUV.v = Svu[0] & 0xff;\n\n          ++Svu;\n          D++;\n     }\n}\n\nstatic GenefxFunc Sop_PFI_to_Dacc[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Sop_argb1555_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Sop_rgb16_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Sop_rgb24_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Sop_rgb32_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Sop_argb_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = Sop_a8_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = Sop_yuy2_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = Sop_rgb332_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = Sop_uyvy_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = Sop_i420_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = Sop_i420_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = Sop_lut8_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = Sop_alut44_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Sop_airgb_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = Sop_nv12_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = Sop_nv12_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Sop_argb2554_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Sop_argb4444_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Sop_rgba4444_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = Sop_nv21_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = Sop_ayuv_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = Sop_a4_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Sop_argb1666_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Sop_argb6666_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Sop_rgb18_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Sop_xrgb4444_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Sop_xrgb1555_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Sop_xbgr1555_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Sop_rgba5551_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Sop_y444_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Sop_argb8565_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Sop_avyu_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Sop_vyu_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = Sop_i420_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Sop_abgr_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Sop_rgbaf88871_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = Sop_nv21_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = Sop_i420_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Sop_y444_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = Sop_nv24_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = Sop_nv42_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Sop_bgr24_to_Dacc,\n};\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_Kto_Dacc *******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_a8_Kto_Dacc( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     u8                *S = gfxs->Sop[0];\n     GenefxAccumulator *D = gfxs->Dacc;\n\n     /* No color to key. */\n     while (--w) {\n          D->RGB.a = *S++;\n          D->RGB.r = 0xff;\n          D->RGB.g = 0xff;\n          D->RGB.b = 0xff;\n\n          ++D;\n     }\n}\n\nstatic void\nSop_yuy2_Kto_Dacc( GenefxState *gfxs )\n{\n     int                w     = (gfxs->length >> 1) + 1;\n     u32               *S     =  gfxs->Sop[0];\n     GenefxAccumulator *D     =  gfxs->Dacc;\n     u32                Skey  =  gfxs->Skey;\n     u32                Skey0 =  gfxs->Skey & 0xff00ffff;\n     u32                Skey1 =  gfxs->Skey & 0xffffff00;\n\n#ifdef WORDS_BIGENDIAN\n#define S0_MASK  0xffffff00\n#define S1_MASK  0xff00ffff\n#else\n#define S0_MASK  0xff00ffff\n#define S1_MASK  0xffffff00\n#endif\n\n     while (--w) {\n          u32 s = *S++;\n\n          if (s != Skey) {\n               u32 cb, cr;\n\n#ifdef WORDS_BIGENDIAN\n               cb = (s & 0xff000000) >> 24;\n               cr = (s & 0x0000ff00) >>  8;\n#else\n               cb = (s & 0x0000ff00) >>  8;\n               cr = (s & 0xff000000) >> 24;\n#endif\n\n               if ((s & S0_MASK) != Skey0) {\n                    D[0].YUV.a = 0xff;\n#ifdef WORDS_BIGENDIAN\n                    D[0].YUV.y = (s & 0x00ff0000) >> 16;\n#else\n                    D[0].YUV.y =  s & 0x000000ff;\n#endif\n                    D[0].YUV.u = cb;\n                    D[0].YUV.v = cr;\n               }\n               else\n                    D[0].YUV.a = 0xf000;\n\n               if ((s & S1_MASK) != Skey1) {\n                    D[1].YUV.a = 0xff;\n#ifdef WORDS_BIGENDIAN\n                    D[1].YUV.y =  s & 0x000000ff;\n#else\n                    D[1].YUV.y = (s & 0x00ff0000) >> 16;\n#endif\n                    D[1].YUV.u = cb;\n                    D[1].YUV.v = cr;\n               }\n               else\n                    D[1].YUV.a = 0xf000;\n          }\n\n          D += 2;\n     }\n\n     if (gfxs->length & 1) {\n          u16 s = *((u16*) S);\n\n          if (s != Skey0) {\n               D->YUV.a = 0xff;\n               D->YUV.y = s & 0xff;\n               D->YUV.u = s >> 8;\n               D->YUV.v = 0x00;\n          }\n          else\n               D->YUV.a = 0xf000;\n     }\n\n#undef S0_MASK\n#undef S1_MASK\n}\n\nstatic void\nSop_rgb332_Kto_Dacc( GenefxState *gfxs )\n{\n     int                w    = gfxs->length + 1;\n     u8                *S    = gfxs->Sop[0];\n     GenefxAccumulator *D    = gfxs->Dacc;\n     u32                Skey = gfxs->Skey;\n\n     while (--w) {\n          u8 s = *S++;\n\n          if (s != Skey) {\n               D->RGB.a = 0xff;\n               D->RGB.r = EXPAND_3to8(  s >> 5         );\n               D->RGB.g = EXPAND_3to8( (s & 0x1c) >> 2 );\n               D->RGB.b = EXPAND_2to8(  s & 0x03       );\n          }\n          else\n               D->RGB.a = 0xf000;\n\n          ++D;\n     }\n}\n\nstatic void\nSop_uyvy_Kto_Dacc( GenefxState *gfxs )\n{\n     int                w     = (gfxs->length >> 1) + 1;\n     u32               *S     =  gfxs->Sop[0];\n     GenefxAccumulator *D     =  gfxs->Dacc;\n     u32                Skey  =  gfxs->Skey;\n     u32                Skey0 =  gfxs->Skey & 0x00ffffff;\n     u32                Skey1 =  gfxs->Skey & 0xffff00ff;\n\n#ifdef WORDS_BIGENDIAN\n#define S0_MASK 0xffff00ff\n#define S1_MASK 0x00ffffff\n#else\n#define S0_MASK 0x00ffffff\n#define S1_MASK 0xffff00ff\n#endif\n\n     while (--w) {\n          u32 s = *S++;\n\n          if (s != Skey) {\n               u32 cb, cr;\n\n#ifdef WORDS_BIGENDIAN\n               cb = (s & 0x00ff0000) >> 16;\n               cr =  s & 0x000000ff;\n#else\n               cb =  s & 0x000000ff;\n               cr = (s & 0x00ff0000) >> 16;\n#endif\n\n               if ((s & S0_MASK) != Skey0) {\n                    D[0].YUV.a = 0xff;\n#ifdef WORDS_BIGENDIAN\n                    D[0].YUV.y = (s & 0xff000000) >> 24;\n#else\n                    D[0].YUV.y = (s & 0x0000ff00) >>  8;\n#endif\n                    D[0].YUV.u = cb;\n                    D[0].YUV.v = cr;\n               }\n               else\n                    D[0].YUV.a = 0xf000;\n\n               if ((s & S1_MASK) != Skey1) {\n                    D[1].YUV.a = 0xff;\n#ifdef WORDS_BIGENDIAN\n                    D[1].YUV.y = (s & 0x0000ff00) >> 8;\n#else\n                    D[1].YUV.y = (s & 0xff000000) >>24;\n#endif\n                    D[1].YUV.u = cb;\n                    D[1].YUV.v = cr;\n               }\n               else\n                    D[1].YUV.a = 0xf000;\n          }\n\n          D += 2;\n     }\n\n     if (gfxs->length & 1) {\n          u16 s = *((u16*) S);\n\n          if (s != Skey0) {\n               D->YUV.a = 0xff;\n               D->YUV.y = s >> 8;\n               D->YUV.u = s & 0xff;\n               D->YUV.v = 0x00;\n          }\n          else\n               D->YUV.a = 0xf000;\n     }\n\n#undef S0_MASK\n#undef S1_MASK\n}\n\nstatic void\nSop_lut8_Kto_Dacc( GenefxState *gfxs )\n{\n     int                w       = gfxs->length + 1;\n     u8                *S       = gfxs->Sop[0];\n     GenefxAccumulator *D       = gfxs->Dacc;\n     u32                Skey    = gfxs->Skey;\n     DFBColor          *entries = gfxs->Slut->entries;\n\n     while (--w) {\n          u8 s = *S++;\n\n          if (s != Skey) {\n               D->RGB.a = entries[s].a;\n               D->RGB.r = entries[s].r;\n               D->RGB.g = entries[s].g;\n               D->RGB.b = entries[s].b;\n          }\n          else\n               D->RGB.a = 0xf000;\n\n          ++D;\n     }\n}\n\nstatic void\nSop_alut44_Kto_Dacc( GenefxState *gfxs )\n{\n     int                w       = gfxs->length + 1;\n     u8                *S       = gfxs->Sop[0];\n     GenefxAccumulator *D       = gfxs->Dacc;\n     u32                Skey    = gfxs->Skey;\n     DFBColor          *entries = gfxs->Slut->entries;\n\n     while (--w) {\n          u8 s = *S++;\n\n          if ((s & 0x0f) != Skey) {\n               D->RGB.a = ((s & 0xf0) >> 4) | (s & 0xf0);\n               s &= 0x0f;\n               D->RGB.r = entries[s].r;\n               D->RGB.g = entries[s].g;\n               D->RGB.b = entries[s].b;\n          }\n          else\n               D->RGB.a = 0xf000;\n\n          ++D;\n     }\n}\n\nstatic void\nSop_y444_Kto_Dacc( GenefxState *gfxs )\n{\n     int                w    = gfxs->length + 1;\n     u8                *Sy   = gfxs->Sop[0];\n     u8                *Su   = gfxs->Sop[1];\n     u8                *Sv   = gfxs->Sop[2];\n     GenefxAccumulator *D    = gfxs->Dacc;\n     u32                Skey = gfxs->Skey;\n\n     while (--w) {\n          u8 sy = *Sy++;\n          u8 su = *Su++;\n          u8 sv = *Sv++;\n\n          if (Skey != (u32) ((sy << 16) | (su << 8) | sv)) {\n               D->YUV.a = 0xff;\n               D->YUV.y = sy;\n               D->YUV.u = su;\n               D->YUV.v = sv;\n          }\n          else\n               D->YUV.a = 0xf000;\n\n          ++D;\n     }\n}\n\nstatic void\nSop_avyu_Kto_Dacc( GenefxState *gfxs )\n{\n     int                w    = gfxs->length + 1;\n     u32               *S    = gfxs->Sop[0];\n     GenefxAccumulator *D    = gfxs->Dacc;\n     u32                Skey = gfxs->Skey;\n\n     while (--w) {\n          u32 s = *S++;\n\n          if ((s & 0x00ffffff) != Skey) {\n               D->YUV.a = (s & 0xff000000) >> 24;\n               D->YUV.v = (s & 0x00ff0000) >> 16;\n               D->YUV.y = (s & 0x0000ff00) >>  8;\n               D->YUV.u =  s & 0x000000ff;\n          }\n          else\n               D->YUV.a = 0xf000;\n\n          ++D;\n     }\n}\n\nstatic void\nSop_vyu_Kto_Dacc( GenefxState *gfxs )\n{\n     int                w    = gfxs->length + 1;\n     u8                *S    = gfxs->Sop[0];\n     GenefxAccumulator *D    = gfxs->Dacc;\n     u32                Skey = gfxs->Skey;\n\n     while (--w) {\n#ifdef WORDS_BIGENDIAN\n          u32 s = S[0] << 16 | S[1] << 8 | S[2];\n#else\n          u32 s = S[2] << 16 | S[1] << 8 | S[0];\n#endif\n\n          if (Skey != s) {\n#ifdef WORDS_BIGENDIAN\n               D->YUV.a = 0xff;\n               D->YUV.v = S[0];\n               D->YUV.y = S[1];\n               D->YUV.u = S[2];\n#else\n               D->YUV.a = 0xff;\n               D->YUV.v = S[2];\n               D->YUV.y = S[1];\n               D->YUV.u = S[0];\n#endif\n          }\n          else\n               D->YUV.a = 0xf000;\n\n          S += 3;\n          ++D;\n     }\n}\n\nstatic GenefxFunc Sop_PFI_Kto_Dacc[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Sop_argb1555_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Sop_rgb16_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Sop_rgb24_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Sop_rgb32_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Sop_argb_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = Sop_a8_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = Sop_yuy2_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = Sop_rgb332_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = Sop_uyvy_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = Sop_lut8_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = Sop_alut44_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Sop_airgb_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Sop_argb2554_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Sop_argb4444_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Sop_rgba4444_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Sop_argb6666_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Sop_argb1666_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Sop_rgb18_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Sop_xrgb4444_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Sop_xrgb1555_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Sop_xbgr1555_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Sop_rgba5551_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Sop_y444_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Sop_argb8565_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Sop_avyu_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Sop_vyu_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Sop_abgr_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Sop_rgbaf88871_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Sop_y444_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Sop_bgr24_Kto_Dacc,\n};\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_Sto_Dacc *******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_a8_Sto_Dacc( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u8                *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          u8 s = S[i>>16];\n\n          D->RGB.a = s;\n          D->RGB.r = 0xff;\n          D->RGB.g = 0xff;\n          D->RGB.b = 0xff;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSop_yuy2_Sto_Dacc( GenefxState *gfxs )\n{\n     int                i     =  gfxs->Xphase;\n     int                w     = (gfxs->length >> 1) + 1;\n     u32               *S     =  gfxs->Sop[0];\n     GenefxAccumulator *D     =  gfxs->Dacc;\n     int                SperD =  gfxs->SperD;\n\n     while (--w) {\n          u32 s = S[i>>17];\n\n          D[0].YUV.a = D[1].YUV.a = 0xff;\n#ifdef WORDS_BIGENDIAN\n          D[0].YUV.u = D[1].YUV.u = (s & 0xff000000) >> 24;\n          D[0].YUV.v = D[1].YUV.v = (s & 0x0000ff00) >>  8;\n#else\n          D[0].YUV.u = D[1].YUV.u = (s & 0x0000ff00) >>  8;\n          D[0].YUV.v = D[1].YUV.v = (s & 0xff000000) >> 24;\n#endif\n          D[0].YUV.y = ((u16*) S)[i>>16]         & 0x00ff;\n          D[1].YUV.y = ((u16*) S)[(i+SperD)>>16] & 0x00ff;\n\n          D += 2;\n          i += SperD << 1;\n     }\n\n     if (gfxs->length & 1) {\n          u16 s = ((u16*) S)[i>>17];\n\n          D->YUV.a = 0xff;\n          D->YUV.y = s & 0xff;\n          D->YUV.u = s >> 8;\n          D->YUV.v = 0x00;\n     }\n}\n\nstatic void\nSop_rgb332_Sto_Dacc( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u8                *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          u8 s = S[i>>16];\n\n          D->RGB.a = 0xff;\n          D->RGB.r = EXPAND_3to8(  s >> 5         );\n          D->RGB.g = EXPAND_3to8( (s & 0x1c) >> 2 );\n          D->RGB.b = EXPAND_2to8(  s & 0x03       );\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSop_uyvy_Sto_Dacc( GenefxState *gfxs )\n{\n     int                i     =  gfxs->Xphase;\n     int                w     = (gfxs->length >> 1) + 1;\n     u32               *S     =  gfxs->Sop[0];\n     GenefxAccumulator *D     =  gfxs->Dacc;\n     int                SperD =  gfxs->SperD;\n\n     while (--w) {\n          u32 s = S[i>>17];\n\n          D[0].YUV.a = D[1].YUV.a = 0xff;\n#ifdef WORDS_BIGENDIAN\n          D[0].YUV.u = D[1].YUV.u = (s & 0x00ff0000) >> 16;\n          D[0].YUV.v = D[1].YUV.v =  s & 0x000000ff;\n#else\n          D[0].YUV.u = D[1].YUV.u =  s & 0x000000ff;\n          D[0].YUV.v = D[1].YUV.v = (s & 0x00ff0000) >> 16;\n#endif\n          D[0].YUV.y = (((u16*) S)[i>>16]         & 0xff00) >> 8;\n          D[1].YUV.y = (((u16*) S)[(i+SperD)>>16] & 0xff00) >> 8;\n\n          D += 2;\n          i += SperD << 1;\n     }\n\n     if (gfxs->length & 1) {\n          u16 s = ((u16*) S)[i>>16];\n\n          D->YUV.a = 0xff;\n          D->YUV.y = s >> 8;\n          D->YUV.u = s & 0xff;\n          D->YUV.v = 0x00;\n     }\n}\n\nstatic void\nSop_i420_Sto_Dacc( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u8                *Sy    = gfxs->Sop[0];\n     u8                *Su    = gfxs->Sop[1];\n     u8                *Sv    = gfxs->Sop[2];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          D->YUV.a = 0xff;\n          D->YUV.y = Sy[i>>16];\n          D->YUV.u = Su[i>>17];\n          D->YUV.v = Sv[i>>17];\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSop_lut8_Sto_Dacc( GenefxState *gfxs )\n{\n     int                i       = gfxs->Xphase;\n     int                w       = gfxs->length + 1;\n     u8                *S       = gfxs->Sop[0];\n     GenefxAccumulator *D       = gfxs->Dacc;\n     int                SperD   = gfxs->SperD;\n     DFBColor          *entries = gfxs->Slut->entries;\n\n     while (--w) {\n          u8 s = S[i>>16];\n\n          D->RGB.a = entries[s].a;\n          D->RGB.r = entries[s].r;\n          D->RGB.g = entries[s].g;\n          D->RGB.b = entries[s].b;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSop_alut44_Sto_Dacc( GenefxState *gfxs )\n{\n     int                i       = gfxs->Xphase;\n     int                w       = gfxs->length + 1;\n     u8                *S       = gfxs->Sop[0];\n     GenefxAccumulator *D       = gfxs->Dacc;\n     int                SperD   = gfxs->SperD;\n     DFBColor          *entries = gfxs->Slut->entries;\n\n     while (--w) {\n          u8 s = S[i>>16];\n\n          D->RGB.a = s & 0xf0;\n          s &= 0x0f;\n          D->RGB.r = entries[s].r;\n          D->RGB.g = entries[s].g;\n          D->RGB.b = entries[s].b;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSop_nv12_Sto_Dacc( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u8                *Sy    = gfxs->Sop[0];\n     u16               *Suv   = gfxs->Sop[1];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          D->YUV.a = 0xff;\n          D->YUV.y = Sy[i>>16];\n          D->YUV.u = Suv[i>>17] & 0xff;\n          D->YUV.v = Suv[i>>17] >> 8;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSop_nv21_Sto_Dacc( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u8                *Sy    = gfxs->Sop[0];\n     u16               *Svu   = gfxs->Sop[1];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          D->YUV.a = 0xff;\n          D->YUV.y = Sy[i>>16];\n          D->YUV.u = Svu[i>>17] >> 8;\n          D->YUV.v = Svu[i>>17] & 0xff;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSop_ayuv_Sto_Dacc( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u32               *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          u32 s = S[i>>16];\n\n          D->YUV.a = (s >> 24);\n          D->YUV.y = (s >> 16) & 0xff;\n          D->YUV.u = (s >>  8) & 0xff;\n          D->YUV.v =  s        & 0xff;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSop_a4_Sto_Dacc( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u8                *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          int j = i >> 16;\n          u8  s = S[j>>1];\n\n          if (j & 1)\n               D->RGB.a = (s & 0x0f) | ((s << 4) & 0xf0);\n          else\n               D->RGB.a = (s & 0xf0) | (s >> 4);\n\n          D->RGB.r = 0xff;\n          D->RGB.g = 0xff;\n          D->RGB.b = 0xff;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSop_y444_Sto_Dacc( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u8                *Sy    = gfxs->Sop[0];\n     u8                *Su    = gfxs->Sop[1];\n     u8                *Sv    = gfxs->Sop[2];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          D->YUV.a = 0xff;\n          D->YUV.y = Sy[i>>16];\n          D->YUV.u = Su[i>>16];\n          D->YUV.v = Sv[i>>16];\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSop_avyu_Sto_Dacc( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u32               *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          u32 s = S[i>>16];\n\n          D->YUV.a = (s >> 24);\n          D->YUV.v = (s >> 16) & 0xff;\n          D->YUV.y = (s >>  8) & 0xff;\n          D->YUV.u =  s        & 0xff;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSop_vyu_Sto_Dacc( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u8                *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          int pixelstart = (i >> 16) * 3;\n\n#ifdef WORDS_BIGENDIAN\n          D->YUV.a = 0xff;\n          D->YUV.v = S[pixelstart+0];\n          D->YUV.y = S[pixelstart+1];\n          D->YUV.u = S[pixelstart+2];\n#else\n          D->YUV.a = 0xff;\n          D->YUV.v = S[pixelstart+2];\n          D->YUV.y = S[pixelstart+1];\n          D->YUV.u = S[pixelstart+0];\n#endif\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSop_nv24_Sto_Dacc( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u8                *Sy    = gfxs->Sop[0];\n     u16               *Suv   = gfxs->Sop[1];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          D->YUV.a = 0xff;\n          D->YUV.y = Sy[i>>16];\n          D->YUV.u = Suv[i>>16] & 0xff;\n          D->YUV.v = Suv[i>>16] >> 8;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSop_nv42_Sto_Dacc( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u8                *Sy    = gfxs->Sop[0];\n     u16               *Svu   = gfxs->Sop[1];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          D->YUV.a = 0xff;\n          D->YUV.y = Sy[i>>16];\n          D->YUV.u = Svu[i>>16] >> 8;\n          D->YUV.v = Svu[i>>16] & 0xff;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic GenefxFunc Sop_PFI_Sto_Dacc[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Sop_argb1555_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Sop_rgb16_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Sop_rgb24_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Sop_rgb32_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Sop_argb_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = Sop_a8_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = Sop_yuy2_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = Sop_rgb332_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = Sop_uyvy_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = Sop_i420_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = Sop_i420_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = Sop_lut8_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = Sop_alut44_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Sop_airgb_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = Sop_nv12_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = Sop_nv12_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Sop_argb2554_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Sop_argb4444_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Sop_rgba4444_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = Sop_nv21_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = Sop_ayuv_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = Sop_a4_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Sop_argb1666_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Sop_argb6666_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Sop_rgb18_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Sop_xrgb4444_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Sop_xrgb1555_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Sop_xbgr1555_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Sop_rgba5551_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Sop_y444_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Sop_argb8565_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Sop_avyu_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Sop_vyu_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = Sop_i420_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Sop_abgr_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Sop_rgbaf88871_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = Sop_nv21_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = Sop_i420_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Sop_y444_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = Sop_nv24_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = Sop_nv42_Sto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Sop_bgr24_Sto_Dacc,\n};\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_SKto_Dacc ******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_a8_SKto_Dacc( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u8                *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                SperD = gfxs->SperD;\n\n     /* No color to key. */\n     while (--w) {\n          u8 s = S[i>>16];\n\n          D->RGB.a = s;\n          D->RGB.r = 0xff;\n          D->RGB.g = 0xff;\n          D->RGB.b = 0xff;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSop_yuy2_SKto_Dacc( GenefxState *gfxs )\n{\n     int                i     =  gfxs->Xphase;\n     int                w     = (gfxs->length >> 1) + 1;\n     u32               *S     =  gfxs->Sop[0];\n     GenefxAccumulator *D     =  gfxs->Dacc;\n     u32                Ky    =  gfxs->Skey & 0x000000ff;\n#ifdef WORDS_BIGENDIAN\n     u32                Kcb   = (gfxs->Skey & 0xff000000) >> 24;\n     u32                Kcr   = (gfxs->Skey & 0x0000ff00) >>  8;\n#else\n     u32                Kcb   = (gfxs->Skey & 0x0000ff00) >>  8;\n     u32                Kcr   = (gfxs->Skey & 0xff000000) >> 24;\n#endif\n     int                SperD =  gfxs->SperD;\n\n     while (--w) {\n          u32 s = S[i>>17];\n          u32 y0, cb, y1, cr;\n\n#ifdef WORDS_BIGENDIAN\n          cb = (s & 0xff000000) >> 24;\n          cr = (s & 0x0000ff00) >>  8;\n#else\n          cb = (s & 0x0000ff00) >>  8;\n          cr = (s & 0xff000000) >> 24;\n#endif\n          y0 = ((u16*) S)[i>>16]         & 0x00ff;\n          y1 = ((u16*) S)[(i+SperD)>>16] & 0x00ff;\n\n          if (y0 != Ky || cb != Kcb || cr != Kcr) {\n               D[0].YUV.a = 0xff;\n               D[0].YUV.y = y0;\n               D[0].YUV.u = cb;\n               D[0].YUV.v = cr;\n          }\n          else\n               D[0].YUV.a = 0xf000;\n\n          if (y0 != Ky || cb != Kcb || cr != Kcr) {\n               D[1].YUV.a = 0xff;\n               D[1].YUV.y = y1;\n               D[1].YUV.u = cb;\n               D[1].YUV.v = cr;\n          }\n          else\n               D[1].YUV.a = 0xf000;\n\n          D += 2;\n          i += SperD << 1;\n     }\n\n     if (gfxs->length & 1) {\n          u16 s = ((u16*) S)[i>>16];\n\n          if (s != (Ky | (Kcb << 8))) {\n               D->YUV.a = 0xff;\n               D->YUV.y = s & 0xff;\n               D->YUV.u = s >> 8;\n               D->YUV.v = 0x00;\n          }\n          else\n               D->YUV.a = 0xf000;\n     }\n}\n\nstatic void\nSop_rgb332_SKto_Dacc( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u8                *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     u8                 Skey  = gfxs->Skey;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          u8 s = S[i>>16];\n\n          if (s != Skey) {\n               D->RGB.a = 0xff;\n               D->RGB.r = EXPAND_3to8(  s >> 5         );\n               D->RGB.g = EXPAND_3to8( (s & 0x1c) >> 2 );\n               D->RGB.b = EXPAND_2to8(  s & 0x03       );\n          }\n          else\n               D->RGB.a = 0xf000;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSop_uyvy_SKto_Dacc( GenefxState *gfxs )\n{\n     int                i     =  gfxs->Xphase;\n     int                w     = (gfxs->length >> 1) + 1;\n     u32               *S     =  gfxs->Sop[0];\n     GenefxAccumulator *D     =  gfxs->Dacc;\n     u32                Ky    = (gfxs->Skey & 0x0000ff00) >>  8;\n#ifdef WORDS_BIGENDIAN\n     u32                Kcb   = (gfxs->Skey & 0x00ff0000) >> 16;\n     u32                Kcr   =  gfxs->Skey & 0x000000ff;\n#else\n     u32                Kcb   =  gfxs->Skey & 0x000000ff;\n     u32                Kcr   = (gfxs->Skey & 0x00ff0000) >> 16;\n#endif\n     int                SperD =  gfxs->SperD;\n\n     while (--w) {\n          u32 s = S[i>>17];\n          u32 cb, y0, cr, y1;\n\n#ifdef WORDS_BIGENDIAN\n          cb = (s & 0x00ff0000) >> 16;\n          cr =  s & 0x000000ff;\n#else\n          cb =  s & 0x000000ff;\n          cr = (s & 0x00ff0000) >> 16;\n#endif\n          y0 = (((u16*) S)[i>>16]         & 0xff00) >> 8;\n          y1 = (((u16*) S)[(i+SperD)>>16] & 0xff00) >> 8;\n\n          if (y0 != Ky || cb != Kcb || cr != Kcr) {\n               D[0].YUV.a = 0xff;\n               D[0].YUV.y = y0;\n               D[0].YUV.u = cb;\n               D[0].YUV.v = cr;\n          }\n          else\n              D[0].YUV.a = 0xf000;\n\n          if (y0 != Ky || cb != Kcb || cr != Kcr) {\n               D[1].YUV.a = 0xff;\n               D[1].YUV.y = y1;\n               D[1].YUV.u = cb;\n               D[1].YUV.v = cr;\n          }\n          else\n               D[1].YUV.a = 0xf000;\n\n          D += 2;\n          i += SperD << 1;\n     }\n\n     if (gfxs->length & 1) {\n          u16 s = ((u16*) S)[i>>16];\n\n          if (s != (Kcb | (Ky << 8))) {\n               D->YUV.a = 0xff;\n               D->YUV.y = s >> 8;\n               D->YUV.u = s & 0xff;\n               D->YUV.v = 0x00;\n          }\n          else\n               D->YUV.a = 0xf000;\n     }\n}\n\nstatic void\nSop_lut8_SKto_Dacc( GenefxState *gfxs )\n{\n     int                i       = gfxs->Xphase;\n     int                w       = gfxs->length + 1;\n     u8                *S       = gfxs->Sop[0];\n     GenefxAccumulator *D       = gfxs->Dacc;\n     u32                Skey    = gfxs->Skey;\n     int                SperD   = gfxs->SperD;\n     DFBColor          *entries = gfxs->Slut->entries;\n\n     while (--w) {\n          u8 s = S[i>>16];\n\n          if (s != Skey) {\n               D->RGB.a = entries[s].a;\n               D->RGB.r = entries[s].r;\n               D->RGB.g = entries[s].g;\n               D->RGB.b = entries[s].b;\n          }\n          else\n               D->RGB.a = 0xf000;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSop_alut44_SKto_Dacc( GenefxState *gfxs )\n{\n     int                i       = gfxs->Xphase;\n     int                w       = gfxs->length + 1;\n     u8                *S       = gfxs->Sop[0];\n     GenefxAccumulator *D       = gfxs->Dacc;\n     u32                Skey    = gfxs->Skey;\n     int                SperD   = gfxs->SperD;\n     DFBColor          *entries = gfxs->Slut->entries;\n\n     while (--w) {\n          u8 s = S[i>>16];\n\n          if ((s & 0x0f) != Skey) {\n               D->RGB.a = ((s & 0xf0) >> 4) | (s & 0xf0);\n               s &= 0x0f;\n               D->RGB.r = entries[s].r;\n               D->RGB.g = entries[s].g;\n               D->RGB.b = entries[s].b;\n          }\n          else\n               D->RGB.a = 0xf000;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSop_y444_SKto_Dacc( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u8                *Sy    = gfxs->Sop[0];\n     u8                *Su    = gfxs->Sop[1];\n     u8                *Sv    = gfxs->Sop[2];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     u32                Skey  = gfxs->Skey;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          u8 sy = Sy[i>>16];\n          u8 su = Su[i>>16];\n          u8 sv = Sv[i>>16];\n\n          if (Skey != (u32) (sy << 16 | su << 8 | sv)) {\n               D->YUV.a = 0xff;\n               D->YUV.y = sy;\n               D->YUV.u = su;\n               D->YUV.v = sv;\n          }\n          else\n               D->YUV.a = 0xff00;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSop_avyu_SKto_Dacc( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u32               *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     u32                Skey  = gfxs->Skey;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          u32 s = S[i>>16];\n\n          if ((s & 0x00ffffff) != Skey) {\n               D->YUV.a = (s & 0xff000000) >> 24;\n               D->YUV.v = (s & 0x00ff0000) >> 16;\n               D->YUV.y = (s & 0x0000ff00) >>  8;\n               D->YUV.u =  s & 0x000000ff;\n          }\n          else\n               D->YUV.a = 0xf000;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSop_vyu_SKto_Dacc( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u8                *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     u32                Skey  = gfxs->Skey;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          int pixelstart = (i >> 16) * 3;\n\n#ifdef WORDS_BIGENDIAN\n          u32 s = S[pixelstart+0] << 16 | S[pixelstart+1] << 8 | S[pixelstart+2];\n#else\n          u32 s = S[pixelstart+2] << 16 | S[pixelstart+1] << 8 | S[pixelstart+0];\n#endif\n\n          if (Skey != s) {\n#ifdef WORDS_BIGENDIAN\n               D->YUV.a = 0xff;\n               D->YUV.v = S[pixelstart+0];\n               D->YUV.y = S[pixelstart+1];\n               D->YUV.u = S[pixelstart+2];\n#else\n               D->YUV.a = 0xff;\n               D->YUV.v = S[pixelstart+2];\n               D->YUV.y = S[pixelstart+1];\n               D->YUV.u = S[pixelstart+0];\n#endif\n          }\n          else\n               D->YUV.a = 0xf000;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic GenefxFunc Sop_PFI_SKto_Dacc[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Sop_argb1555_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Sop_rgb16_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Sop_rgb24_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Sop_rgb32_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Sop_argb_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = Sop_a8_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = Sop_yuy2_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = Sop_rgb332_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = Sop_uyvy_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = Sop_lut8_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = Sop_alut44_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Sop_airgb_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Sop_argb2554_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Sop_argb4444_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Sop_rgba4444_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Sop_argb1666_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Sop_argb6666_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Sop_rgb18_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Sop_xrgb4444_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Sop_xrgb1555_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Sop_xbgr1555_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Sop_rgba5551_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Sop_y444_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Sop_argb8565_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Sop_avyu_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Sop_vyu_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Sop_abgr_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Sop_rgbaf88871_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Sop_y444_SKto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Sop_bgr24_SKto_Dacc,\n};\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_TEX_to_Dacc ****************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_a8_TEX_to_Dacc( GenefxState *gfxs )\n{\n     int                s     = gfxs->s;\n     int                t     = gfxs->t;\n     int                w     = gfxs->length + 1;\n     u8                *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                SperD = gfxs->SperD;\n     int                TperD = gfxs->TperD;\n\n     while (--w) {\n          D->RGB.a = S[(s>>16)+(t>>16)*gfxs->src_pitch];\n          D->RGB.r = 0xff;\n          D->RGB.g = 0xff;\n          D->RGB.b = 0xff;\n\n          ++D;\n          s += SperD;\n          t += TperD;\n     }\n}\n\nstatic GenefxFunc Sop_PFI_TEX_to_Dacc[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Sop_argb1555_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Sop_rgb16_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Sop_rgb24_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Sop_rgb32_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Sop_argb_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = Sop_a8_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Sop_airgb_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Sop_argb2554_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Sop_argb4444_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Sop_rgba4444_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Sop_argb1666_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Sop_argb6666_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Sop_rgb18_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Sop_xrgb4444_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Sop_xrgb1555_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Sop_xbgr1555_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Sop_rgba5551_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Sop_argb8565_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Sop_abgr_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Sop_rgbaf88871_TEX_to_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Sop_bgr24_TEX_to_Dacc,\n};\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_TEX_Kto_Dacc ***************************************************************\n **********************************************************************************************************************/\n\nstatic GenefxFunc Sop_PFI_TEX_Kto_Dacc[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Sop_argb1555_TEX_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Sop_rgb16_TEX_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Sop_rgb24_TEX_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Sop_rgb32_TEX_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Sop_argb_TEX_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Sop_airgb_TEX_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Sop_argb2554_TEX_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Sop_argb4444_TEX_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Sop_rgba4444_TEX_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Sop_argb1666_TEX_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Sop_argb6666_TEX_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Sop_rgb18_TEX_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Sop_xrgb4444_TEX_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Sop_xrgb1555_TEX_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Sop_xbgr1555_TEX_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Sop_rgba5551_TEX_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Sop_argb8565_TEX_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Sop_abgr_TEX_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Sop_rgbaf88871_TEX_Kto_Dacc,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Sop_bgr24_TEX_Kto_Dacc,\n};\n\n/**********************************************************************************************************************\n ********************************* Sacc_to_Aop_PFI ********************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSacc_to_Aop_a8( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *S = gfxs->Sacc;\n     u8                *D = gfxs->Aop[0];\n\n     while (--w) {\n          if (!(S->RGB.a & 0xf000)) {\n               *D = (S->RGB.a & 0xff00) ? 0xff : S->RGB.a;\n          }\n\n          ++S;\n          ++D;\n     }\n}\n\nstatic void\nSacc_to_Aop_yuy2( GenefxState *gfxs )\n{\n     int                l;\n     int                w = gfxs->length;\n     GenefxAccumulator *S = gfxs->Sacc;\n     u16               *D = gfxs->Aop[0];\n\n     if ((long) D & 2) {\n          if (!(S->YUV.a & 0xf00)) {\n               *D = ((S->YUV.y & 0xff00) ? 0x00ff : S->YUV.y) | ((S->YUV.v & 0xff00) ? 0xff00 : (S->YUV.v << 8));\n          }\n\n          ++S;\n          ++D;\n          --w;\n     }\n\n     for (l = w >> 1; l--;) {\n          if (!(S[0].YUV.a & 0xf000) && !(S[1].YUV.a & 0xf000)) {\n               u32 y0, cb, y1, cr;\n\n               y0 = (S[0].YUV.y & 0xff00) ? 0xff : S[0].YUV.y;\n               y1 = (S[1].YUV.y & 0xff00) ? 0xff : S[1].YUV.y;\n\n               cb = (S[0].YUV.u + S[1].YUV.u) >> 1;\n               if (cb & 0xff00)\n                    cb = 0xff;\n\n               cr = (S[0].YUV.v + S[1].YUV.v) >> 1;\n               if (cr & 0xff00)\n                    cr = 0xff;\n\n#ifdef WORDS_BIGENDIAN\n               *((u32*) D) = y1 | (cr << 8) | (y0 << 16) | (cb << 24);\n#else\n               *((u32*) D) = y0 | (cb << 8) | (y1 << 16) | (cr << 24);\n#endif\n          }\n          else if (!(S[0].YUV.a & 0xf000)) {\n               D[0] = ((S[0].YUV.y & 0xff00) ? 0x00ff :  S[0].YUV.y) |\n                      ((S[0].YUV.u & 0xff00) ? 0xff00 : (S[0].YUV.u << 8));\n          }\n          else if (!(S[1].YUV.a & 0xf000)) {\n               D[1] = ((S[1].YUV.y & 0xff00) ? 0x00ff :  S[1].YUV.y) |\n                      ((S[1].YUV.v & 0xff00) ? 0xff00 : (S[1].YUV.v << 8));\n          }\n\n          S += 2;\n          D += 2;\n     }\n\n     if (w & 1) {\n          if (!(S->YUV.a & 0xf00)) {\n               *D = ((S->YUV.y & 0xff00) ? 0x00ff : S->YUV.y) | ((S->YUV.u & 0xff00) ? 0xff00 : (S->YUV.u << 8));\n          }\n     }\n}\n\nstatic void\nSacc_to_Aop_rgb332( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *S = gfxs->Sacc;\n     u8                *D = gfxs->Aop[0];\n\n     while (--w) {\n          if (!(S->RGB.a & 0xf000)) {\n               *D = PIXEL_RGB332( (S->RGB.r & 0xff00) ? 0xff : S->RGB.r,\n                                  (S->RGB.g & 0xff00) ? 0xff : S->RGB.g,\n                                  (S->RGB.b & 0xff00) ? 0xff : S->RGB.b );\n          }\n\n          ++S;\n          ++D;\n     }\n}\n\nstatic void\nSacc_to_Aop_uyvy( GenefxState *gfxs )\n{\n     int                l;\n     int                w = gfxs->length;\n     GenefxAccumulator *S = gfxs->Sacc;\n     u16               *D = gfxs->Aop[0];\n\n     if ((long) D & 2) {\n          if (!(S->YUV.a & 0xf00)) {\n               *D = ((S->YUV.v & 0xff00) ? 0x00ff : S->YUV.v) | ((S->YUV.y & 0xff00) ? 0xff00 : (S->YUV.y << 8));\n          }\n\n          ++S;\n          ++D;\n          --w;\n     }\n\n     for (l = w >> 1; l--;) {\n          if (!(S[0].YUV.a & 0xf000) && !(S[1].YUV.a & 0xf000)) {\n               u32 cb, y0, cr, y1;\n\n               y0 = (S[0].YUV.y & 0xff00) ? 0xff : S[0].YUV.y;\n               y1 = (S[1].YUV.y & 0xff00) ? 0xff : S[1].YUV.y;\n\n               cb = (S[0].YUV.u + S[1].YUV.u) >> 1;\n               if (cb & 0xff00)\n                    cb = 0xff;\n\n               cr = (S[0].YUV.v + S[1].YUV.v) >> 1;\n               if (cr & 0xff00)\n                    cr = 0xff;\n\n#ifdef WORDS_BIGENDIAN\n               *((u32*) D) = cr | (y1 << 8) | (cb << 16) | (y0 << 24);\n#else\n               *((u32*) D) = cb | (y0 << 8) | (cr << 16) | (y1 << 24);\n#endif\n          }\n          else if (!(S[0].YUV.a & 0xf000)) {\n               D[0] = ((S[0].YUV.u & 0xff00) ? 0x00ff :  S[0].YUV.u) |\n                      ((S[0].YUV.y & 0xff00) ? 0xff00 : (S[0].YUV.y << 8));\n          }\n          else if (!(S[1].YUV.a & 0xf000)) {\n               D[1] = ((S[1].YUV.v & 0xff00) ? 0x00ff :  S[1].YUV.v) |\n                      ((S[1].YUV.y & 0xff00) ? 0xff00 : (S[1].YUV.y << 8));\n          }\n\n          S += 2;\n          D += 2;\n     }\n\n     if (w & 1) {\n          if (!(S->YUV.a & 0xf00)) {\n               *D = ((S->YUV.u & 0xff00) ? 0x00ff : S->YUV.u) | ((S->YUV.y & 0xff00) ? 0xff00 : (S->YUV.y << 8));\n          }\n     }\n}\n\nstatic void\nSacc_to_Aop_i420( GenefxState *gfxs )\n{\n     int                w  = gfxs->length + 1;\n     GenefxAccumulator *S  = gfxs->Sacc;\n     u8                *Dy = gfxs->Aop[0];\n\n     while (--w) {\n          if (!(S->YUV.a & 0xf000)) {\n               *Dy = (S->YUV.y & 0xff00) ? 0xff : S->YUV.y;\n          }\n\n          ++S;\n          ++Dy;\n     }\n\n     if (gfxs->AopY & 1) {\n          u8 *Du = gfxs->Aop[1];\n          u8 *Dv = gfxs->Aop[2];\n\n          w = (gfxs->length >> 1) + 1;\n          S =  gfxs->Sacc;\n\n          while (--w) {\n               if (!(S[0].YUV.a & 0xf000) && !(S[1].YUV.a & 0xf000)) {\n                    u32 tmp;\n\n                    tmp = (S[0].YUV.u + S[1].YUV.u) >> 1;\n                    if (tmp & 0xff00)\n                         tmp = 0xff;\n                    *Du = tmp;\n\n                    tmp = (S[0].YUV.v + S[1].YUV.v) >> 1;\n                    if (tmp & 0xff00)\n                         tmp = 0xff;\n                    *Dv = tmp;\n\n               }\n               else if (!(S[0].YUV.a & 0xf000)) {\n                    *Du = (*Du + ((S[0].YUV.u & 0xff00) ? 0xff : S[0].YUV.u)) >> 1;\n                    *Dv = (*Dv + ((S[0].YUV.v & 0xff00) ? 0xff : S[0].YUV.v)) >> 1;\n               }\n               else if (!(S[1].YUV.a & 0xf000)) {\n                    *Du = (*Du + ((S[1].YUV.u & 0xff00) ? 0xff : S[1].YUV.u)) >> 1;\n                    *Dv = (*Dv + ((S[1].YUV.v & 0xff00) ? 0xff : S[1].YUV.v)) >> 1;\n               }\n\n               S += 2;\n               ++Du; ++Dv;\n          }\n     }\n}\n\nstatic void\nSacc_to_Aop_lut8( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *S = gfxs->Sacc;\n     u8                *D = gfxs->Aop[0];\n\n     while (--w) {\n          if (!(S->RGB.a & 0xf000)) {\n               *D = dfb_palette_search( gfxs->Alut,\n                                        (S->RGB.r & 0xff00) ? 0xff : S->RGB.r,\n                                        (S->RGB.g & 0xff00) ? 0xff : S->RGB.g,\n                                        (S->RGB.b & 0xff00) ? 0xff : S->RGB.b,\n                                        (S->RGB.a & 0xff00) ? 0xff : S->RGB.a );\n          }\n\n          ++S;\n          ++D;\n     }\n}\n\nstatic void\nSacc_to_Aop_alut44( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *S = gfxs->Sacc;\n     u8                *D = gfxs->Aop[0];\n\n     while (--w) {\n          if (!(S->RGB.a & 0xf000)) {\n               *D = (S->RGB.a & 0xff00) ?\n                    0xf0 : (S->RGB.a & 0xf0) + dfb_palette_search( gfxs->Alut,\n                                                                   (S->RGB.r & 0xff00) ? 0xff : S->RGB.r,\n                                                                   (S->RGB.g & 0xff00) ? 0xff : S->RGB.g,\n                                                                   (S->RGB.b & 0xff00) ? 0xff : S->RGB.b,\n                                                                   0x80 );\n          }\n\n          ++S;\n          ++D;\n     }\n}\n\nstatic void\nSacc_to_Aop_nv12( GenefxState *gfxs )\n{\n     int                w  = gfxs->length + 1;\n     GenefxAccumulator *S  = gfxs->Sacc;\n     u8                *Dy = gfxs->Aop[0];\n\n     while (--w) {\n          if (!(S->YUV.a & 0xf000)) {\n               *Dy = (S->YUV.y & 0xff00) ? 0xff : S->YUV.y;\n          }\n\n          ++S;\n          ++Dy;\n     }\n\n     if (gfxs->AopY & 1) {\n          u16 *Duv = gfxs->Aop[1];\n\n          w = (gfxs->length >> 1) + 1;\n          S =  gfxs->Sacc;\n\n          while (--w) {\n               u32 cb, cr;\n\n               if (!(S[0].YUV.a & 0xf000) && !(S[1].YUV.a & 0xf000)) {\n                    cb = (S[0].YUV.u + S[1].YUV.u) >> 1;\n                    if (cb & 0xff00)\n                         cb = 0xff;\n\n                    cr = (S[0].YUV.v + S[1].YUV.v) >> 1;\n                    if (cr & 0xff00)\n                         cr = 0xff;\n\n                    *Duv = cb | (cr << 8);\n               }\n               else if (!(S[0].YUV.a & 0xf000)) {\n                    cb   = ((*Duv & 0xff) + ((S[0].YUV.u & 0xff00) ? 0xff : S[0].YUV.u)) >> 1;\n                    cr   = ((*Duv >> 8)   + ((S[0].YUV.v & 0xff00) ? 0xff : S[0].YUV.v)) >> 1;\n                    *Duv = cb | (cr << 8);\n               }\n               else if (!(S[1].YUV.a & 0xf000)) {\n                    cb   = ((*Duv & 0xff) + ((S[1].YUV.u & 0xff00) ? 0xff : S[1].YUV.u)) >> 1;\n                    cr   = ((*Duv >> 8)   + ((S[1].YUV.v & 0xff00) ? 0xff : S[1].YUV.v)) >> 1;\n                    *Duv = cb | (cr << 8);\n               }\n\n               S += 2;\n               ++Duv;\n          }\n     }\n}\n\nstatic void\nSacc_to_Aop_nv16( GenefxState *gfxs )\n{\n     int                w   = gfxs->length + 1;\n     GenefxAccumulator *S   = gfxs->Sacc;\n     u8                *Dy  = gfxs->Aop[0];\n     u16               *Duv = gfxs->Aop[1];\n\n     while (--w) {\n          if (!(S->YUV.a & 0xf000)) {\n               *Dy = (S->YUV.y & 0xff00) ? 0xff : S->YUV.y;\n          }\n\n          ++S;\n          ++Dy;\n     }\n\n     w = (gfxs->length >> 1) + 1;\n     S =  gfxs->Sacc;\n\n     while (--w) {\n          u32 cb, cr;\n\n          if (!(S[0].YUV.a & 0xf000) && !(S[1].YUV.a & 0xf000)) {\n               cb = (S[0].YUV.u + S[1].YUV.u) >> 1;\n               if (cb & 0xff00)\n                    cb = 0xff;\n\n               cr = (S[0].YUV.v + S[1].YUV.v) >> 1;\n               if (cr & 0xff00)\n                    cr = 0xff;\n\n               *Duv = cb | (cr << 8);\n          }\n          else if (!(S[0].YUV.a & 0xf000)) {\n               cb   = ((*Duv & 0xff) + ((S[0].YUV.u & 0xff00) ? 0xff : S[0].YUV.u)) >> 1;\n               cr   = ((*Duv >> 8)   + ((S[0].YUV.v & 0xff00) ? 0xff : S[0].YUV.v)) >> 1;\n               *Duv = cb | (cr << 8);\n          }\n          else if (!(S[1].YUV.a & 0xf000)) {\n               cb   = ((*Duv & 0xff) + ((S[1].YUV.u & 0xff00) ? 0xff : S[1].YUV.u)) >> 1;\n               cr   = ((*Duv >> 8)   + ((S[1].YUV.v & 0xff00) ? 0xff : S[1].YUV.v)) >> 1;\n               *Duv = cb | (cr << 8);\n          }\n\n          S += 2;\n          ++Duv;\n     }\n}\n\nstatic void\nSacc_to_Aop_nv21( GenefxState *gfxs )\n{\n     int                w  = gfxs->length + 1;\n     GenefxAccumulator *S  = gfxs->Sacc;\n     u8                *Dy = gfxs->Aop[0];\n\n     while (--w) {\n          if (!(S->YUV.a & 0xf000)) {\n               *Dy = (S->YUV.y & 0xff00) ? 0xff : S->YUV.y;\n          }\n\n          ++S;\n          ++Dy;\n     }\n\n     if (gfxs->AopY & 1) {\n          u16 *Dvu = gfxs->Aop[1];\n\n          w = (gfxs->length >> 1) + 1;\n          S =  gfxs->Sacc;\n\n          while (--w) {\n               u32 cb, cr;\n\n               if (!(S[0].YUV.a & 0xf000) && !(S[1].YUV.a & 0xf000)) {\n                    cb = (S[0].YUV.u + S[1].YUV.u) >> 1;\n                    if (cb & 0xff00)\n                         cb = 0xff;\n\n                    cr = (S[0].YUV.v + S[1].YUV.v) >> 1;\n                    if (cr & 0xff00)\n                         cr = 0xff;\n\n                    *Dvu = cr | (cb << 8);\n               }\n               else if (!(S[0].YUV.a & 0xf000)) {\n                    cb   = ((*Dvu >> 8)   + ((S[0].YUV.u & 0xff00) ? 0xff : S[0].YUV.u)) >> 1;\n                    cr   = ((*Dvu & 0xff) + ((S[0].YUV.v & 0xff00) ? 0xff : S[0].YUV.v)) >> 1;\n                    *Dvu = cr | (cb << 8);\n               }\n               else if (!(S[1].YUV.a & 0xf000)) {\n                    cb   = ((*Dvu >> 8)   + ((S[1].YUV.u & 0xff00) ? 0xff : S[1].YUV.u)) >> 1;\n                    cr   = ((*Dvu & 0xff) + ((S[1].YUV.v & 0xff00) ? 0xff : S[1].YUV.v)) >> 1;\n                    *Dvu = cr | (cb << 8);\n               }\n\n               S += 2;\n               ++Dvu;\n          }\n     }\n}\n\nstatic void\nSacc_to_Aop_ayuv( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *S = gfxs->Sacc;\n     u32               *D = gfxs->Aop[0];\n\n     while (--w) {\n          if (!(S->YUV.a & 0xf000)) {\n               *D = PIXEL_AYUV( (S->YUV.a & 0xff00) ? 0xff : S->YUV.a,\n                                (S->YUV.y & 0xff00) ? 0xff : S->YUV.y,\n                                (S->YUV.u & 0xff00) ? 0xff : S->YUV.u,\n                                (S->YUV.v & 0xff00) ? 0xff : S->YUV.v );\n          }\n\n          ++S;\n          ++D;\n     }\n}\n\nstatic void\nSacc_to_Aop_a4( GenefxState *gfxs )\n{\n     int                w = (gfxs->length >> 1) + 1;\n     GenefxAccumulator *S =  gfxs->Sacc;\n     u8                *D =  gfxs->Aop[0];\n\n     while (--w) {\n          if (!(S[0].RGB.a & 0xf000) && !(S[1].RGB.a & 0xf000)) {\n               *D = ((S[0].RGB.a & 0xff00) ? 0xf0 : (S[0].RGB.a & 0xf0)) |\n                    ((S[1].RGB.a & 0xff00) ? 0x0f : (S[1].RGB.a >> 4));\n          }\n          else if (!(S[0].RGB.a & 0xf000)) {\n               *D = (*D & 0x0f) | ((S[0].RGB.a & 0xff00) ? 0xf0 : (S[0].RGB.a & 0xf0));\n          }\n          else if (!(S[1].RGB.a & 0xf000)) {\n               *D = (*D & 0xf0) | ((S[1].RGB.a & 0xff00) ? 0x0f : (S[1].RGB.a >> 4));\n          }\n\n          S += 2;\n          ++D;\n     }\n\n     if (gfxs->length & 1) {\n          if (!(S->RGB.a & 0xf000))\n               *D = (*D & 0x0f) | ((S->RGB.a & 0xff00) ? 0xf0 : (S->RGB.a & 0xf0));\n     }\n}\n\nstatic void\nSacc_to_Aop_y444( GenefxState *gfxs )\n{\n     int                w  = gfxs->length + 1;\n     GenefxAccumulator *S  = gfxs->Sacc;\n     u8                *Dy = gfxs->Aop[0];\n     u8                *Du = gfxs->Aop[1];\n     u8                *Dv = gfxs->Aop[2];\n\n     while (--w) {\n          if (!(S->YUV.a & 0xf000)) {\n               *Dy = (S->YUV.y & 0xff00) ? 0xff : S->YUV.y;\n               *Du = (S->YUV.u & 0xff00) ? 0xff : S->YUV.u;\n               *Dv = (S->YUV.v & 0xff00) ? 0xff : S->YUV.v;\n          }\n\n          ++S;\n          ++Dy; ++Du; ++Dv;\n     }\n}\n\nstatic void\nSacc_to_Aop_avyu( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *S = gfxs->Sacc;\n     u32               *D = gfxs->Aop[0];\n\n     while (--w) {\n          if (!(S->YUV.a & 0xf000)) {\n               *D = PIXEL_AVYU( (S->YUV.a & 0xff00) ? 0xff : S->YUV.a,\n                                (S->YUV.y & 0xff00) ? 0xff : S->YUV.y,\n                                (S->YUV.u & 0xff00) ? 0xff : S->YUV.u,\n                                (S->YUV.v & 0xff00) ? 0xff : S->YUV.v );\n          }\n\n          ++S;\n          ++D;\n     }\n}\n\nstatic void\nSacc_to_Aop_vyu( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *S = gfxs->Sacc;\n     u8                *D = gfxs->Aop[0];\n\n     while (--w) {\n          if (!(S->YUV.a & 0xf000)) {\n               u8 y = (S->YUV.y & 0xff00) ? 0xff : S->YUV.y;\n               u8 u = (S->YUV.u & 0xff00) ? 0xff : S->YUV.u;\n               u8 v = (S->YUV.v & 0xff00) ? 0xff : S->YUV.v;\n\n#ifdef WORDS_BIGENDIAN\n               D[0] = v;\n               D[1] = y;\n               D[2] = u;\n#else\n               D[0] = u;\n               D[1] = y;\n               D[2] = v;\n#endif\n          }\n\n          ++S;\n          D += 3;\n     }\n}\n\nstatic void\nSacc_to_Aop_y42b( GenefxState *gfxs )\n{\n     int                w  = gfxs->length + 1;\n     GenefxAccumulator *S  = gfxs->Sacc;\n     u8                *Dy = gfxs->Aop[0];\n     u8                *Du = gfxs->Aop[1];\n     u8                *Dv = gfxs->Aop[2];\n\n     while (--w) {\n          if (!(S->YUV.a & 0xf000)) {\n               *Dy = (S->YUV.y & 0xff00) ? 0xff : S->YUV.y;\n          }\n\n          ++S;\n          ++Dy;\n     }\n\n     w = (gfxs->length / 2) + 1;\n     S =  gfxs->Sacc;\n\n     while (--w) {\n          if (!(S[0].YUV.a & 0xf000) && !(S[1].YUV.a & 0xf000)) {\n               u32 tmp;\n\n               tmp = (S[0].YUV.u + S[1].YUV.u) / 2;\n               if (tmp & 0xff00)\n                    tmp = 0xff;\n               *Du = tmp;\n\n               tmp = (S[0].YUV.v + S[1].YUV.v) / 2;\n               if (tmp & 0xff00)\n                    tmp = 0xff;\n               *Dv = tmp;\n          }\n          else if (!(S[0].YUV.a & 0xf000)) {\n               *Du = (*Du + ((S[0].YUV.u & 0xff00) ? 0xff : S[0].YUV.u)) / 2;\n               *Dv = (*Dv + ((S[0].YUV.v & 0xff00) ? 0xff : S[0].YUV.v)) / 2;\n          }\n          else if (!(S[1].YUV.a & 0xf000)) {\n               *Du = (*Du + ((S[1].YUV.u & 0xff00) ? 0xff : S[1].YUV.u)) / 2;\n               *Dv = (*Dv + ((S[1].YUV.v & 0xff00) ? 0xff : S[1].YUV.v)) / 2;\n          }\n\n          S += 2;\n          ++Du; ++Dv;\n     }\n}\n\nstatic void\nSacc_to_Aop_nv61( GenefxState *gfxs )\n{\n     int                w   = gfxs->length + 1;\n     GenefxAccumulator *S   = gfxs->Sacc;\n     u8                *Dy  = gfxs->Aop[0];\n     u16               *Dvu = gfxs->Aop[1];\n\n     while (--w) {\n          if (!(S->YUV.a & 0xf000)) {\n               *Dy = (S->YUV.y & 0xff00) ? 0xff : S->YUV.y;\n          }\n\n          ++S;\n          ++Dy;\n     }\n\n     w = (gfxs->length >> 1) + 1;\n     S =  gfxs->Sacc;\n\n     while (--w) {\n          u32 cb, cr;\n\n          if (!(S[0].YUV.a & 0xf000) && !(S[1].YUV.a & 0xf000)) {\n               cb = (S[0].YUV.u + S[1].YUV.u) >> 1;\n               if (cb & 0xff00)\n                    cb = 0xff;\n\n               cr = (S[0].YUV.v + S[1].YUV.v) >> 1;\n               if (cr & 0xff00)\n                    cr = 0xff;\n\n               *Dvu = cr | (cb << 8);\n          }\n          else if (!(S[0].YUV.a & 0xf000)) {\n               cb   = ((*Dvu >> 8)   + ((S[0].YUV.u & 0xff00) ? 0xff : S[0].YUV.u)) >> 1;\n               cr   = ((*Dvu & 0xff) + ((S[0].YUV.v & 0xff00) ? 0xff : S[0].YUV.v)) >> 1;\n               *Dvu = cr | (cb << 8);\n          }\n          else if (!(S[1].YUV.a & 0xf000)) {\n               cb   = ((*Dvu >> 8)   + ((S[1].YUV.u & 0xff00) ? 0xff : S[1].YUV.u)) >> 1;\n               cr   = ((*Dvu & 0xff) + ((S[1].YUV.v & 0xff00) ? 0xff : S[1].YUV.v)) >> 1;\n               *Dvu = cr | (cb << 8);\n          }\n\n          S += 2;\n          ++Dvu;\n     }\n}\n\nstatic void\nSacc_to_Aop_nv24( GenefxState *gfxs )\n{\n     int                w   = gfxs->length+1;\n     GenefxAccumulator *S   = gfxs->Sacc;\n     u8                *Dy  = gfxs->Aop[0];\n     u16               *Duv = gfxs->Aop[1];\n\n     while (--w) {\n          if (!(S->YUV.a & 0xf000)) {\n               *Dy = (S->YUV.y & 0xff00) ? 0xff : S->YUV.y;\n          }\n\n          ++S;\n          ++Dy;\n     }\n\n     w = gfxs->length + 1;\n     S = gfxs->Sacc;\n\n     while (--w) {\n          u32 cb, cr;\n\n          if (!(S[0].YUV.a & 0xf000)) {\n               cb   = ((*Duv & 0xff) + ((S[0].YUV.u & 0xff00) ? 0xff : S[0].YUV.u)) >> 1;\n               cr   = ((*Duv >> 8)   + ((S[0].YUV.v & 0xff00) ? 0xff : S[0].YUV.v)) >> 1;\n               *Duv = cb | (cr << 8);\n          }\n\n          S++;\n          ++Duv;\n     }\n}\n\nstatic void\nSacc_to_Aop_nv42( GenefxState *gfxs )\n{\n     int                w   = gfxs->length+1;\n     GenefxAccumulator *S   = gfxs->Sacc;\n     u8                *Dy  = gfxs->Aop[0];\n     u16               *Dvu = gfxs->Aop[1];\n\n     while (--w) {\n          if (!(S->YUV.a & 0xf000)) {\n               *Dy = (S->YUV.y & 0xff00) ? 0xff : S->YUV.y;\n          }\n\n          ++S;\n          ++Dy;\n     }\n\n     w = gfxs->length + 1;\n     S = gfxs->Sacc;\n\n     while (--w) {\n          u32 cb, cr;\n\n          if (!(S[0].YUV.a & 0xf000)) {\n               cb   = ((*Dvu >> 8)   + ((S[0].YUV.u & 0xff00) ? 0xff : S[0].YUV.u)) >> 1;\n               cr   = ((*Dvu & 0xff) + ((S[0].YUV.v & 0xff00) ? 0xff : S[0].YUV.v)) >> 1;\n               *Dvu = cr | (cb << 8);\n          }\n\n          S++;\n          ++Dvu;\n     }\n}\n\nstatic GenefxFunc Sacc_to_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Sacc_to_Aop_argb1555,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Sacc_to_Aop_rgb16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Sacc_to_Aop_rgb24,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Sacc_to_Aop_rgb32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Sacc_to_Aop_argb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = Sacc_to_Aop_a8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = Sacc_to_Aop_yuy2,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = Sacc_to_Aop_rgb332,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = Sacc_to_Aop_uyvy,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = Sacc_to_Aop_i420,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = Sacc_to_Aop_i420,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = Sacc_to_Aop_lut8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = Sacc_to_Aop_alut44,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Sacc_to_Aop_airgb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = Sacc_to_Aop_nv12,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = Sacc_to_Aop_nv16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Sacc_to_Aop_argb2554,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Sacc_to_Aop_argb4444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Sacc_to_Aop_rgba4444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = Sacc_to_Aop_nv21,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = Sacc_to_Aop_ayuv,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = Sacc_to_Aop_a4,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Sacc_to_Aop_argb1666,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Sacc_to_Aop_argb6666,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Sacc_to_Aop_rgb18,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Sacc_to_Aop_xrgb4444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Sacc_to_Aop_xrgb1555,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Sacc_to_Aop_xbgr1555,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Sacc_to_Aop_rgba5551,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Sacc_to_Aop_y444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Sacc_to_Aop_argb8565,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Sacc_to_Aop_avyu,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Sacc_to_Aop_vyu,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = Sacc_to_Aop_y42b,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Sacc_to_Aop_abgr,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Sacc_to_Aop_rgbaf88871,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = Sacc_to_Aop_nv61,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = Sacc_to_Aop_y42b,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Sacc_to_Aop_y444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = Sacc_to_Aop_nv24,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = Sacc_to_Aop_nv42,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Sacc_to_Aop_bgr24,\n};\n\n/**********************************************************************************************************************\n ********************************* Sacc_toK_Aop_PFI *******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSacc_toK_Aop_a8( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *S = gfxs->Sacc;\n     u8                *D = gfxs->Aop[0];\n\n     while (--w) {\n          if (!(S->RGB.a & 0xf000)) {\n               *D = (S->RGB.a & 0xff00) ? 0xff : S->RGB.a;\n          }\n\n          ++S;\n          ++D;\n     }\n}\n\nstatic void\nSacc_toK_Aop_yuy2( GenefxState *gfxs )\n{\n     int                l;\n     int                w     = gfxs->length;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u16               *D     = gfxs->Aop[0];\n     u32                Dkey  = gfxs->Dkey;\n#ifdef WORDS_BIGENDIAN\n     u16                Dkey0 = gfxs->Dkey >> 16;\n     u16                Dkey1 = gfxs->Dkey & 0xffff;\n#else\n     u16                Dkey0 = gfxs->Dkey & 0xffff;\n     u16                Dkey1 = gfxs->Dkey >> 16;\n#endif\n\n     if ((long) D & 2) {\n          if (!(S->YUV.a & 0xf000) && (*D == Dkey1)) {\n               *D = ((S->YUV.y & 0xff00) ? 0x00ff : S->YUV.y) | ((S->YUV.v & 0xff00) ? 0xff00 : (S->YUV.v << 8));\n          }\n\n          ++S;\n          ++D;\n          --w;\n     }\n\n     for (l = w >> 1; l--;) {\n          if (*D == Dkey) {\n               if (!(S[0].YUV.a & 0xf000) && !(S[1].YUV.a & 0xf000)) {\n                    u32 y0, cb, y1, cr;\n\n                    y0 = (S[0].YUV.y & 0xff00) ? 0xff : S[0].YUV.y;\n                    y1 = (S[1].YUV.y & 0xff00) ? 0xff : S[1].YUV.y;\n\n                    cb = (S[0].YUV.u + S[1].YUV.u) >> 1;\n                    if (cb & 0xff00)\n                         cb = 0xff;\n\n                    cr = (S[0].YUV.v + S[1].YUV.v) >> 1;\n                    if (cr & 0xff00)\n                         cr = 0xff;\n\n#ifdef WORDS_BIGENDIAN\n                    *((u32*) D) = y1 | (cr << 8) | (y0 << 16) | (cb << 24);\n#else\n                    *((u32*) D) = y0 | (cb << 8) | (y1 << 16) | (cr << 24);\n#endif\n               }\n               else if (!(S[0].YUV.a & 0xf000)) {\n                    D[0] = ((S[0].YUV.y & 0xff00) ? 0x00ff :  S[0].YUV.y) |\n                           ((S[0].YUV.u & 0xff00) ? 0xff00 : (S[0].YUV.u << 8));\n               }\n               else if (!(S[1].YUV.a & 0xf000)) {\n                    D[1] = ((S[1].YUV.y & 0xff00) ? 0x00ff :  S[1].YUV.y) |\n                           ((S[1].YUV.v & 0xff00) ? 0xff00 : (S[1].YUV.v << 8));\n               }\n          }\n\n          S += 2;\n          D += 2;\n     }\n\n     if (w & 1) {\n          if (!(S->YUV.a & 0xf000) && (*D == Dkey0)) {\n               *D = ((S->YUV.y & 0xff00) ? 0x00ff : S->YUV.y) | ((S->YUV.u & 0xff00) ? 0xff00 : (S->YUV.u << 8));\n          }\n     }\n}\n\nstatic void\nSacc_toK_Aop_rgb332( GenefxState *gfxs )\n{\n     int                w    = gfxs->length + 1;\n     GenefxAccumulator *S    = gfxs->Sacc;\n     u8                *D    = gfxs->Aop[0];\n     u32                Dkey = gfxs->Dkey;\n\n     while (--w) {\n          if (!(S->RGB.a & 0xf000) && (*D == Dkey)) {\n               *D = PIXEL_RGB332( (S->RGB.r & 0xff00) ? 0xff : S->RGB.r,\n                                  (S->RGB.g & 0xff00) ? 0xff : S->RGB.g,\n                                  (S->RGB.b & 0xff00) ? 0xff : S->RGB.b );\n          }\n\n          ++S;\n          ++D;\n     }\n}\n\nstatic void\nSacc_toK_Aop_uyvy( GenefxState *gfxs )\n{\n     int                l;\n     int                w     = gfxs->length;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u16               *D     = gfxs->Aop[0];\n     u32                Dkey  = gfxs->Dkey;\n#ifdef WORDS_BIGENDIAN\n     u16                Dkey0 = gfxs->Dkey >> 16;\n     u16                Dkey1 = gfxs->Dkey & 0xffff;\n#else\n     u16                Dkey0 = gfxs->Dkey & 0xffff;\n     u16                Dkey1 = gfxs->Dkey >> 16;\n#endif\n\n     if ((long) D & 2) {\n          if (!(S->YUV.a & 0xf000) && (*D == Dkey1)) {\n               *D = ((S->YUV.v & 0xff00) ? 0x00ff : S->YUV.v) | ((S->YUV.y & 0xff00) ? 0xff00 : (S->YUV.y << 8));\n          }\n\n          ++S;\n          ++D;\n          --w;\n     }\n\n     for (l = w >> 1; l--;) {\n          if (*D == Dkey) {\n               if (!(S[0].YUV.a & 0xf000) && !(S[1].YUV.a & 0xf000)) {\n                    u32 cb, y0, cr, y1;\n\n                    y0 = (S[0].YUV.y & 0xff00) ? 0xff : S[0].YUV.y;\n                    y1 = (S[1].YUV.y & 0xff00) ? 0xff : S[1].YUV.y;\n\n                    cb = (S[0].YUV.u + S[1].YUV.u) >> 1;\n                    if (cb & 0xff00)\n                         cb = 0xff;\n\n                    cr = (S[0].YUV.v + S[1].YUV.v) >> 1;\n                    if (cr & 0xff00)\n                         cr = 0xff;\n\n#ifdef WORDS_BIGENDIAN\n                    *((u32*) D) = cr | (y1 << 8) | (cb << 16) | (y0 << 24);\n#else\n                    *((u32*) D) = cb | (y0 << 8) | (cr << 16) | (y1 << 24);\n#endif\n               }\n               else if (!(S[0].YUV.a & 0xf000)) {\n                    D[0] = ((S[0].YUV.u & 0xff00) ? 0x00ff :  S[0].YUV.u) |\n                           ((S[0].YUV.y & 0xff00) ? 0xff00 : (S[0].YUV.y << 8));\n               }\n               else if (!(S[1].YUV.a & 0xf000)) {\n                    D[1] = ((S[1].YUV.v & 0xff00) ? 0x00ff :  S[1].YUV.v) |\n                           ((S[1].YUV.y & 0xff00) ? 0xff00 : (S[1].YUV.y << 8));\n               }\n          }\n\n          S += 2;\n          D += 2;\n     }\n\n     if (w & 1) {\n          if (!(S->YUV.a & 0xf000) && (*D == Dkey0)) {\n               *D = ((S->YUV.u & 0xff00) ? 0x00ff : S->YUV.u) | ((S->YUV.y & 0xff00) ? 0xff00 : (S->YUV.y << 8));\n          }\n     }\n}\n\nstatic void\nSacc_toK_Aop_lut8( GenefxState *gfxs )\n{\n     int                w    = gfxs->length + 1;\n     GenefxAccumulator *S    = gfxs->Sacc;\n     u8                *D    = gfxs->Aop[0];\n     u32                Dkey = gfxs->Dkey;\n\n     while (--w) {\n          if (!(S->RGB.a & 0xf000) && (*D == Dkey)) {\n               *D = dfb_palette_search( gfxs->Alut,\n                                        (S->RGB.r & 0xff00) ? 0xff : S->RGB.r,\n                                        (S->RGB.g & 0xff00) ? 0xff : S->RGB.g,\n                                        (S->RGB.b & 0xff00) ? 0xff : S->RGB.b,\n                                        (S->RGB.a & 0xff00) ? 0xff : S->RGB.a );\n          }\n\n          ++S;\n          ++D;\n     }\n}\n\nstatic void\nSacc_toK_Aop_alut44( GenefxState *gfxs )\n{\n     int                w    = gfxs->length + 1;\n     GenefxAccumulator *S    = gfxs->Sacc;\n     u8                *D    = gfxs->Aop[0];\n     u32                Dkey = gfxs->Dkey;\n\n     while (--w) {\n          if (!(S->RGB.a & 0xf000) && ((*D & 0x0f) == Dkey)) {\n               *D = (S->RGB.a & 0xff00) ? 0xf0 :\n                    (S->RGB.a & 0xf0) + dfb_palette_search( gfxs->Alut,\n                                                            (S->RGB.r & 0xff00) ? 0xff : S->RGB.r,\n                                                            (S->RGB.g & 0xff00) ? 0xff : S->RGB.g,\n                                                            (S->RGB.b & 0xff00) ? 0xff : S->RGB.b,\n                                                            0x80 );\n          }\n\n          ++S;\n          ++D;\n     }\n}\n\nstatic void\nSacc_toK_Aop_y444( GenefxState *gfxs )\n{\n     int                w    = gfxs->length + 1;\n     GenefxAccumulator *S    = gfxs->Sacc;\n     u8                *Dy   = gfxs->Aop[0];\n     u8                *Du   = gfxs->Aop[1];\n     u8                *Dv   = gfxs->Aop[2];\n     u32                Dkey = gfxs->Dkey;\n\n     while (--w) {\n          u8 dy = *Dy;\n          u8 du = *Du;\n          u8 dv = *Dv;\n\n          if (!(S->YUV.a & 0xf000) && Dkey == (u32) (dy << 16 | du << 8 | dv)) {\n               *Dy = (S->YUV.y & 0xff00) ? 0xff : S->YUV.y;\n               *Du = (S->YUV.u & 0xff00) ? 0xff : S->YUV.u;\n               *Dv = (S->YUV.v & 0xff00) ? 0xff : S->YUV.v;\n          }\n\n          ++S;\n          ++Dy; ++Du; ++Dv;\n     }\n}\n\nstatic void\nSacc_toK_Aop_avyu( GenefxState *gfxs )\n{\n     int                w    = gfxs->length + 1;\n     GenefxAccumulator *S    = gfxs->Sacc;\n     u32               *D    = gfxs->Aop[0];\n     u32                Dkey = gfxs->Dkey;\n\n     while (--w) {\n          if (!(S->YUV.a & 0xf000) && (*D & 0x00ffffff) == Dkey) {\n               *D = PIXEL_AVYU( (S->YUV.a & 0xff00) ? 0xff : S->YUV.a,\n                                (S->YUV.y & 0xff00) ? 0xff : S->YUV.y,\n                                (S->YUV.u & 0xff00) ? 0xff : S->YUV.u,\n                                (S->YUV.v & 0xff00) ? 0xff : S->YUV.v );\n          }\n\n          ++S;\n          ++D;\n     }\n}\n\nstatic void\nSacc_toK_Aop_vyu( GenefxState *gfxs )\n{\n     int                w    = gfxs->length + 1;\n     GenefxAccumulator *S    = gfxs->Sacc;\n     u8                *D    = gfxs->Aop[0];\n     u32                Dkey = gfxs->Dkey;\n\n     while (--w) {\n#ifdef WORDS_BIGENDIAN\n          u32 d = D[0] << 16 | D[1] << 8 | D[2];\n#else\n          u32 d = D[2] << 16 | D[1] << 8 | D[0];\n#endif\n\n          if (!(S->YUV.a & 0xf000) && Dkey == d) {\n               u8 y = (S->YUV.y & 0xff00) ? 0xff : S->YUV.y;\n               u8 u = (S->YUV.u & 0xff00) ? 0xff : S->YUV.u;\n               u8 v = (S->YUV.v & 0xff00) ? 0xff : S->YUV.v;\n\n#ifdef WORDS_BIGENDIAN\n               D[0] = v;\n               D[1] = y;\n               D[2] = u;\n#else\n               D[0] = u;\n               D[1] = y;\n               D[2] = v;\n#endif\n          }\n\n          ++S;\n          D += 3;\n     }\n}\n\nstatic GenefxFunc Sacc_toK_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Sacc_toK_Aop_argb1555,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Sacc_toK_Aop_rgb16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Sacc_toK_Aop_rgb24,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Sacc_toK_Aop_rgb32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Sacc_toK_Aop_argb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = Sacc_toK_Aop_a8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = Sacc_toK_Aop_yuy2,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = Sacc_toK_Aop_rgb332,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = Sacc_toK_Aop_uyvy,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = Sacc_toK_Aop_lut8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = Sacc_toK_Aop_alut44,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Sacc_toK_Aop_airgb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Sacc_toK_Aop_argb2554,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Sacc_toK_Aop_argb4444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Sacc_toK_Aop_rgba4444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Sacc_toK_Aop_argb1666,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Sacc_toK_Aop_argb6666,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Sacc_toK_Aop_rgb18,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Sacc_toK_Aop_xrgb4444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Sacc_toK_Aop_xrgb1555,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Sacc_toK_Aop_xbgr1555,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Sacc_toK_Aop_rgba5551,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Sacc_toK_Aop_y444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Sacc_toK_Aop_argb8565,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Sacc_toK_Aop_avyu,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Sacc_toK_Aop_vyu,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Sacc_toK_Aop_abgr,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Sacc_toK_Aop_rgbaf88871,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Sacc_toK_Aop_y444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Sacc_toK_Aop_bgr24,\n};\n\n/**********************************************************************************************************************\n ********************************* Sacc_Sto_Aop_PFI *******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSacc_Sto_Aop_a8( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *D     = gfxs->Aop[0];\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->RGB.a & 0xf000))\n               *D = (S0->RGB.a & 0xff00) ? 0xff : S0->RGB.a;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSacc_Sto_Aop_yuy2( GenefxState *gfxs )\n{\n     int                l;\n     int                i      = gfxs->Xphase;\n     int                w      = gfxs->length;\n     GenefxAccumulator *S      = gfxs->Sacc;\n     u16               *D      = gfxs->Aop[0];\n     int                SperD  = gfxs->SperD;\n     int                SperD2 = gfxs->SperD << 1;\n\n     if ((long) D & 2) {\n          if (!(S->YUV.a & 0xf00)) {\n               *D = ((S->YUV.y & 0xff00) ? 0x00ff : S->YUV.y) | ((S->YUV.v & 0xff00) ? 0xff00 : (S->YUV.v << 8));\n          }\n\n          ++D;\n          i = SperD;\n          --w;\n     }\n\n     for (l = w >> 1; l--;) {\n          GenefxAccumulator *S0 = &S[i>>16];\n          GenefxAccumulator *S1 = &S[(i+SperD)>>16];\n\n          if (!(S0->YUV.a & 0xf000) && !(S1->YUV.a & 0xf000)) {\n               u32 y0, cb, y1, cr;\n\n               y0 = (S0->YUV.y & 0xff00) ? 0xff : S0->YUV.y;\n               y1 = (S1->YUV.y & 0xff00) ? 0xff : S1->YUV.y;\n\n               cb = (S0->YUV.u + S1->YUV.u) >> 1;\n               if (cb & 0xff00)\n                    cb = 0xff;\n\n               cr = (S0->YUV.v + S1->YUV.v) >> 1;\n               if (cr & 0xff00)\n                    cr = 0xff;\n\n#ifdef WORDS_BIGENDIAN\n               *((u32*) D) = y1 | (cr << 8) | (y0 << 16) | (cb << 24);\n#else\n               *((u32*) D) = y0 | (cb << 8) | (y1 << 16) | (cr << 24);\n#endif\n          }\n          else if (!(S0->YUV.a & 0xf000)) {\n               D[0] = ((S0->YUV.y & 0xff00) ? 0x00ff : S0->YUV.y) | ((S0->YUV.u & 0xff00) ? 0xff00 : (S0->YUV.u << 8));\n          }\n          else if (!(S1->YUV.a & 0xf000)) {\n               D[1] = ((S1->YUV.y & 0xff00) ? 0x00ff : S1->YUV.y) | ((S1->YUV.v & 0xff00) ? 0xff00 : (S1->YUV.v << 8));\n          }\n\n          D += 2;\n          i += SperD2;\n     }\n\n     if (w & 1) {\n          GenefxAccumulator *S0 = &S[i>>16];\n          if (!(S0->YUV.a & 0xf00)) {\n               *D = ((S0->YUV.y & 0xff00) ? 0x00ff : S0->YUV.y) | ((S0->YUV.u & 0xff00) ? 0xff00 : (S0->YUV.u << 8));\n          }\n     }\n}\n\nstatic void\nSacc_Sto_Aop_rgb332( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *D     = gfxs->Aop[0];\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->RGB.a & 0xf000)) {\n               *D = PIXEL_RGB332( (S0->RGB.r & 0xff00) ? 0xff : S0->RGB.r,\n                                  (S0->RGB.g & 0xff00) ? 0xff : S0->RGB.g,\n                                  (S0->RGB.b & 0xff00) ? 0xff : S0->RGB.b );\n          }\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSacc_Sto_Aop_uyvy( GenefxState *gfxs )\n{\n     int                l;\n     int                i      = gfxs->Xphase;\n     int                w      = gfxs->length;\n     GenefxAccumulator *S      = gfxs->Sacc;\n     u16               *D      = gfxs->Aop[0];\n     int                SperD  = gfxs->SperD;\n     int                SperD2 = gfxs->SperD << 1;\n\n     if ((long) D & 2) {\n          if (!(S->YUV.a & 0xf00)) {\n               *D = ((S->YUV.v & 0xff00) ? 0x00ff : S->YUV.v) | ((S->YUV.y & 0xff00) ? 0xff00 : (S->YUV.y << 8));\n          }\n\n          ++D;\n          i = SperD;\n          --w;\n     }\n\n     for (l = w >> 1; l--;) {\n          GenefxAccumulator *S0 = &S[i>>16];\n          GenefxAccumulator *S1 = &S[(i+SperD)>>16];\n\n          if (!(S0->YUV.a & 0xf000) && !(S1->YUV.a & 0xf000)) {\n               u32 cb, y0, cr, y1;\n\n               y0 = (S0->YUV.y & 0xff00) ? 0xff : S0->YUV.y;\n               y1 = (S1->YUV.y & 0xff00) ? 0xff : S1->YUV.y;\n\n               cb = (S0->YUV.u + S1->YUV.u) >> 1;\n               if (cb & 0xff00)\n                    cb = 0xff;\n\n               cr = (S0->YUV.v + S1->YUV.v) >> 1;\n               if (cr & 0xff00)\n                    cr = 0xff;\n\n#ifdef WORDS_BIGENDIAN\n               *((u32*) D) = cr | (y1 << 8) | (cb << 16) | (y0 << 24);\n#else\n               *((u32*) D) = cb | (y0 << 8) | (cr << 16) | (y1 << 24);\n#endif\n          }\n          else if (!(S0->YUV.a & 0xf000)) {\n               D[0] = ((S0->YUV.u & 0xff00) ? 0x00ff : S0->YUV.u) | ((S0->YUV.y & 0xff00) ? 0xff00 : (S0->YUV.y << 8));\n          }\n          else if (!(S1->YUV.a & 0xf000)) {\n               D[1] = ((S1->YUV.v & 0xff00) ? 0x00ff : S1->YUV.v) | ((S1->YUV.y & 0xff00) ? 0xff00 : (S1->YUV.y << 8));\n          }\n\n          D += 2;\n          i += SperD2;\n     }\n\n     if (w & 1) {\n          GenefxAccumulator *S0 = &S[i>>16];\n          if (!(S0->YUV.a & 0xf00)) {\n               *D = ((S0->YUV.u & 0xff00) ? 0x00ff : S0->YUV.u) | ((S0->YUV.y & 0xff00) ? 0xff00 : (S0->YUV.y << 8));\n          }\n     }\n}\n\nstatic void\nSacc_Sto_Aop_i420( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *Dy    = gfxs->Aop[0];\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->YUV.a & 0xf000)) {\n               *Dy = (S0->YUV.y & 0xff00) ? 0xff : S0->YUV.y;\n          }\n\n          ++Dy;\n          i += SperD;\n     }\n\n     if (gfxs->AopY & 1) {\n          u8 *Du = gfxs->Aop[1];\n          u8 *Dv = gfxs->Aop[2];\n\n          i =  gfxs->Xphase >> 1;\n          w = (gfxs->length >> 1) + 1;\n\n          while (--w) {\n               GenefxAccumulator *S0 = &S[i>>16];\n               GenefxAccumulator *S1 = &S[(i+SperD)>>16];\n\n               if (!(S0->YUV.a & 0xf000) && !(S1->YUV.a & 0xf000)) {\n                    u32 tmp;\n\n                    tmp = (S0->YUV.u + S1->YUV.u) >> 1;\n                    if (tmp & 0xff00)\n                         tmp = 0xff;\n                    *Du = tmp;\n\n                    tmp = (S0->YUV.v + S1->YUV.v) >> 1;\n                    if (tmp & 0xff00)\n                         tmp = 0xff;\n                    *Dv = tmp;\n\n               }\n               else if (!(S0->YUV.a & 0xf000)) {\n                    *Du = (*Du + ((S0->YUV.u & 0xff00) ? 0xff : S0->YUV.u)) >> 1;\n                    *Dv = (*Dv + ((S0->YUV.v & 0xff00) ? 0xff : S0->YUV.v)) >> 1;\n               }\n               else if (!(S1->YUV.a & 0xf000)) {\n                    *Du = (*Du + ((S1->YUV.u & 0xff00) ? 0xff : S1->YUV.u)) >> 1;\n                    *Dv = (*Dv + ((S1->YUV.v & 0xff00) ? 0xff : S1->YUV.v)) >> 1;\n               }\n\n               ++Du; ++Dv;\n               i += SperD << 1;\n          }\n     }\n}\n\nstatic void\nSacc_Sto_Aop_lut8( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *D     = gfxs->Aop[0];\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->RGB.a & 0xf000)) {\n               *D = dfb_palette_search( gfxs->Alut,\n                                        (S0->RGB.r & 0xff00) ? 0xff : S0->RGB.r,\n                                        (S0->RGB.g & 0xff00) ? 0xff : S0->RGB.g,\n                                        (S0->RGB.b & 0xff00) ? 0xff : S0->RGB.b,\n                                        (S0->RGB.a & 0xff00) ? 0xff : S0->RGB.a );\n          }\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSacc_Sto_Aop_alut44( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *D     = gfxs->Aop[0];\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->RGB.a & 0xf000)) {\n               *D = (S0->RGB.a & 0xff00) ?\n                    0xf0 : (S0->RGB.a & 0xf0) + dfb_palette_search( gfxs->Alut,\n                                                                   (S0->RGB.r & 0xff00) ? 0xff : S0->RGB.r,\n                                                                   (S0->RGB.g & 0xff00) ? 0xff : S0->RGB.g,\n                                                                   (S0->RGB.b & 0xff00) ? 0xff : S0->RGB.b,\n                                                                   0x80 );\n          }\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSacc_Sto_Aop_nv12( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *Dy    = gfxs->Aop[0];\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->YUV.a & 0xf000)) {\n               *Dy = (S0->YUV.y & 0xff00) ? 0xff : S0->YUV.y;\n          }\n\n          ++Dy;\n          i += SperD;\n     }\n\n     if (gfxs->AopY & 1) {\n          u16 *Duv = gfxs->Aop[1];\n\n          i =  gfxs->Xphase >> 1;\n          w = (gfxs->length >> 1) + 1;\n\n          while (--w) {\n               GenefxAccumulator *S0 = &S[i>>16];\n               GenefxAccumulator *S1 = &S[(i+SperD)>>16];\n               u32                cb, cr;\n\n               if (!(S0->YUV.a & 0xf000) && !(S1->YUV.a & 0xf000)) {\n                    cb = (S0->YUV.u + S1->YUV.u) >> 1;\n                    if (cb & 0xff00)\n                         cb = 0xff;\n\n                    cr = (S0->YUV.v + S1->YUV.v) >> 1;\n                    if (cr & 0xff00)\n                         cr = 0xff;\n\n                    *Duv = cb | (cr << 8);\n               }\n               else if (!(S0->YUV.a & 0xf000)) {\n                    cb   = ((*Duv & 0xff) + ((S0->YUV.u & 0xff00) ? 0xff : S0->YUV.u)) >> 1;\n                    cr   = ((*Duv >> 8)   + ((S0->YUV.v & 0xff00) ? 0xff : S0->YUV.v)) >> 1;\n                    *Duv = cb | (cr << 8);\n               }\n               else if (!(S1->YUV.a & 0xf000)) {\n                    cb   = ((*Duv & 0xff) + ((S1->YUV.u & 0xff00) ? 0xff : S1->YUV.u)) >> 1;\n                    cr   = ((*Duv >> 8)   + ((S1->YUV.v & 0xff00) ? 0xff : S1->YUV.v)) >> 1;\n                    *Duv = cb | (cr << 8);\n               }\n\n               ++Duv;\n               i += SperD << 1;\n          }\n     }\n}\n\nstatic void\nSacc_Sto_Aop_nv16( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *Dy    = gfxs->Aop[0];\n     u16               *Duv   = gfxs->Aop[1];\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->YUV.a & 0xf000)) {\n               *Dy = (S0->YUV.y & 0xff00) ? 0xff : S0->YUV.y;\n          }\n\n          ++Dy;\n          i += SperD;\n     }\n\n     i =  gfxs->Xphase >> 1;\n     w = (gfxs->length >> 1) + 1;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n          GenefxAccumulator *S1 = &S[(i+SperD)>>16];\n          u32                cb, cr;\n\n          if (!(S0->YUV.a & 0xf000) && !(S1->YUV.a & 0xf000)) {\n               cb = (S0->YUV.u + S1->YUV.u) >> 1;\n               if (cb & 0xff00)\n                    cb = 0xff;\n\n               cr = (S0->YUV.v + S1->YUV.v) >> 1;\n               if (cr & 0xff00)\n                    cr = 0xff;\n\n               *Duv = cb | (cr << 8);\n          }\n          else if (!(S0->YUV.a & 0xf000)) {\n               cb   = ((*Duv & 0xff) + ((S0->YUV.u & 0xff00) ? 0xff : S0->YUV.u)) >> 1;\n               cr   = ((*Duv >> 8)   + ((S0->YUV.v & 0xff00) ? 0xff : S0->YUV.v)) >> 1;\n               *Duv = cb | (cr << 8);\n          }\n          else if (!(S1->YUV.a & 0xf000)) {\n               cb   = ((*Duv & 0xff) + ((S1->YUV.u & 0xff00) ? 0xff : S1->YUV.u)) >> 1;\n               cr   = ((*Duv >> 8)   + ((S1->YUV.v & 0xff00) ? 0xff : S1->YUV.v)) >> 1;\n               *Duv = cb | (cr << 8);\n          }\n\n          ++Duv;\n          i += SperD << 1;\n     }\n}\n\nstatic void\nSacc_Sto_Aop_nv21( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *Dy    = gfxs->Aop[0];\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->YUV.a & 0xf000)) {\n               *Dy = (S0->YUV.y & 0xff00) ? 0xff : S0->YUV.y;\n          }\n\n          ++Dy;\n          i += SperD;\n     }\n\n     if (gfxs->AopY & 1) {\n          u16 *Dvu = gfxs->Aop[1];\n\n          i =  gfxs->Xphase >> 1;\n          w = (gfxs->length >> 1) + 1;\n\n          while (--w) {\n               GenefxAccumulator *S0 = &S[i>>16];\n               GenefxAccumulator *S1 = &S[(i+SperD)>>16];\n               u32                cb, cr;\n\n               if (!(S0->YUV.a & 0xf000) && !(S1->YUV.a & 0xf000)) {\n                    cb = (S0->YUV.u + S1->YUV.u) >> 1;\n                    if (cb & 0xff00)\n                         cb = 0xff;\n\n                    cr = (S0->YUV.v + S1->YUV.v) >> 1;\n                    if (cr & 0xff00)\n                         cr = 0xff;\n\n                    *Dvu = cr | (cb << 8);\n               }\n               else if (!(S0->YUV.a & 0xf000)) {\n                    cb   = ((*Dvu >> 8)   + ((S0->YUV.u & 0xff00) ? 0xff : S0->YUV.u)) >> 1;\n                    cr   = ((*Dvu & 0xff) + ((S0->YUV.v & 0xff00) ? 0xff : S0->YUV.v)) >> 1;\n                    *Dvu = cr | (cb << 8);\n               }\n               else if (!(S1->YUV.a & 0xf000)) {\n                    cb   = ((*Dvu >> 8)   + ((S1->YUV.u & 0xff00) ? 0xff : S1->YUV.u)) >> 1;\n                    cr   = ((*Dvu & 0xff) + ((S1->YUV.v & 0xff00) ? 0xff : S1->YUV.v)) >> 1;\n                    *Dvu = cr | (cb << 8);\n               }\n\n               ++Dvu;\n               i += SperD << 1;\n          }\n     }\n}\n\nstatic void\nSacc_Sto_Aop_ayuv( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u32               *D     = gfxs->Aop[0];\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->YUV.a & 0xf000)) {\n               *D = PIXEL_AYUV( (S0->YUV.a & 0xff00) ? 0xff : S0->YUV.a,\n                                (S0->YUV.y & 0xff00) ? 0xff : S0->YUV.y,\n                                (S0->YUV.u & 0xff00) ? 0xff : S0->YUV.u,\n                                (S0->YUV.v & 0xff00) ? 0xff : S0->YUV.v );\n          }\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSacc_Sto_Aop_y444( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *Dy    = gfxs->Aop[0];\n     u8                *Du    = gfxs->Aop[1];\n     u8                *Dv    = gfxs->Aop[2];\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->YUV.a & 0xf000)) {\n               *Dy = (S0->YUV.y & 0xff00) ? 0xff : S0->YUV.y;\n               *Du = (S0->YUV.u & 0xff00) ? 0xff : S0->YUV.u;\n               *Dv = (S0->YUV.v & 0xff00) ? 0xff : S0->YUV.v;\n          }\n\n          ++Dy; ++Du; ++Dv;\n          i += SperD;\n     }\n}\n\nstatic void\nSacc_Sto_Aop_avyu( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u32               *D     = gfxs->Aop[0];\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->YUV.a & 0xf000)) {\n               *D = PIXEL_AVYU( (S0->YUV.a & 0xff00) ? 0xff : S0->YUV.a,\n                                (S0->YUV.y & 0xff00) ? 0xff : S0->YUV.y,\n                                (S0->YUV.u & 0xff00) ? 0xff : S0->YUV.u,\n                                (S0->YUV.v & 0xff00) ? 0xff : S0->YUV.v );\n          }\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSacc_Sto_Aop_vyu( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *D     = gfxs->Aop[0];\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->YUV.a & 0xf000)) {\n               u8 y = (S0->YUV.y & 0xff00) ? 0xff : S0->YUV.y;\n               u8 u = (S0->YUV.u & 0xff00) ? 0xff : S0->YUV.u;\n               u8 v = (S0->YUV.v & 0xff00) ? 0xff : S0->YUV.v;\n\n#ifdef WORDS_BIGENDIAN\n               D[0] = v;\n               D[1] = y;\n               D[2] = u;\n#else\n               D[0] = u;\n               D[1] = y;\n               D[2] = v;\n#endif\n          }\n\n          D += 3;\n          i += SperD;\n     }\n}\n\nstatic void\nSacc_Sto_Aop_y42b( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *Dy    = gfxs->Aop[0];\n     u8                *Du    = gfxs->Aop[1];\n     u8                *Dv    = gfxs->Aop[2];\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->YUV.a & 0xf000)) {\n               *Dy = (S0->YUV.y & 0xff00) ? 0xff : S0->YUV.y;\n          }\n\n          Dy++;\n          i += SperD;\n     }\n\n     i =  gfxs->Xphase / 2;\n     w = (gfxs->length / 2) + 1;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n          GenefxAccumulator *S1 = &S[(i+SperD)>>16];\n\n          if (!(S0->YUV.a & 0xf000) && !(S1->YUV.a & 0xf000)) {\n               u32 tmp;\n\n               tmp = (S0->YUV.u + S1->YUV.u) / 2;\n               if (tmp & 0xff00)\n                    tmp = 0xff;\n               *Du = tmp;\n\n               tmp = (S0->YUV.v + S1->YUV.v) / 2;\n               if (tmp & 0xff00)\n                    tmp = 0xff;\n               *Dv = tmp;\n          }\n          else if (!(S0->YUV.a & 0xf000)) {\n               *Du = (*Du + ((S0->YUV.u & 0xff00) ? 0xff : S0->YUV.u)) / 2;\n               *Dv = (*Dv + ((S0->YUV.v & 0xff00) ? 0xff : S0->YUV.v)) / 2;\n          }\n          else if (!(S1->YUV.a & 0xf000)) {\n               *Du = (*Du + ((S1->YUV.u & 0xff00) ? 0xff : S1->YUV.u)) / 2;\n               *Dv = (*Dv + ((S1->YUV.v & 0xff00) ? 0xff : S1->YUV.v)) / 2;\n          }\n\n          Du++; Dv++;\n          i += SperD << 1;\n     }\n}\n\nstatic void\nSacc_Sto_Aop_nv61( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *Dy    = gfxs->Aop[0];\n     u16               *Dvu   = gfxs->Aop[1];\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->YUV.a & 0xf000)) {\n               *Dy = (S0->YUV.y & 0xff00) ? 0xff : S0->YUV.y;\n          }\n\n          ++Dy;\n          i += SperD;\n     }\n\n     i =  gfxs->Xphase >> 1;\n     w = (gfxs->length >> 1) + 1;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n          GenefxAccumulator *S1 = &S[(i+SperD)>>16];\n          u32                cb, cr;\n\n          if (!(S0->YUV.a & 0xf000) && !(S1->YUV.a & 0xf000)) {\n               cb = (S0->YUV.u + S1->YUV.u) >> 1;\n               if (cb & 0xff00)\n                    cb = 0xff;\n\n               cr = (S0->YUV.v + S1->YUV.v) >> 1;\n               if (cr & 0xff00)\n                    cr = 0xff;\n\n               *Dvu = cr | (cb << 8);\n          }\n          else if (!(S0->YUV.a & 0xf000)) {\n               cb   = ((*Dvu >> 8)   + ((S0->YUV.u & 0xff00) ? 0xff : S0->YUV.u)) >> 1;\n               cr   = ((*Dvu & 0xff) + ((S0->YUV.v & 0xff00) ? 0xff : S0->YUV.v)) >> 1;\n               *Dvu = cr | (cb << 8);\n          }\n          else if (!(S1->YUV.a & 0xf000)) {\n               cb   = ((*Dvu >> 8)   + ((S1->YUV.u & 0xff00) ? 0xff : S1->YUV.u)) >> 1;\n               cr   = ((*Dvu & 0xff) + ((S1->YUV.v & 0xff00) ? 0xff : S1->YUV.v)) >> 1;\n               *Dvu = cr | (cb << 8);\n          }\n\n          ++Dvu;\n          i += SperD << 1;\n     }\n}\n\nstatic void\nSacc_Sto_Aop_nv24( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *Dy    = gfxs->Aop[0];\n     u16               *Duv   = gfxs->Aop[1];\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->YUV.a & 0xf000)) {\n               *Dy = (S0->YUV.y & 0xff00) ? 0xff : S0->YUV.y;\n          }\n\n          ++Dy;\n          i += SperD;\n     }\n\n     i = gfxs->Xphase;\n     w = gfxs->length + 1;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n          u32                cb, cr;\n\n          if (!(S0->YUV.a & 0xf000)) {\n               cb   = ((*Duv & 0xff) + ((S0->YUV.u & 0xff00) ? 0xff : S0->YUV.u)) >> 1;\n               cr   = ((*Duv >> 8)   + ((S0->YUV.v & 0xff00) ? 0xff : S0->YUV.v)) >> 1;\n               *Duv = cb | (cr << 8);\n          }\n\n          ++Duv;\n          i += SperD;\n     }\n}\n\nstatic void\nSacc_Sto_Aop_nv42( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *Dy    = gfxs->Aop[0];\n     u16               *Dvu   = gfxs->Aop[1];\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->YUV.a & 0xf000)) {\n               *Dy = (S0->YUV.y & 0xff00) ? 0xff : S0->YUV.y;\n          }\n\n          ++Dy;\n          i += SperD;\n     }\n\n     i = gfxs->Xphase;\n     w = gfxs->length + 1;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n          u32                cb, cr;\n\n          if (!(S0->YUV.a & 0xf000)) {\n               cb   = ((*Dvu >> 8)   + ((S0->YUV.u & 0xff00) ? 0xff : S0->YUV.u)) >> 1;\n               cr   = ((*Dvu & 0xff) + ((S0->YUV.v & 0xff00) ? 0xff : S0->YUV.v)) >> 1;\n               *Dvu = cr | (cb << 8);\n          }\n\n          ++Dvu;\n          i += SperD;\n     }\n}\n\nstatic GenefxFunc Sacc_Sto_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Sacc_Sto_Aop_argb1555,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Sacc_Sto_Aop_rgb16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Sacc_Sto_Aop_rgb24,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Sacc_Sto_Aop_rgb32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Sacc_Sto_Aop_argb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = Sacc_Sto_Aop_a8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = Sacc_Sto_Aop_yuy2,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = Sacc_Sto_Aop_rgb332,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = Sacc_Sto_Aop_uyvy,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = Sacc_Sto_Aop_i420,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = Sacc_Sto_Aop_i420,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = Sacc_Sto_Aop_lut8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = Sacc_Sto_Aop_alut44,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Sacc_Sto_Aop_airgb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = Sacc_Sto_Aop_nv12,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = Sacc_Sto_Aop_nv16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Sacc_Sto_Aop_argb2554,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Sacc_Sto_Aop_argb4444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Sacc_Sto_Aop_rgba4444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = Sacc_Sto_Aop_nv21,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = Sacc_Sto_Aop_ayuv,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Sacc_Sto_Aop_argb1666,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Sacc_Sto_Aop_argb6666,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Sacc_Sto_Aop_rgb18,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Sacc_Sto_Aop_xrgb4444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Sacc_Sto_Aop_xrgb1555,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Sacc_Sto_Aop_xbgr1555,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Sacc_Sto_Aop_rgba5551,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Sacc_Sto_Aop_y444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Sacc_Sto_Aop_argb8565,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Sacc_Sto_Aop_avyu,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Sacc_Sto_Aop_vyu,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = Sacc_Sto_Aop_y42b,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Sacc_Sto_Aop_abgr,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Sacc_Sto_Aop_rgbaf88871,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = Sacc_Sto_Aop_nv61,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = Sacc_Sto_Aop_y42b,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Sacc_Sto_Aop_y444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = Sacc_Sto_Aop_nv24,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = Sacc_Sto_Aop_nv42,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Sacc_Sto_Aop_bgr24,\n};\n\n/**********************************************************************************************************************\n ********************************* Sacc_StoK_Aop_PFI ******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSacc_StoK_Aop_y444( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *Dy    = gfxs->Aop[0];\n     u8                *Du    = gfxs->Aop[1];\n     u8                *Dv    = gfxs->Aop[2];\n     u32                Dkey  = gfxs->Dkey;\n     int                SperD = gfxs->Xphase;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n          u8                 dy = *Dy;\n          u8                 du = *Du;\n          u8                 dv = *Dv;\n\n          if (!(S0->YUV.a & 0xf000) && Dkey == (u32) (dy << 16 | du << 8 | dv)) {\n               *Dy = (S0->YUV.y & 0xff00) ? 0xff : S0->YUV.y;\n               *Du = (S0->YUV.u & 0xff00) ? 0xff : S0->YUV.u;\n               *Dv = (S0->YUV.v & 0xff00) ? 0xff : S0->YUV.v;\n          }\n\n          ++Dy; ++Du; ++Dv;\n          i += SperD;\n     }\n}\n\nstatic void\nSacc_StoK_Aop_avyu( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u32               *D     = gfxs->Aop[0];\n     u32                Dkey  = gfxs->Dkey;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->YUV.a & 0xf000) && (*D & 0x00ffffff) == Dkey) {\n               *D = PIXEL_AYUV( (S0->YUV.a & 0xff00) ? 0xff : S0->YUV.a,\n                                (S0->YUV.y & 0xff00) ? 0xff : S0->YUV.y,\n                                (S0->YUV.u & 0xff00) ? 0xff : S0->YUV.u,\n                                (S0->YUV.v & 0xff00) ? 0xff : S0->YUV.v );\n          }\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nSacc_StoK_Aop_vyu( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *D     = gfxs->Aop[0];\n     u32                Dkey  = gfxs->Dkey;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n#ifdef WORDS_BIGENDIAN\n          u32 d = D[0] << 16 | D[1] << 8 | D[2];\n#else\n          u32 d = D[2] << 16 | D[1] << 8 | D[0];\n#endif\n\n          if (!(S0->YUV.a & 0xf000) && Dkey == d) {\n               u8 y = (S0->YUV.y & 0xff00) ? 0xff : S0->YUV.y;\n               u8 u = (S0->YUV.u & 0xff00) ? 0xff : S0->YUV.u;\n               u8 v = (S0->YUV.v & 0xff00) ? 0xff : S0->YUV.v;\n\n#ifdef WORDS_BIGENDIAN\n               D[0] = v;\n               D[1] = y;\n               D[2] = u;\n#else\n               D[0] = u;\n               D[1] = y;\n               D[2] = v;\n#endif\n          }\n\n          D += 3;\n          i += SperD;\n     }\n}\n\nstatic GenefxFunc Sacc_StoK_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Sacc_StoK_Aop_argb1555,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Sacc_StoK_Aop_rgb16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Sacc_StoK_Aop_rgb24,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Sacc_StoK_Aop_rgb32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Sacc_StoK_Aop_argb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Sacc_StoK_Aop_airgb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Sacc_StoK_Aop_argb2554,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Sacc_StoK_Aop_argb4444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Sacc_StoK_Aop_rgba4444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Sacc_StoK_Aop_argb1666,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Sacc_StoK_Aop_argb6666,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Sacc_StoK_Aop_rgb18,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Sacc_StoK_Aop_xrgb4444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Sacc_StoK_Aop_xrgb1555,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Sacc_StoK_Aop_xbgr1555,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Sacc_StoK_Aop_rgba5551,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Sacc_StoK_Aop_y444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Sacc_StoK_Aop_argb8565,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Sacc_StoK_Aop_avyu,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Sacc_StoK_Aop_vyu,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Sacc_StoK_Aop_abgr,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Sacc_StoK_Aop_rgbaf88871,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Sacc_StoK_Aop_y444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Sacc_StoK_Aop_bgr24,\n};\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_to_Aop_PFI *****************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_16_to_Aop( GenefxState *gfxs )\n{\n     direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length * 2 );\n}\n\nstatic void\nBop_24_to_Aop( GenefxState *gfxs )\n{\n     direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length * 3 );\n}\n\nstatic void\nBop_32_to_Aop( GenefxState *gfxs )\n{\n     direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length * 4 );\n}\n\nstatic void\nBop_8_to_Aop( GenefxState *gfxs )\n{\n     direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length );\n}\n\nstatic void\nBop_i420_to_Aop( GenefxState *gfxs )\n{\n     direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length );\n     if (gfxs->AopY & 1) {\n          direct_memmove( gfxs->Aop[1], gfxs->Bop[1], gfxs->length >> 1 );\n          direct_memmove( gfxs->Aop[2], gfxs->Bop[2], gfxs->length >> 1 );\n     }\n}\n\nstatic void\nBop_nv12_to_Aop( GenefxState *gfxs )\n{\n     direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length );\n     if (gfxs->AopY & 1)\n          direct_memmove( gfxs->Aop[1], gfxs->Bop[1], gfxs->length & ~1 );\n}\n\nstatic void\nBop_nv16_to_Aop( GenefxState *gfxs )\n{\n     direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length );\n     direct_memmove( gfxs->Aop[1], gfxs->Bop[1], gfxs->length & ~1 );\n}\n\nstatic void\nBop_4_to_Aop( GenefxState *gfxs )\n{\n     direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length >> 1 );\n}\n\nstatic void\nBop_y444_to_Aop( GenefxState *gfxs )\n{\n     direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length );\n     direct_memmove( gfxs->Aop[1], gfxs->Bop[1], gfxs->length );\n     direct_memmove( gfxs->Aop[2], gfxs->Bop[2], gfxs->length );\n}\n\nstatic void\nBop_y42b_to_Aop( GenefxState *gfxs )\n{\n     direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length );\n     direct_memmove( gfxs->Aop[1], gfxs->Bop[1], gfxs->length / 2 );\n     direct_memmove( gfxs->Aop[2], gfxs->Bop[2], gfxs->length / 2 );\n}\n\nstatic void Bop_nv24_to_Aop( GenefxState *gfxs )\n{\n     direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length );\n     direct_memmove( gfxs->Aop[1], gfxs->Bop[1], gfxs->length * 2 );\n}\n\nstatic GenefxFunc Bop_PFI_to_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Bop_16_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Bop_16_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Bop_24_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Bop_32_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Bop_32_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = Bop_8_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = Bop_16_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = Bop_8_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = Bop_16_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = Bop_i420_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = Bop_i420_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = Bop_8_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = Bop_8_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Bop_32_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = Bop_nv12_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = Bop_nv16_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Bop_16_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Bop_16_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Bop_16_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = Bop_nv12_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = Bop_32_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = Bop_4_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Bop_24_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Bop_24_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Bop_24_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Bop_16_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Bop_16_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Bop_16_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Bop_16_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Bop_y444_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Bop_24_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Bop_32_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Bop_24_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = Bop_y42b_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Bop_32_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Bop_32_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = Bop_nv16_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = Bop_y42b_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Bop_y444_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = Bop_nv24_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = Bop_nv24_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Bop_24_to_Aop,\n};\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_toR_Aop_PFI ****************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_16_toR_Aop( GenefxState *gfxs )\n{\n     int  w     = gfxs->length + 1;\n     u16 *S     = gfxs->Bop[0];\n     u16 *D     = gfxs->Aop[0];\n     int  Dstep = gfxs->Astep;\n\n     while (--w) {\n          *D = *S;\n\n          ++S;\n          D += Dstep;\n     }\n}\n\nstatic void\nBop_24_toR_Aop( GenefxState *gfxs )\n{\n     int  w     = gfxs->length + 1;\n     u8  *S     = gfxs->Bop[0];\n     u8  *D     = gfxs->Aop[0];\n     int  Dstep = gfxs->Astep;\n\n     while (--w) {\n          D[0] = S[0];\n          D[1] = S[1];\n          D[2] = S[2];\n\n          S += 3;\n          D += Dstep * 3;\n     }\n}\n\nstatic void\nBop_32_toR_Aop( GenefxState *gfxs )\n{\n     int  w     = gfxs->length + 1;\n     u32 *S     = gfxs->Bop[0];\n     u32 *D     = gfxs->Aop[0];\n     int  Dstep = gfxs->Astep;\n\n     while (--w) {\n          *D = *S;\n\n          ++S;\n          D += Dstep;\n     }\n}\n\nstatic void\nBop_8_toR_Aop( GenefxState *gfxs )\n{\n     int  w     = gfxs->length + 1;\n     u8  *S     = gfxs->Bop[0];\n     u8  *D     = gfxs->Aop[0];\n     int  Dstep = gfxs->Astep;\n\n     while (--w) {\n          *D = *S;\n\n          ++S;\n          D += Dstep;\n     }\n}\n\nstatic void\nBop_i420_toR_Aop( GenefxState *gfxs )\n{\n     Bop_8_toR_Aop( gfxs );\n\n     if (gfxs->AopY & 1) {\n          int  w     = (gfxs->length >> 1) + 1;\n          u8  *S1    =  gfxs->Bop[1];\n          u8  *S2    =  gfxs->Bop[2];\n          u8  *D1    =  gfxs->Aop[1];\n          u8  *D2    =  gfxs->Aop[2];\n          int  Dstep =  gfxs->Astep >> 1;\n\n          while (--w) {\n               *D1 = *S1++;\n               *D2 = *S2++;\n               D1 += Dstep;\n               D2 += Dstep;\n          }\n     }\n}\n\nstatic void\nBop_nv12_toR_Aop( GenefxState *gfxs )\n{\n     Bop_8_toR_Aop( gfxs );\n\n     if (gfxs->AopY & 1) {\n          int  w     = (gfxs->length & ~1) + 1;\n          u8  *S     =  gfxs->Bop[1];\n          u8  *D     =  gfxs->Aop[1];\n          int  Dstep =  gfxs->Astep;\n\n          while (--w) {\n               *D = *S++;\n               D += Dstep;\n          }\n     }\n}\n\nstatic void\nBop_nv16_toR_Aop( GenefxState *gfxs )\n{\n     int  w     = (gfxs->length & ~1) + 1;\n     u8  *S     =  gfxs->Bop[1];\n     u8  *D     =  gfxs->Aop[1];\n     int  Dstep =  gfxs->Astep;\n\n     Bop_8_toR_Aop( gfxs );\n\n     while (--w) {\n          *D = *S++;\n          D += Dstep;\n     }\n}\n\nstatic void\nBop_4_toR_Aop( GenefxState *gfxs )\n{\n     int  w     = (gfxs->length >> 1) + 1;\n     u8  *S     =  gfxs->Bop[0];\n     u8  *D     =  gfxs->Aop[0];\n     int  Dstep =  gfxs->Astep;\n\n     while (--w) {\n          *D = *S;\n\n          ++S;\n          D += Dstep;\n     }\n}\n\nstatic void\nBop_y444_toR_Aop( GenefxState *gfxs )\n{\n     int  w     = gfxs->length + 1;\n     u8  *Sy    = gfxs->Bop[0];\n     u8  *Su    = gfxs->Bop[1];\n     u8  *Sv    = gfxs->Bop[2];\n     u8  *Dy    = gfxs->Aop[0];\n     u8  *Du    = gfxs->Aop[1];\n     u8  *Dv    = gfxs->Aop[2];\n     int  Dstep = gfxs->Astep;\n\n     while (--w) {\n          u8 sy = *Sy++;\n          u8 su = *Su++;\n          u8 sv = *Sv++;\n\n          *Dy = sy;\n          *Du = su;\n          *Dv = sv;\n\n          Dy += Dstep;\n          Du += Dstep;\n          Dv += Dstep;\n     }\n}\n\nstatic void\nBop_y42b_toR_Aop( GenefxState *gfxs )\n{\n     Bop_8_toR_Aop( gfxs );\n\n     int  w     = (gfxs->length / 2) + 1;\n     u8  *S1    =  gfxs->Bop[1];\n     u8  *S2    =  gfxs->Bop[2];\n     u8  *D1    =  gfxs->Aop[1];\n     u8  *D2    =  gfxs->Aop[2];\n     int  Dstep =  gfxs->Astep / 2;\n\n     while (--w) {\n          *D1 = *S1++;\n          *D2 = *S2++;\n          D1 += Dstep;\n          D2 += Dstep;\n     }\n}\n\nstatic void\nBop_nv24_toR_Aop( GenefxState *gfxs )\n{\n     int  w     = gfxs->length + 1;\n     u16 *S     = gfxs->Bop[1];\n     u16 *D     = gfxs->Aop[1];\n     int  Dstep = gfxs->Astep;\n\n     Bop_8_toR_Aop( gfxs );\n\n     while (--w) {\n          *D = *S++;\n          D += Dstep;\n     }\n}\n\nstatic GenefxFunc Bop_PFI_toR_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Bop_16_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Bop_16_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Bop_24_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Bop_32_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Bop_32_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = Bop_8_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = Bop_16_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = Bop_8_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = Bop_16_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = Bop_i420_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = Bop_i420_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = Bop_8_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = Bop_8_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Bop_32_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = Bop_nv12_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = Bop_nv16_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Bop_16_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Bop_16_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Bop_16_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = Bop_nv12_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = Bop_32_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = Bop_4_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Bop_24_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Bop_24_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Bop_24_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Bop_16_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Bop_16_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Bop_16_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Bop_16_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Bop_y444_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Bop_24_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Bop_32_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Bop_24_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = Bop_y42b_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Bop_32_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Bop_32_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = Bop_nv16_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = Bop_y42b_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Bop_y444_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = Bop_nv24_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = Bop_nv24_toR_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Bop_24_toR_Aop,\n};\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_toK_Aop_PFI ****************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_yuv422_toK_Aop( GenefxState *gfxs )\n{\n     int  l;\n     int  w     = gfxs->length;\n     u16 *S     = gfxs->Bop[0];\n     u16 *D     = gfxs->Aop[0];\n     u32  Dkey  = gfxs->Dkey;\n     int  Ostep = gfxs->Ostep;\n\n     if (Ostep < 0) {\n          S += gfxs->length - 1;\n          D += gfxs->length - 1;\n     }\n\n     if ((long) D & 2) {\n#ifdef WORDS_BIGENDIAN\n          if (*D == (Dkey & 0xffff))\n               *D = *S;\n#else\n          if (*D == (Dkey >> 16))\n               *D = *S;\n#endif\n\n          S += Ostep;\n          D += Ostep;\n          --w;\n     }\n\n     if (Ostep < 0) {\n          S--;\n          D--;\n     }\n\n     for (l = w >> 1; l--;) {\n          if (*D == Dkey)\n               *D = *S;\n\n          S += Ostep << 1;\n          D += Ostep << 1;\n     }\n\n     if (w & 1) {\n#ifdef WORDS_BIGENDIAN\n          if (*D == (Dkey >> 16))\n               *D = *S;\n#else\n          if (*D == (Dkey & 0xffff))\n               *D = *S;\n#endif\n     }\n}\n\nstatic void\nBop_rgb332_toK_Aop( GenefxState *gfxs )\n{\n      int  w    = gfxs->length + 1;\n      u8  *S    = gfxs->Bop[0];\n      u8  *D    = gfxs->Aop[0];\n      u8   Dkey = gfxs->Dkey;\n\n      while (--w) {\n           if (*D == Dkey) {\n                *D = *S;\n           }\n\n           ++S;\n           ++D;\n      }\n}\n\nstatic void\nBop_y444_toK_Aop( GenefxState *gfxs )\n{\n     int  w    = gfxs->length + 1;\n     u8  *Sy   = gfxs->Bop[0];\n     u8  *Su   = gfxs->Bop[1];\n     u8  *Sv   = gfxs->Bop[2];\n     u8  *Dy   = gfxs->Aop[0];\n     u8  *Du   = gfxs->Aop[1];\n     u8  *Dv   = gfxs->Aop[2];\n     u32  Dkey = gfxs->Dkey;\n\n     while (--w) {\n          u8 dy = *Dy;\n          u8 du = *Du;\n          u8 dv = *Dv;\n\n          if (Dkey == (u32) (dy << 16 | du << 8 | dv)) {\n               u8 sy = *Sy;\n               u8 su = *Su;\n               u8 sv = *Sv;\n\n               *Dy = sy;\n               *Du = su;\n               *Dv = sv;\n          }\n\n          ++Sy; ++Su; ++Sv;\n          ++Dy; ++Du; ++Dv;\n     }\n}\n\nstatic void\nBop_8_toK_Aop( GenefxState *gfxs )\n{\n      int  w    = gfxs->length + 1;\n      u8  *S    = gfxs->Bop[0];\n      u8  *D    = gfxs->Aop[0];\n      u8   Dkey = gfxs->Dkey;\n\n      while (--w) {\n           if (*D == Dkey) {\n                *D = *S;\n           }\n\n           ++S;\n           ++D;\n      }\n}\n\nstatic GenefxFunc Bop_PFI_toK_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Bop_15_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Bop_16_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Bop_24_24_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Bop_32_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Bop_32_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = Bop_yuv422_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = Bop_rgb332_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = Bop_yuv422_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = Bop_8_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Bop_32_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Bop_14_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Bop_12_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Bop_12vv_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = Bop_32_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Bop_24_18_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Bop_24_18_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Bop_24_18_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Bop_12_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Bop_15_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Bop_15_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Bop_15_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Bop_y444_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Bop_24_16_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Bop_32_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Bop_24_24_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Bop_32_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Bop_32_24_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Bop_y444_toK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Bop_24_24_toK_Aop,\n};\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_Kto_Aop_PFI ****************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_a8_Kto_Aop( GenefxState *gfxs )\n{\n     /* No color to key. */\n     direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length );\n}\n\nstatic void\nBop_yuv422_Kto_Aop( GenefxState *gfxs )\n{\n     int  l;\n     int  w     = gfxs->length;\n     u16 *S     = gfxs->Bop[0];\n     u16 *D     = gfxs->Aop[0];\n     u32  Skey  = gfxs->Skey;\n     int  Ostep = gfxs->Ostep;\n\n     if (Ostep < 0) {\n          S += gfxs->length - 1;\n          D += gfxs->length - 1;\n     }\n\n     if ((long) D & 2) {\n          u16 s = *S;\n\n#ifdef WORDS_BIGENDIAN\n          if (s != (Skey >> 16))\n               *D = s;\n#else\n          if (s != (Skey & 0xffff))\n               *D = s;\n#endif\n\n          S += Ostep;\n          D += Ostep;\n          --w;\n     }\n\n     if (Ostep < 0) {\n         S--;\n         D--;\n     }\n\n     for (l = w >> 1; l--;) {\n          u32 s = *((u32*) S);\n\n          if (s != Skey)\n               *((u32*) D) = s;\n\n          S += Ostep << 1;\n          D += Ostep << 1;\n     }\n\n     if (w & 1) {\n          u16 s = *S;\n\n#ifdef WORDS_BIGENDIAN\n          if (s != (Skey & 0xffff))\n               *D = s;\n#else\n          if (s != (Skey >> 16))\n               *D = s;\n#endif\n     }\n}\n\n/* change the last value to adjust the size of the device (1-4) */\n#define SET_PIXEL_DUFFS_DEVICE(D,S,w) \\\n     SET_PIXEL_DUFFS_DEVICE_N( D, S, w, 4 )\n\nstatic void\nBop_8_Kto_Aop( GenefxState *gfxs )\n{\n     int  i;\n     int  w    = gfxs->length;\n     u8  *S    = gfxs->Bop[0];\n     u8  *D    = gfxs->Aop[0];\n     u32  Skey = gfxs->Skey;\n\n#define SET_PIXEL(d,s)   \\\n     do {                \\\n          if (s != Skey) \\\n               d = s;    \\\n     } while (0)\n\n     if (gfxs->Ostep > 0) {\n          SET_PIXEL_DUFFS_DEVICE( D, S, w );\n     }\n     else {\n          for (i = w - 1; i >= 0; i--)\n               if (S[i] != Skey)\n                    D[i] = S[i];\n     }\n\n#undef SET_PIXEL\n}\n\n#undef SET_PIXEL_DUFFS_DEVICE\n\nstatic void\nBop_alut44_Kto_Aop( GenefxState *gfxs )\n{\n     int  w     = gfxs->length +1;\n     u8  *S     = gfxs->Bop[0];\n     u8  *D     = gfxs->Aop[0];\n     u32  Skey  = gfxs->Skey;\n     int  Ostep = gfxs->Ostep;\n\n     if (Ostep < 0) {\n          S += gfxs->length - 1;\n          D += gfxs->length - 1;\n     }\n\n     while (--w) {\n          u8 s = *S;\n\n          if ((s & 0x0f) != Skey)\n               *D = s;\n\n          S += Ostep;\n          D += Ostep;\n     }\n}\n\nstatic void\nBop_y444_Kto_Aop( GenefxState *gfxs )\n{\n     int  w     = gfxs->length + 1;\n     u8  *Sy    = gfxs->Bop[0];\n     u8  *Su    = gfxs->Bop[1];\n     u8  *Sv    = gfxs->Bop[2];\n     u8  *Dy    = gfxs->Aop[0];\n     u8  *Du    = gfxs->Aop[1];\n     u8  *Dv    = gfxs->Aop[2];\n     u32  Skey  = gfxs->Skey;\n     int  Ostep = gfxs->Ostep;\n\n     if (Ostep < 0) {\n          int offset = gfxs->length - 1;\n\n          Sy += offset; Su += offset; Sv += offset;\n          Dy += offset; Du += offset; Dv += offset;\n     }\n\n     while (--w) {\n          u8 sy = *Sy;\n          u8 su = *Su;\n          u8 sv = *Sv;\n\n          if (Skey != (u32) (sy << 16 | su << 8 | sv)) {\n               *Dy = sy;\n               *Du = su;\n               *Dv = sv;\n          }\n\n          Sy += Ostep; Su += Ostep; Sv += Ostep;\n          Dy += Ostep; Du += Ostep; Dv += Ostep;\n     }\n}\n\nstatic GenefxFunc Bop_PFI_Kto_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Bop_15_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Bop_16_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Bop_24_24_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Bop_32_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Bop_32_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = Bop_a8_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = Bop_yuv422_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = Bop_8_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = Bop_yuv422_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = Bop_8_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = Bop_alut44_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Bop_32_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Bop_14_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Bop_12_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Bop_12vv_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = Bop_32_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Bop_24_18_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Bop_24_18_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Bop_24_18_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Bop_12_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Bop_15_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Bop_15_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Bop_15_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Bop_y444_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Bop_24_16_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Bop_32_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Bop_24_24_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Bop_32_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Bop_32_24_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Bop_y444_Kto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Bop_24_24_Kto_Aop,\n};\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_KtoK_Aop_PFI ***************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_y444_KtoK_Aop( GenefxState *gfxs )\n{\n     int  w     = gfxs->length + 1;\n     u8  *Sy    = gfxs->Bop[0];\n     u8  *Su    = gfxs->Bop[1];\n     u8  *Sv    = gfxs->Bop[2];\n     u8  *Dy    = gfxs->Aop[0];\n     u8  *Du    = gfxs->Aop[1];\n     u8  *Dv    = gfxs->Aop[2];\n     u32  Skey  = gfxs->Skey;\n     u32  Dkey  = gfxs->Dkey;\n     int  Ostep = gfxs->Ostep;\n\n     if (Ostep < 0) {\n          int offset = gfxs->length - 1;\n\n          Sy += offset; Su += offset; Sv += offset;\n          Dy += offset; Du += offset; Dv += offset;\n     }\n\n     while (--w) {\n          u8 sy = *Sy;\n          u8 su = *Su;\n          u8 sv = *Sv;\n          u8 dy = *Dy;\n          u8 du = *Du;\n          u8 dv = *Dv;\n\n          if (Skey != (u32) (sy << 16 | su << 8 | sv) && Dkey == (u32) (dy << 16 | du << 8 | dv)) {\n               *Dy = sy;\n               *Du = su;\n               *Dv = sv;\n          }\n\n          ++Sy; ++Su; ++Sv;\n          ++Dy; ++Du; ++Dv;\n     }\n}\n\nstatic GenefxFunc Bop_PFI_KtoK_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Bop_15_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Bop_16_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Bop_24_24_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Bop_32_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Bop_32_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Bop_32_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Bop_14_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Bop_12_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Bop_12vv_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Bop_24_18_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Bop_24_18_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Bop_24_18_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Bop_12_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Bop_15_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Bop_15_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Bop_15_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Bop_y444_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Bop_24_16_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Bop_32_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Bop_24_24_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Bop_32_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Bop_32_24_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Bop_y444_KtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Bop_24_24_KtoK_Aop,\n};\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_Sto_Aop_PFI ****************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_16_Sto_Aop( GenefxState *gfxs )\n{\n     int  l;\n     int  i      = gfxs->Xphase;\n     int  w      = gfxs->length;\n     u16 *S      = gfxs->Bop[0];\n     u32 *D      = gfxs->Aop[0];\n     int  SperD  = gfxs->SperD;\n     int  SperD2 = SperD << 1;\n\n     if (((long) D) & 2) {\n          *(u16*) D = *S;\n\n          D = gfxs->Aop[0] + 2;\n          i += SperD;\n          --w;\n     }\n\n     l = w >> 1;\n     while (l--) {\n#ifdef WORDS_BIGENDIAN\n          *D++ =  S[i>>16] << 16 | S[(i+SperD)>>16];\n#else\n          *D++ = (S[(i+SperD)>>16] << 16) | S[i>>16];\n#endif\n          i += SperD2;\n     }\n\n     if (w & 1) {\n          *(u16*) D = S[i>>16];\n     }\n}\n\nstatic void\nBop_24_Sto_Aop( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u8  *S     = gfxs->Bop[0];\n     u8  *D     = gfxs->Aop[0];\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          int pixelstart = (i >> 16) * 3;\n\n          *D++ = S[pixelstart+0];\n          *D++ = S[pixelstart+1];\n          *D++ = S[pixelstart+2];\n          i += SperD;\n     }\n}\n\nstatic void\nBop_32_Sto_Aop( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u32 *S     = gfxs->Bop[0];\n     u32 *D     = gfxs->Aop[0];\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          *D++ = S[i>>16];\n          i += SperD;\n     }\n}\n\nstatic void\nBop_8_Sto_Aop( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u8  *S     = gfxs->Bop[0];\n     u8  *D     = gfxs->Aop[0];\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          *D++ = S[i>>16];\n          i += SperD;\n     }\n}\n\nstatic void\nBop_yuy2_Sto_Aop( GenefxState *gfxs )\n{\n     int  l;\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length;\n     u16 *S     = gfxs->Bop[0];\n     u16 *D     = gfxs->Aop[0];\n     int  SperD = gfxs->SperD;\n\n     if ((long) D & 2) {\n          *D++ = *S;\n          i = SperD;\n          --w;\n     }\n\n     for (l = w >> 1; l--;) {\n          u32 d;\n\n          d  = ((u32*) S)[i>>17] & 0xff00ff00;\n#ifdef WORDS_BIGENDIAN\n          d |= (S[i>>16]          & 0x00ff) << 16;\n          d |=  S[(i+SperD)>>16]  & 0x00ff;\n#else\n          d |=  S[i>>16]          & 0x00ff;\n          d |= (S[(i+SperD)>>16]  & 0x00ff) << 16;\n#endif\n          *((u32*) D) = d;\n\n          D += 2;\n          i += SperD << 1;\n     }\n\n     if (w & 1)\n          *D = S[i>>16];\n}\n\nstatic void\nBop_uyvy_Sto_Aop( GenefxState *gfxs )\n{\n     int  l;\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length;\n     u16 *S     = gfxs->Bop[0];\n     u16 *D     = gfxs->Aop[0];\n     int  SperD = gfxs->SperD;\n\n     if ((long) D & 2) {\n          *D++ = *S;\n          i = SperD;\n          --w;\n     }\n\n     for (l = w >> 1; l--;) {\n          u32 d;\n\n          d  = ((u32*) S)[i>>17] & 0x00ff00ff;\n#ifdef WORDS_BIGENDIAN\n          d |= (S[i>>16]          & 0xff00) << 16;\n          d |= (S[(i+SperD)>>16]  & 0xff00);\n#else\n          d |= (S[i>>16]          & 0xff00);\n          d |= (S[(i+SperD)>>16]  & 0xff00) << 16;\n#endif\n          *((u32*) D) = d;\n\n          D += 2;\n          i += SperD << 1;\n     }\n\n     if (w & 1)\n          *D = S[i>>16];\n}\n\nstatic void\nBop_i420_Sto_Aop( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u8  *Sy    = gfxs->Bop[0];\n     u8  *Dy    = gfxs->Aop[0];\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          *Dy++ = Sy[i>>16];\n          i += SperD;\n     }\n\n     if (gfxs->AopY & 1) {\n          u8 *Su = gfxs->Bop[1];\n          u8 *Sv = gfxs->Bop[2];\n          u8 *Du = gfxs->Aop[1];\n          u8 *Dv = gfxs->Aop[2];\n\n          for (w = gfxs->length >> 1, i = 0; w--;) {\n               *Du++ = Su[i>>16];\n               i += SperD;\n          }\n\n          for (w = gfxs->length >> 1, i = 0; w--;) {\n               *Dv++ = Sv[i>>16];\n               i += SperD;\n          }\n     }\n}\n\nstatic void\nBop_nv12_Sto_Aop( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length +1;\n     u8  *Sy    = gfxs->Bop[0];\n     u8  *Dy    = gfxs->Aop[0];\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          *Dy++ = Sy[i>>16];\n          i += SperD;\n     }\n\n     if (gfxs->AopY & 1) {\n          u16 *Suv = gfxs->Bop[1];\n          u16 *Duv = gfxs->Aop[1];\n\n          for (w = gfxs->length >> 1, i = 0; w--;) {\n               *Duv++ = Suv[i>>16];\n               i += SperD;\n          }\n     }\n}\n\nstatic void\nBop_nv16_Sto_Aop( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length +1;\n     u8  *Sy    = gfxs->Bop[0];\n     u16 *Suv   = gfxs->Bop[1];\n     u8  *Dy    = gfxs->Aop[0];\n     u16 *Duv   = gfxs->Aop[1];\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          *Dy++ = Sy[i>>16];\n          i += SperD;\n     }\n\n     for (w = gfxs->length >> 1, i = 0; w--;) {\n          *Duv++ = Suv[i>>16];\n          i += SperD;\n     }\n}\n\nstatic void\nBop_y444_Sto_Aop( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u8  *Sy    = gfxs->Bop[0];\n     u8  *Su    = gfxs->Bop[1];\n     u8  *Sv    = gfxs->Bop[2];\n     u8  *Dy    = gfxs->Aop[0];\n     u8  *Du    = gfxs->Aop[1];\n     u8  *Dv    = gfxs->Aop[2];\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          u8 sy = Sy[i>>16];\n          u8 su = Su[i>>16];\n          u8 sv = Sv[i>>16];\n\n          *Dy++ = sy;\n          *Du++ = su;\n          *Dv++ = sv;\n          i += SperD;\n     }\n}\n\nstatic void\nBop_y42b_Sto_Aop( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u8  *Sy    = gfxs->Bop[0];\n     u8  *Su    = gfxs->Bop[1];\n     u8  *Sv    = gfxs->Bop[2];\n     u8  *Dy    = gfxs->Aop[0];\n     u8  *Du    = gfxs->Aop[1];\n     u8  *Dv    = gfxs->Aop[2];\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          *Dy++ = Sy[i>>16];\n          i += SperD;\n     }\n\n     i = 0;\n     w = (gfxs->length / 2) + 1;\n     while (--w) {\n          *Du++ = Su[i>>16];\n          *Dv++ = Sv[i>>16];\n          i += SperD;\n     }\n}\n\nstatic void\nBop_nv24_Sto_Aop( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u8  *Sy    = gfxs->Bop[0];\n     u16 *Suv   = gfxs->Bop[1];\n     u8  *Dy    = gfxs->Aop[0];\n     u16 *Duv   = gfxs->Aop[1];\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          *Dy++ = Sy[i>>16];\n          *Duv++ = Suv[i>>16];\n\n          i += SperD;\n     }\n}\n\nstatic GenefxFunc Bop_PFI_Sto_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Bop_16_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Bop_16_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Bop_24_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Bop_32_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Bop_32_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = Bop_8_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = Bop_yuy2_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = Bop_8_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = Bop_uyvy_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = Bop_i420_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = Bop_i420_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = Bop_8_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = Bop_8_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Bop_32_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = Bop_nv12_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = Bop_nv16_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Bop_16_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Bop_16_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Bop_16_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = Bop_nv12_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = Bop_32_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Bop_24_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Bop_24_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Bop_24_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Bop_16_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Bop_16_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Bop_16_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Bop_16_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Bop_y444_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Bop_24_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Bop_32_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Bop_24_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = Bop_y42b_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Bop_32_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Bop_32_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = Bop_nv16_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = Bop_y42b_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Bop_y444_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = Bop_nv24_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = Bop_nv24_Sto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Bop_24_Sto_Aop,\n};\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_SKto_Aop_PFI ***************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_a8_SKto_Aop( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u8  *S     = gfxs->Bop[0];\n     u8  *D     = gfxs->Aop[0];\n     int  SperD = gfxs->SperD;\n\n     /* No color to key. */\n     while (--w) {\n          *D++ = S[i>>16];\n          i += SperD;\n     }\n}\n\nstatic void\nBop_yuy2_SKto_Aop( GenefxState *gfxs )\n{\n     int  l;\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length;\n     u16 *S     = gfxs->Bop[0];\n     u16 *D     = gfxs->Aop[0];\n     u32  Skey  = gfxs->Skey;\n#ifdef WORDS_BIGENDIAN\n     u16  Skey0 = gfxs->Skey >> 16;\n     u16  Skey1 = gfxs->Skey & 0xffff;\n#else\n     u16  Skey0 = gfxs->Skey & 0xffff;\n     u16  Skey1 = gfxs->Skey >> 16;\n#endif\n     int  SperD = gfxs->SperD;\n\n     if ((long) D & 2) {\n          u16 s = *S;\n\n          if (s != Skey0)\n               *D = s;\n\n          ++D;\n          i = SperD;\n          --w;\n     }\n\n     for (l = w >> 1; l--;) {\n          u32 s;\n\n          s  = ((u32*) S)[i>>17] & 0xff00ff00;\n#ifdef WORDS_BIGENDIAN\n          s |= (S[i>>16]          & 0x00ff) << 16;\n          s |=  S[(i+SperD)>>16]  & 0x00ff;\n#else\n          s |=  S[i>>16]          & 0x00ff;\n          s |= (S[(i+SperD)>>16]  & 0x00ff) << 16;\n#endif\n          if (s != Skey)\n               *((u32*) D) = s;\n\n          D += 2;\n          i += SperD << 1;\n     }\n\n     if (w & 1) {\n          u16 s = S[i>>16];\n          if (i & 0x20000) {\n               if (s != Skey1)\n                    *D = s;\n          }\n          else {\n               if (s != Skey0)\n                    *D = s;\n          }\n     }\n}\n\nstatic void\nBop_8_SKto_Aop( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u8  *S     = gfxs->Bop[0];\n     u8  *D     = gfxs->Aop[0];\n     u32  Skey  = gfxs->Skey;\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          u8 s = S[i>>16];\n\n          if (s != Skey)\n               *D = s;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nBop_uyvy_SKto_Aop( GenefxState *gfxs )\n{\n     int  l;\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length;\n     u16 *S     = gfxs->Bop[0];\n     u16 *D     = gfxs->Aop[0];\n     u32  Skey  = gfxs->Skey;\n#ifdef WORDS_BIGENDIAN\n     u16  Skey0 = gfxs->Skey >> 16;\n     u16  Skey1 = gfxs->Skey & 0xffff;\n#else\n     u16  Skey0 = gfxs->Skey & 0xffff;\n     u16  Skey1 = gfxs->Skey >> 16;\n#endif\n     int  SperD = gfxs->SperD;\n\n     if ((long) D & 2) {\n          u16 s = *S;\n          if (s != Skey0)\n               *D = s;\n          ++D;\n          i = SperD;\n          --w;\n     }\n\n     for (l = w >> 1; l--;) {\n          u32 s;\n\n          s  = ((u32*) S)[i>>17] & 0x00ff00ff;\n#ifdef WORDS_BIGENDIAN\n          s |= (S[i>>16]          & 0xff00) << 16;\n          s |= (S[(i+SperD)>>16]  & 0xff00);\n#else\n          s |= (S[i>>16]          & 0xff00);\n          s |= (S[(i+SperD)>>16]  & 0xff00) << 16;\n#endif\n          if (s != Skey)\n               *((u32*) D) = s;\n\n          D += 2;\n          i += SperD << 1;\n     }\n\n     if (w & 1) {\n          u16 s = S[i>>16];\n          if (i & 0x20000) {\n               if (s != Skey1)\n                    *D = s;\n          }\n          else {\n               if (s != Skey0)\n                    *D = s;\n          }\n     }\n}\n\nstatic void\nBop_alut44_SKto_Aop( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u8  *S     = gfxs->Bop[0];\n     u8  *D     = gfxs->Aop[0];\n     u32  Skey  = gfxs->Skey;\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          u8 s = S[i>>16];\n\n          if ((s & 0x0f) != Skey)\n               *D = s;\n\n          ++D;\n          i += SperD;\n     }\n}\n\nstatic void\nBop_y444_SKto_Aop( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u8  *Sy    = gfxs->Bop[0];\n     u8  *Su    = gfxs->Bop[1];\n     u8  *Sv    = gfxs->Bop[2];\n     u8  *Dy    = gfxs->Aop[0];\n     u8  *Du    = gfxs->Aop[1];\n     u8  *Dv    = gfxs->Aop[2];\n     u32  Skey  = gfxs->Skey;\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          u8 sy = Sy[i>>16];\n          u8 su = Su[i>>16];\n          u8 sv = Sv[i>>16];\n\n          if (Skey != (u32) (sy << 16 | su << 8 | sv)) {\n               *Dy = sy;\n               *Du = su;\n               *Dv = sv;\n          }\n\n          ++Dy; ++Du; ++Dv;\n          i += SperD;\n     }\n}\n\nstatic GenefxFunc Bop_PFI_SKto_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Bop_15_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Bop_16_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Bop_24_24_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Bop_32_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Bop_32_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = Bop_a8_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = Bop_yuy2_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = Bop_8_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = Bop_uyvy_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = Bop_8_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = Bop_alut44_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Bop_32_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Bop_14_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Bop_12_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Bop_12vv_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = Bop_32_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Bop_24_18_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Bop_24_18_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Bop_24_18_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Bop_12_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Bop_15_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Bop_15_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Bop_15_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Bop_y444_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Bop_24_16_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Bop_32_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Bop_24_24_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Bop_32_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Bop_32_24_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Bop_y444_SKto_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Bop_24_24_SKto_Aop,\n};\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_StoK_Aop_PFI ***************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_y444_StoK_Aop( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u8  *Sy    = gfxs->Bop[0];\n     u8  *Su    = gfxs->Bop[1];\n     u8  *Sv    = gfxs->Bop[2];\n     u8  *Dy    = gfxs->Aop[0];\n     u8  *Du    = gfxs->Aop[1];\n     u8  *Dv    = gfxs->Aop[2];\n     u32  Dkey  = gfxs->Dkey;\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          u8 dy = *Dy;\n          u8 du = *Du;\n          u8 dv = *Dv;\n\n          if (Dkey == (u32) (dy << 16 | du << 8 | dv)) {\n               u8 sy = Sy[i>>16];\n               u8 su = Su[i>>16];\n               u8 sv = Sv[i>>16];\n\n               *Dy = sy;\n               *Du = su;\n               *Dv = sv;\n          }\n\n          ++Dy; ++Du; ++Dv;\n          i += SperD;\n     }\n}\n\nstatic GenefxFunc Bop_PFI_StoK_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Bop_15_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Bop_16_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Bop_24_24_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Bop_32_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Bop_32_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Bop_32_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Bop_14_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Bop_12_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Bop_12vv_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Bop_24_18_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Bop_24_18_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Bop_24_18_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Bop_12_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Bop_15_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Bop_15_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Bop_15_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Bop_y444_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Bop_24_16_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Bop_32_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Bop_24_24_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Bop_32_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Bop_32_24_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Bop_y444_StoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Bop_24_24_StoK_Aop,\n};\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_SKtoK_Aop_PFI **************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_y444_SKtoK_Aop( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u8  *Sy    = gfxs->Bop[0];\n     u8  *Su    = gfxs->Bop[1];\n     u8  *Sv    = gfxs->Bop[2];\n     u8  *Dy    = gfxs->Aop[0];\n     u8  *Du    = gfxs->Aop[1];\n     u8  *Dv    = gfxs->Aop[2];\n     u32  Skey  = gfxs->Skey;\n     u32  Dkey  = gfxs->Dkey;\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          u8 sy = Sy[i>>16];\n          u8 su = Su[i>>16];\n          u8 sv = Sv[i>>16];\n          u8 dy = *Dy;\n          u8 du = *Du;\n          u8 dv = *Dv;\n\n\n          if (Skey != (u32) (sy << 16 | su << 8 | sv) && Dkey == (u32) (dy << 16 | du << 8 | dv)) {\n               *Dy = sy;\n               *Du = su;\n               *Dv = sv;\n          }\n\n          ++Dy; ++Du; ++Dv;\n          i += SperD;\n     }\n}\n\nstatic GenefxFunc Bop_PFI_SKtoK_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Bop_15_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Bop_16_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Bop_24_24_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Bop_32_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Bop_32_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Bop_32_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Bop_14_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Bop_12_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Bop_12vv_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Bop_24_18_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Bop_24_18_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Bop_24_18_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = Bop_12_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = Bop_15_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = Bop_15_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Bop_15_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Bop_y444_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Bop_24_16_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Bop_32_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Bop_24_24_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Bop_32_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Bop_32_24_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Bop_y444_SKtoK_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Bop_24_24_SKtoK_Aop,\n};\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_TEX_to_Aop_PFI *************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_24_TEX_to_Aop( GenefxState *gfxs )\n{\n     int  s     = gfxs->s;\n     int  t     = gfxs->t;\n     int  w     = gfxs->length + 1;\n     u8  *S     = gfxs->Bop[0];\n     u8  *D     = gfxs->Aop[0];\n     int  sp3   = gfxs->src_pitch / 3;\n     int  SperD = gfxs->SperD;\n     int  TperD = gfxs->TperD;\n\n     while (--w) {\n          int pixelstart = ((s >> 16) + (t >> 16) * sp3) * 3;\n          *D++ = S[pixelstart++];\n          *D++ = S[pixelstart++];\n          *D++ = S[pixelstart];\n\n          s += SperD;\n          t += TperD;\n     }\n}\n\nstatic void\nBop_32_TEX_to_Aop( GenefxState *gfxs )\n{\n     int  s     = gfxs->s;\n     int  t     = gfxs->t;\n     int  w     = gfxs->length + 1;\n     u32 *S     = gfxs->Bop[0];\n     u32 *D     = gfxs->Aop[0];\n     int  sp4   = gfxs->src_pitch / 4;\n     int  SperD = gfxs->SperD;\n     int  TperD = gfxs->TperD;\n\n     while (--w) {\n          *D++ = S[(s>>16)+(t>>16)*sp4];\n\n          s += SperD;\n          t += TperD;\n     }\n}\n\nstatic GenefxFunc Bop_PFI_TEX_to_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Bop_24_TEX_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Bop_32_TEX_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Bop_32_TEX_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Bop_32_TEX_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = Bop_32_TEX_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Bop_24_TEX_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Bop_24_TEX_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Bop_24_TEX_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Bop_24_TEX_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Bop_32_TEX_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Bop_24_TEX_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Bop_32_TEX_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = Bop_32_TEX_to_Aop,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Bop_24_TEX_to_Aop,\n};\n\n/**********************************************************************************************************************\n ********************************* Bop_argb_blend_alphachannel_src_invsrc_Aop_PFI *************************************\n **********************************************************************************************************************/\n\n/* change the last value to adjust the size of the device (1-4) */\n#define SET_PIXEL_DUFFS_DEVICE(D,S,w) \\\n     SET_PIXEL_DUFFS_DEVICE_N( D, S, w, 3 )\n\nstatic void\nBop_argb_blend_alphachannel_src_invsrc_Aop_rgb16( GenefxState *gfxs )\n{\n     int  w = gfxs->length;\n     u32 *S = gfxs->Bop[0];\n     u16 *D = gfxs->Aop[0];\n\n#define SET_PIXEL(d,s)                                                                                                \\\n     switch (s >> 26) {                                                                                               \\\n          case 0:                                                                                                     \\\n               break;                                                                                                 \\\n          case 0x3f:                                                                                                  \\\n               d = ARGB_TO_RGB16( s );                                                                                \\\n               break;                                                                                                 \\\n          default:                                                                                                    \\\n               d = (((((((s >> 8) & 0xf800) | ((s >> 3) & 0x001f)) - (d & 0xf81f)) * ((s >> 26) + 1) +                \\\n                      ((d & 0xf81f) << 6)                                                           ) & 0x003e07c0) + \\\n                    (((( (s >> 5) & 0x07e0)                        - (d & 0x07e0)) * ((s >> 26) + 1) +                \\\n                      ((d & 0x07e0) << 6)                                                           ) & 0x0001f800)   \\\n                   ) >> 6;                                                                                            \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\n#undef SET_PIXEL_DUFFS_DEVICE\n\nstatic void\nBop_argb_blend_alphachannel_src_invsrc_Aop_rgb32( GenefxState *gfxs )\n{\n     int  w     = gfxs->length + 1;\n     u32 *S     = gfxs->Bop[0];\n     u32 *D     = gfxs->Aop[0];\n     int  Dstep = gfxs->Astep;\n\n     while (--w) {\n          u32 dp32   = *D;\n          u32 sp32   = *S++;\n          int salpha = (sp32 >> 25) + 1;\n\n#define rb (sp32 & 0xff00ff)\n#define g  (sp32 & 0x00ff00)\n\n          *D = ((((rb - (dp32 & 0xff00ff)) * salpha + ((dp32 & 0xff00ff) << 7)) & 0x7f807f80) +\n                ((( g - (dp32 & 0x00ff00)) * salpha + ((dp32 & 0x00ff00) << 7)) & 0x007f8000)) >> 7;\n          D += Dstep;\n\n#undef rb\n#undef g\n     }\n}\n\nstatic void\nBop_argb_blend_alphachannel_src_invsrc_Aop_argb8565( GenefxState *gfxs )\n{\n     int  w = gfxs->length + 1;\n     u32 *S = gfxs->Bop[0];\n     u8  *D = gfxs->Aop[0];\n\n     while (--w) {\n#ifdef WORDS_BIGENDIAN\n          u16 dp16 = D[1] << 8 | D[2];\n#else\n          u16 dp16 = D[1] << 8 | D[0];\n#endif\n          u32 sp32   = *S++;\n          int salpha = (sp32 >> 26) + 1;\n\n#define srb (((sp32 >> 8) & 0xf800) | ((sp32 >> 3) & 0x001f))\n#define sg   ((sp32 >> 5) & 0x07e0)\n#define drb (dp16 & 0xf81f)\n#define dg  (dp16 & 0x07e0)\n\n          dp16 = ((((srb - drb) * salpha + (drb << 6)) & 0x003e07c0) +\n                  ((( sg -  dg) * salpha + ( dg << 6)) & 0x0001f800)) >> 6;\n\n#ifdef WORDS_BIGENDIAN\n          D[0] = 0;\n          D[1] = (dp16 >> 8) & 0xff;\n          D[2] =  dp16       & 0xff;\n#else\n          D[0] =  dp16       & 0xff;\n          D[1] = (dp16 >> 8) & 0xff;\n          D[2] = 0;\n#endif\n\n          D += 3;\n#undef dg\n#undef drb\n#undef sg\n#undef srb\n     }\n}\n\nstatic GenefxFunc Bop_argb_blend_alphachannel_src_invsrc_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Bop_argb_blend_alphachannel_src_invsrc_Aop_rgb16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Bop_argb_blend_alphachannel_src_invsrc_Aop_rgb32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Bop_argb_blend_alphachannel_src_invsrc_Aop_argb8565,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = NULL,\n};\n\n/**********************************************************************************************************************\n ********************************* Bop_argb_blend_alphachannel_one_invsrc_Aop_argb ************************************\n **********************************************************************************************************************/\n\n/* change the last value to adjust the size of the device (1-4) */\n#define SET_PIXEL_DUFFS_DEVICE(D,S,w) \\\n     SET_PIXEL_DUFFS_DEVICE_N( D, S, w, 3 )\n\nstatic void\nBop_argb_blend_alphachannel_one_invsrc_Aop_argb( GenefxState *gfxs )\n{\n     int  w = gfxs->length;\n     u32 *S = gfxs->Bop[0];\n     u32 *D = gfxs->Aop[0];\n\n#define SET_PIXEL(d,s)                                          \\\n     switch (s >> 24) {                                         \\\n          case 0:                                               \\\n               d += s;                                          \\\n               break;                                           \\\n          case 0xff:                                            \\\n               d = s;                                           \\\n               break;                                           \\\n          default: {                                            \\\n               int invsrc = 256 - (s >> 24);                    \\\n               u32 Drb = ((d & 0x00ff00ff) * invsrc) >> 8;      \\\n               u32 Dag = ((d & 0xff00ff00) >> 8) * invsrc;      \\\n               d = s + (Drb & 0x00ff00ff) + (Dag & 0xff00ff00); \\\n          }                                                     \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\n#undef SET_PIXEL_DUFFS_DEVICE\n\nstatic GenefxFunc Bop_argb_blend_alphachannel_one_invsrc_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Bop_argb_blend_alphachannel_one_invsrc_Aop_argb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Bop_argb_blend_alphachannel_one_invsrc_Aop_argb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = NULL,\n};\n\n/**********************************************************************************************************************\n ********************************* Bop_argb_blend_alphachannel_one_invsrc_premultiply_Aop_PFI *************************\n **********************************************************************************************************************/\n\n/* change the last value to adjust the size of the device (1-4) */\n#define SET_PIXEL_DUFFS_DEVICE(D,S,w) \\\n     SET_PIXEL_DUFFS_DEVICE_N( D, S, w, 3 )\n\nstatic void\nBop_argb_blend_alphachannel_one_invsrc_premultiply_Aop_argb( GenefxState *gfxs )\n{\n     int  w = gfxs->length;\n     u32 *S = gfxs->Bop[0];\n     u32 *D = gfxs->Aop[0];\n\n#define SET_PIXEL(d,s)                                       \\\n     switch (s >> 24) {                                      \\\n          case 0:                                            \\\n               break;                                        \\\n          case 0xff:                                         \\\n               d = s;                                        \\\n               break;                                        \\\n          default: {                                         \\\n               int src    = (s >> 24) + 1;                   \\\n               int invsrc = 256 - (s >> 24);                 \\\n               u32 Drb = ((d & 0x00ff00ff) * invsrc) >> 8;   \\\n               u32 Dag = ((d & 0xff00ff00) >> 8) * invsrc;   \\\n               u32 Srb = ((s & 0x00ff00ff) * src) >> 8;      \\\n               u32 Sxg = ((s & 0xff00ff00) >> 8) * src;      \\\n               d = (Srb & 0x00ff00ff) + (Sxg & 0x0000ff00) + \\\n                   (Drb & 0x00ff00ff) + (Dag & 0xff00ff00) + \\\n                   (  s & 0xff000000);                       \\\n          }                                                  \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\n#undef SET_PIXEL_DUFFS_DEVICE\n\nstatic GenefxFunc Bop_argb_blend_alphachannel_one_invsrc_premultiply_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Bop_argb_blend_alphachannel_one_invsrc_premultiply_Aop_argb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Bop_argb_blend_alphachannel_one_invsrc_premultiply_Aop_argb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = NULL,\n};\n\n/**********************************************************************************************************************\n ********************************* Bop_a8_set_alphapixel_Aop_PFI ******************************************************\n **********************************************************************************************************************/\n\n/* change the last value to adjust the size of the device (1-4) */\n#define SET_PIXEL_DUFFS_DEVICE(D,S,w) \\\n     SET_PIXEL_DUFFS_DEVICE_N( D, S, w, 3 )\n\nstatic void\nBop_a8_set_alphapixel_Aop_argb1555( GenefxState *gfxs )\n{\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u16 *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop;\n     u32  rb  = Cop & 0x7c1f;\n     u32  g   = Cop & 0x03e0;\n\n#define SET_PIXEL(d,s)                                                                                            \\\n     switch (s) {                                                                                                 \\\n          case 0xff: d = Cop;                                                                                     \\\n          case 0: break;                                                                                          \\\n          default: {                                                                                              \\\n               u32 a  = (s >> 3) + 1;                                                                             \\\n               u32 t1 = d & 0x7c1f;                                                                               \\\n               u32 t2 = d & 0x03e0;                                                                               \\\n               d = (d & 0x8000)      |                                                                            \\\n                   ((s & 0x80) << 8) |                                                                            \\\n                   ((((rb - t1) * a + (t1 << 5)) & 0x000f83e0) + (((g - t2) * a + (t2 << 5)) & 0x00007c00)) >> 5; \\\n          }                                                                                                       \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\nstatic void\nBop_a8_set_alphapixel_Aop_rgb16( GenefxState *gfxs )\n{\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u16 *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop;\n     u32  rb  = Cop & 0xf81f;\n     u32  g   = Cop & 0x07e0;\n\n#define SET_PIXEL(d,s)                                                                                            \\\n     switch (s) {                                                                                                 \\\n          case 0xff: d = Cop;                                                                                     \\\n          case 0: break;                                                                                          \\\n          default: {                                                                                              \\\n               u32 a  = (s >> 2) + 1;                                                                             \\\n               u32 t1 = d & 0xf81f;                                                                               \\\n               u32 t2 = d & 0x07e0;                                                                               \\\n               d = ((((rb - t1) * a + (t1 << 6)) & 0x003e07c0) + (((g - t2) * a + (t2 << 6)) & 0x0001f800)) >> 6; \\\n          }                                                                                                       \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\nstatic void\nBop_a8_set_alphapixel_Aop_rgb24( GenefxState *gfxs )\n{\n     int       w     = gfxs->length;\n     u8       *S     = gfxs->Bop[0];\n     u8       *D     = gfxs->Aop[0];\n     DFBColor  color = gfxs->color;\n\n#define SET_PIXEL(D,r,g,b,s)                               \\\n     switch (s) {                                          \\\n         case 0xff:                                        \\\n               D[0] = b;                                   \\\n               D[1] = g;                                   \\\n               D[2] = r;                                   \\\n          case 0: break;                                   \\\n          default: {                                       \\\n               u16 a = s + 1;                              \\\n               D[0] = ((b - D[0]) * a + (D[0] << 8)) >> 8; \\\n               D[1] = ((g - D[1]) * a + (D[1] << 8)) >> 8; \\\n               D[2] = ((r - D[2]) * a + (D[2] << 8)) >> 8; \\\n          }                                                \\\n     }\n\n     while (w > 4) {\n          SET_PIXEL( D, color.r, color.g, color.b, *S ); D += 3; ++S;\n          SET_PIXEL( D, color.r, color.g, color.b, *S ); D += 3; ++S;\n          SET_PIXEL( D, color.r, color.g, color.b, *S ); D += 3; ++S;\n          SET_PIXEL( D, color.r, color.g, color.b, *S ); D += 3; ++S;\n          w -= 4;\n     }\n\n     while (w--) {\n          SET_PIXEL( D, color.r, color.g, color.b, *S ); D += 3; ++S;\n     }\n\n#undef SET_PIXEL\n}\n\nstatic void\nBop_a8_set_alphapixel_Aop_rgb32( GenefxState *gfxs )\n{\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u32 *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop;\n     u32  rb  = Cop & 0xff00ff;\n     u32  g   = Cop & 0x00ff00;\n\n#define SET_PIXEL(d,s)                                                                                            \\\n     switch (s) {                                                                                                 \\\n          case 0xff: d = Cop;                                                                                     \\\n          case 0: break;                                                                                          \\\n          default: {                                                                                              \\\n               u32 a  = s + 1;                                                                                    \\\n               u32 t1 = d & 0x00ff00ff;                                                                           \\\n               u32 t2 = d & 0x0000ff00;                                                                           \\\n               d = ((((rb - t1) * a + (t1 << 8)) & 0xff00ff00) + (((g - t2) * a + (t2 << 8)) & 0x00ff0000)) >> 8; \\\n          }                                                                                                       \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\nstatic void\nBop_a8_set_alphapixel_Aop_argb( GenefxState *gfxs )\n{\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u32 *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop | 0xff000000;\n     u32  rb  = Cop & 0x00ff00ff;\n     u32  g   = gfxs->color.g;\n\n#define SET_PIXEL(d,s)                                                                 \\\n     switch (s) {                                                                      \\\n          case 0xff: d = Cop;                                                          \\\n          case 0: break;                                                               \\\n          default: {                                                                   \\\n               u32 a  = s + 1;                                                         \\\n               u32 a1 = 256 - s;                                                       \\\n               u32 sa = (((d >> 24) * a1) >> 8) + s;                                   \\\n               d = (sa << 24)                                                        + \\\n                    (((((d & 0x00ff00ff)       * a1) + (rb * a)) >> 8) & 0x00ff00ff) + \\\n                    (((((d & 0x0000ff00) >> 8) * a1) + ( g * a))       & 0x0000ff00);  \\\n          }                                                                            \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\nstatic void\nBop_a8_set_alphapixel_Aop_a8( GenefxState *gfxs )\n{\n     int  w = gfxs->length;\n     u8  *S = gfxs->Bop[0];\n     u8  *D = gfxs->Aop[0];\n\n#define SET_PIXEL(d,s)                  \\\n     switch (s) {                       \\\n          case 0xff: d = 0xff;          \\\n          case 0: break;                \\\n          default: {                    \\\n               u16 a1 = 255 - s;        \\\n               d = ((d * a1) >> 8) + s; \\\n          }                             \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\nstatic void\nBop_a8_set_alphapixel_Aop_yuy2( GenefxState *gfxs )\n{\n     int  w = gfxs->length;\n     u8  *S = gfxs->Bop[0];\n     u16 *D = gfxs->Aop[0];\n     u32  y = gfxs->YCop;\n     u32  u = gfxs->CbCop;\n     u32  v = gfxs->CrCop;\n\n#ifdef WORDS_BIGENDIAN\n     u16 Cop0 = u | (y << 8);\n     u16 Cop1 = v | (y << 8);\n#define SET_PIXEL(d,s)                                                                             \\\n     switch (s) {                                                                                  \\\n          case 0xff:                                                                               \\\n               d = ((long) &(d) & 2) ? Cop1 : Cop0;                                                \\\n          case 0x00: break;                                                                        \\\n          default: {                                                                               \\\n               u32 a  = s + 1;                                                                     \\\n               u32 t1 = d & 0xff;                                                                  \\\n               u32 t2 = d >> 8;                                                                    \\\n               if ((long) &(d) & 2)                                                                \\\n                    d = (((v - t1) * a + (t1 << 8)) >> 8) | (((y - t2) * a + (t2 << 8)) & 0xff00); \\\n               else                                                                                \\\n                    d = (((u - t1) * a + (t1 << 8)) >> 8) | (((y - t2) * a + (t2 << 8)) & 0xff00); \\\n          }                                                                                        \\\n     }\n#else\n     u16 Cop0 = y | (u << 8);\n     u16 Cop1 = y | (v << 8);\n#define SET_PIXEL(d,s)                                                                             \\\n     switch (s) {                                                                                  \\\n          case 0xff:                                                                               \\\n               d = ((long) &(d) & 2) ? Cop1 : Cop0;                                                \\\n          case 0x00: break;                                                                        \\\n          default: {                                                                               \\\n               u32 a  = s + 1;                                                                     \\\n               u32 t1 = d & 0xff;                                                                  \\\n               u32 t2 = d >> 8;                                                                    \\\n               if ((long) &(d) & 2)                                                                \\\n                    d = (((y - t1) * a + (t1 << 8)) >> 8) | (((v - t2) * a + (t2 << 8)) & 0xff00); \\\n               else                                                                                \\\n                    d = (((y - t1) * a + (t1 << 8)) >> 8) | (((u - t2) * a + (t2 << 8)) & 0xff00); \\\n          }                                                                                        \\\n     }\n#endif\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\nstatic void\nBop_a8_set_alphapixel_Aop_rgb332( GenefxState *gfxs )\n{\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u8  *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop;\n     u32  rgb = ((Cop & 0xe0) << 16) | ((Cop & 0x1c) << 8) | (Cop & 0x03);\n\n#define SET_PIXEL(d,s)                                                      \\\n     switch (s) {                                                           \\\n          case 0xff: d = Cop;                                               \\\n          case 0: break;                                                    \\\n          default: {                                                        \\\n               u32 a = s + 1;                                               \\\n               u32 t = ((d & 0xe0) << 16) | ((d & 0x1c) << 8) | (d & 0x03); \\\n               u32 c = ((rgb - t) * a + (t << 8)) & 0xe01c0300;             \\\n               d = (c >> 24) | ((c >> 16) & 0xff) | ((c >> 8) & 0xff);      \\\n          }                                                                 \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\nstatic void\nBop_a8_set_alphapixel_Aop_uyvy( GenefxState *gfxs )\n{\n     int  w    = gfxs->length;\n     u8  *S    = gfxs->Bop[0];\n     u16 *D    = gfxs->Aop[0];\n     u32  y    = gfxs->YCop;\n     u32  u    = gfxs->CbCop;\n     u32  v    = gfxs->CrCop;\n     u16  Cop0 = u | (y << 8);\n     u16  Cop1 = v | (y << 8);\n\n#define SET_PIXEL(d,s)                                                                             \\\n     switch (s) {                                                                                  \\\n          case 0xff: d = ((long) &(d) & 2) ? Cop1 : Cop0;                                          \\\n          case 0x00: break;                                                                        \\\n          default: {                                                                               \\\n               u32 a  = s + 1;                                                                     \\\n               u32 t1 = d & 0xff;                                                                  \\\n               u32 t2 = d >> 8;                                                                    \\\n               if ((long) &(d) & 2)                                                                \\\n                    d = (((v - t1) * a + (t1 << 8)) >> 8) | (((y - t2) * a + (t2 << 8)) & 0xff00); \\\n               else                                                                                \\\n                    d = (((u - t1) * a + (t1 << 8)) >> 8) | (((y - t2) * a + (t2 << 8)) & 0xff00); \\\n          }                                                                                        \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\nstatic void\nBop_a8_set_alphapixel_Aop_lut8( GenefxState *gfxs )\n{\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u8  *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop;\n\n#define SET_PIXEL(d,s) \\\n     if (s & 0x80)     \\\n          d = Cop;\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\nstatic void\nBop_a8_set_alphapixel_Aop_alut44( GenefxState *gfxs )\n{\n     int       w       = gfxs->length + 1;\n     u8       *S       = gfxs->Bop[0];\n     u8       *D       = gfxs->Aop[0];\n     u32       Cop     = gfxs->Cop;\n     DFBColor  color   = gfxs->color;\n     DFBColor *entries = gfxs->Alut->entries;\n\n     while (--w) {\n          u16 s = *S;\n          switch (s) {\n               case 0xff: *D = Cop;\n               case 0: break;\n               default: {\n                    u16      a  = s + 1;\n                    u8       d  = *D;\n                    DFBColor dc = entries[d&0x0f];\n                    u16      sa = (d & 0xf0) + s;\n                    dc.r = ((color.r - dc.r) * a + (dc.r << 8)) >> 8;\n                    dc.g = ((color.g - dc.g) * a + (dc.g << 8)) >> 8;\n                    dc.b = ((color.b - dc.b) * a + (dc.b << 8)) >> 8;\n                    if (sa & 0xff00) sa = 0xf0;\n                    *D = (sa & 0xf0) + dfb_palette_search( gfxs->Alut, dc.r, dc.g, dc.b, 0x80 );\n               }\n          }\n\n          ++S;\n          ++D;\n     }\n}\n\nstatic void\nBop_a8_set_alphapixel_Aop_airgb( GenefxState *gfxs )\n{\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u32 *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop;\n     u32  rb  = Cop & 0x00ff00ff;\n     u32  g   = gfxs->color.g;\n\n#define SET_PIXEL(d,s)                                                                 \\\n     switch (s) {                                                                      \\\n          case 0xff: d = Cop;                                                          \\\n          case 0: break;                                                               \\\n          default: {                                                                   \\\n               u32 a  = s + 1;                                                         \\\n               u32 a1 = 256 - a;                                                       \\\n               s32 sa = (d >> 24) - s;                                                 \\\n               if (sa < 0) sa = 0;                                                     \\\n               d = (sa << 24) +                                                        \\\n                    (((((d & 0x00ff00ff)       * a1) + (rb * a)) >> 8) & 0x00ff00ff) + \\\n                    (((((d & 0x0000ff00) >> 8) * a1) + ( g * a))       & 0x0000ff00);  \\\n          }                                                                            \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\nstatic void\nBop_a8_set_alphapixel_Aop_argb1666( GenefxState *gfxs )\n{\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u8  *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop;\n     u32  rb  = Cop & 0x3f03f;\n     u32  g   = Cop & 0xfc0;\n\n#define SET_PIXEL(d,s)                                                                                            \\\n     switch (s) {                                                                                                 \\\n          case 0xff: d = Cop;                                                                                     \\\n          case 0: break;                                                                                          \\\n          default: {                                                                                              \\\n               u32 a  = (s >> 2) + 1;                                                                             \\\n               u32 t1 = d & 0x3f03f;                                                                              \\\n               u32 t2 = d & 0x00fc0;                                                                              \\\n               d = (d & 0x40000)      |                                                                           \\\n                   ((s & 0x80) << 11) |                                                                           \\\n                   ((((rb - t1) * a + (t1 << 6)) & 0x00fc0fc0) + (((g - t2) * a + (t2 << 6)) & 0x0003f000)) >> 6; \\\n          }                                                                                                       \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\nstatic void\nBop_a8_set_alphapixel_Aop_argb6666( GenefxState *gfxs )\n{\n\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u8  *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop;\n     u32  rb  = Cop & 0x3f03f;\n     u32  g   = Cop & 0xfc0;\n\n#define SET_PIXEL(d,s)                                                                                            \\\n     switch (s) {                                                                                                 \\\n          case 0xff: d = Cop;                                                                                     \\\n          case 0: break;                                                                                          \\\n          default: {                                                                                              \\\n               u32 a  = (s >> 2) + 1;                                                                             \\\n               u32 t1 = d & 0x3f03f;                                                                              \\\n               u32 t2 = d & 0x00fc0;                                                                              \\\n               d = (d & 0xfc0000)     |                                                                           \\\n                   ((s & 0xfc) << 16) |                                                                           \\\n                   ((((rb - t1) * a + (t1 << 6)) & 0x00fc0fc0) + (((g - t2) * a + (t2 << 6)) & 0x0003f000)) >> 6; \\\n          }                                                                                                       \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\nstatic void\nBop_a8_set_alphapixel_Aop_rgb18( GenefxState *gfxs )\n{\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u8  *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop;\n     u32  rb  = Cop & 0x3f03f;\n     u32  g   = Cop & 0xfc0;\n\n#define SET_PIXEL(d,s)                                                                                            \\\n     switch (s) {                                                                                                 \\\n          case 0xff: d = Cop;                                                                                     \\\n          case 0: break;                                                                                          \\\n          default: {                                                                                              \\\n               u32 a  = (s >> 2) + 1;                                                                             \\\n               u32 t1 = d & 0x3f03f;                                                                              \\\n               u32 t2 = d & 0x00fc0;                                                                              \\\n               d = ((((rb - t1) * a + (t1 << 6)) & 0x00fc0fc0) + (((g - t2) * a + (t2 << 6)) & 0x000fc000)) >> 6; \\\n          }                                                                                                       \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\nstatic void\nBop_a8_set_alphapixel_Aop_rgba5551( GenefxState *gfxs )\n{\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u16 *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop;\n     u32  rb  = Cop & 0xf83e;\n     u32  g   = Cop & 0x07c0;\n\n#define SET_PIXEL(d,s)                                                                                            \\\n     switch (s) {                                                                                                 \\\n          case 0xff: d = Cop;                                                                                     \\\n          case 0: break;                                                                                          \\\n          default: {                                                                                              \\\n               u32 a  = (s >> 3) + 1;                                                                             \\\n               u32 t1 = d & 0xf83e;                                                                               \\\n               u32 t2 = d & 0x07c0;                                                                               \\\n               d = (d & 0x0001)      |                                                                            \\\n                   ((s & 0x80) >> 7) |                                                                            \\\n                   ((((rb - t1) * a + (t1 << 4)) & 0x000f83e0) + (((g - t2) * a + (t2 << 4)) & 0x00007c00)) >> 4; \\\n          }                                                                                                       \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\nstatic void\nBop_a8_set_alphapixel_Aop_y444( GenefxState *gfxs )\n{\n     int  w     = gfxs->length + 1;\n     u8  *S     = gfxs->Bop[0];\n     u8  *Dy    = gfxs->Aop[0];\n     u8  *Du    = gfxs->Aop[1];\n     u8  *Dv    = gfxs->Aop[2];\n     u8   YCop  = gfxs->YCop;\n     u8   CbCop = gfxs->CbCop;\n     u8   CrCop = gfxs->CrCop;\n\n     while (--w) {\n          u16 s = *S;\n          switch (s) {\n               case 0xff: *Dy = YCop; *Du = CbCop; *Dv = CrCop;\n               case 0: break;\n               default: {\n                    u16 a  = s + 1;\n                    u8  dy = *Dy;\n                    u8  du = *Du;\n                    u8  dv = *Dv;\n                    *Dy = ((YCop  - dy) * a + (dy << 8)) >> 8;\n                    *Du = ((CbCop - du) * a + (du << 8)) >> 8;\n                    *Dv = ((CrCop - dv) * a + (dv << 8)) >> 8;\n               }\n          }\n\n          ++S;\n          ++Dy; ++Du; ++Dv;\n     }\n}\n\nstatic void\nBop_a8_set_alphapixel_Aop_argb8565( GenefxState *gfxs )\n{\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u8  *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop | 0xff0000;\n     u32  srb = Cop & 0xf81f;\n     u32  sg  = Cop & 0x07e0;\n\n#ifdef WORDS_BIGENDIAN\n#define SET_PIXEL(D,s)                                                                                                 \\\n     switch (s) {                                                                                                      \\\n          case 0xff:                                                                                                   \\\n            D[0] = (Cop >> 16) & 0xff;                                                                                 \\\n            D[1] = (Cop >>  8) & 0xff;                                                                                 \\\n            D[2] =  Cop        & 0xff;                                                                                 \\\n          case 0: break;                                                                                               \\\n          default: {                                                                                                   \\\n               u32 a   = s + 1;                                                                                        \\\n               u32 a1  = 256 - s;                                                                                      \\\n               u16 d16 = D[1] << 8 | D[2];                                                                             \\\n               u32 t1  = (d16 & 0xf81f);                                                                               \\\n               u32 t2  = (d16 & 0x07e0);                                                                               \\\n               D[0] = ((D[0] * a1) >> 8) + s;                                                                          \\\n               d16  = ((((srb - t1) * a + (t1 << 8)) & 0x00f81f00) + (((sg - t2) * a + (t2 << 8)) & 0x0007e000)) >> 8; \\\n               D[1] = (d16 >> 8) & 0xff;                                                                               \\\n               D[2] =  d16       & 0xff;                                                                               \\\n          }                                                                                                            \\\n     }\n#else\n#define SET_PIXEL(D,s)                                                                                                 \\\n     switch (s) {                                                                                                      \\\n          case 0xff:                                                                                                   \\\n            D[0] =  Cop        & 0xff;                                                                                 \\\n            D[1] = (Cop >>  8) & 0xff;                                                                                 \\\n            D[2] = (Cop >> 16) & 0xff;                                                                                 \\\n          case 0: break;                                                                                               \\\n          default: {                                                                                                   \\\n               u32 a   = s + 1;                                                                                        \\\n               u32 a1  = 256 - s;                                                                                      \\\n               u16 d16 = D[1] << 8 | D[0];                                                                             \\\n               u32 t1  = (d16 & 0xf81f);                                                                               \\\n               u32 t2  = (d16 & 0x07e0);                                                                               \\\n               D[2] = ((D[2] * a1) >> 8) + s;                                                                          \\\n               d16  = ((((srb - t1) * a + (t1 << 8)) & 0x00f81f00) + (((sg - t2) * a + (t2 << 8)) & 0x0007e000)) >> 8; \\\n               D[1] = (d16 >> 8) & 0xff;                                                                               \\\n               D[0] =  d16       & 0xff;                                                                               \\\n          }                                                                                                            \\\n     }\n#endif\n\n     while (w > 4) {\n          SET_PIXEL( D, *S ); D += 3; ++S;\n          SET_PIXEL( D, *S ); D += 3; ++S;\n          SET_PIXEL( D, *S ); D += 3; ++S;\n          SET_PIXEL( D, *S ); D += 3; ++S;\n          w -= 4;\n     }\n\n     while (w--) {\n          SET_PIXEL( D, *S ); D += 3; ++S;\n     }\n\n#undef SET_PIXEL\n}\n\nstatic void\nBop_a8_set_alphapixel_Aop_vyu( GenefxState *gfxs )\n{\n     int  w     = gfxs->length;\n     u8  *S     = gfxs->Bop[0];\n     u8  *D     = gfxs->Aop[0];\n     u8   YCop  = gfxs->YCop;\n     u8   CbCop = gfxs->CbCop;\n     u8   CrCop = gfxs->CrCop;\n\n#ifdef WORDS_BIGENDIAN\n#define SET_PIXEL(D,y,cb,cr,s)                              \\\n     switch (s) {                                           \\\n         case 0xff:                                         \\\n               D[0] = cr;                                   \\\n               D[1] = y;                                    \\\n               D[2] = cb;                                   \\\n          case 0: break;                                    \\\n          default: {                                        \\\n               u16 a = s + 1;                               \\\n               D[0] = ((cr - D[0]) * a + (D[0] << 8)) >> 8; \\\n               D[1] = ((y  - D[1]) * a + (D[1] << 8)) >> 8; \\\n               D[2] = ((cb - D[2]) * a + (D[2] << 8)) >> 8; \\\n          }                                                 \\\n     }\n#else\n#define SET_PIXEL(D,y,cb,cr,s)                              \\\n     switch (s) {                                           \\\n         case 0xff:                                         \\\n               D[0] = cb;                                   \\\n               D[1] = y;                                    \\\n               D[2] = cr;                                   \\\n          case 0: break;                                    \\\n          default: {                                        \\\n               u16 a = s + 1;                               \\\n               D[0] = ((cb - D[0]) * a + (D[0] << 8)) >> 8; \\\n               D[1] = ((y  - D[1]) * a + (D[1] << 8)) >> 8; \\\n               D[2] = ((cr - D[2]) * a + (D[2] << 8)) >> 8; \\\n          }                                                 \\\n     }\n#endif\n\n     while (w > 4) {\n          SET_PIXEL( D, YCop, CbCop, CrCop, *S ); D += 3; ++S;\n          SET_PIXEL( D, YCop, CbCop, CrCop, *S ); D += 3; ++S;\n          SET_PIXEL( D, YCop, CbCop, CrCop, *S ); D += 3; ++S;\n          SET_PIXEL( D, YCop, CbCop, CrCop, *S ); D += 3; ++S;\n          w -= 4;\n     }\n\n     while (w--) {\n          SET_PIXEL( D, YCop, CbCop, CrCop, *S ); D += 3; ++S;\n     }\n\n#undef SET_PIXEL\n}\n\nstatic void\nBop_a8_set_alphapixel_Aop_bgr24( GenefxState *gfxs )\n{\n     int       w     = gfxs->length;\n     u8       *S     = gfxs->Bop[0];\n     u8       *D     = gfxs->Aop[0];\n     DFBColor  color = gfxs->color;\n\n#define SET_PIXEL(D,r,g,b,s)                               \\\n     switch (s) {                                          \\\n         case 0xff:                                        \\\n               D[0] = r;                                   \\\n               D[1] = g;                                   \\\n               D[2] = b;                                   \\\n          case 0: break;                                   \\\n          default: {                                       \\\n               u16 a = s + 1;                              \\\n               D[0] = ((r - D[0]) * a + (D[0] << 8)) >> 8; \\\n               D[1] = ((g - D[1]) * a + (D[1] << 8)) >> 8; \\\n               D[2] = ((b - D[2]) * a + (D[2] << 8)) >> 8; \\\n          }                                                \\\n     }\n\n     while (w > 4) {\n          SET_PIXEL( D, color.r, color.g, color.b, *S ); D += 3; ++S;\n          SET_PIXEL( D, color.r, color.g, color.b, *S ); D += 3; ++S;\n          SET_PIXEL( D, color.r, color.g, color.b, *S ); D += 3; ++S;\n          SET_PIXEL( D, color.r, color.g, color.b, *S ); D += 3; ++S;\n          w -= 4;\n     }\n\n     while (w--) {\n          SET_PIXEL( D, color.r, color.g, color.b, *S ); D += 3, ++S;\n     }\n\n#undef SET_PIXEL\n}\n\n#undef SET_PIXEL_DUFFS_DEVICE\n\nstatic GenefxFunc Bop_a8_set_alphapixel_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Bop_a8_set_alphapixel_Aop_argb1555,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Bop_a8_set_alphapixel_Aop_rgb16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Bop_a8_set_alphapixel_Aop_rgb24,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Bop_a8_set_alphapixel_Aop_rgb32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Bop_a8_set_alphapixel_Aop_argb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = Bop_a8_set_alphapixel_Aop_a8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = Bop_a8_set_alphapixel_Aop_yuy2,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = Bop_a8_set_alphapixel_Aop_rgb332,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = Bop_a8_set_alphapixel_Aop_uyvy,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = Bop_a8_set_alphapixel_Aop_lut8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = Bop_a8_set_alphapixel_Aop_alut44,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Bop_a8_set_alphapixel_Aop_airgb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = Bop_a8_set_alphapixel_Aop_argb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Bop_a8_set_alphapixel_Aop_argb1666,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Bop_a8_set_alphapixel_Aop_argb6666,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Bop_a8_set_alphapixel_Aop_rgb18,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Bop_a8_set_alphapixel_Aop_rgba5551,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Bop_a8_set_alphapixel_Aop_y444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Bop_a8_set_alphapixel_Aop_argb8565,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Bop_a8_set_alphapixel_Aop_argb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = Bop_a8_set_alphapixel_Aop_vyu,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Bop_a8_set_alphapixel_Aop_argb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Bop_a8_set_alphapixel_Aop_y444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Bop_a8_set_alphapixel_Aop_bgr24,\n};\n\n/**********************************************************************************************************************\n ********************************* Bop_a1_set_alphapixel_Aop_PFI ******************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_a1_set_alphapixel_Aop_argb1555( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u16 *D   = gfxs->Aop[0];\n     u16  Cop = gfxs->Cop | 0x8000;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_rgb16( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u16 *D   = gfxs->Aop[0];\n     u16  Cop = gfxs->Cop;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_rgb24( GenefxState *gfxs )\n{\n     int       i;\n     int       w     = gfxs->length;\n     u8       *S     = gfxs->Bop[0];\n     u8       *D     = gfxs->Aop[0];\n     DFBColor  color = gfxs->color;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               D[0] = color.b;\n               D[1] = color.g;\n               D[2] = color.r;\n          }\n\n          D += 3;\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_rgb32( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u32 *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_argb( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u32 *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop | 0xff000000;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_a8( GenefxState *gfxs )\n{\n     int  i;\n     int  w = gfxs->length;\n     u8  *S = gfxs->Bop[0];\n     u8  *D = gfxs->Aop[0];\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               D[i] = 0xff;\n          }\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_yuy2( GenefxState *gfxs )\n{\n     int  i;\n     int  w    = gfxs->length;\n     u8  *S    = gfxs->Bop[0];\n     u16 *D    = gfxs->Aop[0];\n     u16  Cop0 = gfxs->YCop | (gfxs->CbCop << 8);\n     u16  Cop1 = gfxs->YCop | (gfxs->CrCop << 8);\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               D[i] = ((long) &D[i] & 2) ? Cop1 : Cop0;\n          }\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_rgb332( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u8  *D   = gfxs->Aop[0];\n     u8   Cop = gfxs->Cop;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_uyvy( GenefxState *gfxs )\n{\n     int  i;\n     int  w    = gfxs->length;\n     u8  *S    = gfxs->Bop[0];\n     u16 *D    = gfxs->Aop[0];\n     u16  Cop0 = gfxs->CbCop | (gfxs->YCop << 8);\n     u16  Cop1 = gfxs->CrCop | (gfxs->YCop << 8);\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               D[i] = ((long) &D[i] & 2) ? Cop1 : Cop0;\n          }\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_lut8( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u8  *D   = gfxs->Aop[0];\n     u8   Cop = gfxs->Cop;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_alut44( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u8  *D   = gfxs->Aop[0];\n     u8   Cop = gfxs->Cop;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_airgb( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u32 *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop & 0x00ffffff;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_argb2554( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u16 *D   = gfxs->Aop[0];\n     u16  Cop = gfxs->Cop | 0xc000;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_argb4444( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u16 *D   = gfxs->Aop[0];\n     u16  Cop = gfxs->Cop | 0xf000;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_rgba4444( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u16 *D   = gfxs->Aop[0];\n     u16  Cop = gfxs->Cop | 0x000f;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_argb1666( GenefxState *gfxs )\n{\n     int       i;\n     int       w     = gfxs->length;\n     u8       *S     = gfxs->Bop[0];\n     u8       *D     = gfxs->Aop[0];\n     DFBColor  color = gfxs->color;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               u32 pixel = PIXEL_ARGB1666( color.a, color.r, color.g, color.b );\n\n               D[0] = pixel;\n               D[1] = pixel >> 8;\n               D[2] = pixel >> 16;\n          }\n\n          D += 3;\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_argb6666( GenefxState *gfxs )\n{\n     int       i;\n     int       w     = gfxs->length;\n     u8       *S     = gfxs->Bop[0];\n     u8       *D     = gfxs->Aop[0];\n     DFBColor  color = gfxs->color;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               u32 pixel = PIXEL_ARGB6666( color.a, color.r, color.g, color.b );\n\n               D[0] = pixel;\n               D[1] = pixel >> 8;\n               D[2] = pixel >> 16;\n          }\n\n          D += 3;\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_rgb18( GenefxState *gfxs )\n{\n     int       i;\n     int       w     = gfxs->length;\n     u8       *S     = gfxs->Bop[0];\n     u8       *D     = gfxs->Aop[0];\n     DFBColor  color = gfxs->color;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               u32 pixel = PIXEL_RGB18( color.r, color.g, color.b );\n\n               D[0] = pixel;\n               D[1] = pixel >> 8;\n               D[2] = pixel >> 16;\n          }\n\n          D += 3;\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_rgba5551( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u16 *D   = gfxs->Aop[0];\n     u16  Cop = gfxs->Cop | 0x0001;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_y444( GenefxState *gfxs )\n{\n     int  i;\n     int  w  = gfxs->length;\n     u8  *S  = gfxs->Bop[0];\n     u8  *Dy = gfxs->Aop[0];\n     u8  *Du = gfxs->Aop[1];\n     u8  *Dv = gfxs->Aop[2];\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               Dy[i] = gfxs->YCop;\n               Du[i] = gfxs->CbCop;\n               Dv[i] = gfxs->CrCop;\n          }\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_argb8565( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u8  *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop | 0xff0000;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n#ifdef WORDS_BIGENDIAN\n               D[0] = (Cop >> 16) & 0xff;\n               D[1] = (Cop >>  8) & 0xff;\n               D[2] =  Cop        & 0xff;\n#else\n               D[0] =  Cop        & 0xff;\n               D[1] = (Cop >>  8) & 0xff;\n               D[2] = (Cop >> 16) & 0xff;\n#endif\n          }\n\n          D += 3;\n     }\n}\n\nstatic void\nBop_a1_set_alphapixel_Aop_bgr24( GenefxState *gfxs )\n{\n     int       i;\n     int       w     = gfxs->length;\n     u8       *S     = gfxs->Bop[0];\n     u8       *D     = gfxs->Aop[0];\n     DFBColor  color = gfxs->color;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (0x80 >> (i & 7))) {\n               D[0] = color.r;\n               D[1] = color.g;\n               D[2] = color.b;\n          }\n\n          D += 3;\n     }\n}\n\nstatic GenefxFunc Bop_a1_set_alphapixel_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Bop_a1_set_alphapixel_Aop_argb1555,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Bop_a1_set_alphapixel_Aop_rgb16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Bop_a1_set_alphapixel_Aop_rgb24,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Bop_a1_set_alphapixel_Aop_rgb32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Bop_a1_set_alphapixel_Aop_argb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = Bop_a1_set_alphapixel_Aop_a8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = Bop_a1_set_alphapixel_Aop_yuy2,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = Bop_a1_set_alphapixel_Aop_rgb332,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = Bop_a1_set_alphapixel_Aop_uyvy,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = Bop_a1_set_alphapixel_Aop_lut8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = Bop_a1_set_alphapixel_Aop_alut44,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Bop_a1_set_alphapixel_Aop_airgb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Bop_a1_set_alphapixel_Aop_argb2554,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Bop_a1_set_alphapixel_Aop_argb4444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = Bop_a1_set_alphapixel_Aop_rgba4444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = Bop_a1_set_alphapixel_Aop_argb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Bop_a1_set_alphapixel_Aop_argb1666,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Bop_a1_set_alphapixel_Aop_argb6666,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Bop_a1_set_alphapixel_Aop_rgb18,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = Bop_a1_set_alphapixel_Aop_rgba5551,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = Bop_a1_set_alphapixel_Aop_y444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = Bop_a1_set_alphapixel_Aop_argb8565,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = Bop_a1_set_alphapixel_Aop_argb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Bop_a1_set_alphapixel_Aop_argb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = Bop_a1_set_alphapixel_Aop_y444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Bop_a1_set_alphapixel_Aop_bgr24,\n};\n\n/**********************************************************************************************************************\n ********************************* Bop_a1_lsb_set_alphapixel_Aop_PFI **************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_a1_lsb_set_alphapixel_Aop_argb1555( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u16 *D   = gfxs->Aop[0];\n     u16  Cop = gfxs->Cop | 0x8000;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (1 << (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_lsb_set_alphapixel_Aop_rgb16( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u16 *D   = gfxs->Aop[0];\n     u16  Cop = gfxs->Cop;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (1 << (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_lsb_set_alphapixel_Aop_rgb24( GenefxState *gfxs )\n{\n     int       i;\n     int       w     = gfxs->length;\n     u8       *S     = gfxs->Bop[0];\n     u8       *D     = gfxs->Aop[0];\n     DFBColor  color = gfxs->color;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (1 << (i & 7))) {\n               D[0] = color.b;\n               D[1] = color.g;\n               D[2] = color.r;\n          }\n\n          D += 3;\n     }\n}\n\nstatic void\nBop_a1_lsb_set_alphapixel_Aop_rgb32( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u32 *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (1 << (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_lsb_set_alphapixel_Aop_argb( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u32 *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop | 0xff000000;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (1 << (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_lsb_set_alphapixel_Aop_a8( GenefxState *gfxs )\n{\n     int  i;\n     int  w = gfxs->length;\n     u8  *S = gfxs->Bop[0];\n     u8  *D = gfxs->Aop[0];\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (1 << (i & 7))) {\n               D[i] = 0xff;\n          }\n     }\n}\n\nstatic void\nBop_a1_lsb_set_alphapixel_Aop_yuy2( GenefxState *gfxs )\n{\n     int  i;\n     int  w    = gfxs->length;\n     u8  *S    = gfxs->Bop[0];\n     u16 *D    = gfxs->Aop[0];\n     u16  Cop0 = gfxs->YCop | (gfxs->CbCop << 8);\n     u16  Cop1 = gfxs->YCop | (gfxs->CrCop << 8);\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (1 << (i & 7))) {\n               D[i] = ((long) &D[i] & 2) ? Cop1 : Cop0;\n          }\n     }\n}\n\nstatic void\nBop_a1_lsb_set_alphapixel_Aop_rgb332( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u8  *D   = gfxs->Aop[0];\n     u8   Cop = gfxs->Cop;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (1 << (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_lsb_set_alphapixel_Aop_uyvy( GenefxState *gfxs )\n{\n     int  i;\n     int  w    = gfxs->length;\n     u8  *S    = gfxs->Bop[0];\n     u16 *D    = gfxs->Aop[0];\n     u16  Cop0 = gfxs->CbCop | (gfxs->YCop << 8);\n     u16  Cop1 = gfxs->CrCop | (gfxs->YCop << 8);\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (1 << (i & 7))) {\n               D[i] = ((long) &D[i] & 2) ? Cop1 : Cop0;\n          }\n     }\n}\n\nstatic void\nBop_a1_lsb_set_alphapixel_Aop_lut8( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u8  *D   = gfxs->Aop[0];\n     u8   Cop = gfxs->Cop;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (1 << (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_lsb_set_alphapixel_Aop_alut44( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u8  *D   = gfxs->Aop[0];\n     u8   Cop = gfxs->Cop;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (1 << (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_lsb_set_alphapixel_Aop_airgb( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u32 *D   = gfxs->Aop[0];\n     u32  Cop = gfxs->Cop & 0x00ffffff;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (1 << (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_lsb_set_alphapixel_Aop_argb2554( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u16 *D   = gfxs->Aop[0];\n     u16  Cop = gfxs->Cop | 0xc000;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (1 << (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_lsb_set_alphapixel_Aop_argb4444( GenefxState *gfxs )\n{\n     int  i;\n     int  w   = gfxs->length;\n     u8  *S   = gfxs->Bop[0];\n     u16 *D   = gfxs->Aop[0];\n     u16  Cop = gfxs->Cop | 0xf000;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (1 << (i & 7))) {\n               D[i] = Cop;\n          }\n     }\n}\n\nstatic void\nBop_a1_lsb_set_alphapixel_Aop_argb1666( GenefxState *gfxs )\n{\n     int       i;\n     int       w     = gfxs->length;\n     u8       *S     = gfxs->Bop[0];\n     u8       *D     = gfxs->Aop[0];\n     DFBColor  color = gfxs->color;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (1 << (i & 7))) {\n               u32 pixel = PIXEL_ARGB1666( color.a, color.r, color.g, color.b );\n\n               D[0] = pixel;\n               D[1] = pixel >> 8;\n               D[2] = pixel >> 16;\n          }\n\n          D += 3;\n     }\n}\n\nstatic void\nBop_a1_lsb_set_alphapixel_Aop_argb6666( GenefxState *gfxs )\n{\n     int       i;\n     int       w     = gfxs->length;\n     u8       *S     = gfxs->Bop[0];\n     u8       *D     = gfxs->Aop[0];\n     DFBColor  color = gfxs->color;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (1 << (i & 7))) {\n               u32 pixel = PIXEL_ARGB6666( color.a, color.r, color.g, color.b );\n\n               D[0] = pixel;\n               D[1] = pixel >> 8;\n               D[2] = pixel >> 16;\n          }\n\n          D += 3;\n     }\n}\n\nstatic void\nBop_a1_lsb_set_alphapixel_Aop_rgb18( GenefxState *gfxs )\n{\n     int       i;\n     int       w     = gfxs->length;\n     u8       *S     = gfxs->Bop[0];\n     u8       *D     = gfxs->Aop[0];\n     DFBColor  color = gfxs->color;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (1 << (i & 7))) {\n               u32 pixel = PIXEL_RGB18( color.r, color.g, color.b );\n\n               D[0] = pixel;\n               D[1] = pixel >> 8;\n               D[2] = pixel >> 16;\n          }\n\n          D += 3;\n     }\n}\n\nstatic void\nBop_a1_lsb_set_alphapixel_Aop_bgr24( GenefxState *gfxs )\n{\n     int       i;\n     int       w     = gfxs->length;\n     u8       *S     = gfxs->Bop[0];\n     u8       *D     = gfxs->Aop[0];\n     DFBColor  color = gfxs->color;\n\n     for (i = 0; i < w; ++i) {\n          if (S[i>>3] & (1 << (i & 7))) {\n               D[0] = color.r;\n               D[1] = color.g;\n               D[2] = color.b;\n          }\n\n          D += 3;\n     }\n}\n\nstatic GenefxFunc Bop_a1_lsb_set_alphapixel_Aop_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = Bop_a1_lsb_set_alphapixel_Aop_argb1555,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = Bop_a1_lsb_set_alphapixel_Aop_rgb16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = Bop_a1_lsb_set_alphapixel_Aop_rgb24,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = Bop_a1_lsb_set_alphapixel_Aop_rgb32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Bop_a1_lsb_set_alphapixel_Aop_argb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = Bop_a1_lsb_set_alphapixel_Aop_a8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = Bop_a1_lsb_set_alphapixel_Aop_yuy2,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = Bop_a1_lsb_set_alphapixel_Aop_rgb332,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = Bop_a1_lsb_set_alphapixel_Aop_uyvy,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = Bop_a1_lsb_set_alphapixel_Aop_lut8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = Bop_a1_lsb_set_alphapixel_Aop_alut44,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = Bop_a1_lsb_set_alphapixel_Aop_airgb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = Bop_a1_lsb_set_alphapixel_Aop_argb2554,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = Bop_a1_lsb_set_alphapixel_Aop_argb4444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = Bop_a1_lsb_set_alphapixel_Aop_argb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = Bop_a1_lsb_set_alphapixel_Aop_argb1666,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = Bop_a1_lsb_set_alphapixel_Aop_argb6666,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = Bop_a1_lsb_set_alphapixel_Aop_rgb18,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = Bop_a1_lsb_set_alphapixel_Aop_argb,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = Bop_a1_lsb_set_alphapixel_Aop_bgr24,\n};\n\n/**********************************************************************************************************************\n ********************************* Bop_lut2_translate_to_Aop_lut8 *****************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_lut2_translate_to_Aop_lut8_C( GenefxState *gfxs )\n{\n     int  i;\n     int  w = gfxs->length;\n     int  l = (w + 3) / 4;\n     u8  *S = gfxs->Bop[0];\n     u8  *D = gfxs->Aop[0];\n\n     for (i = 0; i < l; ++i, D += 4, w -= 4) {\n          u8 index;\n          u8 pixels = S[i];\n\n          switch (w) {\n               default:\n                    index = (pixels & 3);\n                    if (index < gfxs->num_trans && gfxs->trans[index] >= 0)\n                         D[3] = gfxs->trans[index];\n\n               case 3:\n                    index = (pixels >> 2) & 3;\n                    if (index < gfxs->num_trans && gfxs->trans[index] >= 0)\n                         D[2] = gfxs->trans[index];\n\n               case 2:\n                    index = (pixels >> 4) & 3;\n                    if (index < gfxs->num_trans && gfxs->trans[index] >= 0)\n                         D[1] = gfxs->trans[index];\n\n               case 1:\n                    index = pixels >> 6;\n                    if (index < gfxs->num_trans && gfxs->trans[index] >= 0)\n                         D[0] = gfxs->trans[index];\n          }\n     }\n}\n\nstatic GenefxFunc Bop_lut2_translate_to_Aop_lut8 = Bop_lut2_translate_to_Aop_lut8_C;\n\n/**********************************************************************************************************************\n ********************************* Xacc_blend *************************************************************************\n **********************************************************************************************************************/\n\nstatic void\nXacc_blend_zero( GenefxState *gfxs )\n{\n     int                i;\n     int                w = gfxs->length;\n     GenefxAccumulator *X = gfxs->Xacc;\n     GenefxAccumulator *Y = gfxs->Yacc;\n\n     for (i = 0; i < w; ++i) {\n          if (!(Y[i].RGB.a & 0xf000))\n               X[i].RGB.a = X[i].RGB.r = X[i].RGB.g = X[i].RGB.b = 0;\n          else\n               X[i] = Y[i];\n     }\n}\n\nstatic void\nXacc_blend_one( GenefxState *gfxs )\n{\n     int                i;\n     int                w = gfxs->length;\n     GenefxAccumulator *X = gfxs->Xacc;\n     GenefxAccumulator *Y = gfxs->Yacc;\n\n     for (i = 0; i < w; ++i) {\n          X[i] = Y[i];\n     }\n}\n\nstatic void\nXacc_blend_srccolor( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *X = gfxs->Xacc;\n     GenefxAccumulator *Y = gfxs->Yacc;\n\n     if (gfxs->Sacc) {\n          GenefxAccumulator *S = gfxs->Sacc;\n\n          while (--w) {\n               if (!(Y->RGB.a & 0xf000)) {\n                    X->RGB.r = ((S->RGB.r + 1) * Y->RGB.r) >> 8;\n                    X->RGB.g = ((S->RGB.g + 1) * Y->RGB.g) >> 8;\n                    X->RGB.b = ((S->RGB.b + 1) * Y->RGB.b) >> 8;\n                    X->RGB.a = ((S->RGB.a + 1) * Y->RGB.a) >> 8;\n               }\n               else\n                    *X = *Y;\n\n               ++S;\n               ++X; ++Y;\n          }\n     }\n     else {\n          GenefxAccumulator Cacc = gfxs->Cacc;\n          Cacc.RGB.r = Cacc.RGB.r + 1;\n          Cacc.RGB.g = Cacc.RGB.g + 1;\n          Cacc.RGB.b = Cacc.RGB.b + 1;\n          Cacc.RGB.a = Cacc.RGB.a + 1;\n\n          while (--w) {\n               if (!(Y->RGB.a & 0xf000)) {\n                    X->RGB.r = (Cacc.RGB.r * Y->RGB.r) >> 8;\n                    X->RGB.g = (Cacc.RGB.g * Y->RGB.g) >> 8;\n                    X->RGB.b = (Cacc.RGB.b * Y->RGB.b) >> 8;\n                    X->RGB.a = (Cacc.RGB.a * Y->RGB.a) >> 8;\n               }\n               else\n                    *X = *Y;\n\n               ++X; ++Y;\n          }\n     }\n}\n\nstatic void\nXacc_blend_invsrccolor( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *X = gfxs->Xacc;\n     GenefxAccumulator *Y = gfxs->Yacc;\n\n     if (gfxs->Sacc) {\n          GenefxAccumulator *S = gfxs->Sacc;\n\n          while (--w) {\n               if (!(Y->RGB.a & 0xf000)) {\n                    X->RGB.r = ((0x100 - S->RGB.r) * Y->RGB.r) >> 8;\n                    X->RGB.g = ((0x100 - S->RGB.g) * Y->RGB.g) >> 8;\n                    X->RGB.b = ((0x100 - S->RGB.b) * Y->RGB.b) >> 8;\n                    X->RGB.a = ((0x100 - S->RGB.a) * Y->RGB.a) >> 8;\n               }\n               else\n                    *X = *Y;\n\n               ++S;\n               ++X; ++Y;\n          }\n     }\n     else {\n          GenefxAccumulator Cacc = gfxs->Cacc;\n          Cacc.RGB.r = 0x100 - Cacc.RGB.r;\n          Cacc.RGB.g = 0x100 - Cacc.RGB.g;\n          Cacc.RGB.b = 0x100 - Cacc.RGB.b;\n          Cacc.RGB.a = 0x100 - Cacc.RGB.a;\n\n          while (--w) {\n               if (!(Y->RGB.a & 0xf000)) {\n                    X->RGB.r = (Cacc.RGB.r * Y->RGB.r) >> 8;\n                    X->RGB.g = (Cacc.RGB.g * Y->RGB.g) >> 8;\n                    X->RGB.b = (Cacc.RGB.b * Y->RGB.b) >> 8;\n                    X->RGB.a = (Cacc.RGB.a * Y->RGB.a) >> 8;\n               }\n               else\n                    *X = *Y;\n\n               ++X; ++Y;\n          }\n     }\n}\n\nstatic void\nXacc_blend_srcalpha( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *X = gfxs->Xacc;\n     GenefxAccumulator *Y = gfxs->Yacc;\n\n     if (gfxs->Sacc) {\n          GenefxAccumulator *S = gfxs->Sacc;\n\n          while (--w) {\n               if (!(Y->RGB.a & 0xf000)) {\n                    u16 Sa = S->RGB.a + 1;\n\n                    X->RGB.r = (Sa * Y->RGB.r) >> 8;\n                    X->RGB.g = (Sa * Y->RGB.g) >> 8;\n                    X->RGB.b = (Sa * Y->RGB.b) >> 8;\n                    X->RGB.a = (Sa * Y->RGB.a) >> 8;\n               }\n               else\n                    *X = *Y;\n\n               ++S;\n               ++X; ++Y;\n          }\n     }\n     else {\n          u16 Sa = gfxs->color.a + 1;\n\n          while (--w) {\n               if (!(Y->RGB.a & 0xf000)) {\n                    X->RGB.r = (Sa * Y->RGB.r) >> 8;\n                    X->RGB.g = (Sa * Y->RGB.g) >> 8;\n                    X->RGB.b = (Sa * Y->RGB.b) >> 8;\n                    X->RGB.a = (Sa * Y->RGB.a) >> 8;\n               }\n               else\n                    *X = *Y;\n\n               ++X; ++Y;\n          }\n     }\n}\n\nstatic void\nXacc_blend_invsrcalpha( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *X = gfxs->Xacc;\n     GenefxAccumulator *Y = gfxs->Yacc;\n\n     if (gfxs->Sacc) {\n          GenefxAccumulator *S = gfxs->Sacc;\n\n          while (--w) {\n               if (!(Y->RGB.a & 0xf000)) {\n                    u16 Sa = 0x100 - S->RGB.a;\n\n                    X->RGB.r = (Sa * Y->RGB.r) >> 8;\n                    X->RGB.g = (Sa * Y->RGB.g) >> 8;\n                    X->RGB.b = (Sa * Y->RGB.b) >> 8;\n                    X->RGB.a = (Sa * Y->RGB.a) >> 8;\n               }\n               else\n                    *X = *Y;\n\n               ++S;\n               ++X; ++Y;\n          }\n     }\n     else {\n          u16 Sa = 0x100 - gfxs->color.a;\n\n          while (--w) {\n               if (!(Y->RGB.a & 0xf000)) {\n                    X->RGB.a = (Sa * Y->RGB.a) >> 8;\n                    X->RGB.r = (Sa * Y->RGB.r) >> 8;\n                    X->RGB.g = (Sa * Y->RGB.g) >> 8;\n                    X->RGB.b = (Sa * Y->RGB.b) >> 8;\n               }\n               else\n                    *X = *Y;\n\n               ++X; ++Y;\n          }\n     }\n}\n\nstatic void\nXacc_blend_dstalpha( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *D = gfxs->Dacc;\n     GenefxAccumulator *X = gfxs->Xacc;\n     GenefxAccumulator *Y = gfxs->Yacc;\n\n     while (--w) {\n          if (!(Y->RGB.a & 0xf000)) {\n               u16 Da = D->RGB.a + 1;\n\n               X->RGB.r = (Da * Y->RGB.r) >> 8;\n               X->RGB.g = (Da * Y->RGB.g) >> 8;\n               X->RGB.b = (Da * Y->RGB.b) >> 8;\n               X->RGB.a = (Da * Y->RGB.a) >> 8;\n          }\n          else\n               *X = *Y;\n\n          ++D;\n          ++X; ++Y;\n     }\n}\n\nstatic void\nXacc_blend_invdstalpha( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *D = gfxs->Dacc;\n     GenefxAccumulator *X = gfxs->Xacc;\n     GenefxAccumulator *Y = gfxs->Yacc;\n\n     while (--w) {\n          if (!(Y->RGB.a & 0xf000)) {\n               u16 Da = 0x100 - D->RGB.a;\n\n               X->RGB.r = (Da * Y->RGB.r) >> 8;\n               X->RGB.g = (Da * Y->RGB.g) >> 8;\n               X->RGB.b = (Da * Y->RGB.b) >> 8;\n               X->RGB.a = (Da * Y->RGB.a) >> 8;\n          }\n          else\n               *X = *Y;\n\n          ++D;\n          ++X; ++Y;\n     }\n}\n\nstatic void\nXacc_blend_destcolor( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *D = gfxs->Dacc;\n     GenefxAccumulator *X = gfxs->Xacc;\n     GenefxAccumulator *Y = gfxs->Yacc;\n\n     while (--w) {\n          if (!(Y->RGB.a & 0xf000)) {\n               X->RGB.r = ((D->RGB.r + 1) * Y->RGB.r) >> 8;\n               X->RGB.g = ((D->RGB.g + 1) * Y->RGB.g) >> 8;\n               X->RGB.b = ((D->RGB.b + 1) * Y->RGB.b) >> 8;\n               X->RGB.a = ((D->RGB.a + 1) * Y->RGB.a) >> 8;\n          }\n          else\n               *X = *Y;\n\n          ++D;\n          ++X; ++Y;\n     }\n}\n\nstatic void\nXacc_blend_invdestcolor( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *D = gfxs->Dacc;\n     GenefxAccumulator *X = gfxs->Xacc;\n     GenefxAccumulator *Y = gfxs->Yacc;\n\n     while (--w) {\n          if (!(Y->RGB.a & 0xf000)) {\n               X->RGB.r = ((0x100 - D->RGB.r) * Y->RGB.r) >> 8;\n               X->RGB.g = ((0x100 - D->RGB.g) * Y->RGB.g) >> 8;\n               X->RGB.b = ((0x100 - D->RGB.b) * Y->RGB.b) >> 8;\n               X->RGB.a = ((0x100 - D->RGB.a) * Y->RGB.a) >> 8;\n          }\n          else\n               *X = *Y;\n\n          ++D;\n          ++X; ++Y;\n     }\n}\n\nstatic void\nXacc_blend_srcalphasat( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *D = gfxs->Dacc;\n     GenefxAccumulator *X = gfxs->Xacc;\n     GenefxAccumulator *Y = gfxs->Yacc;\n\n     if (gfxs->Sacc) {\n          GenefxAccumulator *S = gfxs->Sacc;\n\n          while (--w) {\n               if (!(Y->RGB.a & 0xf000)) {\n                    u16 Sa = MIN( S->RGB.a + 1, 0x100 - D->RGB.a );\n\n                    X->RGB.a =       Y->RGB.a;\n                    X->RGB.r = (Sa * Y->RGB.r) >> 8;\n                    X->RGB.g = (Sa * Y->RGB.g) >> 8;\n                    X->RGB.b = (Sa * Y->RGB.b) >> 8;\n               }\n               else\n                    *X = *Y;\n\n               ++S;\n               ++D;\n               ++X; ++Y;\n          }\n     }\n     else {\n          while (--w) {\n               if (!(Y->RGB.a & 0xf000)) {\n                    u16 Sa = MIN( gfxs->color.a + 1, 0x100 - D->RGB.a );\n\n                    X->RGB.a =       Y->RGB.a;\n                    X->RGB.r = (Sa * Y->RGB.r) >> 8;\n                    X->RGB.g = (Sa * Y->RGB.g) >> 8;\n                    X->RGB.b = (Sa * Y->RGB.b) >> 8;\n               }\n               else\n                    *X = *Y;\n\n               ++D;\n               ++X; ++Y;\n          }\n     }\n}\n\nstatic GenefxFunc Xacc_blend[] = {\n     [DSBF_ZERO-1]         = Xacc_blend_zero,\n     [DSBF_ONE-1]          = Xacc_blend_one,\n     [DSBF_SRCCOLOR-1]     = Xacc_blend_srccolor,\n     [DSBF_INVSRCCOLOR-1]  = Xacc_blend_invsrccolor,\n     [DSBF_SRCALPHA-1]     = Xacc_blend_srcalpha,\n     [DSBF_INVSRCALPHA-1]  = Xacc_blend_invsrcalpha,\n     [DSBF_DESTALPHA-1]    = Xacc_blend_dstalpha,\n     [DSBF_INVDESTALPHA-1] = Xacc_blend_invdstalpha,\n     [DSBF_DESTCOLOR-1]    = Xacc_blend_destcolor,\n     [DSBF_INVDESTCOLOR-1] = Xacc_blend_invdestcolor,\n     [DSBF_SRCALPHASAT-1]  = Xacc_blend_srcalphasat,\n};\n\n/**********************************************************************************************************************\n ********************************* Dacc_modulation ********************************************************************\n **********************************************************************************************************************/\n\nstatic void\nDacc_set_alpha( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *D = gfxs->Dacc;\n     int                a = gfxs->color.a;\n\n     while (--w) {\n          if (!(D->RGB.a & 0xf000)) {\n               D->RGB.a = a;\n          }\n\n          ++D;\n     }\n}\n\nstatic void\nDacc_modulate_alpha( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *D = gfxs->Dacc;\n     int                a = gfxs->Cacc.RGB.a;\n\n     while (--w) {\n          if (!(D->RGB.a & 0xf000)) {\n               D->RGB.a = (a * D->RGB.a) >> 8;\n          }\n\n          ++D;\n     }\n}\n\nstatic void\nDacc_modulate_rgb( GenefxState *gfxs )\n{\n     int                w    = gfxs->length + 1;\n     GenefxAccumulator *D    = gfxs->Dacc;\n     GenefxAccumulator  Cacc = gfxs->Cacc;\n\n     while (--w) {\n          if (!(D->RGB.a & 0xf000)) {\n               D->RGB.r = (Cacc.RGB.r * D->RGB.r) >> 8;\n               D->RGB.g = (Cacc.RGB.g * D->RGB.g) >> 8;\n               D->RGB.b = (Cacc.RGB.b * D->RGB.b) >> 8;\n          }\n\n          ++D;\n     }\n}\n\nstatic void\nDacc_modulate_rgb_set_alpha( GenefxState *gfxs )\n{\n     int                w    = gfxs->length + 1;\n     GenefxAccumulator *D    = gfxs->Dacc;\n     GenefxAccumulator  Cacc = gfxs->Cacc;\n     int                a    = gfxs->color.a;\n\n     while (--w) {\n          if (!(D->RGB.a & 0xf000)) {\n               D->RGB.a = a;\n               D->RGB.r = (Cacc.RGB.r * D->RGB.r) >> 8;\n               D->RGB.g = (Cacc.RGB.g * D->RGB.g) >> 8;\n               D->RGB.b = (Cacc.RGB.b * D->RGB.b) >> 8;\n          }\n\n          ++D;\n     }\n}\n\nstatic void\nDacc_modulate_argb( GenefxState *gfxs )\n{\n     int                w    = gfxs->length + 1;\n     GenefxAccumulator *D    = gfxs->Dacc;\n     GenefxAccumulator  Cacc = gfxs->Cacc;\n\n     while (--w) {\n          if (!(D->RGB.a & 0xf000)) {\n               D->RGB.a = (Cacc.RGB.a * D->RGB.a) >> 8;\n               D->RGB.r = (Cacc.RGB.r * D->RGB.r) >> 8;\n               D->RGB.g = (Cacc.RGB.g * D->RGB.g) >> 8;\n               D->RGB.b = (Cacc.RGB.b * D->RGB.b) >> 8;\n          }\n\n          ++D;\n     }\n}\n\nstatic GenefxFunc Dacc_modulation[] = {\n     [DSBLIT_NOFX]                                                           = NULL,\n     [DSBLIT_BLEND_ALPHACHANNEL]                                             = NULL,\n     [DSBLIT_BLEND_COLORALPHA]                                               = Dacc_set_alpha,\n     [DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA]                   = Dacc_modulate_alpha,\n     [DSBLIT_COLORIZE]                                                       = Dacc_modulate_rgb,\n     [DSBLIT_COLORIZE | DSBLIT_BLEND_ALPHACHANNEL]                           = Dacc_modulate_rgb,\n     [DSBLIT_COLORIZE | DSBLIT_BLEND_COLORALPHA]                             = Dacc_modulate_rgb_set_alpha,\n     [DSBLIT_COLORIZE | DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA] = Dacc_modulate_argb\n};\n\n/**********************************************************************************************************************\n ********************************* Dacc_modulate_mask_alpha_from_PFI **************************************************\n **********************************************************************************************************************/\n\nstatic void\nDacc_modulate_mask_alpha_ARGB( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *D = gfxs->Dacc;\n     u32               *m = gfxs->Mop[0];\n\n     while (--w) {\n          if (!(D->RGB.a & 0xf000)) {\n               D->RGB.a = (((*m >> 24) + 1) * D->RGB.a) >> 8;\n          }\n\n          ++D;\n          ++m;\n     }\n}\n\nstatic void\nDacc_modulate_mask_alpha_A8( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *D = gfxs->Dacc;\n     u8                *m = gfxs->Mop[0];\n\n     while (--w) {\n          if (!(D->RGB.a & 0xf000)) {\n               D->RGB.a = ((*m + 1) * D->RGB.a) >> 8;\n          }\n\n          ++D;\n          ++m;\n     }\n}\n\nstatic GenefxFunc Dacc_modulate_mask_alpha_from_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Dacc_modulate_mask_alpha_ARGB,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = Dacc_modulate_mask_alpha_A8,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = NULL,\n};\n\n/**********************************************************************************************************************\n ********************************* Dacc_modulate_mask_rgb_from_PFI ****************************************************\n **********************************************************************************************************************/\n\nstatic void\nDacc_modulate_mask_rgb_ARGB( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *D = gfxs->Dacc;\n     u32               *m = gfxs->Mop[0];\n\n     while (--w) {\n          if (!(D->RGB.a & 0xf000)) {\n               D->RGB.r = ((((*m >> 16) & 0xff) + 1) * D->RGB.r) >> 8;\n               D->RGB.g = ((((*m >>  8) & 0xff) + 1) * D->RGB.g) >> 8;\n               D->RGB.b = ((( *m        & 0xff) + 1) * D->RGB.b) >> 8;\n          }\n\n          ++D;\n          ++m;\n     }\n}\n\nstatic GenefxFunc Dacc_modulate_mask_rgb_from_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Dacc_modulate_mask_rgb_ARGB,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = NULL,\n};\n\n/**********************************************************************************************************************\n ********************************* Dacc_modulate_mask_argb_from_PFI ***************************************************\n **********************************************************************************************************************/\n\nstatic void\nDacc_modulate_mask_argb_ARGB( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *D = gfxs->Dacc;\n     u8                *m = gfxs->Mop[0];\n\n     while (--w) {\n          if (!(D->RGB.a & 0xf000)) {\n               D->RGB.a = (( (*m >> 24)         + 1) * D->RGB.a) >> 8;\n               D->RGB.r = ((((*m >> 16) & 0xff) + 1) * D->RGB.r) >> 8;\n               D->RGB.g = ((((*m >>  8) & 0xff) + 1) * D->RGB.g) >> 8;\n               D->RGB.b = ((((*m      ) & 0xff) + 1) * D->RGB.b) >> 8;\n          }\n\n          ++D;\n          ++m;\n     }\n}\n\nstatic GenefxFunc Dacc_modulate_mask_argb_from_PFI[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = Dacc_modulate_mask_argb_ARGB,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = NULL,\n};\n\n/**********************************************************************************************************************\n ********************************* Misc accumulator operations ********************************************************\n **********************************************************************************************************************/\n\nstatic void\nDacc_premultiply_C( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *D = gfxs->Dacc;\n\n     while (--w) {\n          if (!(D->RGB.a & 0xf000)) {\n               u16 Da = D->RGB.a + 1;\n\n               D->RGB.r = (Da * D->RGB.r) >> 8;\n               D->RGB.g = (Da * D->RGB.g) >> 8;\n               D->RGB.b = (Da * D->RGB.b) >> 8;\n          }\n\n          ++D;\n     }\n}\n\nstatic GenefxFunc Dacc_premultiply = Dacc_premultiply_C;\n\n/**********************************************************************************************************************/\n\nstatic void\nDacc_premultiply_color_alpha_C( GenefxState *gfxs )\n{\n     int                w    = gfxs->length + 1;\n     GenefxAccumulator *D    = gfxs->Dacc;\n     GenefxAccumulator  Cacc = gfxs->Cacc;\n\n     while (--w) {\n          if (!(D->RGB.a & 0xf000)) {\n               D->RGB.r = (Cacc.RGB.a * D->RGB.r) >> 8;\n               D->RGB.g = (Cacc.RGB.a * D->RGB.g) >> 8;\n               D->RGB.b = (Cacc.RGB.a * D->RGB.b) >> 8;\n          }\n\n          ++D;\n     }\n}\n\nstatic GenefxFunc Dacc_premultiply_color_alpha = Dacc_premultiply_color_alpha_C;\n\n/**********************************************************************************************************************/\n\nstatic void\nDacc_demultiply_C( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *D = gfxs->Dacc;\n\n     while (--w) {\n          if (!(D->RGB.a & 0xf000)) {\n               u16 Da = D->RGB.a + 1;\n\n               D->RGB.r = (D->RGB.r << 8) / Da;\n               D->RGB.g = (D->RGB.g << 8) / Da;\n               D->RGB.b = (D->RGB.b << 8) / Da;\n          }\n\n          ++D;\n     }\n}\n\nstatic GenefxFunc Dacc_demultiply = Dacc_demultiply_C;\n\n/**********************************************************************************************************************/\n\nstatic void\nDacc_xor_C( GenefxState *gfxs )\n{\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *D     = gfxs->Dacc;\n     DFBColor           color = gfxs->color;\n\n     while (--w) {\n          if (!(D->RGB.a & 0xf000)) {\n               D->RGB.a ^= color.a;\n               D->RGB.r ^= color.r;\n               D->RGB.g ^= color.g;\n               D->RGB.b ^= color.b;\n          }\n\n          ++D;\n     }\n}\n\nstatic GenefxFunc Dacc_xor = Dacc_xor_C;\n\n/**********************************************************************************************************************/\n\nstatic void\nDacc_clamp_C( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *D = gfxs->Dacc;\n\n     while (--w) {\n          if (!(D->RGB.a & 0xf000)) {\n               if (D->RGB.a > 0xff)\n                    D->RGB.a = 0xff;\n               if (D->RGB.r > 0xff)\n                    D->RGB.r = 0xff;\n               if (D->RGB.g > 0xff)\n                    D->RGB.g = 0xff;\n               if (D->RGB.b > 0xff)\n                    D->RGB.b = 0xff;\n          }\n\n          ++D;\n     }\n}\n\nstatic GenefxFunc Dacc_clamp = Dacc_clamp_C;\n\n/**********************************************************************************************************************/\n\nstatic void\nSacc_xor_Dacc_C( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *S = gfxs->Sacc;\n     GenefxAccumulator *D = gfxs->Dacc;\n\n     while (--w) {\n          if (!(D->RGB.a & 0xf000)) {\n               D->RGB.a ^= S->RGB.a;\n               D->RGB.r ^= S->RGB.r;\n               D->RGB.g ^= S->RGB.g;\n               D->RGB.b ^= S->RGB.b;\n          }\n\n          ++S;\n          ++D;\n     }\n}\n\nstatic GenefxFunc Sacc_xor_Dacc = Sacc_xor_Dacc_C;\n\n/**********************************************************************************************************************/\n\nstatic void\nCacc_to_Dacc_C( GenefxState *gfxs )\n{\n     int                w    = gfxs->length + 1;\n     GenefxAccumulator *D    = gfxs->Dacc;\n     GenefxAccumulator  Cacc = gfxs->Cacc;\n\n     while (--w)\n          *D++ = Cacc;\n}\n\nstatic GenefxFunc Cacc_to_Dacc = Cacc_to_Dacc_C;\n\n/**********************************************************************************************************************/\n\nstatic void\nSCacc_add_to_Dacc_C( GenefxState *gfxs )\n{\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *D     = gfxs->Dacc;\n     GenefxAccumulator  SCacc = gfxs->SCacc;\n\n     while (--w) {\n          if (!(D->RGB.a & 0xf000)) {\n               D->RGB.a += SCacc.RGB.a;\n               D->RGB.r += SCacc.RGB.r;\n               D->RGB.g += SCacc.RGB.g;\n               D->RGB.b += SCacc.RGB.b;\n          }\n\n          ++D;\n     }\n}\n\nstatic GenefxFunc SCacc_add_to_Dacc = SCacc_add_to_Dacc_C;\n\n/**********************************************************************************************************************/\n\nstatic void\nSacc_add_to_Dacc_C( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *S = gfxs->Sacc;\n     GenefxAccumulator *D = gfxs->Dacc;\n\n     while (--w) {\n          if (!(D->RGB.a & 0xf000)) {\n               D->RGB.a += S->RGB.a;\n               D->RGB.r += S->RGB.r;\n               D->RGB.g += S->RGB.g;\n               D->RGB.b += S->RGB.b;\n          }\n\n          ++S;\n          ++D;\n     }\n}\n\nstatic GenefxFunc Sacc_add_to_Dacc = Sacc_add_to_Dacc_C;\n\n/**********************************************************************************************************************/\n\n/* change the last value to adjust the size of the device (1-4) */\n#define SET_PIXEL_DUFFS_DEVICE(D,S,w) \\\n     SET_PIXEL_DUFFS_DEVICE_N( D, S, w, 3 )\n\nstatic void\nDacc_RGB_to_YCbCr_BT601_C( GenefxState *gfxs )\n{\n     int                w = gfxs->length;\n     GenefxAccumulator *S = gfxs->Dacc;\n     GenefxAccumulator *D = gfxs->Dacc;\n\n#define SET_PIXEL(d,s)                                                                \\\n     if (!(s.RGB.a & 0xf000)) {                                                       \\\n          RGB_TO_YCBCR_BT601( s.RGB.r, s.RGB.g, s.RGB.b, d.YUV.y, d.YUV.u, d.YUV.v ); \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\nstatic void\nDacc_RGB_to_YCbCr_BT709_C( GenefxState *gfxs )\n{\n     int                w = gfxs->length;\n     GenefxAccumulator *S = gfxs->Dacc;\n     GenefxAccumulator *D = gfxs->Dacc;\n\n#define SET_PIXEL(d,s)                                                                \\\n     if (!(s.RGB.a & 0xf000)) {                                                       \\\n          RGB_TO_YCBCR_BT709( s.RGB.r, s.RGB.g, s.RGB.b, d.YUV.y, d.YUV.u, d.YUV.v ); \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\nstatic void\nDacc_RGB_to_YCbCr_BT2020_C( GenefxState *gfxs )\n{\n     int                w = gfxs->length;\n     GenefxAccumulator *S = gfxs->Dacc;\n     GenefxAccumulator *D = gfxs->Dacc;\n\n#define SET_PIXEL(d,s)                                                                 \\\n     if (!(s.RGB.a & 0xf000)) {                                                        \\\n          RGB_TO_YCBCR_BT2020( s.RGB.r, s.RGB.g, s.RGB.b, d.YUV.y, d.YUV.u, d.YUV.v ); \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\n#undef SET_PIXEL_DUFFS_DEVICE\n\nstatic GenefxFunc Dacc_RGB_to_YCbCr_BT601  = Dacc_RGB_to_YCbCr_BT601_C;\nstatic GenefxFunc Dacc_RGB_to_YCbCr_BT709  = Dacc_RGB_to_YCbCr_BT709_C;\nstatic GenefxFunc Dacc_RGB_to_YCbCr_BT2020 = Dacc_RGB_to_YCbCr_BT2020_C;\n\n/**********************************************************************************************************************/\n\n/* change the last value to adjust the size of the device (1-4) */\n#define SET_PIXEL_DUFFS_DEVICE(D,S,w) \\\n     SET_PIXEL_DUFFS_DEVICE_N( D, S, w, 2 )\n\nstatic void\nDacc_YCbCr_to_RGB_BT601_C( GenefxState *gfxs )\n{\n     int                w = gfxs->length;\n     GenefxAccumulator *S = gfxs->Dacc;\n     GenefxAccumulator *D = gfxs->Dacc;\n\n#define SET_PIXEL(d,s)                                                                \\\n     if (!(s.YUV.a & 0xf000)) {                                                       \\\n          YCBCR_TO_RGB_BT601( s.YUV.y, s.YUV.u, s.YUV.v, d.RGB.r, d.RGB.g, d.RGB.b ); \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\nstatic void\nDacc_YCbCr_to_RGB_BT709_C( GenefxState *gfxs )\n{\n     int                w = gfxs->length;\n     GenefxAccumulator *S = gfxs->Dacc;\n     GenefxAccumulator *D = gfxs->Dacc;\n\n#define SET_PIXEL(d,s)                                                                \\\n     if (!(s.YUV.a & 0xf000)) {                                                       \\\n          YCBCR_TO_RGB_BT709( s.YUV.y, s.YUV.u, s.YUV.v, d.RGB.r, d.RGB.g, d.RGB.b ); \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\nstatic void\nDacc_YCbCr_to_RGB_BT2020_C( GenefxState *gfxs )\n{\n     int                w = gfxs->length;\n     GenefxAccumulator *S = gfxs->Dacc;\n     GenefxAccumulator *D = gfxs->Dacc;\n\n#define SET_PIXEL(d,s)                                                                 \\\n     if (!(s.YUV.a & 0xf000)) {                                                        \\\n          YCBCR_TO_RGB_BT2020( s.YUV.y, s.YUV.u, s.YUV.v, d.RGB.r, d.RGB.g, d.RGB.b ); \\\n     }\n\n     SET_PIXEL_DUFFS_DEVICE( D, S, w );\n\n#undef SET_PIXEL\n}\n\n#undef SET_PIXEL_DUFFS_DEVICE\n\nstatic GenefxFunc Dacc_YCbCr_to_RGB_BT601  = Dacc_YCbCr_to_RGB_BT601_C;\nstatic GenefxFunc Dacc_YCbCr_to_RGB_BT709  = Dacc_YCbCr_to_RGB_BT709_C;\nstatic GenefxFunc Dacc_YCbCr_to_RGB_BT2020 = Dacc_YCbCr_to_RGB_BT2020_C;\n\n/**********************************************************************************************************************/\n\nstatic void\nDacc_Alpha_to_YCbCr_C( GenefxState *gfxs )\n{\n     int                w = gfxs->length + 1;\n     GenefxAccumulator *D = gfxs->Dacc;\n\n     while (--w) {\n          if (!(D->RGB.a & 0xf000)) {\n               D->YUV.y = 235;\n               D->YUV.u = 128;\n               D->YUV.v = 128;\n          }\n\n          ++D;\n     }\n}\n\nstatic GenefxFunc Dacc_Alpha_to_YCbCr = Dacc_Alpha_to_YCbCr_C;\n\n/**********************************************************************************************************************/\n\nstatic void Sop_is_Aop  ( GenefxState *gfxs ) { gfxs->Sop = gfxs->Aop; gfxs->Ostep = gfxs->Astep; }\nstatic void Sop_is_Bop  ( GenefxState *gfxs ) { gfxs->Sop = gfxs->Bop; gfxs->Ostep = gfxs->Bstep; }\n\nstatic void Slut_is_Alut( GenefxState *gfxs ) { gfxs->Slut = gfxs->Alut; }\nstatic void Slut_is_Blut( GenefxState *gfxs ) { gfxs->Slut = gfxs->Blut; }\n\nstatic void Sacc_is_NULL( GenefxState *gfxs ) { gfxs->Sacc = NULL; }\nstatic void Sacc_is_Aacc( GenefxState *gfxs ) { gfxs->Sacc = gfxs->Aacc; }\nstatic void Sacc_is_Bacc( GenefxState *gfxs ) { gfxs->Sacc = gfxs->Bacc; }\nstatic void Sacc_is_Tacc( GenefxState *gfxs ) { gfxs->Sacc = gfxs->Tacc; }\n\nstatic void Dacc_is_Aacc( GenefxState *gfxs ) { gfxs->Dacc = gfxs->Aacc; }\nstatic void Dacc_is_Bacc( GenefxState *gfxs ) { gfxs->Dacc = gfxs->Bacc; }\nstatic void Dacc_is_Tacc( GenefxState *gfxs ) { gfxs->Dacc = gfxs->Tacc; }\n\nstatic void Xacc_is_Bacc( GenefxState *gfxs ) { gfxs->Xacc = gfxs->Bacc; }\nstatic void Xacc_is_Tacc( GenefxState *gfxs ) { gfxs->Xacc = gfxs->Tacc; }\n\nstatic void Yacc_is_Aacc( GenefxState *gfxs ) { gfxs->Yacc = gfxs->Aacc; }\nstatic void Yacc_is_Bacc( GenefxState *gfxs ) { gfxs->Yacc = gfxs->Bacc; }\n\nstatic void Len_is_Slen ( GenefxState *gfxs ) { gfxs->length = gfxs->Slen; }\nstatic void Len_is_Dlen ( GenefxState *gfxs ) { gfxs->length = gfxs->Dlen; }\n\n#define MODULATION_FLAGS (DSBLIT_BLEND_ALPHACHANNEL | \\\n                          DSBLIT_BLEND_COLORALPHA   | \\\n                          DSBLIT_COLORIZE           | \\\n                          DSBLIT_DST_PREMULTIPLY    | \\\n                          DSBLIT_SRC_PREMULTIPLY    | \\\n                          DSBLIT_SRC_PREMULTCOLOR   | \\\n                          DSBLIT_DEMULTIPLY         | \\\n                          DSBLIT_XOR)\n\n/**********************************************************************************************************************/\n\n#ifndef WORDS_BIGENDIAN\n\n#define BGR_TO_RGB16(pixel) ((((pixel) <<  8) & 0xf800) | (((pixel) >>  5) & 0x07e0) | (((pixel) >> 19) & 0x001f))\n\n/*\n * Fast RGB24 to RGB16 conversion.\n */\nstatic void\nBop_rgb24_to_Aop_rgb16_LE( GenefxState *gfxs )\n{\n     int  w = gfxs->length;\n     u8  *S = gfxs->Bop[0];\n     u16 *D = gfxs->Aop[0];\n\n     while ((unsigned long) S & 3) {\n          *D++ = PIXEL_RGB16( S[0], S[1], S[2] );\n\n          S += 3;\n          --w;\n     }\n\n     if ((unsigned long) D & 2) {\n          *D++ = PIXEL_RGB16( S[0], S[1], S[2] );\n\n          S += 3;\n          --w;\n\n          while (w > 1) {\n               *(u32*) D = PIXEL_RGB16( S[0], S[1], S[2] ) | (PIXEL_RGB16( S[3], S[4], S[5] ) << 16);\n\n               S += 6;\n               D += 2;\n               w -= 2;\n          }\n     }\n     else {\n          u32 *S32 = (u32*) S;\n          u32 *D32 = (u32*) D;\n\n          while (w > 3) {\n               D32[0] = BGR_TO_RGB16( S32[0] ) | (BGR_TO_RGB16( (S32[0] >> 24) | (S32[1] << 8) ) << 16);\n               D32[1] = BGR_TO_RGB16( (S32[1] >> 16) | (S32[2] << 16) ) | (BGR_TO_RGB16( S32[2] >> 8 ) << 16);\n\n               S32 += 3;\n               D32 += 2;\n               w   -= 4;\n          }\n\n          S = (u8*)  S32;\n          D = (u16*) D32;\n     }\n\n     while (w > 0) {\n          *D++ = PIXEL_RGB16( S[0], S[1], S[2] );\n\n          S += 3;\n          --w;\n     }\n}\n\n/*\n * Fast RGB32 to RGB16 conversion.\n */\nstatic void\nBop_rgb32_to_Aop_rgb16_LE( GenefxState *gfxs )\n{\n     int  w = gfxs->length;\n     u32 *S = gfxs->Bop[0];\n     u32 *D = gfxs->Aop[0];\n\n     if ((unsigned long) D & 2) {\n          u16 *d = (u16*) D;\n\n          d[0] = ARGB_TO_RGB16( S[0] );\n          D = (u32*) (d + 1);\n\n          ++S;\n          --w;\n     }\n\n     while (w > 1) {\n          D[0] = ARGB_TO_RGB16( S[0] ) | (ARGB_TO_RGB16( S[1] ) << 16);\n\n          S += 2;\n          ++D;\n          w -= 2;\n     }\n\n     if (w > 0) {\n          u16 *d = (u16*) D;\n\n          d[0] = ARGB_TO_RGB16( S[0] );\n     }\n}\n\n#endif /* WORDS_BIGENDIAN */\n\n/**********************************************************************************************************************/\n\n#ifdef USE_MMX\n\n#include \"generic_mmx.h\"\n\n/*\n * patches function pointers to MMX functions\n */\nstatic void\ngInit_MMX( void )\n{\n/********************************* Xacc_blend *************************************/\n     Xacc_blend[DSBF_SRCALPHA-1]    = Xacc_blend_srcalpha_MMX;\n     Xacc_blend[DSBF_INVSRCALPHA-1] = Xacc_blend_invsrcalpha_MMX;\n/********************************* Dacc_modulation ********************************/\n     Dacc_modulation[DSBLIT_COLORIZE | DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA] = Dacc_modulate_argb_MMX;\n/********************************* Misc accumulator operations ********************/\n     SCacc_add_to_Dacc = SCacc_add_to_Dacc_MMX;\n     Sacc_add_to_Dacc  = Sacc_add_to_Dacc_MMX;\n}\n\n#endif\n\n#ifdef USE_NEON\n\n#include \"generic_neon.h\"\n\n/*\n * patches function pointers to NEON functions\n */\nstatic void\ngInit_NEON()\n{\n/********************************* Sop_PFI_to_Dacc ********************************/\n     Sop_PFI_to_Dacc[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)] = Sop_rgb16_to_Dacc_NEON;\n     Sop_PFI_to_Dacc[DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]  = Sop_argb_to_Dacc_NEON;\n/********************************* Sacc_to_Aop_PFI ********************************/\n     Sacc_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)] = Sacc_to_Aop_rgb16_NEON;\n/********************************* Bop_argb_blend_alphachannel_src_invsrc_Aop_PFI */\n     Bop_argb_blend_alphachannel_src_invsrc_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)] =\n          Bop_argb_blend_alphachannel_src_invsrc_Aop_rgb16_NEON;\n/********************************* Xacc_blend *************************************/\n     Xacc_blend[DSBF_SRCALPHA-1]    = Xacc_blend_srcalpha_NEON;\n     Xacc_blend[DSBF_INVSRCALPHA-1] = Xacc_blend_invsrcalpha_NEON;\n/********************************* Dacc_modulation ********************************/\n     Dacc_modulation[DSBLIT_COLORIZE]                                                       = Dacc_modulate_rgb_NEON;\n     Dacc_modulation[DSBLIT_COLORIZE | DSBLIT_BLEND_ALPHACHANNEL]                           = Dacc_modulate_rgb_NEON;\n     Dacc_modulation[DSBLIT_COLORIZE | DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA] = Dacc_modulate_argb_NEON;\n/********************************* Misc accumulator operations ********************/\n     SCacc_add_to_Dacc = SCacc_add_to_Dacc_NEON;\n     Sacc_add_to_Dacc  = Sacc_add_to_Dacc_NEON;\n}\n\n#endif\n\n#if SIZEOF_LONG == 8\n\n#include \"generic_64.h\"\n\n/*\n * patches function pointers to 64 bits functions\n */\nstatic void\ngInit_64bit( void )\n{\n/********************************* Cop_to_Aop_PFI *********************************/\n     Cop_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_RGB32)] = Cop_to_Aop_32_64;\n     Cop_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]  = Cop_to_Aop_32_64;\n     Cop_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)] = Cop_to_Aop_32_64;\n/********************************* Bop_PFI_toK_Aop_PFI ****************************/\n     Bop_PFI_toK_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_RGB32)] = Bop_rgb32_toK_Aop_64;\n     Bop_PFI_toK_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]  = Bop_rgb32_toK_Aop_64;\n     Bop_PFI_toK_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)] = Bop_rgb32_toK_Aop_64;\n/********************************* Bop_PFI_Kto_Aop_PFI ****************************/\n     Bop_PFI_Kto_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_RGB32)] = Bop_rgb32_Kto_Aop_64;\n     Bop_PFI_Kto_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]  = Bop_rgb32_Kto_Aop_64;\n     Bop_PFI_Kto_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)] = Bop_rgb32_Kto_Aop_64;\n/********************************* Bop_PFI_Sto_Aop_PFI ****************************/\n     Bop_PFI_Sto_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_RGB32)] = Bop_32_Sto_Aop_64;\n     Bop_PFI_Sto_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]  = Bop_32_Sto_Aop_64;\n     Bop_PFI_Sto_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)] = Bop_32_Sto_Aop_64;\n/********************************* Misc accumulator operations ********************/\n     Dacc_xor = Dacc_xor_64;\n}\n\n#endif\n\n#ifdef WORDS_BIGENDIAN\n\n/*\n * patches function pointers to big endian functions\n */\nstatic void\ngInit_BigEndian()\n{\n/********************************* Cop_to_Aop_PFI *********************************/\n     Cop_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = Cop_to_Aop_nv21;\n     Cop_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = Cop_to_Aop_nv61;\n     Cop_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = Cop_to_Aop_nv42;\n     Cop_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_NV21)] = Cop_to_Aop_nv12;\n     Cop_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_NV61)] = Cop_to_Aop_nv16;\n     Cop_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_NV42)] = Cop_to_Aop_nv24;\n/********************************* Sop_PFI_to_Dacc ********************************/\n     Sop_PFI_to_Dacc[DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = Sop_nv21_to_Dacc;\n     Sop_PFI_to_Dacc[DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = Sop_nv21_to_Dacc;\n     Sop_PFI_to_Dacc[DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = Sop_nv42_to_Dacc;\n     Sop_PFI_to_Dacc[DFB_PIXELFORMAT_INDEX(DSPF_NV21)] = Sop_nv12_to_Dacc;\n     Sop_PFI_to_Dacc[DFB_PIXELFORMAT_INDEX(DSPF_NV61)] = Sop_nv12_to_Dacc;\n     Sop_PFI_to_Dacc[DFB_PIXELFORMAT_INDEX(DSPF_NV42)] = Sop_nv24_to_Dacc;\n/********************************* Sop_PFI_Sto_Dacc *******************************/\n     Sop_PFI_Sto_Dacc[DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = Sop_nv21_Sto_Dacc;\n     Sop_PFI_Sto_Dacc[DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = Sop_nv21_Sto_Dacc;\n     Sop_PFI_Sto_Dacc[DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = Sop_nv42_Sto_Dacc;\n     Sop_PFI_Sto_Dacc[DFB_PIXELFORMAT_INDEX(DSPF_NV21)] = Sop_nv12_Sto_Dacc;\n     Sop_PFI_Sto_Dacc[DFB_PIXELFORMAT_INDEX(DSPF_NV61)] = Sop_nv12_Sto_Dacc;\n     Sop_PFI_Sto_Dacc[DFB_PIXELFORMAT_INDEX(DSPF_NV42)] = Sop_nv24_Sto_Dacc;\n/********************************* Sacc_to_Aop_PFI ********************************/\n     Sacc_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = Sacc_to_Aop_nv21;\n     Sacc_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = Sacc_to_Aop_nv61;\n     Sacc_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = Sacc_to_Aop_nv42;\n     Sacc_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_NV21)] = Sacc_to_Aop_nv12;\n     Sacc_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_NV61)] = Sacc_to_Aop_nv16;\n     Sacc_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_NV42)] = Sacc_to_Aop_nv24;\n/********************************* Sacc_Sto_Aop_PFI *******************************/\n     Sacc_Sto_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = Sacc_Sto_Aop_nv21;\n     Sacc_Sto_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = Sacc_Sto_Aop_nv61;\n     Sacc_Sto_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = Sacc_Sto_Aop_nv42;\n     Sacc_Sto_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_NV21)] = Sacc_Sto_Aop_nv12;\n     Sacc_Sto_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_NV61)] = Sacc_Sto_Aop_nv16;\n     Sacc_Sto_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_NV42)] = Sacc_Sto_Aop_nv24;\n}\n\n#endif\n\n/**********************************************************************************************************************/\n\nvoid\ngGetDriverInfo( GraphicsDriverInfo *driver_info )\n{\n     snprintf( driver_info->name, DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH, \"Software Driver\" );\n\n#if SIZEOF_LONG == 8\n     gInit_64bit();\n#endif\n\n#ifdef WORDS_BIGENDIAN\n     gInit_BigEndian();\n#endif\n\n#ifdef USE_MMX\n     if (!dfb_config->mmx) {\n          D_INFO( \"DirectFB/Genefx: MMX disabled by option 'no-mmx'\\n\" );\n     }\n     else {\n          gInit_MMX();\n\n          snprintf( driver_info->name, DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH, \"MMX Software Driver\" );\n\n          D_INFO( \"DirectFB/Genefx: MMX enabled\\n\" );\n     }\n#endif\n\n#ifdef USE_NEON\n     if (!dfb_config->neon) {\n          D_INFO( \"DirectFB/Genefx: NEON disabled by option 'no-neon'\\n\" );\n     }\n     else {\n          gInit_NEON();\n\n          snprintf( driver_info->name, DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH, \"NEON Software Driver\" );\n\n          D_INFO( \"DirectFB/Genefx: NEON enabled\\n\" );\n     }\n#endif\n\n     snprintf( driver_info->vendor, DFB_GRAPHICS_DRIVER_INFO_VENDOR_LENGTH, \"DirectFB\" );\n\n     driver_info->version.major = 0;\n     driver_info->version.minor = 7;\n}\n\nvoid\ngGetDeviceInfo( GraphicsDeviceInfo *device_info )\n{\n     snprintf( device_info->name, DFB_GRAPHICS_DEVICE_INFO_NAME_LENGTH, \"Software Rasterizer\" );\n\n     snprintf( device_info->vendor, DFB_GRAPHICS_DEVICE_INFO_VENDOR_LENGTH, \"Genefx\" );\n\n     device_info->caps.flags    = 0;\n     device_info->caps.accel    = DFXL_NONE;\n     device_info->caps.blitting = DSBLIT_NOFX;\n     device_info->caps.drawing  = DSDRAW_NOFX;\n     device_info->caps.clip     = 0;\n}\n\nstatic bool\ngAcquireCheck( CardState           *state,\n               DFBAccelerationMask  accel )\n{\n     GenefxState *gfxs;\n     CoreSurface *destination = state->destination;\n     CoreSurface *source      = state->source;\n     CoreSurface *source_mask = state->source_mask;\n\n     if (dfb_config->hardware_only) {\n          if (dfb_config->software_warn) {\n               if (DFB_BLITTING_FUNCTION( accel ))\n                    D_WARN( \"ignoring blit (%x) from %s to %s, flags 0x%08x, funcs %u %u\", accel,\n                            source ? dfb_pixelformat_name( source->config.format ) : \"NULL SOURCE\",\n                            destination ? dfb_pixelformat_name( destination->config.format ) : \"NULL DESTINATION\",\n                            state->blittingflags, state->src_blend, state->dst_blend );\n               else\n                    D_WARN( \"ignoring draw (%x) to %s, flags 0x%08x\", accel,\n                            destination ? dfb_pixelformat_name( destination->config.format ) : \"NULL DESTINATION\",\n                            state->drawingflags );\n          }\n\n          return false;\n     }\n\n     if (!state->gfxs) {\n          gfxs = D_CALLOC( 1, sizeof(GenefxState) );\n          if (!gfxs) {\n               D_ERROR( \"DirectFB/Genefx: Could not allocate Genefx state!\\n\" );\n               return false;\n          }\n\n          state->gfxs = gfxs;\n     }\n\n     gfxs = state->gfxs;\n\n     /* Destination may have been destroyed. */\n     if (!destination)\n          return false;\n\n     /* Destination buffer may have been destroyed (suspended), i.e. by vt-switching. */\n     if (destination->num_buffers == 0)\n          return false;\n\n     /* Source may have been destroyed. */\n     if (DFB_BLITTING_FUNCTION( accel )) {\n          if (!source)\n               return false;\n\n          if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) {\n               if (!source_mask)\n                    return false;\n          }\n     }\n\n     return true;\n}\n\nstatic DFBResult\ngAcquireLockBuffers( CardState           *state,\n                     DFBAccelerationMask  accel )\n{\n     DFBResult               ret;\n     CoreSurface            *destination = state->destination;\n     CoreSurface            *source      = state->source;\n     CoreSurface            *source_mask = state->source_mask;\n     CoreSurfaceAccessFlags  access      = CSAF_WRITE;\n\n     if (core_dfb->shutdown_running)\n          return DFB_DEAD;\n\n     /*\n      * Destination setup\n      */\n\n     if (DFB_BLITTING_FUNCTION( accel )) {\n          if (state->blittingflags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA   | DSBLIT_DST_COLORKEY))\n               access |= CSAF_READ;\n     }\n     else if (state->drawingflags & (DSDRAW_BLEND | DSDRAW_DST_COLORKEY))\n          access |= CSAF_READ;\n\n     /* Lock destination. */\n     ret = dfb_surface_lock_buffer2( destination, state->to, destination->flips, state->to_eye, CSAID_CPU, access,\n                                     &state->dst );\n     if (ret) {\n          D_DERROR( ret, \"DirectFB/Genefx: Could not lock destination!\\n\" );\n          return ret;\n     }\n\n     /*\n      * Source setup\n      */\n\n     if (DFB_BLITTING_FUNCTION( accel )) {\n          /* Lock source. */\n          ret = dfb_surface_lock_buffer2( source, state->from, source->flips, state->from_eye, CSAID_CPU, CSAF_READ,\n                                          &state->src );\n          if (ret) {\n               D_DERROR( ret, \"DirectFB/Genefx: Could not lock source!\\n\" );\n               dfb_surface_unlock_buffer( destination, &state->dst );\n               return ret;\n          }\n\n          state->flags |= CSF_SOURCE_LOCKED;\n\n          /*\n           * Mask setup\n           */\n\n          if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) {\n               /* Lock source. */\n               ret = dfb_surface_lock_buffer2( source_mask, state->from, source_mask->flips, state->from_eye, CSAID_CPU,\n                                               CSAF_READ, &state->src_mask );\n               if (ret) {\n                    D_DERROR( ret, \"DirectFB/Genefx: Could not lock source mask!\\n\" );\n                    dfb_surface_unlock_buffer( destination, &state->dst );\n\n                    if (state->flags & CSF_SOURCE_LOCKED) {\n                         dfb_surface_unlock_buffer( state->source, &state->src );\n\n                         state->flags &= ~CSF_SOURCE_LOCKED;\n                    }\n\n                    return ret;\n               }\n\n               state->flags |= CSF_SOURCE_MASK_LOCKED;\n          }\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ngAcquireUnlockBuffers( CardState *state )\n{\n     dfb_surface_unlock_buffer( state->destination, &state->dst );\n\n     if (state->flags & CSF_SOURCE_LOCKED) {\n          dfb_surface_unlock_buffer( state->source, &state->src );\n\n          state->flags &= ~CSF_SOURCE_LOCKED;\n     }\n\n     if (state->flags & CSF_SOURCE_MASK_LOCKED) {\n          dfb_surface_unlock_buffer( state->source_mask, &state->src_mask );\n\n          state->flags &= ~CSF_SOURCE_MASK_LOCKED;\n     }\n\n     return DFB_OK;\n}\n\nstatic bool\ngAcquireSetup( CardState           *state,\n               DFBAccelerationMask  accel )\n{\n     GenefxState             *gfxs;\n     GenefxFunc              *funcs;\n     int                      dst_pfi;\n     int                      src_pfi              = 0;\n     int                      mask_pfi             = 0;\n     CoreSurface             *destination          = state->destination;\n     CoreSurface             *source               = state->source;\n     DFBColor                 color                = state->color;\n     bool                     src_ycbcr            = false;\n     bool                     dst_ycbcr            = false;\n     DFBSurfaceBlittingFlags  simpld_blittingflags = state->blittingflags;\n     u16                      ca;\n\n     dfb_simplify_blittingflags( &simpld_blittingflags );\n\n     if (!state->gfxs) {\n          gfxs = D_CALLOC( 1, sizeof(GenefxState) );\n          if (!gfxs) {\n               D_ERROR( \"DirectFB/Genefx: Could not allocate Genefx state!\\n\" );\n               return false;\n          }\n\n          state->gfxs = gfxs;\n     }\n\n     gfxs  = state->gfxs;\n     funcs = gfxs->funcs;\n\n     /*\n      * Destination setup\n      */\n\n     gfxs->dst_caps         = destination->config.caps;\n     gfxs->dst_height       = destination->config.size.h;\n     gfxs->dst_format       = destination->config.format;\n     gfxs->dst_bpp          = DFB_BYTES_PER_PIXEL( gfxs->dst_format );\n     gfxs->dst_org[0]       = state->dst.addr;\n     gfxs->dst_pitch        = state->dst.pitch;\n     gfxs->dst_field_offset = gfxs->dst_height / 2 * gfxs->dst_pitch;\n\n     dst_pfi = DFB_PIXELFORMAT_INDEX( gfxs->dst_format );\n\n     switch (gfxs->dst_format) {\n          case DSPF_I420:\n               gfxs->dst_org[1] = gfxs->dst_org[0] + gfxs->dst_height * gfxs->dst_pitch;\n               gfxs->dst_org[2] = gfxs->dst_org[1] + gfxs->dst_height / 2 * gfxs->dst_pitch / 2;\n               break;\n          case DSPF_YV12:\n               gfxs->dst_org[2] = gfxs->dst_org[0] + gfxs->dst_height * gfxs->dst_pitch;\n               gfxs->dst_org[1] = gfxs->dst_org[2] + gfxs->dst_height / 2 * gfxs->dst_pitch / 2;\n               break;\n          case DSPF_Y42B:\n               gfxs->dst_org[1] = gfxs->dst_org[0] + gfxs->dst_height * gfxs->dst_pitch;\n               gfxs->dst_org[2] = gfxs->dst_org[1] + gfxs->dst_height * gfxs->dst_pitch / 2;\n               break;\n          case DSPF_YV16:\n               gfxs->dst_org[2] = gfxs->dst_org[0] + gfxs->dst_height * gfxs->dst_pitch;\n               gfxs->dst_org[1] = gfxs->dst_org[2] + gfxs->dst_height * gfxs->dst_pitch / 2;\n               break;\n          case DSPF_Y444:\n               gfxs->dst_org[1] = gfxs->dst_org[0] + gfxs->dst_height * gfxs->dst_pitch;\n               gfxs->dst_org[2] = gfxs->dst_org[1] + gfxs->dst_height * gfxs->dst_pitch;\n               break;\n          case DSPF_YV24:\n               gfxs->dst_org[2] = gfxs->dst_org[0] + gfxs->dst_height * gfxs->dst_pitch;\n               gfxs->dst_org[1] = gfxs->dst_org[2] + gfxs->dst_height * gfxs->dst_pitch;\n               break;\n          case DSPF_NV12:\n          case DSPF_NV21:\n          case DSPF_NV16:\n          case DSPF_NV61:\n          case DSPF_NV24:\n          case DSPF_NV42:\n               gfxs->dst_org[1] = gfxs->dst_org[0] + gfxs->dst_height * gfxs->dst_pitch;\n               break;\n          default:\n               break;\n     }\n\n     /*\n      * Source setup\n      */\n\n     if (DFB_BLITTING_FUNCTION( accel )) {\n          CoreSurface *source_mask = state->source_mask;\n\n          gfxs->src_caps         = source->config.caps;\n          gfxs->src_height       = source->config.size.h;\n          gfxs->src_format       = source->config.format;\n          gfxs->src_bpp          = DFB_BYTES_PER_PIXEL( gfxs->src_format );\n          gfxs->src_org[0]       = state->src.addr;\n          gfxs->src_pitch        = state->src.pitch;\n          gfxs->src_field_offset = gfxs->src_height / 2 * gfxs->src_pitch;\n\n          src_pfi = DFB_PIXELFORMAT_INDEX( gfxs->src_format );\n\n          switch (gfxs->src_format) {\n               case DSPF_I420:\n                    gfxs->src_org[1] = gfxs->src_org[0] + gfxs->src_height * gfxs->src_pitch;\n                    gfxs->src_org[2] = gfxs->src_org[1] + gfxs->src_height / 2 * gfxs->src_pitch / 2;\n                    break;\n               case DSPF_YV12:\n                    gfxs->src_org[2] = gfxs->src_org[0] + gfxs->src_height * gfxs->src_pitch;\n                    gfxs->src_org[1] = gfxs->src_org[2] + gfxs->src_height / 2 * gfxs->src_pitch / 2;\n                    break;\n               case DSPF_Y42B:\n                    gfxs->src_org[1] = gfxs->src_org[0] + gfxs->src_height * gfxs->src_pitch;\n                    gfxs->src_org[2] = gfxs->src_org[1] + gfxs->src_height * gfxs->src_pitch / 2;\n                    break;\n               case DSPF_YV16:\n                    gfxs->src_org[2] = gfxs->src_org[0] + gfxs->src_height * gfxs->src_pitch;\n                    gfxs->src_org[1] = gfxs->src_org[2] + gfxs->src_height * gfxs->src_pitch / 2;\n                    break;\n               case DSPF_Y444:\n                    gfxs->src_org[1] = gfxs->src_org[0] + gfxs->src_height * gfxs->src_pitch;\n                    gfxs->src_org[2] = gfxs->src_org[1] + gfxs->src_height * gfxs->src_pitch;\n                    break;\n               case DSPF_YV24:\n                    gfxs->src_org[2] = gfxs->src_org[0] + gfxs->src_height * gfxs->src_pitch;\n                    gfxs->src_org[1] = gfxs->src_org[2] + gfxs->src_height * gfxs->src_pitch;\n                    break;\n               case DSPF_NV12:\n               case DSPF_NV21:\n               case DSPF_NV16:\n               case DSPF_NV61:\n               case DSPF_NV24:\n               case DSPF_NV42:\n                    gfxs->src_org[1] = gfxs->src_org[0] + gfxs->src_height * gfxs->src_pitch;\n                    break;\n               default:\n                    break;\n          }\n\n          /*\n           * Mask setup\n           */\n\n          if (simpld_blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) {\n               gfxs->mask_caps         = source_mask->config.caps;\n               gfxs->mask_height       = source_mask->config.size.h;\n               gfxs->mask_format       = source_mask->config.format;\n               gfxs->mask_bpp          = DFB_BYTES_PER_PIXEL( gfxs->mask_format );\n               gfxs->mask_org[0]       = state->src_mask.addr;\n               gfxs->mask_pitch        = state->src_mask.pitch;\n               gfxs->mask_field_offset = gfxs->mask_height / 2 * gfxs->mask_pitch;\n\n               mask_pfi = DFB_PIXELFORMAT_INDEX( gfxs->mask_format );\n\n               switch (gfxs->mask_format) {\n                    case DSPF_I420:\n                         gfxs->mask_org[1] = gfxs->mask_org[0] + gfxs->mask_height * gfxs->mask_pitch;\n                         gfxs->mask_org[2] = gfxs->mask_org[1] + gfxs->mask_height / 2 * gfxs->mask_pitch / 2;\n                         break;\n                    case DSPF_YV12:\n                         gfxs->mask_org[2] = gfxs->mask_org[0] + gfxs->mask_height * gfxs->mask_pitch;\n                         gfxs->mask_org[1] = gfxs->mask_org[2] + gfxs->mask_height / 2 * gfxs->mask_pitch / 2;\n                         break;\n                    case DSPF_Y42B:\n                         gfxs->mask_org[1] = gfxs->mask_org[0] + gfxs->mask_height * gfxs->mask_pitch;\n                         gfxs->mask_org[2] = gfxs->mask_org[1] + gfxs->mask_height * gfxs->mask_pitch / 2;\n                         break;\n                    case DSPF_YV16:\n                         gfxs->mask_org[2] = gfxs->mask_org[0] + gfxs->mask_height * gfxs->mask_pitch;\n                         gfxs->mask_org[1] = gfxs->mask_org[2] + gfxs->mask_height * gfxs->mask_pitch / 2;\n                         break;\n                    case DSPF_Y444:\n                         gfxs->mask_org[1] = gfxs->mask_org[0] + gfxs->mask_height * gfxs->mask_pitch;\n                         gfxs->mask_org[2] = gfxs->mask_org[1] + gfxs->mask_height * gfxs->mask_pitch;\n                         break;\n                    case DSPF_YV24:\n                         gfxs->mask_org[2] = gfxs->mask_org[0] + gfxs->mask_height * gfxs->mask_pitch;\n                         gfxs->mask_org[1] = gfxs->mask_org[2] + gfxs->mask_height * gfxs->mask_pitch;\n                         break;\n                    case DSPF_NV12:\n                    case DSPF_NV21:\n                    case DSPF_NV16:\n                    case DSPF_NV61:\n                    case DSPF_NV24:\n                    case DSPF_NV42:\n                         gfxs->mask_org[1] = gfxs->mask_org[0] + gfxs->mask_height * gfxs->mask_pitch;\n                         break;\n                    default:\n                         break;\n               }\n          }\n     }\n\n     /* Premultiply source (color). */\n     if (DFB_DRAWING_FUNCTION(accel) && (state->drawingflags & DSDRAW_SRC_PREMULTIPLY)) {\n          ca = color.a + 1;\n          color.r = (color.r * ca) >> 8;\n          color.g = (color.g * ca) >> 8;\n          color.b = (color.b * ca) >> 8;\n     }\n\n     gfxs->color = color;\n\n#define RGB_TO_YCBCR(r,g,b,y,cb,cr)                          \\\n     if (destination->config.colorspace == DSCS_BT601)       \\\n          RGB_TO_YCBCR_BT601(r,g,b,y,cb,cr);                 \\\n     else if (destination->config.colorspace == DSCS_BT709)  \\\n          RGB_TO_YCBCR_BT709(r,g,b,y,cb,cr);                 \\\n     else if (destination->config.colorspace == DSCS_BT2020) \\\n          RGB_TO_YCBCR_BT2020(r,g,b,y,cb,cr);                \\\n     else {                                                  \\\n          y = 16;                                            \\\n          cb = cr = 128;                                     \\\n     }\n\n     switch (gfxs->dst_format) {\n          case DSPF_ARGB1555:\n               gfxs->Cop = PIXEL_ARGB1555( color.a, color.r, color.g, color.b );\n               break;\n          case DSPF_ARGB8565:\n               gfxs->Cop = PIXEL_ARGB8565( color.a, color.r, color.g, color.b );\n               break;\n          case DSPF_RGB16:\n               gfxs->Cop = PIXEL_RGB16( color.r, color.g, color.b );\n               break;\n          case DSPF_RGB18:\n               gfxs->Cop = PIXEL_RGB18( color.r, color.g, color.b );\n               break;\n          case DSPF_RGB24:\n               gfxs->Cop = PIXEL_RGB32( color.r, color.g, color.b );\n               break;\n          case DSPF_BGR24:\n               gfxs->Cop = PIXEL_RGB32( color.b, color.g, color.r );\n               break;\n          case DSPF_RGB32:\n               gfxs->Cop = PIXEL_RGB32( color.r, color.g, color.b );\n               break;\n          case DSPF_ARGB:\n               gfxs->Cop = PIXEL_ARGB( color.a, color.r, color.g, color.b );\n               break;\n          case DSPF_ABGR:\n               gfxs->Cop = PIXEL_ABGR( color.a, color.r, color.g, color.b );\n               break;\n          case DSPF_AiRGB:\n               gfxs->Cop = PIXEL_AiRGB( color.a, color.r, color.g, color.b );\n               break;\n          case DSPF_ARGB6666:\n               gfxs->Cop = PIXEL_ARGB6666( color.a, color.r, color.g, color.b );\n               break;\n          case DSPF_ARGB1666:\n               gfxs->Cop = PIXEL_ARGB1666( color.a, color.r, color.g, color.b );\n               break;\n          case DSPF_A1:\n               gfxs->Cop = color.a >> 7;\n               break;\n          case DSPF_A4:\n               gfxs->Cop = color.a >> 4;\n               break;\n          case DSPF_A8:\n               gfxs->Cop = color.a;\n               break;\n          case DSPF_YUY2:\n               RGB_TO_YCBCR( color.r, color.g, color.b, gfxs->YCop, gfxs->CbCop, gfxs->CrCop );\n#ifdef WORDS_BIGENDIAN\n               gfxs->Cop = PIXEL_YUY2_BE( gfxs->YCop, gfxs->CbCop, gfxs->CrCop );\n#else\n               gfxs->Cop = PIXEL_YUY2_LE( gfxs->YCop, gfxs->CbCop, gfxs->CrCop );\n#endif\n               break;\n          case DSPF_RGB332:\n               gfxs->Cop = PIXEL_RGB332( color.r, color.g, color.b );\n               break;\n          case DSPF_UYVY:\n               RGB_TO_YCBCR( color.r, color.g, color.b, gfxs->YCop, gfxs->CbCop, gfxs->CrCop );\n#ifdef WORDS_BIGENDIAN\n               gfxs->Cop = PIXEL_UYVY_BE( gfxs->YCop, gfxs->CbCop, gfxs->CrCop );\n#else\n               gfxs->Cop = PIXEL_UYVY_LE( gfxs->YCop, gfxs->CbCop, gfxs->CrCop );\n#endif\n               break;\n          case DSPF_I420:\n          case DSPF_YV12:\n          case DSPF_NV12:\n          case DSPF_NV21:\n          case DSPF_Y42B:\n          case DSPF_YV16:\n          case DSPF_NV16:\n          case DSPF_NV61:\n          case DSPF_Y444:\n          case DSPF_YV24:\n          case DSPF_NV24:\n          case DSPF_NV42:\n               RGB_TO_YCBCR( color.r, color.g, color.b, gfxs->YCop, gfxs->CbCop, gfxs->CrCop );\n               gfxs->Cop = gfxs->YCop;\n               break;\n          case DSPF_LUT1:\n          case DSPF_LUT2:\n          case DSPF_LUT8:\n               gfxs->Cop  = state->color_index;\n               gfxs->Alut = destination->palette;\n               break;\n          case DSPF_ALUT44:\n               gfxs->Cop  = (color.a & 0xf0) + state->color_index;\n               gfxs->Alut = destination->palette;\n               break;\n          case DSPF_ARGB2554:\n               gfxs->Cop = PIXEL_ARGB2554( color.a, color.r, color.g, color.b );\n               break;\n          case DSPF_ARGB4444:\n               gfxs->Cop = PIXEL_ARGB4444( color.a, color.r, color.g, color.b );\n               break;\n          case DSPF_RGBA4444:\n               gfxs->Cop = PIXEL_RGBA4444( color.a, color.r, color.g, color.b );\n               break;\n          case DSPF_AYUV:\n               RGB_TO_YCBCR( color.r, color.g, color.b, gfxs->YCop, gfxs->CbCop, gfxs->CrCop );\n               gfxs->Cop = PIXEL_AYUV( color.a, gfxs->YCop, gfxs->CbCop, gfxs->CrCop );\n               break;\n          case DSPF_RGB444:\n               gfxs->Cop = PIXEL_RGB444( color.r, color.g, color.b );\n               break;\n          case DSPF_RGB555:\n               gfxs->Cop = PIXEL_RGB555( color.r, color.g, color.b );\n               break;\n          case DSPF_BGR555:\n               gfxs->Cop = PIXEL_BGR555( color.r, color.g, color.b );\n               break;\n          case DSPF_RGBA5551:\n               gfxs->Cop = PIXEL_RGBA5551( color.a, color.r, color.g, color.b );\n               break;\n          case DSPF_RGBAF88871:\n               gfxs->Cop = PIXEL_RGBAF88871( color.a, color.r, color.g, color.b );\n               break;\n          case DSPF_AVYU:\n               RGB_TO_YCBCR( color.r, color.g, color.b, gfxs->YCop, gfxs->CbCop, gfxs->CrCop );\n               gfxs->Cop = PIXEL_AVYU( color.a, gfxs->YCop, gfxs->CbCop, gfxs->CrCop );\n               break;\n          case DSPF_VYU:\n               RGB_TO_YCBCR( color.r, color.g, color.b, gfxs->YCop, gfxs->CbCop, gfxs->CrCop );\n               gfxs->Cop = PIXEL_VYU( gfxs->YCop, gfxs->CbCop, gfxs->CrCop );\n               break;\n          case DSPF_A1_LSB:\n               gfxs->Cop = color.a & 1;\n               break;\n          default:\n               D_ONCE( \"unsupported destination format\" );\n               return false;\n     }\n\n#undef RGB_TO_YCBCR\n\n     dst_ycbcr = is_ycbcr[DFB_PIXELFORMAT_INDEX(gfxs->dst_format)];\n\n     if (DFB_BLITTING_FUNCTION( accel )) {\n          switch (gfxs->src_format) {\n               case DSPF_LUT1:\n               case DSPF_LUT2:\n               case DSPF_LUT8:\n               case DSPF_ALUT44:\n                    gfxs->Blut = source->palette;\n               case DSPF_ARGB1555:\n               case DSPF_RGBA5551:\n               case DSPF_ARGB2554:\n               case DSPF_ARGB4444:\n               case DSPF_RGBA4444:\n               case DSPF_ARGB1666:\n               case DSPF_ARGB6666:\n               case DSPF_ARGB8565:\n               case DSPF_RGB16:\n               case DSPF_RGB18:\n               case DSPF_RGB24:\n               case DSPF_BGR24:\n               case DSPF_RGB32:\n               case DSPF_ARGB:\n               case DSPF_ABGR:\n               case DSPF_AiRGB:\n               case DSPF_RGB332:\n               case DSPF_RGB444:\n               case DSPF_RGB555:\n               case DSPF_BGR555:\n               case DSPF_RGBAF88871:\n                    if (dst_ycbcr && simpld_blittingflags & (DSBLIT_COLORIZE | DSBLIT_SRC_PREMULTCOLOR))\n                         return false;\n               case DSPF_A1:\n               case DSPF_A1_LSB:\n               case DSPF_A4:\n               case DSPF_A8:\n                    if (DFB_PLANAR_PIXELFORMAT(gfxs->dst_format) && simpld_blittingflags & DSBLIT_DST_COLORKEY)\n                         return false;\n                    break;\n               case DSPF_I420:\n               case DSPF_YV12:\n               case DSPF_NV12:\n               case DSPF_NV21:\n               case DSPF_Y42B:\n               case DSPF_YV16:\n               case DSPF_NV16:\n               case DSPF_NV61:\n               case DSPF_Y444:\n               case DSPF_YV24:\n               case DSPF_NV24:\n               case DSPF_NV42:\n                    if (simpld_blittingflags & DSBLIT_SRC_COLORKEY)\n                         return false;\n               case DSPF_YUY2:\n               case DSPF_UYVY:\n               case DSPF_AYUV:\n               case DSPF_AVYU:\n               case DSPF_VYU:\n                    if (dst_ycbcr && simpld_blittingflags & (DSBLIT_COLORIZE | DSBLIT_SRC_PREMULTCOLOR))\n                         return false;\n                    if (DFB_PLANAR_PIXELFORMAT(gfxs->dst_format) && simpld_blittingflags & DSBLIT_DST_COLORKEY)\n                         return false;\n                    break;\n               default:\n                    D_ONCE( \"unsupported source format\" );\n                    return false;\n          }\n     }\n\n     src_ycbcr = is_ycbcr[DFB_PIXELFORMAT_INDEX(gfxs->src_format)];\n\n     gfxs->need_accumulator = true;\n\n     gfxs->Astep = gfxs->Bstep = gfxs->Ostep = 1;\n\n     switch (accel) {\n          case DFXL_FILLRECTANGLE:\n          case DFXL_DRAWRECTANGLE:\n          case DFXL_DRAWLINE:\n          case DFXL_FILLTRIANGLE:\n               if (state->drawingflags & ~(DSDRAW_DST_COLORKEY | DSDRAW_SRC_PREMULTIPLY | DSDRAW_DST_PREMULTIPLY)) {\n                    GenefxAccumulator Cacc, SCacc;\n\n                    if (state->drawingflags & DSDRAW_BLEND) {\n                         if (state->src_blend == DSBF_ZERO) {\n                              if (state->dst_blend == DSBF_ZERO) {\n                                   gfxs->Cop = 0;\n                                   if (state->drawingflags & DSDRAW_DST_COLORKEY) {\n                                        gfxs->Dkey = state->dst_colorkey;\n                                        *funcs++ = Cop_toK_Aop_PFI[dst_pfi];\n                                   }\n                                   else\n                                        *funcs++ = Cop_to_Aop_PFI[dst_pfi];\n                                   break;\n                              }\n                              else if (state->dst_blend == DSBF_ONE) {\n                                   break;\n                              }\n                         }\n                         else if (state->src_blend == DSBF_ONE && state->dst_blend == DSBF_ZERO) {\n                              if (state->drawingflags & DSDRAW_DST_COLORKEY) {\n                                   gfxs->Dkey = state->dst_colorkey;\n                                   *funcs++ = Cop_toK_Aop_PFI[dst_pfi];\n                              }\n                              else\n                                   *funcs++ = Cop_to_Aop_PFI[dst_pfi];\n                              break;\n                         }\n                    }\n\n                    /* Load from destination. */\n                    *funcs++ = Sop_is_Aop;\n                    if (DFB_PIXELFORMAT_IS_INDEXED( gfxs->dst_format ))\n                         *funcs++ = Slut_is_Alut;\n                    *funcs++ = Dacc_is_Aacc;\n                    *funcs++ = Sop_PFI_to_Dacc[dst_pfi];\n\n                    if (dst_ycbcr) {\n                         if (destination->config.colorspace == DSCS_BT601)\n                              *funcs++ = Dacc_YCbCr_to_RGB_BT601;\n                         else if (destination->config.colorspace == DSCS_BT709)\n                              *funcs++ = Dacc_YCbCr_to_RGB_BT709;\n                         else if (destination->config.colorspace == DSCS_BT2020)\n                              *funcs++ = Dacc_YCbCr_to_RGB_BT2020;\n                    }\n\n                    /* Premultiply destination. */\n                    if (state->drawingflags & DSDRAW_DST_PREMULTIPLY)\n                         *funcs++ = Dacc_premultiply;\n\n                    /* Load source (color). */\n                    Cacc.RGB.a = color.a;\n                    Cacc.RGB.r = color.r;\n                    Cacc.RGB.g = color.g;\n                    Cacc.RGB.b = color.b;\n\n                    if (state->drawingflags & DSDRAW_BLEND) {\n                         /* Source blending. */\n                         switch (state->src_blend) {\n                              case DSBF_ZERO:\n                                   break;\n                              case DSBF_ONE:\n                                   SCacc = Cacc;\n                                   break;\n                              case DSBF_SRCCOLOR:\n                                   SCacc.RGB.a = (Cacc.RGB.a * (Cacc.RGB.a + 1)) >> 8;\n                                   SCacc.RGB.r = (Cacc.RGB.r * (Cacc.RGB.r + 1)) >> 8;\n                                   SCacc.RGB.g = (Cacc.RGB.g * (Cacc.RGB.g + 1)) >> 8;\n                                   SCacc.RGB.b = (Cacc.RGB.b * (Cacc.RGB.b + 1)) >> 8;\n                                   break;\n                              case DSBF_INVSRCCOLOR:\n                                   SCacc.RGB.a = (Cacc.RGB.a * (0x100 - Cacc.RGB.a)) >> 8;\n                                   SCacc.RGB.r = (Cacc.RGB.r * (0x100 - Cacc.RGB.r)) >> 8;\n                                   SCacc.RGB.g = (Cacc.RGB.g * (0x100 - Cacc.RGB.g)) >> 8;\n                                   SCacc.RGB.b = (Cacc.RGB.b * (0x100 - Cacc.RGB.b)) >> 8;\n                                   break;\n                              case DSBF_SRCALPHA:\n                                   ca = color.a + 1;\n                                   SCacc.RGB.a = (Cacc.RGB.a * ca) >> 8;\n                                   SCacc.RGB.r = (Cacc.RGB.r * ca) >> 8;\n                                   SCacc.RGB.g = (Cacc.RGB.g * ca) >> 8;\n                                   SCacc.RGB.b = (Cacc.RGB.b * ca) >> 8;\n                                   break;\n                              case DSBF_INVSRCALPHA:\n                                   ca = 0x100 - color.a;\n                                   SCacc.RGB.a = (Cacc.RGB.a * ca) >> 8;\n                                   SCacc.RGB.r = (Cacc.RGB.r * ca) >> 8;\n                                   SCacc.RGB.g = (Cacc.RGB.g * ca) >> 8;\n                                   SCacc.RGB.b = (Cacc.RGB.b * ca) >> 8;\n                                   break;\n                              case DSBF_SRCALPHASAT:\n                                   *funcs++ = Sacc_is_NULL;\n                              case DSBF_DESTALPHA:\n                              case DSBF_INVDESTALPHA:\n                              case DSBF_DESTCOLOR:\n                              case DSBF_INVDESTCOLOR:\n                                   *funcs++ = Dacc_is_Bacc;\n                                   *funcs++ = Cacc_to_Dacc;\n                                   *funcs++ = Dacc_is_Aacc;\n                                   *funcs++ = Xacc_is_Bacc;\n                                   *funcs++ = Yacc_is_Bacc;\n                                   *funcs++ = Xacc_blend[state->src_blend-1];\n                                   break;\n                              default:\n                                   D_BUG( \"unknown src_blend %u\", state->src_blend );\n                         }\n\n                         /* Destination blending. */\n                         *funcs++ = Sacc_is_NULL;\n                         *funcs++ = Xacc_is_Tacc;\n                         *funcs++ = Yacc_is_Aacc;\n\n                         if (state->dst_blend > D_ARRAY_SIZE(Xacc_blend) || state->dst_blend < 1)\n                              D_BUG( \"unknown dst_blend %u\", state->dst_blend );\n                         else\n                              *funcs++ = Xacc_blend[state->dst_blend-1];\n\n                         /* Add source to destination accumulator. */\n                         switch (state->src_blend) {\n                              case DSBF_ZERO:\n                                   break;\n                              case DSBF_ONE:\n                              case DSBF_SRCCOLOR:\n                              case DSBF_INVSRCCOLOR:\n                              case DSBF_SRCALPHA:\n                              case DSBF_INVSRCALPHA:\n                                   if (SCacc.RGB.a || SCacc.RGB.r || SCacc.RGB.g || SCacc.RGB.b) {\n                                        *funcs++ = Dacc_is_Tacc;\n                                        *funcs++ = SCacc_add_to_Dacc;\n                                   }\n                                   break;\n                              case DSBF_DESTALPHA:\n                              case DSBF_INVDESTALPHA:\n                              case DSBF_DESTCOLOR:\n                              case DSBF_INVDESTCOLOR:\n                              case DSBF_SRCALPHASAT:\n                                   *funcs++ = Sacc_is_Bacc;\n                                   *funcs++ = Dacc_is_Tacc;\n                                   *funcs++ = Sacc_add_to_Dacc;\n                                   break;\n                              default:\n                                   D_BUG( \"unknown src_blend %u\", state->src_blend );\n                         }\n                    }\n\n                    /* Demultiply result. */\n                    if (state->drawingflags & DSDRAW_DEMULTIPLY)\n                         *funcs++ = Dacc_demultiply;\n\n                    /* XOR destination. */\n                    if (state->drawingflags & DSDRAW_XOR) {\n                         if (state->drawingflags & DSDRAW_BLEND) {\n                              *funcs++ = Sacc_is_Aacc;\n                              *funcs++ = Sacc_xor_Dacc;\n                              *funcs++ = Sacc_is_Tacc;\n\n                              if (dst_ycbcr)\n                                   *funcs++ = Dacc_is_Tacc;\n                         }\n                         else {\n                              *funcs++ = Dacc_xor;\n                              *funcs++ = Sacc_is_Aacc;\n\n                              if (dst_ycbcr)\n                                   *funcs++ = Dacc_is_Aacc;\n                         }\n                    }\n                    else if (state->drawingflags & DSDRAW_BLEND) {\n                         *funcs++ = Sacc_is_Tacc;\n\n                         if (dst_ycbcr)\n                              *funcs++ = Dacc_is_Tacc;\n                    }\n                    else {\n                         *funcs++ = Sacc_is_Aacc;\n\n                         if (dst_ycbcr)\n                              *funcs++ = Dacc_is_Aacc;\n                    }\n\n                    if (dst_ycbcr) {\n                         if (destination->config.colorspace == DSCS_BT601)\n                              *funcs++ = Dacc_RGB_to_YCbCr_BT601;\n                         else if (destination->config.colorspace == DSCS_BT709)\n                              *funcs++ = Dacc_RGB_to_YCbCr_BT709;\n                         else if (destination->config.colorspace == DSCS_BT2020)\n                              *funcs++ = Dacc_RGB_to_YCbCr_BT2020;\n                    }\n\n                    /* Write to destination. */\n                    if (state->drawingflags & DSDRAW_DST_COLORKEY) {\n                         gfxs->Dkey = state->dst_colorkey;\n                         *funcs++ = Sacc_toK_Aop_PFI[dst_pfi];\n                    }\n                    else\n                         *funcs++ = Sacc_to_Aop_PFI[dst_pfi];\n\n                    /* Store computed Cacc. */\n                    gfxs->Cacc  = Cacc;\n                    gfxs->SCacc = SCacc;\n               }\n               else {\n                    gfxs->need_accumulator = false;\n\n                    if (state->drawingflags & DSDRAW_DST_COLORKEY) {\n                         gfxs->Dkey = state->dst_colorkey;\n                         *funcs++ = Cop_toK_Aop_PFI[dst_pfi];\n                    }\n                    else\n                         *funcs++ = Cop_to_Aop_PFI[dst_pfi];\n               }\n               break;\n          case DFXL_BLIT:\n               if (simpld_blittingflags == DSBLIT_BLEND_ALPHACHANNEL &&\n                   state->src_blend == DSBF_SRCALPHA &&\n                   state->dst_blend == DSBF_INVSRCALPHA) {\n                    if (gfxs->src_format == DSPF_ARGB &&\n                        Bop_argb_blend_alphachannel_src_invsrc_Aop_PFI[dst_pfi]) {\n                         *funcs++ = Bop_argb_blend_alphachannel_src_invsrc_Aop_PFI[dst_pfi];\n                         break;\n                    }\n               }\n               if (simpld_blittingflags == DSBLIT_BLEND_ALPHACHANNEL &&\n                   state->src_blend == DSBF_ONE &&\n                   state->dst_blend == DSBF_INVSRCALPHA) {\n                    if (gfxs->src_format == DSPF_ARGB &&\n                        Bop_argb_blend_alphachannel_one_invsrc_Aop_PFI[dst_pfi]) {\n                         *funcs++ = Bop_argb_blend_alphachannel_one_invsrc_Aop_PFI[dst_pfi];\n                         break;\n                    }\n               }\n               if (simpld_blittingflags == (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_SRC_PREMULTIPLY) &&\n                   state->src_blend == DSBF_ONE &&\n                   state->dst_blend == DSBF_INVSRCALPHA) {\n                    if (gfxs->src_format == DSPF_ARGB &&\n                        Bop_argb_blend_alphachannel_one_invsrc_premultiply_Aop_PFI[dst_pfi]) {\n                         *funcs++ = Bop_argb_blend_alphachannel_one_invsrc_premultiply_Aop_PFI[dst_pfi];\n                         break;\n                    }\n               }\n               if (((simpld_blittingflags == (DSBLIT_COLORIZE | DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_SRC_PREMULTIPLY) &&\n                     state->src_blend == DSBF_ONE) ||\n                    (simpld_blittingflags == (DSBLIT_COLORIZE | DSBLIT_BLEND_ALPHACHANNEL) &&\n                     state->src_blend == DSBF_SRCALPHA)) &&\n                   state->dst_blend   == DSBF_INVSRCALPHA) {\n                    if (gfxs->src_format == DSPF_A8 && Bop_a8_set_alphapixel_Aop_PFI[dst_pfi]) {\n                         *funcs++ = Bop_a8_set_alphapixel_Aop_PFI[dst_pfi];\n                         break;\n                    }\n                    if (gfxs->src_format == DSPF_A1 && Bop_a1_set_alphapixel_Aop_PFI[dst_pfi]) {\n                         *funcs++ = Bop_a1_set_alphapixel_Aop_PFI[dst_pfi];\n                         break;\n                    }\n                    if (gfxs->src_format == DSPF_A1_LSB && Bop_a1_lsb_set_alphapixel_Aop_PFI[dst_pfi]) {\n                         *funcs++ = Bop_a1_lsb_set_alphapixel_Aop_PFI[dst_pfi];\n                         break;\n                    }\n               }\n#ifndef WORDS_BIGENDIAN\n               if (simpld_blittingflags       == DSBLIT_NOFX &&\n                   source->config.format      == DSPF_RGB24 &&\n                   destination->config.format == DSPF_RGB16) {\n                    *funcs++ = Bop_rgb24_to_Aop_rgb16_LE;\n                    break;\n               }\n               if (simpld_blittingflags       == DSBLIT_NOFX &&\n                   (source->config.format     == DSPF_RGB32 || source->config.format == DSPF_ARGB) &&\n                   destination->config.format == DSPF_RGB16) {\n                    *funcs++ = Bop_rgb32_to_Aop_rgb16_LE;\n                    break;\n               }\n#endif\n               /* fall through */\n          case DFXL_TEXTRIANGLES:\n          case DFXL_STRETCHBLIT: {\n               int modulation = simpld_blittingflags & MODULATION_FLAGS;\n\n               if (modulation                                                                   ||\n                   (accel == DFXL_TEXTRIANGLES && (src_pfi != dst_pfi || simpld_blittingflags)) ||\n                   (simpld_blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR))     ||\n                   ((simpld_blittingflags & DSBLIT_ROTATE90) && accel == DFXL_STRETCHBLIT)) {\n                    bool read_destination         = false;\n                    bool source_needs_destination = false;\n                    bool scale_from_accumulator;\n\n                    /* Check if destination has to be read. */\n                    if (simpld_blittingflags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) {\n                         switch (state->src_blend) {\n                              case DSBF_DESTALPHA:\n                              case DSBF_DESTCOLOR:\n                              case DSBF_INVDESTALPHA:\n                              case DSBF_INVDESTCOLOR:\n                              case DSBF_SRCALPHASAT:\n                                   source_needs_destination = true;\n                              default:\n                                   ;\n                         }\n\n                         read_destination = source_needs_destination || (state->dst_blend != DSBF_ZERO) ||\n                                            (simpld_blittingflags & DSBLIT_XOR);\n                    }\n                    else if (simpld_blittingflags & DSBLIT_XOR) {\n                         read_destination = true;\n                    }\n\n                    scale_from_accumulator = !read_destination && (accel == DFXL_STRETCHBLIT);\n\n                    /* Read the destination if needed. */\n                    if (read_destination) {\n                         *funcs++ = Sop_is_Aop;\n                         if (DFB_PIXELFORMAT_IS_INDEXED( gfxs->dst_format ))\n                              *funcs++ = Slut_is_Alut;\n                         *funcs++ = Dacc_is_Aacc;\n                         *funcs++ = Sop_PFI_to_Dacc[dst_pfi];\n\n                         if (dst_ycbcr) {\n                              if (destination->config.colorspace == DSCS_BT601)\n                                   *funcs++ = Dacc_YCbCr_to_RGB_BT601;\n                              else if (destination->config.colorspace == DSCS_BT709)\n                                   *funcs++ = Dacc_YCbCr_to_RGB_BT709;\n                              else if (destination->config.colorspace == DSCS_BT2020)\n                                   *funcs++ = Dacc_YCbCr_to_RGB_BT2020;\n                         }\n\n                         if (simpld_blittingflags & DSBLIT_DST_PREMULTIPLY)\n                              *funcs++ = Dacc_premultiply;\n                    }\n                    else if (scale_from_accumulator) {\n                         *funcs++ = Len_is_Slen;\n                    }\n\n                    /* Read the source */\n                    *funcs++ = Sop_is_Bop;\n                    if (DFB_PIXELFORMAT_IS_INDEXED( gfxs->src_format ))\n                         *funcs++ = Slut_is_Blut;\n                    *funcs++ = Dacc_is_Bacc;\n                    if (accel == DFXL_TEXTRIANGLES) {\n                         if (simpld_blittingflags & DSBLIT_SRC_COLORKEY) {\n                              gfxs->Skey = state->src_colorkey;\n\n                              *funcs++ = Sop_PFI_TEX_Kto_Dacc[src_pfi];\n                         }\n                         else {\n                              *funcs++ = Sop_PFI_TEX_to_Dacc[src_pfi];\n                         }\n                    }\n                    else {\n                         if (simpld_blittingflags & DSBLIT_SRC_COLORKEY) {\n                              gfxs->Skey = state->src_colorkey;\n                              if (accel == DFXL_BLIT || scale_from_accumulator)\n                                   *funcs++ = Sop_PFI_Kto_Dacc[src_pfi];\n                              else\n                                   *funcs++ = Sop_PFI_SKto_Dacc[src_pfi];\n                         }\n                         else {\n                              if (accel == DFXL_BLIT || scale_from_accumulator)\n                                   *funcs++ = Sop_PFI_to_Dacc[src_pfi];\n                              else\n                                   *funcs++ = Sop_PFI_Sto_Dacc[src_pfi];\n                         }\n                    }\n\n                    if (src_ycbcr) {\n                         if (source->config.colorspace == DSCS_BT601)\n                              *funcs++ = Dacc_YCbCr_to_RGB_BT601;\n                         else if (source->config.colorspace == DSCS_BT709)\n                              *funcs++ = Dacc_YCbCr_to_RGB_BT709;\n                         else if (source->config.colorspace == DSCS_BT2020)\n                              *funcs++ = Dacc_YCbCr_to_RGB_BT2020;\n                    }\n\n                    /* Premultiply color alpha. */\n                    if (simpld_blittingflags & DSBLIT_SRC_PREMULTCOLOR) {\n                         gfxs->Cacc.RGB.a = color.a + 1;\n                         *funcs++ = Dacc_premultiply_color_alpha;\n                    }\n\n                    /* Modulate the source if requested. */\n                    if (Dacc_modulation[modulation & (DSBLIT_COLORIZE           |\n                                                      DSBLIT_BLEND_ALPHACHANNEL |\n                                                      DSBLIT_BLEND_COLORALPHA)]) {\n                         /* Modulation source. */\n                         gfxs->Cacc.RGB.a = color.a + 1;\n                         gfxs->Cacc.RGB.r = color.r + 1;\n                         gfxs->Cacc.RGB.g = color.g + 1;\n                         gfxs->Cacc.RGB.b = color.b + 1;\n\n                         *funcs++ = Dacc_modulation[modulation & (DSBLIT_COLORIZE           |\n                                                                  DSBLIT_BLEND_ALPHACHANNEL |\n                                                                  DSBLIT_BLEND_COLORALPHA)];\n                    }\n\n                    /* Modulate the source with mask if requested. */\n                    if (simpld_blittingflags & DSBLIT_SRC_MASK_ALPHA) {\n                         if (simpld_blittingflags & DSBLIT_SRC_MASK_COLOR) {\n                              if (Dacc_modulate_mask_argb_from_PFI[mask_pfi])\n                                   *funcs++ = Dacc_modulate_mask_argb_from_PFI[mask_pfi];\n                         }\n                         else {\n                              if (Dacc_modulate_mask_alpha_from_PFI[mask_pfi])\n                                   *funcs++ = Dacc_modulate_mask_alpha_from_PFI[mask_pfi];\n                         }\n                    }\n                    else if (simpld_blittingflags & DSBLIT_SRC_MASK_COLOR) {\n                         if (Dacc_modulate_mask_rgb_from_PFI[mask_pfi])\n                              *funcs++ = Dacc_modulate_mask_rgb_from_PFI[mask_pfi];\n                    }\n\n                    /* Premultiply (modulated) source alpha. */\n                    if (simpld_blittingflags & DSBLIT_SRC_PREMULTIPLY)\n                         *funcs++ = Dacc_premultiply;\n\n                    /* Do blend functions and combine both accumulators. */\n                    if (simpld_blittingflags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) {\n                         *funcs++ = Sacc_is_Bacc;\n                         *funcs++ = Dacc_is_Aacc;\n\n                         if (source_needs_destination &&\n                             state->dst_blend != DSBF_ONE) {\n                              /* Blend the destination. */\n                              *funcs++ = Yacc_is_Aacc;\n                              *funcs++ = Xacc_is_Tacc;\n                              *funcs++ = Xacc_blend[state->dst_blend-1];\n\n                              /* Blend the source. */\n                              *funcs++ = Xacc_is_Bacc;\n                              *funcs++ = Yacc_is_Bacc;\n                              *funcs++ = Xacc_blend[state->src_blend-1];\n                         }\n                         else {\n                              /* Blend the destination if needed. */\n                              if (read_destination) {\n                                   *funcs++ = Yacc_is_Aacc;\n                                   *funcs++ = Xacc_is_Tacc;\n                                   *funcs++ = Xacc_blend[state->dst_blend-1];\n                              }\n\n                              /* Blend the source. */\n                              *funcs++ = Xacc_is_Bacc;\n                              *funcs++ = Yacc_is_Bacc;\n                              *funcs++ = Xacc_blend[state->src_blend-1];\n                         }\n\n                         /* Add the destination to the source. */\n                         if (read_destination) {\n                              *funcs++ = Sacc_is_Tacc;\n                              *funcs++ = Dacc_is_Bacc;\n                              *funcs++ = Sacc_add_to_Dacc;\n                         }\n                    }\n\n                    if (simpld_blittingflags & DSBLIT_DEMULTIPLY) {\n                         *funcs++ = Dacc_is_Bacc;\n                         *funcs++ = Dacc_demultiply;\n                    }\n\n                    /* XOR source with destination. */\n                    if (simpld_blittingflags & DSBLIT_XOR) {\n                         *funcs++ = Sacc_is_Aacc;\n                         *funcs++ = Dacc_is_Bacc;\n                         *funcs++ = Dacc_clamp;\n                         *funcs++ = Sacc_xor_Dacc;\n                    }\n\n                    if (dst_ycbcr) {\n                         *funcs++ = Dacc_is_Bacc;\n                         if (destination->config.colorspace == DSCS_BT601)\n                              *funcs++ = Dacc_RGB_to_YCbCr_BT601;\n                         else if (destination->config.colorspace == DSCS_BT709)\n                              *funcs++ = Dacc_RGB_to_YCbCr_BT709;\n                         else if (destination->config.colorspace == DSCS_BT2020)\n                              *funcs++ = Dacc_RGB_to_YCbCr_BT2020;\n                    }\n\n                    /* Write source to destination. */\n                    *funcs++ = Sacc_is_Bacc;\n                    if (scale_from_accumulator) {\n                         *funcs++ = Len_is_Dlen;\n                         if (simpld_blittingflags & DSBLIT_DST_COLORKEY) {\n                              gfxs->Dkey = state->dst_colorkey;\n                              *funcs++ = Sacc_StoK_Aop_PFI[dst_pfi];\n                         }\n                         else\n                              *funcs++ = Sacc_Sto_Aop_PFI[dst_pfi];\n                    }\n                    else {\n                         if (simpld_blittingflags & DSBLIT_DST_COLORKEY) {\n                              gfxs->Dkey = state->dst_colorkey;\n                              *funcs++ = Sacc_toK_Aop_PFI[dst_pfi];\n                         }\n                         else\n                              *funcs++ = Sacc_to_Aop_PFI[dst_pfi];\n                    }\n               }\n               else if (simpld_blittingflags == DSBLIT_INDEX_TRANSLATION &&\n                        DFB_PIXELFORMAT_IS_INDEXED( gfxs->src_format ) &&\n                        DFB_PIXELFORMAT_IS_INDEXED( gfxs->dst_format )) {\n                    gfxs->trans     = state->index_translation;\n                    gfxs->num_trans = state->num_translation;\n\n                    switch (gfxs->src_format) {\n                         case DSPF_LUT2:\n                              switch (gfxs->dst_format) {\n                                   case DSPF_LUT8:\n                                        *funcs++ = Bop_lut2_translate_to_Aop_lut8;\n                                        break;\n\n                                   default:\n                                        D_ONCE( \"no index translation to %s implemented\",\n                                                dfb_pixelformat_name( gfxs->dst_format ) );\n                                        break;\n                              }\n                              break;\n                         default:\n                              D_ONCE( \"no index translation from %s implemented\",\n                                      dfb_pixelformat_name( gfxs->src_format ) );\n                              break;\n                    }\n               }\n               else if (((gfxs->src_format == gfxs->dst_format &&\n                          (!DFB_PIXELFORMAT_IS_INDEXED( gfxs->src_format ) ||\n                           dfb_palette_equal( gfxs->Alut, gfxs->Blut ))) ||\n                         ((gfxs->src_format == DSPF_I420 ||\n                           gfxs->src_format == DSPF_YV12 ||\n                           gfxs->src_format == DSPF_Y42B ||\n                           gfxs->src_format == DSPF_YV16) &&\n                          (gfxs->dst_format == DSPF_I420 ||\n                           gfxs->dst_format == DSPF_YV12 ||\n                           gfxs->dst_format == DSPF_Y42B ||\n                           gfxs->dst_format == DSPF_YV16))) &&\n                        (accel == DFXL_BLIT || !(simpld_blittingflags & (DSBLIT_ROTATE90 | DSBLIT_FLIP_HORIZONTAL)))) {\n                    gfxs->need_accumulator = false;\n\n                    switch (accel) {\n                         case DFXL_BLIT:\n                              if (simpld_blittingflags & DSBLIT_SRC_COLORKEY &&\n                                  simpld_blittingflags & DSBLIT_DST_COLORKEY) {\n                                   gfxs->Skey = state->src_colorkey;\n                                   gfxs->Dkey = state->dst_colorkey;\n                                   *funcs++ = Bop_PFI_KtoK_Aop_PFI[dst_pfi];\n                              }\n                              else if (simpld_blittingflags & DSBLIT_SRC_COLORKEY) {\n                                   gfxs->Skey = state->src_colorkey;\n                                   *funcs++ = Bop_PFI_Kto_Aop_PFI[dst_pfi];\n                              }\n                              else if (simpld_blittingflags & DSBLIT_DST_COLORKEY) {\n                                   gfxs->Dkey = state->dst_colorkey;\n                                   *funcs++ = Bop_PFI_toK_Aop_PFI[dst_pfi];\n                              }\n                              else if (simpld_blittingflags & (DSBLIT_ROTATE90 | DSBLIT_FLIP_HORIZONTAL)) {\n                                   *funcs++ = Bop_PFI_toR_Aop_PFI[dst_pfi];\n                              }\n                              else\n                                   *funcs++ = Bop_PFI_to_Aop_PFI[dst_pfi];\n                              break;\n                         case DFXL_STRETCHBLIT:\n                              if (simpld_blittingflags & DSBLIT_SRC_COLORKEY &&\n                                  simpld_blittingflags & DSBLIT_DST_COLORKEY) {\n                                   gfxs->Skey = state->src_colorkey;\n                                   gfxs->Dkey = state->dst_colorkey;\n                                   *funcs++ = Bop_PFI_SKtoK_Aop_PFI[dst_pfi];\n                              }\n                              else if (simpld_blittingflags & DSBLIT_SRC_COLORKEY) {\n                                   gfxs->Skey = state->src_colorkey;\n                                   *funcs++ = Bop_PFI_SKto_Aop_PFI[dst_pfi];\n                              }\n                              else if (simpld_blittingflags & DSBLIT_DST_COLORKEY) {\n                                   gfxs->Dkey = state->dst_colorkey;\n                                   *funcs++ = Bop_PFI_StoK_Aop_PFI[dst_pfi];\n                              }\n                              else\n                                   *funcs++ = Bop_PFI_Sto_Aop_PFI[dst_pfi];\n                              break;\n                         case DFXL_TEXTRIANGLES:\n                              *funcs++ = Bop_PFI_TEX_to_Aop_PFI[dst_pfi];\n                              break;\n                         default:\n                              break;\n                    }\n               }\n               else {\n                    bool scale_from_accumulator = (src_ycbcr != dst_ycbcr) && (accel == DFXL_STRETCHBLIT);\n\n                    if (scale_from_accumulator)\n                         *funcs++ = Len_is_Slen;\n\n                    gfxs->Sop = gfxs->Bop;\n\n                    if (DFB_PIXELFORMAT_IS_INDEXED( gfxs->src_format ))\n                         *funcs++ = Slut_is_Blut;\n\n                    if (accel == DFXL_BLIT || scale_from_accumulator) {\n                         if (simpld_blittingflags & DSBLIT_SRC_COLORKEY) {\n                              gfxs->Skey = state->src_colorkey;\n                              *funcs++ = Sop_PFI_Kto_Dacc[src_pfi];\n                         }\n                         else\n                              *funcs++ = Sop_PFI_to_Dacc[src_pfi];\n                    }\n                    else { /* DFXL_STRETCHBLIT */\n                         if (simpld_blittingflags & DSBLIT_SRC_COLORKEY) {\n                              gfxs->Skey = state->src_colorkey;\n                              *funcs++ = Sop_PFI_SKto_Dacc[src_pfi];\n                         }\n                         else\n                              *funcs++ = Sop_PFI_Sto_Dacc[src_pfi];\n\n                    }\n\n                    if (!src_ycbcr && dst_ycbcr) {\n                         if (DFB_COLOR_BITS_PER_PIXEL( gfxs->src_format )) {\n                              if (destination->config.colorspace == DSCS_BT601)\n                                   *funcs++ = Dacc_RGB_to_YCbCr_BT601;\n                              else if (destination->config.colorspace == DSCS_BT709)\n                                   *funcs++ = Dacc_RGB_to_YCbCr_BT709;\n                              else if (destination->config.colorspace == DSCS_BT2020)\n                                   *funcs++ = Dacc_RGB_to_YCbCr_BT2020;\n                         }\n                         else\n                              *funcs++ = Dacc_Alpha_to_YCbCr;\n                    }\n                    else if (src_ycbcr && !dst_ycbcr) {\n                         if (DFB_COLOR_BITS_PER_PIXEL( gfxs->dst_format )) {\n                              if (source->config.colorspace == DSCS_BT601)\n                                   *funcs++ = Dacc_YCbCr_to_RGB_BT601;\n                              else if (source->config.colorspace == DSCS_BT709)\n                                   *funcs++ = Dacc_YCbCr_to_RGB_BT709;\n                              else if (source->config.colorspace == DSCS_BT2020)\n                                   *funcs++ = Dacc_YCbCr_to_RGB_BT2020;\n                         }\n                    }\n\n                    if (scale_from_accumulator) {\n                         *funcs++ = Len_is_Dlen;\n                         if (simpld_blittingflags & DSBLIT_DST_COLORKEY) {\n                              gfxs->Dkey = state->dst_colorkey;\n                              *funcs++ = Sacc_StoK_Aop_PFI[dst_pfi];\n                         }\n                         else\n                              *funcs++ = Sacc_Sto_Aop_PFI[dst_pfi];\n                    }\n                    else {\n                         if (simpld_blittingflags & DSBLIT_DST_COLORKEY) {\n                              gfxs->Dkey = state->dst_colorkey;\n                              *funcs++ = Sacc_toK_Aop_PFI[dst_pfi];\n                         }\n                         else\n                              *funcs++ = Sacc_to_Aop_PFI[dst_pfi];\n                    }\n               }\n               break;\n          }\n          default:\n               D_ONCE( \"unimplemented drawing/blitting function\" );\n               return false;\n     }\n\n     *funcs = NULL;\n\n     dfb_state_update( state, state->flags & CSF_SOURCE_LOCKED );\n\n     return true;\n}\n\nbool\ngAcquire( CardState           *state,\n          DFBAccelerationMask  accel )\n{\n     DFBResult ret;\n\n     if (!gAcquireCheck( state, accel ))\n          return false;\n\n     /* Push our own identity for buffer locking calls (locality of accessor). */\n     Core_PushIdentity( 0 );\n\n     ret = gAcquireLockBuffers( state, accel );\n     if (ret) {\n          Core_PopIdentity();\n          return false;\n     }\n\n     if (!gAcquireSetup( state, accel )) {\n          gAcquireUnlockBuffers( state );\n          Core_PopIdentity();\n          return false;\n     }\n\n     return true;\n}\n\nvoid\ngRelease( CardState *state )\n{\n     gAcquireUnlockBuffers( state );\n\n     Core_PopIdentity();\n}\n"
  },
  {
    "path": "src/gfx/generic/generic.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __GENERIC_H__\n#define __GENERIC_H__\n\n#include <core/coretypes.h>\n\n/**********************************************************************************************************************/\n\ntypedef void (*GenefxFunc)( GenefxState *gfxs );\n\ntypedef union {\n     struct {\n          u16 b;\n          u16 g;\n          u16 r;\n          u16 a;\n     } RGB;\n     struct {\n          u16 u;\n          u16 v;\n          u16 y;\n          u16 a;\n     } YUV;\n} GenefxAccumulator;\n\nstruct __DFB_GenefxState {\n     GenefxFunc               funcs[32];\n\n     int                      length;            /* span length */\n     int                      Slen;              /* span length (source) */\n     int                      Dlen;              /* span length (destination) */\n\n     void                    *dst_org[3];\n     void                    *src_org[3];\n     void                    *mask_org[3];\n\n     int                      dst_pitch;\n     int                      src_pitch;\n     int                      mask_pitch;\n\n     int                      dst_bpp;\n     int                      src_bpp;\n     int                      mask_bpp;\n\n     DFBSurfaceCapabilities   dst_caps;\n     DFBSurfaceCapabilities   src_caps;\n     DFBSurfaceCapabilities   mask_caps;\n\n     DFBSurfacePixelFormat    dst_format;\n     DFBSurfacePixelFormat    src_format;\n     DFBSurfacePixelFormat    mask_format;\n\n     int                      dst_height;\n     int                      src_height;\n     int                      mask_height;\n\n     int                      dst_field_offset;\n     int                      src_field_offset;\n     int                      mask_field_offset;\n\n     DFBColor                 color;\n\n     /*\n      * operands\n      */\n     void                    *Aop[3];\n     void                    *Bop[3];\n     void                    *Mop[3];\n     u32                      Cop;\n\n     int                      Astep;\n     int                      Bstep;\n\n     u8                       YCop;\n     u8                       CbCop;\n     u8                       CrCop;\n\n     int                      Aop_field;\n     int                      Bop_field;\n     int                      Mop_field;\n\n     int                      AopY;\n     int                      BopY;\n     int                      MopY;\n\n     int                      s;\n     int                      t;\n\n     /*\n      * color keys\n      */\n     u32                      Dkey;\n     u32                      Skey;\n\n     /*\n      * color lookup tables\n      */\n     CorePalette             *Alut;\n     CorePalette             *Blut;\n\n     /*\n      * accumulators\n      */\n     void                    *ABstart;\n     int                      ABsize;\n     GenefxAccumulator       *Aacc;\n     GenefxAccumulator       *Bacc;\n     GenefxAccumulator       *Tacc;              /* for simultaneous S+D blending */\n     GenefxAccumulator        Cacc;\n     GenefxAccumulator        SCacc;\n\n     /*\n      * dataflow control\n      */\n     GenefxAccumulator       *Xacc;              /* writing pointer for blending */\n     GenefxAccumulator       *Yacc;              /* input pointer for blending */\n     GenefxAccumulator       *Dacc;\n     GenefxAccumulator       *Sacc;\n\n     void                   **Sop;\n     CorePalette             *Slut;\n\n     int                      Ostep;             /* for horizontal blitting direction */\n\n     int                      SperD;             /* for scaled/texture routines only */\n     int                      TperD;             /* for texture routines only */\n     int                      Xphase;            /* initial value for fractional steps (zero if not clipped) */\n\n     bool                     need_accumulator;\n\n     int                     *trans;\n     int                      num_trans;\n};\n\n/**********************************************************************************************************************/\n\nvoid gGetDriverInfo( GraphicsDriverInfo  *driver_info );\n\nvoid gGetDeviceInfo( GraphicsDeviceInfo  *device_info );\n\nbool gAcquire      ( CardState           *state,\n                     DFBAccelerationMask  accel );\n\nvoid gRelease      ( CardState           *state );\n\n#endif\n"
  },
  {
    "path": "src/gfx/generic/generic_64.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\nstatic void\nCop_to_Aop_32_64( GenefxState *gfxs )\n{\n     int  l;\n     int  w    = gfxs->length;\n     u32 *D    = gfxs->Aop[0];\n     u32  Cop  = gfxs->Cop;\n     u64  DCop = ((u64) Cop << 32) | Cop;\n\n     if ((long) D & 4) {\n          *D++ = Cop;\n          w--;\n     }\n\n     for (l = w >> 1; l; l--) {\n          *((u64*) D) = DCop;\n          D += 2;\n     }\n\n     if (w & 1)\n          *D = Cop;\n}\n\nstatic void\nBop_rgb32_toK_Aop_64( GenefxState *gfxs )\n{\n     int  l;\n     int  w     = gfxs->length;\n     u32 *S     = gfxs->Bop[0];\n     u32 *D     = gfxs->Aop[0];\n     u32  Dkey  = gfxs->Dkey;\n     u64  DDkey = ((u64) Dkey << 32) | Dkey;\n\n     if ((long) D & 4) {\n          if ((*D & 0x00ffffff) == Dkey)\n               *D = *S;\n\n          S++;\n          D++;\n          w--;\n     }\n\n     for (l = w >> 1; l; l--) {\n          u64 d = *((u64*) D);\n\n          if ((d & 0x00ffffff00000000ull) == (DDkey & 0x00ffffff00000000ull)) {\n               if ((d & 0x0000000000ffffffull) == (DDkey & 0x0000000000ffffffull)) {\n                    *((u64*) D) = *((u64*) S);\n               }\n               else {\n#ifdef WORDS_BIGENDIAN\n                    D[0] = S[0];\n#else\n                    D[1] = S[1];\n#endif\n               }\n          }\n          else if ((d & 0x0000000000ffffffull) == (DDkey & 0x0000000000ffffffull)) {\n#ifdef WORDS_BIGENDIAN\n               D[1] = S[1];\n#else\n               D[0] = S[0];\n#endif\n          }\n\n          S += 2;\n          D += 2;\n     }\n\n     if (w & 1) {\n          if ((*D & 0x00ffffff) == Dkey)\n               *D = *S;\n     }\n}\n\nstatic void\nBop_rgb32_Kto_Aop_64( GenefxState *gfxs )\n{\n     int  l;\n     int  w     = gfxs->length;\n     u32 *S     = gfxs->Bop[0];\n     u32 *D     = gfxs->Aop[0];\n     u32  Skey  = gfxs->Skey;\n     u64  DSkey = ((u64) Skey << 32) | Skey;\n\n     if ((long) D & 4) {\n          if ((*S & 0x00ffffff) != Skey)\n               *D = *S;\n\n          S++;\n          D++;\n          w--;\n     }\n\n     for (l = w >> 1; l; l--) {\n          u64 s = *((u64*) S);\n\n          if ((s & 0x00ffffff00ffffffull) != DSkey) {\n               if ((s & 0x00ffffff00000000ull) != (DSkey & 0x00ffffff00000000ull)) {\n                    if ((s & 0x0000000000ffffffull) != (DSkey & 0x0000000000ffffffull)) {\n                         *((u64*) D) = s;\n                    }\n                    else {\n#ifdef WORDS_BIGENDIAN\n                         D[0] = (u32) (s >> 32);\n#else\n                         D[1] = (u32) (s >> 32);\n#endif\n                    }\n               }\n               else {\n#ifdef WORDS_BIGENDIAN\n                    D[1] = (u32) s;\n#else\n                    D[0] = (u32) s;\n#endif\n               }\n          }\n\n          S += 2;\n          D += 2;\n     }\n\n     if (w & 1) {\n          if ((*S & 0x00ffffff) != Skey)\n               *D = *S;\n     }\n}\n\nstatic void\nBop_32_Sto_Aop_64( GenefxState *gfxs )\n{\n     int  l;\n     int  w      = gfxs->length;\n     int  i      = 0;\n     u32 *D      = gfxs->Aop[0];\n     u32 *S      = gfxs->Bop[0];\n     int  SperD  = gfxs->SperD;\n     int  SperD2 = SperD << 1;\n\n     if ((long) D & 4) {\n          *D++ = *S;\n          i += SperD;\n          w--;\n     }\n\n     for (l = w >> 1; l; l--) {\n#ifdef WORDS_BIGENDIAN\n          *((u64*) D) = ((u64) S[i>>16] << 32) | S[(i+SperD)>>16];\n#else\n          *((u64*) D) = ((u64) S[(i+SperD)>>16] << 32) | S[i>>16];\n#endif\n          D += 2;\n          i += SperD2;\n     }\n\n     if (w & 1)\n          *D = S[i>>16];\n}\n\nstatic void\nDacc_xor_64( GenefxState *gfxs )\n{\n     int  w = gfxs->length;\n     u64 *D = (u64*) gfxs->Dacc;\n     u64  color;\n\n#ifdef WORDS_BIGENDIAN\n     color = ((u64) gfxs->color.b << 48) |\n             ((u64) gfxs->color.g << 32) |\n             ((u64) gfxs->color.r << 16) |\n             ((u64) gfxs->color.a);\n#else\n     color = ((u64) gfxs->color.a << 48) |\n             ((u64) gfxs->color.r << 32) |\n             ((u64) gfxs->color.g << 16) |\n             ((u64) gfxs->color.b);\n#endif\n\n     for (; w; w--) {\n          *D ^= color;\n          D++;\n     }\n}\n"
  },
  {
    "path": "src/gfx/generic/generic_blit.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/state.h>\n#include <gfx/generic/generic.h>\n#include <gfx/generic/generic_blit.h>\n#include <gfx/generic/generic_util.h>\n#include <gfx/util.h>\n\n/**********************************************************************************************************************/\n\ntypedef void (*XopAdvanceFunc)( GenefxState *gfxs );\n\nvoid\ngBlit( CardState    *state,\n       DFBRectangle *rect,\n       int           dx,\n       int           dy )\n{\n     GenefxState             *gfxs;\n     XopAdvanceFunc           Aop_advance;\n     XopAdvanceFunc           Bop_advance;\n     int                      Aop_X;\n     int                      Aop_Y;\n     int                      Bop_X;\n     int                      Bop_Y;\n     XopAdvanceFunc           Mop_advance = NULL;\n     int                      Mop_X       = 0;\n     int                      Mop_Y       = 0;\n     int                      h;\n     int                      mask_h;\n     int                      mask_x;\n     int                      mask_y;\n     DFBSurfaceBlittingFlags  rotflip_blittingflags;\n\n     D_ASSERT( state != NULL );\n     D_ASSERT( state->gfxs != NULL );\n\n     gfxs = state->gfxs;\n\n     rotflip_blittingflags = state->blittingflags;\n\n     dfb_simplify_blittingflags( &rotflip_blittingflags );\n     rotflip_blittingflags &= (DSBLIT_FLIP_HORIZONTAL | DSBLIT_FLIP_VERTICAL | DSBLIT_ROTATE90 );\n\n     if (dfb_config->software_warn) {\n          D_WARN( \"Blit (%4d,%4d-%4dx%4d) %6s, flags 0x%08x, funcs %u/%u, color 0x%02x%02x%02x%02x <- (%4d,%4d) %6s\",\n                  dx, dy, rect->w, rect->h, dfb_pixelformat_name( gfxs->dst_format ), state->blittingflags,\n                  state->src_blend, state->dst_blend, state->color.a, state->color.r, state->color.g, state->color.b,\n                  rect->x, rect->y, dfb_pixelformat_name( gfxs->src_format ) );\n     }\n\n     D_ASSERT( state->clip.x1 <= dx );\n     D_ASSERT( state->clip.y1 <= dy );\n     D_ASSERT(  (rotflip_blittingflags & DSBLIT_ROTATE90) || state->clip.x2 >= (dx + rect->w - 1) );\n     D_ASSERT(  (rotflip_blittingflags & DSBLIT_ROTATE90) || state->clip.y2 >= (dy + rect->h - 1) );\n     D_ASSERT( !(rotflip_blittingflags & DSBLIT_ROTATE90) || state->clip.x2 >= (dx + rect->h - 1) );\n     D_ASSERT( !(rotflip_blittingflags & DSBLIT_ROTATE90) || state->clip.y2 >= (dy + rect->w - 1) );\n\n     CHECK_PIPELINE();\n\n     if (!Genefx_ABacc_prepare( gfxs, rect->w ))\n          return;\n\n     switch (gfxs->src_format) {\n          case DSPF_A4:\n          case DSPF_YUY2:\n          case DSPF_UYVY:\n               rect->x &= ~1;\n               break;\n          default:\n               break;\n     }\n\n     switch (gfxs->dst_format) {\n          case DSPF_A4:\n          case DSPF_YUY2:\n          case DSPF_UYVY:\n               dx &= ~1;\n               break;\n          default:\n               break;\n     }\n\n     gfxs->length = rect->w;\n\n     if (gfxs->src_org[0] == gfxs->dst_org[0] && dy == rect->y && dx > rect->x)\n          /* We must blit from right to left. */\n          gfxs->Astep = gfxs->Bstep = -1;\n     else\n          /* We must blit from left to right. */\n          gfxs->Astep = gfxs->Bstep = 1;\n\n     mask_x = mask_y = 0;\n\n     if ((state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) &&\n         (state->src_mask_flags & DSMF_STENCIL)) {\n          mask_x = state->src_mask_offset.x;\n          mask_y = state->src_mask_offset.y;\n     }\n\n     mask_h = gfxs->mask_height;\n\n     if (rotflip_blittingflags == (DSBLIT_FLIP_HORIZONTAL | DSBLIT_FLIP_VERTICAL)) {\n          gfxs->Astep *= -1;\n\n          Aop_X = dx + rect->w - 1;\n          Aop_Y = dy;\n\n          Bop_X = rect->x;\n          Bop_Y = rect->y + rect->h - 1;\n\n          Aop_advance = Genefx_Aop_next;\n          Bop_advance = Genefx_Bop_prev;\n\n          if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) {\n               Mop_X = mask_x;\n               Mop_Y = mask_y + mask_h - 1;\n\n               Mop_advance = Genefx_Mop_prev;\n          }\n     }\n     else if (rotflip_blittingflags == DSBLIT_FLIP_HORIZONTAL) {\n          gfxs->Astep *= -1;\n\n          Aop_X = dx + rect->w - 1;\n          Aop_Y = dy;\n\n          Bop_X = rect->x;\n          Bop_Y = rect->y;\n\n          Aop_advance = Genefx_Aop_next;\n          Bop_advance = Genefx_Bop_next;\n\n          if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) {\n               Mop_X = mask_x;\n               Mop_Y = mask_y;\n\n               Mop_advance = Genefx_Mop_next;\n          }\n     }\n     else if (rotflip_blittingflags == DSBLIT_FLIP_VERTICAL) {\n          Aop_X = dx;\n          Aop_Y = dy + rect->h - 1;\n\n          Bop_X = rect->x;\n          Bop_Y = rect->y;\n\n          Aop_advance = Genefx_Aop_prev;\n          Bop_advance = Genefx_Bop_next;\n\n          if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) {\n               Mop_X = mask_x;\n               Mop_Y = mask_y;\n\n               Mop_advance = Genefx_Mop_next;\n          }\n     }\n     else if (rotflip_blittingflags == (DSBLIT_ROTATE90 | DSBLIT_FLIP_HORIZONTAL | DSBLIT_FLIP_VERTICAL)) {\n          if (gfxs->dst_bpp == 0) {\n               D_UNIMPLEMENTED();\n               return;\n          }\n\n          gfxs->Astep *= gfxs->dst_pitch / gfxs->dst_bpp;\n\n          Aop_X = dx;\n          Aop_Y = dy;\n\n          Bop_X = rect->x;\n          Bop_Y = rect->y + rect->h - 1;\n\n          Aop_advance = Genefx_Aop_crab;\n          Bop_advance = Genefx_Bop_prev;\n\n          if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) {\n               Mop_X = mask_x;\n               Mop_Y = mask_y + mask_h - 1;\n\n               Mop_advance = Genefx_Mop_prev;\n          }\n     }\n     else if (rotflip_blittingflags == DSBLIT_ROTATE90) {\n          if (gfxs->dst_bpp == 0) {\n               D_UNIMPLEMENTED();\n               return;\n          }\n\n          gfxs->Astep *= -gfxs->dst_pitch / gfxs->dst_bpp;\n\n          Aop_X = dx;\n          Aop_Y = dy + rect->w - 1;\n\n          Bop_X = rect->x;\n          Bop_Y = rect->y;\n\n          Aop_advance = Genefx_Aop_crab;\n          Bop_advance = Genefx_Bop_next;\n\n          if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) {\n               Mop_X = mask_x;\n               Mop_Y = mask_y;\n\n               Mop_advance = Genefx_Mop_next;\n          }\n     }\n     else if (rotflip_blittingflags == (DSBLIT_ROTATE90 | DSBLIT_FLIP_VERTICAL)) {\n          if (gfxs->dst_bpp == 0) {\n               D_UNIMPLEMENTED();\n               return;\n          }\n\n          gfxs->Astep *= -gfxs->dst_pitch / gfxs->dst_bpp;\n\n          Aop_X = dx + rect->h - 1;\n          Aop_Y = dy + rect->w - 1;\n\n          Bop_X = rect->x;\n          Bop_Y = rect->y;\n\n          Aop_advance = Genefx_Aop_prev_crab;\n          Bop_advance = Genefx_Bop_next;\n\n          if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) {\n               Mop_X = mask_x;\n               Mop_Y = mask_y;\n\n               Mop_advance = Genefx_Mop_next;\n          }\n     }\n     else if (rotflip_blittingflags == (DSBLIT_ROTATE90 | DSBLIT_FLIP_HORIZONTAL)) {\n          if (gfxs->dst_bpp == 0) {\n               D_UNIMPLEMENTED();\n               return;\n          }\n\n          gfxs->Astep *= gfxs->dst_pitch / gfxs->dst_bpp;\n\n          Aop_X = dx;\n          Aop_Y = dy;\n\n          Bop_X = rect->x;\n          Bop_Y = rect->y;\n\n          Aop_advance = Genefx_Aop_crab;\n          Bop_advance = Genefx_Bop_next;\n\n          if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) {\n               Mop_X = mask_x;\n               Mop_Y = mask_y;\n\n               Mop_advance = Genefx_Mop_next;\n          }\n     }\n     else if (gfxs->src_org[0] == gfxs->dst_org[0] && dy > rect->y && !(state->blittingflags & DSBLIT_DEINTERLACE)) {\n          /* We must blit from bottom to top. */\n          Aop_X = dx;\n          Aop_Y = dy + rect->h - 1;\n\n          Bop_X = rect->x;\n          Bop_Y = rect->y + rect->h - 1;\n\n          Aop_advance = Genefx_Aop_prev;\n          Bop_advance = Genefx_Bop_prev;\n\n          if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) {\n               Mop_X = mask_x;\n               Mop_Y = mask_y + mask_h - 1;\n\n               Mop_advance = Genefx_Mop_prev;\n          }\n     }\n     else {\n          /* We must blit from top to bottom. */\n          Aop_X = dx;\n          Aop_Y = dy;\n\n          Bop_X = rect->x;\n          Bop_Y = rect->y;\n\n          Aop_advance = Genefx_Aop_next;\n          Bop_advance = Genefx_Bop_next;\n\n          if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) {\n               Mop_X = mask_x;\n               Mop_Y = mask_y;\n\n               Mop_advance = Genefx_Mop_next;\n          }\n     }\n\n     Genefx_Aop_xy( gfxs, Aop_X, Aop_Y );\n     Genefx_Bop_xy( gfxs, Bop_X, Bop_Y );\n\n     if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR))\n          Genefx_Mop_xy( gfxs, Mop_X, Mop_Y );\n\n     if (state->blittingflags & DSBLIT_DEINTERLACE) {\n          if (state->source->field) {\n               Aop_advance( gfxs );\n               Bop_advance( gfxs );\n\n               if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR))\n                    Mop_advance( gfxs );\n\n               rect->h--;\n          }\n\n          for (h = rect->h / 2; h; h--) {\n               RUN_PIPELINE();\n\n               Aop_advance( gfxs );\n\n               RUN_PIPELINE();\n\n               Aop_advance( gfxs );\n\n               Bop_advance( gfxs );\n               Bop_advance( gfxs );\n\n               if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) {\n                    Mop_advance( gfxs );\n                    Mop_advance( gfxs );\n               }\n          }\n     }\n     else {\n          for (h = rect->h; h; h--) {\n               RUN_PIPELINE();\n\n               Aop_advance( gfxs );\n               Bop_advance( gfxs );\n\n               if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR))\n                    Mop_advance( gfxs );\n          }\n     }\n\n     Genefx_ABacc_flush( gfxs );\n}\n"
  },
  {
    "path": "src/gfx/generic/generic_blit.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __GENERIC_BLIT_H__\n#define __GENERIC_BLIT_H__\n\n#include <core/coretypes.h>\n\n/**********************************************************************************************************************/\n\nvoid gBlit( CardState    *state,\n            DFBRectangle *rect,\n            int           dx,\n            int           dy );\n\n#endif\n"
  },
  {
    "path": "src/gfx/generic/generic_draw_line.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/state.h>\n#include <gfx/generic/generic.h>\n#include <gfx/generic/generic_draw_line.h>\n#include <gfx/generic/generic_fill_rectangle.h>\n#include <gfx/generic/generic_util.h>\n\n/**********************************************************************************************************************/\n\nvoid\ngDrawLine( CardState *state,\n           DFBRegion *line )\n{\n     GenefxState *gfxs;\n     int          i, dx, dy, sdy, dxabs, dyabs, x, y, px, py;\n\n     D_ASSERT( state != NULL );\n     D_ASSERT( state->gfxs != NULL );\n\n     gfxs = state->gfxs;\n\n     CHECK_PIPELINE();\n\n     /* The horizontal distance of the line. */\n     dx    = line->x2 - line->x1;\n     dxabs = ABS( dx );\n\n     if (!Genefx_ABacc_prepare( gfxs, dxabs ))\n          return;\n\n     /* The vertical distance of the line. */\n     dy    = line->y2 - line->y1;\n     dyabs = ABS( dy );\n\n     /* Draw horizontal/vertical line. */\n     if (!dx || !dy) {\n          DFBRectangle rect = { MIN( line->x1, line->x2 ), MIN( line->y1, line->y2 ), dxabs + 1, dyabs + 1 };\n          gFillRectangle( state, &rect );\n          return;\n     }\n\n     if (dfb_config->software_warn) {\n          D_WARN( \"DrawLine (%4d,%4d-%4d,%4d) %6s, flags 0x%08x, color 0x%02x%02x%02x%02x\",\n                  DFB_RECTANGLE_VALS_FROM_REGION( line ), dfb_pixelformat_name( gfxs->dst_format ), state->drawingflags,\n                  state->color.a, state->color.r, state->color.g, state->color.b );\n     }\n\n     sdy = SIGN( dy ) * SIGN( dx );\n     x   = dyabs >> 1;\n     y   = dxabs >> 1;\n\n     if (dx > 0) {\n          px = line->x1;\n          py = line->y1;\n     }\n     else {\n          px = line->x2;\n          py = line->y2;\n     }\n\n     /* The line is more horizontal than vertical. */\n     if (dxabs >= dyabs) {\n          for (i = 0, gfxs->length = 1; i < dxabs; i++, gfxs->length++) {\n               y += dyabs;\n\n               if (y >= dxabs) {\n                    Genefx_Aop_xy( gfxs, px, py );\n\n                    RUN_PIPELINE();\n\n                    px += gfxs->length;\n\n                    gfxs->length = 0;\n\n                    y -= dxabs;\n\n                    py += sdy;\n               }\n          }\n\n          Genefx_Aop_xy( gfxs, px, py );\n\n          RUN_PIPELINE();\n     }\n     /* The line is more vertical than horizontal. */\n     else {\n          gfxs->length = 1;\n\n          Genefx_Aop_xy( gfxs, px, py );\n\n          RUN_PIPELINE();\n\n          for (i = 0; i < dyabs; i++) {\n               x += dxabs;\n\n               if (x >= dyabs) {\n                    x -= dyabs;\n                    px++;\n               }\n\n               py += sdy;\n\n               Genefx_Aop_xy( gfxs, px, py );\n\n               RUN_PIPELINE();\n          }\n     }\n\n     Genefx_ABacc_flush( gfxs );\n}\n"
  },
  {
    "path": "src/gfx/generic/generic_draw_line.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __GENERIC_DRAW_LINE_H__\n#define __GENERIC_DRAW_LINE_H__\n\n#include <core/coretypes.h>\n\n/**********************************************************************************************************************/\n\nvoid gDrawLine( CardState *state,\n                DFBRegion *line );\n\n#endif\n"
  },
  {
    "path": "src/gfx/generic/generic_fill_rectangle.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/state.h>\n#include <gfx/generic/generic.h>\n#include <gfx/generic/generic_fill_rectangle.h>\n#include <gfx/generic/generic_util.h>\n\n/**********************************************************************************************************************/\n\nvoid\ngFillRectangle( CardState    *state,\n                DFBRectangle *rect )\n{\n     GenefxState *gfxs;\n     int          h;\n\n     D_ASSERT( state != NULL );\n     D_ASSERT( state->gfxs != NULL );\n     D_ASSERT( state->clip.x1 <= rect->x );\n     D_ASSERT( state->clip.y1 <= rect->y );\n     D_ASSERT( state->clip.x2 >= (rect->x + rect->w - 1) );\n     D_ASSERT( state->clip.y2 >= (rect->y + rect->h - 1) );\n\n     gfxs = state->gfxs;\n\n     if (dfb_config->software_warn) {\n          D_WARN( \"FillRectangle (%4d,%4d-%4dx%4d) %6s, flags 0x%08x, color 0x%02x%02x%02x%02x\",\n                  DFB_RECTANGLE_VALS( rect ), dfb_pixelformat_name( gfxs->dst_format ), state->drawingflags,\n                  state->color.a, state->color.r, state->color.g, state->color.b );\n     }\n\n     CHECK_PIPELINE();\n\n     if (!Genefx_ABacc_prepare( gfxs, rect->w ))\n          return;\n\n     gfxs->length = rect->w;\n\n     Genefx_Aop_xy( gfxs, rect->x, rect->y );\n\n     h = rect->h;\n     while (h--) {\n          RUN_PIPELINE();\n\n          Genefx_Aop_next( gfxs );\n     }\n\n     Genefx_ABacc_flush( gfxs );\n}\n"
  },
  {
    "path": "src/gfx/generic/generic_fill_rectangle.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __GENERIC_FILL_RECTANGLE_H__\n#define __GENERIC_FILL_RECTANGLE_H__\n\n#include <core/coretypes.h>\n\n/**********************************************************************************************************************/\n\nvoid gFillRectangle( CardState    *state,\n                     DFBRectangle *rect );\n\n#endif\n"
  },
  {
    "path": "src/gfx/generic/generic_mmx.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\nstatic void\nXacc_blend_srcalpha_MMX( GenefxState *gfxs )\n{\n     static const u32 ones[]  = { 0x00010001, 0x00010001 };\n     static const u32 zeros[] = { 0, 0 };\n\n     __asm__ __volatile__ (\n          \"movq      %3, %%mm7\\n\\t\"\n          \"cmp       $0, %2\\n\\t\"\n          \"jne       3f\\n\\t\"\n          \"movq      %4, %%mm6\\n\\t\"\n          \"movd      %5, %%mm0\\n\\t\"\n          \"punpcklbw %%mm6, %%mm0\\n\\t\"   /* mm0 = 00aa 00rr 00gg 00bb */\n          \"punpcklwd %%mm0, %%mm0\\n\\t\"   /* mm0 = 00aa 00aa xxxx xxxx */\n          \"punpckldq %%mm0, %%mm0\\n\\t\"   /* mm0 = 00aa 00aa 00aa 00aa */\n          \"paddw     %%mm7, %%mm0\\n\"\n          \".align    16\\n\"\n          \"4:\\n\\t\"                       /* blend from color */\n          \"testw     $0xf000, 6(%0)\\n\\t\"\n          \"jnz       6f\\n\\t\"\n          \"movq      (%0), %%mm1\\n\\t\"\n          \"pmullw    %%mm0, %%mm1\\n\\t\"\n          \"psrlw     $8, %%mm1\\n\\t\"\n          \"movq      %%mm1, (%6)\\n\\t\"\n          \"jmp       1f\\n\"\n          \"6:\\n\\t\"\n          \"movq      (%0), %%mm1\\n\\t\"\n          \"movq      %%mm1, (%6)\\n\"\n          \"1:\\n\\t\"\n          \"add       $8, %0\\n\\t\"\n          \"add       $8, %6\\n\\t\"\n          \"dec       %1\\n\\t\"\n          \"jnz       4b\\n\\t\"\n          \"jmp       2f\\n\"\n          \".align    16\\n\"\n          \"3:\\n\\t\"                       /* blend from Sacc */\n          \"testw     $0xf000, 6(%0)\\n\\t\"\n          \"jnz       5f\\n\\t\"\n          \"movq      (%2), %%mm0\\n\\t\"\n          \"movq      (%0), %%mm1\\n\\t\"\n          \"punpckhwd %%mm0, %%mm0\\n\\t\"   /* mm2 = 00aa 00aa xxxx xxxx */\n          \"punpckhdq %%mm0, %%mm0\\n\\t\"   /* mm2 = 00aa 00aa 00aa 00aa */\n          \"paddw     %%mm7, %%mm0\\n\\t\"\n          \"pmullw    %%mm0, %%mm1\\n\\t\"\n          \"psrlw     $8, %%mm1\\n\\t\"\n          \"movq      %%mm1, (%6)\\n\\t\"\n          \"jmp       7f\\n\"\n          \"5:\\n\\t\"\n          \"movq      (%0), %%mm1\\n\\t\"\n          \"movq      %%mm1, (%6)\\n\"\n          \"7:\\n\\t\"\n          \"add       $8, %2\\n\\t\"\n          \"add       $8, %0\\n\\t\"\n          \"add       $8, %6\\n\\t\"\n          \"dec       %1\\n\\t\"\n          \"jnz       3b\\n\"\n          \"2:\\n\\t\"\n          \"emms\"\n          : /* no outputs */\n          : \"D\" (gfxs->Yacc), \"c\" (gfxs->length), \"S\" (gfxs->Sacc),\n            \"m\" (*ones), \"m\" (*zeros), \"m\" (gfxs->color), \"r\" (gfxs->Xacc)\n          : \"%st\", \"memory\"\n     );\n}\n\nstatic void\nXacc_blend_invsrcalpha_MMX( GenefxState *gfxs )\n{\n     static const u32 ones[]  = { 0x01000100, 0x01000100 };\n     static const u32 zeros[] = { 0, 0 };\n\n     __asm__ __volatile__ (\n          \"movq      %3, %%mm7\\n\\t\"\n          \"cmp       $0, %2\\n\\t\"\n          \"jne       1f\\n\\t\"\n          \"movq      %4, %%mm6\\n\\t\"\n          \"movd      %5, %%mm0\\n\\t\"\n          \"punpcklbw %%mm6, %%mm0\\n\\t\"   /* mm0 = 00aa 00rr 00gg 00bb */\n          \"punpcklwd %%mm0, %%mm0\\n\\t\"   /* mm0 = 00aa 00aa xxxx xxxx */\n          \"movq      %%mm7, %%mm1\\n\\t\"\n          \"punpckldq %%mm0, %%mm0\\n\\t\"   /* mm0 = 00aa 00aa 00aa 00aa */\n          \"psubw     %%mm0, %%mm1\\n\"\n          \".align    16\\n\"\n          \"2:\\n\\t\"                       /* blend from color */\n          \"testw     $0xf000, 6(%0)\\n\\t\"\n          \"jnz       3f\\n\\t\"\n          \"movq      (%0), %%mm0\\n\\t\"\n          \"pmullw    %%mm1, %%mm0\\n\\t\"\n          \"psrlw     $8, %%mm0\\n\\t\"\n          \"movq      %%mm0, (%6)\\n\\t\"\n          \"jmp       4f\\n\"\n          \"3:\\n\\t\"\n          \"movq      (%0), %%mm0\\n\\t\"\n          \"movq      %%mm0, (%6)\\n\"\n          \"4:\\n\\t\"\n          \"add       $8, %0\\n\\t\"\n          \"add       $8, %6\\n\\t\"\n          \"dec       %1\\n\\t\"\n          \"jnz       2b\\n\\t\"\n          \"jmp       9f\\n\"\n          \".align    16\\n\"\n          \"1:\\n\\t\"                       /* blend from Sacc */\n          \"testw     $0xf000, 6(%0)\\n\\t\"\n          \"jnz       5f\\n\\t\"\n          \"movq      (%2), %%mm2\\n\\t\"\n          \"movq      (%0), %%mm0\\n\\t\"\n          \"punpckhwd %%mm2, %%mm2\\n\\t\"   /* mm2 = 00aa 00aa xxxx xxxx */\n          \"movq      %%mm7, %%mm1\\n\\t\"\n          \"punpckhdq %%mm2, %%mm2\\n\\t\"   /* mm2 = 00aa 00aa 00aa 00aa */\n          \"psubw     %%mm2, %%mm1\\n\\t\"\n          \"pmullw    %%mm1, %%mm0\\n\\t\"\n          \"psrlw     $8, %%mm0\\n\\t\"\n          \"movq      %%mm0, (%6)\\n\\t\"\n          \"jmp       6f\\n\"\n          \"5:\\n\\t\"\n          \"movq      (%0), %%mm0\\n\\t\"\n          \"movq      %%mm0, (%6)\\n\"\n          \"6:\\n\\t\"\n          \"add       $8, %2\\n\\t\"\n          \"add       $8, %0\\n\\t\"\n          \"add       $8, %6\\n\\t\"\n          \"dec       %1\\n\\t\"\n          \"jnz       1b\\n\"\n          \"9:\\n\\t\"\n          \"emms\"\n          : /* no outputs */\n          : \"D\" (gfxs->Yacc), \"c\" (gfxs->length), \"S\" (gfxs->Sacc),\n            \"m\" (*ones), \"m\" (*zeros), \"m\" (gfxs->color), \"r\" (gfxs->Xacc)\n          : \"%st\", \"memory\"\n     );\n}\n\nstatic void\nDacc_modulate_argb_MMX( GenefxState *gfxs )\n{\n     __asm__ __volatile__ (\n          \"movq      %2, %%mm0\\n\"\n          \".align    16\\n\"\n          \"1:\\n\\t\"\n          \"testw     $0xf000, 6(%0)\\n\\t\"\n          \"jnz       2f\\n\\t\"\n          \"movq      (%0), %%mm1\\n\\t\"\n          \"pmullw    %%mm0, %%mm1\\n\\t\"\n          \"psrlw     $8, %%mm1\\n\\t\"\n          \"movq      %%mm1, (%0)\\n\"\n          \".align    16\\n\"\n          \"2:\\n\\t\"\n          \"add       $8, %0\\n\\t\"\n          \"dec       %1\\n\\t\"\n          \"jnz       1b\\n\\t\"\n          \"emms\"\n          : /* no outputs */\n          : \"D\" (gfxs->Dacc), \"c\" (gfxs->length), \"m\" (gfxs->Cacc)\n          : \"%st\", \"memory\"\n     );\n}\n\nstatic void\nSCacc_add_to_Dacc_MMX( GenefxState *gfxs )\n{\n     __asm__ __volatile__ (\n          \"movq      %2, %%mm0\\n\"\n          \".align    16\\n\"\n          \"1:\\n\\t\"\n          \"movq      (%0), %%mm1\\n\\t\"\n          \"paddw     %%mm0, %%mm1\\n\\t\"\n          \"movq      %%mm1, (%0)\\n\\t\"\n          \"add       $8, %0\\n\\t\"\n          \"dec       %1\\n\\t\"\n          \"jnz       1b\\n\\t\"\n          \"emms\"\n          : /* no outputs */\n          : \"D\" (gfxs->Dacc), \"c\" (gfxs->length), \"m\" (gfxs->SCacc)\n          : \"%st\", \"memory\"\n     );\n}\n\nstatic void\nSacc_add_to_Dacc_MMX( GenefxState *gfxs )\n{\n     __asm__ __volatile__ (\n          \".align    16\\n\"\n          \"1:\\n\\t\"\n          \"movq      (%2), %%mm0\\n\\t\"\n          \"movq      (%0), %%mm1\\n\\t\"\n          \"paddw     %%mm1, %%mm0\\n\\t\"\n          \"movq      %%mm0, (%0)\\n\\t\"\n          \"add       $8, %0\\n\\t\"\n          \"add       $8, %2\\n\\t\"\n          \"dec       %1\\n\\t\"\n          \"jnz       1b\\n\\t\"\n          \"emms\"\n          : /* no outputs */\n          : \"D\" (gfxs->Dacc), \"c\" (gfxs->length), \"S\" (gfxs->Sacc)\n          : \"%st\", \"memory\"\n     );\n}\n"
  },
  {
    "path": "src/gfx/generic/generic_neon.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\nstatic void\nSop_rgb16_to_Dacc_NEON( GenefxState *gfxs )\n{\n     int                l;\n     int                w     = gfxs->length;\n     u16               *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                Ostep = gfxs->Ostep;\n\n#define EXPAND_Rto8(r) (((r) << 3) | ((r) >> 2))\n#define EXPAND_Gto8(g) (((g) << 2) | ((g) >> 4))\n#define EXPAND_Bto8(b) (((b) << 3) | ((b) >> 2))\n#define EXPAND(d,s) do {                            \\\n     (d).RGB.a = 0xff;                              \\\n     (d).RGB.r = EXPAND_Rto8( (s & 0xf800) >> 11 ); \\\n     (d).RGB.g = EXPAND_Gto8( (s & 0x07e0) >> 5 );  \\\n     (d).RGB.b = EXPAND_Bto8(  s & 0x001f );        \\\n} while (0)\n\n     if (Ostep != 1) {\n          while (w--) {\n               u16 s = *S;\n\n               EXPAND( *D, s );\n\n               S += Ostep;\n               ++D;\n          }\n\n          return;\n     }\n\n     l = w & 0x7;\n     while (l) {\n          u16 s = *S;\n\n          EXPAND( *D, s );\n\n          ++S;\n          ++D;\n          --l;\n     }\n\n     l = w >> 3;\n     if (l) {\n          __asm__ __volatile__ (\n               \"1:\\n\\t\"\n               \"pld       [%[S], #0xC0]\\n\\t\"\n               \"vld1.16   {q0}, [%[S]]!\\n\\t\"\n               \"vmov.i16  q4, #0x00FF\\n\\t\"\n               \"vshr.u16  q3, q0, #8\\n\\t\"\n               \"vsri.u8   q3, q3, #5\\n\\t\"\n               \"vshl.u16  q2, q0, #5\\n\\t\"\n               \"vshl.u16  q1, q0, #11\\n\\t\"\n               \"vshr.u16  q2, q2, #8\\n\\t\"\n               \"vshr.u16  q1, q1, #8\\n\\t\"\n               \"vsri.u8   q2, q2, #6\\n\\t\"\n               \"vsri.u8   q1, q1, #5\\n\\t\"\n               \"vst4.16   {d2, d4, d6, d8}, [%[D]]!\\n\\t\"\n               \"vst4.16   {d3, d5, d7, d9}, [%[D]]!\\n\\t\"\n               \"subs      %[l], %[l], #1\\n\\t\"\n               \"bne       1b\"\n               : /* no outputs */\n               : [S] \"r\" (S), [D] \"r\" (D), [l] \"r\" (l)\n               : \"memory\", \"d2\", \"d3\", \"d4\", \"d5\", \"d6\", \"d7\", \"d8\", \"d9\"\n          );\n     }\n\n#undef EXPAND\n#undef EXPAND_Rto8\n#undef EXPAND_Gto8\n#undef EXPAND_Bto8\n}\n\nstatic void\nSop_argb_to_Dacc_NEON( GenefxState *gfxs )\n{\n     int                w     = gfxs->length;\n     u16               *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                Ostep = gfxs->Ostep;\n\n     __asm__ __volatile__ (\n          \"mov       r5, %[w]\\n\\t\"\n          \"cmp       %[Ostep], #1\\n\\t\"\n          /* Ostep != 1 */\n          \"bne       1f\\n\\t\"\n          \"lsrs      r4, %[w], #3\\n\\t\"\n          /* Ostep = 1 && w < 8 */\n          \"beq       1f\\n\\t\"\n          /* Ostep = 1 && w >= 8 */\n          \"2:\\n\\t\"\n          \"pld       [%[S], #0xC0] \\n\\t\"\n          \"vld4.8    {d0, d1, d2, d3}, [%[S]]!\\n\\t\"\n          \"vmovl.u8  q2, d0\\n\\t\"\n          \"vmovl.u8  q3, d1\\n\\t\"\n          \"vmovl.u8  q4, d2\\n\\t\"\n          \"vmovl.u8  q5, d3\\n\\t\"\n          \"vst4.16   {d4, d6, d8, d10}, [%[D]]!\\n\\t\"\n          \"vst4.16   {d5, d7, d9, d11}, [%[D]]!\\n\\t\"\n          \"subs      r4, r4, #1\\n\\t\"\n          \"bne       2b\\n\\t\"\n          \"ands      r5, %[w], #7\\n\\t\"\n          /* Ostep = 1 && w = 8 */\n          \"beq       5f\\n\\t\"\n          \"1:\\n\\t\"\n          \"lsl       r6, %[Ostep], #2\\n\\t\"\n          \"vmov.i32  d0, #0\\n\\t\"\n          \"vmov      d1, d0\\n\\t\"\n          \"vmov      d2, d0\\n\\t\"\n          \"vmov      d3, d0\\n\\t\"\n          \"lsrs      r4, r5, #2\\n\\t\"\n          /* w < 4 */\n          \"beq       4f\\n\\t\"\n          /* w >= 4 */\n          \"3:\\n\\t\"\n          \"pld       [%[S], #0xC0]\\n\\t\"\n          \"vld4.8    {d0[0], d1[0], d2[0], d3[0]}, [%[S]],r6\\n\\t\"\n          \"vld4.8    {d0[2], d1[2], d2[2], d3[2]}, [%[S]],r6\\n\\t\"\n          \"vld4.8    {d0[4], d1[4], d2[4], d3[4]}, [%[S]],r6\\n\\t\"\n          \"vld4.8    {d0[6], d1[6], d2[6], d3[6]}, [%[S]],r6\\n\\t\"\n          \"vst4.16   {d0, d1, d2, d3}, [%[D]]!\\n\\t\"\n          \"subs      r4, r4, #1\\n\\t\"\n          \"bne       3b\\n\\t\"\n          \"ands      r5, %[w], #3\\n\\t\"\n          /* w = 4 */\n          \"beq       5f\\n\\t\"\n          \"4:\\n\\t\"\n          \"vld4.8    {d0[0], d1[0], d2[0], d3[0]}, [%[S]],r6\\n\\t\"\n          \"vst4.16   {d0[0], d1[0], d2[0], d3[0]}, [%[D]]!\\n\\t\"\n          \"subs      r5, r5, #1\\n\\t\"\n          \"bne       4b\\n\\t\"\n          \"5:\"\n          : /* no outputs */\n          : [S] \"r\" (S), [D] \"r\" (D), [w] \"r\" (w), [Ostep] \"r\" (Ostep)\n          : \"memory\", \"r4\", \"r5\", \"r6\", \"d0\", \"d1\", \"d2\", \"d3\", \"d4\", \"d5\", \"d6\", \"d7\", \"d8\", \"d9\", \"d10\", \"d11\"\n     );\n}\n\nstatic void\nSacc_to_Aop_rgb16_NEON( GenefxState *gfxs )\n{\n     int                l;\n     int                w     = gfxs->length;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u16               *D     = gfxs->Aop[0];\n     int                Dstep = gfxs->Astep;\n     u32                mask  = 0xff00ff00;\n     u32                color = 0x00ff00ff;\n\n#define PIXEL_OUT(r,g,b) ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))\n#define PIXEL(x) PIXEL_OUT( ((x).RGB.r & 0xff00) ? 0xff : (x).RGB.r, \\\n                            ((x).RGB.g & 0xff00) ? 0xff : (x).RGB.g, \\\n                            ((x).RGB.b & 0xff00) ? 0xff : (x).RGB.b )\n\n     if (Dstep != 1) {\n          while (w--) {\n               if (!(S->RGB.a & 0xf000))\n                    *D = PIXEL( *S );\n\n               ++S;\n               D += Dstep;\n          }\n\n          return;\n     }\n\n     if ((long) D & 2) {\n          if (!(S->RGB.a & 0xf000))\n               *D = PIXEL( *S );\n\n          ++S;\n          ++D;\n          --w;\n     }\n\n     l = w >> 3;\n     while (l) {\n          int i;\n\n          for (i = 0; i < 8; i++) {\n               if (S[i].RGB.a & 0xf000)\n                    break;\n          }\n\n          if (i < 8) {\n               int j;\n\n               for (j = 0; j < i; j++)\n                    D[j] = PIXEL( S[j] );\n\n               for (j = i + 1; j < 8; j++) {\n                    if (!(S[j].RGB.a & 0xf000))\n                         D[j] = PIXEL( S[j] );\n               }\n          }\n          else {\n               __asm__ __volatile__ (\n                    \"mov       r4, %[S]\\n\\t\"\n                    \"pld       [r4, #0xC0]\\n\\t\"\n                    \"pld       [r4, #0x100]\\n\\t\"\n                    \"vld4.16   {d0, d2, d4, d6}, [r4]!\\n\\t\"\n                    \"vld4.16   {d1, d3, d5, d7}, [r4]\\n\\t\"\n                    \"vdup.32   q3, %[mask]\\n\\t\"\n                    \"vdup.32   q4, %[color]\\n\\t\"\n                    /* b */\n                    \"vtst.16   q5, q0, q3\\n\\t\"\n                    \"vceq.u16  q6, q5, #0\\n\\t\"\n                    \"vand.16   q5, q4, q5\\n\\t\"\n                    \"vand.16   q6, q0, q6\\n\\t\"\n                    \"vorr.16   q0, q5, q6\\n\\t\"\n                    \"vshr.u16  q0, q0, #3\\n\\t\"\n                    /* g */\n                    \"vtst.16   q5, q1, q3\\n\\t\"\n                    \"vceq.u16  q6, q5, #0\\n\\t\"\n                    \"vand.16   q5, q4, q5\\n\\t\"\n                    \"vand.16   q6, q1, q6\\n\\t\"\n                    \"vorr.16   q1, q5, q6\\n\\t\"\n                    \"vshr.u16  q1, q1, #2\\n\\t\"\n                    \"vshl.u16  q1, q1, #5\\n\\t\"\n                    /* r */\n                    \"vtst.16   q5, q2, q3\\n\\t\"\n                    \"vceq.u16  q6, q5, #0\\n\\t\"\n                    \"vand.16   q5, q4, q5\\n\\t\"\n                    \"vand.16   q6, q2, q6\\n\\t\"\n                    \"vorr.16   q2, q5, q6\\n\\t\"\n                    \"vshr.u16  q2, q2, #3\\n\\t\"\n                    \"vshl.u16  q2, q2, #11\\n\\t\"\n                    /* rgb */\n                    \"vorr.16   q1, q1, q2\\n\\t\"\n                    \"vorr.16   q0, q0, q1\\n\\t\"\n                    \"vst1.16   {d0, d1}, [%[D]]\"\n                    : /* no outputs */\n                    : [D] \"r\" (D), [S] \"r\" (S),\n                      [mask] \"r\" (mask), [color] \"r\" (color)\n                    : \"memory\", \"r4\", \"d0\", \"d1\", \"d2\", \"d3\", \"d4\",\"d5\", \"d6\", \"d7\"\n               );\n          }\n\n          S += 8;\n          D += 8;\n          --l;\n     }\n\n     l = w & 0x7;\n     while (l) {\n          if (!(S->RGB.a & 0xf000)) {\n               *D = PIXEL( *S );\n          }\n\n          ++S;\n          ++D;\n          --l;\n     }\n\n#undef PIXEL\n#undef PIXEL_OUT\n}\n\nstatic void\nBop_argb_blend_alphachannel_src_invsrc_Aop_rgb16_NEON( GenefxState *gfxs )\n{\n     int  l;\n     int  w     = gfxs->length;\n     u32 *S     = gfxs->Bop[0];\n     u16 *D     = gfxs->Aop[0];\n     u16  f0    = 0xf81f;\n     u16  f1    = 0x07e0;\n     u32  vf[4] = { 0x0000f800, 0x0000001f, 0x003e07c0, 0x0001f800 };\n\n#define SET_PIXEL(d,s)                                                                                                \\\n     switch (s >> 26) {                                                                                               \\\n          case 0:                                                                                                     \\\n               break;                                                                                                 \\\n          case 0x3f:                                                                                                  \\\n               d = ((s & 0x00f80000) >> 8) | ((s & 0x0000fc00) >> 5) | ((s & 0x000000f8) >> 3);                       \\\n               break;                                                                                                 \\\n          default:                                                                                                    \\\n               d = (((((((s >> 8) & 0xf800) | ((s >> 3) & 0x001f)) - (d & 0xf81f)) * ((s >> 26) + 1) +                \\\n                      ((d & 0xf81f) << 6)                                                           ) & 0x003e07c0) + \\\n                    ((((( s >> 5) & 0x07e0)                        - (d & 0x07e0)) * ((s >> 26) + 1) +                \\\n                      ((d & 0x07e0) << 6)                                                           ) & 0x0001f800)   \\\n                   ) >> 6;                                                                                            \\\n     }\n\n     l = w & 3;\n     while (l) {\n          SET_PIXEL( *D, *S );\n\n          ++S;\n          ++D;\n          --l;\n     }\n\n     __asm__ __volatile__ (\n          \"vld1.32   {d0, d1}, [%[vf]]\\n\\t\"\n          \"vdup.32   q1, d0[0]\\n\\t\"\n          \"vdup.32   q2, d0[1]\\n\\t\"\n          \"vdup.32   q3, %[f0]\\n\\t\"\n          \"vdup.32   q4, d1[0]\\n\\t\"\n          \"vdup.32   q5, %[f1]\\n\\t\"\n          \"vdup.32   q6, d1[1]\\n\\t\"\n          \"vmov.i32  q11, #0x1\\n\\t\"\n          : /* no outputs */\n          : [vf] \"r\" (vf), [f0] \"r\" (f0), [f1] \"r\" (f1)\n          : \"memory\", \"d0\", \"d1\"\n     );\n\n     l = w >> 2;\n     while (l) {\n          int  i;\n          u32  valpha = 0;\n          bool a_flag = false;\n\n          for (i = 0; i < 4; i++) {\n               u32 alpha;\n\n               alpha   = S[i] >> 26;\n               valpha |= alpha << (i << 3);\n               a_flag  = a_flag || (alpha == 0) || (alpha == 0x3f);\n          }\n\n          switch (valpha) {\n               case 0:\n                    break;\n               case 0x3f3f3f3f:\n                    __asm__ __volatile__ (\n                         \"pld       [%[S], #0xC0]\\n\\t\"\n                         \"vld1.32   {d0, d1}, [%[S]]\\n\\t\"\n                         \"vshr.u32  q7, q0, #19\\n\\t\"\n                         \"vshr.u16  q8, q0, #10\\n\\t\"\n                         \"vshl.u16  q9, q0, #8\\n\\t\"\n                         \"vshl.u16  q7, q7, #11\\n\\t\"\n                         \"vshl.u16  q8, q8, #5\\n\\t\"\n                         \"vshr.u16  q9, q9, #11\\n\\t\"\n                         \"vorr      q7, q7, q8\\n\\t\"\n                         \"vorr      q7, q7, q9\\n\\t\"\n                         \"vmovn.i32 d14, q7\\n\\t\"\n                         \"vst1.16   {d14}, [%[D]]\"\n                         : /* no outputs */\n                         : [S] \"r\" (S), [D] \"r\" (D)\n                         : \"memory\", \"d0\", \"d1\", \"d14\"\n                    );\n                    break;\n               default:\n                    if (a_flag) {\n                         for (i = 0; i < 4; i++)\n                              SET_PIXEL( D[i], S[i] );\n                    }\n                    else {\n                         __asm__ __volatile__ (\n                              \"pld       [%[D], #0xC0]\\n\\t\"\n                              \"pld       [%[S], #0xC0]\\n\\t\"\n                              \"vld1.16   {d14}, [%[D]]\\n\\t\"\n                              \"vld1.32   {d0, d1}, [%[S]]\\n\\t\"\n                              \"vmovl.u16 q7, d14\\n\\t\"\n                              \"vshr.u32  q8, q0, #8\\n\\t\"\n                              \"vand      q8, q8, q1\\n\\t\"\n                              \"vshr.u32  q9, q0, #3\\n\\t\"\n                              \"vand      q9, q9, q2\\n\\t\"\n                              \"vorr      q8, q8, q9\\n\\t\"\n                              \"vand      q9, q7, q3\\n\\t\"\n                              \"vsub.i32  q8, q8, q9\\n\\t\"\n                              \"vshr.u32  q10, q0, #26\\n\\t\"\n                              \"vadd.i32  q10, q10, q11\\n\\t\"\n                              \"vmul.i32  q8, q8, q10\\n\\t\"\n                              \"vshl.u32  q9, q9, #6\\n\\t\"\n                              \"vadd.i32  q8, q8, q9\\n\\t\"\n                              \"vand      q8, q8, q4\\n\\t\"\n                              \"vshr.u32  q12, q0, #5\\n\\t\"\n                              \"vand      q12, q12, q5\\n\\t\"\n                              \"vand      q13, q7, q5\\n\\t\"\n                              \"vsub.i32  q12, q12, q13\\n\\t\"\n                              \"vmul.i32  q12, q12, q10\\n\\t\"\n                              \"vshl.u32  q13, q13, #6\\n\\t\"\n                              \"vadd.i32  q12, q12, q13\\n\\t\"\n                              \"vand      q12, q12, q6\\n\\t\"\n                              \"vadd.i32  q8, q8, q12\\n\\t\"\n                              \"vshrn.u32 d16, q8, #6\\n\\t\"\n                              \"vst1.16   {d16}, [%[D]]\"\n                              : /* no outputs */\n                              : [S] \"r\" (S), [D] \"r\" (D)\n                              : \"memory\", \"d0\", \"d1\", \"d14\", \"d16\"\n                         );\n                    }\n                    break;\n          }\n\n          S += 4;\n          D += 4;\n          --l;\n     }\n}\n\nstatic void\nXacc_blend_srcalpha_NEON( GenefxState *gfxs )\n{\n     int                l;\n     int                w    = gfxs->length;\n     GenefxAccumulator *X    = gfxs->Xacc;\n     GenefxAccumulator *Y    = gfxs->Yacc;\n     u16                mask = 0xf000;\n\n     if (gfxs->Sacc) {\n          GenefxAccumulator *S    = gfxs->Sacc;\n          u16                sadd = 1;\n\n          l = w >> 3;\n          if (l) {\n               __asm__ __volatile__ (\n                    \"vdup.16   q8, %[mask]\\n\\t\"\n                    \"vdup.16   q9, %[sadd]\\n\\t\"\n                    \"1:\\n\\t\"\n                    \"pld       [%[Y], #0xC0]\\n\\t\"\n                    \"pld       [%[Y], #0x100]\\n\\t\"\n                    \"pld       [%[S], #0xC0]\\n\\t\"\n                    \"pld       [%[S], #0x100]\\n\\t\"\n                    \"vld4.16   {d0, d2, d4, d6}, [%[Y]]!\\n\\t\"\n                    \"vld4.16   {d1, d3, d5, d7}, [%[Y]]!\\n\\t\"\n                    \"vld4.16   {d8, d10, d12, d14}, [%[S]]!\\n\\t\"\n                    \"vld4.16   {d9, d11, d13, d15}, [%[S]]!\\n\\t\"\n                    \"vand      q4, q3, q8\\n\\t\"\n                    \"vceq.i16  q4, q4, #0\\n\\t\"\n                    \"vadd.i16  q5, q9, q7\\n\\t\"\n                    /* b */\n                    \"vmull.u16 q6, d10, d0\\n\\t\"\n                    \"vshrn.i32 d20, q6, #8\\n\\t\"\n                    \"vmull.u16 q6, d11, d1\\n\\t\"\n                    \"vshrn.i32 d21, q6, #8\\n\\t\"\n                    /* g */\n                    \"vmull.u16 q6, d10, d2\\n\\t\"\n                    \"vshrn.i32 d22, q6, #8\\n\\t\"\n                    \"vmull.u16 q6, d11, d3\\n\\t\"\n                    \"vshrn.i32 d23, q6, #8\\n\\t\"\n                    /* r */\n                    \"vmull.u16 q6, d10, d4\\n\\t\"\n                    \"vshrn.i32 d24, q6, #8\\n\\t\"\n                    \"vmull.u16 q6, d11, d5\\n\\t\"\n                    \"vshrn.i32 d25, q6, #8\\n\\t\"\n                    /* a */\n                    \"vmull.u16 q6, d10, d6\\n\\t\"\n                    \"vshrn.i32 d26, q6, #8\\n\\t\"\n                    \"vmull.u16 q6, d11, d7\\n\\t\"\n                    \"vshrn.i32 d27, q6, #8\\n\\t\"\n                    /* if (!(Y->RGB.a & 0xf000)) */\n                    \"vand      q10, q4, q10\\n\\t\"\n                    \"vand      q11, q4, q11\\n\\t\"\n                    \"vand      q12, q4, q12\\n\\t\"\n                    \"vand      q13, q4, q13\\n\\t\"\n                    /* if ((Y->RGB.a & 0xf000)) */\n                    \"vceq.i16  q4, q4, #0\\n\\t\"\n                    \"vand      q0, q4, q0\\n\\t\"\n                    \"vand      q1, q4, q1\\n\\t\"\n                    \"vand      q2, q4, q2\\n\\t\"\n                    \"vand      q3, q4, q3\\n\\t\"\n                    /* X: q0(b), q1(g), q2(r), q3(a) */\n                    \"vorr      q0, q0, q10\\n\\t\"\n                    \"vorr      q1, q1, q11\\n\\t\"\n                    \"vorr      q2, q2, q12\\n\\t\"\n                    \"vorr      q3, q3, q13\\n\\t\"\n                    \"vst4.16   {d0, d2, d4, d6}, [%[X]]!\\n\\t\"\n                    \"vst4.16   {d1, d3, d5, d7}, [%[X]]!\\n\\t\"\n                    \"subs      %[l], %[l], #1\\n\\t\"\n                    \"bne       1b\"\n                    : /* no outputs */\n                    : [X] \"r\" (X), [Y] \"r\" (Y), [S] \"r\" (S), [mask] \"r\" (mask), [sadd] \"r\" (sadd), [l] \"r\" (l)\n                    : \"memory\", \"d0\", \"d1\", \"d2\", \"d3\", \"d4\", \"d5\", \"d6\", \"d7\", \"d8\", \"d9\", \"d10\", \"d11\",\n                      \"d12\", \"d13\", \"d14\", \"d15\", \"d20\", \"d21\", \"d22\", \"d23\", \"d24\", \"d25\", \"d26\", \"d27\"\n               );\n          }\n\n          l = w & 0x7;\n          while (l) {\n               if (!(Y->RGB.a & 0xf000)) {\n                    u16 Sa = S->RGB.a + 1;\n\n                    X->RGB.r = (Sa * Y->RGB.r) >> 8;\n                    X->RGB.g = (Sa * Y->RGB.g) >> 8;\n                    X->RGB.b = (Sa * Y->RGB.b) >> 8;\n                    X->RGB.a = (Sa * Y->RGB.a) >> 8;\n               }\n               else\n                    *X = *Y;\n\n               ++S;\n               ++X; ++Y;\n               --l;\n          }\n     }\n     else {\n          u16 Sa = gfxs->color.a + 1;\n\n          l = w >> 3;\n          if (l) {\n               __asm__ __volatile__ (\n                    \"vdup.16   q7, %[mask]\\n\\t\"\n                    \"vdup.16   q5, %[Sa]\\n\\t\"\n                    \"1:\\n\\t\"\n                    \"pld       [%[Y], #0xC0]\\n\\t\"\n                    \"pld       [%[Y], #0x100]\\n\\t\"\n                    \"vld4.16   {d0, d2, d4, d6}, [%[Y]]!\\n\\t\"\n                    \"vld4.16   {d1, d3, d5, d7}, [%[Y]]!\\n\\t\"\n                    \"vand      q4, q3, q7\\n\\t\"\n                    \"vceq.i16  q4, q4, #0\\n\\t\"\n                    /* b */\n                    \"vmull.u16 q6, d10, d0\\n\\t\"\n                    \"vshrn.i32 d20, q6, #8\\n\\t\"\n                    \"vmull.u16 q6, d11, d1\\n\\t\"\n                    \"vshrn.i32 d21, q6, #8\\n\\t\"\n                    /* g */\n                    \"vmull.u16 q6, d10, d2\\n\\t\"\n                    \"vshrn.i32 d22, q6, #8\\n\\t\"\n                    \"vmull.u16 q6, d11, d3\\n\\t\"\n                    \"vshrn.i32 d23, q6, #8\\n\\t\"\n                    /* r */\n                    \"vmull.u16 q6, d10, d4\\n\\t\"\n                    \"vshrn.i32 d24, q6, #8\\n\\t\"\n                    \"vmull.u16 q6, d11, d5\\n\\t\"\n                    \"vshrn.i32 d25, q6, #8\\n\\t\"\n                    /* a */\n                    \"vmull.u16 q6, d10, d6\\n\\t\"\n                    \"vshrn.i32 d26, q6, #8\\n\\t\"\n                    \"vmull.u16 q6, d11, d7\\n\\t\"\n                    \"vshrn.i32 d27, q6, #8\\n\\t\"\n                    /* if (!(Y->RGB.a & 0xf000)) */\n                    \"vand      q10, q4, q10\\n\\t\"\n                    \"vand      q11, q4, q11\\n\\t\"\n                    \"vand      q12, q4, q12\\n\\t\"\n                    \"vand      q13, q4, q13\\n\\t\"\n                    /* if ((Y->RGB.a & 0xf000)) */\n                    \"vceq.i16  q4, q4, #0\\n\\t\"\n                    \"vand      q0, q4, q0\\n\\t\"\n                    \"vand      q1, q4, q1\\n\\t\"\n                    \"vand      q2, q4, q2\\n\\t\"\n                    \"vand      q3, q4, q3\\n\\t\"\n                    /* X: q0(b), q1(g), q2(r), q3(a) */\n                    \"vorr      q0, q0, q10\\n\\t\"\n                    \"vorr      q1, q1, q11\\n\\t\"\n                    \"vorr      q2, q2, q12\\n\\t\"\n                    \"vorr      q3, q3, q13\\n\\t\"\n                    \"vst4.16   {d0, d2, d4, d6}, [%[X]]!\\n\\t\"\n                    \"vst4.16   {d1, d3, d5, d7}, [%[X]]!\\n\\t\"\n                    \"subs      %[l], %[l], #1\\n\\t\"\n                    \"bne       1b\"\n                    : /* no outputs */\n                    : [X] \"r\" (X), [Y] \"r\" (Y), [Sa] \"r\" (Sa), [mask] \"r\" (mask), [l] \"r\" (l)\n                    : \"memory\", \"d0\", \"d1\", \"d2\", \"d3\", \"d4\", \"d5\", \"d6\", \"d7\", \"d10\", \"d11\",\n                      \"d20\", \"d21\", \"d22\", \"d23\", \"d24\", \"d25\", \"d26\", \"d27\"\n               );\n          }\n\n          l = w & 0x7;\n          while (l) {\n               if (!(Y->RGB.a & 0xf000)) {\n                    X->RGB.r = (Sa * Y->RGB.r) >> 8;\n                    X->RGB.g = (Sa * Y->RGB.g) >> 8;\n                    X->RGB.b = (Sa * Y->RGB.b) >> 8;\n                    X->RGB.a = (Sa * Y->RGB.a) >> 8;\n               }\n               else\n                    *X = *Y;\n\n               ++X; ++Y;\n               --l;\n          }\n     }\n}\n\nstatic void\nXacc_blend_invsrcalpha_NEON( GenefxState *gfxs )\n{\n     int                l;\n     int                w = gfxs->length;\n     GenefxAccumulator *X = gfxs->Xacc;\n     GenefxAccumulator *Y = gfxs->Yacc;\n     u16                mask = 0xf000;\n\n     if (gfxs->Sacc) {\n          GenefxAccumulator *S   = gfxs->Sacc;\n          u16                inv = 0x100;\n\n          l = w >> 3;\n          if (l) {\n               __asm__ __volatile__ (\n                    \"vdup.16   q8, %[mask]\\n\\t\"\n                    \"vdup.16   q9, %[inv]\\n\\t\"\n                    \"1:\\n\\t\"\n                    \"pld       [%[Y], #0xC0]\\n\\t\"\n                    \"pld       [%[Y], #0x100]\\n\\t\"\n                    \"pld       [%[S], #0xC0]\\n\\t\"\n                    \"pld       [%[S], #0x100]\\n\\t\"\n                    \"vld4.16   {d0, d2, d4, d6}, [%[Y]]!\\n\\t\"\n                    \"vld4.16   {d1, d3, d5, d7}, [%[Y]]!\\n\\t\"\n                    \"vld4.16   {d8, d10, d12, d14}, [%[S]]!\\n\\t\"\n                    \"vld4.16   {d9, d11, d13, d15}, [%[S]]!\\n\\t\"\n                    \"vand      q4, q3, q8\\n\\t\"\n                    \"vceq.i16  q4, q4, #0\\n\\t\"\n                    \"vsub.i16  q5, q9, q7\\n\\t\"\n                    /* b */\n                    \"vmull.u16 q6, d10, d0\\n\\t\"\n                    \"vshrn.i32 d20, q6, #8\\n\\t\"\n                    \"vmull.u16 q6, d11, d1\\n\\t\"\n                    \"vshrn.i32 d21, q6, #8\\n\\t\"\n                    /* g */\n                    \"vmull.u16 q6, d10, d2\\n\\t\"\n                    \"vshrn.i32 d22, q6, #8\\n\\t\"\n                    \"vmull.u16 q6, d11, d3\\n\\t\"\n                    \"vshrn.i32 d23, q6, #8\\n\\t\"\n                    /* r */\n                    \"vmull.u16 q6, d10, d4\\n\\t\"\n                    \"vshrn.i32 d24, q6, #8\\n\\t\"\n                    \"vmull.u16 q6, d11, d5\\n\\t\"\n                    \"vshrn.i32 d25, q6, #8\\n\\t\"\n                    /* a */\n                    \"vmull.u16 q6, d10, d6\\n\\t\"\n                    \"vshrn.i32 d26, q6, #8\\n\\t\"\n                    \"vmull.u16 q6, d11, d7\\n\\t\"\n                    \"vshrn.i32 d27, q6, #8\\n\\t\"\n                    /* if (!(Y->RGB.a & 0xf000)) */\n                    \"vand      q10, q4, q10\\n\\t\"\n                    \"vand      q11, q4, q11\\n\\t\"\n                    \"vand      q12, q4, q12\\n\\t\"\n                    \"vand      q13, q4, q13\\n\\t\"\n                    /* if ((Y->RGB.a & 0xf000)) */\n                    \"vceq.i16  q4, q4, #0\\n\\t\"\n                    \"vand      q0, q4, q0\\n\\t\"\n                    \"vand      q1, q4, q1\\n\\t\"\n                    \"vand      q2, q4, q2\\n\\t\"\n                    \"vand      q3, q4, q3\\n\\t\"\n                    /* X: q0(b), q1(g), q2(r), q3(a) */\n                    \"vorr      q0, q0, q10\\n\\t\"\n                    \"vorr      q1, q1, q11\\n\\t\"\n                    \"vorr      q2, q2, q12\\n\\t\"\n                    \"vorr      q3, q3, q13\\n\\t\"\n                    \"vst4.16   {d0, d2, d4, d6}, [%[X]]!\\n\\t\"\n                    \"vst4.16   {d1, d3, d5, d7}, [%[X]]!\\n\\t\"\n                    \"subs      %[l], %[l], #1\\n\\t\"\n                    \"bne       1b\"\n                    : /* no outputs */\n                    : [X] \"r\" (X), [Y] \"r\" (Y), [S] \"r\" (S), [mask] \"r\" (mask), [inv] \"r\" (inv), [l] \"r\" (l)\n                    : \"memory\", \"d0\", \"d1\", \"d2\", \"d3\", \"d4\", \"d5\", \"d6\", \"d7\", \"d8\", \"d9\", \"d10\", \"d11\",\n                      \"d12\", \"d13\", \"d14\", \"d15\", \"d20\", \"d21\", \"d22\", \"d23\", \"d24\", \"d25\", \"d26\", \"d27\"\n               );\n          }\n\n          l = w & 0x7;\n          while (l) {\n               if (!(Y->RGB.a & 0xf000)) {\n                    u16 Sa = 0x100 - S->RGB.a;\n\n                    X->RGB.r = (Sa * Y->RGB.r) >> 8;\n                    X->RGB.g = (Sa * Y->RGB.g) >> 8;\n                    X->RGB.b = (Sa * Y->RGB.b) >> 8;\n                    X->RGB.a = (Sa * Y->RGB.a) >> 8;\n               }\n               else\n                    *X = *Y;\n\n               ++S;\n               ++X; ++Y;\n               --l;\n          }\n     }\n     else {\n          u16 Sa = 0x100 - gfxs->color.a;\n\n          l = w >> 3;\n          if (l) {\n               __asm__ __volatile__ (\n                    \"vdup.16   q7, %[mask]\\n\\t\"\n                    \"vdup.16   q5, %[Sa]\\n\\t\"\n                    \"1:\\n\\t\"\n                    \"pld       [%[Y], #0xC0]\\n\\t\"\n                    \"pld       [%[Y], #0x100]\\n\\t\"\n                    \"vld4.16   {d0, d2, d4, d6}, [%[Y]]!\\n\\t\"\n                    \"vld4.16   {d1, d3, d5, d7}, [%[Y]]!\\n\\t\"\n                    \"vand      q4, q3, q7\\n\\t\"\n                    \"vceq.i16  q4, q4, #0\\n\\t\"\n                    /* b */\n                    \"vmull.u16 q6, d10, d0\\n\\t\"\n                    \"vshrn.i32 d20, q6, #8\\n\\t\"\n                    \"vmull.u16 q6, d11, d1\\n\\t\"\n                    \"vshrn.i32 d21, q6, #8\\n\\t\"\n                    /* g */\n                    \"vmull.u16 q6, d10, d2\\n\\t\"\n                    \"vshrn.i32 d22, q6, #8\\n\\t\"\n                    \"vmull.u16 q6, d11, d3\\n\\t\"\n                    \"vshrn.i32 d23, q6, #8\\n\\t\"\n                    /* r */\n                    \"vmull.u16 q6, d10, d4\\n\\t\"\n                    \"vshrn.i32 d24, q6, #8\\n\\t\"\n                    \"vmull.u16 q6, d11, d5\\n\\t\"\n                    \"vshrn.i32 d25, q6, #8\\n\\t\"\n                    /* a */\n                    \"vmull.u16 q6, d10, d6\\n\\t\"\n                    \"vshrn.i32 d26, q6, #8\\n\\t\"\n                    \"vmull.u16 q6, d11, d7\\n\\t\"\n                    \"vshrn.i32 d27, q6, #8\\n\\t\"\n                    /* if (!(Y->RGB.a & 0xf000)) */\n                    \"vand      q10, q4, q10\\n\\t\"\n                    \"vand      q11, q4, q11\\n\\t\"\n                    \"vand      q12, q4, q12\\n\\t\"\n                    \"vand      q13, q4, q13\\n\\t\"\n                    /* if ((Y->RGB.a & 0xf000)) */\n                    \"vceq.i16  q4, q4, #0\\n\\t\"\n                    \"vand      q0, q4, q0\\n\\t\"\n                    \"vand      q1, q4, q1\\n\\t\"\n                    \"vand      q2, q4, q2\\n\\t\"\n                    \"vand      q3, q4, q3\\n\\t\"\n                    /* X: q0(b), q1(g), q2(r), q3(a) */\n                    \"vorr      q0, q0, q10\\n\\t\"\n                    \"vorr      q1, q1, q11\\n\\t\"\n                    \"vorr      q2, q2, q12\\n\\t\"\n                    \"vorr      q3, q3, q13\\n\\t\"\n                    \"vst4.16   {d0, d2, d4, d6}, [%[X]]!\\n\\t\"\n                    \"vst4.16   {d1, d3, d5, d7}, [%[X]]!\\n\\t\"\n                    \"subs      %[l], %[l], #1\\n\\t\"\n                    \"bne       1b\"\n                    : /* no outputs */\n                    : [X] \"r\" (X), [Y] \"r\" (Y), [Sa] \"r\" (Sa), [mask] \"r\" (mask), [l] \"r\" (l)\n                    : \"memory\", \"d0\", \"d1\", \"d2\", \"d3\", \"d4\", \"d5\", \"d6\", \"d7\", \"d10\", \"d11\",\n                      \"d20\", \"d21\", \"d22\", \"d23\", \"d24\", \"d25\", \"d26\", \"d27\"\n               );\n          }\n\n          l = w & 0x7;\n          while (l) {\n               if (!(Y->RGB.a & 0xf000)) {\n                    X->RGB.r = (Sa * Y->RGB.r) >> 8;\n                    X->RGB.g = (Sa * Y->RGB.g) >> 8;\n                    X->RGB.b = (Sa * Y->RGB.b) >> 8;\n                    X->RGB.a = (Sa * Y->RGB.a) >> 8;\n               }\n               else\n                    *X = *Y;\n\n               ++X; ++Y;\n               --l;\n          }\n     }\n}\n\nstatic void\nDacc_modulate_rgb_NEON( GenefxState *gfxs )\n{\n     int                l;\n     int                w    = gfxs->length;\n     GenefxAccumulator *D    = gfxs->Dacc;\n     GenefxAccumulator  Cacc = gfxs->Cacc;\n     u16                mask = 0xf000;\n\n     l = w & 0x7;\n     while (l) {\n          if (!(D->RGB.a & 0xf000)) {\n               D->RGB.r = (Cacc.RGB.r * D->RGB.r) >> 8;\n               D->RGB.g = (Cacc.RGB.g * D->RGB.g) >> 8;\n               D->RGB.b = (Cacc.RGB.b * D->RGB.b) >> 8;\n          }\n\n          ++D;\n          --l;\n     }\n\n     l = w >> 3;\n     if (l) {\n          __asm__ __volatile__ (\n               \"mov       r4, %[D]\\n\\t\"\n               \"mov       r5, %[D]\\n\\t\"\n               \"vdup.16   q2, %[Cacc_r]\\n\\t\"\n               \"vdup.16   q1, %[Cacc_g]\\n\\t\"\n               \"vdup.16   q0, %[Cacc_b]\\n\\t\"\n               \"vdup.16   q8, %[mask]\\n\\t\"\n               \"1:\\n\\t\"\n               \"pld       [r4, #0xC0]\\n\\t\"\n               \"pld       [r4, #0x100]\\n\\t\"\n               \"vld4.16   {d8, d10, d12, d14}, [r4]!\\n\\t\"\n               \"vld4.16   {d9, d11, d13, d15}, [r4]!\\n\\t\"\n               \"vand      q9, q7, q8\\n\\t\"\n               \"vceq.i16  q9, q9, #0\\n\\t\"\n               /* b */\n               \"vmull.u16 q3, d8, d0\\n\\t\"\n               \"vshrn.i32 d20, q3, #8\\n\\t\"\n               \"vmull.u16 q3, d9, d1\\n\\t\"\n               \"vshrn.i32 d21, q3, #8\\n\\t\"\n               /* g */\n               \"vmull.u16 q3, d10, d2\\n\\t\"\n               \"vshrn.i32 d22, q3, #8\\n\\t\"\n               \"vmull.u16 q3, d11, d3\\n\\t\"\n               \"vshrn.i32 d23, q3, #8\\n\\t\"\n               /* r */\n               \"vmull.u16 q3, d12, d4\\n\\t\"\n               \"vshrn.i32 d24, q3, #8\\n\\t\"\n               \"vmull.u16 q3, d13, d5\\n\\t\"\n               \"vshrn.i32 d25, q3, #8\\n\\t\"\n               /* if (!(D->RGB.a & 0xf000)) */\n               \"vand      q10, q9, q10\\n\\t\"\n               \"vand      q11, q9, q11\\n\\t\"\n               \"vand      q12, q9, q12\\n\\t\"\n               /* if ((D->RGB.a & 0xf000)) */\n               \"vceq.i16  q9, q9, #0\\n\\t\"\n               \"vand      q4, q9, q4\\n\\t\"\n               \"vand      q5, q9, q5\\n\\t\"\n               \"vand      q6, q9, q6\\n\\t\"\n               /* D: q4(b), q5(g), q6(r), q7(a) */\n               \"vorr      q4, q4, q10\\n\\t\"\n               \"vorr      q5, q5, q11\\n\\t\"\n               \"vorr      q6, q6, q12\\n\\t\"\n               \"vst4.16   {d8, d10, d12, d14}, [r5]!\\n\\t\"\n               \"vst4.16   {d9, d11, d13, d15}, [r5]!\\n\\t\"\n               \"subs      %[l], %[l], #1\\n\\t\"\n               \"bne       1b\"\n               : /* no outputs */\n               : [Cacc_r] \"r\" (Cacc.RGB.r), [Cacc_g] \"r\" (Cacc.RGB.g), [Cacc_b] \"r\" (Cacc.RGB.b),\n                 [D] \"r\" (D), [mask] \"r\" (mask), [l] \"r\" (l)\n               : \"memory\", \"r4\", \"r5\", \"d0\", \"d1\", \"d2\", \"d3\", \"d4\", \"d5\", \"d8\", \"d9\", \"d10\", \"d11\",\n                 \"d12\", \"d13\", \"d14\", \"d15\", \"d20\", \"d21\", \"d22\", \"d23\", \"d24\", \"d25\"\n          );\n     }\n}\n\nstatic void\nDacc_modulate_argb_NEON( GenefxState *gfxs )\n{\n     int                l;\n     int                w    = gfxs->length;\n     GenefxAccumulator *D    = gfxs->Dacc;\n     GenefxAccumulator  Cacc = gfxs->Cacc;\n     u16                mask = 0xf000;\n\n     l = w & 0x7;\n     while (l) {\n          if (!(D->RGB.a & 0xf000)) {\n               D->RGB.a = (Cacc.RGB.a * D->RGB.a) >> 8;\n               D->RGB.r = (Cacc.RGB.r * D->RGB.r) >> 8;\n               D->RGB.g = (Cacc.RGB.g * D->RGB.g) >> 8;\n               D->RGB.b = (Cacc.RGB.b * D->RGB.b) >> 8;\n          }\n\n          ++D;\n          --l;\n     }\n\n     l = w >> 3;\n     if (l) {\n          __asm__ __volatile__ (\n               \"mov       r4, %[D]\\n\\t\"\n               \"mov       r5, %[D]\\n\\t\"\n               \"vdup.16   q3, %[Cacc_a]\\n\\t\"\n               \"vdup.16   q2, %[Cacc_r]\\n\\t\"\n               \"vdup.16   q1, %[Cacc_g]\\n\\t\"\n               \"vdup.16   q0, %[Cacc_b]\\n\\t\"\n               \"vdup.16   q8, %[mask]\\n\\t\"\n               \"1:\\n\\t\"\n               \"pld       [r4, #0xC0]\\n\\t\"\n               \"pld       [r4, #0x100]\\n\\t\"\n               \"vld4.16   {d8, d10, d12, d14}, [r4]!\\n\\t\"\n               \"vld4.16   {d9, d11, d13, d15}, [r4]!\\n\\t\"\n               \"vand      q9, q7, q8\\n\\t\"\n               \"vceq.i16  q9, q9, #0\\n\\t\"\n               /* b */\n               \"vmull.u16 q14, d8, d0\\n\\t\"\n               \"vshrn.i32 d20, q14, #8\\n\\t\"\n               \"vmull.u16 q14, d9, d1\\n\\t\"\n               \"vshrn.i32 d21, q14, #8\\n\\t\"\n               /* g */\n               \"vmull.u16 q14, d10, d2\\n\\t\"\n               \"vshrn.i32 d22, q14, #8\\n\\t\"\n               \"vmull.u16 q14, d11, d3\\n\\t\"\n               \"vshrn.i32 d23, q14, #8\\n\\t\"\n               /* r */\n               \"vmull.u16 q14, d12, d4\\n\\t\"\n               \"vshrn.i32 d24, q14, #8\\n\\t\"\n               \"vmull.u16 q14, d13, d5\\n\\t\"\n               \"vshrn.i32 d25, q14, #8\\n\\t\"\n               /* a */\n               \"vmull.u16 q14, d14, d6\\n\\t\"\n               \"vshrn.i32 d26, q14, #8\\n\\t\"\n               \"vmull.u16 q14, d15, d7\\n\\t\"\n               \"vshrn.i32 d27, q14, #8\\n\\t\"\n               /* if (!(D->RGB.a & 0xf000)) */\n               \"vand      q10, q9, q10\\n\\t\"\n               \"vand      q11, q9, q11\\n\\t\"\n               \"vand      q12, q9, q12\\n\\t\"\n               \"vand      q13, q9, q13\\n\\t\"\n               /* if ((D->RGB.a & 0xf000)) */\n               \"vceq.i16  q9, q9, #0\\n\\t\"\n               \"vand      q4, q9, q4\\n\\t\"\n               \"vand      q5, q9, q5\\n\\t\"\n               \"vand      q6, q9, q6\\n\\t\"\n               \"vand      q7, q9, q7\\n\\t\"\n               /* D: q4(b), q5(g), q6(r), q7(a) */\n               \"vorr      q4, q4, q10\\n\\t\"\n               \"vorr      q5, q5, q11\\n\\t\"\n               \"vorr      q6, q6, q12\\n\\t\"\n               \"vorr      q7, q7, q13\\n\\t\"\n               \"vst4.16   {d8, d10, d12, d14}, [r5]!\\n\\t\"\n               \"vst4.16   {d9, d11, d13, d15}, [r5]!\\n\\t\"\n               \"subs      %[l], %[l], #1\\n\\t\"\n               \"bne       1b\"\n               : /* no outputs */\n               : [Cacc_a] \"r\" (Cacc.RGB.a),\n                 [Cacc_r] \"r\" (Cacc.RGB.r), [Cacc_g] \"r\" (Cacc.RGB.g), [Cacc_b] \"r\" (Cacc.RGB.b),\n                 [D] \"r\" (D), [mask] \"r\" (mask), [l] \"r\" (l)\n               : \"memory\", \"r4\", \"r5\", \"d0\", \"d1\", \"d2\", \"d3\", \"d4\", \"d5\", \"d6\", \"d7\", \"d8\", \"d9\", \"d10\", \"d11\",\n                 \"d12\", \"d13\", \"d14\", \"d15\", \"d20\", \"d21\", \"d22\", \"d23\", \"d24\", \"d25\", \"d26\", \"d27\"\n          );\n     }\n}\n\nstatic void\nSCacc_add_to_Dacc_NEON( GenefxState *gfxs )\n{\n     int                l;\n     int                w     = gfxs->length;\n     GenefxAccumulator *D     = gfxs->Dacc;\n     GenefxAccumulator  SCacc = gfxs->SCacc;\n     u16                mask  = 0xf000;\n\n     l = w & 0x7;\n     while (l) {\n          if (!(D->RGB.a & 0xf000)) {\n               D->RGB.a += SCacc.RGB.a;\n               D->RGB.r += SCacc.RGB.r;\n               D->RGB.g += SCacc.RGB.g;\n               D->RGB.b += SCacc.RGB.b;\n          }\n\n          ++D;\n          --l;\n     }\n\n     l = w >> 3;\n     if (l) {\n          __asm__ __volatile__ (\n               \"mov       r4, %[D]\\n\\t\"\n               \"mov       r5, %[D]\\n\\t\"\n               \"vdup.16   q3, %[SCacc_a]\\n\\t\"\n               \"vdup.16   q2, %[SCacc_r]\\n\\t\"\n               \"vdup.16   q1, %[SCacc_g]\\n\\t\"\n               \"vdup.16   q0, %[SCacc_b]\\n\\t\"\n               \"vdup.16   q8, %[mask]\\n\\t\"\n               \"1:\\n\\t\"\n               \"pld       [r4, #0xC0]\\n\\t\"\n               \"pld       [r4, #0x100]\\n\\t\"\n               \"vld4.16   {d8, d10, d12, d14}, [r4]!\\n\\t\"\n               \"vld4.16   {d9, d11, d13, d15}, [r4]!\\n\\t\"\n               \"vand      q9, q7, q8\\n\\t\"\n               \"vceq.i16  q9, q9, #0\\n\\t\"\n               \"vand      q10, q9, q0\\n\\t\"\n               \"vand      q11, q9, q1\\n\\t\"\n               \"vand      q12, q9, q2\\n\\t\"\n               \"vand      q13, q9, q3\\n\\t\"\n               \"vadd.i16  q4, q4, q10\\n\\t\"\n               \"vadd.i16  q5, q5, q11\\n\\t\"\n               \"vadd.i16  q6, q6, q12\\n\\t\"\n               \"vadd.i16  q7, q7, q13\\n\\t\"\n               \"vst4.16   {d8, d10, d12, d14}, [r5]!\\n\\t\"\n               \"vst4.16   {d9, d11, d13, d15}, [r5]!\\n\\t\"\n               \"subs      %[l], %[l], #1\\n\\t\"\n               \"bne       1b\"\n               : /* no outputs */\n               : [SCacc_a] \"r\" (gfxs->SCacc.RGB.a),\n                 [SCacc_r] \"r\" (gfxs->SCacc.RGB.r), [SCacc_g] \"r\" (gfxs->SCacc.RGB.g), [SCacc_b] \"r\" (gfxs->SCacc.RGB.b),\n                 [D] \"r\" (D), [mask] \"r\" (mask), [l] \"r\" (l)\n               : \"memory\", \"r4\", \"r5\", \"d8\", \"d9\", \"d10\", \"d11\", \"d12\", \"d13\", \"d14\", \"d15\"\n          );\n     }\n}\n\nstatic void\nSacc_add_to_Dacc_NEON( GenefxState *gfxs )\n{\n     int                l;\n     int                w    = gfxs->length;\n     GenefxAccumulator *D    = gfxs->Dacc;\n     GenefxAccumulator *S    = gfxs->Sacc;\n     u16                mask = 0xf000;\n\n     l = w & 0x7;\n     while (l) {\n          if (!(D->RGB.a & 0xf000)) {\n               D->RGB.a += S->RGB.a;\n               D->RGB.r += S->RGB.r;\n               D->RGB.g += S->RGB.g;\n               D->RGB.b += S->RGB.b;\n          }\n\n          ++S;\n          ++D;\n          --l;\n     }\n\n     l = w >> 3;\n     if (l) {\n          __asm__ __volatile__ (\n               \"mov       r4, %[D]\\n\\t\"\n               \"mov       r5, %[S]\\n\\t\"\n               \"mov       r6, %[D]\\n\\t\"\n               \"vdup.16   q8, %[mask]\\n\\t\"\n               \"1:\\n\\t\"\n               \"pld       [r4, #0xC0]\\n\\t\"\n               \"pld       [r4, #0x100]\\n\\t\"\n               \"vld4.16   {d8, d10, d12, d14}, [r4]!\\n\\t\"\n               \"vld4.16   {d9, d11, d13, d15}, [r4]!\\n\\t\"\n               \"pld       [r5, #0xC0]\\n\\t\"\n               \"pld       [r5, #0x100]\\n\\t\"\n               \"vld4.16   {d0, d2, d4, d6}, [r5]!\\n\\t\"\n               \"vld4.16   {d1, d3, d5, d7}, [r5]!\\n\\t\"\n               \"vand      q9, q7, q8\\n\\t\"\n               \"vceq.i16  q9, q9, #0\\n\\t\"\n               \"vand      q0, q9, q0\\n\\t\"\n               \"vand      q1, q9, q1\\n\\t\"\n               \"vand      q2, q9, q2\\n\\t\"\n               \"vand      q3, q9, q3\\n\\t\"\n               \"vadd.i16  q4, q4, q0\\n\\t\"\n               \"vadd.i16  q5, q5, q1\\n\\t\"\n               \"vadd.i16  q6, q6, q2\\n\\t\"\n               \"vadd.i16  q7, q7, q3\\n\\t\"\n               \"vst4.16   {d8, d10, d12, d14}, [r6]!\\n\\t\"\n               \"vst4.16   {d9, d11, d13, d15}, [r6]!\\n\\t\"\n               \"subs      %[l], %[l], #1\\n\\t\"\n               \"bne       1b\"\n               : /* no outputs */\n               : [S] \"r\" (S), [D] \"r\" (D), [mask] \"r\" (mask), [l] \"r\" (l)\n               : \"memory\", \"r4\", \"r5\", \"r6\", \"d0\", \"d1\", \"d2\", \"d3\", \"d4\", \"d5\", \"d6\", \"d7\", \"d8\", \"d9\", \"d10\", \"d11\",\n                 \"d12\", \"d13\", \"d14\", \"d15\"\n          );\n     }\n}\n"
  },
  {
    "path": "src/gfx/generic/generic_stretch_blit.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <config.h>\n#include <core/state.h>\n#include <core/palette.h>\n#include <gfx/convert.h>\n#include <gfx/generic/generic.h>\n#include <gfx/generic/generic_util.h>\n#include <gfx/util.h>\n\n/**********************************************************************************************************************/\n\n#if DFB_SMOOTH_SCALING\n\ntypedef struct {\n     DFBRegion      clip;\n     const void    *colors;\n     unsigned long  protect;\n     unsigned long  key;\n} StretchCtx;\n\ntypedef void (*StretchHVx)( void             *dst,\n                            int               dpitch,\n                            const void       *src,\n                            int               spitch,\n                            int               width,\n                            int               height,\n                            int               dst_width,\n                            int               dst_height,\n                            const StretchCtx *ctx );\n\n#define STRETCH_NONE           0\n#define STRETCH_SRCKEY         1\n#define STRETCH_PROTECT        2\n#define STRETCH_SRCKEY_PROTECT 3\n#define STRETCH_NUM            4\n\ntypedef struct {\n     struct {\n          StretchHVx up[STRETCH_NUM];\n          StretchHVx down[STRETCH_NUM];\n     } f[DFB_NUM_PIXELFORMATS];\n} StretchFunctionTable;\n\n/**********************************************************************************************************************/\n/*** 16 bit RGB 565 scalers *******************************************************************************************/\n/**********************************************************************************************************************/\n\n#define DST_FORMAT              DSPF_RGB16\n#define TABLE_NAME              stretch_hvx_RGB16\n#define FUNC_NAME(UPDOWN,K,P,F) stretch_hvx_RGB16_ ## UPDOWN ## _ ## K ## P ## _ ## F\n#define SHIFT_R5                5\n#define SHIFT_R6                6\n#define X_F81F                  0xf81f\n#define X_07E0                  0x07e0\n#define MASK_RGB                0xffff\n\n#define FORMAT_RGB16\n#include \"stretch_up_down_16.h\"\n#undef FORMAT_RGB16\n\n#undef DST_FORMAT\n#undef TABLE_NAME\n#undef FUNC_NAME\n#undef SHIFT_R5\n#undef SHIFT_R6\n#undef X_F81F\n#undef X_07E0\n#undef MASK_RGB\n\n/**********************************************************************************************************************/\n/*** 32 bit RGB 888 scalers *******************************************************************************************/\n/**********************************************************************************************************************/\n\n#define DST_FORMAT              DSPF_RGB32\n#define TABLE_NAME              stretch_hvx_RGB32\n#define FUNC_NAME(UPDOWN,K,P,F) stretch_hvx_RGB32_ ## UPDOWN ## _ ## K ## P ## _ ## F\n#define SHIFT_R8                8\n#define SHIFT_L8                8\n#define X_00FF00FF              0x00ff00ff\n#define X_FF00FF00              0x0000ff00\n#define MASK_RGB                0x00ffffff\n\n#include \"stretch_up_down_32.h\"\n\n#undef DST_FORMAT\n#undef TABLE_NAME\n#undef FUNC_NAME\n#undef SHIFT_R8\n#undef SHIFT_L8\n#undef X_00FF00FF\n#undef X_FF00FF00\n#undef MASK_RGB\n\n/**********************************************************************************************************************/\n/*** 32 bit ARGB 8888 scalers *****************************************************************************************/\n/**********************************************************************************************************************/\n\n#define DST_FORMAT              DSPF_ARGB\n#define TABLE_NAME              stretch_hvx_ARGB\n#define FUNC_NAME(UPDOWN,K,P,F) stretch_hvx_ARGB_ ## UPDOWN ## _ ## K ## P ## _ ## F\n#define SHIFT_R8                8\n#define SHIFT_L8                8\n#define X_00FF00FF              0x00ff00ff\n#define X_FF00FF00              0xff00ff00\n#define MASK_RGB                0x00ffffff\n#define HAS_ALPHA\n\n#include \"stretch_up_down_32.h\"\n\n#undef DST_FORMAT\n#undef TABLE_NAME\n#undef FUNC_NAME\n#undef SHIFT_R8\n#undef SHIFT_L8\n#undef X_00FF00FF\n#undef X_FF00FF00\n#undef MASK_RGB\n#undef HAS_ALPHA\n\n/**********************************************************************************************************************/\n/*** 16 bit ARGB 4444 scalers *****************************************************************************************/\n/**********************************************************************************************************************/\n\n#define DST_FORMAT              DSPF_ARGB4444\n#define TABLE_NAME              stretch_hvx_ARGB4444\n#define FUNC_NAME(UPDOWN,K,P,F) stretch_hvx_ARGB4444_ ## UPDOWN ## _ ## K ## P ## _ ## F\n#define SHIFT_R5                4\n#define SHIFT_R6                4\n#define X_F81F                  0x0f0f\n#define X_07E0                  0xf0f0\n#define MASK_RGB                0x0fff\n#define HAS_ALPHA\n\n#define FORMAT_ARGB4444\n#include \"stretch_up_down_16.h\"\n#undef FORMAT_ARGB4444\n\n#undef DST_FORMAT\n#undef TABLE_NAME\n#undef FUNC_NAME\n#undef SHIFT_R5\n#undef SHIFT_R6\n#undef X_F81F\n#undef X_07E0\n#undef MASK_RGB\n#undef HAS_ALPHA\n\n/**********************************************************************************************************************/\n/*** 16 bit RGBA 4444 scalers *****************************************************************************************/\n/**********************************************************************************************************************/\n\n#define DST_FORMAT              DSPF_RGBA4444\n#define TABLE_NAME              stretch_hvx_RGBA4444\n#define FUNC_NAME(UPDOWN,K,P,F) stretch_hvx_RGBA4444_ ## UPDOWN ## _ ## K ## P ## _ ## F\n#define SHIFT_R5                4\n#define SHIFT_R6                4\n#define X_F81F                  0x0f0f\n#define X_07E0                  0xf0f0\n#define MASK_RGB                0xfff0\n#define HAS_ALPHA\n\n#include \"stretch_up_down_16.h\"\n\n#undef DST_FORMAT\n#undef TABLE_NAME\n#undef FUNC_NAME\n#undef SHIFT_R5\n#undef SHIFT_R6\n#undef X_F81F\n#undef X_07E0\n#undef MASK_RGB\n#undef HAS_ALPHA\n\nstatic const StretchFunctionTable *stretch_tables[DFB_NUM_PIXELFORMATS] = {\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1555)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]      = &stretch_hvx_RGB16,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB24)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]      = &stretch_hvx_RGB32,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]       = &stretch_hvx_ARGB,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ABGR)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A8)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YUY2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB332)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_UYVY)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_I420)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT8)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ALUT44)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV12)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)]   = &stretch_hvx_ARGB4444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)]   = &stretch_hvx_RGBA4444,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV21)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AYUV)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A4)]         = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB1666)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB6666)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB18)]      = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT1)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_LUT2)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB444)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR555)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBA5551)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y444)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_ARGB8565)]   = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_RGBAF88871)] = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_AVYU)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_VYU)]        = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)]     = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV16)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV61)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_Y42B)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_YV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV24)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_NV42)]       = NULL,\n     [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)]      = NULL,\n};\n\n/**********************************************************************************************************************/\n/*** NV12 / NV21 8 bit scalers ****************************************************************************************/\n/**********************************************************************************************************************/\n\n#define FUNC_NAME(UPDOWN) stretch_hvx_8_ ## UPDOWN\n\n#include \"stretch_up_down_8.h\"\n\n#undef FUNC_NAME\n\n#define FUNC_NAME(UPDOWN) stretch_hvx_88_ ## UPDOWN\n\n#include \"stretch_up_down_88.h\"\n\n#undef FUNC_NAME\n\n__attribute__((noinline))\nstatic bool\nstretch_hvx_planar( CardState    *state,\n                    DFBRectangle *srect,\n                    DFBRectangle *drect,\n                    bool          down )\n{\n     GenefxState *gfxs;\n     void        *dst;\n     void        *src;\n     DFBRegion    clip;\n\n     D_ASSERT( state != NULL );\n     DFB_RECTANGLE_ASSERT( srect );\n     DFB_RECTANGLE_ASSERT( drect );\n\n     gfxs = state->gfxs;\n\n     if (state->blittingflags)\n          return false;\n\n     if (gfxs->dst_format != gfxs->src_format)\n          return false;\n\n     clip = state->clip;\n\n     if (!dfb_region_rectangle_intersect( &clip, drect ))\n          return false;\n\n     dfb_region_translate( &clip, - drect->x, - drect->y );\n\n     dst = gfxs->dst_org[0] + drect->y * gfxs->dst_pitch + DFB_BYTES_PER_LINE( gfxs->dst_format, drect->x );\n     src = gfxs->src_org[0] + srect->y * gfxs->src_pitch + DFB_BYTES_PER_LINE( gfxs->src_format, srect->x );\n\n     switch (gfxs->dst_format) {\n          case DSPF_NV12:\n          case DSPF_NV21:\n               if (down)\n                    stretch_hvx_8_down( dst, gfxs->dst_pitch, src, gfxs->src_pitch,\n                                        srect->w, srect->h, drect->w, drect->h, &clip );\n               else\n                    stretch_hvx_8_up( dst, gfxs->dst_pitch, src, gfxs->src_pitch,\n                                      srect->w, srect->h, drect->w, drect->h, &clip );\n\n               clip.x1 /= 2;\n               clip.x2 /= 2;\n               clip.y1 /= 2;\n               clip.y2 /= 2;\n\n               dst = gfxs->dst_org[1] + drect->y/2 * gfxs->dst_pitch + DFB_BYTES_PER_LINE( gfxs->dst_format, drect->x );\n               src = gfxs->src_org[1] + srect->y/2 * gfxs->src_pitch + DFB_BYTES_PER_LINE( gfxs->src_format, srect->x );\n\n               if (down)\n                    stretch_hvx_88_down( dst, gfxs->dst_pitch, src, gfxs->src_pitch,\n                                         srect->w / 2, srect->h, drect->w / 2, drect->h, &clip );\n               else\n                    stretch_hvx_88_up( dst, gfxs->dst_pitch, src, gfxs->src_pitch,\n                                       srect->w / 2, srect->h, drect->w / 2, drect->h, &clip );\n               break;\n\n          default:\n               break;\n     }\n\n     return true;\n}\n\n__attribute__((noinline))\nstatic bool\nstretch_hvx( CardState    *state,\n             DFBRectangle *srect,\n             DFBRectangle *drect )\n{\n     GenefxState                *gfxs;\n     const StretchFunctionTable *table;\n     StretchHVx                  stretch;\n     void                       *dst;\n     void                       *src;\n     StretchCtx                  ctx;\n     u32                         colors[256];\n     bool                        down = false;\n     int                         idx  = STRETCH_NONE;\n\n     D_ASSERT( state != NULL );\n     DFB_RECTANGLE_ASSERT( srect );\n     DFB_RECTANGLE_ASSERT( drect );\n\n     gfxs = state->gfxs;\n\n     if (srect->w > drect->w && srect->h > drect->h)\n          down = true;\n\n     if (down) {\n          if (!(state->render_options & DSRO_SMOOTH_DOWNSCALE))\n               return false;\n     }\n     else {\n          if (!(state->render_options & DSRO_SMOOTH_UPSCALE))\n               return false;\n     }\n\n     switch (gfxs->dst_format) {\n          case DSPF_NV12:\n          case DSPF_NV21:\n               return stretch_hvx_planar( state, srect, drect, down );\n\n          default:\n               break;\n     }\n\n     if (state->blittingflags & ~(DSBLIT_COLORKEY_PROTECT | DSBLIT_SRC_COLORKEY | DSBLIT_SRC_PREMULTIPLY))\n          return false;\n\n     if (state->blittingflags & DSBLIT_SRC_PREMULTIPLY && !DFB_PIXELFORMAT_IS_INDEXED( gfxs->src_format ))\n          return false;\n\n     if (DFB_PIXELFORMAT_INDEX(gfxs->dst_format) >= D_ARRAY_SIZE(stretch_tables))\n          return false;\n\n     if (DFB_PIXELFORMAT_INDEX(gfxs->src_format) >= D_ARRAY_SIZE((stretch_tables[0])->f))\n          return false;\n\n     table = stretch_tables[DFB_PIXELFORMAT_INDEX(gfxs->dst_format)];\n     if (!table)\n          return false;\n\n     if (state->blittingflags & DSBLIT_SRC_COLORKEY)\n          idx |= STRETCH_SRCKEY;\n\n     if (state->blittingflags & DSBLIT_COLORKEY_PROTECT)\n          idx |= STRETCH_PROTECT;\n\n     if (down)\n          stretch = table->f[DFB_PIXELFORMAT_INDEX(gfxs->src_format)].down[idx];\n     else\n          stretch = table->f[DFB_PIXELFORMAT_INDEX(gfxs->src_format)].up[idx];\n\n     if (!stretch)\n          return false;\n\n     ctx.clip = state->clip;\n\n     if (!dfb_region_rectangle_intersect( &ctx.clip, drect ))\n          return false;\n\n     dfb_region_translate( &ctx.clip, - drect->x, - drect->y );\n\n     if (DFB_PIXELFORMAT_IS_INDEXED( gfxs->src_format )) {\n          int             i;\n          const DFBColor *entries;\n          u16            *colors16 = (void*) colors;\n\n          D_ASSERT( gfxs->Blut != NULL );\n\n          entries = gfxs->Blut->entries;\n\n          switch (gfxs->dst_format) {\n               case DSPF_ARGB:\n                    if (state->blittingflags & DSBLIT_SRC_PREMULTIPLY) {\n                         for (i = 0; i < gfxs->Blut->num_entries; i++) {\n                              int alpha = entries[i].a + 1;\n\n                              switch (alpha) {\n                                   case 0:\n                                        colors[i] = 0;\n                                        break;\n\n                                   case 255:\n                                        colors[i] = PIXEL_ARGB( entries[i].a,\n                                                                entries[i].r,\n                                                                entries[i].g,\n                                                                entries[i].b );\n                                        break;\n\n                                   default:\n                                        colors[i] = PIXEL_ARGB( entries[i].a,\n                                                                (alpha * entries[i].r) >> 8,\n                                                                (alpha * entries[i].g) >> 8,\n                                                                (alpha * entries[i].b) >> 8 );\n                              }\n                         }\n                    }\n                    else {\n                         for (i = 0; i < gfxs->Blut->num_entries; i++)\n                              colors[i] = PIXEL_ARGB( entries[i].a, entries[i].r, entries[i].g, entries[i].b );\n                    }\n                    break;\n\n               case DSPF_ABGR:\n                    if (state->blittingflags & DSBLIT_SRC_PREMULTIPLY) {\n                         for (i = 0; i < gfxs->Blut->num_entries; i++) {\n                              int alpha = entries[i].a + 1;\n\n                              switch (alpha) {\n                                   case 0:\n                                        colors[i] = 0;\n                                        break;\n\n                                   case 255:\n                                        colors[i] = PIXEL_ABGR( entries[i].a,\n                                                                entries[i].r,\n                                                                entries[i].g,\n                                                                entries[i].b );\n                                        break;\n\n                                   default:\n                                        colors[i] = PIXEL_ABGR( entries[i].a,\n                                                                (alpha * entries[i].r) >> 8,\n                                                                (alpha * entries[i].g) >> 8,\n                                                                (alpha * entries[i].b) >> 8 );\n                              }\n                         }\n                    }\n                    else {\n                         for (i = 0; i < gfxs->Blut->num_entries; i++)\n                              colors[i] = PIXEL_ABGR( entries[i].a, entries[i].r, entries[i].g, entries[i].b );\n                    }\n                    break;\n\n               case DSPF_RGBAF88871:\n                    if (state->blittingflags & DSBLIT_SRC_PREMULTIPLY) {\n                         for (i = 0; i < gfxs->Blut->num_entries; i++) {\n                              int alpha = entries[i].a + 1;\n\n                              switch (alpha) {\n                                   case 0:\n                                        colors[i] = 0;\n                                        break;\n\n                                   case 255:\n                                        colors[i] = PIXEL_RGBAF88871( entries[i].a,\n                                                                      entries[i].r,\n                                                                      entries[i].g,\n                                                                      entries[i].b );\n                                        break;\n\n                                   default:\n                                        colors[i] = PIXEL_RGBAF88871( entries[i].a,\n                                                                      (alpha * entries[i].r) >> 8,\n                                                                      (alpha * entries[i].g) >> 8,\n                                                                      (alpha * entries[i].b) >> 8 );\n                              }\n                         }\n                    }\n                    else {\n                         for (i = 0; i < gfxs->Blut->num_entries; i++)\n                              colors[i] = PIXEL_RGBAF88871( entries[i].a, entries[i].r, entries[i].g, entries[i].b );\n                    }\n                    break;\n\n               case DSPF_RGB32:\n                    for (i = 0; i < gfxs->Blut->num_entries; i++)\n                         colors[i] = PIXEL_RGB32( entries[i].r, entries[i].g, entries[i].b );\n                    break;\n\n               case DSPF_RGB16:\n                    for (i = 0; i < gfxs->Blut->num_entries; i++)\n                         colors16[i] = PIXEL_RGB16( entries[i].r, entries[i].g, entries[i].b );\n                    break;\n\n               case DSPF_ARGB4444:\n                    if (state->blittingflags & DSBLIT_SRC_PREMULTIPLY) {\n                         for (i = 0; i < gfxs->Blut->num_entries; i++) {\n                              int alpha = entries[i].a + 1;\n\n                              switch (alpha) {\n                                   case 0:\n                                        colors16[i] = 0;\n                                        break;\n\n                                   case 255:\n                                        colors16[i] = PIXEL_ARGB4444( entries[i].a,\n                                                                      entries[i].r,\n                                                                      entries[i].g,\n                                                                      entries[i].b );\n                                        break;\n\n                                   default:\n                                        colors16[i] = PIXEL_ARGB4444( entries[i].a,\n                                                                      (alpha * entries[i].r) >> 8,\n                                                                      (alpha * entries[i].g) >> 8,\n                                                                      (alpha * entries[i].b) >> 8 );\n                              }\n                         }\n                    }\n                    else {\n                         for (i = 0; i < gfxs->Blut->num_entries; i++)\n                              colors16[i] = PIXEL_ARGB4444( entries[i].a, entries[i].r, entries[i].g, entries[i].b );\n                    }\n                    break;\n\n               case DSPF_RGBA4444:\n                    if (state->blittingflags & DSBLIT_SRC_PREMULTIPLY) {\n                         for (i = 0; i < gfxs->Blut->num_entries; i++) {\n                              int alpha = entries[i].a + 1;\n\n                              switch (alpha) {\n                                   case 0:\n                                        colors16[i] = 0;\n                                        break;\n\n                                   case 255:\n                                        colors16[i] = PIXEL_RGBA4444( entries[i].a,\n                                                                      entries[i].r,\n                                                                      entries[i].g,\n                                                                      entries[i].b );\n                                        break;\n\n                                   default:\n                                        colors16[i] = PIXEL_RGBA4444( entries[i].a,\n                                                                      (alpha * entries[i].r) >> 8,\n                                                                      (alpha * entries[i].g) >> 8,\n                                                                      (alpha * entries[i].b) >> 8 );\n                              }\n                         }\n                    }\n                    else {\n                         for (i = 0; i < gfxs->Blut->num_entries; i++)\n                              colors16[i] = PIXEL_RGBA4444( entries[i].a, entries[i].r, entries[i].g, entries[i].b );\n                    }\n                    break;\n\n               case DSPF_RGB444:\n                    for (i = 0; i < gfxs->Blut->num_entries; i++)\n                         colors16[i] = PIXEL_RGB444( entries[i].r, entries[i].g, entries[i].b );\n                    break;\n\n               default:\n                    D_UNIMPLEMENTED();\n          }\n\n          ctx.colors = colors;\n\n          if (state->blittingflags & DSBLIT_SRC_COLORKEY) {\n               if (DFB_PIXELFORMAT_IS_INDEXED( gfxs->dst_format ))\n                    ctx.key = state->src_colorkey;\n               else {\n                    const DFBColor *color = &entries[state->src_colorkey % gfxs->Blut->num_entries];\n\n                    ctx.key = dfb_pixel_from_color( gfxs->dst_format, state->destination->config.colorspace, color );\n               }\n          }\n     }\n     else {\n          ctx.colors = NULL;\n\n          if (state->blittingflags & DSBLIT_SRC_COLORKEY) {\n               DFBColor color;\n\n               dfb_pixel_to_color( gfxs->src_format, state->source->config.colorspace, state->src_colorkey, &color );\n\n               ctx.key = dfb_pixel_from_color( gfxs->dst_format, state->destination->config.colorspace, &color );\n          }\n     }\n\n     if (state->blittingflags & DSBLIT_COLORKEY_PROTECT) {\n          if (DFB_PIXELFORMAT_IS_INDEXED( gfxs->dst_format ))\n               ctx.protect = state->colorkey.index;\n          else {\n               DFBColor color = { 0, state->colorkey.r, state->colorkey.g, state->colorkey.b };\n\n               ctx.protect = dfb_pixel_from_color( gfxs->dst_format, state->destination->config.colorspace, &color );\n          }\n     }\n\n     dst = gfxs->dst_org[0] + drect->y * gfxs->dst_pitch + DFB_BYTES_PER_LINE( gfxs->dst_format, drect->x );\n     src = gfxs->src_org[0] + srect->y * gfxs->src_pitch + DFB_BYTES_PER_LINE( gfxs->src_format, srect->x );\n\n     stretch( dst, gfxs->dst_pitch, src, gfxs->src_pitch, srect->w, srect->h, drect->w, drect->h, &ctx );\n\n     return true;\n}\n\n#endif /* DFB_SMOOTH_SCALING */\n\n/**********************************************************************************************************************/\n\ntypedef void (*XopAdvanceFunc)( GenefxState *gfxs );\n\nvoid\ngStretchBlit( CardState    *state,\n              DFBRectangle *srect,\n              DFBRectangle *drect )\n{\n     GenefxState             *gfxs;\n     XopAdvanceFunc           Aop_advance;\n     XopAdvanceFunc           Bop_advance;\n     int                      Aop_X;\n     int                      Aop_Y;\n     int                      Bop_X;\n     int                      Bop_Y;\n     int                      fx, fy;\n     int                      ix, iy;\n     int                      h;\n     DFBRectangle             orect = *drect;\n     bool                     rotated = false;\n     DFBSurfaceBlittingFlags  rotflip_blittingflags;\n\n     D_ASSERT( state != NULL );\n     D_ASSERT( state->gfxs != NULL );\n\n     gfxs = state->gfxs;\n\n     rotflip_blittingflags = state->blittingflags;\n\n     dfb_simplify_blittingflags( &rotflip_blittingflags );\n     rotflip_blittingflags &= (DSBLIT_FLIP_HORIZONTAL | DSBLIT_FLIP_VERTICAL | DSBLIT_ROTATE90 );\n\n     if (rotflip_blittingflags & DSBLIT_ROTATE90)\n          rotated = true;\n\n     if (dfb_config->software_warn) {\n          D_WARN( \"StretchBlit (%4d,%4d-%4dx%4d) %6s, flags 0x%08x, color 0x%02x%02x%02x%02x <- (%4d,%4d-%4dx%4d) %6s\",\n                  drect->x, drect->y, drect->w, drect->h, dfb_pixelformat_name( gfxs->dst_format ),\n                  state->blittingflags, state->color.a, state->color.r, state->color.g, state->color.b,\n                  srect->x, srect->y, srect->w, srect->h, dfb_pixelformat_name( gfxs->src_format ) );\n     }\n\n     CHECK_PIPELINE();\n\n#if DFB_SMOOTH_SCALING\n     if (state->render_options & (DSRO_SMOOTH_UPSCALE | DSRO_SMOOTH_DOWNSCALE) && stretch_hvx( state, srect, drect ))\n          return;\n#endif\n\n     /* Clip destination rectangle. */\n     if (!dfb_rectangle_intersect_by_region( drect, &state->clip ))\n          return;\n\n     /* Calculate fractions */\n     if (rotated) {\n          fx = (srect->h << 16) / orect.w;\n          fy = (srect->w << 16) / orect.h;\n     }\n     else {\n          fx = (srect->w << 16) / orect.w;\n          fy = (srect->h << 16) / orect.h;\n     }\n\n     /* Calculate horizontal and vertical phase. */\n\n     switch (rotflip_blittingflags & (DSBLIT_FLIP_HORIZONTAL | DSBLIT_FLIP_VERTICAL | DSBLIT_ROTATE90)) {\n          case DSBLIT_NOFX:\n               ix = fx * (drect->x - orect.x);\n               iy = fy * (drect->y - orect.y);\n               break;\n          case DSBLIT_FLIP_HORIZONTAL:\n               ix = fx * ((orect.x + orect.w - 1) - (drect->x + drect->w - 1));\n               iy = fy * (drect->y - orect.y);\n               break;\n          case DSBLIT_FLIP_VERTICAL:\n               ix = fx * (drect->x - orect.x);\n               iy = fy * ((orect.y + orect.h - 1) - (drect->y + drect->h - 1));\n               break;\n          case DSBLIT_ROTATE90:\n               ix = fx * (drect->x - orect.x);\n               iy = fy * ((orect.y + orect.h - 1) - (drect->y + drect->h - 1));\n               break;\n          case DSBLIT_FLIP_HORIZONTAL | DSBLIT_FLIP_VERTICAL: /* ROTATE180 */\n               ix = fx * ((orect.x + orect.w - 1) - (drect->x + drect->w - 1));\n               iy = fy * ((orect.y + orect.h - 1) - (drect->y + drect->h - 1));\n               break;\n          case DSBLIT_ROTATE90 | DSBLIT_FLIP_VERTICAL | DSBLIT_FLIP_HORIZONTAL: /* ROTATE270 */\n               ix = fx * ((orect.x + orect.w - 1) - (drect->x + drect->w - 1));\n               iy = fy * (drect->y - orect.y);\n               break;\n          case DSBLIT_ROTATE90 | DSBLIT_FLIP_HORIZONTAL:\n               ix = fx * (drect->x - orect.x);\n               iy = fy * (drect->y - orect.y);\n               break;\n          case DSBLIT_ROTATE90 | DSBLIT_FLIP_VERTICAL:\n               ix = fx * ((orect.x + orect.w - 1) - (drect->x + drect->w - 1));\n               iy = fy * ((orect.y + orect.h - 1) - (drect->y + drect->h - 1));\n               break;\n          default:\n              ix = 0;\n              iy = 0;\n     }\n\n     /* Adjust source size. */\n     if (rotated) {\n          srect->x += iy >> 16;\n          srect->y += ix >> 16;\n          ix &= 0xffff;\n          iy &= 0xffff;\n          srect->w = ((drect->h * fy + iy) + 0xffff) >> 16;\n          srect->h = ((drect->w * fx + ix) + 0xffff) >> 16;\n     }\n     else {\n          srect->x += ix >> 16;\n          srect->y += iy >> 16;\n          ix &= 0xffff;\n          iy &= 0xffff;\n          srect->w = ((drect->w * fx + ix) + 0xffff) >> 16;\n          srect->h = ((drect->h * fy + iy) + 0xffff) >> 16;\n     }\n\n     D_ASSERT( srect->x + srect->w <= state->source->config.size.w );\n     D_ASSERT( srect->y + srect->h <= state->source->config.size.h );\n     D_ASSERT( drect->x + drect->w <= state->clip.x2 + 1 );\n     D_ASSERT( drect->y + drect->h <= state->clip.y2 + 1 );\n\n     if (!Genefx_ABacc_prepare( gfxs, MAX( srect->w, drect->w ) ))\n          return;\n\n     switch (gfxs->src_format) {\n          case DSPF_A4:\n          case DSPF_YUY2:\n          case DSPF_UYVY:\n               srect->x &= ~1;\n               break;\n          default:\n               break;\n     }\n\n     switch (gfxs->dst_format) {\n          case DSPF_A4:\n          case DSPF_YUY2:\n          case DSPF_UYVY:\n               drect->x &= ~1;\n               break;\n          default:\n               break;\n     }\n\n     if (rotated) {\n          gfxs->Dlen   = drect->h;\n          gfxs->SperD  = fy;\n          gfxs->Xphase = iy;\n\n          h = drect->w;\n     }\n     else {\n          gfxs->Dlen   = drect->w;\n          gfxs->SperD  = fx;\n          gfxs->Xphase = ix;\n\n          h = drect->h;\n     }\n\n     gfxs->Slen   = srect->w;\n     gfxs->length = gfxs->Dlen;\n\n     Aop_X = drect->x;\n     Aop_Y = drect->y;\n\n     Bop_X = srect->x;\n     Bop_Y = srect->y;\n\n     Bop_advance = Genefx_Bop_next;\n     Aop_advance = Genefx_Aop_next;\n\n     switch ((unsigned int) rotflip_blittingflags) {\n          case DSBLIT_FLIP_HORIZONTAL:\n               gfxs->Astep *= -1;\n               Aop_X += (drect->w - 1);\n               break;\n\n          case DSBLIT_FLIP_VERTICAL:\n               Aop_Y += (drect->h - 1);\n               Aop_advance = Genefx_Aop_prev;\n               break;\n\n          case DSBLIT_ROTATE90:\n               Aop_Y = drect->y + drect->h - 1;\n               gfxs->Astep *= -gfxs->dst_pitch / gfxs->dst_bpp;\n               Aop_advance = Genefx_Aop_crab;\n               break;\n\n          case DSBLIT_FLIP_VERTICAL | DSBLIT_FLIP_HORIZONTAL: /* ROTATE180 */\n               gfxs->Astep *= -1;\n               Aop_X += (drect->w - 1);\n               Aop_Y += (drect->h - 1);\n               Aop_advance = Genefx_Aop_prev;\n               break;\n\n          case DSBLIT_ROTATE90 | DSBLIT_FLIP_HORIZONTAL | DSBLIT_FLIP_VERTICAL: /* ROTATE270 */\n               gfxs->Astep *= gfxs->dst_pitch / gfxs->dst_bpp;\n               Bop_Y = srect->y + srect->h - 1;\n               Aop_advance = Genefx_Aop_crab;\n               Bop_advance = Genefx_Bop_prev;\n               break;\n\n          case DSBLIT_ROTATE90 | DSBLIT_FLIP_VERTICAL:\n               gfxs->Astep *= -gfxs->dst_pitch / gfxs->dst_bpp;\n               Aop_X = drect->x + drect->w - 1;\n               Aop_Y = drect->y + drect->h - 1;\n               Aop_advance = Genefx_Aop_prev_crab;\n               break;\n\n          case DSBLIT_ROTATE90 | DSBLIT_FLIP_HORIZONTAL:\n               gfxs->Astep *= gfxs->dst_pitch / gfxs->dst_bpp;\n               Aop_advance = Genefx_Aop_crab;\n               break;\n\n          default:\n               break;\n     }\n\n     Genefx_Aop_xy( gfxs, Aop_X, Aop_Y );\n     Genefx_Bop_xy( gfxs, Bop_X, Bop_Y );\n\n     while (h--) {\n          RUN_PIPELINE();\n\n          Aop_advance( gfxs );\n\n          iy += rotated ? fx : fy;\n\n          while (iy > 0xffff) {\n               iy -= 0x10000;\n               Bop_advance( gfxs );\n          }\n     }\n\n     Genefx_ABacc_flush( gfxs );\n}\n"
  },
  {
    "path": "src/gfx/generic/generic_stretch_blit.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __GENERIC_STRETCH_BLIT_H__\n#define __GENERIC_STRETCH_BLIT_H__\n\n#include <core/coretypes.h>\n\n/**********************************************************************************************************************/\n\nvoid gStretchBlit( CardState    *state,\n                   DFBRectangle *srect,\n                   DFBRectangle *drect );\n\n#endif\n"
  },
  {
    "path": "src/gfx/generic/generic_texture_triangles.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/state.h>\n#include <gfx/generic/generic.h>\n#include <gfx/generic/generic_texture_triangles.h>\n#include <gfx/generic/generic_util.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n   int xi;\n   int xf;\n   int mi;\n   int mf;\n   int _2dy;\n} DDA;\n\n#define SETUP_DDA(xs,ys,xe,ye,dda)           \\\n     do {                                    \\\n          int dx = (xe) - (xs);              \\\n          int dy = (ye) - (ys);              \\\n          dda.xi = (xs);                     \\\n          if (dy != 0) {                     \\\n               dda.mi = dx / dy;             \\\n               dda.mf = 2 * (dx % dy);       \\\n               dda.xf = -dy;                 \\\n               dda._2dy = 2 * dy;            \\\n               if (dda.mf < 0) {             \\\n                    dda.mf += 2 * ABS( dy ); \\\n                    dda.mi--;                \\\n               }                             \\\n          }                                  \\\n          else {                             \\\n               dda.mi = 0;                   \\\n               dda.mf = 0;                   \\\n               dda.xf = 0;                   \\\n               dda._2dy = 0;                 \\\n          }                                  \\\n     } while (0)\n\n#define INC_DDA(dda)                         \\\n     do {                                    \\\n          dda.xi += dda.mi;                  \\\n          dda.xf += dda.mf;                  \\\n          if (dda.xf > 0) {                  \\\n               dda.xi++;                     \\\n               dda.xf -= dda._2dy;           \\\n          }                                  \\\n     } while (0)\n\nstatic void\nGenefx_TextureTriangleAffine( GenefxState        *gfxs,\n                              GenefxVertexAffine *v0,\n                              GenefxVertexAffine *v1,\n                              GenefxVertexAffine *v2,\n                              const DFBRegion    *clip )\n{\n     /* All points on one horizontal line. */\n     if (v0->y == v1->y && v1->y == v2->y)\n          return;\n\n     GenefxVertexAffine *v_tmp;\n\n     /* Triangle sorting (vertical). */\n     if (v1->y < v0->y) {\n          v_tmp = v0;\n          v0    = v1;\n          v1    = v_tmp;\n     }\n     if (v2->y < v0->y) {\n          v_tmp = v2;\n          v2 = v1;\n          v1 = v0;\n          v0 = v_tmp;\n     }\n     else if (v2->y < v1->y) {\n          v_tmp = v1;\n          v1    = v2;\n          v2    = v_tmp;\n     }\n\n     int y_top    = v0->y;\n     int y_bottom = v2->y;\n\n     /* Totally clipped (vertical). */\n     if (y_top > clip->y2 || y_bottom < clip->y1)\n          return;\n\n     /* Totally clipped right. */\n     if (v0->x > clip->x2 && v1->x > clip->x2 && v2->x > clip->x2)\n          return;\n\n     /* Totally clipped left. */\n     if (v0->x < clip->x1 && v1->x < clip->x1 && v2->x < clip->x1)\n          return;\n\n     int y_update = -1;\n\n     /* Triangle Sorting (horizontal). */\n     if (v0->y == v1->y) {\n          if (v0->x > v1->x) {\n               v_tmp = v0;\n               v0    = v1;\n               v1    = v_tmp;\n          }\n     }\n     else if (v1->y == v2->y) {\n          if (v1->x > v2->x) {\n               v_tmp = v1;\n               v1    = v2;\n               v2    = v_tmp;\n          }\n     }\n     else\n          y_update = v1->y;\n\n     /* Triangle Setup. */\n\n     int height      = v2->y - v0->y;\n     int half_top    = v1->y - v0->y;\n     int half_bottom = v2->y - v1->y;\n     int y;\n     int sl, sr;\n     int tl, tr;\n     int dsl, dsr;\n     int dtl, dtr;\n     int dsl2, dsr2;\n     int dtl2, dtr2;\n\n     /* Flat top. */\n     if (v0->y == v1->y) {\n          /* Top points equal. */\n          if (v0->x == v1->x)\n               return;\n\n          sl = v0->s;\n          sr = v1->s;\n\n          dsl = dsl2 = (v2->s - sl) / height;\n          dsr = dsr2 = (v2->s - sr) / height;\n\n          tl = v0->t;\n          tr = v1->t;\n\n          dtl = dtl2 = (v2->t - tl) / height;\n          dtr = dtr2 = (v2->t - tr) / height;\n     }\n     /* Flat bottom. */\n     else if (v1->y == v2->y) {\n          /* Bottom points equal. */\n          if (v1->x == v2->x)\n               return;\n\n          sl = sr = v0->s;\n\n          dsl = dsl2 = (v1->s - sl) / height;\n          dsr = dsr2 = (v2->s - sr) / height;\n\n          tl = tr = v0->t;\n\n          dtl = dtl2 = (v1->t - tl) / height;\n          dtr = dtr2 = (v2->t - tr) / height;\n     }\n     /* Two parts. */\n     else {\n          sl = sr = v0->s;\n          tl = tr = v0->t;\n\n          int x_v1 = v0->x + (v2->x - v0->x) * (v1->y - v0->y) / height;\n\n          /* Update left. */\n          if (x_v1 > v1->x) {\n               dsl = (v1->s - sl) / half_top;\n               dsr = (v2->s - sr) / height;\n\n               dsl2 = (v2->s - v1->s) / half_bottom;\n               dsr2 = dsr;\n\n               dtl = (v1->t - tl) / half_top;\n               dtr = (v2->t - tr) / height;\n\n               dtl2 = (v2->t - v1->t) / half_bottom;\n               dtr2 = dtr;\n          }\n          /* Update right. */\n          else if (x_v1 < v1->x) {\n               dsl = (v2->s - sl) / height;\n               dsr = (v1->s - sr) / half_top;\n\n               dsl2 = dsl;\n               dsr2 = (v2->s - v1->s) / half_bottom;\n\n               dtl = (v2->t - tl) / height;\n               dtr = (v1->t - tr) / half_top;\n\n               dtl2 = dtl;\n               dtr2 = (v2->t - v1->t) / half_bottom;\n          }\n          /* All points on one line. */\n          else\n               return;\n     }\n\n     DDA dda1 = { .xi = 0 }, dda2 = { .xi = 0 };\n\n     SETUP_DDA( v0->x, v0->y, v2->x, v2->y, dda1 );\n     SETUP_DDA( v0->x, v0->y, v1->x, v1->y, dda2 );\n\n     /* Vertical clipping. */\n\n     if (y_top < clip->y1) {\n          y_top = clip->y1;\n     }\n\n     if (y_bottom > clip->y2) {\n          y_bottom = clip->y2;\n     }\n\n     if (y_top > v0->y) {\n          for (y = v0->y; y < y_top; y++) {\n               if (y == v1->y)\n                    SETUP_DDA( v1->x, v1->y, v2->x, v2->y, dda2 );\n\n               INC_DDA( dda1 );\n               INC_DDA( dda2 );\n          }\n\n          /* Two parts. */\n          if (y_update != -1 && y_top > y_update) {\n               sl += dsl * (y_update - v0->y) + dsl2 * (y_top - v1->y);\n               sr += dsr * (y_update - v0->y) + dsr2 * (y_top - v1->y);\n\n               tl += dtl * (y_update - v0->y) + dtl2 * (y_top - v1->y);\n               tr += dtr * (y_update - v0->y) + dtr2 * (y_top - v1->y);\n\n               dsl = dsl2;\n               dsr = dsr2;\n\n               dtl = dtl2;\n               dtr = dtr2;\n          }\n          /* One part or only top clipped. */\n          else {\n               sl += dsl * (y_top - v0->y);\n               sr += dsr * (y_top - v0->y);\n\n               tl += dtl * (y_top - v0->y);\n               tr += dtr * (y_top - v0->y);\n          }\n     }\n\n     /* Loop over clipped lines. */\n     for (y = y_top; y <= y_bottom; y++) {\n          /* Slope update (for bottom half). */\n          if (y == y_update) {\n               dsl = dsl2;\n               dtl = dtl2;\n\n               dsr = dsr2;\n               dtr = dtr2;\n          }\n\n          if (y == v1->y)\n               SETUP_DDA( v1->x, v1->y, v2->x, v2->y, dda2 );\n\n          int len = ABS( dda1.xi - dda2.xi );\n          int x1  = MIN( dda1.xi, dda2.xi );\n          int x2  = x1 + len - 1;\n\n          if (len > 0 && x1 <= clip->x2 && x2 >= clip->x1) {\n               int csl   = sl;\n               int ctl   = tl;\n               int SperD = (sr - sl) / len;\n               int TperD = (tr - tl) / len;\n\n               /* Horizontal clipping. */\n\n               if (x1 < clip->x1) {\n                    csl += SperD * (clip->x1 - x1);\n                    ctl += TperD * (clip->x1 - x1);\n\n                    x1 = clip->x1;\n               }\n\n               if (x2 > clip->x2) {\n                    x2 = clip->x2;\n               }\n\n               gfxs->Dlen   = x2 - x1 + 1;\n               gfxs->length = gfxs->Dlen;\n               gfxs->SperD  = SperD;\n               gfxs->TperD  = TperD;\n               gfxs->s      = csl;\n               gfxs->t      = ctl;\n\n               Genefx_Aop_xy( gfxs, x1, y );\n\n               RUN_PIPELINE();\n          }\n\n          sl += dsl;\n          sr += dsr;\n\n          tl += dtl;\n          tr += dtr;\n\n          INC_DDA( dda1 );\n          INC_DDA( dda2 );\n     }\n}\n\nvoid\nGenefx_TextureTrianglesAffine( CardState            *state,\n                               GenefxVertexAffine   *vertices,\n                               int                   num,\n                               DFBTriangleFormation  formation,\n                               const DFBRegion      *clip )\n{\n     GenefxState *gfxs;\n     int          index = 0;\n\n     D_ASSERT( state != NULL );\n     D_ASSERT( state->gfxs != NULL );\n\n     gfxs = state->gfxs;\n\n     CHECK_PIPELINE();\n\n     if (!Genefx_ABacc_prepare( gfxs, state->destination->config.size.w ))\n          return;\n\n     /* Reset Bop to 0,0 as texture lookup accesses the whole buffer arbitrarily. */\n     Genefx_Bop_xy( gfxs, 0, 0 );\n\n     /* Render triangles. */\n     for (index = 0; index < num;) {\n          GenefxVertexAffine *v[3];\n\n          if (index == 0) {\n               v[0] = &vertices[index+0];\n               v[1] = &vertices[index+1];\n               v[2] = &vertices[index+2];\n\n               index += 3;\n          }\n          else {\n               switch (formation) {\n                    case DTTF_LIST:\n                         v[0] = &vertices[index+0];\n                         v[1] = &vertices[index+1];\n                         v[2] = &vertices[index+2];\n\n                         index += 3;\n                         break;\n\n                    case DTTF_STRIP:\n                         v[0] = &vertices[index-2];\n                         v[1] = &vertices[index-1];\n                         v[2] = &vertices[index+0];\n\n                         index += 1;\n                         break;\n\n                    case DTTF_FAN:\n                         v[0] = &vertices[0];\n                         v[1] = &vertices[index-1];\n                         v[2] = &vertices[index+0];\n\n                         index += 1;\n                         break;\n\n                    default:\n                         D_BUG( \"unknown formation %u\", formation );\n                         Genefx_ABacc_flush( gfxs );\n                         return;\n               }\n          }\n\n          if (dfb_config->software_warn) {\n               D_WARN( \"TexTriangles (%d,%d-%d,%d-%d,%d) %6s, flags 0x%08x, color 0x%02x%02x%02x%02x <- (%4d,%4d) %6s\",\n                       v[0]->x, v[0]->y, v[1]->x, v[1]->y, v[2]->x, v[2]->y, dfb_pixelformat_name( gfxs->dst_format ),\n                       state->blittingflags, state->color.a, state->color.r, state->color.g, state->color.b,\n                       state->source->config.size.w, state->source->config.size.h,\n                       dfb_pixelformat_name( gfxs->src_format ) );\n          }\n\n          Genefx_TextureTriangleAffine( gfxs, v[0], v[1], v[2], clip );\n     }\n\n     Genefx_ABacc_flush( gfxs );\n}\n"
  },
  {
    "path": "src/gfx/generic/generic_texture_triangles.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __GENERIC_TEXTURE_TRIANGLES_H__\n#define __GENERIC_TEXTURE_TRIANGLES_H__\n\n#include <core/coretypes.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int x;\n     int y;\n     int s;\n     int t;\n} GenefxVertexAffine;\n\n/**********************************************************************************************************************/\n\nvoid Genefx_TextureTrianglesAffine( CardState            *state,\n                                    GenefxVertexAffine   *vertices,\n                                    int                   num,\n                                    DFBTriangleFormation  formation,\n                                    const DFBRegion      *clip );\n\n#endif\n"
  },
  {
    "path": "src/gfx/generic/generic_util.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <gfx/generic/generic.h>\n#include <gfx/generic/generic_util.h>\n\n/**********************************************************************************************************************/\n\nvoid\nGenefx_Aop_crab( GenefxState *gfxs )\n{\n     gfxs->Aop[0] += gfxs->dst_bpp;\n     gfxs->AopY++;\n}\n\nvoid\nGenefx_Aop_prev_crab( GenefxState *gfxs )\n{\n     gfxs->Aop[0] -= gfxs->dst_bpp;\n     gfxs->AopY++;\n}\n\nvoid\nGenefx_Aop_xy( GenefxState *gfxs,\n               int          x,\n               int          y )\n{\n     int pitch = gfxs->dst_pitch;\n\n     gfxs->Aop[0] = gfxs->dst_org[0];\n     gfxs->AopY   = y;\n\n     if (gfxs->dst_caps & DSCAPS_SEPARATED) {\n          gfxs->Aop_field = y & 1;\n          if (gfxs->Aop_field)\n               gfxs->Aop[0] += gfxs->dst_field_offset;\n\n          y /= 2;\n     }\n\n     D_ASSUME( !(x & DFB_PIXELFORMAT_ALIGNMENT( gfxs->dst_format )) );\n\n     gfxs->Aop[0] += y * pitch + DFB_BYTES_PER_LINE( gfxs->dst_format, x );\n\n     if (DFB_PLANAR_PIXELFORMAT(gfxs->dst_format)) {\n          int dst_field_offset = gfxs->dst_field_offset;\n\n          switch (gfxs->dst_format) {\n               case DSPF_I420:\n               case DSPF_YV12:\n                    dst_field_offset /= 4;\n                    pitch /= 2;\n                    y /= 2;\n                    x /= 2;\n                    break;\n               case DSPF_Y42B:\n               case DSPF_YV16:\n                    dst_field_offset /= 2;\n                    pitch /= 2;\n                    x /= 2;\n                    break;\n               case DSPF_NV12:\n               case DSPF_NV21:\n                    dst_field_offset /= 2;\n                    y /= 2;\n               case DSPF_NV16:\n               case DSPF_NV61:\n                    x &= ~1;\n                    break;\n               case DSPF_Y444:\n               case DSPF_YV24:\n               case DSPF_NV24:\n               case DSPF_NV42:\n                    /* nothing to adjust */\n               default:\n                    break;\n          }\n\n          gfxs->Aop[1] = gfxs->dst_org[1];\n          gfxs->Aop[2] = gfxs->dst_org[2];\n\n          if (gfxs->dst_caps & DSCAPS_SEPARATED && gfxs->Aop_field) {\n               gfxs->Aop[1] += dst_field_offset;\n               gfxs->Aop[2] += dst_field_offset;\n          }\n\n          gfxs->Aop[1] += y * pitch + x;\n          gfxs->Aop[2] += y * pitch + x;\n\n          if (gfxs->dst_format == DSPF_NV24 || gfxs->dst_format == DSPF_NV42)\n               gfxs->Aop[1] += y * pitch + x;\n     }\n}\n\nvoid\nGenefx_Aop_next( GenefxState *gfxs )\n{\n     int pitch = gfxs->dst_pitch;\n\n     if (gfxs->dst_caps & DSCAPS_SEPARATED) {\n          gfxs->Aop_field++;\n\n          if (gfxs->Aop_field & 1)\n               gfxs->Aop[0] += gfxs->dst_field_offset;\n          else\n               gfxs->Aop[0] += pitch - gfxs->dst_field_offset;\n     }\n     else\n          gfxs->Aop[0] += pitch;\n\n     if (DFB_PLANAR_PIXELFORMAT(gfxs->dst_format)) {\n          if (gfxs->dst_format == DSPF_I420 || gfxs->dst_format == DSPF_YV12) {\n               if (gfxs->AopY & 1) {\n                    if (gfxs->dst_caps & DSCAPS_SEPARATED) {\n                         if (gfxs->Aop_field & 2) {\n                              gfxs->Aop[1] += gfxs->dst_field_offset / 4;\n                              gfxs->Aop[2] += gfxs->dst_field_offset / 4;\n                         }\n                         else {\n                              gfxs->Aop[1] += pitch / 2 - gfxs->dst_field_offset / 4;\n                              gfxs->Aop[2] += pitch / 2 - gfxs->dst_field_offset / 4;\n                         }\n                    }\n                    else {\n                         gfxs->Aop[1] += pitch / 2;\n                         gfxs->Aop[2] += pitch / 2;\n                    }\n               }\n          }\n          else if (gfxs->dst_format == DSPF_Y42B || gfxs->dst_format == DSPF_YV16) {\n               if (gfxs->dst_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Aop_field & 2) {\n                         gfxs->Aop[1] += gfxs->dst_field_offset / 2;\n                         gfxs->Aop[2] += gfxs->dst_field_offset / 2;\n                    }\n                    else {\n                         gfxs->Aop[1] += pitch / 2 - gfxs->dst_field_offset / 2;\n                         gfxs->Aop[2] += pitch / 2 - gfxs->dst_field_offset / 2;\n                    }\n               }\n               else {\n                    gfxs->Aop[1] += pitch / 2;\n                    gfxs->Aop[2] += pitch / 2;\n               }\n          }\n          else if (gfxs->dst_format == DSPF_Y444 || gfxs->dst_format == DSPF_YV24) {\n               if (gfxs->dst_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Aop_field & 1) {\n                         gfxs->Aop[1] += gfxs->dst_field_offset;\n                         gfxs->Aop[2] += gfxs->dst_field_offset;\n                    }\n                    else {\n                         gfxs->Aop[1] += pitch - gfxs->dst_field_offset;\n                         gfxs->Aop[2] += pitch - gfxs->dst_field_offset;\n                    }\n               }\n               else {\n                    gfxs->Aop[1] += pitch;\n                    gfxs->Aop[2] += pitch;\n               }\n          }\n          else if (gfxs->dst_format == DSPF_NV12 || gfxs->dst_format == DSPF_NV21) {\n               if (gfxs->AopY & 1) {\n                    if (gfxs->dst_caps & DSCAPS_SEPARATED) {\n                         if (gfxs->Aop_field & 2)\n                              gfxs->Aop[1] += gfxs->dst_field_offset / 2;\n                         else\n                              gfxs->Aop[1] += pitch - gfxs->dst_field_offset / 2;\n                    }\n                    else {\n                         gfxs->Aop[1] += pitch;\n                    }\n               }\n          }\n          else if (gfxs->dst_format == DSPF_NV16 || gfxs->dst_format == DSPF_NV61) {\n               if (gfxs->dst_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Aop_field & 1)\n                         gfxs->Aop[1] += gfxs->dst_field_offset;\n                    else\n                         gfxs->Aop[1] += pitch - gfxs->dst_field_offset;\n               }\n               else {\n                    gfxs->Aop[1] += pitch;\n               }\n          }\n          else { /* DSPF_NV24 || DSPF_NV42 */\n               if (gfxs->dst_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Aop_field & 1)\n                         gfxs->Aop[1] += gfxs->dst_field_offset * 2;\n                    else\n                         gfxs->Aop[1] += pitch - gfxs->dst_field_offset * 2;\n               }\n               else {\n                    gfxs->Aop[1] += pitch * 2;\n               }\n          }\n     }\n\n     gfxs->AopY++;\n}\n\nvoid\nGenefx_Aop_prev( GenefxState *gfxs )\n{\n     int pitch = gfxs->dst_pitch;\n\n     if (gfxs->dst_caps & DSCAPS_SEPARATED) {\n          gfxs->Aop_field++;\n\n          if (gfxs->Aop_field & 1)\n               gfxs->Aop[0] += gfxs->dst_field_offset - pitch;\n          else\n               gfxs->Aop[0] -= gfxs->dst_field_offset;\n     }\n     else\n          gfxs->Aop[0] -= pitch;\n\n     if (DFB_PLANAR_PIXELFORMAT(gfxs->dst_format)) {\n          if (gfxs->dst_format == DSPF_I420 || gfxs->dst_format == DSPF_YV12) {\n               if (gfxs->AopY & 1) {\n                    if (gfxs->dst_caps & DSCAPS_SEPARATED) {\n                         if (gfxs->Aop_field & 2) {\n                              gfxs->Aop[1] += gfxs->dst_field_offset / 4 - pitch / 2;\n                              gfxs->Aop[2] += gfxs->dst_field_offset / 4 - pitch / 2;\n                         }\n                         else {\n                              gfxs->Aop[1] -= gfxs->dst_field_offset / 4;\n                              gfxs->Aop[2] -= gfxs->dst_field_offset / 4;\n                         }\n                    }\n                    else {\n                         gfxs->Aop[1] -= pitch / 2;\n                         gfxs->Aop[2] -= pitch / 2;\n                    }\n               }\n          }\n          else if (gfxs->dst_format == DSPF_Y42B || gfxs->dst_format == DSPF_YV16) {\n               if (gfxs->dst_caps & DSCAPS_SEPARATED) {\n                   if (gfxs->Aop_field & 2) {\n                        gfxs->Aop[1] += gfxs->dst_field_offset / 2 - pitch / 2;\n                        gfxs->Aop[2] += gfxs->dst_field_offset / 2 - pitch / 2;\n                   }\n                   else {\n                        gfxs->Aop[1] -= gfxs->dst_field_offset / 2;\n                        gfxs->Aop[2] -= gfxs->dst_field_offset / 2;\n                   }\n               }\n               else {\n                    gfxs->Aop[1] -= pitch / 2;\n                    gfxs->Aop[2] -= pitch / 2;\n               }\n          }\n          else if (gfxs->dst_format == DSPF_Y444 || gfxs->dst_format == DSPF_YV24) {\n               if (gfxs->dst_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Aop_field & 1) {\n                         gfxs->Aop[1] += gfxs->dst_field_offset - pitch;\n                         gfxs->Aop[2] += gfxs->dst_field_offset - pitch;\n                    }\n                    else {\n                         gfxs->Aop[1] -= gfxs->dst_field_offset;\n                         gfxs->Aop[2] -= gfxs->dst_field_offset;\n                    }\n               }\n               else {\n                    gfxs->Aop[1] -= pitch;\n                    gfxs->Aop[2] -= pitch;\n               }\n          }\n          else if (gfxs->dst_format == DSPF_NV12 || gfxs->dst_format == DSPF_NV21) {\n               if (gfxs->AopY & 1) {\n                    if (gfxs->dst_caps & DSCAPS_SEPARATED) {\n                         if (gfxs->Aop_field & 2)\n                              gfxs->Aop[1] += gfxs->dst_field_offset / 2 - pitch;\n                         else\n                              gfxs->Aop[1] -= gfxs->dst_field_offset / 2;\n                    }\n                    else {\n                         gfxs->Aop[1] -= pitch;\n                    }\n               }\n          }\n          else if (gfxs->dst_format == DSPF_NV16 || gfxs->dst_format == DSPF_NV61) {\n               if (gfxs->dst_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Aop_field & 1)\n                         gfxs->Aop[1] += gfxs->dst_field_offset - pitch;\n                    else\n                         gfxs->Aop[1] -= gfxs->dst_field_offset;\n               }\n               else {\n                    gfxs->Aop[1] -= pitch;\n               }\n          }\n          else { /* DSPF_NV24 || DSPF_NV42 */\n               if (gfxs->dst_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Aop_field & 1)\n                         gfxs->Aop[1] += gfxs->dst_field_offset * 2 - pitch;\n                    else\n                         gfxs->Aop[1] -= gfxs->dst_field_offset * 2;\n               }\n               else {\n                    gfxs->Aop[1] -= pitch * 2;\n               }\n          }\n     }\n\n     gfxs->AopY--;\n}\n\nvoid\nGenefx_Bop_xy( GenefxState *gfxs,\n               int          x,\n               int          y )\n{\n     int pitch = gfxs->src_pitch;\n\n     gfxs->Bop[0] = gfxs->src_org[0];\n     gfxs->BopY   = y;\n\n     if (gfxs->src_caps & DSCAPS_SEPARATED) {\n          gfxs->Bop_field = y & 1;\n          if (gfxs->Bop_field)\n               gfxs->Bop[0] += gfxs->src_field_offset;\n\n          y /= 2;\n     }\n\n     D_ASSUME( !(x & DFB_PIXELFORMAT_ALIGNMENT( gfxs->src_format )) );\n\n     gfxs->Bop[0] += y * pitch + DFB_BYTES_PER_LINE( gfxs->src_format, x );\n\n     if (DFB_PLANAR_PIXELFORMAT(gfxs->src_format)) {\n          int src_field_offset = gfxs->src_field_offset;\n\n          switch (gfxs->src_format) {\n               case DSPF_I420:\n               case DSPF_YV12:\n                    src_field_offset /= 4;\n                    pitch /= 2;\n                    y /= 2;\n                    x /= 2;\n                    break;\n               case DSPF_Y42B:\n               case DSPF_YV16:\n                    src_field_offset /= 2;\n                    pitch /= 2;\n                    x /= 2;\n                    break;\n               case DSPF_NV12:\n               case DSPF_NV21:\n                    src_field_offset /= 2;\n                    y /= 2;\n               case DSPF_NV16:\n               case DSPF_NV61:\n                    x &= ~1;\n                    break;\n               case DSPF_Y444:\n               case DSPF_YV24:\n               case DSPF_NV24:\n               case DSPF_NV42:\n                    /* nothing to adjust */\n               default:\n                    break;\n          }\n\n          gfxs->Bop[1] = gfxs->src_org[1];\n          gfxs->Bop[2] = gfxs->src_org[2];\n\n          if (gfxs->src_caps & DSCAPS_SEPARATED && gfxs->Bop_field) {\n               gfxs->Bop[1] += src_field_offset;\n               gfxs->Bop[2] += src_field_offset;\n          }\n\n          gfxs->Bop[1] += y * pitch + x;\n          gfxs->Bop[2] += y * pitch + x;\n\n          if (gfxs->src_format == DSPF_NV24 || gfxs->src_format == DSPF_NV42)\n               gfxs->Bop[1] += y * pitch + x;\n     }\n}\n\nvoid\nGenefx_Bop_next( GenefxState *gfxs )\n{\n     int pitch = gfxs->src_pitch;\n\n     if (gfxs->src_caps & DSCAPS_SEPARATED) {\n          gfxs->Bop_field++;\n\n          if (gfxs->Bop_field & 1)\n               gfxs->Bop[0] += gfxs->src_field_offset;\n          else\n               gfxs->Bop[0] += pitch - gfxs->src_field_offset;\n     }\n     else\n          gfxs->Bop[0] += pitch;\n\n     if (DFB_PLANAR_PIXELFORMAT(gfxs->src_format)) {\n          if (gfxs->src_format == DSPF_I420 || gfxs->src_format == DSPF_YV12) {\n               if (gfxs->BopY & 1) {\n                    if (gfxs->src_caps & DSCAPS_SEPARATED) {\n                         if (gfxs->Bop_field & 2) {\n                              gfxs->Bop[1] += gfxs->src_field_offset / 4;\n                              gfxs->Bop[2] += gfxs->src_field_offset / 4;\n                         }\n                         else {\n                              gfxs->Bop[1] += pitch / 2 - gfxs->src_field_offset / 4;\n                              gfxs->Bop[2] += pitch / 2 - gfxs->src_field_offset / 4;\n                         }\n                    }\n                    else {\n                         gfxs->Bop[1] += pitch / 2;\n                         gfxs->Bop[2] += pitch / 2;\n                    }\n               }\n          }\n          else if (gfxs->src_format == DSPF_Y42B || gfxs->src_format == DSPF_YV16) {\n               if (gfxs->src_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Bop_field & 2) {\n                         gfxs->Bop[1] += gfxs->src_field_offset / 2;\n                         gfxs->Bop[2] += gfxs->src_field_offset / 2;\n                    }\n                    else {\n                         gfxs->Bop[1] += pitch / 2 - gfxs->src_field_offset / 2;\n                         gfxs->Bop[2] += pitch / 2 - gfxs->src_field_offset / 2;\n                    }\n               }\n               else {\n                    gfxs->Bop[1] += pitch / 2;\n                    gfxs->Bop[2] += pitch / 2;\n               }\n          }\n          else if (gfxs->src_format == DSPF_Y444 || gfxs->src_format == DSPF_YV24) {\n               if (gfxs->src_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Bop_field & 1) {\n                         gfxs->Bop[1] += gfxs->src_field_offset;\n                         gfxs->Bop[2] += gfxs->src_field_offset;\n                    }\n                    else {\n                         gfxs->Bop[1] += pitch - gfxs->src_field_offset;\n                         gfxs->Bop[2] += pitch - gfxs->src_field_offset;\n                    }\n               }\n               else {\n                    gfxs->Bop[1] += pitch;\n                    gfxs->Bop[2] += pitch;\n               }\n          }\n          else if (gfxs->src_format == DSPF_NV12 || gfxs->src_format == DSPF_NV21) {\n               if (gfxs->BopY & 1) {\n                    if (gfxs->src_caps & DSCAPS_SEPARATED) {\n                         if (gfxs->Bop_field & 2)\n                              gfxs->Bop[1] += gfxs->src_field_offset / 2;\n                         else\n                              gfxs->Bop[1] += pitch - gfxs->src_field_offset / 2;\n                    }\n                    else {\n                         gfxs->Bop[1] += pitch;\n                    }\n               }\n          }\n          else if (gfxs->src_format == DSPF_NV16 || gfxs->src_format == DSPF_NV61) {\n               if (gfxs->src_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Bop_field & 1)\n                         gfxs->Bop[1] += gfxs->src_field_offset;\n                    else\n                         gfxs->Bop[1] += pitch - gfxs->src_field_offset;\n               }\n               else {\n                    gfxs->Bop[1] += pitch;\n               }\n          }\n          else { /* DSPF_NV24 || DSPF_NV42 */\n               if (gfxs->src_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Bop_field & 1)\n                         gfxs->Bop[1] += gfxs->src_field_offset * 2;\n                    else\n                         gfxs->Bop[1] += pitch - gfxs->src_field_offset * 2;\n               }\n               else {\n                    gfxs->Bop[1] += pitch * 2;\n               }\n          }\n     }\n\n     gfxs->BopY++;\n}\n\nvoid\nGenefx_Bop_prev( GenefxState *gfxs )\n{\n     int pitch = gfxs->src_pitch;\n\n     if (gfxs->src_caps & DSCAPS_SEPARATED) {\n          gfxs->Bop_field++;\n\n          if (gfxs->Bop_field & 1)\n               gfxs->Bop[0] += gfxs->src_field_offset - pitch;\n          else\n               gfxs->Bop[0] -= gfxs->src_field_offset;\n     }\n     else\n          gfxs->Bop[0] -= pitch;\n\n     if (DFB_PLANAR_PIXELFORMAT(gfxs->src_format)) {\n          if (gfxs->src_format == DSPF_I420 || gfxs->src_format == DSPF_YV12) {\n               if (gfxs->BopY & 1) {\n                    if (gfxs->src_caps & DSCAPS_SEPARATED) {\n                         if (gfxs->Bop_field & 2) {\n                              gfxs->Bop[1] += gfxs->src_field_offset / 4 - pitch / 2;\n                              gfxs->Bop[2] += gfxs->src_field_offset / 4 - pitch / 2;\n                         }\n                         else {\n                              gfxs->Bop[1] -= gfxs->src_field_offset / 4;\n                              gfxs->Bop[2] -= gfxs->src_field_offset / 4;\n                         }\n                    }\n                    else {\n                         gfxs->Bop[1] -= pitch / 2;\n                         gfxs->Bop[2] -= pitch / 2;\n                    }\n               }\n          }\n          else if (gfxs->src_format == DSPF_Y42B || gfxs->src_format == DSPF_YV16) {\n               if (gfxs->src_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Bop_field & 2) {\n                         gfxs->Bop[1] += gfxs->src_field_offset / 2 - pitch / 2;\n                         gfxs->Bop[2] += gfxs->src_field_offset / 2 - pitch / 2;\n                    }\n                    else {\n                         gfxs->Bop[1] -= gfxs->src_field_offset / 2;\n                         gfxs->Bop[2] -= gfxs->src_field_offset / 2;\n                    }\n               }\n               else {\n                    gfxs->Bop[1] -= pitch / 2;\n                    gfxs->Bop[2] -= pitch / 2;\n               }\n          }\n          else if (gfxs->src_format == DSPF_Y444 || gfxs->src_format == DSPF_YV24) {\n               if (gfxs->src_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Bop_field & 1) {\n                         gfxs->Bop[1] += gfxs->src_field_offset - pitch;\n                         gfxs->Bop[2] += gfxs->src_field_offset - pitch;\n                    }\n                    else {\n                         gfxs->Bop[1] -= gfxs->src_field_offset;\n                         gfxs->Bop[2] -= gfxs->src_field_offset;\n                    }\n               }\n               else {\n                    gfxs->Bop[1] -= pitch;\n                    gfxs->Bop[2] -= pitch;\n               }\n          }\n          else if (gfxs->src_format == DSPF_NV12 || gfxs->src_format == DSPF_NV21) {\n               if (gfxs->BopY & 1) {\n                    if (gfxs->src_caps & DSCAPS_SEPARATED) {\n                         if (gfxs->Bop_field & 2)\n                              gfxs->Bop[1] += gfxs->src_field_offset / 2 - pitch;\n                         else\n                              gfxs->Bop[1] -= gfxs->src_field_offset / 2;\n                    }\n                    else {\n                         gfxs->Bop[1] -= pitch;\n                    }\n               }\n          }\n          else if (gfxs->src_format == DSPF_NV16 || gfxs->src_format == DSPF_NV61) {\n               if (gfxs->src_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Bop_field & 1)\n                         gfxs->Bop[1] += gfxs->src_field_offset - pitch;\n                    else\n                         gfxs->Bop[1] -= gfxs->src_field_offset;\n               }\n               else {\n                    gfxs->Bop[1] -= pitch;\n               }\n          }\n          else { /* DSPF_NV24 || DSPF_NV42 */\n               if (gfxs->src_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Bop_field & 1)\n                         gfxs->Bop[1] += gfxs->src_field_offset * 2 - pitch;\n                    else\n                         gfxs->Bop[1] -= gfxs->src_field_offset * 2;\n               }\n               else {\n                    gfxs->Bop[1] -= pitch * 2;\n               }\n          }\n     }\n\n     gfxs->BopY--;\n}\n\nvoid\nGenefx_Mop_xy( GenefxState *gfxs,\n               int          x,\n               int          y )\n{\n     int pitch = gfxs->mask_pitch;\n\n     gfxs->Mop[0] = gfxs->mask_org[0];\n     gfxs->MopY   = y;\n\n     if (gfxs->mask_caps & DSCAPS_SEPARATED) {\n          gfxs->Mop_field = y & 1;\n          if (gfxs->Mop_field)\n               gfxs->Mop[0] += gfxs->mask_field_offset;\n\n          y /= 2;\n     }\n\n     D_ASSUME( !(x & DFB_PIXELFORMAT_ALIGNMENT( gfxs->mask_format )) );\n\n     gfxs->Mop[0] += y * pitch + DFB_BYTES_PER_LINE( gfxs->mask_format, x );\n\n     if (DFB_PLANAR_PIXELFORMAT(gfxs->mask_format)) {\n          int mask_field_offset = gfxs->mask_field_offset;\n\n          switch (gfxs->mask_format) {\n               case DSPF_I420:\n               case DSPF_YV12:\n                    mask_field_offset /= 4;\n                    pitch /= 2;\n                    y /= 2;\n                    x /= 2;\n                    break;\n               case DSPF_Y42B:\n               case DSPF_YV16:\n                    mask_field_offset /= 2;\n                    pitch /= 2;\n                    x /= 2;\n                    break;\n               case DSPF_NV12:\n               case DSPF_NV21:\n                    mask_field_offset /= 2;\n                    y /= 2;\n               case DSPF_NV16:\n               case DSPF_NV61:\n                    x &= ~1;\n                    break;\n               case DSPF_Y444:\n               case DSPF_YV24:\n               case DSPF_NV24:\n               case DSPF_NV42:\n                    /* nothing to adjust */\n               default:\n                    break;\n          }\n\n          gfxs->Mop[1] = gfxs->mask_org[1];\n          gfxs->Mop[2] = gfxs->mask_org[2];\n\n          if (gfxs->mask_caps & DSCAPS_SEPARATED && gfxs->Mop_field) {\n               gfxs->Mop[1] += mask_field_offset;\n               gfxs->Mop[2] += mask_field_offset;\n          }\n\n          gfxs->Mop[1] += y * pitch + x;\n          gfxs->Mop[2] += y * pitch + x;\n\n          if (gfxs->mask_format == DSPF_NV24 || gfxs->mask_format == DSPF_NV42)\n               gfxs->Mop[1] += y * pitch + x;\n     }\n}\n\nvoid\nGenefx_Mop_next( GenefxState *gfxs )\n{\n     int pitch = gfxs->mask_pitch;\n\n     if (gfxs->mask_caps & DSCAPS_SEPARATED) {\n          gfxs->Mop_field++;\n\n          if (gfxs->Mop_field & 1)\n               gfxs->Mop[0] += gfxs->mask_field_offset;\n          else\n               gfxs->Mop[0] += pitch - gfxs->mask_field_offset;\n     }\n     else\n          gfxs->Mop[0] += pitch;\n\n     if (DFB_PLANAR_PIXELFORMAT(gfxs->mask_format)) {\n          if (gfxs->mask_format == DSPF_I420 || gfxs->mask_format == DSPF_YV12) {\n               if (gfxs->MopY & 1) {\n                    if (gfxs->mask_caps & DSCAPS_SEPARATED) {\n                         if (gfxs->Mop_field & 2) {\n                              gfxs->Mop[1] += gfxs->mask_field_offset / 4;\n                              gfxs->Mop[2] += gfxs->mask_field_offset / 4;\n                         }\n                         else {\n                              gfxs->Mop[1] += pitch / 2 - gfxs->mask_field_offset / 4;\n                              gfxs->Mop[2] += pitch / 2 - gfxs->mask_field_offset / 4;\n                         }\n                    }\n                    else {\n                         gfxs->Mop[1] += pitch / 2;\n                         gfxs->Mop[2] += pitch / 2;\n                    }\n               }\n          }\n          else if (gfxs->mask_format == DSPF_Y42B || gfxs->mask_format == DSPF_YV16) {\n               if (gfxs->mask_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Mop_field & 2) {\n                         gfxs->Mop[1] += gfxs->mask_field_offset / 2;\n                         gfxs->Mop[2] += gfxs->mask_field_offset / 2;\n                    }\n                    else {\n                         gfxs->Mop[1] += pitch / 2 - gfxs->mask_field_offset / 2;\n                         gfxs->Mop[2] += pitch / 2 - gfxs->mask_field_offset / 2;\n                    }\n               }\n               else {\n                    gfxs->Mop[1] += pitch / 2;\n                    gfxs->Mop[2] += pitch / 2;\n               }\n          }\n          else if (gfxs->mask_format == DSPF_Y444 || gfxs->mask_format == DSPF_YV24) {\n               if (gfxs->mask_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Mop_field & 1) {\n                         gfxs->Mop[1] += gfxs->mask_field_offset;\n                         gfxs->Mop[2] += gfxs->mask_field_offset;\n                    }\n                    else {\n                         gfxs->Mop[1] += pitch - gfxs->mask_field_offset;\n                         gfxs->Mop[2] += pitch - gfxs->mask_field_offset;\n                    }\n               }\n               else {\n                    gfxs->Mop[1] += pitch;\n                    gfxs->Mop[2] += pitch;\n               }\n          }\n          else if (gfxs->mask_format == DSPF_NV12 || gfxs->mask_format == DSPF_NV21) {\n               if (gfxs->MopY & 1) {\n                    if (gfxs->mask_caps & DSCAPS_SEPARATED) {\n                         if (gfxs->Mop_field & 2)\n                              gfxs->Mop[1] += gfxs->mask_field_offset / 2;\n                         else\n                              gfxs->Mop[1] += pitch - gfxs->mask_field_offset / 2;\n                    }\n                    else {\n                         gfxs->Mop[1] += pitch;\n                    }\n               }\n          }\n          else if (gfxs->mask_format == DSPF_NV16 || gfxs->mask_format == DSPF_NV61) {\n               if (gfxs->mask_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Mop_field & 1)\n                         gfxs->Mop[1] += gfxs->mask_field_offset;\n                    else\n                         gfxs->Mop[1] += pitch - gfxs->mask_field_offset;\n               }\n               else {\n                    gfxs->Mop[1] += pitch;\n               }\n          }\n          else { /* DSPF_NV24 || DSPF_NV42 */\n               if (gfxs->mask_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Mop_field & 1)\n                         gfxs->Mop[1] += gfxs->mask_field_offset * 2;\n                    else\n                         gfxs->Mop[1] += pitch - gfxs->mask_field_offset * 2;\n               }\n               else {\n                    gfxs->Mop[1] += pitch * 2;\n               }\n          }\n     }\n\n     gfxs->MopY++;\n}\n\nvoid\nGenefx_Mop_prev( GenefxState *gfxs )\n{\n     int pitch = gfxs->mask_pitch;\n\n     if (gfxs->mask_caps & DSCAPS_SEPARATED) {\n          gfxs->Mop_field++;\n\n          if (gfxs->Mop_field & 1)\n               gfxs->Mop[0] += gfxs->mask_field_offset - pitch;\n          else\n               gfxs->Mop[0] -= gfxs->mask_field_offset;\n     }\n     else\n          gfxs->Mop[0] -= pitch;\n\n     if (DFB_PLANAR_PIXELFORMAT(gfxs->mask_format)) {\n          if (gfxs->mask_format == DSPF_I420 || gfxs->mask_format == DSPF_YV12) {\n               if (gfxs->MopY & 1) {\n                    if (gfxs->mask_caps & DSCAPS_SEPARATED) {\n                         if (gfxs->Mop_field & 2) {\n                              gfxs->Mop[1] += gfxs->mask_field_offset / 4 - pitch / 2;\n                              gfxs->Mop[2] += gfxs->mask_field_offset / 4 - pitch / 2;\n                         }\n                         else {\n                              gfxs->Mop[1] -= gfxs->mask_field_offset / 4;\n                              gfxs->Mop[2] -= gfxs->mask_field_offset / 4;\n                         }\n                    }\n                    else {\n                         gfxs->Mop[1] -= pitch / 2;\n                         gfxs->Mop[2] -= pitch / 2;\n                    }\n               }\n          }\n          else if (gfxs->mask_format == DSPF_Y42B || gfxs->mask_format == DSPF_YV16) {\n               if (gfxs->mask_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Mop_field & 2) {\n                         gfxs->Mop[1] += gfxs->mask_field_offset / 2 - pitch / 2;\n                         gfxs->Mop[2] += gfxs->mask_field_offset / 2 - pitch / 2;\n                    }\n                    else {\n                         gfxs->Mop[1] -= gfxs->mask_field_offset / 2;\n                         gfxs->Mop[2] -= gfxs->mask_field_offset / 2;\n                    }\n               }\n               else {\n                    gfxs->Mop[1] -= pitch / 2;\n                    gfxs->Mop[2] -= pitch / 2;\n               }\n          }\n          else if (gfxs->mask_format == DSPF_Y444 || gfxs->mask_format == DSPF_YV24) {\n               if (gfxs->mask_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Mop_field & 1) {\n                         gfxs->Mop[1] += gfxs->mask_field_offset - pitch;\n                         gfxs->Mop[2] += gfxs->mask_field_offset - pitch;\n                    }\n                    else {\n                         gfxs->Mop[1] -= gfxs->mask_field_offset;\n                         gfxs->Mop[2] -= gfxs->mask_field_offset;\n                    }\n               }\n               else {\n                    gfxs->Mop[1] -= pitch;\n                    gfxs->Mop[2] -= pitch;\n               }\n          }\n          else if (gfxs->mask_format == DSPF_NV12 || gfxs->mask_format == DSPF_NV21) {\n               if (gfxs->MopY & 1) {\n                    if (gfxs->mask_caps & DSCAPS_SEPARATED) {\n                         if (gfxs->Mop_field & 2)\n                              gfxs->Mop[1] += gfxs->mask_field_offset / 2 - pitch;\n                         else\n                              gfxs->Mop[1] -= gfxs->mask_field_offset / 2;\n                    }\n                    else {\n                         gfxs->Mop[1] -= pitch;\n                    }\n               }\n          }\n          else if (gfxs->mask_format == DSPF_NV16 || gfxs->mask_format == DSPF_NV61) {\n               if (gfxs->mask_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Mop_field & 1)\n                         gfxs->Mop[1] += gfxs->mask_field_offset - pitch;\n                    else\n                         gfxs->Mop[1] -= gfxs->mask_field_offset;\n               }\n               else {\n                    gfxs->Mop[1] -= pitch;\n               }\n          }\n          else { /* DSPF_NV24 || DSPF_NV42 */\n               if (gfxs->mask_caps & DSCAPS_SEPARATED) {\n                    if (gfxs->Mop_field & 1)\n                         gfxs->Mop[1] += gfxs->mask_field_offset * 2 - pitch;\n                    else\n                         gfxs->Mop[1] -= gfxs->mask_field_offset * 2;\n               }\n               else {\n                    gfxs->Mop[1] -= pitch * 2;\n               }\n          }\n     }\n\n     gfxs->MopY--;\n}\n\nbool\nGenefx_ABacc_prepare( GenefxState *gfxs, int width )\n{\n     int size;\n\n     if (!gfxs->need_accumulator)\n          return true;\n\n     size = (width + 31) & ~31;\n\n     if (gfxs->ABsize < size) {\n          void *ABstart = D_MALLOC( size * sizeof(GenefxAccumulator) * 3 + 31 );\n\n          if (!ABstart) {\n               D_WARN( \"out of memory\" );\n               return false;\n          }\n\n          if (gfxs->ABstart)\n               D_FREE( gfxs->ABstart );\n\n          gfxs->ABstart = ABstart;\n          gfxs->ABsize  = size;\n          gfxs->Aacc    = (GenefxAccumulator*) (((unsigned long) ABstart+31) & ~31);\n          gfxs->Bacc    = gfxs->Aacc + size;\n          gfxs->Tacc    = gfxs->Aacc + size + size;\n     }\n\n     gfxs->Sacc = gfxs->Dacc = gfxs->Aacc;\n\n     return true;\n}\n\nvoid\nGenefx_ABacc_flush( GenefxState *gfxs )\n{\n     if (dfb_config->keep_accumulators >= 0 && gfxs->ABsize > dfb_config->keep_accumulators) {\n          D_FREE( gfxs->ABstart );\n\n          gfxs->ABsize  = 0;\n          gfxs->ABstart = NULL;\n          gfxs->Aacc    = NULL;\n          gfxs->Bacc    = NULL;\n          gfxs->Sacc    = NULL;\n          gfxs->Dacc    = NULL;\n     }\n}\n"
  },
  {
    "path": "src/gfx/generic/generic_util.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __GENERIC_UTIL_H__\n#define __GENERIC_UTIL_H__\n\n#include <core/coretypes.h>\n#include <direct/log.h>\n#include <direct/trace.h>\n#include <misc/conf.h>\n\n/**********************************************************************************************************************/\n\n#define CHECK_PIPELINE()                                                                                          \\\n     {                                                                                                            \\\n          if (!gfxs->funcs[0])                                                                                    \\\n               return;                                                                                            \\\n                                                                                                                  \\\n          if (dfb_config->software_trace) {                                                                       \\\n               int         idx;                                                                                   \\\n               GenefxFunc *funcs = gfxs->funcs;                                                                   \\\n               DirectLog  *log   = direct_log_default();                                                          \\\n                                                                                                                  \\\n               direct_log_lock( log );                                                                            \\\n               direct_log_printf( log, \"  Software Fallback Pipeline:\\n\" );                                       \\\n                                                                                                                  \\\n               for (idx = 0; funcs[idx]; ++idx)                                                                   \\\n                    direct_log_printf( log, \"    [%2d] %s\\n\", idx, direct_trace_lookup_symbol_at( funcs[idx] ) ); \\\n                                                                                                                  \\\n               direct_log_printf( log, \"\\n\" );                                                                    \\\n               direct_log_unlock( log );                                                                          \\\n          }                                                                                                       \\\n     }\n\n#define RUN_PIPELINE()                     \\\n     {                                     \\\n          int         idx;                 \\\n          GenefxFunc *funcs = gfxs->funcs; \\\n                                           \\\n          for (idx = 0; funcs[idx]; ++idx) \\\n               funcs[idx]( gfxs );         \\\n     }\n\n/**********************************************************************************************************************/\n\nvoid Genefx_Aop_crab     ( GenefxState *gfxs );\n\nvoid Genefx_Aop_prev_crab( GenefxState *gfxs );\n\nvoid Genefx_Aop_xy       ( GenefxState *gfxs,\n                           int          x,\n                           int          y );\n\nvoid Genefx_Aop_next     ( GenefxState *gfxs );\n\nvoid Genefx_Aop_prev     ( GenefxState *gfxs );\n\nvoid Genefx_Bop_xy       ( GenefxState *gfxs,\n                           int          x,\n                           int          y );\n\nvoid Genefx_Bop_next     ( GenefxState *gfxs );\n\nvoid Genefx_Bop_prev     ( GenefxState *gfxs );\n\nvoid Genefx_Mop_xy       ( GenefxState *gfxs,\n                           int          x,\n                           int          y );\n\nvoid Genefx_Mop_next     ( GenefxState *gfxs );\n\nvoid Genefx_Mop_prev     ( GenefxState *gfxs );\n\nbool Genefx_ABacc_prepare( GenefxState *gfxs,\n                           int          width );\n\nvoid Genefx_ABacc_flush  ( GenefxState *gfxs );\n\n#endif\n"
  },
  {
    "path": "src/gfx/generic/stretch_hvx_16.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef SOURCE_LOOKUP\n#define SOURCE_LOOKUP(x) (x)\n#define SOURCE_LOOKUP_AUTO\n#endif\n\n#ifndef SOURCE_TYPE\n#define SOURCE_TYPE u16\n#define SOURCE_TYPE_AUTO\n#endif\n\n#define SHIFT_L5   SHIFT_R5\n#define SHIFT_L6   SHIFT_R6\n#define SHIFT_L10  (16 - SHIFT_L6)\n\n#define X_003F     (X_07E0 >> SHIFT_R5)\n\n#define X_003E07C0 (X_F81F << SHIFT_L6)\n#define X_0001F800 (X_07E0 << SHIFT_L6)\n\n#define X_07E0F81F ((X_07E0 << 16) | X_F81F)\n#define X_F81F07E0 ((X_F81F << 16) | X_07E0)\n\n#define X_F81FF81F ((X_F81F << 16) | X_F81F)\n#define X_07E007E0 ((X_07E0 << 16) | X_07E0)\n\n#define X_07C0F83F (X_F81F07E0 >> SHIFT_R5)\n\n#if D_DEBUG_ENABLED\n#define HVX_DEBUG(x...) direct_log_printf( NULL, x )\n#else\n#define HVX_DEBUG(x...) do {} while (0)\n#endif\n\n/* static void\n   stretch_hvx_RGB16/ARGB4444/RGBA4444_up/down_KP_F */ ( void             *dst,\n                                                         int               dpitch,\n                                                         const void       *src,\n                                                         int               spitch,\n                                                         int               width,\n                                                         int               height,\n                                                         int               dst_width,\n                                                         int               dst_height,\n                                                         const StretchCtx *ctx )\n{\n     long  x, y;\n     long  r      = 0;\n     long  head   = ((((unsigned long) dst) & 2) >> 1) ^ (ctx->clip.x1 & 1);\n     long  cw     = ctx->clip.x2 - ctx->clip.x1 + 1;\n     long  ch     = ctx->clip.y2 - ctx->clip.y1 + 1;\n     long  tail   = (cw - head) & 1;\n     long  w2     = (cw - head) / 2;\n     long  hfraq  = ((width  - MINUS_1) << 18) / dst_width;\n     long  vfraq  = ((height - MINUS_1) << 18) / dst_height;\n     long  dp4    = dpitch / 4;\n     long  point0 = POINT_0 + ctx->clip.x1 * hfraq;\n     long  point  = point0;\n     long  line   = LINE_0 + ctx->clip.y1 * vfraq;\n     long  ratios[cw];\n     u32  *dst32;\n     u32   dt;\n     u16   l_;\n     u32   _lbT[w2+8];\n     u32   _lbB[w2+8];\n     u32  *lbX;\n     u32  *lbT    = (u32*) ((((unsigned long) (&_lbT[0])) + 31) & ~31);\n     u32  *lbB    = (u32*) ((((unsigned long) (&_lbB[0])) + 31) & ~31);\n     long  lineT  = -2000;\n\n     for (x = 0; x < cw; x++) {\n          ratios[x] = POINT_TO_RATIO( point, hfraq );\n\n          point += hfraq;\n     }\n\n     HVX_DEBUG( \"%dx%d -> %dx%d  (0x%lx, 0x%lx) prot %lx, key %lx\\n\", width, height, dst_width, dst_height,\n                (unsigned long) hfraq, (unsigned long) vfraq, ctx->protect, ctx->key );\n\n     dst += ctx->clip.x1 * 2 + ctx->clip.y1 * dpitch;\n\n     dst32 = dst;\n\n     if (head) {\n          u32 dpT, dpB, L, R;\n\n          u16 *dst16 = dst;\n\n          point = point0;\n\n          for (y = 0; y < ch; y++) {\n               long X = LINE_TO_RATIO( line, vfraq );\n\n               const SOURCE_TYPE *srcT = src + spitch * LINE_T( line, vfraq );\n               const SOURCE_TYPE *srcB = src + spitch * LINE_B( line, vfraq );\n\n               /* Horizontal interpolation. */\n               long pl = POINT_L( point, hfraq );\n\n               HVX_DEBUG( \"h,%ld %ld  (%ld/%ld)  0x%lx  0x%lx\\n\", y, pl,\n                           POINT_L( point, hfraq ), POINT_R( point, hfraq ),\n                           (unsigned long) point, (unsigned long) ratios[r] );\n\n               D_ASSERT( pl >= 0 );\n               D_ASSERT( pl < width - 1 );\n\n               L = SOURCE_LOOKUP( srcT[pl] );\n               R = SOURCE_LOOKUP( srcT[pl+1] );\n\n               dpT = (((((R & X_F81F) - (L & X_F81F)) * ratios[r] + ((L & X_F81F) << SHIFT_L6)) & X_003E07C0)\n                    + ((((R & X_07E0) - (L & X_07E0)) * ratios[r] + ((L & X_07E0) << SHIFT_L6)) & X_0001F800)\n                     ) >> SHIFT_R6;\n\n               L = SOURCE_LOOKUP( srcB[pl] );\n               R = SOURCE_LOOKUP( srcB[pl+1] );\n\n               dpB = (((((R & X_F81F) - (L & X_F81F)) * ratios[r] + ((L & X_F81F) << SHIFT_L6)) & X_003E07C0)\n                    + ((((R & X_07E0) - (L & X_07E0)) * ratios[r] + ((L & X_07E0) << SHIFT_L6)) & X_0001F800)\n                     ) >> SHIFT_R6;\n\n               /* Vertical interpolation. */\n               l_ = ((((((dpB & X_F81F) - (dpT & X_F81F)) * X) >> SHIFT_R5) + (dpT & X_F81F)) & X_F81F) +\n                    ((((((dpB >> SHIFT_R5) & X_003F) - ((dpT >> SHIFT_R5) & X_003F)) * X) + (dpT & X_07E0)) & X_07E0);\n#if defined(COLOR_KEY) || defined(KEY_PROTECT)\n#ifdef COLOR_KEY\n               if ((l_ & MASK_RGB) != (COLOR_KEY))\n#endif\n#ifdef KEY_PROTECT\n                    /* Write to destination with color key protection. */\n                    dst16[0] = ((l_ & MASK_RGB) == KEY_PROTECT) ? l_ ^ 1 : l_;\n#else\n                    /* Write to destination without color key protection. */\n                    dst16[0] = l_;\n#endif\n#else /* defined(COLOR_KEY) || defined(KEY_PROTECT) */\n               /* Write to destination without color key protection. */\n               dst16[0] = l_;\n#endif /* defined(COLOR_KEY) || defined(KEY_PROTECT) */\n\n               dst16 += dpitch / 2;\n               line  += vfraq;\n          }\n\n          /* Adjust. */\n          point0 += hfraq;\n          dst32   = dst + 2;\n\n          /* Reset. */\n          line = LINE_0 + ctx->clip.y1 * vfraq;\n     }\n\n     /* Scale line by line. */\n     for (y = 0; y < ch; y++) {\n          long X;\n          long nlT = LINE_T( line, vfraq );\n\n          D_ASSERT( nlT >= 0 );\n          D_ASSERT( nlT < height - 1 );\n\n          /* Fill line buffer(s). */\n          if (nlT != lineT) {\n               u32 L, R, dpT, dpB;\n               const SOURCE_TYPE *srcT = src + spitch * nlT;\n               const SOURCE_TYPE *srcB = src + spitch * (nlT + 1);\n               long               diff = nlT - lineT;\n\n               if (diff > 1) {\n                    /* Two output pixels per step. */\n                    for (x = 0, r = head, point = point0; x < w2; x++) {\n                         /* Horizontal interpolation. */\n                         long pl = POINT_L( point, hfraq );\n\n                         HVX_DEBUG( \"%ld,%ld %ld  (%ld/%ld)  0x%lx  0x%lx\\n\",\n                                    x, y, pl, POINT_L( point, hfraq ), POINT_R( point, hfraq ),\n                                    (unsigned long) point, (unsigned long) ratios[r] );\n\n                         D_ASSERT( pl >= 0 );\n                         D_ASSERT( pl < width - 1 );\n\n                         L = SOURCE_LOOKUP( srcT[pl] );\n                         R = SOURCE_LOOKUP( srcT[pl+1] );\n\n                         dpT = (((((R & X_F81F) - (L & X_F81F)) * ratios[r] + ((L & X_F81F) << SHIFT_L6)) & X_003E07C0)\n                              + ((((R & X_07E0) - (L & X_07E0)) * ratios[r] + ((L & X_07E0) << SHIFT_L6)) & X_0001F800)\n#ifdef WORDS_BIGENDIAN\n                               ) << SHIFT_L10;\n#else\n                               ) >> SHIFT_R6;\n#endif\n\n                         L = SOURCE_LOOKUP( srcB[pl] );\n                         R = SOURCE_LOOKUP( srcB[pl+1] );\n\n                         dpB = (((((R & X_F81F) - (L & X_F81F)) * ratios[r] + ((L & X_F81F) << SHIFT_L6)) & X_003E07C0)\n                              + ((((R & X_07E0) - (L & X_07E0)) * ratios[r] + ((L & X_07E0) << SHIFT_L6)) & X_0001F800)\n#ifdef WORDS_BIGENDIAN\n                               ) << SHIFT_L10;\n#else\n                               ) >> SHIFT_R6;\n#endif\n\n                         point += hfraq;\n                         r++;\n\n                         pl = POINT_L( point, hfraq );\n\n                         HVX_DEBUG( \"%ld,%ld %ld  (%ld/%ld)  0x%lx  0x%lx\\n\",\n                                    x, y, pl, POINT_L( point, hfraq ), POINT_R( point, hfraq ),\n                                    (unsigned long) point, (unsigned long) ratios[r] );\n\n                         D_ASSERT( pl >= 0 );\n                         D_ASSERT( pl < width - 1 );\n\n                         L = SOURCE_LOOKUP( srcT[pl] );\n                         R = SOURCE_LOOKUP( srcT[pl+1] );\n\n                         dpT |= (((((R & X_F81F) - (L & X_F81F)) * ratios[r] + ((L & X_F81F) << SHIFT_L6)) & X_003E07C0)\n                               + ((((R & X_07E0) - (L & X_07E0)) * ratios[r] + ((L & X_07E0) << SHIFT_L6)) & X_0001F800)\n#ifdef WORDS_BIGENDIAN\n                                ) >> SHIFT_R6;\n#else\n                                ) << SHIFT_L10;\n#endif\n\n                         L = SOURCE_LOOKUP( srcB[pl] );\n                         R = SOURCE_LOOKUP( srcB[pl+1] );\n\n                         dpB |= (((((R & X_F81F) - (L & X_F81F)) * ratios[r] + ((L & X_F81F) << SHIFT_L6)) & X_003E07C0)\n                               + ((((R & X_07E0) - (L & X_07E0)) * ratios[r] + ((L & X_07E0) << SHIFT_L6)) & X_0001F800)\n#ifdef WORDS_BIGENDIAN\n                                ) >> SHIFT_R6;\n#else\n                                ) << SHIFT_L10;\n#endif\n\n                         point += hfraq;\n                         r++;\n\n                         /* Store. */\n                         lbT[x] = dpT;\n                         lbB[x] = dpB;\n                    }\n               }\n               else {\n                    /* Swap. */\n                    lbX = lbT;\n                    lbT = lbB;\n                    lbB = lbX;\n\n                    /* Two output pixels per step. */\n                    for (x = 0, r = head, point = point0; x < w2; x++) {\n                         /* Horizontal interpolation. */\n                         long pl = POINT_L( point, hfraq );\n\n                         HVX_DEBUG( \"%ld,%ld %ld  (%ld/%ld)  0x%lx  0x%lx\\n\",\n                                    x, y, pl, POINT_L( point, hfraq ), POINT_R( point, hfraq ),\n                                    (unsigned long) point, (unsigned long) ratios[r] );\n\n                         D_ASSERT( pl >= 0 );\n                         D_ASSERT( pl < width - 1 );\n\n                         L = SOURCE_LOOKUP( srcB[pl] );\n                         R = SOURCE_LOOKUP( srcB[pl+1] );\n\n                         dpB = (((((R & X_F81F) - (L & X_F81F)) * ratios[r] + ((L & X_F81F) << SHIFT_L6)) & X_003E07C0)\n                              + ((((R & X_07E0) - (L & X_07E0)) * ratios[r] + ((L & X_07E0) << SHIFT_L6)) & X_0001F800)\n#ifdef WORDS_BIGENDIAN\n                               ) << SHIFT_L10;\n#else\n                               ) >> SHIFT_R6;\n#endif\n\n                         point += hfraq;\n                         r++;\n\n                         pl = POINT_L( point, hfraq );\n\n                         HVX_DEBUG( \"%ld,%ld %ld  (%ld/%ld)  0x%lx  0x%lx\\n\",\n                                    x, y, pl, POINT_L( point, hfraq ), POINT_R( point, hfraq ),\n                                    (unsigned long) point, (unsigned long) ratios[r] );\n\n                         D_ASSERT( pl >= 0 );\n                         D_ASSERT( pl < width - 1 );\n\n                         L = SOURCE_LOOKUP( srcB[pl] );\n                         R = SOURCE_LOOKUP( srcB[pl+1] );\n\n                         dpB |= (((((R & X_F81F) - (L & X_F81F)) * ratios[r] + ((L & X_F81F) << SHIFT_L6)) & X_003E07C0)\n                               + ((((R & X_07E0) - (L & X_07E0)) * ratios[r] + ((L & X_07E0) << SHIFT_L6)) & X_0001F800)\n#ifdef WORDS_BIGENDIAN\n                                ) >> SHIFT_R6;\n#else\n                                ) << SHIFT_L10;\n#endif\n\n                         point += hfraq;\n                         r++;\n\n                         /* Store. */\n                         lbB[x] = dpB;\n                    }\n               }\n\n               lineT = nlT;\n          }\n\n          /* Vertical interpolation. */\n          X = LINE_TO_RATIO( line, vfraq );\n\n          for (x = 0; x < w2; x++) {\n#ifdef HAS_ALPHA\n               dt = ((((((lbB[x] & X_F81FF81F) - (lbT[x] & X_F81FF81F)) * X) >> SHIFT_R5) +\n                      (lbT[x] & X_F81FF81F)) & X_F81FF81F) +\n                    ((((((lbB[x] >> SHIFT_R5) & X_F81FF81F) - ((lbT[x] >> SHIFT_R5) & X_F81FF81F)) * X) +\n                      (lbT[x] & X_07E007E0)) & X_07E007E0);\n#else\n               dt = ((((((lbB[x] & X_07E0F81F) - (lbT[x] & X_07E0F81F)) * X) >> SHIFT_R5) +\n                      (lbT[x] & X_07E0F81F)) & X_07E0F81F) +\n                    ((((((lbB[x] >> SHIFT_R5) & X_07C0F83F) - ((lbT[x] >> SHIFT_R5) & X_07C0F83F)) * X) +\n                      (lbT[x] & X_F81F07E0)) & X_F81F07E0);\n#endif\n\n#if defined(COLOR_KEY) || defined(KEY_PROTECT)\n               u16 h_;\n\n               /* Get two new pixels. */\n               l_ = dt;\n               h_ = dt >> 16;\n\n#ifdef COLOR_KEY\n               if ((l_ & MASK_RGB) != (COLOR_KEY)) {\n                    if ((h_ & MASK_RGB) != (COLOR_KEY)) {\n#ifdef KEY_PROTECT\n                         /* Write to destination with color key protection. */\n                         dst32[x] = ((((h_ & MASK_RGB) == KEY_PROTECT) ? h_ ^ 1 : h_) << 16) |\n                                    ( ((l_ & MASK_RGB) == KEY_PROTECT) ? l_ ^ 1 : l_);\n#else\n                         /* Write to destination without color key protection. */\n                         dst32[x] = dt;\n#endif\n                    }\n                    else {\n                         u16 *_dst16 = (u16*) &dst32[x];\n\n#ifdef KEY_PROTECT\n                         /* Write to destination with color key protection. */\n                         *_dst16 = (((l_ & MASK_RGB) == KEY_PROTECT) ? l_ ^ 1 : l_);\n#else\n                         /* Write to destination without color key protection. */\n                         *_dst16 = l_;\n#endif\n                    }\n               }\n               else if ((h_ & MASK_RGB) != (COLOR_KEY)) {\n                    u16 *_dst16 = ((u16*) &dst32[x]) + 1;\n\n#ifdef KEY_PROTECT\n                    /* Write to destination with color key protection. */\n                    *_dst16 = (((h_ & MASK_RGB) == KEY_PROTECT) ? h_ ^ 1 : h_);\n#else\n                    /* Write to destination without color key protection. */\n                    *_dst16 = h_;\n#endif\n               }\n#else\n               /* Write to destination with color key protection */\n               dst32[x] = ((((h_ & MASK_RGB) == KEY_PROTECT) ? h_ ^ 1 : h_) << 16) |\n                          ( ((l_ & MASK_RGB) == KEY_PROTECT) ? l_ ^ 1 : l_);\n#endif\n#else /* defined(COLOR_KEY) || defined(KEY_PROTECT) */\n               dst32[x] = dt;\n#endif /* defined(COLOR_KEY) || defined(KEY_PROTECT) */\n          }\n\n          dst32 += dp4;\n          line  += vfraq;\n     }\n\n     if (tail) {\n          u32 dpT, dpB, L, R;\n\n          u16 *dst16 = dst + cw * 2 - 2;\n\n          /* Reset. */\n          line = LINE_0 + ctx->clip.y1 * vfraq;\n\n          for (y = 0; y < ch; y++) {\n               long X = LINE_TO_RATIO( line, vfraq );\n\n               const SOURCE_TYPE *srcT = src + spitch * LINE_T( line, vfraq );\n               const SOURCE_TYPE *srcB = src + spitch * LINE_B( line, vfraq );\n\n               /* Horizontal interpolation. */\n               long pl = POINT_L( point, hfraq );\n\n               HVX_DEBUG( \"t,%ld %ld  (%ld/%ld)  0x%lx  0x%lx\\n\",\n                          y, pl, POINT_L( point, hfraq ), POINT_R( point, hfraq ),\n                          (unsigned long) point, (unsigned long) ratios[r] );\n\n               D_ASSERT( pl >= 0 );\n               D_ASSERT( pl < width - 1 );\n\n               L = SOURCE_LOOKUP( srcT[pl] );\n               R = SOURCE_LOOKUP( srcT[pl+1] );\n\n               dpT = (((((R & X_F81F) - (L & X_F81F)) * ratios[r] + ((L & X_F81F) << SHIFT_L6)) & X_003E07C0)\n                    + ((((R & X_07E0) - (L & X_07E0)) * ratios[r] + ((L & X_07E0) << SHIFT_L6)) & X_0001F800)\n                     ) >> SHIFT_R6;\n\n               L = SOURCE_LOOKUP( srcB[pl] );\n               R = SOURCE_LOOKUP( srcB[pl+1] );\n\n               dpB = (((((R & X_F81F) - (L & X_F81F)) * ratios[r] + ((L & X_F81F) << SHIFT_L6)) & X_003E07C0)\n                    + ((((R & X_07E0) - (L & X_07E0)) * ratios[r] + ((L & X_07E0) << SHIFT_L6)) & X_0001F800)\n                     ) >> SHIFT_R6;\n\n               /* Vertical interpolation. */\n               l_ = ((((((dpB & X_F81F) - (dpT & X_F81F)) * X) >> SHIFT_R5) + (dpT & X_F81F)) & X_F81F) +\n                    ((((((dpB >> SHIFT_R5) & X_003F) - ((dpT >> SHIFT_R5) & X_003F)) * X) + (dpT & X_07E0)) & X_07E0);\n#if defined(COLOR_KEY) || defined(KEY_PROTECT)\n#ifdef COLOR_KEY\n               if ((l_ & MASK_RGB) != (COLOR_KEY))\n#endif\n#ifdef KEY_PROTECT\n                    /* Write to destination with color key protection. */\n                    dst16[0] = ((l_ & MASK_RGB) == KEY_PROTECT) ? l_ ^ 1 : l_;\n#else\n                    /* Write to destination without color key protection. */\n                    dst16[0] = l_;\n#endif\n#else /* defined(COLOR_KEY) || defined(KEY_PROTECT) */\n               /* Write to destination without color key protection. */\n               dst16[0] = l_;\n#endif /* defined(COLOR_KEY) || defined(KEY_PROTECT) */\n\n               dst16 += dpitch / 2;\n               line  += vfraq;\n          }\n     }\n}\n\n#undef SHIFT_L5\n#undef SHIFT_L6\n#undef SHIFT_L10\n\n#undef X_003F\n\n#undef X_003E07C0\n#undef X_0001F800\n\n#undef X_07E0F81F\n#undef X_F81F07E0\n\n#undef X_07C0F83F\n\n#ifdef SOURCE_LOOKUP_AUTO\n#undef SOURCE_LOOKUP_AUTO\n#undef SOURCE_LOOKUP\n#endif\n\n#ifdef SOURCE_TYPE_AUTO\n#undef SOURCE_TYPE_AUTO\n#undef SOURCE_TYPE\n#endif\n"
  },
  {
    "path": "src/gfx/generic/stretch_hvx_32.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef SOURCE_LOOKUP\n#define SOURCE_LOOKUP(x) (x)\n#define SOURCE_LOOKUP_AUTO\n#endif\n\n#ifndef SOURCE_TYPE\n#define SOURCE_TYPE u32\n#define SOURCE_TYPE_AUTO\n#endif\n\n#if D_DEBUG_ENABLED\n#define HVX_DEBUG(x...) direct_log_printf( NULL, x )\n#else\n#define HVX_DEBUG(x...) do {} while (0)\n#endif\n\n/* static void\n   stretch_hvx_RGB32/ARGB_up/down_32_KPI */ ( void             *dst,\n                                              int               dpitch,\n                                              const void       *src,\n                                              int               spitch,\n                                              int               width,\n                                              int               height,\n                                              int               dst_width,\n                                              int               dst_height,\n                                              const StretchCtx *ctx )\n{\n     long  x, y;\n     long  cw     = ctx->clip.x2 - ctx->clip.x1 + 1;\n     long  ch     = ctx->clip.y2 - ctx->clip.y1 + 1;\n     long  hfraq  = ((width  - MINUS_1) << 18) / dst_width;\n     long  vfraq  = ((height - MINUS_1) << 18) / dst_height;\n     long  dp4    = dpitch / 4;\n     long  point0 = POINT_0 + ctx->clip.x1 * hfraq;\n     long  point  = point0;\n     long  line   = LINE_0 + ctx->clip.y1 * vfraq;\n     long  ratios[cw];\n     u32  *dst32;\n     u32   dt;\n     u32   _lbT[cw+8];\n     u32   _lbB[cw+8];\n     u32  *lbX;\n     u32  *lbT    = (u32*) ((((unsigned long) (&_lbT[0])) + 31) & ~31);\n     u32  *lbB    = (u32*) ((((unsigned long) (&_lbB[0])) + 31) & ~31);\n     long  lineT  = -2000;\n\n     for (x = 0; x < cw; x++) {\n          ratios[x] = POINT_TO_RATIO( point, hfraq );\n\n          point += hfraq;\n     }\n\n     HVX_DEBUG( \"%dx%d -> %dx%d  (0x%lx, 0x%lx) prot %lx, key %lx\\n\", width, height, dst_width, dst_height,\n                (unsigned long) hfraq, (unsigned long) vfraq, ctx->protect, ctx->key );\n\n     dst += ctx->clip.x1 * 4 + ctx->clip.y1 * dpitch;\n\n     dst32 = dst;\n\n     /* Scale line by line. */\n     for (y = 0; y < ch; y++) {\n          long X;\n          long nlT = LINE_T( line, vfraq );\n\n          D_ASSERT( nlT >= 0 );\n          D_ASSERT( nlT < height - 1 );\n\n          /* Fill line buffer(s). */\n          if (nlT != lineT) {\n               u32 L, R;\n               const SOURCE_TYPE *srcT = src + spitch * nlT;\n               const SOURCE_TYPE *srcB = src + spitch * (nlT + 1);\n               long               diff = nlT - lineT;\n\n               if (diff > 1) {\n                    for (x = 0, point = point0; x < cw; x++, point += hfraq) {\n                         /* Horizontal interpolation. */\n                         long pl = POINT_L( point, hfraq );\n\n                         HVX_DEBUG( \"%ld,%ld %ld  (%ld/%ld)  0x%lx  0x%lx\\n\",\n                                    x, y, pl, POINT_L( point, hfraq ), POINT_R( point, hfraq ),\n                                    (unsigned long) point, (unsigned long) ratios[x] );\n\n                         D_ASSERT( pl >= 0 );\n                         D_ASSERT( pl < width - 1 );\n\n                         L = SOURCE_LOOKUP( srcT[pl] );\n                         R = SOURCE_LOOKUP( srcT[pl+1] );\n\n                         lbT[x] = ((((((R & X_00FF00FF) - (L & X_00FF00FF)) * ratios[x]) >> SHIFT_R8) +\n                                    (L & X_00FF00FF)) & X_00FF00FF) +\n                                  ((((((R >> SHIFT_R8) & X_00FF00FF) - ((L >> SHIFT_R8) & X_00FF00FF)) * ratios[x]) +\n                                    (L & X_FF00FF00)) & X_FF00FF00);\n\n                         L = SOURCE_LOOKUP( srcB[pl] );\n                         R = SOURCE_LOOKUP( srcB[pl+1] );\n\n                         lbB[x] = ((((((R & X_00FF00FF) - (L & X_00FF00FF)) * ratios[x]) >> SHIFT_R8) +\n                                    (L & X_00FF00FF)) & X_00FF00FF) +\n                                  ((((((R >> SHIFT_R8) & X_00FF00FF) - ((L >> SHIFT_R8) & X_00FF00FF)) * ratios[x]) +\n                                    (L & X_FF00FF00)) & X_FF00FF00);\n                    }\n               }\n               else {\n                    /* Swap. */\n                    lbX = lbT;\n                    lbT = lbB;\n                    lbB = lbX;\n\n                    for (x = 0, point = point0; x < cw; x++, point += hfraq) {\n                         /* Horizontal interpolation. */\n                         long pl = POINT_L( point, hfraq );\n\n                         HVX_DEBUG( \"%ld,%ld %ld  (%ld/%ld)  0x%lx  0x%lx\\n\",\n                                    x, y, pl, POINT_L( point, hfraq ), POINT_R( point, hfraq ),\n                                    (unsigned long) point, (unsigned long) ratios[x] );\n\n                         D_ASSERT( pl >= 0 );\n                         D_ASSERT( pl < width - 1 );\n\n                         L = SOURCE_LOOKUP( srcB[pl] );\n                         R = SOURCE_LOOKUP( srcB[pl+1] );\n\n                         lbB[x] = ((((((R & X_00FF00FF) - (L & X_00FF00FF)) * ratios[x]) >> SHIFT_R8) +\n                                    (L & X_00FF00FF)) & X_00FF00FF) +\n                                  ((((((R >> SHIFT_R8) & X_00FF00FF) - ((L >> SHIFT_R8) & X_00FF00FF)) * ratios[x]) +\n                                    (L & X_FF00FF00)) & X_FF00FF00);\n                    }\n               }\n\n               lineT = nlT;\n          }\n\n          /* Vertical interpolation. */\n          X = LINE_TO_RATIO( line, vfraq );\n\n          for (x = 0; x < cw; x++) {\n               dt = ((((((lbB[x] & X_00FF00FF) - (lbT[x] & X_00FF00FF)) * X) >> SHIFT_R8) +\n                      (lbT[x] & X_00FF00FF)) & X_00FF00FF) +\n                    ((((((lbB[x] >> SHIFT_R8) & X_00FF00FF) - ((lbT[x] >> SHIFT_R8) & X_00FF00FF)) * X) +\n                      (lbT[x] & X_FF00FF00)) & X_FF00FF00);\n\n#if defined(COLOR_KEY) || defined(KEY_PROTECT)\n#ifdef COLOR_KEY\n               if (dt != (COLOR_KEY))\n#endif\n#ifdef KEY_PROTECT\n                    /* Write to destination with color key protection. */\n                    dst32[x] = ((dt & MASK_RGB) == KEY_PROTECT) ? dt ^ 1 : dt;\n#else\n                    /* Write to destination without color key protection. */\n                    dst32[x] = dt;\n#endif\n#else /* defined(COLOR_KEY) || defined(KEY_PROTECT) */\n               /* Write to destination without color key protection. */\n               dst32[x] = dt;\n#endif /* defined(COLOR_KEY) || defined(KEY_PROTECT) */\n          }\n\n          dst32 += dp4;\n          line  += vfraq;\n     }\n}\n\n#ifdef SOURCE_LOOKUP_AUTO\n#undef SOURCE_LOOKUP_AUTO\n#undef SOURCE_LOOKUP\n#endif\n\n#ifdef SOURCE_TYPE_AUTO\n#undef SOURCE_TYPE_AUTO\n#undef SOURCE_TYPE\n#endif\n"
  },
  {
    "path": "src/gfx/generic/stretch_hvx_8.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#define SOURCE_LOOKUP(x) (x)\n#define SOURCE_TYPE u8\n\n#if D_DEBUG_ENABLED\n#define HVX_DEBUG(x...) direct_log_printf( NULL, x )\n#else\n#define HVX_DEBUG(x...) do {} while (0)\n#endif\n\n/* static void\n   stretch_hvx_8_up/down */ ( void       *dst,\n                              int         dpitch,\n                              const void *src,\n                              int         spitch,\n                              int         width,\n                              int         height,\n                              int         dst_width,\n                              int         dst_height,\n                              DFBRegion  *clip )\n{\n     long  x, y;\n     long  cw     = clip->x2 - clip->x1 + 1;\n     long  ch     = clip->y2 - clip->y1 + 1;\n     long  hfraq  = ((width  - MINUS_1) << 18) / dst_width;\n     long  vfraq  = ((height - MINUS_1) << 18) / dst_height;\n     long  point0 = POINT_0 + clip->x1 * hfraq;\n     long  point  = point0;\n     long  line   = LINE_0 + clip->y1 * vfraq;\n     long  ratios[cw];\n     u8   *dst8;\n     u8    _lbT[cw+32];\n     u8    _lbB[cw+32];\n     u8   *lbX;\n     u8   *lbT    = (u8*) ((((unsigned long) (&_lbT[0])) + 31) & ~31);\n     u8   *lbB    = (u8*) ((((unsigned long) (&_lbB[0])) + 31) & ~31);\n     long  lineT  = -2000;\n\n     for (x = 0; x < cw; x++) {\n          ratios[x] = POINT_TO_RATIO( point, hfraq );\n\n          point += hfraq;\n     }\n\n     HVX_DEBUG( \"%dx%d -> %dx%d  (0x%lx, 0x%lx)\\n\", width, height, dst_width, dst_height,\n                (unsigned long) hfraq, (unsigned long) vfraq );\n\n     dst += clip->x1 + clip->y1 * dpitch;\n\n     dst8 = dst;\n\n     /* Scale line by line.  */\n     for (y = 0; y < ch; y++) {\n          long X;\n          long nlT = LINE_T( line, vfraq );\n\n          D_ASSERT( nlT >= 0 );\n          D_ASSERT( nlT < height - 1 );\n\n          /* Fill line buffer(s). */\n          if (nlT != lineT) {\n               u8 L, R;\n               const SOURCE_TYPE *srcT = src + spitch * nlT;\n               const SOURCE_TYPE *srcB = src + spitch * (nlT + 1);\n               long               diff = nlT - lineT;\n\n               if (diff > 1) {\n                    for (x = 0, point = point0; x < cw; x++, point += hfraq) {\n                         /* Horizontal interpolation. */\n                         long pl = POINT_L( point, hfraq );\n\n                         HVX_DEBUG( \"%ld,%ld %ld  (%ld/%ld)  0x%lx  0x%lx\\n\",\n                                    x, y, pl, POINT_L( point, hfraq ), POINT_R( point, hfraq ),\n                                    (unsigned long) point, (unsigned long) ratios[x] );\n\n                         D_ASSERT( pl >= 0 );\n                         D_ASSERT( pl < width - 1 );\n\n                         L = SOURCE_LOOKUP( srcT[pl] );\n                         R = SOURCE_LOOKUP( srcT[pl+1] );\n\n                         lbT[x] = (((R - L) * ratios[x]) >> 8) + L;\n\n                         L = SOURCE_LOOKUP( srcB[pl] );\n                         R = SOURCE_LOOKUP( srcB[pl+1] );\n\n                         lbB[x] = (((R - L) * ratios[x]) >> 8) + L;\n                    }\n               }\n               else {\n                    /* Swap. */\n                    lbX = lbT;\n                    lbT = lbB;\n                    lbB = lbX;\n\n                    for (x = 0, point = point0; x < cw; x++, point += hfraq) {\n                         /* Horizontal interpolation. */\n                         long pl = POINT_L( point, hfraq );\n\n                         HVX_DEBUG( \"%ld,%ld %ld  (%ld/%ld)  0x%lx  0x%lx\\n\",\n                                    x, y, pl, POINT_L( point, hfraq ), POINT_R( point, hfraq ),\n                                    (unsigned long) point, (unsigned long) ratios[x] );\n\n                         D_ASSERT( pl >= 0 );\n                         D_ASSERT( pl < width - 1 );\n\n                         L = SOURCE_LOOKUP( srcB[pl] );\n                         R = SOURCE_LOOKUP( srcB[pl+1] );\n\n                         lbB[x] = (((R - L) * ratios[x]) >> 8) + L;\n                    }\n               }\n\n               lineT = nlT;\n          }\n\n          /* Vertical interpolation. */\n          X = LINE_TO_RATIO( line, vfraq );\n\n          for (x = 0; x < cw; x++)\n               dst8[x] = (((lbB[x] - lbT[x]) * X) >> 8) + lbT[x];\n\n          dst8 += dpitch;\n          line += vfraq;\n     }\n}\n\n#undef SOURCE_LOOKUP\n#undef SOURCE_TYPE\n"
  },
  {
    "path": "src/gfx/generic/stretch_hvx_88.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#define SOURCE_LOOKUP(x) (x)\n#define SOURCE_TYPE u16\n\n#if D_DEBUG_ENABLED\n#define HVX_DEBUG(x...) direct_log_printf( NULL, x )\n#else\n#define HVX_DEBUG(x...) do {} while (0)\n#endif\n\n/* static void\n   stretch_hvx_88_up/down */ ( void       *dst,\n                               int         dpitch,\n                               const void *src,\n                               int         spitch,\n                               int         width,\n                               int         height,\n                               int         dst_width,\n                               int         dst_height,\n                               DFBRegion  *clip )\n\n{\n     long  x, y;\n     long  cw     = clip->x2 - clip->x1 + 1;\n     long  ch     = clip->y2 - clip->y1 + 1;\n     long  hfraq  = ((width  - MINUS_1) << 18) / dst_width;\n     long  vfraq  = ((height - MINUS_1) << 18) / dst_height;\n     long  point0 = POINT_0 + clip->x1 * hfraq;\n     long  point  = point0;\n     long  line   = LINE_0 + clip->y1 * vfraq;\n     long  ratios[cw];\n     u16  *dst16;\n     u16   _lbT[cw+16];\n     u16   _lbB[cw+16];\n     u16  *lbX;\n     u16  *lbT    = (u16*) ((((unsigned long) (&_lbT[0])) + 31) & ~31);\n     u16  *lbB    = (u16*) ((((unsigned long) (&_lbB[0])) + 31) & ~31);\n     long  lineT  = -2000;\n\n     for (x = 0; x < cw; x++) {\n          ratios[x] = POINT_TO_RATIO( point, hfraq );\n\n          point += hfraq;\n     }\n\n     HVX_DEBUG( \"%dx%d -> %dx%d  (0x%lx, 0x%lx)\\n\", width, height, dst_width, dst_height,\n                (unsigned long) hfraq, (unsigned long) vfraq );\n\n     dst += clip->x1 * 2 + clip->y1 * dpitch;\n\n     dst16 = dst;\n\n     /* Scale line by line. */\n     for (y = 0; y < ch; y++) {\n          long X;\n          long nlT = LINE_T( line, vfraq );\n\n          D_ASSERT( nlT >= 0 );\n          D_ASSERT( nlT < height - 1 );\n\n          /* Fill line buffer(s). */\n          if (nlT != lineT) {\n               u16 L, R;\n               const SOURCE_TYPE *srcT = src + spitch * nlT;\n               const SOURCE_TYPE *srcB = src + spitch * (nlT + 1);\n               long               diff = nlT - lineT;\n\n               if (diff > 1) {\n                    for (x = 0, point = point0; x < cw; x++, point += hfraq) {\n                         /* Horizontal interpolation. */\n                         long pl = POINT_L( point, hfraq );\n\n                         HVX_DEBUG( \"%ld,%ld %ld  (%ld/%ld)  0x%lx  0x%lx\\n\",\n                                    x, y, pl, POINT_L( point, hfraq ), POINT_R( point, hfraq ),\n                                    (unsigned long) point, (unsigned long) ratios[x] );\n\n                         D_ASSERT( pl >= 0 );\n                         D_ASSERT( pl < width - 1 );\n\n                         L = SOURCE_LOOKUP( srcT[pl] );\n                         R = SOURCE_LOOKUP( srcT[pl+1] );\n\n                         lbT[x] = (((((R & 0x00ff) - (L & 0x00ff)) * ratios[x] + ((L & 0x00ff) << 8)) & 0x00ff00) +\n                                   ((((R & 0xff00) - (L & 0xff00)) * ratios[x] + ((L & 0xff00) << 8)) & 0xff0000)) >> 8;\n\n                         L = SOURCE_LOOKUP( srcB[pl] );\n                         R = SOURCE_LOOKUP( srcB[pl+1] );\n\n                         lbB[x] = (((((R & 0x00ff) - (L & 0x00ff)) * ratios[x] + ((L & 0x00ff) << 8)) & 0x00ff00) +\n                                   ((((R & 0xff00) - (L & 0xff00)) * ratios[x] + ((L & 0xff00) << 8)) & 0xff0000)) >> 8;\n                    }\n               }\n               else {\n                    /* Swap. */\n                    lbX = lbT;\n                    lbT = lbB;\n                    lbB = lbX;\n\n                    for (x = 0, point = point0; x < cw; x++, point += hfraq) {\n                         /* Horizontal interpolation. */\n                         long pl = POINT_L( point, hfraq );\n\n                         HVX_DEBUG( \"%ld,%ld %ld  (%ld/%ld)  0x%lx  0x%lx\\n\",\n                                    x, y, pl, POINT_L( point, hfraq ), POINT_R( point, hfraq ),\n                                    (unsigned long) point, (unsigned long) ratios[x] );\n\n                         D_ASSERT( pl >= 0 );\n                         D_ASSERT( pl < width - 1 );\n\n                         L = SOURCE_LOOKUP( srcB[pl] );\n                         R = SOURCE_LOOKUP( srcB[pl+1] );\n\n                         lbB[x] = (((((R & 0x00ff) - (L & 0x00ff)) * ratios[x] + ((L & 0x00ff) << 8)) & 0x00ff00) +\n                                   ((((R & 0xff00) - (L & 0xff00)) * ratios[x] + ((L & 0xff00) << 8)) & 0xff0000)) >> 8;\n                    }\n               }\n\n               lineT = nlT;\n          }\n\n          /* Vertical interpolation. */\n          X = LINE_TO_RATIO( line, vfraq );\n\n          for (x = 0; x < cw; x++)\n               dst16[x] = (((((lbB[x] & 0x00ff) - (lbT[x] & 0x00ff)) * X + ((lbT[x] & 0x00ff) << 8)) & 0x00ff00) +\n                           ((((lbB[x] & 0xff00) - (lbT[x] & 0xff00)) * X + ((lbT[x] & 0xff00) << 8)) & 0xff0000)) >> 8;\n\n          dst16 += dpitch / 2;\n          line  += vfraq;\n     }\n}\n\n#undef SOURCE_LOOKUP\n#undef SOURCE_TYPE\n"
  },
  {
    "path": "src/gfx/generic/stretch_hvx_N.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#if UPDOWN == 1\n#define FUNC_NAME_(K,P,F) FUNC_NAME(up,K,P,F)\n#else\n#define FUNC_NAME_(K,P,F) FUNC_NAME(down,K,P,F)\n#endif\n\n/**********************************************************************************************************************/\n/* DST_FORMAT */\n\n/* DST_FORMAT NONE */\nstatic void\nFUNC_NAME_(_,_,DST_FORMAT)\n#include STRETCH_HVX_N_H\n\n/* DST_FORMAT SRCKEY */\n#define COLOR_KEY ctx->key\nstatic void\nFUNC_NAME_(K,_,DST_FORMAT)\n#include STRETCH_HVX_N_H\n#undef COLOR_KEY\n\n/* DST_FORMAT PROTECT */\n#define KEY_PROTECT ctx->protect\nstatic void\nFUNC_NAME_(_,P,DST_FORMAT)\n#include STRETCH_HVX_N_H\n\n/* DST_FORMAT SRCKEY PROTECT */\n#define COLOR_KEY ctx->key\nstatic void\nFUNC_NAME_(K,P,DST_FORMAT)\n#include STRETCH_HVX_N_H\n#undef COLOR_KEY\n#undef KEY_PROTECT\n\n/**********************************************************************************************************************/\n/* DSPF_LUT8 */\n#define SOURCE_LOOKUP(x) ((const uN*) ctx->colors)[x]\n#define SOURCE_TYPE      u8\n\n/* DSPF_LUT8 NONE */\nstatic void\nFUNC_NAME_(_,_,DSPF_LUT8)\n#include STRETCH_HVX_N_H\n\n/* DSPF_LUT8 SRCKEY */\n#define COLOR_KEY ctx->key\nstatic void\nFUNC_NAME_(K,_,DSPF_LUT8)\n#include STRETCH_HVX_N_H\n#undef COLOR_KEY\n\n/* DSPF_LUT8 PROTECT */\n#define KEY_PROTECT ctx->protect\nstatic void\nFUNC_NAME_(_,P,DSPF_LUT8)\n#include STRETCH_HVX_N_H\n\n/* DSPF_LUT8 SRCKEY PROTECT */\n#define COLOR_KEY ctx->key\nstatic void\nFUNC_NAME_(K,P,DSPF_LUT8)\n#include STRETCH_HVX_N_H\n#undef COLOR_KEY\n#undef KEY_PROTECT\n\n#undef SOURCE_LOOKUP\n#undef SOURCE_TYPE\n\n#ifdef FORMAT_RGB16\n\n/**********************************************************************************************************************/\n/* DSPF_ARGB4444 */\n#define SOURCE_LOOKUP(x) PIXEL_RGB16( (((x) & 0x0f00) >> 4) | (((x) & 0x0f00) >> 8), \\\n                                      ( (x) & 0x00f0      ) | (((x) & 0x00f0) >> 4), \\\n                                      (((x) & 0x000f) << 4) | ( (x) & 0x000f      ) )\n\n/* DSPF_ARGB4444 NONE */\nstatic void\nFUNC_NAME_(_,_,DSPF_ARGB4444)\n#include STRETCH_HVX_N_H\n\n/* DSPF_ARGB4444 SRCKEY */\n#define COLOR_KEY ctx->key\nstatic void\nFUNC_NAME_(K,_,DSPF_ARGB4444)\n#include STRETCH_HVX_N_H\n#undef COLOR_KEY\n\n/* DSPF_ARGB4444 PROTECT */\n#define KEY_PROTECT ctx->protect\nstatic void\nFUNC_NAME_(_,P,DSPF_ARGB4444)\n#include STRETCH_HVX_N_H\n\n/* DSPF_ARGB4444 PROTECT SRCKEY */\n#define COLOR_KEY ctx->key\nstatic void\nFUNC_NAME_(K,P,DSPF_ARGB4444)\n#include STRETCH_HVX_N_H\n#undef COLOR_KEY\n#undef KEY_PROTECT\n\n#undef SOURCE_LOOKUP\n\n#endif /* FORMAT_RGB16 */\n\n#ifdef FORMAT_ARGB4444\n\n/**********************************************************************************************************************/\n/* DSPF_RGB16 */\n#define SOURCE_LOOKUP(x) PIXEL_ARGB4444( 0xff,                  \\\n                                         (((x) & 0xf800) >> 8), \\\n                                         (((x) & 0x07e0) >> 3), \\\n                                         (((x) & 0x001f) << 3) )\n\n/* DSPF_RGB16 NONE */\nstatic void\nFUNC_NAME_(_,_,DSPF_RGB16)\n#include STRETCH_HVX_N_H\n\n/* DSPF_RGB16 SRCKEY */\n#define COLOR_KEY ctx->key\nstatic void\nFUNC_NAME_(K,_,DSPF_RGB16)\n#include STRETCH_HVX_N_H\n#undef COLOR_KEY\n\n/* DSPF_RGB16 PROTECT */\n#define KEY_PROTECT ctx->protect\nstatic void\nFUNC_NAME_(_,P,DSPF_RGB16)\n#include STRETCH_HVX_N_H\n\n/* DSPF_RGB16 PROTECT SRCKEY */\n#define COLOR_KEY ctx->key\nstatic void\nFUNC_NAME_(K,P,DSPF_RGB16)\n#include STRETCH_HVX_N_H\n#undef COLOR_KEY\n#undef KEY_PROTECT\n\n#undef SOURCE_LOOKUP\n\n#endif /* FORMAT_ARGB4444 */\n\n/**********************************************************************************************************************/\n\n#undef FUNC_NAME_\n"
  },
  {
    "path": "src/gfx/generic/stretch_up_down_16.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#define STRETCH_HVX_N_H \"stretch_hvx_16.h\"\n#define uN u16\n\n/**********************************************************************************************************************/\n/* Upscaling */\n\n#define POINT_0              0\n#define LINE_0               0\n#define MINUS_1              1\n#define POINT_TO_RATIO(p,ps) ( ((p) & 0x3ffff) >> (18 - SHIFT_L6) )\n#define LINE_TO_RATIO(l,ls)  ( ((l) & 0x3ffff) >> (18 - SHIFT_L5) )\n#define POINT_L(p,ps)        (  (p) >> 18 )\n#define POINT_R(p,ps)        ( ((p) >> 18) + 1 )\n#define LINE_T(l,ls)         (  (l) >> 18 )\n#define LINE_B(l,ls)         ( ((l) >> 18) + 1 )\n\n#define UPDOWN 1\n#include \"stretch_hvx_N.h\"\n#undef UPDOWN\n\n#undef POINT_0\n#undef LINE_0\n#undef MINUS_1\n#undef POINT_TO_RATIO\n#undef LINE_TO_RATIO\n#undef POINT_L\n#undef POINT_R\n#undef LINE_T\n#undef LINE_B\n\n/**********************************************************************************************************************/\n/* Downscaling */\n\n#define POINT_0              hfraq\n#define LINE_0               vfraq\n#define MINUS_1              0\n#define POINT_TO_RATIO(p,ps) ( ((((p) & 0x3ffff) ?: 0x40000) << SHIFT_L6) / (ps) )\n#define LINE_TO_RATIO(l,ls)  ( ((((l) & 0x3ffff) ?: 0x40000) << SHIFT_L5) / (ls) )\n#define POINT_L(p,ps)        (  (((p) - 1) >> 18) - 1 )\n#define POINT_R(p,ps)        (   ((p) - 1) >> 18 )\n#define LINE_T(l,ls)         (  (((l) - 1) >> 18) - 1 )\n#define LINE_B(l,ls)         (   ((l) - 1) >> 18 )\n\n#define UPDOWN 0\n#include \"stretch_hvx_N.h\"\n#undef UPDOWN\n\n#undef POINT_0\n#undef LINE_0\n#undef MINUS_1\n#undef POINT_TO_RATIO\n#undef LINE_TO_RATIO\n#undef POINT_L\n#undef POINT_R\n#undef LINE_T\n#undef LINE_B\n\n/**********************************************************************************************************************/\n\n#undef STRETCH_HVX_N_H\n#undef uN\n\n#include \"stretch_up_down_table.h\"\n"
  },
  {
    "path": "src/gfx/generic/stretch_up_down_32.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#define STRETCH_HVX_N_H  \"stretch_hvx_32.h\"\n#define uN u32\n\n/**********************************************************************************************************************/\n/* Upscaling */\n\n#define POINT_0              0\n#define LINE_0               0\n#define MINUS_1              1\n#define POINT_TO_RATIO(p,ps) ( ((p) & 0x3ffff) >> (18 - SHIFT_L8) )\n#define LINE_TO_RATIO(l,ls)  ( ((l) & 0x3ffff) >> (18 - SHIFT_L8) )\n#define POINT_L(p,ps)        (  (p) >> 18 )\n#define POINT_R(p,ps)        ( ((p) >> 18) + 1 )\n#define LINE_T(l,ls)         (  (l) >> 18 )\n#define LINE_B(l,ls)         ( ((l) >> 18) + 1 )\n\n#define UPDOWN 1\n#include \"stretch_hvx_N.h\"\n#undef UPDOWN\n\n#undef POINT_0\n#undef LINE_0\n#undef MINUS_1\n#undef POINT_TO_RATIO\n#undef LINE_TO_RATIO\n#undef POINT_L\n#undef POINT_R\n#undef LINE_T\n#undef LINE_B\n\n/**********************************************************************************************************************/\n/* Downscaling */\n\n#define POINT_0              hfraq\n#define LINE_0               vfraq\n#define MINUS_1              0\n#define POINT_TO_RATIO(p,ps) ( ((((p) & 0x3ffff) ?: 0x40000) << SHIFT_L8) / (ps) )\n#define LINE_TO_RATIO(l,ls)  ( ((((l) & 0x3ffff) ?: 0x40000) << SHIFT_L8) / (ls) )\n#define POINT_L(p,ps)        (  (((p) - 1) >> 18) - 1 )\n#define POINT_R(p,ps)        (   ((p) - 1) >> 18 )\n#define LINE_T(l,ls)         (  (((l) - 1) >> 18) - 1 )\n#define LINE_B(l,ls)         (   ((l) - 1) >> 18 )\n\n#define UPDOWN 0\n#include \"stretch_hvx_N.h\"\n#undef UPDOWN\n\n#undef POINT_0\n#undef LINE_0\n#undef MINUS_1\n#undef POINT_TO_RATIO\n#undef LINE_TO_RATIO\n#undef POINT_L\n#undef POINT_R\n#undef LINE_T\n#undef LINE_B\n\n/**********************************************************************************************************************/\n\n#undef STRETCH_HVX_N_H\n#undef uN\n\n#include \"stretch_up_down_table.h\"\n"
  },
  {
    "path": "src/gfx/generic/stretch_up_down_8.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n/**********************************************************************************************************************/\n/* Upscaling */\n\n#define POINT_0              0\n#define LINE_0               0\n#define MINUS_1              1\n#define POINT_TO_RATIO(p,ps) ( ((p) & 0x3ffff) >> (18 - 8) )\n#define LINE_TO_RATIO(l,ls)  ( ((l) & 0x3ffff) >> (18 - 8) )\n#define POINT_L(p,ps)        (  (p) >> 18 )\n#define POINT_R(p,ps)        ( ((p) >> 18) + 1 )\n#define LINE_T(l,ls)         (  (l) >> 18 )\n#define LINE_B(l,ls)         ( ((l) >> 18) + 1 )\n\nstatic void\nFUNC_NAME(up)\n#include \"stretch_hvx_8.h\"\n\n#undef POINT_0\n#undef LINE_0\n#undef MINUS_1\n#undef POINT_TO_RATIO\n#undef LINE_TO_RATIO\n#undef POINT_L\n#undef POINT_R\n#undef LINE_T\n#undef LINE_B\n\n/**********************************************************************************************************************/\n/* Downscaling */\n\n#define POINT_0              hfraq\n#define LINE_0               vfraq\n#define MINUS_1              0\n#define POINT_TO_RATIO(p,ps) ( ((((p) & 0x3ffff) ?: 0x40000) << 8) / (ps) )\n#define LINE_TO_RATIO(l,ls)  ( ((((l) & 0x3ffff) ?: 0x40000) << 8) / (ls) )\n#define POINT_L(p,ps)        (  (((p) - 1) >> 18) - 1 )\n#define POINT_R(p,ps)        (   ((p) - 1) >> 18 )\n#define LINE_T(l,ls)         (  (((l) - 1) >> 18) - 1 )\n#define LINE_B(l,ls)         (   ((l) - 1) >> 18 )\n\nstatic void\nFUNC_NAME(down)\n#include \"stretch_hvx_8.h\"\n\n#undef POINT_0\n#undef LINE_0\n#undef MINUS_1\n#undef POINT_TO_RATIO\n#undef LINE_TO_RATIO\n#undef POINT_L\n#undef POINT_R\n#undef LINE_T\n#undef LINE_B\n"
  },
  {
    "path": "src/gfx/generic/stretch_up_down_88.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n/**********************************************************************************************************************/\n/* Upscaling */\n\n#define POINT_0              0\n#define LINE_0               0\n#define MINUS_1              1\n#define POINT_TO_RATIO(p,ps) ( ((p) & 0x3ffff) >> (18 - 8) )\n#define LINE_TO_RATIO(l,ls)  ( ((l) & 0x3ffff) >> (18 - 8) )\n#define POINT_L(p,ps)        (  (p) >> 18 )\n#define POINT_R(p,ps)        ( ((p) >> 18) + 1 )\n#define LINE_T(l,ls)         (  (l) >> 18 )\n#define LINE_B(l,ls)         ( ((l) >> 18) + 1 )\n\nstatic void\nFUNC_NAME(up)\n#include \"stretch_hvx_88.h\"\n\n#undef POINT_0\n#undef LINE_0\n#undef MINUS_1\n#undef POINT_TO_RATIO\n#undef LINE_TO_RATIO\n#undef POINT_L\n#undef POINT_R\n#undef LINE_T\n#undef LINE_B\n\n/**********************************************************************************************************************/\n/* Downscaling */\n\n#define POINT_0              hfraq\n#define LINE_0               vfraq\n#define MINUS_1              0\n#define POINT_TO_RATIO(p,ps) ( ((((p) & 0x3ffff) ?: 0x40000) << 8) / (ps) )\n#define LINE_TO_RATIO(l,ls)  ( ((((l) & 0x3ffff) ?: 0x40000) << 8) / (ls) )\n#define POINT_L(p,ps)        (  (((p) - 1) >> 18) - 1 )\n#define POINT_R(p,ps)        (   ((p) - 1) >> 18 )\n#define LINE_T(l,ls)         (  (((l) - 1) >> 18) - 1 )\n#define LINE_B(l,ls)         (   ((l) - 1) >> 18 )\n\nstatic void\nFUNC_NAME(down)\n#include \"stretch_hvx_88.h\"\n\n#undef POINT_0\n#undef LINE_0\n#undef MINUS_1\n#undef POINT_TO_RATIO\n#undef LINE_TO_RATIO\n#undef POINT_L\n#undef POINT_R\n#undef LINE_T\n#undef LINE_B\n"
  },
  {
    "path": "src/gfx/generic/stretch_up_down_table.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\nstatic const StretchFunctionTable TABLE_NAME = {\n#define FUNC_NAME_(K,P,F) FUNC_NAME(up,K,P,F)\n     .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].up[STRETCH_NONE]                = FUNC_NAME_(_,_,DST_FORMAT),\n     .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].up[STRETCH_PROTECT]             = FUNC_NAME_(_,P,DST_FORMAT),\n     .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].up[STRETCH_SRCKEY]              = FUNC_NAME_(K,_,DST_FORMAT),\n     .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].up[STRETCH_SRCKEY_PROTECT]      = FUNC_NAME_(K,P,DST_FORMAT),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].up[STRETCH_NONE]                 = FUNC_NAME_(_,_,DSPF_LUT8),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].up[STRETCH_PROTECT]              = FUNC_NAME_(_,P,DSPF_LUT8),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].up[STRETCH_SRCKEY]               = FUNC_NAME_(K,_,DSPF_LUT8),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].up[STRETCH_SRCKEY_PROTECT]       = FUNC_NAME_(K,P,DSPF_LUT8),\n#ifdef FORMAT_RGB16\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].up[STRETCH_NONE]             = FUNC_NAME_(_,_,DSPF_ARGB4444),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].up[STRETCH_PROTECT]          = FUNC_NAME_(_,P,DSPF_ARGB4444),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].up[STRETCH_SRCKEY]           = FUNC_NAME_(K,_,DSPF_ARGB4444),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].up[STRETCH_SRCKEY_PROTECT]   = FUNC_NAME_(K,P,DSPF_ARGB4444),\n#endif\n#ifdef FORMAT_ARGB4444\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].up[STRETCH_NONE]                = FUNC_NAME_(_,_,DSPF_RGB16),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].up[STRETCH_PROTECT]             = FUNC_NAME_(_,P,DSPF_RGB16),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].up[STRETCH_SRCKEY]              = FUNC_NAME_(K,_,DSPF_RGB16),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].up[STRETCH_SRCKEY_PROTECT]      = FUNC_NAME_(K,P,DSPF_RGB16),\n#endif\n#undef FUNC_NAME_\n\n#define FUNC_NAME_(K,P,F) FUNC_NAME(down,K,P,F)\n     .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].down[STRETCH_NONE]              = FUNC_NAME_(_,_,DST_FORMAT),\n     .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].down[STRETCH_PROTECT]           = FUNC_NAME_(_,P,DST_FORMAT),\n     .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].down[STRETCH_SRCKEY]            = FUNC_NAME_(K,_,DST_FORMAT),\n     .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].down[STRETCH_SRCKEY_PROTECT]    = FUNC_NAME_(K,P,DST_FORMAT),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].down[STRETCH_NONE]               = FUNC_NAME_(_,_,DSPF_LUT8),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].down[STRETCH_PROTECT]            = FUNC_NAME_(_,P,DSPF_LUT8),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].down[STRETCH_SRCKEY]             = FUNC_NAME_(K,_,DSPF_LUT8),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].down[STRETCH_SRCKEY_PROTECT]     = FUNC_NAME_(K,P,DSPF_LUT8),\n#ifdef FORMAT_RGB16\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].down[STRETCH_NONE]           = FUNC_NAME_(_,_,DSPF_ARGB4444),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].down[STRETCH_PROTECT]        = FUNC_NAME_(_,P,DSPF_ARGB4444),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].down[STRETCH_SRCKEY]         = FUNC_NAME_(K,_,DSPF_ARGB4444),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].down[STRETCH_SRCKEY_PROTECT] = FUNC_NAME_(K,P,DSPF_ARGB4444),\n#endif\n#ifdef FORMAT_ARGB4444\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].down[STRETCH_NONE]              = FUNC_NAME_(_,_,DSPF_RGB16),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].down[STRETCH_PROTECT]           = FUNC_NAME_(_,P,DSPF_RGB16),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].down[STRETCH_SRCKEY]            = FUNC_NAME_(K,_,DSPF_RGB16),\n     .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].down[STRETCH_SRCKEY_PROTECT]    = FUNC_NAME_(K,P,DSPF_RGB16),\n#endif\n#undef FUNC_NAME_\n};\n"
  },
  {
    "path": "src/gfx/generic/template_acc_16.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#define RGB_MASK (R_MASK | G_MASK | B_MASK)\n\n#if RGB_MASK == 0xffff\n#define MASK_RGB(p) (p)\n#else\n#define MASK_RGB(p) ((p) & RGB_MASK)\n#endif\n\n#define PIXEL(x) PIXEL_OUT( ((x).RGB.a & 0xff00) ? 0xff : (x).RGB.a, \\\n                            ((x).RGB.r & 0xff00) ? 0xff : (x).RGB.r, \\\n                            ((x).RGB.g & 0xff00) ? 0xff : (x).RGB.g, \\\n                            ((x).RGB.b & 0xff00) ? 0xff : (x).RGB.b )\n\n#define EXPAND(d,s) do {                                 \\\n     (d).RGB.a = EXPAND_Ato8( (s & A_MASK) >> A_SHIFT ); \\\n     (d).RGB.r = EXPAND_Rto8( (s & R_MASK) >> R_SHIFT ); \\\n     (d).RGB.g = EXPAND_Gto8( (s & G_MASK) >> G_SHIFT ); \\\n     (d).RGB.b = EXPAND_Bto8( (s & B_MASK) >> B_SHIFT ); \\\n} while (0)\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_to_Dacc ********************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_PFI_OP_Dacc(to)( GenefxState *gfxs )\n{\n     int                l;\n     int                w     = gfxs->length;\n     u16               *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                Ostep = gfxs->Ostep;\n\n     if (Ostep != 1) {\n          w++;\n          while (--w) {\n               u16 s = *S;\n\n               EXPAND( *D, s );\n\n               S += Ostep;\n               ++D;\n          }\n\n          return;\n     }\n\n     if ((long) S & 2) {\n          u16 s = *S++;\n\n          EXPAND( *D, s );\n\n          ++D;\n          --w;\n     }\n\n     l = (w >> 1) + 1;\n     while (--l) {\n          u32 s = *(u32*) S;\n\n#ifdef WORDS_BIGENDIAN\n          EXPAND( D[0], s >> 16 );\n          EXPAND( D[1], s );\n#else\n          EXPAND( D[0], s );\n          EXPAND( D[1], s >> 16 );\n#endif\n\n          S += 2;\n          D += 2;\n     }\n\n     if (w & 1) {\n          u16 s = *S;\n\n          EXPAND( *D, s );\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_Kto_Dacc *******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_PFI_OP_Dacc(Kto)( GenefxState *gfxs )\n{\n     int                w     = gfxs->length + 1;\n     u16               *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     u16                Skey  = gfxs->Skey;\n     int                Ostep = gfxs->Ostep;\n\n     while (--w) {\n          u16 s = *S;\n\n          if (MASK_RGB( s ) != Skey)\n               EXPAND( *D, s );\n          else\n               D->RGB.a = 0xf000;\n\n          S += Ostep;\n          ++D;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_Sto_Dacc *******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_PFI_OP_Dacc(Sto)( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u16               *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                SperD = gfxs->SperD;\n     int                Ostep = gfxs->Ostep;\n\n     if (Ostep != 1)\n          D_UNIMPLEMENTED();\n\n     while (--w) {\n          u16 s = S[i>>16];\n\n          EXPAND( *D, s );\n\n          ++D;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_SKto_Dacc ******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_PFI_OP_Dacc(SKto)( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u16               *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     u16                Skey  = gfxs->Skey;\n     int                SperD = gfxs->SperD;\n     int                Ostep = gfxs->Ostep;\n\n     if (Ostep != 1)\n          D_UNIMPLEMENTED();\n\n     while (--w) {\n          u16 s = S[i>>16];\n\n          if (MASK_RGB( s ) != Skey)\n               EXPAND( *D, s );\n          else\n               D->RGB.a = 0xf000;\n\n          ++D;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_TEX_to_Dacc ****************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_PFI_OP_Dacc(TEX_to)( GenefxState *gfxs )\n{\n     int                s     = gfxs->s;\n     int                t     = gfxs->t;\n     int                w     = gfxs->length + 1;\n     u16               *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                sp2   = gfxs->src_pitch / 2;\n     int                SperD = gfxs->SperD;\n     int                TperD = gfxs->TperD;\n     int                Ostep = gfxs->Ostep;\n\n     if (Ostep != 1)\n          D_UNIMPLEMENTED();\n\n     while (--w) {\n          u16 p = S[(s>>16)+(t>>16)*sp2];\n\n          EXPAND( *D, p );\n\n          ++D;\n          s += SperD;\n          t += TperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_TEX_Kto_Dacc ***************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_PFI_OP_Dacc(TEX_Kto)( GenefxState *gfxs )\n{\n     int                s     = gfxs->s;\n     int                t     = gfxs->t;\n     int                w     = gfxs->length + 1;\n     u16               *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                sp2   = gfxs->src_pitch / 2;\n     u16                Skey  = gfxs->Skey;\n     int                SperD = gfxs->SperD;\n     int                TperD = gfxs->TperD;\n     int                Ostep = gfxs->Ostep;\n\n     if (Ostep != 1)\n          D_UNIMPLEMENTED();\n\n     while (--w) {\n          u16 p = S[(s>>16)+(t>>16)*sp2];\n\n          if ((p & RGB_MASK) != Skey)\n               EXPAND( *D, p );\n          else\n               D->RGB.a = 0xf000;\n\n          ++D;\n          s += SperD;\n          t += TperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sacc_to_Aop_PFI ********************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSacc_OP_Aop_PFI(to)( GenefxState *gfxs )\n{\n     int                l;\n     int                w     = gfxs->length;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u16               *D     = gfxs->Aop[0];\n     int                Dstep = gfxs->Astep;\n\n     if (Dstep != 1) {\n          w++;\n          while (--w) {\n               if (!(S->RGB.a & 0xf000))\n                    *D = PIXEL( *S );\n\n               ++S;\n               D += Dstep;\n          }\n\n          return;\n     }\n\n     if ((long) D & 2) {\n          if (!(S->RGB.a & 0xf000))\n               *D = PIXEL( *S );\n\n          ++S;\n          ++D;\n          --w;\n     }\n\n     l = (w >> 1) + 1;\n     while (--l) {\n          u32 *D2 = (u32*) D;\n\n          if (!(S[0].RGB.a & 0xf000) && !(S[1].RGB.a & 0xf000)) {\n#ifdef WORDS_BIGENDIAN\n               *D2 = PIXEL( S[1] ) | PIXEL( S[0] ) << 16;\n#else\n               *D2 = PIXEL( S[0] ) | PIXEL( S[1] ) << 16;\n#endif\n          }\n          else {\n               if (!(S[0].RGB.a & 0xf000))\n                    D[0] = PIXEL( S[0] );\n               else if (!(S[1].RGB.a & 0xf000))\n                    D[1] = PIXEL( S[1] );\n          }\n\n          S += 2;\n          D += 2;\n     }\n\n     if (w & 1) {\n          if (!(S->RGB.a & 0xf000))\n               *D = PIXEL( *S );\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sacc_toK_Aop_PFI *******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSacc_OP_Aop_PFI(toK)( GenefxState *gfxs )\n{\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u16               *D     = gfxs->Aop[0];\n     u16                Dkey  = gfxs->Dkey;\n     int                Dstep = gfxs->Astep;\n\n     while (--w) {\n          if (!(S->RGB.a & 0xf000) && MASK_RGB( *D ) == Dkey)\n               *D = PIXEL( *S );\n\n          ++S;\n          D += Dstep;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sacc_Sto_Aop_PFI *******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSacc_OP_Aop_PFI(Sto)( GenefxState *gfxs )\n{\n     int                l;\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u16               *D     = gfxs->Aop[0];\n     int                Dstep = gfxs->Astep;\n     int                SperD = gfxs->SperD;\n\n     if (Dstep != 1) {\n         w++;\n         while (--w) {\n               GenefxAccumulator *S0 = &S[i>>16];\n\n               if (!(S0->RGB.a & 0xf000))\n                    *D = PIXEL( *S0 );\n\n               D += Dstep;\n               i += SperD;\n         }\n\n         return;\n     }\n\n     if ((long) D & 2) {\n          if (!(S->RGB.a & 0xf000))\n               *D = PIXEL( *S );\n\n          ++D;\n          --w;\n          i += SperD;\n     }\n\n     l = (w >> 1) + 1;\n     while (--l) {\n          GenefxAccumulator *S0 = &S[i>>16];\n          GenefxAccumulator *S1 = &S[(i+SperD)>>16];\n          u32               *D2 = (u32*) D;\n\n          if (!(S0->RGB.a & 0xf000) && !(S1->RGB.a & 0xf000)) {\n#ifdef WORDS_BIGENDIAN\n               *D2 = PIXEL( *S1 ) | PIXEL( *S0 ) << 16;\n#else\n               *D2 = PIXEL( *S0 ) | PIXEL( *S1 ) << 16;\n#endif\n          }\n          else {\n               if (!(S0->RGB.a & 0xf000))\n                    D[0] = PIXEL( *S0 );\n               else if (!(S1->RGB.a & 0xf000))\n                    D[1] = PIXEL( *S1 );\n          }\n\n          D += 2;\n          i += SperD << 1;\n     }\n\n     if (w & 1) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->RGB.a & 0xf000))\n               *D = PIXEL( *S0 );\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sacc_StoK_Aop_PFI ******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSacc_OP_Aop_PFI(StoK)( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u16               *D     = gfxs->Aop[0];\n     u16                Dkey  = gfxs->Dkey;\n     int                Dstep = gfxs->Astep;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->RGB.a & 0xf000) && MASK_RGB( *D ) == Dkey)\n               *D = PIXEL( *S0 );\n\n          D += Dstep;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************/\n\n#undef RGB_MASK\n#undef MASK_RGB\n#undef PIXEL\n#undef EXPAND\n\n#undef A_SHIFT\n#undef R_SHIFT\n#undef G_SHIFT\n#undef B_SHIFT\n#undef A_MASK\n#undef R_MASK\n#undef G_MASK\n#undef B_MASK\n#undef PIXEL_OUT\n#undef EXPAND_Ato8\n#undef EXPAND_Rto8\n#undef EXPAND_Gto8\n#undef EXPAND_Bto8\n#undef Sop_PFI_OP_Dacc\n#undef Sacc_OP_Aop_PFI\n"
  },
  {
    "path": "src/gfx/generic/template_acc_24.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#define RGB_MASK (R_MASK | G_MASK | B_MASK)\n\n#if RGB_MASK == 0xffffff\n#define MASK_RGB(p) (p)\n#else\n#define MASK_RGB(p) ((p) & RGB_MASK)\n#endif\n\n#define PIXEL(x) PIXEL_OUT( ((x).RGB.a & 0xff00) ? 0xff : (x).RGB.a, \\\n                            ((x).RGB.r & 0xff00) ? 0xff : (x).RGB.r, \\\n                            ((x).RGB.g & 0xff00) ? 0xff : (x).RGB.g, \\\n                            ((x).RGB.b & 0xff00) ? 0xff : (x).RGB.b )\n\n#define EXPAND(d,s) do {                                 \\\n     (d).RGB.a = EXPAND_Ato8( (s & A_MASK) >> A_SHIFT ); \\\n     (d).RGB.r = EXPAND_Rto8( (s & R_MASK) >> R_SHIFT ); \\\n     (d).RGB.g = EXPAND_Gto8( (s & G_MASK) >> G_SHIFT ); \\\n     (d).RGB.b = EXPAND_Bto8( (s & B_MASK) >> B_SHIFT ); \\\n} while (0)\n\n#ifdef WORD_BIGENDIAN\n#define READ_PIXEL(S)                     \\\n     (                                    \\\n          ((S)[0] << 16) |                \\\n          ((S)[1] <<  8) |                \\\n           (S)[2]                         \\\n     )\n#define WRITE_PIXEL(D,pix)                \\\n     do {                                 \\\n           (D)[0] = ((pix) >> 16) & 0xff; \\\n           (D)[1] = ((pix) >>  8) & 0xff; \\\n           (D)[2] =  (pix)        & 0xff; \\\n     } while (0)\n#else\n#define READ_PIXEL(S)                     \\\n     (                                    \\\n          ((S)[2] << 16) |                \\\n          ((S)[1] <<  8) |                \\\n           (S)[0]                         \\\n     )\n#define WRITE_PIXEL(D,pix)                \\\n     do {                                 \\\n           (D)[0] =  (pix)        & 0xff; \\\n           (D)[1] = ((pix) >>  8) & 0xff; \\\n           (D)[2] = ((pix) >> 16) & 0xff; \\\n     } while (0)\n#endif\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_to_Dacc ********************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_PFI_OP_Dacc(to)( GenefxState *gfxs )\n{\n     int                w     = gfxs->length + 1;\n     u8                *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                Ostep = gfxs->Ostep * 3;\n\n     while (--w) {\n          u32 s = READ_PIXEL( S );\n\n          EXPAND( *D, s );\n\n          S += Ostep;\n          ++D;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_Kto_Dacc *******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_PFI_OP_Dacc(Kto)( GenefxState *gfxs )\n{\n     int                w     = gfxs->length + 1;\n     u8                *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     u32                Skey  = gfxs->Skey;\n     int                Ostep = gfxs->Ostep * 3;\n\n     while (--w) {\n          u32 s = READ_PIXEL( S );\n\n          if (MASK_RGB( s ) != Skey)\n               EXPAND( *D, s );\n          else\n               D->RGB.a = 0xf000;\n\n          S += Ostep;\n          ++D;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_Sto_Dacc *******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_PFI_OP_Dacc(Sto)( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u8                *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                SperD = gfxs->SperD;\n     int                Ostep = gfxs->Ostep;\n\n     if (Ostep != 1)\n          D_UNIMPLEMENTED();\n\n     while (--w) {\n          int pixelstart = (i >> 16) * 3;\n          u32 s = READ_PIXEL( &S[pixelstart] );\n\n          EXPAND( *D, s );\n\n          ++D;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_SKto_Dacc ******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_PFI_OP_Dacc(SKto)( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u8                *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     u32                Skey  = gfxs->Skey;\n     int                SperD = gfxs->SperD;\n     int                Ostep = gfxs->Ostep;\n\n     if (Ostep != 1)\n          D_UNIMPLEMENTED();\n\n     while (--w) {\n          int pixelstart = (i >> 16) * 3;\n          u32 s = READ_PIXEL( &S[pixelstart] );\n\n          if (MASK_RGB( s ) != Skey)\n               EXPAND( *D, s );\n          else\n               D->RGB.a = 0xf000;\n\n          ++D;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_TEX_to_Dacc ****************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_PFI_OP_Dacc(TEX_to)( GenefxState *gfxs )\n{\n     int                s     = gfxs->s;\n     int                t     = gfxs->t;\n     int                w     = gfxs->length + 1;\n     u8                *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                sp3   = gfxs->src_pitch / 3;\n     int                SperD = gfxs->SperD;\n     int                TperD = gfxs->TperD;\n     int                Ostep = gfxs->Ostep * 3;\n\n     if (Ostep != 1)\n          D_UNIMPLEMENTED();\n\n     while (--w) {\n          int pixelstart = ((s >> 16) + (t >> 16) * sp3) * 3;\n          u32 p = READ_PIXEL( &S[pixelstart] );\n\n          EXPAND( *D, p );\n\n          ++D;\n          s += SperD;\n          t += TperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_TEX_Kto_Dacc ***************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_PFI_OP_Dacc(TEX_Kto)( GenefxState *gfxs )\n{\n     int                s     = gfxs->s;\n     int                t     = gfxs->t;\n     int                w     = gfxs->length + 1;\n     u8                *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                sp3   = gfxs->src_pitch / 3;\n     u32                Skey  = gfxs->Skey;\n     int                SperD = gfxs->SperD;\n     int                TperD = gfxs->TperD;\n     int                Ostep = gfxs->Ostep * 3;\n\n     if (Ostep != 1)\n          D_UNIMPLEMENTED();\n\n     while (--w) {\n          int pixelstart = ((s >> 16) + (t >> 16) * sp3) * 3;\n          u32 p = READ_PIXEL( &S[pixelstart] );\n\n          if (MASK_RGB( p ) != Skey)\n               EXPAND( *D, p );\n          else\n               D->RGB.a = 0xf000;\n\n          ++D;\n          s += SperD;\n          t += TperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sacc_to_Aop_PFI ********************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSacc_OP_Aop_PFI(to)( GenefxState *gfxs )\n{\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *D     = gfxs->Aop[0];\n     int                Dstep = gfxs->Astep * 3;\n\n     while (--w) {\n          if (!(S->RGB.a & 0xf000)) {\n               u32 pix = PIXEL( *S );\n               WRITE_PIXEL( D, pix );\n          }\n\n          ++S;\n          D += Dstep;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sacc_toK_Aop_PFI *******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSacc_OP_Aop_PFI(toK)( GenefxState *gfxs )\n{\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *D     = gfxs->Aop[0];\n     u32                Dkey  = gfxs->Dkey;\n     int                Dstep = gfxs->Astep * 3;\n\n     while (--w) {\n          if (!(S->RGB.a & 0xf000)) {\n               u32 pix = READ_PIXEL( D );\n\n               if (MASK_RGB( pix ) == Dkey) {\n                    pix = PIXEL( *S );\n                    WRITE_PIXEL( D, pix );\n               }\n          }\n\n          ++S;\n          D += Dstep;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sacc_Sto_Aop_PFI *******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSacc_OP_Aop_PFI(Sto)( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *D     = gfxs->Aop[0];\n     int                Dstep = gfxs->Astep * 3;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->RGB.a & 0xf000)) {\n               u32 pix = PIXEL( *S0 );\n               WRITE_PIXEL( D, pix );\n          }\n\n          D += Dstep;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sacc_StoK_Aop_PFI ******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSacc_OP_Aop_PFI(StoK)( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u8                *D     = gfxs->Aop[0];\n     u32                Dkey  = gfxs->Dkey;\n     int                Dstep = gfxs->Astep * 3;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->RGB.a & 0xf000)) {\n               u32 pix = READ_PIXEL( D );\n\n               if (MASK_RGB( pix ) == Dkey) {\n                    pix = PIXEL( *S0 );\n                    WRITE_PIXEL( D, pix );\n               }\n          }\n\n          D += Dstep;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************/\n\n#undef RGB_MASK\n#undef MASK_RGB\n#undef PIXEL\n#undef EXPAND\n#undef READ_PIXEL\n#undef WRITE_PIXEL\n\n#undef A_SHIFT\n#undef R_SHIFT\n#undef G_SHIFT\n#undef B_SHIFT\n#undef A_MASK\n#undef R_MASK\n#undef G_MASK\n#undef B_MASK\n#undef PIXEL_OUT\n#undef EXPAND_Ato8\n#undef EXPAND_Rto8\n#undef EXPAND_Gto8\n#undef EXPAND_Bto8\n#undef Sop_PFI_OP_Dacc\n#undef Sacc_OP_Aop_PFI\n"
  },
  {
    "path": "src/gfx/generic/template_acc_32.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#define RGB_MASK (R_MASK | G_MASK | B_MASK)\n\n#define PIXEL(s) PIXEL_OUT( ((s).RGB.a & 0xff00) ? 0xff : (s).RGB.a, \\\n                            ((s).RGB.r & 0xff00) ? 0xff : (s).RGB.r, \\\n                            ((s).RGB.g & 0xff00) ? 0xff : (s).RGB.g, \\\n                            ((s).RGB.b & 0xff00) ? 0xff : (s).RGB.b )\n\n#define EXPAND(d,s)                                      \\\ndo {                                                     \\\n     (d).RGB.a = EXPAND_Ato8( (s & A_MASK) >> A_SHIFT ); \\\n     (d).RGB.r = EXPAND_Rto8( (s & R_MASK) >> R_SHIFT ); \\\n     (d).RGB.g = EXPAND_Gto8( (s & G_MASK) >> G_SHIFT ); \\\n     (d).RGB.b = EXPAND_Bto8( (s & B_MASK) >> B_SHIFT ); \\\n} while (0)\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_to_Dacc ********************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_PFI_OP_Dacc(to)( GenefxState *gfxs )\n{\n     int                w     = gfxs->length + 1;\n     u32               *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                Ostep = gfxs->Ostep;\n\n     while (--w) {\n          u32 s = *S;\n\n          EXPAND( *D, s );\n\n          S += Ostep;\n          ++D;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_Kto_Dacc *******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_PFI_OP_Dacc(Kto)( GenefxState *gfxs )\n{\n     int                w     = gfxs->length + 1;\n     u32               *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     u32                Skey  = gfxs->Skey;\n     int                Ostep = gfxs->Ostep;\n\n     while (--w) {\n          u32 s = *S;\n\n          if ((s & RGB_MASK) != Skey)\n               EXPAND( *D, s );\n          else\n               D->RGB.a = 0xf000;\n\n          S += Ostep;\n          ++D;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_Sto_Dacc *******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_PFI_OP_Dacc(Sto)( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u32               *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                SperD = gfxs->SperD;\n     int                Ostep = gfxs->Ostep;\n\n     if (Ostep != 1)\n          D_UNIMPLEMENTED();\n\n     while (--w) {\n          u32 s = S[i>>16];\n\n          EXPAND( *D, s );\n\n          ++D;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_SKto_Dacc ******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_PFI_OP_Dacc(SKto)( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     u32               *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     u32                Skey  = gfxs->Skey;\n     int                SperD = gfxs->SperD;\n     int                Ostep = gfxs->Ostep;\n\n     if (Ostep != 1)\n          D_UNIMPLEMENTED();\n\n     while (--w) {\n          u32 s = S[i>>16];\n\n          if ((s & RGB_MASK) != Skey)\n               EXPAND( *D, s );\n          else\n               D->RGB.a = 0xf000;\n\n          ++D;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_TEX_to_Dacc ****************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_PFI_OP_Dacc(TEX_to)( GenefxState *gfxs )\n{\n     int                s     = gfxs->s;\n     int                t     = gfxs->t;\n     int                w     = gfxs->length + 1;\n     u32               *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                sp4   = gfxs->src_pitch / 4;\n     int                SperD = gfxs->SperD;\n     int                TperD = gfxs->TperD;\n     int                Ostep = gfxs->Ostep;\n\n     if (Ostep != 1)\n          D_UNIMPLEMENTED();\n\n     while (--w) {\n          u32 p = S[(s>>16) + (t>>16) * sp4];\n\n          EXPAND( *D, p );\n\n          ++D;\n          s += SperD;\n          t += TperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sop_PFI_TEX_Kto_Dacc ***************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSop_PFI_OP_Dacc(TEX_Kto)( GenefxState *gfxs )\n{\n     int                s     = gfxs->s;\n     int                t     = gfxs->t;\n     int                w     = gfxs->length + 1;\n     u32               *S     = gfxs->Sop[0];\n     GenefxAccumulator *D     = gfxs->Dacc;\n     int                sp4   = gfxs->src_pitch / 4;\n     u32                Skey  = gfxs->Skey;\n     int                SperD = gfxs->SperD;\n     int                TperD = gfxs->TperD;\n     int                Ostep = gfxs->Ostep;\n\n     if (Ostep != 1)\n          D_UNIMPLEMENTED();\n\n     while (--w) {\n          u32 p = S[(s>>16) + (t>>16) * sp4];\n\n          if ((p & RGB_MASK) != Skey)\n               EXPAND( *D, p );\n          else\n               D->RGB.a = 0xf000;\n\n          ++D;\n          s += SperD;\n          t += TperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sacc_to_Aop_PFI ********************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSacc_OP_Aop_PFI(to)( GenefxState *gfxs )\n{\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u32               *D     = gfxs->Aop[0];\n     int                Dstep = gfxs->Astep;\n\n     while (--w) {\n          if (!(S->RGB.a & 0xf000))\n               *D = PIXEL( *S );\n\n          ++S;\n          D += Dstep;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sacc_toK_Aop_PFI *******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSacc_OP_Aop_PFI(toK)( GenefxState *gfxs )\n{\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u32               *D     = gfxs->Aop[0];\n     u32                Dkey  = gfxs->Dkey;\n     int                Dstep = gfxs->Astep;\n\n     while (--w) {\n          if (!(S->RGB.a & 0xf000) && (*D & RGB_MASK) == Dkey)\n               *D = PIXEL( *S );\n\n          ++S;\n          D += Dstep;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sacc_Sto_Aop_PFI *******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSacc_OP_Aop_PFI(Sto)( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u32               *D     = gfxs->Aop[0];\n     int                Dstep = gfxs->Astep;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->RGB.a & 0xf000))\n               *D = PIXEL( *S0 );\n\n          D += Dstep;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Sacc_StoK_Aop_PFI ******************************************************************\n **********************************************************************************************************************/\n\nstatic void\nSacc_OP_Aop_PFI(StoK)( GenefxState *gfxs )\n{\n     int                i     = gfxs->Xphase;\n     int                w     = gfxs->length + 1;\n     GenefxAccumulator *S     = gfxs->Sacc;\n     u32               *D     = gfxs->Aop[0];\n     u32                Dkey  = gfxs->Dkey;\n     int                Dstep = gfxs->Astep;\n     int                SperD = gfxs->SperD;\n\n     while (--w) {\n          GenefxAccumulator *S0 = &S[i>>16];\n\n          if (!(S0->RGB.a & 0xf000) && (*D & RGB_MASK) == Dkey)\n               *D = PIXEL( *S0 );\n\n          D += Dstep;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************/\n\n#undef RGB_MASK\n#undef PIXEL\n#undef EXPAND\n\n#undef A_SHIFT\n#undef R_SHIFT\n#undef G_SHIFT\n#undef B_SHIFT\n#undef A_MASK\n#undef R_MASK\n#undef G_MASK\n#undef B_MASK\n#undef PIXEL_OUT\n#undef EXPAND_Ato8\n#undef EXPAND_Rto8\n#undef EXPAND_Gto8\n#undef EXPAND_Bto8\n#undef Sop_PFI_OP_Dacc\n#undef Sacc_OP_Aop_PFI\n"
  },
  {
    "path": "src/gfx/generic/template_colorkey_16.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#if RGB_MASK == 0xffff\n#define MASK_RGB(p) (p)\n#else\n#define MASK_RGB(p) ((p) & RGB_MASK)\n#endif\n\n#define MASK_RGB_L(p)  ((p) & RGB_MASK)\n#define MASK_RGB_H(p)  ((p) & (RGB_MASK << 16))\n#define MASK_RGB_32(p) ((p) & (RGB_MASK << 16 | RGB_MASK))\n\n/**********************************************************************************************************************\n ********************************* Cop_toK_Aop_PFI ********************************************************************\n **********************************************************************************************************************/\n\nstatic void\nCop_OP_Aop_PFI(toK)( GenefxState *gfxs )\n{\n     int  w    = gfxs->length + 1;\n     u16 *D    = gfxs->Aop[0];\n     u16  Cop  = gfxs->Cop;\n     u16  Dkey = gfxs->Dkey;\n\n     while (--w) {\n          if (MASK_RGB( *D ) == Dkey)\n               *D = Cop;\n\n          ++D;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_toK_Aop_PFI ****************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_PFI_OP_Aop_PFI(toK)( GenefxState *gfxs )\n{\n     int  l;\n     int  w     = gfxs->length;\n     u16 *S     = gfxs->Bop[0];\n     u16 *D     = gfxs->Aop[0];\n     u16  Dkey  = gfxs->Dkey;\n     u32  DkeyH = gfxs->Dkey << 16;\n     int  Ostep = gfxs->Ostep;\n\n     if (Ostep < 0) {\n          S += gfxs->length - 1;\n          D += gfxs->length - 1;\n     }\n\n     if (((long) S & 2) != ((long) D & 2)) {\n          w++;\n          while (--w) {\n               if (MASK_RGB( *D ) == Dkey)\n                    *D = *S;\n\n               S += Ostep;\n               D += Ostep;\n          }\n\n          return;\n     }\n\n     if ((Ostep > 0)) {\n          if ((long) D & 2) {\n               if (MASK_RGB( *D ) == Dkey)\n                    *D = *S;\n\n               ++S;\n               ++D;\n               --w;\n          }\n     }\n     else {\n          if ((long) D & 2) {\n               --S;\n               --D;\n          }\n          else {\n               if (MASK_RGB( *D ) == Dkey)\n                    *D = *S;\n\n               S -= 2;\n               D -= 2;\n               --w;\n          }\n     }\n\n     Ostep <<= 1;\n     l = (w >> 1) + 1;\n     while (--l) {\n          u32 d = *(u32*) D;\n\n          if (MASK_RGB_32( d ) == (DkeyH | Dkey)) {\n               *(u32*) D = *(u32*) S;\n          }\n          else {\n               if (MASK_RGB_L( d ) == Dkey) {\n#ifdef WORDS_BIGENDIAN\n                    D[0] = S[0];\n#else\n                    D[1] = S[1];\n#endif\n               }\n               else if (MASK_RGB_H( d ) == DkeyH) {\n#ifdef WORDS_BIGENDIAN\n                    D[1] = S[1];\n#else\n                    D[0] = S[0];\n#endif\n               }\n          }\n\n          S += Ostep;\n          D += Ostep;\n     }\n\n     if (w & 1) {\n          if (Ostep < 0) {\n               ++S;\n               ++D;\n          }\n\n          if (MASK_RGB( *D ) == Dkey)\n               *D = *S;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_Kto_Aop_PFI ****************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_PFI_OP_Aop_PFI(Kto)( GenefxState *gfxs )\n{\n     int  l;\n     int  w     = gfxs->length;\n     u16 *S     = gfxs->Bop[0];\n     u16 *D     = gfxs->Aop[0];\n     u16  Skey  = gfxs->Skey;\n     u32  SkeyH = gfxs->Skey << 16;\n     int  Ostep = gfxs->Ostep;\n\n     if (Ostep < 0) {\n          S += gfxs->length - 1;\n          D += gfxs->length - 1;\n     }\n\n     if (((long) S & 2) != ((long) D & 2)) {\n          w++;\n          while (--w) {\n               u16 s = *S;\n\n               if (MASK_RGB( s ) != Skey)\n                    *D = s;\n\n               S += Ostep;\n               D += Ostep;\n          }\n\n          return;\n     }\n\n     if (Ostep > 0) {\n          if ((long) D & 2) {\n               u16 s = *S;\n\n               if (MASK_RGB( s ) != Skey)\n                    *D = s;\n\n               ++S;\n               ++D;\n               --w;\n          }\n     }\n     else {\n          if ((long) D & 2) {\n               --S;\n               --D;\n          }\n          else {\n               u16 s = *S;\n\n               if (MASK_RGB( s ) != Skey)\n                    *D = s;\n\n               S -= 2;\n               D -= 2;\n               --w;\n          }\n     }\n\n     Ostep <<= 1;\n     l = (w >> 1) + 1;\n     while (--l) {\n          u32 s = *(u32*) S;\n\n          if (MASK_RGB_L( s ) != Skey) {\n               if (MASK_RGB_H( s ) != SkeyH) {\n                    *(u32*) D = s;\n               }\n               else {\n#ifdef WORDS_BIGENDIAN\n                    D[1] = (u16) s;\n#else\n                    D[0] = (u16) s;\n#endif\n               }\n          }\n          else if (MASK_RGB_H( s ) != SkeyH) {\n#ifdef WORDS_BIGENDIAN\n               D[0] = (u16) (s >> 16);\n#else\n               D[1] = (u16) (s >> 16);\n#endif\n          }\n\n          S += Ostep;\n          D += Ostep;\n     }\n\n     if (w & 1) {\n          u16 s;\n\n          if (Ostep < 0) {\n               ++S;\n               ++D;\n          }\n\n          s = *S;\n          if (MASK_RGB( s ) != Skey)\n               *D = s;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_KtoK_Aop_PFI ***************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_PFI_OP_Aop_PFI(KtoK)( GenefxState *gfxs )\n{\n     int  w     = gfxs->length + 1;\n     u16 *S     = gfxs->Bop[0];\n     u16 *D     = gfxs->Aop[0];\n     u16  Skey  = gfxs->Skey;\n     u16  Dkey  = gfxs->Dkey;\n     int  Ostep = gfxs->Ostep;\n\n     if (Ostep < 0) {\n          S += gfxs->length - 1;\n          D += gfxs->length - 1;\n     }\n\n     while (--w) {\n          u16 s = *S;\n\n          if (MASK_RGB( s ) != Skey && MASK_RGB( *D ) == Dkey)\n               *D = s;\n\n          S += Ostep;\n          D += Ostep;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_SKto_Aop_PFI ***************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_PFI_OP_Aop_PFI(SKto)( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u16 *S     = gfxs->Bop[0];\n     u16 *D     = gfxs->Aop[0];\n     u16  Skey  = gfxs->Skey;\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          u16 s = S[i>>16];\n\n          if (MASK_RGB( s ) != Skey)\n               *D = s;\n\n          ++D;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_StoK_Aop_PFI ***************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_PFI_OP_Aop_PFI(StoK)( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u16 *S     = gfxs->Bop[0];\n     u16 *D     = gfxs->Aop[0];\n     u16  Dkey  = gfxs->Dkey;\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          if (MASK_RGB( *D ) == Dkey)\n               *D = S[i>>16];\n\n          ++D;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_SKtoK_Aop_PFI **************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_PFI_OP_Aop_PFI(SKtoK)( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u16 *S     = gfxs->Bop[0];\n     u16 *D     = gfxs->Aop[0];\n     u16  Skey  = gfxs->Skey;\n     u16  Dkey  = gfxs->Dkey;\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          u16 s = S[i>>16];\n\n          if (MASK_RGB( s ) != Skey && MASK_RGB( *D ) == Dkey)\n               *D = s;\n\n          ++D;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************/\n\n#undef MASK_RGB\n#undef MASK_RGB_L\n#undef MASK_RGB_H\n#undef MASK_RGB_32\n\n#undef RGB_MASK\n#undef Cop_OP_Aop_PFI\n#undef Bop_PFI_OP_Aop_PFI\n"
  },
  {
    "path": "src/gfx/generic/template_colorkey_24.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifdef WORD_BIGENDIAN\n#define READ_PIXEL(S)                     \\\n     (                                    \\\n          ((S)[0] << 16) |                \\\n          ((S)[1] <<  8) |                \\\n           (S)[2]                         \\\n     )\n#define WRITE_PIXEL(D,pix)                \\\n     do {                                 \\\n           (D)[0] = ((pix) >> 16) & 0xff; \\\n           (D)[1] = ((pix) >>  8) & 0xff; \\\n           (D)[2] =  (pix)        & 0xff; \\\n     } while (0)\n#else\n#define READ_PIXEL(S)                     \\\n     (                                    \\\n          ((S)[2] << 16) |                \\\n          ((S)[1] <<  8) |                \\\n           (S)[0]                         \\\n     )\n#define WRITE_PIXEL(d,pix)                \\\n     do {                                 \\\n           (D)[0] =  (pix)        & 0xff; \\\n           (D)[1] = ((pix) >>  8) & 0xff; \\\n           (D)[2] = ((pix) >> 16) & 0xff; \\\n     } while (0)\n#endif\n\n/**********************************************************************************************************************\n ********************************* Cop_toK_Aop_PFI ********************************************************************\n **********************************************************************************************************************/\n\nstatic void\nCop_OP_Aop_PFI(toK)( GenefxState *gfxs )\n{\n     int  w    = gfxs->length + 1;\n     u8  *D    = gfxs->Aop[0];\n     u32  Cop  = gfxs->Cop;\n     u32  Dkey = gfxs->Dkey;\n\n     while (--w) {\n          u32 d = READ_PIXEL( D );\n\n          if ((d & RGB_MASK) == Dkey)\n               WRITE_PIXEL( D, Cop );\n\n          D += 3;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_toK_Aop_PFI ****************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_PFI_OP_Aop_PFI(toK)( GenefxState *gfxs )\n{\n     int  w     = gfxs->length + 1;\n     u8  *S     = gfxs->Bop[0];\n     u8  *D     = gfxs->Aop[0];\n     u32  Dkey  = gfxs->Dkey;\n     int  Ostep = gfxs->Ostep * 3;\n\n     if (Ostep < 0) {\n          S += (gfxs->length - 1) * 3;\n          D += (gfxs->length - 1) * 3;\n     }\n\n     while (--w) {\n          u32 d = READ_PIXEL( D );\n\n          if ((d & RGB_MASK) == Dkey) {\n               D[0] = S[0];\n               D[1] = S[1];\n               D[2] = S[2];\n          }\n\n          S += Ostep;\n          D += Ostep;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_Kto_Aop_PFI ****************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_PFI_OP_Aop_PFI(Kto)( GenefxState *gfxs )\n{\n     int  w     = gfxs->length + 1;\n     u8  *S     = gfxs->Bop[0];\n     u8  *D     = gfxs->Aop[0];\n     u32  Skey  = gfxs->Skey;\n     int  Ostep = gfxs->Ostep * 3;\n\n     if (Ostep < 0) {\n          S += (gfxs->length - 1) * 3;\n          D += (gfxs->length - 1) * 3;\n     }\n\n     while (--w) {\n          u32 s = READ_PIXEL( S );\n\n          if ((s & RGB_MASK) != Skey) {\n               D[0] = S[0];\n               D[1] = S[1];\n               D[2] = S[2];\n          }\n\n          S += Ostep;\n          D += Ostep;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_KtoK_Aop_PFI ***************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_PFI_OP_Aop_PFI(KtoK)( GenefxState *gfxs )\n{\n     int  w     = gfxs->length + 1;\n     u8  *S     = gfxs->Bop[0];\n     u8  *D     = gfxs->Aop[0];\n     u32  Skey  = gfxs->Skey;\n     u32  Dkey  = gfxs->Dkey;\n     int  Ostep = gfxs->Ostep * 3;\n\n     if (Ostep < 0) {\n          S += (gfxs->length - 1) * 3;\n          D += (gfxs->length - 1) * 3;\n     }\n\n     while (--w) {\n          u32 s = READ_PIXEL( S );\n\n          if ((s & RGB_MASK) != Skey) {\n               u32 d = READ_PIXEL( D );\n\n               if ((d & RGB_MASK) == Dkey) {\n                    D[0] = S[0];\n                    D[1] = S[1];\n                    D[2] = S[2];\n               }\n          }\n\n          S += Ostep;\n          D += Ostep;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_SKto_Aop_PFI ***************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_PFI_OP_Aop_PFI(SKto)( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u8  *S     = gfxs->Bop[0];\n     u8  *D     = gfxs->Aop[0];\n     u32  Skey  = gfxs->Skey;\n     int  Dstep = gfxs->Astep * 3;\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          int pixelstart = (i >> 16) * 3;\n          u32 s = READ_PIXEL( &S[pixelstart] );\n\n          if ((s & RGB_MASK) != Skey) {\n               D[0] = S[pixelstart++];\n               D[1] = S[pixelstart++];\n               D[2] = S[pixelstart];\n          }\n\n          D += Dstep;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_StoK_Aop_PFI ***************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_PFI_OP_Aop_PFI(StoK)( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u8  *S     = gfxs->Bop[0];\n     u8  *D     = gfxs->Aop[0];\n     u32  Dkey  = gfxs->Dkey;\n     int  Dstep = gfxs->Astep * 3;\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          u32 d = READ_PIXEL( D );\n\n          if ((d & RGB_MASK) == Dkey) {\n               int pixelstart = (i >> 16) * 3;\n               D[0] = S[pixelstart++];\n               D[1] = S[pixelstart++];\n               D[2] = S[pixelstart];\n          }\n\n          D += Dstep;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_SKtoK_Aop_PFI **************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_PFI_OP_Aop_PFI(SKtoK)( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u8  *S     = gfxs->Bop[0];\n     u8  *D     = gfxs->Aop[0];\n     u32  Skey  = gfxs->Skey;\n     u32  Dkey  = gfxs->Dkey;\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          int pixelstart = (i >> 16) * 3;\n          u32 s = READ_PIXEL( &S[pixelstart] );\n\n          if ((s & RGB_MASK) != Skey) {\n               u32 d = READ_PIXEL( D );\n\n               if ((d & RGB_MASK) == Dkey) {\n                    D[0] = S[pixelstart++];\n                    D[1] = S[pixelstart++];\n                    D[2] = S[pixelstart];\n               }\n          }\n\n          D += 3;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************/\n\n#undef READ_PIXEL\n#undef WRITE_PIXEL\n\n#undef RGB_MASK\n#undef Cop_OP_Aop_PFI\n#undef Bop_PFI_OP_Aop_PFI\n"
  },
  {
    "path": "src/gfx/generic/template_colorkey_32.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n/**********************************************************************************************************************\n ********************************* Cop_toK_Aop_PFI ********************************************************************\n **********************************************************************************************************************/\n\nstatic void\nCop_OP_Aop_PFI(toK)( GenefxState *gfxs )\n{\n     int  w    = gfxs->length + 1;\n     u32 *D    = gfxs->Aop[0];\n     u32  Cop  = gfxs->Cop;\n     u32  Dkey = gfxs->Dkey;\n\n     while (--w) {\n          if ((*D & RGB_MASK) == Dkey)\n               *D = Cop;\n\n          ++D;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_toK_Aop_PFI ****************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_PFI_OP_Aop_PFI(toK)( GenefxState *gfxs )\n{\n     int  w     = gfxs->length + 1;\n     u32 *S     = gfxs->Bop[0];\n     u32 *D     = gfxs->Aop[0];\n     u32  Dkey  = gfxs->Dkey;\n     int  Sstep = gfxs->Bstep;\n     int  Dstep = gfxs->Astep;\n\n     if (Sstep < 0) {\n          S +=  gfxs->length - 1;\n          D += (gfxs->length - 1) * Dstep;\n     }\n\n     while (--w) {\n          if ((*D & RGB_MASK) == Dkey)\n               *D = *S;\n\n          S += Sstep;\n          D += Dstep;\n     }\n}\n\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_Kto_Aop_PFI ****************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_PFI_OP_Aop_PFI(Kto)( GenefxState *gfxs )\n{\n     int  w     = gfxs->length + 1;\n     u32 *S     = gfxs->Bop[0];\n     u32 *D     = gfxs->Aop[0];\n     u32  Skey  = gfxs->Skey;\n     int  Sstep = gfxs->Bstep;\n     int  Dstep = gfxs->Astep;\n\n     if (Sstep < 0) {\n          S +=  gfxs->length - 1;\n          D += (gfxs->length - 1) * Dstep;\n     }\n\n     while (--w) {\n          u32 s = *S;\n\n          if ((s & RGB_MASK) != Skey)\n               *D = s;\n\n          S += Sstep;\n          D += Dstep;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_KtoK_Aop_PFI ***************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_PFI_OP_Aop_PFI(KtoK)( GenefxState *gfxs )\n{\n     int  w     = gfxs->length + 1;\n     u32 *S     = gfxs->Bop[0];\n     u32 *D     = gfxs->Aop[0];\n     u32  Skey  = gfxs->Skey;\n     u32  Dkey  = gfxs->Dkey;\n     int  Sstep = gfxs->Bstep;\n     int  Dstep = gfxs->Astep;\n\n     if (Sstep < 0) {\n          S +=  gfxs->length - 1;\n          D += (gfxs->length - 1) * Dstep;\n     }\n\n     while (--w) {\n          u32 s = *S;\n\n          if ((s & RGB_MASK) != Skey && (*D & RGB_MASK) == Dkey)\n               *D = s;\n\n          S += Sstep;\n          D += Dstep;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_SKto_Aop_PFI ***************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_PFI_OP_Aop_PFI(SKto)( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u32 *S     = gfxs->Bop[0];\n     u32 *D     = gfxs->Aop[0];\n     u32  Skey  = gfxs->Skey;\n     int  Dstep = gfxs->Astep;\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          u32 s = S[i>>16];\n\n          if ((s & RGB_MASK) != Skey)\n               *D = s;\n\n          D += Dstep;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_StoK_Aop_PFI ***************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_PFI_OP_Aop_PFI(StoK)( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u32 *S     = gfxs->Bop[0];\n     u32 *D     = gfxs->Aop[0];\n     u32  Dkey  = gfxs->Dkey;\n     int  Dstep = gfxs->Astep;\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          if ((*D & RGB_MASK) == Dkey)\n               *D = S[i>>16];\n\n          D += Dstep;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************\n ********************************* Bop_PFI_SKtoK_Aop_PFI **************************************************************\n **********************************************************************************************************************/\n\nstatic void\nBop_PFI_OP_Aop_PFI(SKtoK)( GenefxState *gfxs )\n{\n     int  i     = gfxs->Xphase;\n     int  w     = gfxs->length + 1;\n     u32 *S     = gfxs->Bop[0];\n     u32 *D     = gfxs->Aop[0];\n     u32  Skey  = gfxs->Skey;\n     u32  Dkey  = gfxs->Dkey;\n     int  Dstep = gfxs->Astep;\n     int  SperD = gfxs->SperD;\n\n     while (--w) {\n          u32 s = S[i>>16];\n\n          if ((s & RGB_MASK) != Skey && (*D & RGB_MASK) == Dkey)\n               *D = s;\n\n          D += Dstep;\n          i += SperD;\n     }\n}\n\n/**********************************************************************************************************************/\n\n#undef RGB_MASK\n#undef Cop_OP_Aop_PFI\n#undef Bop_PFI_OP_Aop_PFI\n"
  },
  {
    "path": "src/gfx/util.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreGraphicsStateClient.h>\n#include <core/state.h>\n#include <gfx/util.h>\n\n/**********************************************************************************************************************/\n\nstatic bool      copy_state_inited;\nstatic CardState copy_state;\n\nstatic bool      btf_state_inited;\nstatic CardState btf_state;\n\nstatic DirectMutex copy_lock = DIRECT_MUTEX_INITIALIZER();\nstatic DirectMutex btf_lock  = DIRECT_MUTEX_INITIALIZER();\n\nvoid\ndfb_gfx_copy_stereo( CoreSurface         *source,\n                     DFBSurfaceStereoEye  source_eye,\n                     CoreSurface         *destination,\n                     DFBSurfaceStereoEye  destination_eye,\n                     const DFBRectangle  *rect,\n                     int                  x,\n                     int                  y,\n                     bool                 from_back )\n{\n     DFBRectangle sourcerect = { 0, 0, source->config.size.w, source->config.size.h };\n\n     direct_mutex_lock( &copy_lock );\n\n     if (!copy_state_inited) {\n          dfb_state_init( &copy_state, NULL );\n          copy_state_inited = true;\n     }\n\n     copy_state.modified   |= SMF_CLIP | SMF_SOURCE | SMF_DESTINATION | SMF_FROM | SMF_TO;\n     copy_state.clip.x2     = destination->config.size.w - 1;\n     copy_state.clip.y2     = destination->config.size.h - 1;\n     copy_state.source      = source;\n     copy_state.destination = destination;\n     copy_state.from        = from_back ? DSBR_BACK : DSBR_FRONT;\n     copy_state.from_eye    = source_eye;\n     copy_state.to          = DSBR_BACK;\n     copy_state.to_eye      = destination_eye;\n\n     if (rect) {\n          if (dfb_rectangle_intersect( &sourcerect, rect ))\n               dfb_gfxcard_blit( &sourcerect, x + sourcerect.x - rect->x, y + sourcerect.y - rect->y, &copy_state );\n     }\n     else\n          dfb_gfxcard_blit( &sourcerect, x, y, &copy_state );\n\n     dfb_gfxcard_flush();\n\n     /* Signal end of sequence. */\n     dfb_state_stop_drawing( &copy_state );\n\n     copy_state.destination = NULL;\n     copy_state.source      = NULL;\n\n     direct_mutex_unlock( &copy_lock );\n}\n\nvoid\ndfb_gfx_clear( CoreSurface          *surface,\n               DFBSurfaceBufferRole  role )\n{\n     DFBRectangle rect = { 0, 0, surface->config.size.w, surface->config.size.h };\n\n     direct_mutex_lock( &copy_lock );\n\n     if (!copy_state_inited) {\n          dfb_state_init( &copy_state, NULL );\n          copy_state_inited = true;\n     }\n\n     copy_state.modified   |= SMF_CLIP | SMF_COLOR | SMF_DESTINATION | SMF_TO;\n     copy_state.clip.x2     = surface->config.size.w - 1;\n     copy_state.clip.y2     = surface->config.size.h - 1;\n     copy_state.destination = surface;\n     copy_state.to          = role;\n     copy_state.to_eye      = DSSE_LEFT;\n     copy_state.color.a     = 0;\n     copy_state.color.r     = 0;\n     copy_state.color.g     = 0;\n     copy_state.color.b     = 0;\n     copy_state.color_index = 0;\n\n     dfb_gfxcard_fillrectangles( &rect, 1, &copy_state );\n\n     dfb_gfxcard_flush();\n\n     /* Signal end of sequence. */\n     dfb_state_stop_drawing( &copy_state );\n\n     copy_state.destination = NULL;\n\n     direct_mutex_unlock( &copy_lock );\n}\n\nvoid\ndfb_gfx_stretch_stereo( CoreSurface         *source,\n                        DFBSurfaceStereoEye  source_eye,\n                        CoreSurface         *destination,\n                        DFBSurfaceStereoEye  destination_eye,\n                        const DFBRectangle  *srect,\n                        const DFBRectangle  *drect,\n                        bool                 from_back )\n{\n     DFBRectangle sourcerect = { 0, 0, source->config.size.w, source->config.size.h };\n     DFBRectangle destrect   = { 0, 0, destination->config.size.w, destination->config.size.h };\n\n     if (srect) {\n          if (!dfb_rectangle_intersect( &sourcerect, srect ))\n               return;\n     }\n\n     if (drect) {\n          if (!dfb_rectangle_intersect( &destrect, drect ))\n               return;\n     }\n\n     direct_mutex_lock( &copy_lock );\n\n     if (!copy_state_inited) {\n          dfb_state_init( &copy_state, NULL );\n          copy_state_inited = true;\n     }\n\n     copy_state.modified   |= SMF_CLIP | SMF_SOURCE | SMF_DESTINATION | SMF_FROM | SMF_TO;\n     copy_state.clip.x2     = destination->config.size.w - 1;\n     copy_state.clip.y2     = destination->config.size.h - 1;\n     copy_state.source      = source;\n     copy_state.destination = destination;\n     copy_state.from        = from_back ? DSBR_BACK : DSBR_FRONT;\n     copy_state.from_eye    = source_eye;\n     copy_state.to          = DSBR_BACK;\n     copy_state.to_eye      = destination_eye;\n\n     dfb_gfxcard_stretchblit( &sourcerect, &destrect, &copy_state );\n\n     dfb_gfxcard_flush();\n\n     /* Signal end of sequence. */\n     dfb_state_stop_drawing( &copy_state );\n\n     copy_state.destination = NULL;\n     copy_state.source      = NULL;\n\n     direct_mutex_unlock( &copy_lock );\n}\n\nvoid\ndfb_gfx_copy_regions_client( CoreSurface             *source,\n                             DFBSurfaceBufferRole     from,\n                             DFBSurfaceStereoEye      source_eye,\n                             CoreSurface             *destination,\n                             DFBSurfaceBufferRole     to,\n                             DFBSurfaceStereoEye      destination_eye,\n                             const DFBRegion         *regions,\n                             unsigned int             num,\n                             int                      x,\n                             int                      y,\n                             CoreGraphicsStateClient *client )\n{\n     unsigned int  i, n = 0;\n     DFBRectangle  rect = { 0, 0, source->config.size.w, source->config.size.h };\n     DFBRectangle  rects[num];\n     DFBPoint      points[num];\n     CardState    *state;\n     CardState     backup;\n\n     for (i = 0; i < num; i++) {\n          DFB_REGION_ASSERT( &regions[i] );\n\n          rects[n] = DFB_RECTANGLE_INIT_FROM_REGION( &regions[i] );\n\n          if (dfb_rectangle_intersect( &rects[n], &rect )) {\n               points[n].x = x + rects[n].x;\n               points[n].y = y + rects[n].y;\n\n               n++;\n          }\n     }\n\n     if (n > 0) {\n          if (!client) {\n               direct_mutex_lock( &copy_lock );\n\n               if (!copy_state_inited) {\n                    dfb_state_init( &copy_state, NULL );\n                    copy_state_inited = true;\n               }\n\n               state = &copy_state;\n          }\n          else\n               state = client->state;\n\n          backup.clip          = state->clip;\n          backup.source        = state->source;\n          backup.destination   = state->destination;\n          backup.from          = state->from;\n          backup.from_eye      = state->from_eye;\n          backup.to            = state->to;\n          backup.to_eye        = state->to_eye;\n          backup.blittingflags = state->blittingflags;\n\n          state->modified     |= SMF_CLIP | SMF_SOURCE | SMF_DESTINATION | SMF_FROM | SMF_TO | SMF_BLITTING_FLAGS;\n          state->clip.x1       = 0;\n          state->clip.y1       = 0;\n          state->clip.x2       = destination->config.size.w - 1;\n          state->clip.y2       = destination->config.size.h - 1;\n          state->source        = source;\n          state->destination   = destination;\n          state->from          = from;\n          state->from_eye      = source_eye;\n          state->to            = to;\n          state->to_eye        = destination_eye;\n          state->blittingflags = DSBLIT_NOFX;\n\n          if (!client) {\n               dfb_gfxcard_batchblit( rects, points, n, &copy_state );\n\n               dfb_gfxcard_flush();\n          }\n          else {\n               CoreGraphicsStateClient_Blit( client, rects, points, n );\n\n               CoreGraphicsStateClient_Flush( client );\n          }\n\n          state->modified     |= SMF_CLIP | SMF_SOURCE | SMF_DESTINATION | SMF_FROM | SMF_TO | SMF_BLITTING_FLAGS;\n          state->clip          = backup.clip;\n          state->source        = backup.source;\n          state->destination   = backup.destination;\n          state->from          = backup.from;\n          state->from_eye      = backup.from_eye;\n          state->to            = backup.to;\n          state->to_eye        = backup.to_eye;\n          state->blittingflags = backup.blittingflags;\n\n          if (!client)\n               direct_mutex_unlock( &copy_lock );\n     }\n}\n\nstatic void\nback_to_front_copy( CoreSurface             *surface,\n                    DFBSurfaceStereoEye      eye,\n                    const DFBRegion         *region,\n                    DFBSurfaceBlittingFlags  flags,\n                    int                      rotation )\n{\n     DFBRectangle  rect;\n     int           dx, dy;\n     CardState    *state = &btf_state;\n\n     if (region) {\n          rect.x = region->x1;\n          rect.y = region->y1;\n          rect.w = region->x2 - region->x1 + 1;\n          rect.h = region->y2 - region->y1 + 1;\n     }\n     else {\n          rect.x = 0;\n          rect.y = 0;\n          rect.w = surface->config.size.w;\n          rect.h = surface->config.size.h;\n     }\n\n     dx = rect.x;\n     dy = rect.y;\n\n     direct_mutex_lock( &btf_lock );\n\n     if (!btf_state_inited) {\n          dfb_state_init( state, NULL );\n\n          state->from = DSBR_BACK;\n          state->to   = DSBR_FRONT;\n\n          btf_state_inited = true;\n     }\n\n     state->modified   |= SMF_CLIP | SMF_SOURCE | SMF_DESTINATION | SMF_FROM | SMF_TO;\n     state->clip.x2     = surface->config.size.w - 1;\n     state->clip.y2     = surface->config.size.h - 1;\n     state->source      = surface;\n     state->destination = surface;\n     state->from_eye    = eye;\n     state->to_eye      = eye;\n\n     if (rotation == 90) {\n          dx = rect.y;\n          dy = surface->config.size.w - rect.w - rect.x;\n\n          flags |= DSBLIT_ROTATE90;\n     }\n     else if (rotation == 180) {\n          dx = surface->config.size.w - rect.w - rect.x;\n          dy = surface->config.size.h - rect.h - rect.y;\n\n          flags |= DSBLIT_ROTATE180;\n     }\n     else if (rotation == 270) {\n          dx = surface->config.size.h - rect.h - rect.y;\n          dy = rect.x;\n\n          flags |= DSBLIT_ROTATE270;\n     }\n\n     dfb_state_set_blitting_flags( state, flags );\n\n     dfb_gfxcard_blit( &rect, dx, dy, state );\n\n     dfb_gfxcard_flush();\n\n     /* Signal end of sequence. */\n     dfb_state_stop_drawing( state );\n\n     direct_mutex_unlock( &btf_lock );\n}\n\nvoid\ndfb_back_to_front_copy_stereo( CoreSurface         *surface,\n                               DFBSurfaceStereoEye  eyes,\n                               const DFBRegion     *left_region,\n                               const DFBRegion     *right_region,\n                               int                  rotation )\n{\n     if (eyes & DSSE_LEFT)\n          back_to_front_copy( surface, DSSE_LEFT, left_region, DSBLIT_NOFX, rotation );\n\n     if (eyes & DSSE_RIGHT)\n          back_to_front_copy( surface, DSSE_RIGHT, right_region, DSBLIT_NOFX, rotation );\n}\n\nvoid\ndfb_sort_triangle( DFBTriangle *tri )\n{\n     int temp;\n\n     if (tri->y1 > tri->y2) {\n          temp = tri->x1;\n          tri->x1 = tri->x2;\n          tri->x2 = temp;\n\n          temp = tri->y1;\n          tri->y1 = tri->y2;\n          tri->y2 = temp;\n     }\n\n     if (tri->y2 > tri->y3) {\n          temp = tri->x2;\n          tri->x2 = tri->x3;\n          tri->x3 = temp;\n\n          temp = tri->y2;\n          tri->y2 = tri->y3;\n          tri->y3 = temp;\n     }\n\n     if (tri->y1 > tri->y2) {\n          temp = tri->x1;\n          tri->x1 = tri->x2;\n          tri->x2 = temp;\n\n          temp = tri->y1;\n          tri->y1 = tri->y2;\n          tri->y2 = temp;\n     }\n}\n\nvoid\ndfb_sort_trapezoid( DFBTrapezoid *trap )\n{\n     int temp;\n\n     if (trap->y1 > trap->y2) {\n          temp = trap->x1;\n          trap->x1 = trap->x2;\n          trap->x2 = temp;\n\n          temp = trap->y1;\n          trap->y1 = trap->y2;\n          trap->y2 = temp;\n\n          temp = trap->w1;\n          trap->w1 = trap->w2;\n          trap->w2 = temp;\n     }\n}\n"
  },
  {
    "path": "src/gfx/util.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __GFX__UTIL_H__\n#define __GFX__UTIL_H__\n\n#include <core/coretypes.h>\n\n/**********************************************************************************************************************/\n\nvoid dfb_gfx_copy_stereo          ( CoreSurface             *source,\n                                    DFBSurfaceStereoEye      source_eye,\n                                    CoreSurface             *destination,\n                                    DFBSurfaceStereoEye      destination_eye,\n                                    const DFBRectangle      *rect,\n                                    int                      x,\n                                    int                      y,\n                                    bool                     from_back );\n\nvoid dfb_gfx_clear                ( CoreSurface             *surface,\n                                    DFBSurfaceBufferRole     role );\n\nvoid dfb_gfx_stretch_stereo       ( CoreSurface             *source,\n                                    DFBSurfaceStereoEye      source_eye,\n                                    CoreSurface             *destination,\n                                    DFBSurfaceStereoEye      destination_eye,\n                                    const DFBRectangle      *srect,\n                                    const DFBRectangle      *drect,\n                                    bool                     from_back );\n\nvoid dfb_gfx_copy_regions_client  ( CoreSurface             *source,\n                                    DFBSurfaceBufferRole     from,\n                                    DFBSurfaceStereoEye      source_eye,\n                                    CoreSurface             *destination,\n                                    DFBSurfaceBufferRole     to,\n                                    DFBSurfaceStereoEye      destination_eye,\n                                    const DFBRegion         *regions,\n                                    unsigned int             num,\n                                    int                      x,\n                                    int                      y,\n                                    CoreGraphicsStateClient *client );\n\nvoid dfb_back_to_front_copy_stereo( CoreSurface             *surface,\n                                    DFBSurfaceStereoEye      eyes,\n                                    const DFBRegion         *left_region,\n                                    const DFBRegion         *right_region,\n                                    int                      rotation );\n\nvoid dfb_sort_triangle            ( DFBTriangle             *tri );\n\nvoid dfb_sort_trapezoid           ( DFBTrapezoid            *trap );\n\n/**********************************************************************************************************************/\n\n/*\n * Simplify blitting flags.\n *\n * Allow any combination of DSBLIT_ROTATE_ and DSBLIT_FLIP_ flags to be reduced to a combination of DSBLIT_ROTATE_90,\n * DSBLIT_FLIP_HORIZONTAL and DSBLIT_FLIP_VERTICAL\n */\nstatic __inline__ void\ndfb_simplify_blittingflags( DFBSurfaceBlittingFlags *flags )\n{\n     if (*flags & DSBLIT_ROTATE180)\n          *flags = *flags ^ (DSBLIT_ROTATE180 | DSBLIT_FLIP_HORIZONTAL | DSBLIT_FLIP_VERTICAL);\n\n     if (*flags & DSBLIT_ROTATE270) {\n          if (*flags & DSBLIT_ROTATE90)\n               *flags = *flags ^ (DSBLIT_ROTATE90 | DSBLIT_ROTATE270);\n          else\n               *flags = *flags ^ (DSBLIT_ROTATE90 | DSBLIT_ROTATE270 | DSBLIT_FLIP_HORIZONTAL | DSBLIT_FLIP_VERTICAL);\n     }\n}\n\n#endif\n"
  },
  {
    "path": "src/idirectfb.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreDFB.h>\n#include <core/CoreLayer.h>\n#include <core/CoreLayerContext.h>\n#include <core/CoreLayerRegion.h>\n#include <core/CorePalette.h>\n#include <core/CoreSurface.h>\n#include <core/CoreWindow.h>\n#include <core/CoreWindowStack.h>\n#include <core/layers.h>\n#include <core/layer_context.h>\n#include <core/layer_control.h>\n#include <core/palette.h>\n#include <core/screen.h>\n#include <core/screens.h>\n#include <core/surface_pool.h>\n#include <core/system.h>\n#include <core/windows.h>\n#include <core/wm.h>\n#include <direct/direct.h>\n#include <direct/filesystem.h>\n#include <direct/memcpy.h>\n#include <direct/thread.h>\n#include <display/idirectfbdisplaylayer.h>\n#include <display/idirectfbpalette.h>\n#include <display/idirectfbscreen.h>\n#include <display/idirectfbsurface.h>\n#include <display/idirectfbsurface_layer.h>\n#include <display/idirectfbsurface_window.h>\n#include <idirectfb.h>\n#include <input/idirectfbeventbuffer.h>\n#include <input/idirectfbinputdevice.h>\n#include <media/idirectfbdatabuffer_file.h>\n#include <media/idirectfbdatabuffer_memory.h>\n#include <media/idirectfbdatabuffer_streamed.h>\n#include <media/idirectfbfont.h>\n#include <media/idirectfbimageprovider.h>\n#include <media/idirectfbvideoprovider.h>\n\nD_DEBUG_DOMAIN( DirectFB, \"IDirectFB\", \"IDirectFB Interface\" );\n\n/**********************************************************************************************************************/\n\n/*\n * private data struct of IDirectFB\n */\ntypedef struct {\n     int                         ref;            /* reference counter */\n\n     CoreDFB                    *core;           /* the core object */\n\n     DFBCooperativeLevel         level;          /* current cooperative level */\n\n     CoreLayer                  *layer;          /* primary display layer */\n     CoreLayerContext           *context;        /* shared context of primary layer */\n     CoreWindowStack            *stack;          /* window stack of primary layer */\n\n     struct {\n          int                    width;\n          int                    height;\n          DFBSurfacePixelFormat  format;\n          DFBSurfaceColorSpace   colorspace;\n\n          CoreWindow            *window;\n          Reaction               reaction;\n          bool                   focused;\n\n          CoreLayerContext      *context;\n          DFBWindowOptions       window_options;\n     } primary;\n\n     bool                        app_focus;\n\n     struct {\n          CoreLayer             *layer;\n          CoreLayerContext      *context;\n          CoreLayerRegion       *region;\n          CoreSurface           *surface;\n          CorePalette           *palette;\n     } layers[MAX_LAYERS];\n\n     bool                        init_done;\n     DirectMutex                 init_lock;\n     DirectWaitQueue             init_wq;\n} IDirectFB_data;\n\ntypedef struct {\n     DFBScreenCallback  callback;\n     void              *callback_ctx;\n} EnumScreens_Context;\n\ntypedef struct {\n     IDirectFBScreen **interface;\n     DFBScreenID       id;\n     DFBResult         ret;\n} GetScreen_Context;\n\ntypedef struct {\n     DFBDisplayLayerCallback  callback;\n     void                    *callback_ctx;\n} EnumDisplayLayers_Context;\n\ntypedef struct {\n     IDirectFBDisplayLayer **interface;\n     DFBDisplayLayerID       id;\n     DFBResult               ret;\n     CoreDFB                *core;\n     IDirectFB              *idirectfb;\n} GetDisplayLayer_Context;\n\ntypedef struct {\n     DFBInputDeviceCallback  callback;\n     void                   *callback_ctx;\n} EnumInputDevices_Context;\n\ntypedef struct {\n     IDirectFBInputDevice **interface;\n     DFBInputDeviceID       id;\n     DFBResult              ret;\n} GetInputDevice_Context;\n\ntypedef struct {\n     IDirectFBEventBuffer       **interface;\n     DFBInputDeviceCapabilities   caps;\n} CreateEventBuffer_Context;\n\nstatic DFBEnumerationResult EnumScreens_Callback      ( CoreScreen      *screen, void *ctx );\nstatic DFBEnumerationResult GetScreen_Callback        ( CoreScreen      *screen, void *ctx );\nstatic DFBEnumerationResult EnumDisplayLayers_Callback( CoreLayer       *layer,  void *ctx );\nstatic DFBEnumerationResult GetDisplayLayer_Callback  ( CoreLayer       *layer,  void *ctx );\nstatic DFBEnumerationResult EnumInputDevices_Callback ( CoreInputDevice *device, void *ctx );\nstatic DFBEnumerationResult GetInputDevice_Callback   ( CoreInputDevice *device, void *ctx );\nstatic DFBEnumerationResult CreateEventBuffer_Callback( CoreInputDevice *device, void *ctx );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     DirectLink                  link;\n     DFBInputDeviceCapabilities  caps;\n     IDirectFBEventBuffer       *iface;\n} EventBuffer_Container;\n\nstatic DirectLink  *eventbuffer_containers      = NULL;\nstatic DirectMutex  eventbuffer_containers_lock = DIRECT_MUTEX_INITIALIZER();\n\nstatic void\neventbuffer_containers_add( CreateEventBuffer_Context *context )\n{\n     EventBuffer_Container *container;\n\n     D_DEBUG_AT( DirectFB, \"%s()\\n\", __FUNCTION__ );\n\n     direct_mutex_lock( &eventbuffer_containers_lock );\n\n     container = D_CALLOC( 1, sizeof(EventBuffer_Container) );\n     if (!container) {\n          D_OOM();\n     }\n\n     container->caps  = context->caps;\n     container->iface = *context->interface;\n\n     direct_list_append( &eventbuffer_containers, &container->link );\n\n     direct_mutex_unlock( &eventbuffer_containers_lock );\n}\n\nvoid\neventbuffer_containers_remove( IDirectFBEventBuffer *thiz )\n{\n     EventBuffer_Container *container, *next;\n\n     D_DEBUG_AT( DirectFB, \"%s()\\n\", __FUNCTION__ );\n\n     direct_mutex_lock( &eventbuffer_containers_lock );\n\n     direct_list_foreach_safe (container, next, eventbuffer_containers) {\n          if (thiz == container->iface) {\n               direct_list_remove( &eventbuffer_containers, &container->link );\n               D_FREE( container );\n          }\n     }\n\n     direct_mutex_unlock( &eventbuffer_containers_lock );\n}\n\nvoid\neventbuffer_containers_attach_device( CoreInputDevice *device )\n{\n     EventBuffer_Container      *container;\n     DFBInputDeviceCapabilities  dev_caps;\n\n     D_DEBUG_AT( DirectFB, \"%s()\\n\", __FUNCTION__ );\n\n     dev_caps = dfb_input_device_caps( device );\n\n     direct_mutex_lock( &eventbuffer_containers_lock );\n\n     direct_list_foreach (container, eventbuffer_containers) {\n          if (dev_caps & container->caps) {\n               IDirectFBEventBuffer_AttachInputDevice( container->iface, device );\n          }\n     }\n\n     direct_mutex_unlock( &eventbuffer_containers_lock );\n}\n\nvoid\neventbuffer_containers_detach_device( CoreInputDevice *device )\n{\n     EventBuffer_Container *container;\n\n     D_DEBUG_AT( DirectFB, \"%s()\\n\", __FUNCTION__ );\n\n     direct_mutex_lock( &eventbuffer_containers_lock );\n\n     direct_list_foreach (container, eventbuffer_containers) {\n          IDirectFBEventBuffer_DetachInputDevice( container->iface, device );\n     }\n\n     direct_mutex_unlock( &eventbuffer_containers_lock );\n}\n\n/**********************************************************************************************************************/\n\nstatic void\ndrop_window( IDirectFB_data *data,\n             bool            enable_cursor )\n{\n     if (!data->primary.window)\n          return;\n\n     dfb_window_detach( data->primary.window, &data->primary.reaction );\n     dfb_window_unref( data->primary.window );\n\n     data->primary.window  = NULL;\n     data->primary.focused = false;\n\n     if (dfb_config->cursor_automation)\n          CoreWindowStack_CursorEnable( data->stack, enable_cursor );\n}\n\nstatic DFBResult\nIDirectFB_Destruct( IDirectFB *thiz )\n{\n     DFBResult       ret;\n     IDirectFB_data *data = thiz->priv;\n     int             i;\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     drop_window( data, false );\n\n     if (data->primary.context)\n          dfb_layer_context_unref( data->primary.context );\n\n     dfb_layer_context_unref( data->context );\n\n     direct_thread_sleep( 10000 );\n\n     for (i = 0; i < MAX_LAYERS; i++) {\n          if (data->layers[i].context) {\n               if (data->layers[i].palette)\n                    dfb_palette_unref( data->layers[i].palette );\n\n               dfb_surface_unref( data->layers[i].surface );\n               dfb_layer_region_unref( data->layers[i].region );\n               dfb_layer_context_unref( data->layers[i].context );\n          }\n     }\n\n     ret = dfb_core_destroy( data->core, false );\n\n     DIRECT_DEALLOCATE_INTERFACE( thiz );\n\n     direct_shutdown();\n\n     if (thiz == idirectfb_singleton)\n          idirectfb_singleton = NULL;\n\n     return ret;\n}\n\nstatic DirectResult\nIDirectFB_AddRef( IDirectFB *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref++;\n\n     return DFB_OK;\n}\n\nstatic DirectResult\nIDirectFB_Release( IDirectFB *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->ref == 0)\n          return IDirectFB_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFB_SetCooperativeLevel( IDirectFB           *thiz,\n                               DFBCooperativeLevel  level )\n{\n     DFBResult         ret;\n     CoreLayerContext *context;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p, %u )\\n\", __FUNCTION__, thiz, level );\n\n     if (level == data->level)\n          return DFB_OK;\n\n     switch (level) {\n          case DFSCL_NORMAL:\n               data->primary.focused = false;\n\n               dfb_layer_context_unref( data->primary.context );\n\n               data->primary.context = NULL;\n               break;\n\n          case DFSCL_FULLSCREEN:\n          case DFSCL_EXCLUSIVE:\n               if (dfb_config->primary_id)\n                    return DFB_ACCESSDENIED;\n\n               if (dfb_config->force_windowed)\n                    return DFB_ACCESSDENIED;\n\n               if (data->level == DFSCL_NORMAL) {\n                    ret = CoreLayer_CreateContext( data->layer, &context );\n                    if (ret)\n                         return ret;\n\n                    ret = CoreLayer_ActivateContext( data->layer, context );\n                    if (ret) {\n                         dfb_layer_context_unref( context );\n                         return ret;\n                    }\n\n                    drop_window( data, true );\n\n                    data->primary.context = context;\n               }\n\n               data->primary.focused = true;\n               break;\n\n          default:\n               return DFB_INVARG;\n     }\n\n     data->level = level;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFB_SetVideoMode( IDirectFB *thiz,\n                        int        width,\n                        int        height,\n                        int        bpp )\n{\n     DFBResult             ret;\n     DFBDisplayLayerConfig config;\n     DFBSurfacePixelFormat format;\n     DFBSurfaceColorSpace  colorspace;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p, %dx%d %dbit )\\n\", __FUNCTION__, thiz, width, height, bpp );\n\n     if (width < 1 || height < 1 || bpp < 1)\n          return DFB_INVARG;\n\n     format = dfb_pixelformat_for_depth( bpp );\n     if (format == DSPF_UNKNOWN)\n          return DFB_INVARG;\n\n     colorspace = DFB_COLORSPACE_DEFAULT( format );\n\n     switch (data->level) {\n          case DFSCL_NORMAL:\n               if (data->primary.window) {\n                    ret = dfb_window_resize( data->primary.window, width, height );\n                    if (ret)\n                         return ret;\n               }\n               break;\n\n          case DFSCL_FULLSCREEN:\n          case DFSCL_EXCLUSIVE:\n               config.flags       = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT;\n               config.width       = width;\n               config.height      = height;\n               config.pixelformat = format;\n               config.colorspace  = colorspace;\n\n               ret = CoreLayerContext_SetConfiguration( data->primary.context, &config );\n               if (ret)\n                    return ret;\n\n               break;\n     }\n\n     data->primary.width          = width;\n     data->primary.height         = height;\n     data->primary.format         = format;\n     data->primary.colorspace     = colorspace;\n     data->primary.window_options = DWOP_KEEP_SIZE;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFB_GetDeviceDescription( IDirectFB                    *thiz,\n                                DFBGraphicsDeviceDescription *ret_desc )\n{\n     GraphicsDeviceInfo device_info;\n     GraphicsDriverInfo driver_info;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_desc)\n          return DFB_INVARG;\n\n     dfb_gfxcard_get_device_info( &device_info );\n     dfb_gfxcard_get_driver_info( &driver_info );\n\n     ret_desc->acceleration_mask = device_info.caps.accel;\n     ret_desc->blitting_flags    = device_info.caps.blitting;\n     ret_desc->drawing_flags     = device_info.caps.drawing;\n     ret_desc->video_memory      = dfb_gfxcard_memory_length();\n\n     direct_snputs( ret_desc->name,   device_info.name,   DFB_GRAPHICS_DEVICE_DESC_NAME_LENGTH );\n     direct_snputs( ret_desc->vendor, device_info.vendor, DFB_GRAPHICS_DEVICE_DESC_NAME_LENGTH );\n\n     ret_desc->driver.major = driver_info.version.major;\n     ret_desc->driver.minor = driver_info.version.minor;\n\n     direct_snputs( ret_desc->driver.name,   driver_info.name,   DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH );\n     direct_snputs( ret_desc->driver.vendor, driver_info.vendor, DFB_GRAPHICS_DRIVER_INFO_VENDOR_LENGTH );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFB_EnumVideoModes( IDirectFB            *thiz,\n                          DFBVideoModeCallback  callback,\n                          void                 *callbackdata )\n{\n     VideoMode *m;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!callback)\n          return DFB_INVARG;\n\n     m = dfb_system_modes();\n     while (m) {\n          if (callback( m->xres, m->yres, m->bpp, callbackdata ) == DFENUM_CANCEL)\n               break;\n\n          m = m->next;\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ninit_palette( CoreSurface                 *surface,\n              const DFBSurfaceDescription *desc )\n{\n     DFBResult    ret;\n     CorePalette *palette;\n\n     if (!(desc->flags & DSDESC_PALETTE))\n          return DFB_OK;\n\n     ret = CoreSurface_GetPalette( surface, &palette );\n     if (ret)\n          return ret;\n\n     ret = CorePalette_SetEntries( palette, desc->palette.entries, MIN( desc->palette.size, palette->num_entries ), 0 );\n\n     dfb_palette_unref( palette );\n\n     return ret;\n}\n\nstatic ReactionResult\nfocus_listener( const void *msg_data,\n                void       *ctx )\n{\n     const DFBWindowEvent *evt  = msg_data;\n     IDirectFB_data       *data = ctx;\n\n     switch (evt->type) {\n          case DWET_DESTROYED:\n               dfb_window_unref( data->primary.window );\n               data->primary.window = NULL;\n               data->primary.focused = false;\n               return RS_REMOVE;\n\n          case DWET_GOTFOCUS:\n               data->primary.focused = true;\n               break;\n\n          case DWET_LOSTFOCUS:\n               data->primary.focused = false;\n               break;\n\n          default:\n               break;\n     }\n\n     return RS_OK;\n}\n\nstatic DFBResult\nIDirectFB_CreateSurface( IDirectFB                    *thiz,\n                         const DFBSurfaceDescription  *desc,\n                         IDirectFBSurface            **ret_interface )\n{\n     DFBResult               ret;\n     DFBDisplayLayerConfig   config;\n     DFBSurfacePixelFormat   format;\n     DFBSurfaceColorSpace    colorspace;\n     CoreSurface            *surface;\n     IDirectFBSurface       *iface;\n     unsigned long           resource_id = 0;\n     int                     width       = 256;\n     int                     height      = 256;\n     DFBSurfaceCapabilities  caps        = DSCAPS_NONE;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->primary.context)\n          dfb_layer_context_get_configuration( data->primary.context, &config );\n     else if (data->context)\n          dfb_layer_context_get_configuration( data->context, &config );\n     else {\n          config.width       = 512;\n          config.height      = 512;\n          config.pixelformat = DSPF_ARGB;\n          config.colorspace  = DSCS_RGB;\n     }\n\n     if (desc->flags & DSDESC_HINTS && desc->hints & DSHF_FONT) {\n          format     = dfb_config->font_format;\n          colorspace = DFB_COLORSPACE_DEFAULT( format );\n\n          if (dfb_config->font_premult)\n               caps  = DSCAPS_PREMULTIPLIED;\n     }\n     else {\n          format     = config.pixelformat;\n          colorspace = config.colorspace;\n     }\n\n     if (!desc || !ret_interface)\n          return DFB_INVARG;\n\n     D_DEBUG_AT( DirectFB, \"  -> flags  0x%08x\\n\", desc->flags );\n\n     if (desc->flags & DSDESC_WIDTH) {\n          D_DEBUG_AT( DirectFB, \"  -> width  %d\\n\", desc->width );\n\n          width = desc->width;\n          if (width < 1 || width > 20480)\n               return DFB_INVARG;\n     }\n\n     if (desc->flags & DSDESC_HEIGHT) {\n          D_DEBUG_AT( DirectFB, \"  -> height %d\\n\", desc->height );\n\n          height = desc->height;\n          if (height < 1 || height > 20480)\n               return DFB_INVARG;\n     }\n\n     if (desc->flags & DSDESC_PALETTE) {\n          D_DEBUG_AT( DirectFB, \"  -> PALETTE\\n\" );\n\n          if (!desc->palette.entries) {\n               D_DEBUG_AT( DirectFB, \"    -> no entries!\\n\" );\n               return DFB_INVARG;\n          }\n\n          if (!desc->palette.size) {\n               D_DEBUG_AT( DirectFB, \"    -> no size!\\n\" );\n               return DFB_INVARG;\n          }\n     }\n\n     if (desc->flags & DSDESC_CAPS) {\n          D_DEBUG_AT( DirectFB, \"  -> caps   0x%08x\\n\", desc->caps );\n\n          caps = desc->caps;\n     }\n\n     if (desc->flags & DSDESC_PIXELFORMAT) {\n          D_DEBUG_AT( DirectFB, \"  -> format %s\\n\", dfb_pixelformat_name( desc->pixelformat ) );\n\n          format     = desc->pixelformat;\n          colorspace = DFB_COLORSPACE_DEFAULT( format );\n     }\n\n     if (desc->flags & DSDESC_COLORSPACE) {\n          D_DEBUG_AT( DirectFB, \"  -> colorspace %s\\n\", dfb_colorspace_name( desc->pixelformat ) );\n\n          if (!DFB_COLORSPACE_IS_COMPATIBLE( desc->colorspace, format )) {\n               D_DEBUG_AT( DirectFB, \"    -> incompatible colorspace!\\n\" );\n               return DFB_INVARG;\n          }\n\n          colorspace = desc->colorspace;\n     }\n\n     if (desc->flags & DSDESC_RESOURCE_ID)\n          resource_id = desc->resource_id;\n\n     switch (format) {\n          case DSPF_A1:\n          case DSPF_A1_LSB:\n          case DSPF_A4:\n          case DSPF_A8:\n          case DSPF_ARGB:\n          case DSPF_ABGR:\n          case DSPF_ARGB8565:\n          case DSPF_ARGB1555:\n          case DSPF_RGBA5551:\n          case DSPF_ARGB1666:\n          case DSPF_ARGB6666:\n          case DSPF_ARGB2554:\n          case DSPF_ARGB4444:\n          case DSPF_RGBA4444:\n          case DSPF_AYUV:\n          case DSPF_AVYU:\n          case DSPF_AiRGB:\n          case DSPF_I420:\n          case DSPF_Y42B:\n          case DSPF_Y444:\n          case DSPF_LUT1:\n          case DSPF_LUT2:\n          case DSPF_LUT8:\n          case DSPF_ALUT44:\n          case DSPF_RGB16:\n          case DSPF_RGB18:\n          case DSPF_RGB24:\n          case DSPF_BGR24:\n          case DSPF_RGB32:\n          case DSPF_RGB332:\n          case DSPF_UYVY:\n          case DSPF_YUY2:\n          case DSPF_YV12:\n          case DSPF_YV16:\n          case DSPF_YV24:\n          case DSPF_NV12:\n          case DSPF_NV21:\n          case DSPF_NV16:\n          case DSPF_NV61:\n          case DSPF_NV24:\n          case DSPF_NV42:\n          case DSPF_VYU:\n          case DSPF_RGB444:\n          case DSPF_RGB555:\n          case DSPF_BGR555:\n          case DSPF_RGBAF88871:\n               break;\n\n          default:\n               D_DEBUG_AT( DirectFB, \"  -> invalid pixelformat 0x%08x\\n\", (unsigned int) format );\n               return DFB_INVARG;\n     }\n\n     if (caps & DSCAPS_PRIMARY) {\n          D_DEBUG_AT( DirectFB, \"  -> PRIMARY\\n\" );\n\n          if (dfb_config->primary_id) {\n               D_DEBUG_AT( DirectFB, \"    -> primary-id 0x%x\\n\", dfb_config->primary_id );\n\n               ret = CoreDFB_GetSurface( data->core, dfb_config->primary_id, &surface );\n               if (ret)\n                    return ret;\n\n               DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBSurface );\n\n               ret = IDirectFBSurface_Construct( iface, NULL, NULL, NULL, NULL, surface, DSCAPS_PRIMARY, data->core,\n                                                 thiz );\n               if (ret) {\n                    dfb_surface_unref( surface );\n                    return ret;\n               }\n\n               init_palette( surface, desc );\n\n               dfb_surface_unref( surface );\n\n               *ret_interface = iface;\n\n               return ret;\n          }\n\n          if (desc->flags & DSDESC_PREALLOCATED) {\n               D_DEBUG_AT( DirectFB, \"    -> cannot make preallocated primary!\\n\" );\n               return DFB_INVARG;\n          }\n\n          if (desc->flags & DSDESC_PIXELFORMAT)\n               format     = desc->pixelformat;\n          else if (data->primary.format) {\n               format     = data->primary.format;\n               colorspace = data->primary.colorspace;\n          }\n          else if (dfb_config->mode.format) {\n               format     = dfb_config->mode.format;\n               colorspace = DFB_COLORSPACE_DEFAULT( format );\n          }\n          else {\n               format     = config.pixelformat;\n               colorspace = config.colorspace;\n          }\n\n          if (desc->flags & DSDESC_WIDTH)\n               width = desc->width;\n          else if (data->primary.width)\n               width = data->primary.width;\n          else if (dfb_config->mode.width)\n               width = dfb_config->mode.width;\n          else\n               width = config.width;\n\n          if (desc->flags & DSDESC_HEIGHT)\n               height = desc->height;\n          else if (data->primary.height)\n               height = data->primary.height;\n          else if (dfb_config->mode.height)\n               height = dfb_config->mode.height;\n          else\n               height = config.height;\n\n          switch (data->level) {\n               case DFSCL_NORMAL: {\n                    D_DEBUG_AT( DirectFB, \"    -> level normal\\n\" );\n\n                    CoreWindow           *window;\n                    DFBWindowDescription  wd;\n\n                    memset( &wd, 0, sizeof(wd) );\n\n                    wd.flags = DWDESC_POSX | DWDESC_POSY | DWDESC_CAPS | DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_OPTIONS |\n                               DWDESC_PIXELFORMAT | DWDESC_COLORSPACE | DWDESC_SURFACE_CAPS | DWDESC_RESOURCE_ID;\n\n                    if (dfb_config->scaled.width && dfb_config->scaled.height) {\n                         wd.posx = (config.width  - dfb_config->scaled.width)  / 2;\n                         wd.posy = (config.height - dfb_config->scaled.height) / 2;\n                    }\n                    else {\n                         wd.posx = (config.width  - width)  / 2;\n                         wd.posy = (config.height - height) / 2;\n                    }\n\n                    if (!(caps & (DSCAPS_VIDEOONLY | DSCAPS_SYSTEMONLY))) {\n                         if (dfb_config->window_policy == DWSP_SYSTEMONLY)\n                              caps |= DSCAPS_SYSTEMONLY;\n                         else if (dfb_config->window_policy == DWSP_VIDEOONLY)\n                              caps |= DSCAPS_VIDEOONLY;\n                    }\n\n                    wd.width        = width;\n                    wd.height       = height;\n                    wd.pixelformat  = format;\n                    wd.colorspace   = colorspace;\n                    wd.surface_caps = caps;\n                    wd.resource_id  = resource_id;\n                    wd.options      = data->primary.window_options;\n\n                    if (desc->flags & (DSDESC_WIDTH | DSDESC_HEIGHT))\n                         wd.options |= DWOP_KEEP_SIZE;\n\n                    switch (format) {\n                         case DSPF_ARGB8565:\n                         case DSPF_ARGB4444:\n                         case DSPF_RGBA4444:\n                         case DSPF_ARGB2554:\n                         case DSPF_ARGB1555:\n                         case DSPF_RGBA5551:\n                         case DSPF_ARGB:\n                         case DSPF_ABGR:\n                         case DSPF_AYUV:\n                         case DSPF_AVYU:\n                         case DSPF_AiRGB:\n                         case DSPF_RGBAF88871:\n                              wd.caps |= DWCAPS_ALPHACHANNEL;\n                              if (caps & DSCAPS_PREMULTIPLIED)\n                                   wd.options |= DWOP_ALPHACHANNEL;\n                              break;\n\n                         default:\n                              break;\n                    }\n\n                    if ((caps & DSCAPS_FLIPPING) == DSCAPS_DOUBLE)\n                         wd.caps |= DWCAPS_DOUBLEBUFFER;\n\n                    if (caps & DSCAPS_STEREO)\n                         wd.caps |= DWCAPS_STEREO;\n\n                    ret = CoreLayerContext_CreateWindow( data->context, &wd, &window );\n                    if (ret)\n                         return ret;\n\n                    drop_window( data, true );\n\n                    data->primary.window = window;\n\n                    dfb_window_attach( window, focus_listener, data, &data->primary.reaction );\n\n                    CoreWindow_ChangeOptions( window, DWOP_NONE, DWOP_SCALE );\n\n                    CoreWindow_AllowFocus( window );\n\n                    if (dfb_config->scaled.width && dfb_config->scaled.height)\n                         CoreWindow_Resize( window, dfb_config->scaled.width, dfb_config->scaled.height );\n\n                    init_palette( window->surface, desc );\n\n                    DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBSurface );\n\n                    ret = IDirectFBSurface_Window_Construct( iface, NULL, NULL, NULL, window, caps, data->core, thiz );\n                    if (ret == DFB_OK)\n                         *ret_interface = iface;\n\n                    return ret;\n               }\n\n               case DFSCL_FULLSCREEN:\n               case DFSCL_EXCLUSIVE: {\n                    CoreLayerRegion  *region;\n                    CoreLayerContext *context = data->primary.context;\n\n                    config.flags |= DLCONF_PIXELFORMAT | DLCONF_COLORSPACE | DLCONF_WIDTH | DLCONF_HEIGHT |\n                                    DLCONF_BUFFERMODE;\n\n                    config.surface_caps = DSCAPS_NONE;\n\n                    if (caps & DSCAPS_PREMULTIPLIED) {\n                          config.flags        |= DLCONF_SURFACE_CAPS;\n                          config.surface_caps |= DSCAPS_PREMULTIPLIED;\n                    }\n\n                    if (caps & DSCAPS_GL) {\n                          config.flags        |= DLCONF_SURFACE_CAPS;\n                          config.surface_caps |= DSCAPS_GL;\n                    }\n\n                    if (caps & DSCAPS_TRIPLE) {\n                         if (caps & DSCAPS_SYSTEMONLY)\n                              return DFB_UNSUPPORTED;\n                         config.buffermode = DLBM_TRIPLE;\n                    }\n                    else if (caps & DSCAPS_DOUBLE) {\n                         if (caps & DSCAPS_SYSTEMONLY)\n                              config.buffermode = DLBM_BACKSYSTEM;\n                         else\n                              config.buffermode = DLBM_BACKVIDEO;\n                    }\n                    else\n                         config.buffermode = DLBM_FRONTONLY;\n\n                    if (caps & DSCAPS_STEREO) {\n                         config.flags   |= DLCONF_OPTIONS;\n                         config.options  = DLOP_STEREO;\n                    }\n\n                    config.pixelformat = format;\n                    config.colorspace  = colorspace;\n                    config.width       = width;\n                    config.height      = height;\n\n                    ret = CoreLayerContext_SetConfiguration( context, &config );\n                    if (ret) {\n                         if (caps & (DSCAPS_SYSTEMONLY | DSCAPS_VIDEOONLY))\n                              return ret;\n\n                         if (config.buffermode == DLBM_TRIPLE) {\n                              config.buffermode = DLBM_BACKVIDEO;\n\n                              ret = CoreLayerContext_SetConfiguration( context, &config );\n                              if (ret) {\n                                   config.buffermode = DLBM_BACKSYSTEM;\n\n                                   ret = CoreLayerContext_SetConfiguration( context, &config );\n                                   if (ret)\n                                        return ret;\n                              }\n                         }\n                         else if (config.buffermode == DLBM_BACKVIDEO) {\n                              config.buffermode = DLBM_BACKSYSTEM;\n\n                              ret = CoreLayerContext_SetConfiguration( context, &config );\n                              if (ret)\n                                   return ret;\n                         }\n                         else\n                              return ret;\n                    }\n\n                    if ((caps & DSCAPS_FLIPPING) == DSCAPS_FLIPPING) {\n                         if (config.buffermode == DLBM_TRIPLE)\n                              caps &= ~DSCAPS_DOUBLE;\n                         else\n                              caps &= ~DSCAPS_TRIPLE;\n                    }\n\n                    ret = CoreLayerContext_GetPrimaryRegion( context, true, &region );\n                    if (ret)\n                         return ret;\n\n                    ret = CoreLayerRegion_GetSurface( region, &surface );\n                    if (ret) {\n                         dfb_layer_region_unref( region );\n                         return ret;\n                    }\n\n                    init_palette( surface, desc );\n\n                    if (config.buffermode != DLBM_BACKVIDEO &&\n                        config.buffermode != DLBM_TRIPLE) {\n                         /* If a window stack is available, give it the opportunity to render the background\n                            and flip the display layer so it is visible.\n                            Otherwise, just directly flip the display layer and make it visible. */\n                         if (data->stack) {\n                              CoreWindowStack_RepaintAll( data->stack );\n                         }\n                         else {\n                              CoreSurface_Flip2( surface, DFB_FALSE, NULL, NULL, DSFLIP_NONE, -1 );\n                         }\n                    }\n\n                    DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBSurface );\n\n                    ret = IDirectFBSurface_Layer_Construct( iface, NULL, NULL, NULL, region, caps, data->core, thiz );\n\n                    dfb_surface_unref( surface );\n                    dfb_layer_region_unref( region );\n\n                    if (ret == DFB_OK)\n                         *ret_interface = iface;\n\n                    return ret;\n               }\n          }\n     }\n\n     if ((caps & DSCAPS_FLIPPING) == DSCAPS_FLIPPING)\n          caps &= ~DSCAPS_TRIPLE;\n\n     if (desc->flags & DSDESC_PREALLOCATED) {\n          int               min_pitch;\n          CoreSurfaceConfig surface_config;\n          int               i, num = 1;\n\n          min_pitch = DFB_BYTES_PER_LINE( format, width );\n\n          if (caps & DSCAPS_DOUBLE)\n               num = 2;\n          else if (caps & DSCAPS_TRIPLE)\n               num = 3;\n\n          D_DEBUG_AT( DirectFB, \"  -> %d buffers, min pitch %d\\n\", num, min_pitch );\n\n          for (i = 0; i < num; i++) {\n               if (!desc->preallocated[i].data) {\n                    D_DEBUG_AT( DirectFB, \"    -> no data in preallocated [%d]\\n\", i );\n                    return DFB_INVARG;\n               }\n\n               if (desc->preallocated[i].pitch < min_pitch) {\n                    D_DEBUG_AT( DirectFB, \"    -> wrong pitch (%d) in preallocated [%d]\\n\",\n                                desc->preallocated[i].pitch, i );\n                    return DFB_INVARG;\n               }\n          }\n\n          surface_config.flags      = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_COLORSPACE | CSCONF_CAPS | CSCONF_PREALLOCATED;\n          surface_config.size.w     = width;\n          surface_config.size.h     = height;\n          surface_config.format     = format;\n          surface_config.colorspace = colorspace;\n          surface_config.caps       = caps;\n\n          ret = dfb_surface_pools_prealloc( desc, &surface_config );\n          if (ret) {\n               D_DERROR( ret, \"IDirectFB: Preallocation failed!\\n\" );\n               return ret;\n          }\n\n          ret = CoreDFB_CreateSurface( data->core, &surface_config, CSTF_PREALLOCATED, resource_id, NULL, &surface );\n          if (ret)\n               return ret;\n     }\n     else {\n          CoreSurfaceConfig surface_config;\n\n          surface_config.flags      = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_COLORSPACE | CSCONF_CAPS;\n          surface_config.size.w     = width;\n          surface_config.size.h     = height;\n          surface_config.format     = format;\n          surface_config.colorspace = colorspace;\n          surface_config.caps       = caps;\n\n          ret = CoreDFB_CreateSurface( data->core, &surface_config, CSTF_NONE, resource_id, NULL, &surface );\n          if (ret)\n               return ret;\n     }\n\n     init_palette( surface, desc );\n\n     DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBSurface );\n\n     ret = IDirectFBSurface_Construct( iface, NULL, NULL, NULL, NULL, surface, caps, data->core, thiz );\n\n     dfb_surface_unref( surface );\n\n     if (ret == DFB_OK)\n          *ret_interface = iface;\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFB_CreatePalette( IDirectFB                    *thiz,\n                         const DFBPaletteDescription  *desc,\n                         IDirectFBPalette            **ret_interface )\n{\n     DFBResult             ret;\n     CorePalette          *palette;\n     IDirectFBPalette     *iface;\n     unsigned int          size       = 256;\n     DFBSurfaceColorSpace  colorspace = DSCS_RGB;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     if (desc && desc->flags & DPDESC_SIZE) {\n          if (!desc->size)\n               return DFB_INVARG;\n\n          size = desc->size;\n     }\n\n     if (desc && desc->flags & DPDESC_COLORSPACE) {\n          colorspace = desc->colorspace;\n     }\n\n     ret = CoreDFB_CreatePalette( data->core, size, colorspace, &palette );\n     if (ret)\n          return ret;\n\n     if (desc && desc->flags & DPDESC_ENTRIES)\n          CorePalette_SetEntries( palette, desc->entries, size, 0 );\n     else\n          dfb_palette_generate_rgb332_map( palette );\n\n     DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBPalette );\n\n     ret = IDirectFBPalette_Construct( iface, palette, data->core );\n\n     dfb_palette_unref( palette );\n\n     if (ret == DFB_OK)\n          *ret_interface = iface;\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFB_EnumScreens( IDirectFB         *thiz,\n                       DFBScreenCallback  callback,\n                       void              *callbackdata )\n{\n     EnumScreens_Context context;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!callback)\n          return DFB_INVARG;\n\n     context.callback     = callback;\n     context.callback_ctx = callbackdata;\n\n     dfb_screens_enumerate( EnumScreens_Callback, &context );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFB_GetScreen( IDirectFB        *thiz,\n                     DFBScreenID       screen_id,\n                     IDirectFBScreen **ret_interface )\n{\n     GetScreen_Context  context;\n     IDirectFBScreen   *iface;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p, %u )\\n\", __FUNCTION__, thiz, screen_id );\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     if (dfb_config->primary_only && screen_id != DLID_PRIMARY)\n          return DFB_IDNOTFOUND;\n\n     context.interface = &iface;\n     context.id        = screen_id;\n     context.ret       = DFB_IDNOTFOUND;\n\n     dfb_screens_enumerate( GetScreen_Callback, &context );\n\n     if (!context.ret)\n          *ret_interface = iface;\n\n     return context.ret;\n}\n\nstatic DFBResult\nIDirectFB_EnumDisplayLayers( IDirectFB               *thiz,\n                             DFBDisplayLayerCallback  callback,\n                             void                    *callbackdata )\n{\n     EnumDisplayLayers_Context context;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!callback)\n          return DFB_INVARG;\n\n     context.callback     = callback;\n     context.callback_ctx = callbackdata;\n\n     dfb_layers_enumerate( EnumDisplayLayers_Callback, &context );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFB_GetDisplayLayer( IDirectFB              *thiz,\n                           DFBDisplayLayerID       layer_id,\n                           IDirectFBDisplayLayer **ret_interface )\n{\n     GetDisplayLayer_Context  context;\n     IDirectFBDisplayLayer   *iface;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p, %u )\\n\", __FUNCTION__, thiz, layer_id );\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     if (dfb_config->primary_only && layer_id != DLID_PRIMARY)\n          return DFB_IDNOTFOUND;\n\n     context.interface = &iface;\n     context.id        = layer_id;\n     context.ret       = DFB_IDNOTFOUND;\n     context.core      = data->core;\n     context.idirectfb = thiz;\n\n     dfb_layers_enumerate( GetDisplayLayer_Callback, &context );\n\n     if (!context.ret)\n          *ret_interface = iface;\n\n     return context.ret;\n}\n\nstatic DFBResult\nIDirectFB_EnumInputDevices( IDirectFB              *thiz,\n                            DFBInputDeviceCallback  callback,\n                            void                   *callbackdata )\n{\n     EnumInputDevices_Context context;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!callback)\n          return DFB_INVARG;\n\n     context.callback     = callback;\n     context.callback_ctx = callbackdata;\n\n     dfb_input_enumerate_devices( EnumInputDevices_Callback, &context, DICAPS_ALL );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFB_GetInputDevice( IDirectFB             *thiz,\n                          DFBInputDeviceID       device_id,\n                          IDirectFBInputDevice **ret_interface )\n{\n     GetInputDevice_Context  context;\n     IDirectFBInputDevice   *iface;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p, %u )\\n\", __FUNCTION__, thiz, device_id );\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     context.interface = &iface;\n     context.id        = device_id;\n     context.ret       = DFB_IDNOTFOUND;\n\n     dfb_input_enumerate_devices( GetInputDevice_Callback, &context, DICAPS_ALL );\n\n     if (!context.ret)\n          *ret_interface = iface;\n\n     return context.ret;\n}\n\nstatic DFBResult\nIDirectFB_CreateEventBuffer( IDirectFB             *thiz,\n                             IDirectFBEventBuffer **ret_interface )\n{\n     DFBResult             ret;\n     IDirectFBEventBuffer *iface;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBEventBuffer );\n\n     ret = IDirectFBEventBuffer_Construct( iface, NULL, NULL );\n\n     if (ret == DFB_OK)\n          *ret_interface = iface;\n\n     return ret;\n}\n\nstatic bool\ninput_filter_local( DFBEvent *evt,\n                    void     *ctx )\n{\n     IDirectFB_data *data = ctx;\n\n     if (evt->clazz == DFEC_INPUT) {\n          DFBInputEvent *event = &evt->input;\n\n          if (!data->primary.focused && !data->app_focus)\n               return true;\n\n          if (dfb_config->cursor_automation) {\n               switch (event->type) {\n                    case DIET_BUTTONPRESS:\n                         if (data->primary.window)\n                              CoreWindowStack_CursorEnable( data->stack, false );\n                         break;\n                    case DIET_KEYPRESS:\n                         if (data->primary.window)\n                              CoreWindowStack_CursorEnable( data->stack,\n                                                            (event->key_symbol == DIKS_ESCAPE) ||\n                                                            (event->modifiers & DIMM_META) );\n                         break;\n                    default:\n                         break;\n               }\n          }\n     }\n\n     return false;\n}\n\nstatic bool\ninput_filter_global( DFBEvent *evt,\n                     void     *ctx )\n{\n     IDirectFB_data *data = ctx;\n\n     if (evt->clazz == DFEC_INPUT) {\n          DFBInputEvent *event = &evt->input;\n\n          if (!data->primary.focused && !data->app_focus)\n               event->flags |= DIEF_GLOBAL;\n     }\n\n     return false;\n}\n\nstatic DFBResult\nIDirectFB_CreateInputEventBuffer( IDirectFB                   *thiz,\n                                  DFBInputDeviceCapabilities   caps,\n                                  DFBBoolean                   global,\n                                  IDirectFBEventBuffer       **ret_interface )\n{\n     DFBResult                  ret;\n     CreateEventBuffer_Context  context;\n     IDirectFBEventBuffer      *iface;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBEventBuffer );\n\n     ret = IDirectFBEventBuffer_Construct( iface, global ? input_filter_global : input_filter_local, data );\n     if (ret)\n          return ret;\n\n     context.caps      = caps;\n     context.interface = &iface;\n\n     /* Store the context of the event buffer for input device hotplug support. */\n     eventbuffer_containers_add( &context );\n\n     dfb_input_enumerate_devices( CreateEventBuffer_Callback, &context, caps );\n\n     *ret_interface = iface;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nCreateDataBufferFile( IDirectFB            *thiz,\n                      const char           *filename,\n                      IDirectFBDataBuffer **buffer )\n{\n     DFBResult                ret;\n     DFBDataBufferDescription desc;\n\n     desc.flags = DBDESC_FILE;\n     desc.file  = filename;\n\n     ret = thiz->CreateDataBuffer( thiz, &desc, buffer );\n     if (ret)\n          return ret;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFB_CreateImageProvider( IDirectFB               *thiz,\n                               const char              *filename,\n                               IDirectFBImageProvider **ret_interface )\n{\n     DFBResult               ret;\n     IDirectFBDataBuffer    *buffer;\n     IDirectFBImageProvider *iface;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p, '%s' )\\n\", __FUNCTION__, thiz, filename );\n\n     /* Check arguments. */\n     if (!filename || !ret_interface)\n          return DFB_INVARG;\n\n     /* Create a data buffer. */\n     ret = CreateDataBufferFile( thiz, filename, &buffer );\n     if (ret) {\n          D_DEBUG_AT( DirectFB, \"  -> data buffer creation failed!\\n\" );\n          return ret;\n     }\n\n     /* Create (probing) the image provider. */\n     ret = IDirectFBImageProvider_CreateFromBuffer( buffer, data->core, thiz, &iface );\n\n     /* We don't need it anymore, image provider has its own reference. */\n     buffer->Release( buffer );\n\n     if (ret == DFB_OK)\n          *ret_interface = iface;\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFB_CreateVideoProvider( IDirectFB               *thiz,\n                               const char              *filename,\n                               IDirectFBVideoProvider **ret_interface )\n{\n     DFBResult               ret;\n     IDirectFBDataBuffer    *buffer;\n     IDirectFBVideoProvider *iface;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p, '%s' )\\n\", __FUNCTION__, thiz, filename );\n\n     /* Check arguments. */\n     if (!filename || !ret_interface)\n          return DFB_INVARG;\n\n     /* Create a data buffer. */\n     ret = CreateDataBufferFile( thiz, filename, &buffer );\n     if (ret) {\n          D_DEBUG_AT( DirectFB, \"  -> data buffer creation failed!\\n\" );\n          return ret;\n     }\n\n     /* Create (probing) the video provider. */\n     ret = IDirectFBVideoProvider_CreateFromBuffer( buffer, data->core, thiz, &iface );\n\n     /* We don't need it anymore, video provider has its own reference. */\n     buffer->Release( buffer );\n\n     if (ret == DFB_OK)\n          *ret_interface = iface;\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFB_CreateFont( IDirectFB                 *thiz,\n                      const char                *filename,\n                      const DFBFontDescription  *desc,\n                      IDirectFBFont            **ret_interface )\n{\n     DFBResult            ret;\n     IDirectFBDataBuffer *buffer;\n     IDirectFBFont       *iface;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p, '%s' )\\n\", __FUNCTION__, thiz, filename );\n\n     /* Check arguments. */\n     if (!filename || !desc || !ret_interface)\n          return DFB_INVARG;\n\n     if ((desc->flags & DFDESC_HEIGHT) && desc->height < 1) {\n          D_DEBUG_AT( DirectFB, \"  -> invalid height %d\\n\", desc->height );\n          return DFB_INVARG;\n     }\n\n     if ((desc->flags & DFDESC_WIDTH) && desc->width < 1) {\n          D_DEBUG_AT( DirectFB, \"  -> invalid width %d\\n\", desc->width );\n          return DFB_INVARG;\n     }\n\n     /* Create a data buffer. */\n     ret = CreateDataBufferFile( thiz, filename, &buffer );\n     if (ret) {\n          D_DEBUG_AT( DirectFB, \"  -> data buffer creation failed!\\n\" );\n          return ret;\n     }\n\n     /* Create (probing) the font. */\n     ret = IDirectFBFont_CreateFromBuffer( buffer, data->core, desc, &iface );\n\n     /* We don't need it anymore. */\n     buffer->Release( buffer );\n\n     if (ret == DFB_OK)\n          *ret_interface = iface;\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFB_CreateDataBuffer( IDirectFB                       *thiz,\n                            const DFBDataBufferDescription  *desc,\n                            IDirectFBDataBuffer            **ret_interface )\n{\n     DFBResult            ret;\n     IDirectFBDataBuffer *iface;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     if (!desc) {\n          DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBDataBuffer );\n\n          ret = IDirectFBDataBuffer_Streamed_Construct( iface, data->core, thiz );\n     }\n     else if (desc->flags & DBDESC_FILE) {\n          /* Check for valid filename. */\n          if (!desc->file)\n               return DFB_INVARG;\n\n          DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBDataBuffer );\n\n          ret = IDirectFBDataBuffer_File_Construct( iface, desc->file, data->core, thiz );\n     }\n     else if (desc->flags & DBDESC_MEMORY) {\n          if (!desc->memory.data || !desc->memory.length)\n               return DFB_INVARG;\n\n          DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBDataBuffer );\n\n          ret = IDirectFBDataBuffer_Memory_Construct( iface, desc->memory.data, desc->memory.length, data->core, thiz );\n     }\n     else\n          return DFB_INVARG;\n\n     if (ret == DFB_OK)\n          *ret_interface = iface;\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFB_SetClipboardData( IDirectFB      *thiz,\n                            const char     *mime_type,\n                            const void     *clip_data,\n                            unsigned int    size,\n                            struct timeval *timestamp )\n{\n     struct timeval tv;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!mime_type || !data || !size)\n          return DFB_INVARG;\n\n     if (timestamp)\n          tv = *timestamp;\n     else {\n          long long timestamp_us = direct_clock_get_abs_micros();\n          tv.tv_sec  = timestamp_us / 1000000;\n          tv.tv_usec = timestamp_us % 1000000;\n     }\n\n     return CoreDFB_ClipboardSet( data->core, mime_type, strlen( mime_type ) + 1, clip_data, size,\n                                  tv.tv_sec * 1000000 + tv.tv_usec );\n}\n\nstatic DFBResult\nIDirectFB_GetClipboardData( IDirectFB     *thiz,\n                            char         **ret_mime_type,\n                            void         **ret_clip_data,\n                            unsigned int  *ret_size )\n{\n     DFBResult ret;\n     char      mime_type[MAX_CLIPBOARD_MIME_TYPE_SIZE];\n     u32       mime_type_size;\n     char      clip_data[MAX_CLIPBOARD_DATA_SIZE];\n     u32       size;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_mime_type && !data && !ret_size)\n          return DFB_INVARG;\n\n     ret = CoreDFB_ClipboardGet( data->core, mime_type, &mime_type_size, clip_data, &size );\n     if (ret)\n          return ret;\n\n     *ret_mime_type = D_STRDUP( mime_type );\n     if (!*ret_mime_type)\n          return D_OOM();\n\n     *ret_clip_data = D_MALLOC( size );\n     if (!*ret_clip_data) {\n          free( *ret_mime_type );\n          return D_OOM();\n     }\n\n     direct_memcpy( *ret_clip_data, clip_data, size );\n\n     *ret_size = size;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFB_GetClipboardTimeStamp( IDirectFB      *thiz,\n                                 struct timeval *ret_timestamp )\n{\n     DFBResult ret;\n     u64       ts;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_timestamp)\n          return DFB_INVARG;\n\n     ret = CoreDFB_ClipboardGetTimestamp( data->core, &ts );\n     if (ret)\n          return ret;\n\n     ret_timestamp->tv_sec  = ts / 1000000;\n     ret_timestamp->tv_usec = ts % 1000000;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFB_Suspend( IDirectFB *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return dfb_core_suspend( data->core );\n}\n\nstatic DFBResult\nIDirectFB_Resume( IDirectFB *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return dfb_core_resume( data->core );\n}\n\nstatic DFBResult\nIDirectFB_WaitIdle( IDirectFB *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     CoreDFB_WaitIdle( data->core );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFB_WaitForSync( IDirectFB *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     CoreLayer_WaitVSync( data->layer );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFB_GetInterface( IDirectFB   *thiz,\n                        const char  *type,\n                        const char  *implementation,\n                        void        *arg,\n                        void       **ret_interface )\n{\n     DFBResult             ret;\n     DirectInterfaceFuncs *funcs = NULL;\n     void                 *iface;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p, '%s' )\\n\", __FUNCTION__, thiz, type );\n\n     if (!type || !ret_interface)\n          return DFB_INVARG;\n\n     ret = DirectGetInterface( &funcs, type, implementation, DirectProbeInterface, arg );\n     if (ret)\n          return ret;\n\n     ret = funcs->Allocate( &iface );\n     if (ret)\n          return ret;\n\n     ret = funcs->Construct( iface, arg, data->core );\n\n     if (ret == DFB_OK)\n          *ret_interface = iface;\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFB_GetSurface( IDirectFB         *thiz,\n                      DFBSurfaceID       surface_id,\n                      IDirectFBSurface **ret_interface )\n{\n     DFBResult         ret;\n     CoreSurface      *surface;\n     IDirectFBSurface *iface;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p, %u )\\n\", __FUNCTION__, thiz, surface_id );\n\n     ret = CoreDFB_GetSurface( data->core, surface_id, &surface );\n     if (ret)\n          return ret;\n\n     DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBSurface );\n\n     ret = IDirectFBSurface_Construct( iface, NULL, NULL, NULL, NULL, surface, surface->config.caps, data->core, thiz );\n\n     dfb_surface_unref( surface );\n\n     if (ret == DFB_OK)\n          *ret_interface = iface;\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFB_GetFontSurfaceFormat( IDirectFB             *thiz,\n                                DFBSurfacePixelFormat *ret_fontformat )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_fontformat)\n          return DFB_INVARG;\n\n     *ret_fontformat = dfb_config->font_format;\n\n     return DFB_OK;\n}\n\nstatic void\nLoadBackgroundImage( IDirectFB       *dfb,\n                     CoreWindowStack *stack,\n                     DFBConfigLayer  *conf )\n{\n     DFBResult               ret;\n     DFBSurfaceDescription   desc;\n     IDirectFBImageProvider *provider;\n     IDirectFBSurface       *image;\n     IDirectFBSurface_data  *image_data;\n\n     ret = dfb->CreateImageProvider( dfb, conf->background.filename, &provider );\n     if (ret) {\n          D_DERROR( ret, \"IDirectFB: Failed loading background image '%s'!\\n\", conf->background.filename );\n          return;\n     }\n\n     if (conf->background.mode == DLBM_IMAGE) {\n          desc.flags  = DSDESC_WIDTH | DSDESC_HEIGHT;\n          desc.width  = conf->config.width;\n          desc.height = conf->config.height;\n     }\n     else {\n          provider->GetSurfaceDescription( provider, &desc );\n     }\n\n     desc.flags       |= DSDESC_CAPS | DSDESC_PIXELFORMAT;\n     desc.caps         = DSCAPS_SHARED;\n     desc.pixelformat  = conf->config.pixelformat;\n\n     ret = dfb->CreateSurface( dfb, &desc, &image );\n     if (ret) {\n          D_DERROR( ret, \"IDirectFB: Failed creating surface for background image!\\n\" );\n          provider->Release( provider );\n          return;\n     }\n\n     ret = provider->RenderTo( provider, image, NULL );\n     if (ret) {\n          D_DERROR( ret, \"IDirectFB: Failed loading background image!\\n\" );\n          image->Release( image );\n          provider->Release( provider );\n          return;\n     }\n\n     provider->Release( provider );\n\n     image_data = image->priv;\n\n     CoreWindowStack_BackgroundSetImage( stack, image_data->surface );\n\n     image->Release( image );\n}\n\nstatic DFBResult\nInitLayerPalette( IDirectFB_data  *data,\n                  DFBConfigLayer  *conf,\n                  CoreSurface     *surface,\n                  CorePalette    **ret_palette )\n{\n     DFBResult    ret;\n     CorePalette *palette;\n\n     ret = dfb_palette_create( data->core, 256, surface->config.colorspace, &palette );\n     if (ret) {\n          D_DERROR( ret, \"IDirectFB: Could not create palette!\\n\" );\n          return ret;\n     }\n\n     direct_memcpy( palette->entries, conf->palette, sizeof(DFBColor) * 256 );\n\n     ret = dfb_surface_set_palette( surface, palette );\n     if (ret) {\n          D_DERROR( ret, \"IDirectFB: Could not set palette!\\n\" );\n          dfb_palette_unref( palette );\n          return ret;\n     }\n\n     *ret_palette = palette;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nInitLayers( IDirectFB *thiz )\n{\n     DFBResult ret;\n     int       i;\n     int       num = dfb_layers_num();\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     for (i = 0; i < num; i++) {\n          CoreLayer      *layer = dfb_layer_at_translated( i );\n          DFBConfigLayer *conf  = &dfb_config->layers[i];\n\n          if (conf->init) {\n               CoreLayerContext           *context;\n               CoreWindowStack            *stack;\n               CardCapabilities            caps;\n               DFBDisplayLayerConfigFlags  fail;\n               DFBColorKey                 key;\n\n               ret = CoreLayer_GetPrimaryContext( layer, false, &context );\n               if (ret) {\n                    D_DERROR( ret, \"IDirectFB: Could not get context of layer %d!\\n\", i );\n                    goto error;\n               }\n\n               stack = dfb_layer_context_windowstack( context );\n\n               D_ASSERT( stack != NULL );\n\n               /* Set default desktop configuration. */\n               if (!(conf->config.flags & DLCONF_BUFFERMODE)) {\n                    dfb_gfxcard_get_capabilities( &caps );\n\n                    conf->config.flags      |= DLCONF_BUFFERMODE;\n                    conf->config.buffermode  = (caps.accel & DFXL_BLIT) ? DLBM_BACKVIDEO : DLBM_BACKSYSTEM;\n               }\n\n               if (CoreLayerContext_TestConfiguration( context, &conf->config, &fail )) {\n                    if (fail & (DLCONF_WIDTH | DLCONF_HEIGHT)) {\n                         D_ERROR( \"IDirectFB: Setting desktop resolution to %dx%d failed!\\n\"\n                                  \"  -> Using default resolution\\n\", conf->config.width, conf->config.height );\n\n                         conf->config.flags &= ~(DLCONF_WIDTH | DLCONF_HEIGHT);\n                    }\n\n                    if (fail & DLCONF_PIXELFORMAT) {\n                         D_ERROR( \"IDirectFB: Setting desktop format failed!\\n\"\n                                  \"  -> Using default format\\n\" );\n\n                         conf->config.flags &= ~DLCONF_PIXELFORMAT;\n                    }\n\n                    if (fail & DLCONF_BUFFERMODE) {\n                         D_ERROR( \"IDirectFB: Setting desktop buffer mode failed!\\n\"\n                                  \"  -> No virtual resolution support or not enough memory\\n\"\n                                  \"     Falling back to system back buffer\\n\" );\n\n                         conf->config.buffermode = DLBM_BACKSYSTEM;\n\n                         if (CoreLayerContext_TestConfiguration( context, &conf->config, &fail )) {\n                              D_ERROR( \"IDirectFB: Setting system memory desktop back buffer failed!\\n\"\n                                       \"  -> Using front buffer only mode\\n\" );\n\n                              conf->config.flags &= ~DLCONF_BUFFERMODE;\n                         }\n                    }\n               }\n\n               if (conf->config.flags) {\n                    ret = CoreLayerContext_SetConfiguration( context, &conf->config );\n                    if (ret) {\n                         D_DERROR( ret, \"IDirectFB: Could not set configuration for layer %d!\\n\", i );\n                         dfb_layer_context_unref( context );\n                         goto error;\n                    }\n               }\n\n               ret = dfb_layer_context_get_configuration( context, &conf->config );\n               if (ret)\n                    goto error;\n\n               ret = CoreLayerContext_GetPrimaryRegion( context, true, &data->layers[i].region );\n               if (ret) {\n                    D_DERROR( ret, \"IDirectFB: Could not get primary region of layer %d!\\n\", i );\n                    dfb_layer_context_unref( context );\n                    goto error;\n               }\n\n               ret = dfb_layer_region_get_surface( data->layers[i].region, &data->layers[i].surface );\n               if (ret) {\n                    D_DERROR( ret, \"IDirectFB: Could not get surface of primary region of layer %d!\\n\", i );\n                    dfb_layer_region_unref( data->layers[i].region );\n                    dfb_layer_context_unref( context );\n                    goto error;\n               }\n\n               if (conf->palette_set)\n                    InitLayerPalette( data, conf, data->layers[i].surface, &data->layers[i].palette );\n\n               if (conf->src_key_index >= 0 && conf->src_key_index < 256) {\n                    conf->src_key.r = conf->palette[conf->src_key_index].r;\n                    conf->src_key.g = conf->palette[conf->src_key_index].g;\n                    conf->src_key.b = conf->palette[conf->src_key_index].b;\n               }\n\n               key.r     = conf->src_key.r;\n               key.g     = conf->src_key.g;\n               key.b     = conf->src_key.b;\n               key.index = conf->src_key_index;\n\n               CoreLayerContext_SetSrcColorKey( context, &key );\n\n               switch (conf->background.mode) {\n                    case DLBM_COLOR:\n                         CoreWindowStack_BackgroundSetColor( stack, &conf->background.color );\n                         CoreWindowStack_BackgroundSetColorIndex( stack, conf->background.color_index );\n                         break;\n\n                    case DLBM_IMAGE:\n                    case DLBM_TILE:\n                         LoadBackgroundImage( thiz, stack, conf );\n                         break;\n\n                    default:\n                         break;\n               }\n\n               CoreWindowStack_BackgroundSetMode( stack, conf->background.mode );\n\n               data->layers[i].context = context;\n          }\n\n          data->layers[i].layer = layer;\n     }\n\n     for (i = 0; i < num; i++) {\n          if (data->layers[i].context)\n               dfb_layer_activate_context( data->layers[i].layer, data->layers[i].context );\n     }\n\n     return DFB_OK;\n\nerror:\n     for (i = num - 1; i >= 0; i--) {\n          if (data->layers[i].context) {\n               if (data->layers[i].palette)\n                    dfb_palette_unref( data->layers[i].palette );\n\n               dfb_surface_unref( data->layers[i].surface );\n               dfb_layer_region_unref( data->layers[i].region );\n               dfb_layer_context_unref( data->layers[i].context );\n\n               data->layers[i].context = NULL;\n          }\n     }\n\n     return ret;\n}\n\nstatic void\nInitIDirectFB_Async( void *ctx,\n                     void *ctx2 )\n{\n     DFBResult       ret;\n     IDirectFB      *thiz = ctx;\n     IDirectFB_data *data = ctx2;\n\n     D_DEBUG_AT( DirectFB, \"%s( %p, %p )\\n\", __FUNCTION__, thiz, data );\n\n     ret = CoreLayer_GetPrimaryContext( data->layer, true, &data->context );\n     if (ret) {\n          D_ERROR( \"IDirectFB: Could not get default context of primary layer!\\n\" );\n          return;\n     }\n\n     data->stack = dfb_layer_context_windowstack( data->context );\n\n     if (dfb_core_is_master( data->core )) {\n          ret = InitLayers( thiz );\n          if (ret)\n               return;\n\n          ret = dfb_wm_post_init( data->core );\n          if (ret)\n               D_DERROR( ret, \"IDirectFB: Post initialization of WM failed!\\n\" );\n\n          dfb_core_activate( data->core );\n     }\n\n     direct_mutex_lock( &data->init_lock );\n\n     data->init_done = true;\n\n     direct_waitqueue_broadcast( &data->init_wq );\n\n     direct_mutex_unlock( &data->init_lock );\n}\n\nDFBResult\nIDirectFB_Construct( IDirectFB *thiz )\n{\n     DFBResult ret;\n\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     ret = dfb_core_create( &core_dfb );\n     if (ret) {\n          DIRECT_DEALLOCATE_INTERFACE( thiz );\n          return ret;\n     }\n\n     if (dfb_layers_num() < 1) {\n          D_ERROR( \"IDirectFB: No layers available!\\n\" );\n          dfb_core_destroy( core_dfb, false );\n          DIRECT_DEALLOCATE_INTERFACE( thiz );\n          return DFB_UNSUPPORTED;\n     }\n\n     data->ref   = 1;\n     data->core  = core_dfb;\n     data->level = DFSCL_NORMAL;\n     data->layer = dfb_layer_at_translated( DLID_PRIMARY );\n\n     thiz->AddRef                 = IDirectFB_AddRef;\n     thiz->Release                = IDirectFB_Release;\n     thiz->SetCooperativeLevel    = IDirectFB_SetCooperativeLevel;\n     thiz->SetVideoMode           = IDirectFB_SetVideoMode;\n     thiz->GetDeviceDescription   = IDirectFB_GetDeviceDescription;\n     thiz->EnumVideoModes         = IDirectFB_EnumVideoModes;\n     thiz->CreateSurface          = IDirectFB_CreateSurface;\n     thiz->CreatePalette          = IDirectFB_CreatePalette;\n     thiz->EnumScreens            = IDirectFB_EnumScreens;\n     thiz->GetScreen              = IDirectFB_GetScreen;\n     thiz->EnumDisplayLayers      = IDirectFB_EnumDisplayLayers;\n     thiz->GetDisplayLayer        = IDirectFB_GetDisplayLayer;\n     thiz->EnumInputDevices       = IDirectFB_EnumInputDevices;\n     thiz->GetInputDevice         = IDirectFB_GetInputDevice;\n     thiz->CreateEventBuffer      = IDirectFB_CreateEventBuffer;\n     thiz->CreateInputEventBuffer = IDirectFB_CreateInputEventBuffer;\n     thiz->CreateImageProvider    = IDirectFB_CreateImageProvider;\n     thiz->CreateVideoProvider    = IDirectFB_CreateVideoProvider;\n     thiz->CreateFont             = IDirectFB_CreateFont;\n     thiz->CreateDataBuffer       = IDirectFB_CreateDataBuffer;\n     thiz->SetClipboardData       = IDirectFB_SetClipboardData;\n     thiz->GetClipboardData       = IDirectFB_GetClipboardData;\n     thiz->GetClipboardTimeStamp  = IDirectFB_GetClipboardTimeStamp;\n     thiz->Suspend                = IDirectFB_Suspend;\n     thiz->Resume                 = IDirectFB_Resume;\n     thiz->WaitIdle               = IDirectFB_WaitIdle;\n     thiz->WaitForSync            = IDirectFB_WaitForSync;\n     thiz->GetInterface           = IDirectFB_GetInterface;\n     thiz->GetSurface             = IDirectFB_GetSurface;\n     thiz->GetFontSurfaceFormat   = IDirectFB_GetFontSurfaceFormat;\n\n     direct_mutex_init( &data->init_lock );\n     direct_waitqueue_init( &data->init_wq );\n\n     if (dfb_config->call_nodirect && dfb_core_is_master( data->core ))\n          Core_AsyncCall( InitIDirectFB_Async, thiz, data );\n     else\n          InitIDirectFB_Async( thiz, data );\n\n     return DFB_OK;\n}\n\nDFBResult\nIDirectFB_WaitInitialised( IDirectFB *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     direct_mutex_lock( &data->init_lock );\n\n     while (!data->init_done)\n          direct_waitqueue_wait( &data->init_wq, &data->init_lock );\n\n     direct_mutex_unlock( &data->init_lock );\n\n     return DFB_OK;\n}\n\nDFBResult\nIDirectFB_SetAppFocus( IDirectFB  *thiz,\n                       DFBBoolean  focused )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFB )\n\n     D_DEBUG_AT( DirectFB, \"%s( %p, %s )\\n\", __FUNCTION__, thiz, focused ? \"true\" : \"false\" );\n\n     data->app_focus = focused;\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic DFBEnumerationResult\nEnumScreens_Callback( CoreScreen *screen,\n                      void       *ctx )\n{\n     DFBScreenDescription  desc;\n     DFBScreenID           id;\n     EnumScreens_Context  *context = ctx;\n\n     id = dfb_screen_id_translated( screen );\n\n     if (dfb_config->primary_only && id != DSCID_PRIMARY)\n          return DFENUM_OK;\n\n     dfb_screen_get_info( screen, NULL, &desc );\n\n     return context->callback( id, desc, context->callback_ctx );\n}\n\nstatic DFBEnumerationResult\nGetScreen_Callback( CoreScreen *screen,\n                    void       *ctx )\n{\n     GetScreen_Context *context = ctx;\n\n     if (dfb_screen_id_translated( screen ) != context->id)\n          return DFENUM_OK;\n\n     DIRECT_ALLOCATE_INTERFACE( *context->interface, IDirectFBScreen );\n\n     context->ret = IDirectFBScreen_Construct( *context->interface, screen );\n\n     return DFENUM_CANCEL;\n}\n\nstatic DFBEnumerationResult\nEnumDisplayLayers_Callback( CoreLayer *layer,\n                            void      *ctx )\n{\n     DFBDisplayLayerDescription  desc;\n     DFBDisplayLayerID           id;\n     EnumDisplayLayers_Context  *context = ctx;\n\n     id = dfb_layer_id_translated( layer );\n\n     if (dfb_config->primary_only && id != DLID_PRIMARY)\n          return DFENUM_OK;\n\n     dfb_layer_get_description( layer, &desc );\n\n     return context->callback( id, desc, context->callback_ctx );\n}\n\nstatic DFBEnumerationResult\nGetDisplayLayer_Callback( CoreLayer *layer,\n                          void      *ctx )\n{\n     GetDisplayLayer_Context *context = ctx;\n\n     if (dfb_layer_id_translated( layer ) != context->id)\n          return DFENUM_OK;\n\n     DIRECT_ALLOCATE_INTERFACE( *context->interface, IDirectFBDisplayLayer );\n\n     context->ret = IDirectFBDisplayLayer_Construct( *context->interface, layer, context->core, context->idirectfb );\n\n     return DFENUM_CANCEL;\n}\n\nstatic DFBEnumerationResult\nEnumInputDevices_Callback( CoreInputDevice *device,\n                           void            *ctx )\n{\n     DFBInputDeviceDescription  desc;\n     EnumInputDevices_Context  *context = ctx;\n\n     dfb_input_device_description( device, &desc );\n\n     return context->callback( dfb_input_device_id( device ), desc, context->callback_ctx );\n}\n\nstatic DFBEnumerationResult\nGetInputDevice_Callback( CoreInputDevice *device,\n                         void            *ctx )\n{\n     GetInputDevice_Context *context = ctx;\n\n     if (dfb_input_device_id( device ) != context->id)\n          return DFENUM_OK;\n\n     DIRECT_ALLOCATE_INTERFACE( *context->interface, IDirectFBInputDevice );\n\n     context->ret = IDirectFBInputDevice_Construct( *context->interface, device );\n\n     return DFENUM_CANCEL;\n}\n\nstatic DFBEnumerationResult\nCreateEventBuffer_Callback( CoreInputDevice *device,\n                            void            *ctx )\n{\n     DFBInputDeviceDescription  desc;\n     CreateEventBuffer_Context *context = ctx;\n\n     dfb_input_device_description( device, &desc );\n\n     IDirectFBEventBuffer_AttachInputDevice( *context->interface, device );\n\n     return DFENUM_OK;\n}\n"
  },
  {
    "path": "src/idirectfb.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __IDIRECTFB_H__\n#define __IDIRECTFB_H__\n\n#include <core/coretypes.h>\n\nvoid eventbuffer_containers_remove( IDirectFBEventBuffer *thiz );\n\n/*\n * initializes interface struct and private data\n */\nDFBResult IDirectFB_Construct      ( IDirectFB  *thiz );\n\nDFBResult IDirectFB_WaitInitialised( IDirectFB  *thiz );\n\nDFBResult IDirectFB_SetAppFocus    ( IDirectFB  *thiz,\n                                     DFBBoolean  focused );\n\n#endif\n"
  },
  {
    "path": "src/init.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core.h>\n#include <directfb_result.h>\n\n/**********************************************************************************************************************/\n\ntypedef void (*Func)( void );\n\nstatic Func init_funcs[] = {\n      DFBResult__init,\n      Core_TLS__init,\n};\n\nstatic Func deinit_funcs[] = {\n      Core_TLS__deinit,\n      DFBResult__deinit,\n};\n\n/**********************************************************************************************************************/\n\n__dfb_constructor__\nvoid\n__DFB_init_all( void )\n{\n     size_t i;\n\n     for (i = 0; i < D_ARRAY_SIZE(init_funcs); i++)\n          init_funcs[i]();\n}\n\n__dfb_destructor__\nvoid\n__DFB_deinit_all( void )\n{\n     size_t i;\n\n     dfb_config_deinit();\n\n     for (i = 0; i < D_ARRAY_SIZE(deinit_funcs); i++)\n          deinit_funcs[i]();\n}\n"
  },
  {
    "path": "src/input/idirectfbeventbuffer.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreWindow.h>\n#include <core/input.h>\n#include <core/surface.h>\n#include <core/windows.h>\n#include <direct/memcpy.h>\n#include <direct/thread.h>\n#include <directfb_util.h>\n#include <idirectfb.h>\n#include <input/idirectfbeventbuffer.h>\n#include <misc/conf.h>\n\nD_DEBUG_DOMAIN( EventBuffer,         \"IDirectFBEventBuffer\",         \"IDirectFBEventBuffer Interface\" );\nD_DEBUG_DOMAIN( EventBuffer_Feed,    \"IDirectFBEventBuffer/Feed\",    \"IDirectFBEventBuffer Interface Feed\" );\nD_DEBUG_DOMAIN( EventBuffer_Surface, \"IDirectFBEventBuffer/Surface\", \"IDirectFBEventBuffer Interface Surface\" );\n\n/**********************************************************************************************************************/\n\n/*\n * private data struct of IDirectFBEventBuffer\n */\ntypedef struct {\n     int                        ref;            /* reference counter */\n\n     EventBufferFilterCallback  filter;         /* input filter callback */\n     void                      *filter_ctx;     /* context passed as argument of the filter callback */\n\n     DirectLink                *devices;        /* attached devices */\n     DirectLink                *windows;        /* attached windows */\n     DirectLink                *surfaces;       /* attached surfaces */\n\n     DirectLink                *events;         /* linked list containing events */\n\n     DirectMutex                events_mutex;   /* mutex lock for accessing the event queue */\n\n     DirectWaitQueue            wait_condition; /* condition used for idle wait */\n\n     bool                       pipe;           /* pipe mode */\n     int                        pipe_fds[2];    /* read & write file descriptors */\n     DirectThread              *pipe_thread;    /* thread feeding the pipe */\n\n     DFBEventBufferStats        stats;\n     bool                       stats_enabled;\n} IDirectFBEventBuffer_data;\n\ntypedef struct {\n     DirectLink   link;\n     DFBEvent     evt;\n} EventBufferItem;\n\nstatic void IDirectFBEventBuffer_AddItem( IDirectFBEventBuffer_data *data, EventBufferItem *item );\n\ntypedef struct {\n     DirectLink       link;\n\n     CoreInputDevice *device;\n     Reaction         reaction;\n\n     DFBInputDeviceDescription desc;\n} AttachedDevice;\n\ntypedef struct {\n     DirectLink  link;\n\n     CoreWindow *window;\n     Reaction    reaction;\n} AttachedWindow;\n\ntypedef struct {\n     DirectLink   link;\n\n     CoreSurface *surface;\n     Reaction     reaction;\n} AttachedSurface;\n\nstatic ReactionResult IDirectFBEventBuffer_InputReact  ( const void *msg_data, void *ctx );\nstatic ReactionResult IDirectFBEventBuffer_WindowReact ( const void *msg_data, void *ctx );\nstatic ReactionResult IDirectFBEventBuffer_SurfaceReact( const void *msg_data, void *ctx );\n\nstatic void *IDirectFBEventBuffer_Feed( DirectThread *thread, void *arg );\n\nstatic void CollectEventStatistics( DFBEventBufferStats *stats, const DFBEvent *event, int incdec );\n\n/**********************************************************************************************************************/\n\nstatic void\ndump_event( const DFBEvent *event )\n{\n     switch (event->clazz) {\n          case DFEC_INPUT:\n               D_DEBUG_AT( EventBuffer, \"  -> INPUT %u (type 0x%08x)\\n\", event->input.device_id, event->input.type );\n               break;\n\n          case DFEC_WINDOW:\n               D_DEBUG_AT( EventBuffer, \"  -> WINDOW %u (type 0x%08x)\\n\", event->window.window_id, event->window.type );\n               break;\n\n          case DFEC_USER:\n               D_DEBUG_AT( EventBuffer, \"  -> USER (type 0x%08x, data %p)\\n\", event->user.type, event->user.data );\n               break;\n\n          case DFEC_VIDEOPROVIDER:\n               D_DEBUG_AT( EventBuffer, \"  -> VIDEOPROVIDER (type 0x%08x, data_type 0x%08x)\\n\",\n                           event->videoprovider.type, event->videoprovider.data_type );\n               break;\n\n          case DFEC_SURFACE:\n               D_DEBUG_AT( EventBuffer, \"  -> SURFACE %u (type 0x%08x)\\n\", event->surface.surface_id,\n                           event->surface.type );\n               break;\n\n          case DFEC_UNIVERSAL:\n               D_DEBUG_AT( EventBuffer, \"  -> UNIVERSAL (size %u)\\n\", event->universal.size );\n               break;\n\n          default:\n               D_DEBUG_AT( EventBuffer, \"  -> UNKNOWN EVENT CLASS 0x%08x\\n\", event->clazz );\n               break;\n     }\n}\n\nstatic void\nIDirectFBEventBuffer_Destruct( IDirectFBEventBuffer *thiz )\n{\n     IDirectFBEventBuffer_data *data = thiz->priv;\n     AttachedDevice            *device;\n     AttachedWindow            *window;\n     AttachedSurface           *surface;\n     EventBufferItem           *item;\n     DirectLink                *next;\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     /* Remove the event buffer from the containers linked list. */\n     eventbuffer_containers_remove( thiz );\n\n     direct_mutex_lock( &data->events_mutex );\n\n     if (data->pipe) {\n          data->pipe = false;\n\n          direct_waitqueue_broadcast( &data->wait_condition );\n\n          direct_mutex_unlock( &data->events_mutex );\n\n          direct_thread_join( data->pipe_thread );\n          direct_thread_destroy( data->pipe_thread );\n\n          direct_mutex_lock( &data->events_mutex );\n\n          close( data->pipe_fds[0] );\n          close( data->pipe_fds[1] );\n     }\n\n     direct_mutex_unlock( &data->events_mutex );\n\n     direct_list_foreach_safe (surface, next, data->surfaces) {\n          dfb_surface_detach( surface->surface, &surface->reaction );\n\n          dfb_surface_unref( surface->surface );\n\n          D_FREE( surface );\n     }\n\n     direct_list_foreach_safe (device, next, data->devices) {\n          dfb_input_detach( device->device, &device->reaction );\n\n          D_FREE( device );\n     }\n\n     direct_list_foreach_safe (window, next, data->windows) {\n          if (window->window)\n               dfb_window_detach( window->window, &window->reaction );\n     }\n\n     direct_list_foreach_safe (window, next, data->windows) {\n          if (window->window)\n               dfb_window_unref( window->window );\n\n          D_FREE( window );\n     }\n\n     direct_mutex_lock( &data->events_mutex );\n\n     direct_list_foreach_safe (item, next, data->events) {\n          D_FREE( item );\n     }\n\n     direct_waitqueue_deinit( &data->wait_condition );\n     direct_mutex_deinit( &data->events_mutex );\n\n     DIRECT_DEALLOCATE_INTERFACE( thiz );\n}\n\nstatic DirectResult\nIDirectFBEventBuffer_AddRef( IDirectFBEventBuffer *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBEventBuffer )\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref++;\n\n     return DFB_OK;\n}\n\nstatic DirectResult\nIDirectFBEventBuffer_Release( IDirectFBEventBuffer *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBEventBuffer )\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->ref == 0)\n          IDirectFBEventBuffer_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBEventBuffer_Reset( IDirectFBEventBuffer *thiz )\n{\n     EventBufferItem *item, *next;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBEventBuffer )\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->pipe)\n          return DFB_UNSUPPORTED;\n\n     direct_mutex_lock( &data->events_mutex );\n\n     direct_list_foreach_safe (item, next, data->events) {\n          D_FREE( item );\n     }\n\n     data->events = NULL;\n\n     direct_mutex_unlock( &data->events_mutex );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBEventBuffer_WaitForEvent( IDirectFBEventBuffer *thiz )\n{\n     DFBResult ret = DFB_OK;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBEventBuffer )\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->pipe)\n          return DFB_UNSUPPORTED;\n\n     direct_mutex_lock( &data->events_mutex );\n\n     if (!data->events)\n          direct_waitqueue_wait( &data->wait_condition, &data->events_mutex );\n\n     if (!data->events)\n          ret = DFB_INTERRUPTED;\n\n     direct_mutex_unlock( &data->events_mutex );\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBEventBuffer_WaitForEventWithTimeout( IDirectFBEventBuffer *thiz,\n                                              unsigned int          seconds,\n                                              unsigned int          milli_seconds )\n{\n     DirectResult ret    = DR_OK;\n     int          locked = 0;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBEventBuffer )\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p, %u, %u )\\n\", __FUNCTION__, thiz, seconds, milli_seconds );\n\n     if (data->pipe)\n          return DFB_UNSUPPORTED;\n\n     if (direct_mutex_trylock( &data->events_mutex ) == 0) {\n          if (data->events) {\n               direct_mutex_unlock ( &data->events_mutex );\n               return ret;\n          }\n\n          locked = 1;\n     }\n\n     if (!locked)\n          direct_mutex_lock( &data->events_mutex );\n\n     if (!data->events) {\n          ret = direct_waitqueue_wait_timeout( &data->wait_condition, &data->events_mutex,\n                                               seconds * 1000000 + milli_seconds * 1000 );\n          if (ret != DR_TIMEOUT && !data->events)\n               ret = DFB_INTERRUPTED;\n     }\n\n     direct_mutex_unlock( &data->events_mutex );\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBEventBuffer_GetEvent( IDirectFBEventBuffer *thiz,\n                               DFBEvent             *ret_event )\n{\n     EventBufferItem *item;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBEventBuffer )\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p, %p )\\n\", __FUNCTION__, thiz, ret_event );\n\n     if (data->pipe) {\n          D_DEBUG_AT( EventBuffer, \"  -> pipe mode, returning UNSUPPORTED\\n\" );\n          return DFB_UNSUPPORTED;\n     }\n\n     direct_mutex_lock( &data->events_mutex );\n\n     if (!data->events) {\n          D_DEBUG_AT( EventBuffer, \"  -> no events, returning BUFFEREMPTY\\n\" );\n          direct_mutex_unlock( &data->events_mutex );\n          return DFB_BUFFEREMPTY;\n     }\n\n     item = (EventBufferItem*) data->events;\n\n     switch (item->evt.clazz) {\n          case DFEC_INPUT:\n               ret_event->input = item->evt.input;\n               break;\n\n          case DFEC_WINDOW:\n               ret_event->window = item->evt.window;\n               break;\n\n          case DFEC_USER:\n               ret_event->user = item->evt.user;\n               break;\n\n          case DFEC_VIDEOPROVIDER:\n               ret_event->videoprovider = item->evt.videoprovider;\n               break;\n\n          case DFEC_UNIVERSAL:\n               direct_memcpy( ret_event, &item->evt, item->evt.universal.size );\n               break;\n\n          case DFEC_SURFACE:\n               ret_event->surface = item->evt.surface;\n               break;\n\n          default:\n               D_BUG( \"unknown event class\" );\n     }\n\n     if (data->stats_enabled)\n          CollectEventStatistics( &data->stats, &item->evt, -1 );\n\n     direct_list_remove( &data->events, &item->link );\n\n     D_FREE( item );\n\n     direct_mutex_unlock( &data->events_mutex );\n\n     dump_event( ret_event );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBEventBuffer_PeekEvent( IDirectFBEventBuffer *thiz,\n                                DFBEvent             *ret_event )\n{\n     EventBufferItem *item;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBEventBuffer )\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p, %p )\\n\", __FUNCTION__, thiz, ret_event );\n\n     if (data->pipe)\n          return DFB_UNSUPPORTED;\n\n     direct_mutex_lock( &data->events_mutex );\n\n     if (!data->events) {\n          direct_mutex_unlock( &data->events_mutex );\n          return DFB_BUFFEREMPTY;\n     }\n\n     item = (EventBufferItem*) data->events;\n\n     switch (item->evt.clazz) {\n          case DFEC_INPUT:\n               ret_event->input = item->evt.input;\n               break;\n\n          case DFEC_WINDOW:\n               ret_event->window = item->evt.window;\n               break;\n\n          case DFEC_USER:\n               ret_event->user = item->evt.user;\n               break;\n\n          case DFEC_VIDEOPROVIDER:\n               ret_event->videoprovider = item->evt.videoprovider;\n               break;\n\n          case DFEC_UNIVERSAL:\n               direct_memcpy( ret_event, &item->evt, item->evt.universal.size );\n               break;\n\n          case DFEC_SURFACE:\n               ret_event->surface = item->evt.surface;\n               break;\n\n          default:\n               D_BUG( \"unknown event class\" );\n     }\n\n     direct_mutex_unlock( &data->events_mutex );\n\n     dump_event( ret_event );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBEventBuffer_HasEvent( IDirectFBEventBuffer *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBEventBuffer )\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p ) <- events %p, pipe %d\\n\", __FUNCTION__, thiz, data->events, data->pipe );\n\n     if (data->pipe)\n          return DFB_UNSUPPORTED;\n\n     return (data->events ? DFB_OK : DFB_BUFFEREMPTY);\n}\n\nstatic DFBResult\nIDirectFBEventBuffer_PostEvent( IDirectFBEventBuffer *thiz,\n                                const DFBEvent       *event )\n{\n     EventBufferItem *item;\n     int              size;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBEventBuffer )\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p, %p [class %u, type %u, data %p] )\\n\", __FUNCTION__,\n                 thiz, event, event->clazz, event->user.type, event->user.data );\n\n     dump_event( event );\n\n     switch (event->clazz) {\n          case DFEC_INPUT:\n          case DFEC_WINDOW:\n          case DFEC_USER:\n          case DFEC_VIDEOPROVIDER:\n          case DFEC_SURFACE:\n               size = sizeof(EventBufferItem);\n               break;\n\n          case DFEC_UNIVERSAL:\n               size = event->universal.size;\n               if (size < sizeof(DFBUniversalEvent))\n                    return DFB_INVARG;\n               /* We must not exceed the union for the generic code (reading DFBEvent) and to support pipe mode where\n                  each written block must have a fixed size. */\n               if (size > sizeof(DFBEvent))\n                    return DFB_INVARG;\n               size += sizeof(DirectLink);\n               break;\n\n          default:\n               return DFB_INVARG;\n     }\n\n     item = D_CALLOC( 1, size );\n     if (!item)\n          return D_OOM();\n\n     switch (event->clazz) {\n          case DFEC_INPUT:\n               item->evt.input = event->input;\n               break;\n\n          case DFEC_WINDOW:\n               item->evt.window = event->window;\n               break;\n\n          case DFEC_USER:\n               item->evt.user = event->user;\n               break;\n\n          case DFEC_VIDEOPROVIDER:\n               item->evt.videoprovider = event->videoprovider;\n               break;\n\n          case DFEC_UNIVERSAL:\n               direct_memcpy( &item->evt, event, event->universal.size );\n               break;\n\n          case DFEC_SURFACE:\n               item->evt.surface = event->surface;\n               break;\n\n          default:\n               D_BUG( \"unexpected event class\" );\n     }\n\n     IDirectFBEventBuffer_AddItem( data, item );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBEventBuffer_WakeUp( IDirectFBEventBuffer *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBEventBuffer )\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->pipe)\n          return DFB_UNSUPPORTED;\n\n     direct_waitqueue_broadcast( &data->wait_condition );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBEventBuffer_CreateFileDescriptor( IDirectFBEventBuffer *thiz,\n                                           int                  *ret_fd )\n{\n     DirectResult ret;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBEventBuffer )\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     /* Check arguments. */\n     if (!ret_fd)\n          return DFB_INVARG;\n\n     /* Lock the event queue. */\n     direct_mutex_lock( &data->events_mutex );\n\n     /* Already in pipe mode. */\n     if (data->pipe) {\n          direct_mutex_unlock( &data->events_mutex );\n          return DFB_BUSY;\n     }\n\n     /* Create the file descriptor(s). */\n#if DIRECT_BUILD_NETWORK\n     ret = socketpair( PF_LOCAL, SOCK_STREAM, 0, data->pipe_fds );\n#else /* DIRECT_BUILD_NETWORK */\n     ret = pipe( data->pipe_fds );\n#endif /* DIRECT_BUILD_NETWORK */\n     if (ret) {\n          direct_mutex_unlock( &data->events_mutex );\n          return ret;\n     }\n\n     D_DEBUG_AT( EventBuffer, \"  -> entering pipe mode\\n\" );\n\n     /* Enter pipe mode. */\n     data->pipe = true;\n\n     /* Signal any waiting processes. */\n     direct_waitqueue_broadcast( &data->wait_condition );\n\n     /* Create the feeding thread. */\n     data->pipe_thread = direct_thread_create( DTT_MESSAGING, IDirectFBEventBuffer_Feed, data, \"EventBuffer Feed\" );\n\n     /* Unlock the event queue. */\n     direct_mutex_unlock( &data->events_mutex );\n\n     /* Return the file descriptor for reading. */\n     *ret_fd = data->pipe_fds[0];\n\n     D_DEBUG_AT( EventBuffer, \"  -> fd %d/%d\\n\", data->pipe_fds[0], data->pipe_fds[1] );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBEventBuffer_EnableStatistics( IDirectFBEventBuffer *thiz,\n                                       DFBBoolean            enable )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBEventBuffer )\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p, %sable )\\n\", __FUNCTION__, thiz, enable ? \"en\" : \"dis\" );\n\n     /* Lock the event queue. */\n     direct_mutex_lock( &data->events_mutex );\n\n     /* Already enabled. */\n     if (data->stats_enabled == enable) {\n          direct_mutex_unlock( &data->events_mutex );\n          return DFB_OK;\n     }\n\n     if (enable) {\n          EventBufferItem *item;\n\n          /* Collect statistics for events already in the queue. */\n          direct_list_foreach (item, data->events) {\n               CollectEventStatistics( &data->stats, &item->evt, 1 );\n          }\n     }\n     else {\n          /* Clear statistics. */\n          memset( &data->stats, 0, sizeof(DFBEventBufferStats) );\n     }\n\n     /* Remember state. */\n     data->stats_enabled = enable;\n\n     /* Unlock the event queue. */\n     direct_mutex_unlock( &data->events_mutex );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBEventBuffer_GetStatistics( IDirectFBEventBuffer *thiz,\n                                    DFBEventBufferStats  *ret_stats )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBEventBuffer )\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p, %p )\\n\", __FUNCTION__, thiz, ret_stats );\n\n     if (!ret_stats)\n          return DFB_INVARG;\n\n     /* Lock the event queue. */\n     direct_mutex_lock( &data->events_mutex );\n\n     /* Not enabled. */\n     if (!data->stats_enabled) {\n          direct_mutex_unlock( &data->events_mutex );\n          return DFB_UNSUPPORTED;\n     }\n\n     /* Return current stats. */\n     *ret_stats = data->stats;\n\n     /* Unlock the event queue. */\n     direct_mutex_unlock( &data->events_mutex );\n\n     return DFB_OK;\n}\n\nDFBResult\nIDirectFBEventBuffer_Construct( IDirectFBEventBuffer      *thiz,\n                                EventBufferFilterCallback  filter,\n                                void                      *filter_ctx )\n{\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBEventBuffer )\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p, %p, %p )\\n\", __FUNCTION__, thiz, filter, filter_ctx );\n\n     data->ref        = 1;\n     data->filter     = filter;\n     data->filter_ctx = filter_ctx;\n\n     direct_mutex_init( &data->events_mutex );\n     direct_waitqueue_init( &data->wait_condition );\n\n     thiz->AddRef                  = IDirectFBEventBuffer_AddRef;\n     thiz->Release                 = IDirectFBEventBuffer_Release;\n     thiz->Reset                   = IDirectFBEventBuffer_Reset;\n     thiz->WaitForEvent            = IDirectFBEventBuffer_WaitForEvent;\n     thiz->WaitForEventWithTimeout = IDirectFBEventBuffer_WaitForEventWithTimeout;\n     thiz->GetEvent                = IDirectFBEventBuffer_GetEvent;\n     thiz->PeekEvent               = IDirectFBEventBuffer_PeekEvent;\n     thiz->HasEvent                = IDirectFBEventBuffer_HasEvent;\n     thiz->PostEvent               = IDirectFBEventBuffer_PostEvent;\n     thiz->WakeUp                  = IDirectFBEventBuffer_WakeUp;\n     thiz->CreateFileDescriptor    = IDirectFBEventBuffer_CreateFileDescriptor;\n     thiz->EnableStatistics        = IDirectFBEventBuffer_EnableStatistics;\n     thiz->GetStatistics           = IDirectFBEventBuffer_GetStatistics;\n\n     return DFB_OK;\n}\n\nDFBResult\nIDirectFBEventBuffer_AttachInputDevice( IDirectFBEventBuffer *thiz,\n                                        CoreInputDevice      *device )\n{\n     AttachedDevice            *attached;\n     DFBInputDeviceDescription  desc;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBEventBuffer )\n\n     D_ASSERT( device != NULL );\n\n     dfb_input_device_description( device, &desc );\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p, %p [%02u - %s] )\\n\", __FUNCTION__, thiz, device, dfb_input_device_id( device ),\n                 desc.name );\n\n     attached = D_CALLOC( 1, sizeof(AttachedDevice) );\n\n     attached->device = device;\n     attached->desc   = desc;\n\n     direct_list_prepend( &data->devices, &attached->link );\n\n     dfb_input_attach( device, IDirectFBEventBuffer_InputReact, data, &attached->reaction );\n\n     return DFB_OK;\n}\n\nDFBResult\nIDirectFBEventBuffer_DetachInputDevice( IDirectFBEventBuffer *thiz,\n                                        CoreInputDevice      *device )\n{\n     AttachedDevice *attached, *next;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBEventBuffer )\n\n     D_ASSERT( device != NULL );\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p, %p [%02u] )\\n\", __FUNCTION__, thiz, device, dfb_input_device_id( device ) );\n\n     direct_list_foreach_safe (attached, next, data->devices) {\n          if (attached->device == device) {\n               direct_list_remove( &data->devices, &attached->link );\n\n               dfb_input_detach( attached->device, &attached->reaction );\n\n               D_FREE( attached );\n\n               return DFB_OK;\n          }\n     }\n\n     return DFB_ITEMNOTFOUND;\n}\n\nDFBResult\nIDirectFBEventBuffer_AttachWindow( IDirectFBEventBuffer *thiz,\n                                   CoreWindow           *window )\n{\n     AttachedWindow *attached;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBEventBuffer )\n\n     D_ASSERT( window != NULL );\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p, %p [%02u - %4d,%4d-%4dx%4d] )\\n\", __FUNCTION__, thiz, window, window->id,\n                 window->config.bounds.x, window->config.bounds.y, window->config.bounds.w, window->config.bounds.h );\n\n     attached = D_CALLOC( 1, sizeof(AttachedWindow) );\n\n     attached->window = window;\n\n     dfb_window_ref( window );\n\n     direct_list_prepend( &data->windows, &attached->link );\n\n     dfb_window_attach( window, IDirectFBEventBuffer_WindowReact, data, &attached->reaction );\n\n     CoreWindow_AllowFocus( window );\n\n     return DFB_OK;\n}\n\nDFBResult\nIDirectFBEventBuffer_DetachWindow( IDirectFBEventBuffer *thiz,\n                                   CoreWindow           *window )\n{\n     AttachedWindow *attached, *next;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBEventBuffer )\n\n     D_ASSERT( window != NULL );\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p, %p [%02u - %4d,%4d-%4dx%4d] )\\n\", __FUNCTION__, thiz, window, window->id,\n                 window->config.bounds.x, window->config.bounds.y, window->config.bounds.w, window->config.bounds.h );\n\n     direct_list_foreach_safe (attached, next, data->windows) {\n          if (!attached->window || attached->window == window) {\n               direct_list_remove( &data->windows, &attached->link );\n\n               if (attached->window) {\n                    dfb_window_detach( attached->window, &attached->reaction );\n                    dfb_window_unref( attached->window );\n               }\n\n               D_FREE( attached );\n          }\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nIDirectFBEventBuffer_AttachSurface( IDirectFBEventBuffer *thiz,\n                                    CoreSurface          *surface )\n{\n     AttachedSurface *attached;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBEventBuffer )\n\n     D_ASSERT( surface != NULL );\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p, %p [%02u - %dx%d] )\\n\", __FUNCTION__, thiz, surface, surface->object.id,\n                 surface->config.size.w, surface->config.size.h );\n\n     attached = D_CALLOC( 1, sizeof(AttachedSurface) );\n\n     attached->surface = surface;\n\n     dfb_surface_ref( surface );\n\n     direct_list_prepend( &data->surfaces, &attached->link );\n\n     dfb_surface_attach_channel( surface, CSCH_EVENT, IDirectFBEventBuffer_SurfaceReact, data, &attached->reaction );\n\n     D_DEBUG_AT( EventBuffer, \"  -> flip count %u\\n\", surface->flips );\n\n     if (surface->flips > 0 || !(surface->config.caps & DSCAPS_FLIPPING)) {\n          EventBufferItem *item;\n\n          item = D_CALLOC( 1, sizeof(EventBufferItem) );\n          if (!item)\n               return D_OOM();\n          else {\n               item->evt.surface.clazz        = DFEC_SURFACE;\n               item->evt.surface.type         = DSEVT_UPDATE;\n               item->evt.surface.surface_id   = surface->object.id;\n               item->evt.surface.update.x1    = 0;\n               item->evt.surface.update.y1    = 0;\n               item->evt.surface.update.x2    = surface->config.size.w - 1;\n               item->evt.surface.update.y2    = surface->config.size.h - 1;\n               item->evt.surface.update_right = item->evt.surface.update;\n               item->evt.surface.flip_count   = surface->flips;\n               item->evt.surface.time_stamp   = surface->last_frame_time;\n\n               IDirectFBEventBuffer_AddItem( data, item );\n          }\n     }\n\n     return DFB_OK;\n}\n\nDFBResult\nIDirectFBEventBuffer_DetachSurface( IDirectFBEventBuffer *thiz,\n                                    CoreSurface          *surface )\n{\n     AttachedSurface *attached, *next;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBEventBuffer )\n\n     D_ASSERT( surface != NULL );\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p, %p [%02u - %dx%d] )\\n\", __FUNCTION__, thiz, surface, surface->object.id,\n                 surface->config.size.w, surface->config.size.h );\n\n     direct_list_foreach_safe (attached, next, data->surfaces) {\n          if (!attached->surface || attached->surface == surface) {\n               direct_list_remove( &data->surfaces, &attached->link );\n\n               if (attached->surface) {\n                    dfb_surface_detach( attached->surface, &attached->reaction );\n                    dfb_surface_unref( attached->surface );\n               }\n\n               D_FREE( attached );\n          }\n     }\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\n/*\n * Adds an event to the event queue.\n */\nstatic void\nIDirectFBEventBuffer_AddItem( IDirectFBEventBuffer_data *data,\n                              EventBufferItem           *item )\n{\n     if (data->filter && data->filter( &item->evt, data->filter_ctx )) {\n          D_FREE( item );\n          return;\n     }\n\n     direct_mutex_lock( &data->events_mutex );\n\n     if (data->stats_enabled)\n          CollectEventStatistics( &data->stats, &item->evt, 1 );\n\n     direct_list_append( &data->events, &item->link );\n\n     direct_waitqueue_broadcast( &data->wait_condition );\n\n     direct_mutex_unlock( &data->events_mutex );\n}\n\nstatic ReactionResult\nIDirectFBEventBuffer_InputReact( const void *msg_data,\n                                 void       *ctx )\n{\n     const DFBInputEvent       *evt  = msg_data;\n     IDirectFBEventBuffer_data *data = ctx;\n     EventBufferItem           *item;\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p, %p ) <- type %06x\\n\", __FUNCTION__, evt, data, evt->type );\n\n     if (dfb_config->discard_repeat_events && (evt->flags & DIEF_REPEAT)) {\n          D_DEBUG_AT( EventBuffer, \"  -> discarding repeat event!\\n\" );\n          return DFB_OK;\n     }\n\n     item = D_CALLOC( 1, sizeof(EventBufferItem) );\n\n     item->evt.input = *evt;\n     item->evt.clazz = DFEC_INPUT;\n\n     IDirectFBEventBuffer_AddItem( data, item );\n\n     return RS_OK;\n}\n\nstatic ReactionResult\nIDirectFBEventBuffer_WindowReact( const void *msg_data,\n                                  void       *ctx )\n{\n     const DFBWindowEvent      *evt  = msg_data;\n     IDirectFBEventBuffer_data *data = ctx;\n     EventBufferItem           *item;\n\n     D_DEBUG_AT( EventBuffer, \"%s( %p, %p ) <- type %06x\\n\", __FUNCTION__, evt, data, evt->type );\n\n     if (dfb_config->discard_repeat_events && (evt->flags & DWEF_REPEAT)) {\n          D_DEBUG_AT( EventBuffer, \"  -> discarding repeat event!\\n\" );\n          return DFB_OK;\n     }\n\n     item = D_CALLOC( 1, sizeof(EventBufferItem) );\n\n     item->evt.window = *evt;\n     item->evt.clazz  = DFEC_WINDOW;\n\n     IDirectFBEventBuffer_AddItem( data, item );\n\n     if (evt->type == DWET_DESTROYED) {\n          AttachedWindow *window;\n\n          direct_list_foreach (window, data->windows) {\n               if (!window->window)\n                    continue;\n\n               if (window->window->id == evt->window_id) {\n                    dfb_window_unref( window->window );\n                    window->window = NULL;\n               }\n          }\n\n          return RS_REMOVE;\n     }\n\n     return RS_OK;\n}\n\nstatic ReactionResult\nIDirectFBEventBuffer_SurfaceReact( const void *msg_data,\n                                   void       *ctx )\n{\n     const DFBSurfaceEvent     *evt  = msg_data;\n     IDirectFBEventBuffer_data *data = ctx;\n     EventBufferItem           *item;\n\n     D_DEBUG_AT( EventBuffer_Surface, \"%s( %p, %p ) <- type %06x\\n\", __FUNCTION__, evt, data, evt->type );\n     D_DEBUG_AT( EventBuffer_Surface, \"  -> surface id %u\\n\", evt->surface_id );\n\n     if (evt->type == DSEVT_UPDATE) {\n          D_DEBUG_AT( EventBuffer_Surface, \"  -> updated %4d,%4d-%4dx%4d (left)\\n\",\n                      DFB_RECTANGLE_VALS_FROM_REGION( &evt->update ) );\n          D_DEBUG_AT( EventBuffer_Surface, \"  -> updated %4d,%4d-%4dx%4d (right)\\n\",\n                      DFB_RECTANGLE_VALS_FROM_REGION( &evt->update_right ) );\n          D_DEBUG_AT( EventBuffer_Surface, \"  -> flip count %u\\n\", evt->flip_count );\n          D_DEBUG_AT( EventBuffer_Surface, \"  -> time stamp %lld\\n\", evt->time_stamp );\n     }\n\n     item = D_CALLOC( 1, sizeof(EventBufferItem) );\n\n     item->evt.surface = *evt;\n     item->evt.clazz   = DFEC_SURFACE;\n\n     IDirectFBEventBuffer_AddItem( data, item );\n\n     if (evt->type == DSEVT_DESTROYED) {\n          AttachedSurface *surface;\n\n          direct_list_foreach (surface, data->surfaces) {\n               if (!surface->surface)\n                    continue;\n\n               if (surface->surface->object.id == evt->surface_id) {\n                    dfb_surface_unref( surface->surface );\n                    surface->surface = NULL;\n               }\n          }\n\n          return RS_REMOVE;\n     }\n\n     return RS_OK;\n}\n\nstatic void *\nIDirectFBEventBuffer_Feed( DirectThread *thread,\n                           void         *arg )\n{\n     IDirectFBEventBuffer_data *data = arg;\n\n     direct_mutex_lock( &data->events_mutex );\n\n     while (data->pipe) {\n          while (data->events && data->pipe) {\n               ssize_t          num;\n               EventBufferItem *item = (EventBufferItem*) data->events;\n\n               D_UNUSED_P( num );\n\n               if (data->stats_enabled)\n                    CollectEventStatistics( &data->stats, &item->evt, -1 );\n\n               direct_list_remove( &data->events, &item->link );\n\n               if (item->evt.clazz == DFEC_UNIVERSAL) {\n                    D_WARN( \"universal events not supported in pipe mode\" );\n                    continue;\n               }\n\n               direct_mutex_unlock( &data->events_mutex );\n\n               D_DEBUG_AT( EventBuffer_Feed, \"Going to write \"_ZU\" bytes to file descriptor %d...\\n\",\n                           sizeof(DFBEvent), data->pipe_fds[1] );\n\n               num = write( data->pipe_fds[1], &item->evt, sizeof(DFBEvent) );\n\n               D_DEBUG_AT( EventBuffer_Feed, \"...wrote \"_ZD\" bytes to file descriptor %d\\n\", num, data->pipe_fds[1] );\n\n               D_FREE( item );\n\n               direct_mutex_lock( &data->events_mutex );\n          }\n\n          if (data->pipe)\n               direct_waitqueue_wait( &data->wait_condition, &data->events_mutex );\n     }\n\n     direct_mutex_unlock( &data->events_mutex );\n\n     return NULL;\n}\n\nstatic void\nCollectEventStatistics( DFBEventBufferStats *stats,\n                        const DFBEvent      *event,\n                        int                  incdec )\n{\n     stats->num_events += incdec;\n\n     switch (event->clazz) {\n          case DFEC_INPUT:\n               stats->DFEC_INPUT += incdec;\n\n               switch (event->input.type) {\n                    case DIET_KEYPRESS:\n                         stats->DIET_KEYPRESS += incdec;\n                         break;\n\n                    case DIET_KEYRELEASE:\n                         stats->DIET_KEYRELEASE += incdec;\n                         break;\n\n                    case DIET_BUTTONPRESS:\n                         stats->DIET_BUTTONPRESS += incdec;\n                         break;\n\n                    case DIET_BUTTONRELEASE:\n                         stats->DIET_BUTTONRELEASE += incdec;\n                         break;\n\n                    case DIET_AXISMOTION:\n                         stats->DIET_AXISMOTION += incdec;\n                         break;\n\n                    default:\n                         D_BUG( \"unknown input event type 0x%08x\", event->input.type );\n               }\n               break;\n\n          case DFEC_WINDOW:\n               stats->DFEC_WINDOW += incdec;\n\n               switch (event->window.type) {\n                    case DWET_POSITION:\n                         stats->DWET_POSITION += incdec;\n                         break;\n\n                    case DWET_SIZE:\n                         stats->DWET_SIZE += incdec;\n                         break;\n\n                    case DWET_CLOSE:\n                         stats->DWET_CLOSE += incdec;\n                         break;\n\n                    case DWET_DESTROYED:\n                         stats->DWET_DESTROYED += incdec;\n                         break;\n\n                    case DWET_GOTFOCUS:\n                         stats->DWET_GOTFOCUS += incdec;\n                         break;\n\n                    case DWET_LOSTFOCUS:\n                         stats->DWET_LOSTFOCUS += incdec;\n                         break;\n\n                    case DWET_KEYDOWN:\n                         stats->DWET_KEYDOWN += incdec;\n                         break;\n\n                    case DWET_KEYUP:\n                         stats->DWET_KEYUP += incdec;\n                         break;\n\n                    case DWET_BUTTONDOWN:\n                         stats->DWET_BUTTONDOWN += incdec;\n                         break;\n\n                    case DWET_BUTTONUP:\n                         stats->DWET_BUTTONUP += incdec;\n                         break;\n\n                    case DWET_MOTION:\n                         stats->DWET_MOTION += incdec;\n                         break;\n\n                    case DWET_ENTER:\n                         stats->DWET_ENTER += incdec;\n                         break;\n\n                    case DWET_LEAVE:\n                         stats->DWET_LEAVE += incdec;\n                         break;\n\n                    case DWET_WHEEL:\n                         stats->DWET_WHEEL += incdec;\n                         break;\n\n                    case DWET_POSITION_SIZE:\n                         stats->DWET_POSITION_SIZE += incdec;\n                         break;\n\n                    default:\n                         D_BUG( \"unknown window event type 0x%08x\", event->window.type );\n               }\n               break;\n\n          case DFEC_USER:\n               stats->DFEC_USER += incdec;\n               break;\n\n          case DFEC_VIDEOPROVIDER:\n               stats->DFEC_VIDEOPROVIDER +=incdec;\n\n               switch (event->videoprovider.type) {\n                    case DVPET_STARTED:\n                         stats->DVPET_STARTED += incdec;\n                         break;\n\n                    case DVPET_STOPPED:\n                         stats->DVPET_STOPPED += incdec;\n                         break;\n\n                    case DVPET_SPEEDCHANGE:\n                         stats->DVPET_SPEEDCHANGE += incdec;\n                         break;\n\n                    case DVPET_STREAMCHANGE:\n                         stats->DVPET_STREAMCHANGE += incdec;\n                         break;\n\n                    case DVPET_FATALERROR:\n                         stats->DVPET_FATALERROR += incdec;\n                         break;\n\n                    case DVPET_FINISHED:\n                         stats->DVPET_FINISHED += incdec;\n                         break;\n\n                    case DVPET_SURFACECHANGE:\n                         stats->DVPET_SURFACECHANGE += incdec;\n                         break;\n\n                    case DVPET_FRAMEDECODED:\n                         stats->DVPET_FRAMEDECODED += incdec;\n                         break;\n\n                    case DVPET_FRAMEDISPLAYED:\n                         stats->DVPET_FRAMEDISPLAYED += incdec;\n                         break;\n\n                    case DVPET_DATAEXHAUSTED:\n                         stats->DVPET_DATAEXHAUSTED += incdec;\n                         break;\n\n                    case DVPET_VIDEOACTION:\n                         stats->DVPET_VIDEOACTION += incdec;\n                         break;\n\n                    case DVPET_DATALOW:\n                         stats->DVPET_DATALOW += incdec;\n                         break;\n\n                   case DVPET_DATAHIGH:\n                         stats->DVPET_DATAHIGH += incdec;\n                         break;\n\n                   case DVPET_BUFFERTIMELOW:\n                         stats->DVPET_BUFFERTIMELOW += incdec;\n                         break;\n\n                   case DVPET_BUFFERTIMEHIGH:\n                         stats->DVPET_BUFFERTIMEHIGH += incdec;\n                         break;\n\n                    default:\n                         D_BUG( \"unknown video provider event type 0x%08x\", event->videoprovider.type );\n               }\n               break;\n\n          case DFEC_UNIVERSAL:\n               stats->DFEC_UNIVERSAL += incdec;\n               break;\n\n          default:\n               D_BUG( \"unknown event class 0x%08x\", event->clazz );\n     }\n}\n"
  },
  {
    "path": "src/input/idirectfbeventbuffer.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __INPUT__IDIRECTFBEVENTBUFFER_H__\n#define __INPUT__IDIRECTFBEVENTBUFFER_H__\n\n#include <core/coretypes.h>\n\ntypedef bool (*EventBufferFilterCallback)( DFBEvent *evt, void *ctx );\n\n/*\n * initializes interface struct and private data\n */\nDFBResult IDirectFBEventBuffer_Construct        ( IDirectFBEventBuffer      *thiz,\n                                                  EventBufferFilterCallback  filter,\n                                                  void                      *filter_ctx );\n\nDFBResult IDirectFBEventBuffer_AttachInputDevice( IDirectFBEventBuffer      *thiz,\n                                                  CoreInputDevice           *device );\n\nDFBResult IDirectFBEventBuffer_DetachInputDevice( IDirectFBEventBuffer      *thiz,\n                                                  CoreInputDevice           *device );\n\nDFBResult IDirectFBEventBuffer_AttachWindow     ( IDirectFBEventBuffer      *thiz,\n                                                  CoreWindow                *window );\n\nDFBResult IDirectFBEventBuffer_DetachWindow     ( IDirectFBEventBuffer      *thiz,\n                                                  CoreWindow                *window );\n\nDFBResult IDirectFBEventBuffer_AttachSurface    ( IDirectFBEventBuffer      *thiz,\n                                                  CoreSurface               *surface );\n\nDFBResult IDirectFBEventBuffer_DetachSurface    ( IDirectFBEventBuffer      *thiz,\n                                                  CoreSurface               *surface );\n\n#endif\n"
  },
  {
    "path": "src/input/idirectfbinputdevice.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreInputDevice.h>\n#include <input/idirectfbeventbuffer.h>\n#include <input/idirectfbinputdevice.h>\n\nD_DEBUG_DOMAIN( InputDevice, \"IDirectFBInputDevice\", \"IDirectFBInputDevice Interface\" );\n\n/**********************************************************************************************************************/\n\n/*\n * private data struct of IDirectFBInputDevice\n */\ntypedef struct {\n     int                         ref;                            /* reference counter */\n\n     CoreInputDevice            *device;                         /* the input device object */\n\n     int                         axis[DIAI_LAST+1];              /* position of all axes */\n     DFBInputDeviceKeyState      keystates[DIKI_NUMBER_OF_KEYS]; /* state of all keys */\n\n     DFBInputDeviceDescription   desc;                           /* device description */\n\n     Reaction                    reaction;\n} IDirectFBInputDevice_data;\n\n/**********************************************************************************************************************/\n\nstatic void\nIDirectFBInputDevice_Destruct( IDirectFBInputDevice *thiz )\n{\n     IDirectFBInputDevice_data *data = thiz->priv;\n\n     D_DEBUG_AT( InputDevice, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     dfb_input_detach( data->device, &data->reaction );\n\n     DIRECT_DEALLOCATE_INTERFACE( thiz );\n}\n\nstatic DirectResult\nIDirectFBInputDevice_AddRef( IDirectFBInputDevice *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBInputDevice )\n\n     D_DEBUG_AT( InputDevice, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref++;\n\n     return DFB_OK;\n}\n\nstatic DirectResult\nIDirectFBInputDevice_Release( IDirectFBInputDevice *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBInputDevice )\n\n     D_DEBUG_AT( InputDevice, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->ref == 0)\n          IDirectFBInputDevice_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBInputDevice_GetID( IDirectFBInputDevice *thiz,\n                            DFBInputDeviceID     *ret_device_id )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBInputDevice )\n\n     D_DEBUG_AT( InputDevice, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_device_id)\n          return DFB_INVARG;\n\n     *ret_device_id = dfb_input_device_id( data->device );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBInputDevice_GetDescription( IDirectFBInputDevice      *thiz,\n                                     DFBInputDeviceDescription *ret_desc )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBInputDevice )\n\n     D_DEBUG_AT( InputDevice, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_desc)\n          return DFB_INVARG;\n\n     *ret_desc = data->desc;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBInputDevice_GetKeymapEntry( IDirectFBInputDevice      *thiz,\n                                     int                        keycode,\n                                     DFBInputDeviceKeymapEntry *ret_entry )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBInputDevice )\n\n     D_DEBUG_AT( InputDevice, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_entry)\n          return DFB_INVARG;\n\n     if (data->desc.min_keycode < 0 || data->desc.max_keycode < 0)\n          return DFB_UNSUPPORTED;\n\n     if (keycode < data->desc.min_keycode || keycode > data->desc.max_keycode)\n          return DFB_INVARG;\n\n     return dfb_input_device_get_keymap_entry( data->device, keycode, ret_entry );\n}\n\nstatic DFBResult\nIDirectFBInputDevice_SetKeymapEntry( IDirectFBInputDevice      *thiz,\n                                     int                        keycode,\n                                     DFBInputDeviceKeymapEntry *entry )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBInputDevice )\n\n     D_DEBUG_AT( InputDevice, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!entry)\n          return DFB_INVARG;\n\n     if (data->desc.min_keycode < 0 || data->desc.max_keycode < 0)\n          return DFB_UNSUPPORTED;\n\n     if (keycode < data->desc.min_keycode || keycode > data->desc.max_keycode)\n          return DFB_INVARG;\n\n     return CoreInputDevice_SetKeymapEntry( data->device, keycode, entry );\n}\n\nstatic DFBResult\nIDirectFBInputDevice_LoadKeymap ( IDirectFBInputDevice *thiz,\n                                  char                 *filename )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBInputDevice )\n\n     D_DEBUG_AT( InputDevice, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!filename)\n          return DFB_INVARG;\n\n     return dfb_input_device_load_keymap( data->device, filename );\n}\n\nstatic DFBResult\nIDirectFBInputDevice_CreateEventBuffer( IDirectFBInputDevice  *thiz,\n                                        IDirectFBEventBuffer **ret_interface )\n{\n     IDirectFBEventBuffer *iface;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBInputDevice )\n\n     D_DEBUG_AT( InputDevice, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBEventBuffer );\n\n     IDirectFBEventBuffer_Construct( iface, NULL, NULL );\n\n     IDirectFBEventBuffer_AttachInputDevice( iface, data->device );\n\n     *ret_interface = iface;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBInputDevice_AttachEventBuffer( IDirectFBInputDevice *thiz,\n                                        IDirectFBEventBuffer *buffer )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBInputDevice )\n\n     D_DEBUG_AT( InputDevice, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return IDirectFBEventBuffer_AttachInputDevice( buffer, data->device );\n}\n\nstatic DFBResult\nIDirectFBInputDevice_DetachEventBuffer( IDirectFBInputDevice *thiz,\n                                        IDirectFBEventBuffer *buffer )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBInputDevice )\n\n     D_DEBUG_AT( InputDevice, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return IDirectFBEventBuffer_DetachInputDevice( buffer, data->device );\n}\n\nstatic DFBResult\nIDirectFBInputDevice_GetKeyState( IDirectFBInputDevice        *thiz,\n                                  DFBInputDeviceKeyIdentifier  key_id,\n                                  DFBInputDeviceKeyState      *ret_state )\n{\n     unsigned int index = key_id - DFB_KEY( IDENTIFIER, 0 );\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBInputDevice )\n\n     D_DEBUG_AT( InputDevice, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_state || index >= DIKI_NUMBER_OF_KEYS)\n          return DFB_INVARG;\n\n     *ret_state = data->keystates[index];\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBInputDevice_GetModifiers( IDirectFBInputDevice       *thiz,\n                                   DFBInputDeviceModifierMask *ret_modifiers )\n{\n     DFBResult        ret;\n     InputDeviceState state;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBInputDevice )\n\n     D_DEBUG_AT( InputDevice, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_modifiers)\n          return DFB_INVARG;\n\n     ret = dfb_input_device_get_state( data->device, &state );\n     if (ret)\n          return ret;\n\n     *ret_modifiers = state.modifiers_l | state.modifiers_r;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBInputDevice_GetLockState( IDirectFBInputDevice    *thiz,\n                                   DFBInputDeviceLockState *ret_locks )\n{\n     DFBResult        ret;\n     InputDeviceState state;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBInputDevice )\n\n     D_DEBUG_AT( InputDevice, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_locks)\n          return DFB_INVARG;\n\n     ret = dfb_input_device_get_state( data->device, &state );\n     if (ret)\n          return ret;\n\n     *ret_locks = state.locks;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBInputDevice_GetButtons( IDirectFBInputDevice     *thiz,\n                                 DFBInputDeviceButtonMask *ret_buttons )\n{\n     DFBResult        ret;\n     InputDeviceState state;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBInputDevice )\n\n     D_DEBUG_AT( InputDevice, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_buttons)\n          return DFB_INVARG;\n\n     ret = dfb_input_device_get_state( data->device, &state );\n     if (ret)\n          return ret;\n\n     *ret_buttons = state.buttons;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBInputDevice_GetButtonState( IDirectFBInputDevice           *thiz,\n                                     DFBInputDeviceButtonIdentifier  button,\n                                     DFBInputDeviceButtonState      *ret_state )\n{\n     DFBResult        ret;\n     InputDeviceState state;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBInputDevice )\n\n     D_DEBUG_AT( InputDevice, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     ret = dfb_input_device_get_state( data->device, &state );\n     if (ret)\n          return ret;\n\n     if (!ret_state || button < DIBI_FIRST || button > DIBI_LAST)\n          return DFB_INVARG;\n\n     *ret_state = (state.buttons & (1 << button)) ? DIBS_DOWN : DIBS_UP;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBInputDevice_GetAxis( IDirectFBInputDevice         *thiz,\n                              DFBInputDeviceAxisIdentifier  axis,\n                              int                          *ret_pos )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBInputDevice )\n\n     D_DEBUG_AT( InputDevice, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_pos || axis < DIAI_FIRST || axis > DIAI_LAST)\n          return DFB_INVARG;\n\n     *ret_pos = data->axis[axis];\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBInputDevice_GetXY( IDirectFBInputDevice *thiz,\n                            int                  *ret_x,\n                            int                  *ret_y )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBInputDevice )\n\n     D_DEBUG_AT( InputDevice, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_x && !ret_y)\n          return DFB_INVARG;\n\n     if (ret_x)\n          *ret_x = data->axis[DIAI_X];\n\n     if (ret_y)\n          *ret_y = data->axis[DIAI_Y];\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBInputDevice_SetConfiguration( IDirectFBInputDevice       *thiz,\n                                       const DFBInputDeviceConfig *config )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBInputDevice )\n\n     return CoreInputDevice_SetConfiguration( data->device, config );\n}\n\nstatic ReactionResult\nIDirectFBInputDevice_React( const void *msg_data,\n                            void       *ctx )\n{\n     const DFBInputEvent       *evt  = msg_data;\n     IDirectFBInputDevice_data *data = ctx;\n     unsigned int               index;\n\n     D_DEBUG_AT( InputDevice, \"%s( %p, %p ) <- type %06x\\n\", __FUNCTION__, evt, data, evt->type );\n\n     switch (evt->type) {\n          case DIET_KEYPRESS:\n               index = evt->key_id - DFB_KEY( IDENTIFIER, 0 );\n               if (index < DIKI_NUMBER_OF_KEYS)\n                    data->keystates[index] = DIKS_DOWN;\n             break;\n\n          case DIET_KEYRELEASE:\n               index = evt->key_id - DFB_KEY( IDENTIFIER, 0 );\n               if (index < DIKI_NUMBER_OF_KEYS)\n                    data->keystates[index] = DIKS_UP;\n               break;\n\n          case DIET_AXISMOTION:\n               if (evt->flags & DIEF_AXISREL)\n                    data->axis[evt->axis] += evt->axisrel;\n               if (evt->flags & DIEF_AXISABS)\n                    data->axis[evt->axis] = evt->axisabs;\n               break;\n\n          default:\n               D_DEBUG_AT( InputDevice, \"  -> unknown event type, skipping!\\n\" );\n     }\n\n     return RS_OK;\n}\n\nDFBResult\nIDirectFBInputDevice_Construct( IDirectFBInputDevice *thiz,\n                                CoreInputDevice      *device )\n{\n     DFBResult ret;\n\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBInputDevice )\n\n     D_DEBUG_AT( InputDevice, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref    = 1;\n     data->device = device;\n\n     dfb_input_device_description( device, &data->desc );\n\n     ret = dfb_input_attach( data->device, IDirectFBInputDevice_React, data, &data->reaction );\n     if (ret) {\n          D_DERROR( ret, \"IDirectFBInputDevice: Could not attach to reactor!\\n\" );\n          DIRECT_DEALLOCATE_INTERFACE( thiz );\n          return ret;\n     }\n\n     thiz->AddRef            = IDirectFBInputDevice_AddRef;\n     thiz->Release           = IDirectFBInputDevice_Release;\n     thiz->GetID             = IDirectFBInputDevice_GetID;\n     thiz->GetDescription    = IDirectFBInputDevice_GetDescription;\n     thiz->GetKeymapEntry    = IDirectFBInputDevice_GetKeymapEntry;\n     thiz->SetKeymapEntry    = IDirectFBInputDevice_SetKeymapEntry;\n     thiz->LoadKeymap        = IDirectFBInputDevice_LoadKeymap;\n     thiz->CreateEventBuffer = IDirectFBInputDevice_CreateEventBuffer;\n     thiz->AttachEventBuffer = IDirectFBInputDevice_AttachEventBuffer;\n     thiz->DetachEventBuffer = IDirectFBInputDevice_DetachEventBuffer;\n     thiz->GetKeyState       = IDirectFBInputDevice_GetKeyState;\n     thiz->GetModifiers      = IDirectFBInputDevice_GetModifiers;\n     thiz->GetLockState      = IDirectFBInputDevice_GetLockState;\n     thiz->GetButtons        = IDirectFBInputDevice_GetButtons;\n     thiz->GetButtonState    = IDirectFBInputDevice_GetButtonState;\n     thiz->GetAxis           = IDirectFBInputDevice_GetAxis;\n     thiz->GetXY             = IDirectFBInputDevice_GetXY;\n     thiz->SetConfiguration  = IDirectFBInputDevice_SetConfiguration;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/input/idirectfbinputdevice.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __INPUT__IDIRECTFBINPUTDEVICE_H__\n#define __INPUT__IDIRECTFBINPUTDEVICE_H__\n\n#include <core/input.h>\n\n/*\n * initializes interface struct and private data\n */\nDFBResult IDirectFBInputDevice_Construct( IDirectFBInputDevice *thiz,\n                                          CoreInputDevice      *device );\n\n#endif\n"
  },
  {
    "path": "src/media/idirectfbdatabuffer.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <media/idirectfbdatabuffer.h>\n#include <media/idirectfbfont.h>\n#include <media/idirectfbimageprovider.h>\n#include <media/idirectfbvideoprovider.h>\n\nD_DEBUG_DOMAIN( DataBuffer, \"IDirectFBDataBuffer\", \"IDirectFBDataBuffer Interface\" );\n\n/**********************************************************************************************************************/\n\nvoid\nIDirectFBDataBuffer_Destruct( IDirectFBDataBuffer *thiz )\n{\n     IDirectFBDataBuffer_data *data = thiz->priv;\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->filename)\n          D_FREE( data->filename );\n\n     DIRECT_DEALLOCATE_INTERFACE( thiz );\n}\n\nstatic DirectResult\nIDirectFBDataBuffer_AddRef( IDirectFBDataBuffer *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref++;\n\n     return DFB_OK;\n}\n\nstatic DirectResult\nIDirectFBDataBuffer_Release( IDirectFBDataBuffer *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->ref == 0)\n          IDirectFBDataBuffer_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Flush( IDirectFBDataBuffer *thiz )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Finish( IDirectFBDataBuffer *thiz )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_SeekTo( IDirectFBDataBuffer *thiz,\n                            unsigned int         offset )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_GetPosition( IDirectFBDataBuffer *thiz,\n                                 unsigned int        *ret_offset )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_GetLength( IDirectFBDataBuffer *thiz,\n                               unsigned int        *ret_length )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_WaitForData( IDirectFBDataBuffer *thiz,\n                                 unsigned int         length )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_WaitForDataWithTimeout( IDirectFBDataBuffer *thiz,\n                                            unsigned int         length,\n                                            unsigned int         seconds,\n                                            unsigned int         milli_seconds )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_GetData( IDirectFBDataBuffer *thiz,\n                             unsigned int         length,\n                             void                *ret_data_ptr,\n                             unsigned int        *ret_read )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_PeekData( IDirectFBDataBuffer *thiz,\n                              unsigned int         length,\n                              int                  offset,\n                              void                *ret_data_ptr,\n                              unsigned int        *ret_read )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_HasData( IDirectFBDataBuffer *thiz )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_PutData( IDirectFBDataBuffer *thiz,\n                             const void          *data_ptr,\n                             unsigned int         length )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_CreateImageProvider( IDirectFBDataBuffer     *thiz,\n                                         IDirectFBImageProvider **ret_interface )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     /* Check arguments. */\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     return IDirectFBImageProvider_CreateFromBuffer( thiz, data->core, data->idirectfb, ret_interface );\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_CreateVideoProvider( IDirectFBDataBuffer     *thiz,\n                                         IDirectFBVideoProvider **ret_interface )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     /* Check arguments. */\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     return IDirectFBVideoProvider_CreateFromBuffer( thiz, data->core, data->idirectfb, ret_interface );\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_CreateFont( IDirectFBDataBuffer       *thiz,\n                                const DFBFontDescription  *desc,\n                                IDirectFBFont            **ret_interface )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     /* Check arguments. */\n     if (!desc || !ret_interface)\n          return DFB_INVARG;\n\n     return IDirectFBFont_CreateFromBuffer( thiz, data->core, desc, ret_interface );\n}\n\nDFBResult\nIDirectFBDataBuffer_Construct( IDirectFBDataBuffer *thiz,\n                               const char          *filename,\n                               const void          *buffer,\n                               unsigned int         length,\n                               CoreDFB             *core,\n                               IDirectFB           *idirectfb )\n{\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBDataBuffer )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref       = 1;\n     data->core      = core;\n     data->idirectfb = idirectfb;\n\n     if (filename)\n          data->filename = D_STRDUP( filename );\n\n     if (buffer) {\n          data->buffer = (void*) buffer;\n          data->length = length;\n     }\n\n     thiz->AddRef                 = IDirectFBDataBuffer_AddRef;\n     thiz->Release                = IDirectFBDataBuffer_Release;\n     thiz->Flush                  = IDirectFBDataBuffer_Flush;\n     thiz->Finish                 = IDirectFBDataBuffer_Finish;\n     thiz->SeekTo                 = IDirectFBDataBuffer_SeekTo;\n     thiz->GetPosition            = IDirectFBDataBuffer_GetPosition;\n     thiz->GetLength              = IDirectFBDataBuffer_GetLength;\n     thiz->WaitForData            = IDirectFBDataBuffer_WaitForData;\n     thiz->WaitForDataWithTimeout = IDirectFBDataBuffer_WaitForDataWithTimeout;\n     thiz->GetData                = IDirectFBDataBuffer_GetData;\n     thiz->PeekData               = IDirectFBDataBuffer_PeekData;\n     thiz->HasData                = IDirectFBDataBuffer_HasData;\n     thiz->PutData                = IDirectFBDataBuffer_PutData;\n     thiz->CreateImageProvider    = IDirectFBDataBuffer_CreateImageProvider;\n     thiz->CreateVideoProvider    = IDirectFBDataBuffer_CreateVideoProvider;\n     thiz->CreateFont             = IDirectFBDataBuffer_CreateFont;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/media/idirectfbdatabuffer.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __MEDIA__IDIRECTFBDATABUFFER_H__\n#define __MEDIA__IDIRECTFBDATABUFFER_H__\n\n#include <core/coretypes.h>\n\n/*\n * private data struct of IDirectFBDataBuffer\n */\ntypedef struct {\n     int           ref;       /* reference counter */\n\n     char         *filename;  /* only set if databuffer is created from file */\n     void         *buffer;    /* only set if databuffer is created from memory */\n     unsigned int  length;\n\n     CoreDFB      *core;\n     IDirectFB    *idirectfb;\n} IDirectFBDataBuffer_data;\n\n/*\n * initializes interface struct and private data\n */\nDFBResult IDirectFBDataBuffer_Construct( IDirectFBDataBuffer *thiz,\n                                         const char          *filename,\n                                         const void          *buffer,\n                                         unsigned int         length,\n                                         CoreDFB             *core,\n                                         IDirectFB           *idirectfb );\n\n/*\n * destroys databuffer and frees private data\n */\nvoid      IDirectFBDataBuffer_Destruct ( IDirectFBDataBuffer *thiz );\n\n#endif\n"
  },
  {
    "path": "src/media/idirectfbdatabuffer_file.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/mutex.h>\n#include <direct/stream.h>\n#include <media/idirectfbdatabuffer.h>\n#include <media/idirectfbdatabuffer_file.h>\n\nD_DEBUG_DOMAIN( DataBuffer, \"IDirectFBDataBufferF\", \"IDirectFBDataBuffer_File Interface\" );\n\n/**********************************************************************************************************************/\n\n/*\n * private data struct of IDirectFBDataBuffer_File\n */\ntypedef struct {\n     IDirectFBDataBuffer_data  base;   /* base databuffer implementation */\n\n     DirectStream             *stream;\n\n     DirectMutex               mutex;\n} IDirectFBDataBuffer_File_data;\n\n/**********************************************************************************************************************/\n\nstatic void\nIDirectFBDataBuffer_File_Destruct( IDirectFBDataBuffer *thiz )\n{\n     IDirectFBDataBuffer_File_data *data = thiz->priv;\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     direct_stream_destroy( data->stream );\n\n     direct_mutex_deinit( &data->mutex );\n\n     IDirectFBDataBuffer_Destruct( thiz );\n}\n\nstatic DirectResult\nIDirectFBDataBuffer_File_Release( IDirectFBDataBuffer *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->ref == 0)\n          IDirectFBDataBuffer_File_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_File_Flush( IDirectFBDataBuffer *thiz )\n{\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return DFB_UNSUPPORTED;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_File_Finish( IDirectFBDataBuffer *thiz )\n{\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return DFB_UNSUPPORTED;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_File_SeekTo( IDirectFBDataBuffer *thiz,\n                                 unsigned int         offset )\n{\n     DFBResult ret;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_File )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!direct_stream_seekable( data->stream ))\n          return DFB_UNSUPPORTED;\n\n     direct_mutex_lock( &data->mutex );\n\n     ret = direct_stream_seek( data->stream, offset );\n\n     direct_mutex_unlock( &data->mutex );\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_File_GetPosition( IDirectFBDataBuffer *thiz,\n                                      unsigned int        *ret_offset )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_File )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_offset)\n          return DFB_INVARG;\n\n     *ret_offset = direct_stream_offset( data->stream );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_File_GetLength( IDirectFBDataBuffer *thiz,\n                                    unsigned int        *ret_length )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_File )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_length)\n          return DFB_INVARG;\n\n     *ret_length = direct_stream_length( data->stream );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_File_WaitForData( IDirectFBDataBuffer *thiz,\n                                      unsigned int         length )\n{\n     DFBResult ret;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_File )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     direct_mutex_lock( &data->mutex );\n\n     ret = direct_stream_wait( data->stream, length, NULL );\n\n     direct_mutex_unlock( &data->mutex );\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_File_WaitForDataWithTimeout( IDirectFBDataBuffer *thiz,\n                                                 unsigned int         length,\n                                                 unsigned int         seconds,\n                                                 unsigned int         milli_seconds )\n{\n     DirectResult   ret;\n     struct timeval tv;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_File )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     tv.tv_sec  = seconds;\n     tv.tv_usec = milli_seconds*1000;\n\n     while ((ret = direct_mutex_trylock( &data->mutex ))) {\n          struct timespec t, r;\n\n          if (ret != DR_BUSY)\n               return ret;\n\n          t.tv_sec  = 0;\n          t.tv_nsec = 10000;\n          nanosleep( &t, &r );\n\n          tv.tv_usec -= (t.tv_nsec - r.tv_nsec + 500) / 1000;\n          if (tv.tv_usec < 0) {\n               if (tv.tv_sec < 1)\n                    return DFB_TIMEOUT;\n\n               tv.tv_sec--;\n               tv.tv_usec += 999999;\n          }\n     }\n\n     ret = direct_stream_wait( data->stream, length, &tv );\n\n     direct_mutex_unlock( &data->mutex );\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_File_GetData( IDirectFBDataBuffer *thiz,\n                                  unsigned int         length,\n                                  void                *ret_data_ptr,\n                                  unsigned int        *ret_read )\n{\n     DFBResult ret;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_File )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_data_ptr || !length)\n          return DFB_INVARG;\n\n     direct_mutex_lock( &data->mutex );\n\n     ret = direct_stream_read( data->stream, length, ret_data_ptr, ret_read );\n\n     direct_mutex_unlock( &data->mutex );\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_File_PeekData( IDirectFBDataBuffer *thiz,\n                                   unsigned int         length,\n                                   int                  offset,\n                                   void                *ret_data_ptr,\n                                   unsigned int        *ret_read )\n{\n     DFBResult ret;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_File )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_data_ptr || !length)\n          return DFB_INVARG;\n\n     direct_mutex_lock( &data->mutex );\n\n     ret = direct_stream_peek( data->stream, length, offset, ret_data_ptr, ret_read );\n\n     direct_mutex_unlock( &data->mutex );\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_File_HasData( IDirectFBDataBuffer *thiz )\n{\n     struct timeval tv = { 0, 0 };\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_File )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return direct_stream_wait( data->stream, 1, &tv );\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_File_PutData( IDirectFBDataBuffer *thiz,\n                                  const void          *data_ptr,\n                                  unsigned int         length )\n{\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return DFB_UNSUPPORTED;\n}\n\nDFBResult\nIDirectFBDataBuffer_File_Construct( IDirectFBDataBuffer *thiz,\n                                    const char          *filename,\n                                    CoreDFB             *core,\n                                    IDirectFB           *idirectfb )\n{\n     DFBResult ret;\n\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBDataBuffer_File )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     IDirectFBDataBuffer_Construct( thiz, filename, NULL, 0, core, idirectfb );\n\n     ret = direct_stream_create( filename, &data->stream );\n     if (ret) {\n          D_DERROR( ret, \"IDirectFBDataBufferF: Failed to create stream '%s'!\\n\", filename );\n          DIRECT_DEALLOCATE_INTERFACE( thiz );\n          return ret;\n     }\n\n     direct_mutex_init( &data->mutex );\n\n     thiz->Release                = IDirectFBDataBuffer_File_Release;\n     thiz->Flush                  = IDirectFBDataBuffer_File_Flush;\n     thiz->Finish                 = IDirectFBDataBuffer_File_Finish;\n     thiz->SeekTo                 = IDirectFBDataBuffer_File_SeekTo;\n     thiz->GetPosition            = IDirectFBDataBuffer_File_GetPosition;\n     thiz->GetLength              = IDirectFBDataBuffer_File_GetLength;\n     thiz->WaitForData            = IDirectFBDataBuffer_File_WaitForData;\n     thiz->WaitForDataWithTimeout = IDirectFBDataBuffer_File_WaitForDataWithTimeout;\n     thiz->GetData                = IDirectFBDataBuffer_File_GetData;\n     thiz->PeekData               = IDirectFBDataBuffer_File_PeekData;\n     thiz->HasData                = IDirectFBDataBuffer_File_HasData;\n     thiz->PutData                = IDirectFBDataBuffer_File_PutData;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/media/idirectfbdatabuffer_file.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __MEDIA__IDIRECTFBDATABUFFER_FILE_H__\n#define __MEDIA__IDIRECTFBDATABUFFER_FILE_H__\n\n#include <core/coretypes.h>\n\n/*\n * calls base databuffer constructor and initializes file based static databuffer\n */\nDFBResult IDirectFBDataBuffer_File_Construct( IDirectFBDataBuffer *thiz,\n                                              const char          *filename,\n                                              CoreDFB             *core,\n                                              IDirectFB           *idirectfb );\n\n#endif\n"
  },
  {
    "path": "src/media/idirectfbdatabuffer_memory.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/memcpy.h>\n#include <direct/util.h>\n#include <media/idirectfbdatabuffer.h>\n#include <media/idirectfbdatabuffer_memory.h>\n\nD_DEBUG_DOMAIN( DataBuffer, \"IDirectFBDataBufferM\", \"IDirectFBDataBuffer_Memory Interface\" );\n\n/**********************************************************************************************************************/\n\n/*\n * private data struct of IDirectFBDataBuffer_Memory\n */\ntypedef struct {\n     IDirectFBDataBuffer_data  base;\n\n     const void               *buffer;\n     unsigned int              length;\n\n     unsigned int              pos;\n} IDirectFBDataBuffer_Memory_data;\n\n/**********************************************************************************************************************/\n\nstatic void\nIDirectFBDataBuffer_Memory_Destruct( IDirectFBDataBuffer *thiz )\n{\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     IDirectFBDataBuffer_Destruct( thiz );\n}\n\nstatic DirectResult\nIDirectFBDataBuffer_Memory_Release( IDirectFBDataBuffer *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->ref == 0)\n          IDirectFBDataBuffer_Memory_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Memory_Flush( IDirectFBDataBuffer *thiz )\n{\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return DFB_UNSUPPORTED;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Memory_Finish( IDirectFBDataBuffer *thiz )\n{\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return DFB_UNSUPPORTED;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Memory_SeekTo( IDirectFBDataBuffer *thiz,\n                                   unsigned int         offset )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_Memory )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (offset >= data->length)\n          return DFB_INVARG;\n\n     data->pos = offset;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Memory_GetPosition( IDirectFBDataBuffer *thiz,\n                                        unsigned int        *ret_offset )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_Memory )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_offset)\n          return DFB_INVARG;\n\n     *ret_offset = data->pos;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Memory_GetLength( IDirectFBDataBuffer *thiz,\n                                      unsigned int        *ret_length )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_Memory )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_length)\n          return DFB_INVARG;\n\n     *ret_length = data->length;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Memory_WaitForData( IDirectFBDataBuffer *thiz,\n                                        unsigned int         length )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_Memory )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->pos + length > data->length)\n          return DFB_EOF;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Memory_WaitForDataWithTimeout( IDirectFBDataBuffer *thiz,\n                                                   unsigned int         length,\n                                                   unsigned int         seconds,\n                                                   unsigned int         milli_seconds )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_Memory )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->pos + length > data->length)\n          return DFB_EOF;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Memory_GetData( IDirectFBDataBuffer *thiz,\n                                    unsigned int         length,\n                                    void                *ret_data_ptr,\n                                    unsigned int        *ret_read )\n{\n     unsigned int size;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_Memory )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_data_ptr || !length)\n          return DFB_INVARG;\n\n     if (data->pos >= data->length)\n          return DFB_EOF;\n\n     size = MIN( length, data->length - data->pos );\n\n     direct_memcpy( ret_data_ptr, data->buffer + data->pos, size );\n\n     data->pos += size;\n\n     if (ret_read)\n          *ret_read = size;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Memory_PeekData( IDirectFBDataBuffer *thiz,\n                                     unsigned int         length,\n                                     int                  offset,\n                                     void                *ret_data_ptr,\n                                     unsigned int        *ret_read )\n{\n     unsigned int size;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_Memory )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_data_ptr || !length)\n          return DFB_INVARG;\n\n     if (data->pos + offset >= data->length)\n          return DFB_EOF;\n\n     size = MIN( length, data->length - data->pos - offset );\n\n     direct_memcpy( ret_data_ptr, data->buffer + data->pos + offset, size );\n\n     if (ret_read)\n          *ret_read = size;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Memory_HasData( IDirectFBDataBuffer *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_Memory )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->pos >= data->length)\n          return DFB_EOF;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Memory_PutData( IDirectFBDataBuffer *thiz,\n                                    const void          *data_ptr,\n                                    unsigned int         length )\n{\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return DFB_UNSUPPORTED;\n}\n\nDFBResult\nIDirectFBDataBuffer_Memory_Construct( IDirectFBDataBuffer *thiz,\n                                      const void          *buffer,\n                                      unsigned int         length,\n                                      CoreDFB             *core,\n                                      IDirectFB           *idirectfb )\n{\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBDataBuffer_Memory )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     IDirectFBDataBuffer_Construct( thiz, NULL, buffer, length, core, idirectfb );\n\n     data->buffer = buffer;\n     data->length = length;\n\n     thiz->Release                = IDirectFBDataBuffer_Memory_Release;\n     thiz->Flush                  = IDirectFBDataBuffer_Memory_Flush;\n     thiz->Finish                 = IDirectFBDataBuffer_Memory_Finish;\n     thiz->SeekTo                 = IDirectFBDataBuffer_Memory_SeekTo;\n     thiz->GetPosition            = IDirectFBDataBuffer_Memory_GetPosition;\n     thiz->GetLength              = IDirectFBDataBuffer_Memory_GetLength;\n     thiz->WaitForData            = IDirectFBDataBuffer_Memory_WaitForData;\n     thiz->WaitForDataWithTimeout = IDirectFBDataBuffer_Memory_WaitForDataWithTimeout;\n     thiz->GetData                = IDirectFBDataBuffer_Memory_GetData;\n     thiz->PeekData               = IDirectFBDataBuffer_Memory_PeekData;\n     thiz->HasData                = IDirectFBDataBuffer_Memory_HasData;\n     thiz->PutData                = IDirectFBDataBuffer_Memory_PutData;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/media/idirectfbdatabuffer_memory.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __MEDIA__IDIRECTFBDATABUFFER_MEMORY_H__\n#define __MEDIA__IDIRECTFBDATABUFFER_MEMORY_H__\n\n#include <core/coretypes.h>\n\n/*\n * calls base databuffer constructor and initializes memory based static databuffer\n */\nDFBResult IDirectFBDataBuffer_Memory_Construct( IDirectFBDataBuffer *thiz,\n                                                const void          *buffer,\n                                                unsigned int         length,\n                                                CoreDFB             *core,\n                                                IDirectFB           *idirectfb );\n\n#endif\n"
  },
  {
    "path": "src/media/idirectfbdatabuffer_streamed.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/list.h>\n#include <direct/memcpy.h>\n#include <direct/waitqueue.h>\n#include <media/idirectfbdatabuffer.h>\n#include <media/idirectfbdatabuffer_streamed.h>\n\nD_DEBUG_DOMAIN( DataBuffer, \"IDirectFBDataBufferS\", \"IDirectFBDataBuffer_Streamed Interface\" );\n\n/**********************************************************************************************************************/\n\n/*\n * private data struct of IDirectFBDataBuffer_Streamed\n */\ntypedef struct {\n     IDirectFBDataBuffer_data  base;           /* base databuffer implementation */\n\n     DirectLink               *chunks;         /* data chunks */\n\n     unsigned int              length;         /* total length of all chunks */\n\n     bool                      finished;       /* whether Finish() has been called */\n\n     DirectMutex               chunks_mutex;   /* mutex lock for accessing the chunk list */\n\n     DirectWaitQueue           wait_condition; /* condition used for idle wait */\n} IDirectFBDataBuffer_Streamed_data;\n\ntypedef struct {\n     DirectLink    link;\n\n     void         *data;   /* actual data hold */\n     unsigned int  length; /* length of chunk */\n\n     unsigned int  done;   /* number of bytes already consumed */\n} DataChunk;\n\nstatic DataChunk *create_chunk ( const void *data, int length );\nstatic void       destroy_chunk( DataChunk *chunk );\n\nstatic void DestroyAllChunks( IDirectFBDataBuffer_Streamed_data *data );\nstatic void ReadChunkData   ( IDirectFBDataBuffer_Streamed_data *data,\n                              void                              *buffer,\n                              unsigned int                       offset,\n                              unsigned int                       length,\n                              bool                               flush );\n\n/**********************************************************************************************************************/\n\nstatic void\nIDirectFBDataBuffer_Streamed_Destruct( IDirectFBDataBuffer *thiz )\n{\n     IDirectFBDataBuffer_Streamed_data *data = thiz->priv;\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     direct_waitqueue_deinit( &data->wait_condition );\n     direct_mutex_deinit( &data->chunks_mutex );\n\n     IDirectFBDataBuffer_Destruct( thiz );\n}\n\nstatic DirectResult\nIDirectFBDataBuffer_Streamed_Release( IDirectFBDataBuffer *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->ref == 0)\n          IDirectFBDataBuffer_Streamed_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Streamed_Flush( IDirectFBDataBuffer *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_Streamed )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     direct_mutex_lock( &data->chunks_mutex );\n\n     DestroyAllChunks( data );\n\n     direct_mutex_unlock( &data->chunks_mutex );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Streamed_Finish( IDirectFBDataBuffer *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_Streamed )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->finished) {\n          data->finished = true;\n\n          direct_mutex_lock( &data->chunks_mutex );\n          direct_waitqueue_broadcast( &data->wait_condition );\n          direct_mutex_unlock( &data->chunks_mutex );\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Streamed_SeekTo( IDirectFBDataBuffer *thiz,\n                                     unsigned int         offset )\n{\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return DFB_UNSUPPORTED;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Streamed_GetPosition( IDirectFBDataBuffer *thiz,\n                                          unsigned int        *ret_offset )\n{\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return DFB_UNSUPPORTED;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Streamed_GetLength( IDirectFBDataBuffer *thiz,\n                                        unsigned int        *ret_length )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_Streamed )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_length)\n          return DFB_INVARG;\n\n     *ret_length = data->length;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Streamed_WaitForData( IDirectFBDataBuffer *thiz,\n                                          unsigned int         length )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_Streamed )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->finished && !data->chunks)\n          return DFB_EOF;\n\n     direct_mutex_lock( &data->chunks_mutex );\n\n     while (data->length < length && !data->finished)\n          direct_waitqueue_wait( &data->wait_condition, &data->chunks_mutex );\n\n     direct_mutex_unlock( &data->chunks_mutex );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Streamed_WaitForDataWithTimeout( IDirectFBDataBuffer *thiz,\n                                                     unsigned int         length,\n                                                     unsigned int         seconds,\n                                                     unsigned int         milli_seconds )\n{\n     DirectResult ret    = DR_OK;\n     bool         locked = false;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_Streamed )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->finished && !data->chunks)\n          return DFB_EOF;\n\n     if (direct_mutex_trylock( &data->chunks_mutex ) == 0) {\n          if (data->length >= length) {\n               direct_mutex_unlock( &data->chunks_mutex );\n\n               return DFB_OK;\n          }\n\n          locked = true;\n     }\n\n     if (!locked)\n          direct_mutex_lock( &data->chunks_mutex );\n\n     while (data->length < length && !data->finished) {\n          ret = direct_waitqueue_wait_timeout( &data->wait_condition, &data->chunks_mutex,\n                                               seconds * 1000000 + milli_seconds * 1000 );\n          if (ret == DR_TIMEOUT)\n               break;\n     }\n\n     direct_mutex_unlock( &data->chunks_mutex );\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Streamed_GetData( IDirectFBDataBuffer *thiz,\n                                      unsigned int         length,\n                                      void                *ret_data_ptr,\n                                      unsigned int        *ret_read )\n{\n     unsigned int len;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_Streamed )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_data_ptr || !length)\n          return DFB_INVARG;\n\n     direct_mutex_lock( &data->chunks_mutex );\n\n     if (!data->chunks) {\n          direct_mutex_unlock( &data->chunks_mutex );\n          return data->finished ? DFB_EOF : DFB_BUFFEREMPTY;\n     }\n\n     /* Calculate maximum number of bytes to be read. */\n     len = MIN( length, data->length );\n\n     /* Read data from chunks (destructive). */\n     ReadChunkData( data, ret_data_ptr, 0, len, true );\n\n     /* Decrease total number of bytes. */\n     data->length -= len;\n\n     /* Return number of bytes read. */\n     if (ret_read)\n          *ret_read = len;\n\n     direct_mutex_unlock( &data->chunks_mutex );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Streamed_PeekData( IDirectFBDataBuffer *thiz,\n                                       unsigned int         length,\n                                       int                  offset,\n                                       void                *ret_data_ptr,\n                                       unsigned int        *ret_read )\n{\n     unsigned int len;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_Streamed )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_data_ptr || !length || offset < 0)\n          return DFB_INVARG;\n\n     direct_mutex_lock( &data->chunks_mutex );\n\n     if (!data->chunks || (unsigned int) offset >= data->length) {\n          direct_mutex_unlock( &data->chunks_mutex );\n          return data->finished ? DFB_EOF : DFB_BUFFEREMPTY;\n     }\n\n     /* Calculate maximum number of bytes to be read. */\n     len = MIN( length, data->length - offset );\n\n     /* Read data from chunks (non-destructive). */\n     ReadChunkData( data, ret_data_ptr, offset, len, false );\n\n     /* Return number of bytes read. */\n     if (ret_read)\n          *ret_read = len;\n\n     direct_mutex_unlock( &data->chunks_mutex );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Streamed_HasData( IDirectFBDataBuffer *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_Streamed )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     /* If there's no chunk there's no data. */\n     if (!data->chunks)\n          return data->finished ? DFB_EOF : DFB_BUFFEREMPTY;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBDataBuffer_Streamed_PutData( IDirectFBDataBuffer *thiz,\n                                      const void          *data_ptr,\n                                      unsigned int         length )\n{\n     DataChunk *chunk;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBDataBuffer_Streamed )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data_ptr || !length)\n          return DFB_INVARG;\n\n     /* Fail if Finish() has been called. */\n     if (data->finished)\n          return DFB_UNSUPPORTED;\n\n     /* Create a chunk containing a copy of the provided data. */\n     chunk = create_chunk( data_ptr, length );\n     if (!chunk)\n          return DFB_NOSYSTEMMEMORY;\n\n     direct_mutex_lock( &data->chunks_mutex );\n\n     /* Append new chunk. */\n     direct_list_append( &data->chunks, &chunk->link );\n\n     /* Increase total length. */\n     data->length += length;\n\n     direct_waitqueue_broadcast( &data->wait_condition );\n\n     direct_mutex_unlock( &data->chunks_mutex );\n\n     return DFB_OK;\n}\n\nDFBResult\nIDirectFBDataBuffer_Streamed_Construct( IDirectFBDataBuffer *thiz,\n                                        CoreDFB             *core,\n                                        IDirectFB           *idirectfb )\n{\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBDataBuffer_Streamed )\n\n     D_DEBUG_AT( DataBuffer, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     IDirectFBDataBuffer_Construct( thiz, NULL, NULL, 0, core, idirectfb );\n\n     direct_mutex_init( &data->chunks_mutex );\n     direct_waitqueue_init( &data->wait_condition );\n\n     thiz->Release                = IDirectFBDataBuffer_Streamed_Release;\n     thiz->Flush                  = IDirectFBDataBuffer_Streamed_Flush;\n     thiz->Finish                 = IDirectFBDataBuffer_Streamed_Finish;\n     thiz->SeekTo                 = IDirectFBDataBuffer_Streamed_SeekTo;\n     thiz->GetPosition            = IDirectFBDataBuffer_Streamed_GetPosition;\n     thiz->GetLength              = IDirectFBDataBuffer_Streamed_GetLength;\n     thiz->WaitForData            = IDirectFBDataBuffer_Streamed_WaitForData;\n     thiz->WaitForDataWithTimeout = IDirectFBDataBuffer_Streamed_WaitForDataWithTimeout;\n     thiz->GetData                = IDirectFBDataBuffer_Streamed_GetData;\n     thiz->PeekData               = IDirectFBDataBuffer_Streamed_PeekData;\n     thiz->HasData                = IDirectFBDataBuffer_Streamed_HasData;\n     thiz->PutData                = IDirectFBDataBuffer_Streamed_PutData;\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic void\nDestroyAllChunks( IDirectFBDataBuffer_Streamed_data *data )\n{\n     DataChunk *chunk, *next;\n\n     D_ASSERT( data != NULL );\n\n     /* Loop through list. */\n     direct_list_foreach_safe (chunk, next, data->chunks) {\n          /* Deallocate chunk. */\n          destroy_chunk( chunk );\n     }\n\n     /* Clear lists. */\n     data->chunks = NULL;\n}\n\nstatic void\nReadChunkData( IDirectFBDataBuffer_Streamed_data *data,\n               void                              *buffer,\n               unsigned int                       offset,\n               unsigned int                       length,\n               bool                               flush )\n{\n     DataChunk *chunk, *next;\n\n     D_ASSERT( data != NULL );\n     D_ASSERT( buffer != NULL );\n\n     /* Loop through list. */\n     direct_list_foreach_safe (chunk, next, data->chunks) {\n          unsigned int  len;\n          unsigned int  off   = 0;\n\n          /* Data to be skipped. */\n          if (offset) {\n               /* Calculate number of bytes to be skipped from this chunk. */\n               off = MIN( offset, chunk->length - chunk->done );\n\n               /* Decrease number of bytes to skipped. */\n               offset -= off;\n          }\n\n          /* Calculate number of bytes to be read from this chunk. */\n          len = MIN( length, chunk->length - chunk->done - off );\n\n          /* Read from this chunk. */\n          if (len) {\n               /* Copy as many bytes as possible. */\n               direct_memcpy( buffer, chunk->data + chunk->done + off, len );\n\n               /* Increase write pointer. */\n               buffer = buffer + len;\n\n               /* Decrease number of bytes to read. */\n               length -= len;\n          }\n\n          /* Destructive read. */\n          if (flush) {\n               /* Increase number of consumed bytes. */\n               chunk->done += len + off;\n\n               /* Chunk completely consumed. */\n               if (chunk->done == chunk->length) {\n                    /* Remove the chunk from the list. */\n                    direct_list_remove( &data->chunks, &chunk->link );\n\n                    /* Deallocate chunk. */\n                    destroy_chunk( chunk );\n               }\n          }\n     }\n}\n\nstatic DataChunk *\ncreate_chunk( const void *data,\n              int         length )\n{\n     DataChunk *chunk;\n\n     D_ASSERT( data != NULL );\n     D_ASSERT( length > 0 );\n\n     /* Allocate chunk information. */\n     chunk = D_CALLOC( 1, sizeof(DataChunk) );\n     if (!chunk)\n          return NULL;\n\n     /* Allocate chunk data. */\n     chunk->data = D_MALLOC( length );\n     if (!chunk->data) {\n          D_FREE( chunk );\n          return NULL;\n     }\n\n     /* Fill chunk data. */\n     direct_memcpy( chunk->data, data, length );\n\n     /* Remember chunk length. */\n     chunk->length = length;\n\n     return chunk;\n}\n\nstatic void\ndestroy_chunk( DataChunk *chunk )\n{\n     D_ASSERT( chunk != NULL );\n     D_ASSERT( chunk->data != NULL );\n\n     /* Deallocate chunk data. */\n     D_FREE( chunk->data );\n\n     /* Deallocate chunk information. */\n     D_FREE( chunk );\n}\n"
  },
  {
    "path": "src/media/idirectfbdatabuffer_streamed.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __MEDIA__IDIRECTFBDATABUFFER_STREAMED_H__\n#define __MEDIA__IDIRECTFBDATABUFFER_STREAMED_H__\n\n#include <core/coretypes.h>\n\n/*\n * calls base databuffer constructor and initializes generic streamed databuffer\n */\nDFBResult IDirectFBDataBuffer_Streamed_Construct( IDirectFBDataBuffer *thiz,\n                                                  CoreDFB             *core,\n                                                  IDirectFB           *idirectfb );\n\n#endif\n"
  },
  {
    "path": "src/media/idirectfbfont.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/fonts.h>\n#include <direct/filesystem.h>\n#include <direct/utf8.h>\n#include <direct/util.h>\n#include <directfb_util.h>\n#include <media/idirectfbdatabuffer.h>\n#include <media/idirectfbfont.h>\n\nD_DEBUG_DOMAIN( Font, \"IDirectFBFont\", \"IDirectFBFont Interface\" );\n\n/**********************************************************************************************************************/\n\nstatic unsigned int\nsqrt16( unsigned int val )\n{\n     unsigned short op  = 1 << 15;\n     unsigned int   res = 1 << 15;\n\n     while (1) {\n          if (res * res > val)\n               res = res ^ op;\n\n          op >>= 1;\n\n          if (op == 0) {\n               res = res + ((val - res * res) > res ? 1 : 0);\n               break;\n          }\n\n          res = res | op;\n     }\n\n     return res;\n}\n\n/**********************************************************************************************************************/\n\nvoid\nIDirectFBFont_Destruct( IDirectFBFont *thiz )\n{\n     IDirectFBFont_data *data = thiz->priv;\n\n     D_DEBUG_AT( Font, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     dfb_font_destroy( data->font );\n\n     if (data->content) {\n          switch (data->content_type) {\n               case IDFBFONT_CONTEXT_CONTENT_TYPE_MALLOCED:\n                    D_FREE( data->content );\n                    break;\n\n               case IDFBFONT_CONTEXT_CONTENT_TYPE_MAPPED:\n                    direct_file_unmap( data->content, data->content_size );\n                    break;\n\n               case IDFBFONT_CONTEXT_CONTENT_TYPE_MEMORY:\n                    break;\n\n               default:\n                    D_BUG( \"unexpected content type %u\", data->content_type );\n          }\n     }\n\n     DIRECT_DEALLOCATE_INTERFACE( thiz );\n}\n\nstatic DirectResult\nIDirectFBFont_AddRef( IDirectFBFont *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     D_DEBUG_AT( Font, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref++;\n\n     return DFB_OK;\n}\n\nstatic DirectResult\nIDirectFBFont_Release( IDirectFBFont *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     D_DEBUG_AT( Font, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->ref == 0)\n          IDirectFBFont_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBFont_GetAscender( IDirectFBFont *thiz,\n                           int           *ret_ascender )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     D_DEBUG_AT( Font, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_ascender)\n          return DFB_INVARG;\n\n     *ret_ascender = data->font->ascender;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBFont_GetDescender( IDirectFBFont *thiz,\n                            int           *ret_descender )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     D_DEBUG_AT( Font, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_descender)\n          return DFB_INVARG;\n\n     *ret_descender = data->font->descender;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBFont_GetHeight( IDirectFBFont *thiz,\n                         int           *ret_height )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     D_DEBUG_AT( Font, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_height)\n          return DFB_INVARG;\n\n     *ret_height = data->font->height;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBFont_GetMaxAdvance( IDirectFBFont *thiz,\n                             int           *ret_maxadvance )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     D_DEBUG_AT( Font, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_maxadvance)\n          return DFB_INVARG;\n\n     *ret_maxadvance = data->font->maxadvance;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBFont_GetKerning( IDirectFBFont *thiz,\n                          unsigned int   prev,\n                          unsigned int   current,\n                          int           *ret_kern_x,\n                          int           *ret_kern_y )\n{\n     DFBResult    ret;\n     int          x = 0, y = 0;\n     unsigned int prev_index, current_index;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     D_DEBUG_AT( Font, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_kern_x && !ret_kern_y)\n          return DFB_INVARG;\n\n     dfb_font_lock( data->font );\n\n     if (data->font->GetKerning) {\n          ret = dfb_font_decode_character( data->font, data->encoding, prev, &prev_index );\n          if (ret)\n               goto error;\n\n          ret = dfb_font_decode_character( data->font, data->encoding, current, &current_index );\n          if (ret)\n               goto error;\n\n          ret = data->font->GetKerning( data->font, prev_index, current_index, &x, &y );\n          if (ret)\n               goto error;\n     }\n\n     dfb_font_unlock( data->font );\n\n     if (ret_kern_x)\n          *ret_kern_x = x;\n\n     if (ret_kern_y)\n          *ret_kern_y = y;\n\n     return DFB_OK;\n\nerror:\n     dfb_font_unlock( data->font );\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBFont_GetStringWidth( IDirectFBFont *thiz,\n                              const char    *text,\n                              int            bytes,\n                              int           *ret_width )\n{\n     DFBResult ret;\n     int       xsize = 0;\n     int       ysize = 0;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     D_DEBUG_AT( Font, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!text || !ret_width)\n          return DFB_INVARG;\n\n     if (bytes < 0)\n          bytes = strlen( text );\n\n     if (bytes > 0) {\n          int          i, num;\n          unsigned int prev = 0;\n          unsigned int indices[bytes];\n\n          dfb_font_lock( data->font );\n\n          /* Decode string to character indices. */\n          ret = dfb_font_decode_text( data->font, data->encoding, text, bytes, indices, &num );\n          if (ret) {\n               dfb_font_unlock( data->font );\n               return ret;\n          }\n\n          /* Calculate string width. */\n          for (i = 0; i < num; i++) {\n               unsigned int   current = indices[i];\n               CoreGlyphData *glyph;\n\n               if (dfb_font_get_glyph_data( data->font, current, 0, &glyph ) == DFB_OK) {\n                    int kx, ky;\n\n                    xsize += glyph->xadvance;\n                    ysize += glyph->yadvance;\n\n                    if (prev && data->font->GetKerning &&\n                        data->font->GetKerning( data->font, prev, current, &kx, &ky ) == DFB_OK) {\n                         xsize += kx << 8;\n                         ysize += ky << 8;\n                    }\n               }\n\n               prev = current;\n          }\n\n          dfb_font_unlock( data->font );\n     }\n\n     if (!ysize) {\n          *ret_width = xsize >> 8;\n     }\n     else if (!xsize) {\n          *ret_width = ysize >> 8;\n     }\n     else {\n          *ret_width = sqrt16( xsize * xsize + ysize * ysize ) / 4096.0f;\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBFont_GetStringExtents( IDirectFBFont *thiz,\n                                const char    *text,\n                                int            bytes,\n                                DFBRectangle  *ret_logical_rect,\n                                DFBRectangle  *ret_ink_rect )\n{\n     DFBResult ret;\n     int       xbaseline = 0;\n     int       ybaseline = 0;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     D_DEBUG_AT( Font, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!text)\n          return DFB_INVARG;\n\n     if (!ret_logical_rect && !ret_ink_rect)\n          return DFB_INVARG;\n\n     if (bytes < 0)\n          bytes = strlen( text );\n\n     if (ret_ink_rect)\n          memset( ret_ink_rect, 0, sizeof(DFBRectangle) );\n\n     dfb_font_lock( data->font );\n\n     if (bytes > 0) {\n          int          i, num;\n          unsigned int prev  = 0;\n          unsigned int indices[bytes];\n\n          /* Decode string to character indices. */\n          ret = dfb_font_decode_text( data->font, data->encoding, text, bytes, indices, &num );\n          if (ret) {\n               dfb_font_unlock( data->font );\n               return ret;\n          }\n\n          for (i = 0; i < num; i++) {\n               unsigned int   current = indices[i];\n               CoreGlyphData *glyph;\n\n               if (dfb_font_get_glyph_data( data->font, current, 0, &glyph ) == DFB_OK) {\n                    int kx, ky;\n\n                    if (prev && data->font->GetKerning &&\n                        data->font->GetKerning( data->font, prev, current, &kx, &ky ) == DFB_OK) {\n                         xbaseline += kx << 8;\n                         ybaseline += ky << 8;\n                    }\n\n                    if (ret_ink_rect) {\n                         DFBRectangle glyph_rect = { xbaseline + (glyph->left << 8), ybaseline + (glyph->top << 8),\n                                                     glyph->width << 8,              glyph->height << 8 };\n\n                         dfb_rectangle_union( ret_ink_rect, &glyph_rect );\n                    }\n\n                    xbaseline += glyph->xadvance;\n                    ybaseline += glyph->yadvance;\n               }\n\n               prev = current;\n          }\n     }\n\n     if (ret_logical_rect) {\n          /* We already have the text baseline vector in (xbaseline,ybaseline).\n             Find the ascender and descender vectors. */\n          int xascender =  data->font->ascender * data->font->up_unit_x;\n          int yascender =  data->font->ascender * data->font->up_unit_y;\n          int xdescender = data->font->descender * data->font->up_unit_x;\n          int ydescender = data->font->descender * data->font->up_unit_y;\n\n          /* Now find top/bottom and left/right points relative to the text. */\n          int top_left_x     = xascender;\n          int top_left_y     = yascender;\n          int bottom_left_x  = xdescender;\n          int bottom_left_y  = ydescender;\n          int top_right_x    = top_left_x    + (xbaseline >> 8);\n          int top_right_y    = top_left_y    + (ybaseline >> 8);\n          int bottom_right_x = bottom_left_x + (xbaseline >> 8);\n          int bottom_right_y = bottom_left_y + (ybaseline >> 8);\n\n          /* The logical rectangle is the bounding-box of these points. */\n          #define MIN4(a,b,c,d) (MIN( MIN( a, b ), MIN( c, d ) ))\n          #define MAX4(a,b,c,d) (MAX( MAX( a, b ), MAX( c, d ) ))\n          ret_logical_rect->x = MIN4( top_left_x, bottom_left_x, top_right_x, bottom_right_x );\n          ret_logical_rect->y = MIN4( top_left_y, bottom_left_y, top_right_y, bottom_right_y );\n          ret_logical_rect->w = MAX4( top_left_x, bottom_left_x, top_right_x, bottom_right_x ) - ret_logical_rect->x;\n          ret_logical_rect->h = MAX4( top_left_y, bottom_left_y, top_right_y, bottom_right_y ) - ret_logical_rect->y;\n     }\n\n     if (ret_ink_rect) {\n          if (ret_ink_rect->w < 0) {\n               ret_ink_rect->x +=  ret_ink_rect->w;\n               ret_ink_rect->w  = -ret_ink_rect->w;\n          }\n          ret_ink_rect->x += (data->font->ascender * data->font->up_unit_x) / 256.0f;\n          ret_ink_rect->y += (data->font->ascender * data->font->up_unit_y) / 256.0f;\n\n          ret_ink_rect->x >>= 8;\n          ret_ink_rect->y >>= 8;\n          ret_ink_rect->w >>= 8;\n          ret_ink_rect->h >>= 8;\n     }\n\n     dfb_font_unlock( data->font );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBFont_GetGlyphExtents( IDirectFBFont *thiz,\n                               unsigned int   character,\n                               DFBRectangle  *ret_rect,\n                               int           *ret_advance )\n{\n     DFBResult      ret;\n     CoreGlyphData *glyph;\n     unsigned int   index;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     D_DEBUG_AT( Font, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_rect && !ret_advance)\n          return DFB_INVARG;\n\n     dfb_font_lock( data->font );\n\n     ret = dfb_font_decode_character( data->font, data->encoding, character, &index );\n     if (ret) {\n          dfb_font_unlock( data->font );\n          return ret;\n     }\n\n     if (dfb_font_get_glyph_data( data->font, index, 0, &glyph ) != DFB_OK) {\n          if (ret_rect)\n               ret_rect->x = ret_rect->y = ret_rect->w = ret_rect->h = 0;\n\n          if (ret_advance)\n               *ret_advance = 0;\n     }\n     else {\n          if (ret_rect) {\n               ret_rect->x = glyph->left;\n               ret_rect->y = glyph->top - data->font->ascender;\n               ret_rect->w = glyph->width;\n               ret_rect->h = glyph->height;\n          }\n\n          if (ret_advance)\n               *ret_advance = glyph->xadvance >> 8;\n     }\n\n     dfb_font_unlock( data->font );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBFont_GetStringBreak( IDirectFBFont  *thiz,\n                              const char     *text,\n                              int             bytes,\n                              int             max_width,\n                              int            *ret_width,\n                              int            *ret_str_length,\n                              const char    **ret_next_line )\n{\n     DFBResult      ret;\n     const u8      *string;\n     const u8      *last;\n     const u8      *end;\n     CoreGlyphData *glyph;\n     int            kern_x;\n     int            kern_y;\n     int            length = 0;\n     int            xsize = 0;\n     int            ysize = 0;\n     int            width = 0;\n     unichar        current;\n     unsigned int   index;\n     unsigned int   prev  = 0;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     if (!text || !ret_next_line || !ret_str_length || !ret_width)\n          return DFB_INVARG;\n\n     if (data->encoding != DTEID_UTF8)\n          return DFB_UNSUPPORTED;\n\n     if (bytes < 0)\n          bytes = strlen( text );\n\n     if (!bytes) {\n          *ret_next_line  = NULL;\n          *ret_str_length = 0;\n          *ret_width      = 0;\n\n          return DFB_OK;\n     }\n\n     string = (const u8*) text;\n     end    = string + bytes;\n\n     *ret_next_line = NULL;\n\n     dfb_font_lock( data->font );\n\n     do {\n          *ret_width = width >> 8;\n\n          current = DIRECT_UTF8_GET_CHAR( string );\n\n          last    = string;\n          string += DIRECT_UTF8_SKIP( string[0] );\n\n          if (current == ' ' || current == 0x0a) {\n               *ret_next_line  = (const char*) string;\n               *ret_str_length = length;\n               *ret_width      = width >> 8;\n          }\n\n          length++;\n\n          ret = dfb_font_decode_character( data->font, data->encoding, current, &index );\n          if (ret)\n               continue;\n\n          ret = dfb_font_get_glyph_data( data->font, index, 0, &glyph );\n          if (ret)\n               continue;\n\n          xsize += glyph->xadvance;\n          ysize += glyph->yadvance;\n\n          if (prev && data->font->GetKerning &&\n              data->font->GetKerning( data->font, prev, index, &kern_x, NULL ) == DFB_OK)\n               width += kern_x << 8;\n\n          if (prev && data->font->GetKerning &&\n              data->font->GetKerning( data->font, prev, index, &kern_x, &kern_y) == DFB_OK) {\n               xsize += kern_x << 8;\n               ysize += kern_y << 8;\n          }\n\n          if (!ysize) {\n               width = xsize;\n          }\n          else if (!xsize) {\n               width = ysize;\n          }\n          else {\n               width = sqrt16( xsize * xsize + ysize * ysize ) / 256.0f;\n          }\n\n          prev = index;\n     } while ((width >> 8) < max_width && string < end && current != 0x0a);\n\n     dfb_font_unlock( data->font );\n\n     if ((width >> 8) < max_width && string >= end) {\n          *ret_next_line  = NULL;\n          *ret_str_length = length;\n          *ret_width      = width >> 8;\n\n          return DFB_OK;\n     }\n\n     if (*ret_next_line == NULL) {\n          if (length == 1) {\n               *ret_str_length = length;\n               *ret_next_line  = (const char*) string;\n               *ret_width      = width >> 8;\n          }\n          else {\n               *ret_str_length = length - 1;\n               *ret_next_line  = (const char*) last;\n          }\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBFont_SetEncoding( IDirectFBFont     *thiz,\n                           DFBTextEncodingID  encoding )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     D_DEBUG_AT( Font, \"%s( %p, %u )\\n\", __FUNCTION__, thiz, encoding );\n\n     if (encoding > data->font->last_encoding)\n          return DFB_IDNOTFOUND;\n\n     data->encoding = encoding;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBFont_EnumEncodings( IDirectFBFont           *thiz,\n                             DFBTextEncodingCallback  callback,\n                             void                    *callbackdata )\n{\n     int i;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     if (!callback)\n          return DFB_INVARG;\n\n     D_DEBUG_AT( Font, \"%s( %p, %p, %p )\\n\", __FUNCTION__, thiz, callback, callbackdata );\n\n     if (callback( DTEID_UTF8, \"UTF8\", callbackdata ) == DFENUM_OK) {\n          for (i = DTEID_OTHER; i <= data->font->last_encoding; i++) {\n               if (callback( i, data->font->encodings[i]->name, callbackdata ) != DFENUM_OK)\n                    break;\n          }\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBFont_FindEncoding( IDirectFBFont     *thiz,\n                            const char        *name,\n                            DFBTextEncodingID *ret_encoding )\n{\n     int i;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     if (!name || !ret_encoding)\n          return DFB_INVARG;\n\n     D_DEBUG_AT( Font, \"%s( %p, '%s', %p )\\n\", __FUNCTION__, thiz, name, ret_encoding );\n\n     if (!strcasecmp( name, \"UTF8\" )) {\n          *ret_encoding = DTEID_UTF8;\n          return DFB_OK;\n     }\n\n     for (i = DTEID_OTHER; i <= data->font->last_encoding; i++) {\n          if (!strcasecmp( name, data->font->encodings[i]->name )) {\n               *ret_encoding = i;\n               return DFB_OK;\n          }\n     }\n\n     return DFB_IDNOTFOUND;\n}\n\nstatic DFBResult\nIDirectFBFont_Dispose( IDirectFBFont *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     D_DEBUG_AT( Font, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return dfb_font_dispose( data->font );\n}\n\nstatic DFBResult\nIDirectFBFont_GetLineSpacingVector( IDirectFBFont *thiz,\n                                    int           *ret_xspacing,\n                                    int           *ret_yspacing )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     D_DEBUG_AT( Font, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_xspacing && !ret_yspacing)\n          return DFB_INVARG;\n\n     if (ret_xspacing) {\n          *ret_xspacing = - data->font->height * data->font->up_unit_x;\n     }\n\n     if (ret_yspacing) {\n          *ret_yspacing = - data->font->height * data->font->up_unit_y;\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBFont_GetGlyphExtentsXY( IDirectFBFont *thiz,\n                                 unsigned int   character,\n                                 DFBRectangle  *ret_rect,\n                                 int           *ret_xadvance,\n                                 int           *ret_yadvance )\n{\n     DFBResult      ret;\n     CoreGlyphData *glyph;\n     unsigned int   index;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     D_DEBUG_AT( Font, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_rect && !ret_xadvance && !ret_yadvance)\n          return DFB_INVARG;\n\n     dfb_font_lock( data->font );\n\n     ret = dfb_font_decode_character( data->font, data->encoding, character, &index );\n     if (ret) {\n          dfb_font_unlock( data->font );\n          return ret;\n     }\n\n     if (dfb_font_get_glyph_data( data->font, index, 0, &glyph ) != DFB_OK) {\n          if (ret_rect)\n               ret_rect->x = ret_rect->y = ret_rect->w = ret_rect->h = 0;\n\n          if (ret_xadvance)\n               *ret_xadvance = 0;\n\n          if (ret_yadvance)\n               *ret_yadvance = 0;\n     }\n     else {\n          if (ret_rect) {\n               ret_rect->x = glyph->left + data->font->ascender * data->font->up_unit_x;\n               ret_rect->y = glyph->top  + data->font->ascender * data->font->up_unit_y;\n               ret_rect->w = glyph->width;\n               ret_rect->h = glyph->height;\n          }\n\n          if (ret_xadvance)\n               *ret_xadvance = glyph->xadvance;\n\n          if (ret_yadvance)\n               *ret_yadvance = glyph->yadvance;\n     }\n\n     dfb_font_unlock( data->font );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBFont_GetUnderline( IDirectFBFont *thiz,\n                            int           *ret_underline_position,\n                            int           *ret_underline_thickness )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     D_DEBUG_AT( Font, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (ret_underline_position)\n          *ret_underline_position = data->font->underline_position;\n\n     if (ret_underline_thickness)\n          *ret_underline_thickness = data->font->underline_thickness;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBFont_GetDescription( IDirectFBFont      *thiz,\n                              DFBFontDescription *ret_desc )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBFont )\n\n     D_DEBUG_AT( Font, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!ret_desc)\n          return DFB_INVARG;\n\n     *ret_desc = data->font->description;\n\n     return DFB_OK;\n}\n\nDFBResult\nIDirectFBFont_Construct( IDirectFBFont *thiz, CoreFont *font )\n{\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBFont )\n\n     D_DEBUG_AT( Font, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref  = 1;\n     data->font = font;\n\n     thiz->AddRef               = IDirectFBFont_AddRef;\n     thiz->Release              = IDirectFBFont_Release;\n     thiz->GetAscender          = IDirectFBFont_GetAscender;\n     thiz->GetDescender         = IDirectFBFont_GetDescender;\n     thiz->GetHeight            = IDirectFBFont_GetHeight;\n     thiz->GetMaxAdvance        = IDirectFBFont_GetMaxAdvance;\n     thiz->GetKerning           = IDirectFBFont_GetKerning;\n     thiz->GetStringWidth       = IDirectFBFont_GetStringWidth;\n     thiz->GetStringExtents     = IDirectFBFont_GetStringExtents;\n     thiz->GetGlyphExtents      = IDirectFBFont_GetGlyphExtents;\n     thiz->GetStringBreak       = IDirectFBFont_GetStringBreak;\n     thiz->SetEncoding          = IDirectFBFont_SetEncoding;\n     thiz->EnumEncodings        = IDirectFBFont_EnumEncodings;\n     thiz->FindEncoding         = IDirectFBFont_FindEncoding;\n     thiz->Dispose              = IDirectFBFont_Dispose;\n     thiz->GetLineSpacingVector = IDirectFBFont_GetLineSpacingVector;\n     thiz->GetGlyphExtentsXY    = IDirectFBFont_GetGlyphExtentsXY;\n     thiz->GetUnderline         = IDirectFBFont_GetUnderline;\n     thiz->GetDescription       = IDirectFBFont_GetDescription;\n\n     return DFB_OK;\n}\n\nstatic void\nunmap_or_free( IDirectFBFont_ProbeContext *ctx )\n{\n     if (ctx->content) {\n          switch (ctx->content_type) {\n               case IDFBFONT_CONTEXT_CONTENT_TYPE_MALLOCED:\n                    D_FREE( ctx->content );\n                    break;\n\n               case IDFBFONT_CONTEXT_CONTENT_TYPE_MAPPED:\n                    direct_file_unmap( ctx->content, ctx->content_size );\n                    break;\n\n               case IDFBFONT_CONTEXT_CONTENT_TYPE_MEMORY:\n                    break;\n\n               default:\n                    D_BUG( \"unexpected content type %u\", ctx->content_type );\n          }\n\n          ctx->content = NULL;\n     }\n}\n\nDFBResult\nIDirectFBFont_CreateFromBuffer( IDirectFBDataBuffer       *buffer,\n                                CoreDFB                   *core,\n                                const DFBFontDescription  *desc,\n                                IDirectFBFont            **ret_interface )\n{\n     DFBResult                   ret;\n     DirectInterfaceFuncs       *funcs = NULL;\n     IDirectFBDataBuffer_data   *buffer_data;\n     IDirectFBFont              *iface;\n     IDirectFBFont_ProbeContext  ctx = { NULL, NULL, 0, IDFBFONT_CONTEXT_CONTENT_TYPE_UNKNOWN };\n     IDirectFBFont_data         *data;\n\n     D_DEBUG_AT( Font, \"%s( %p )\\n\", __FUNCTION__, buffer );\n\n     /* Get the private information of the data buffer. */\n     buffer_data = buffer->priv;\n     if (!buffer_data)\n          return DFB_DEAD;\n\n     /* Provide a fallback for fonts without data buffer support. */\n     ctx.filename = buffer_data->filename;\n\n     if (buffer_data->buffer) {\n          ctx.content      = buffer_data->buffer;\n          ctx.content_size = buffer_data->length;\n          ctx.content_type = IDFBFONT_CONTEXT_CONTENT_TYPE_MEMORY;\n     }\n     else if (buffer_data->filename) {\n          DirectFile      fd;\n          DirectFileInfo  info;\n          void           *ptr;\n\n          /* Open the file. */\n          ret = direct_file_open( &fd, ctx.filename, O_RDONLY, 0 );\n          if (ret) {\n               D_DERROR( ret, \"IDirectFBFont: Could not open '%s'\\n\", ctx.filename );\n               return ret;\n          }\n\n          /* Query file size. */\n          ret = direct_file_get_info( &fd, &info );\n          if (ret) {\n               D_DERROR( ret, \"IDirectFBFont: Could not query info about '%s'\\n\", ctx.filename );\n               direct_file_close( &fd );\n               return ret;\n          }\n\n          /* Memory-mapped file. */\n          ret = direct_file_map( &fd, NULL, 0, info.size, DFP_READ, &ptr );\n          if (ret) {\n               D_DERROR( ret, \"IDirectFBFont: Could not mmap '%s'\\n\", ctx.filename );\n               direct_file_close( &fd );\n               return ret;\n          }\n\n          ctx.content      = ptr;\n          ctx.content_size = info.size;\n          ctx.content_type = IDFBFONT_CONTEXT_CONTENT_TYPE_MAPPED;\n\n          direct_file_close( &fd );\n     }\n     else {\n          ctx.content_size = 0;\n          ctx.content_type = IDFBFONT_CONTEXT_CONTENT_TYPE_MALLOCED;\n\n          while (1) {\n               unsigned int bytes;\n\n               ctx.content = D_REALLOC( ctx.content, ctx.content_size + 4096 );\n               if (!ctx.content) {\n                    ret = D_OOM();\n                    return ret;\n               }\n\n               buffer->WaitForData( buffer, 4096 );\n               if (buffer->GetData( buffer, 4096, ctx.content + ctx.content_size, &bytes ))\n                    break;\n\n               ctx.content_size += bytes;\n          }\n     }\n\n     D_ASSERT( ctx.content_type != IDFBFONT_CONTEXT_CONTENT_TYPE_UNKNOWN );\n\n     /* Find a suitable implementation. */\n     ret = DirectGetInterface( &funcs, \"IDirectFBFont\", NULL, DirectProbeInterface, &ctx );\n     if (ret) {\n          unmap_or_free( &ctx );\n          return ret;\n     }\n\n     DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBFont );\n\n     /* Construct the interface. */\n     ret = funcs->Construct( iface, core, &ctx, desc );\n     if (ret) {\n          DIRECT_DEALLOCATE_INTERFACE( iface );\n          unmap_or_free( &ctx );\n          return ret;\n     }\n\n     /* Store content pointer informations for deletion. */\n     data = iface->priv;\n     data->content      = ctx.content;\n     data->content_size = ctx.content_size;\n     data->content_type = ctx.content_type;\n\n     *ret_interface = iface;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/media/idirectfbfont.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __MEDIA__IDIRECTFBFONT_H__\n#define __MEDIA__IDIRECTFBFONT_H__\n\n#include <core/coretypes.h>\n\n/*\n * type of probing context\n */\ntypedef enum {\n     IDFBFONT_CONTEXT_CONTENT_TYPE_UNKNOWN  = 0x00000000,\n\n     IDFBFONT_CONTEXT_CONTENT_TYPE_MALLOCED = 0x00000001,\n     IDFBFONT_CONTEXT_CONTENT_TYPE_MAPPED   = 0x00000002,\n     IDFBFONT_CONTEXT_CONTENT_TYPE_MEMORY   = 0x00000003\n} IDirectFBFont_ProbeContextContentType;\n\n/*\n * probing context\n */\ntypedef struct {\n     const char                            *filename;\n     unsigned char                         *content;\n     unsigned int                           content_size;\n     IDirectFBFont_ProbeContextContentType  content_type;\n} IDirectFBFont_ProbeContext;\n\n/*\n * private data struct of IDirectFBFont\n */\ntypedef struct {\n     int                                    ref;          /* reference counter */\n\n     CoreFont                              *font;         /* the font object */\n\n     unsigned char                         *content;\n     unsigned int                           content_size;\n     IDirectFBFont_ProbeContextContentType  content_type;\n     DFBTextEncodingID                      encoding;\n} IDirectFBFont_data;\n\n/*\n * common code to initialize interface struct and private data\n */\nDFBResult IDirectFBFont_Construct       ( IDirectFBFont             *thiz,\n                                          CoreFont                  *font );\n\n/*\n * common code to destroy font and free private data\n */\nvoid      IDirectFBFont_Destruct        ( IDirectFBFont             *thiz );\n\n/*\n * create (probing) the font\n */\nDFBResult IDirectFBFont_CreateFromBuffer( IDirectFBDataBuffer       *buffer,\n                                          CoreDFB                   *core,\n                                          const DFBFontDescription  *desc,\n                                          IDirectFBFont            **ret_interface );\n\n#endif\n"
  },
  {
    "path": "src/media/idirectfbimageprovider.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <media/idirectfbdatabuffer.h>\n#include <media/idirectfbimageprovider.h>\n\nD_DEBUG_DOMAIN( ImageProvider, \"IDirectFBImageProvider\", \"IDirectFBImageProvider Interface\" );\n\n/**********************************************************************************************************************/\n\nstatic DirectResult\nIDirectFBImageProvider_AddRef( IDirectFBImageProvider *thiz )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DirectResult\nIDirectFBImageProvider_Release( IDirectFBImageProvider *thiz )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBImageProvider_GetSurfaceDescription( IDirectFBImageProvider *thiz,\n                                              DFBSurfaceDescription  *ret_desc )\n{\n     if (!ret_desc)\n          return DFB_INVARG;\n\n     ret_desc->flags = DSDESC_NONE;\n\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBImageProvider_GetImageDescription( IDirectFBImageProvider *thiz,\n                                            DFBImageDescription    *ret_desc )\n{\n     if (!ret_desc)\n          return DFB_INVARG;\n\n     ret_desc->caps = DICAPS_NONE;\n\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBImageProvider_RenderTo( IDirectFBImageProvider *thiz,\n                                 IDirectFBSurface       *destination,\n                                 const DFBRectangle     *dest_rect )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBImageProvider_SetRenderCallback( IDirectFBImageProvider *thiz,\n                                          DIRenderCallback        callback,\n                                          void                   *ctx )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBImageProvider_SetRenderFlags( IDirectFBImageProvider *thiz,\n                                       DIRenderFlags           flags )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic void\nIDirectFBImageProvider_Construct( IDirectFBImageProvider *thiz )\n{\n     D_DEBUG_AT( ImageProvider, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     thiz->AddRef                = IDirectFBImageProvider_AddRef;\n     thiz->Release               = IDirectFBImageProvider_Release;\n     thiz->GetSurfaceDescription = IDirectFBImageProvider_GetSurfaceDescription;\n     thiz->GetImageDescription   = IDirectFBImageProvider_GetImageDescription;\n     thiz->RenderTo              = IDirectFBImageProvider_RenderTo;\n     thiz->SetRenderCallback     = IDirectFBImageProvider_SetRenderCallback;\n     thiz->SetRenderFlags        = IDirectFBImageProvider_SetRenderFlags;\n}\n\nDFBResult\nIDirectFBImageProvider_CreateFromBuffer( IDirectFBDataBuffer     *buffer,\n                                         CoreDFB                 *core,\n                                         IDirectFB               *idirectfb,\n                                         IDirectFBImageProvider **ret_interface )\n{\n     DFBResult                            ret;\n     DirectInterfaceFuncs                *funcs = NULL;\n     IDirectFBDataBuffer_data            *buffer_data;\n     IDirectFBImageProvider              *iface;\n     IDirectFBImageProvider_ProbeContext  ctx;\n\n     D_DEBUG_AT( ImageProvider, \"%s( %p )\\n\", __FUNCTION__, buffer );\n\n     /* Get the private information of the data buffer. */\n     buffer_data = buffer->priv;\n     if (!buffer_data)\n          return DFB_DEAD;\n\n     /* Clear probe context header. */\n     memset( ctx.header, 0, sizeof(ctx.header) );\n\n     /* Provide a fallback for image providers without data buffer support. */\n     ctx.filename = buffer_data->filename;\n\n     /* Wait until 32 bytes are available. */\n     ret = buffer->WaitForData( buffer, sizeof(ctx.header) );\n     if (ret)\n          return ret;\n\n     /* Read the first 32 bytes. */\n     buffer->PeekData( buffer, sizeof(ctx.header), 0, ctx.header, NULL );\n\n     /* Find a suitable implementation. */\n     ret = DirectGetInterface( &funcs, \"IDirectFBImageProvider\", NULL, DirectProbeInterface, &ctx );\n     if (ret)\n          return ret;\n\n     DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBImageProvider );\n\n     /* Initialize interface pointers. */\n     IDirectFBImageProvider_Construct( iface );\n\n     /* Construct the interface. */\n     ret = funcs->Construct( iface, buffer, core, idirectfb );\n     if (ret)\n          return ret;\n\n     *ret_interface = iface;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/media/idirectfbimageprovider.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __MEDIA__IDIRECTFBIMAGEPROVIDER_H__\n#define __MEDIA__IDIRECTFBIMAGEPROVIDER_H__\n\n#include <core/coretypes.h>\n\n/*\n * probing context\n */\ntypedef struct {\n     unsigned char  header[32];\n     const char    *filename;\n} IDirectFBImageProvider_ProbeContext;\n\n/*\n * create (probing) the image provider\n */\nDFBResult IDirectFBImageProvider_CreateFromBuffer( IDirectFBDataBuffer     *buffer,\n                                                   CoreDFB                 *core,\n                                                   IDirectFB               *idirectfb,\n                                                   IDirectFBImageProvider **ret_interface );\n\n#endif\n"
  },
  {
    "path": "src/media/idirectfbvideoprovider.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <media/idirectfbdatabuffer.h>\n#include <media/idirectfbvideoprovider.h>\n\nD_DEBUG_DOMAIN( VideoProvider, \"IDirectFBVideoProvider\", \"IDirectFBVideoProvider Interface\" );\n\n/**********************************************************************************************************************/\n\nstatic DirectResult\nIDirectFBVideoProvider_AddRef( IDirectFBVideoProvider *thiz )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DirectResult\nIDirectFBVideoProvider_Release( IDirectFBVideoProvider *thiz )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_GetCapabilities( IDirectFBVideoProvider       *thiz,\n                                        DFBVideoProviderCapabilities *ret_caps )\n{\n     if (!ret_caps)\n          return DFB_INVARG;\n\n     *ret_caps = DVCAPS_BASIC;\n\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_GetSurfaceDescription( IDirectFBVideoProvider *thiz,\n                                              DFBSurfaceDescription  *ret_desc )\n{\n     if (!ret_desc)\n          return DFB_INVARG;\n\n     ret_desc->flags = DSDESC_NONE;\n\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_GetStreamDescription( IDirectFBVideoProvider *thiz,\n                                             DFBStreamDescription   *ret_desc )\n{\n     if (!ret_desc)\n          return DFB_INVARG;\n\n     memset( ret_desc, 0, sizeof(DFBStreamDescription) );\n\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_PlayTo( IDirectFBVideoProvider *thiz,\n                               IDirectFBSurface       *destination,\n                               const DFBRectangle     *dest_rect,\n                               DVFrameCallback         callback,\n                               void                   *ctx )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_Stop( IDirectFBVideoProvider *thiz )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_GetStatus( IDirectFBVideoProvider *thiz,\n                                  DFBVideoProviderStatus *ret_status )\n{\n     if (!ret_status)\n          return DFB_INVARG;\n\n     *ret_status = DVSTATE_UNKNOWN;\n\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_SeekTo( IDirectFBVideoProvider *thiz,\n                               double                  seconds )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_GetPos( IDirectFBVideoProvider *thiz,\n                               double                 *ret_seconds )\n{\n     if (!ret_seconds)\n          return DFB_INVARG;\n\n     *ret_seconds = 0.0;\n\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_GetLength( IDirectFBVideoProvider *thiz,\n                                  double                 *ret_seconds )\n{\n     if (!ret_seconds)\n          return DFB_INVARG;\n\n     *ret_seconds = 0.0;\n\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_GetColorAdjustment( IDirectFBVideoProvider *thiz,\n                                           DFBColorAdjustment     *ret_adj )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_SetColorAdjustment( IDirectFBVideoProvider   *thiz,\n                                           const DFBColorAdjustment *adj )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_SendEvent( IDirectFBVideoProvider *thiz,\n                                  const DFBEvent         *event )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_SetPlaybackFlags( IDirectFBVideoProvider        *thiz,\n                                         DFBVideoProviderPlaybackFlags  flags )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_SetSpeed( IDirectFBVideoProvider *thiz,\n                                 double                  multiplier )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_GetSpeed( IDirectFBVideoProvider *thiz,\n                                 double                 *ret_multiplier )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_SetVolume( IDirectFBVideoProvider *thiz,\n                                  float                   level )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_GetVolume( IDirectFBVideoProvider *thiz,\n                                  float                  *ret_level )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_CreateEventBuffer( IDirectFBVideoProvider *thiz,\n                                          IDirectFBEventBuffer   **ret_interface )\n{\n    return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_AttachEventBuffer( IDirectFBVideoProvider *thiz,\n                                          IDirectFBEventBuffer   *buffer )\n{\n    return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_EnableEvents(IDirectFBVideoProvider    *thiz,\n                                    DFBVideoProviderEventType  mask )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DisableEvents(IDirectFBVideoProvider    *thiz,\n                                     DFBVideoProviderEventType  mask )\n{\n    return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_DetachEventBuffer( IDirectFBVideoProvider *thiz,\n                                          IDirectFBEventBuffer   *buffer )\n{\n    return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_GetBufferOccupancy( IDirectFBVideoProvider *thiz,\n                                           DFBBufferOccupancy     *ret_occ )\n{\n     if (!ret_occ)\n          return DFB_INVARG;\n\n     memset( ret_occ, 0, sizeof(DFBBufferOccupancy) );\n\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_SetBufferThresholds( IDirectFBVideoProvider *thiz,\n                                            DFBBufferThresholds    thresh )\n{\n    return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_GetBufferThresholds( IDirectFBVideoProvider *thiz,\n                                            DFBBufferThresholds    *ret_thresh )\n{\n     if (!ret_thresh)\n          return DFB_INVARG;\n\n     memset( ret_thresh, 0, sizeof(DFBBufferThresholds) );\n\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nIDirectFBVideoProvider_SetDestination( IDirectFBVideoProvider *thiz,\n                                       IDirectFBSurface       *destination,\n                                       const DFBRectangle     *dest_rect )\n{\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic void\nIDirectFBVideoProvider_Construct( IDirectFBVideoProvider *thiz )\n{\n     D_DEBUG_AT( VideoProvider, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     thiz->AddRef                = IDirectFBVideoProvider_AddRef;\n     thiz->Release               = IDirectFBVideoProvider_Release;\n     thiz->GetCapabilities       = IDirectFBVideoProvider_GetCapabilities;\n     thiz->GetSurfaceDescription = IDirectFBVideoProvider_GetSurfaceDescription;\n     thiz->GetStreamDescription  = IDirectFBVideoProvider_GetStreamDescription;\n     thiz->PlayTo                = IDirectFBVideoProvider_PlayTo;\n     thiz->Stop                  = IDirectFBVideoProvider_Stop;\n     thiz->GetStatus             = IDirectFBVideoProvider_GetStatus;\n     thiz->SeekTo                = IDirectFBVideoProvider_SeekTo;\n     thiz->GetPos                = IDirectFBVideoProvider_GetPos;\n     thiz->GetLength             = IDirectFBVideoProvider_GetLength;\n     thiz->GetColorAdjustment    = IDirectFBVideoProvider_GetColorAdjustment;\n     thiz->SetColorAdjustment    = IDirectFBVideoProvider_SetColorAdjustment;\n     thiz->SendEvent             = IDirectFBVideoProvider_SendEvent;\n     thiz->SetPlaybackFlags      = IDirectFBVideoProvider_SetPlaybackFlags;\n     thiz->SetSpeed              = IDirectFBVideoProvider_SetSpeed;\n     thiz->GetSpeed              = IDirectFBVideoProvider_GetSpeed;\n     thiz->SetVolume             = IDirectFBVideoProvider_SetVolume;\n     thiz->GetVolume             = IDirectFBVideoProvider_GetVolume;\n     thiz->CreateEventBuffer     = IDirectFBVideoProvider_CreateEventBuffer;\n     thiz->AttachEventBuffer     = IDirectFBVideoProvider_AttachEventBuffer;\n     thiz->EnableEvents          = IDirectFBVideoProvider_EnableEvents;\n     thiz->DisableEvents         = IDirectFBVideoProvider_DisableEvents;\n     thiz->DetachEventBuffer     = IDirectFBVideoProvider_DetachEventBuffer;\n     thiz->GetBufferOccupancy    = IDirectFBVideoProvider_GetBufferOccupancy;\n     thiz->SetBufferThresholds   = IDirectFBVideoProvider_SetBufferThresholds;\n     thiz->GetBufferThresholds   = IDirectFBVideoProvider_GetBufferThresholds;\n     thiz->SetDestination        = IDirectFBVideoProvider_SetDestination;\n}\n\nDFBResult\nIDirectFBVideoProvider_CreateFromBuffer( IDirectFBDataBuffer     *buffer,\n                                         CoreDFB                 *core,\n                                         IDirectFB               *idirectfb,\n                                         IDirectFBVideoProvider **ret_interface )\n{\n     DFBResult                            ret;\n     DirectInterfaceFuncs                *funcs = NULL;\n     IDirectFBDataBuffer_data            *buffer_data;\n     IDirectFBVideoProvider              *iface;\n     IDirectFBVideoProvider_ProbeContext  ctx;\n\n     D_DEBUG_AT( VideoProvider, \"%s( %p )\\n\", __FUNCTION__, buffer );\n\n     /* Get the private information of the data buffer. */\n     buffer_data = buffer->priv;\n     if (!buffer_data)\n          return DFB_DEAD;\n\n     /* Clear probe context header. */\n     memset( ctx.header, 0, sizeof(ctx.header) );\n\n     /* Provide a fallback for video providers without data buffer support. */\n     ctx.filename = buffer_data->filename;\n     ctx.buffer   = buffer;\n\n     /* Wait until 64 bytes are available. */\n     ret = buffer->WaitForData( buffer, sizeof(ctx.header) );\n     if (ret)\n          return ret;\n\n     /* Read the first 64 bytes. */\n     buffer->PeekData( buffer, sizeof(ctx.header), 0, ctx.header, NULL );\n\n     /* Find a suitable implementation. */\n     ret = DirectGetInterface( &funcs, \"IDirectFBVideoProvider\", NULL, DirectProbeInterface, &ctx );\n     if (ret)\n          return ret;\n\n     DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBVideoProvider );\n\n     /* Initialize interface pointers. */\n     IDirectFBVideoProvider_Construct( iface );\n\n     /* Construct the interface. */\n     ret = funcs->Construct( iface, buffer, core, idirectfb );\n     if (ret)\n          return ret;\n\n     *ret_interface = iface;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/media/idirectfbvideoprovider.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __MEDIA__IDIRECTFBVIDEOPROVIDER_H__\n#define __MEDIA__IDIRECTFBVIDEOPROVIDER_H__\n\n#include <core/coretypes.h>\n\n/*\n * probing context\n */\ntypedef struct {\n     unsigned char        header[64];\n     const char          *filename;\n     IDirectFBDataBuffer *buffer;     /* useful if provider needs more data for probing */\n} IDirectFBVideoProvider_ProbeContext;\n\n/*\n * create (probing) the video provider\n */\nDFBResult IDirectFBVideoProvider_CreateFromBuffer( IDirectFBDataBuffer     *buffer,\n                                                   CoreDFB                 *core,\n                                                   IDirectFB               *idirectfb,\n                                                   IDirectFBVideoProvider **ret_interface );\n\n#endif\n"
  },
  {
    "path": "src/meson.build",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\nsubdir('core')\n\ndirectfb_sources = [\n  'directfb.c',\n  'directfb_result.c',\n  'idirectfb.c',\n  'init.c',\n  'core/CoreDFB_real.c',\n  'core/CoreGraphicsState_real.c',\n  'core/CoreGraphicsStateClient.c',\n  'core/CoreInputDevice_real.c',\n  'core/CoreLayer_real.c',\n  'core/CoreLayerContext_real.c',\n  'core/CoreLayerRegion_real.c',\n  'core/CorePalette_real.c',\n  'core/CoreScreen_real.c',\n  'core/CoreSlave_real.c',\n  'core/CoreSurface_real.c',\n  'core/CoreSurfaceAllocation_real.c',\n  'core/CoreSurfaceClient_real.c',\n  'core/CoreWindow_real.c',\n  'core/CoreWindowStack_real.c',\n  'core/clipboard.c',\n  'core/colorhash.c',\n  'core/core.c',\n  'core/core_parts.c',\n  'core/fonts.c',\n  'core/gfxcard.c',\n  'core/graphics_state.c',\n  'core/input.c', directfb_keynames,\n  'core/layer_context.c',\n  'core/layer_control.c',\n  'core/layer_region.c',\n  'core/layers.c',\n  'core/palette.c',\n  'core/prealloc_surface_pool.c',\n  'core/prealloc_surface_pool_bridge.c',\n  'core/screen.c',\n  'core/screens.c',\n  'core/state.c',\n  'core/surface.c',\n  'core/surface_allocation.c',\n  'core/surface_buffer.c',\n  'core/surface_client.c',\n  'core/surface_core.c',\n  'core/surface_pool.c',\n  'core/surface_pool_bridge.c',\n  'core/system.c',\n  'core/windows.c',\n  'core/windowstack.c',\n  'core/wm.c',\n  'display/idirectfbdisplaylayer.c',\n  'display/idirectfbpalette.c',\n  'display/idirectfbscreen.c',\n  'display/idirectfbsurface.c',\n  'display/idirectfbsurfaceallocation.c',\n  'display/idirectfbsurface_layer.c',\n  'display/idirectfbsurface_window.c',\n  'gfx/clip.c',\n  'gfx/convert.c',\n  'gfx/util.c',\n  'gfx/generic/generic.c',\n  'gfx/generic/generic_blit.c',\n  'gfx/generic/generic_draw_line.c',\n  'gfx/generic/generic_fill_rectangle.c',\n  'gfx/generic/generic_stretch_blit.c',\n  'gfx/generic/generic_texture_triangles.c',\n  'gfx/generic/generic_util.c',\n  'input/idirectfbeventbuffer.c',\n  'input/idirectfbinputdevice.c',\n  'media/idirectfbdatabuffer.c',\n  'media/idirectfbdatabuffer_file.c',\n  'media/idirectfbdatabuffer_memory.c',\n  'media/idirectfbdatabuffer_streamed.c',\n  'media/idirectfbfont.c',\n  'media/idirectfbimageprovider.c',\n  'media/idirectfbvideoprovider.c',\n  'misc/conf.c',\n  'misc/gfx_util.c',\n  'misc/util.c', directfb_strings,\n  'windows/idirectfbwindow.c'\n]\n\ncore_headers = [\n  'core/CoreGraphicsStateClient.h',\n  'core/CoreSlave_includes.h',\n  'core/core.h',\n  'core/core_resourcemanager.h',\n  'core/core_system.h',\n  'core/coredefs.h',\n  'core/coretypes.h',\n  'core/fonts.h',\n  'core/gfxcard.h',\n  'core/graphics_driver.h',\n  'core/input.h',\n  'core/input_driver.h',\n  'core/layer_context.h',\n  'core/layer_control.h',\n  'core/layer_region.h',\n  'core/layers.h',\n  'core/palette.h',\n  'core/screen.h',\n  'core/screens.h',\n  'core/state.h',\n  'core/surface.h',\n  'core/surface_allocation.h',\n  'core/surface_buffer.h',\n  'core/surface_client.h',\n  'core/surface_pool.h',\n  'core/surface_pool_bridge.h',\n  'core/system.h',\n  'core/video_mode.h',\n  'core/windows.h',\n  'core/windowstack.h',\n  'core/wm.h',\n  'core/wm_module.h'\n]\n\ndisplay_headers = [\n  'display/idirectfbsurface.h',\n]\n\ngfx_headers = [\n  'gfx/clip.h',\n  'gfx/convert.h',\n  'gfx/util.h'\n]\n\nmedia_headers = [\n  'media/idirectfbdatabuffer.h',\n  'media/idirectfbfont.h',\n  'media/idirectfbimageprovider.h',\n  'media/idirectfbvideoprovider.h'\n]\n\nmisc_headers = [\n  'misc/conf.h',\n  'misc/gfx_util.h',\n]\n\nif get_option('multi')\n  surface_pool_sources = [\n    'core/shared_secure_surface_pool.c',\n    'core/shared_surface_pool.c'\n  ]\nelse\n  surface_pool_sources = 'core/local_surface_pool.c'\nendif\n\nbuild_conf = configuration_data()\n\nbuild_conf.set_quoted('DIRECTFB_VERSION_VENDOR', get_option('vendor-version'))\n\nbuild_conf.set10('DFB_SMOOTH_SCALING', get_option('smooth-scaling'))\n\nconfigure_file(configuration: build_conf,\n               output: 'build.h',\n               install: true,\n               install_dir: get_option('includedir') / 'directfb-internal')\n\ndirectfb_private = []\nif get_option('default_library') == 'static'\n  directfb_private = 'directfb-gfxdriver directfb-inputdriver directfb-interface directfb-system directfb-wm'\nendif\n\nlibdirectfb_private = []\nif get_option('default_library') == 'static' and get_option('constructors')\n  libdirectfb_private = '-Wl,-u,__DFB_init_all'\nendif\n\nlibdirectfb = library('directfb-@0@.@1@'.format(directfb_major_version, directfb_minor_version),\n                      directfb_sources, flux_sources, surface_pool_sources,\n                      include_directories: [config_inc, directfb_inc],\n                      c_args: ['-DBUILDTIME=\"'  + run_command('date', '-u', '+%Y-%m-%d %H:%M',\n                                                              check: true).stdout().strip()                  + '\"',\n                               '-DSYSCONFDIR=\"' + get_option('prefix') / get_option('sysconfdir') + '\"'],\n                      build_rpath: get_option('prefix') / get_option('libdir'),\n                      dependencies: [direct_dep, fusion_dep],\n                      version: '0.@0@.0'.format(directfb_micro_version),\n                      install: true,\n                      install_rpath: get_option('prefix') / get_option('libdir'))\n\ninstall_symlink('libdirectfb' + libsuffix,\n                pointing_to: 'libdirectfb-@0@.@1@'.format(directfb_major_version, directfb_minor_version) + libsuffix,\n                install_dir: get_option('prefix') / get_option('libdir'))\n\ninstall_headers('idirectfb.h',   subdir: 'directfb-internal')\ninstall_headers(core_headers,    subdir: 'directfb-internal/core')\ninstall_headers(display_headers, subdir: 'directfb-internal/display')\ninstall_headers(gfx_headers,     subdir: 'directfb-internal/gfx')\ninstall_headers(media_headers,   subdir: 'directfb-internal/media')\ninstall_headers(misc_headers,    subdir: 'directfb-internal/misc')\n\npkgconfig.generate(filebase: 'directfb',\n                   name: 'DirectFB',\n                   description: 'Graphics and windowing library in Framebuffer memory',\n                   requires: 'direct fusion',\n                   requires_private: directfb_private,\n                   libraries: '-L${libdir} -ldirectfb',\n                   libraries_private: libdirectfb_private,\n                   subdirs: 'directfb')\n\npkgconfig.generate(filebase: 'directfb-internal',\n                   variables: ['moduledirname=' + moduledirname, 'moduledir=' + moduledir],\n                   name: 'DirectFB-internal',\n                   description: 'DirectFB internal module infrastructure',\n                   requires: 'directfb',\n                   subdirs: 'directfb-internal')\n\ndirectfb_dep = declare_dependency(include_directories: directfb_inc, link_with: [libdirectfb, libdirect, libfusion])\n"
  },
  {
    "path": "src/misc/conf.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/filesystem.h>\n#include <direct/memcpy.h>\n#include <direct/system.h>\n#include <direct/util.h>\n#include <directfb_util.h>\n#include <directfb_version.h>\n#include <fusion/conf.h>\n#include <misc/conf.h>\n\nD_DEBUG_DOMAIN( DirectFB_Config, \"DirectFB/Config\", \"DirectFB Runtime Configuration options\" );\n\n/**********************************************************************************************************************/\n\nDFBConfig  *dfb_config = NULL;\nconst char *dfb_config_usage =\n     \"\\n\"\n     \" --dfb-help                      Output DirectFB usage information and exit\\n\"\n     \" --dfb:<option>[,<option>...]    Pass options to DirectFB (see below)\\n\"\n     \"\\n\"\n     \"DirectFB options:\\n\"\n     \"\\n\"\n     \"  help                           Output DirectFB usage information and exit\\n\"\n     \"  include=<config file>          Include the specified file, relative to the current file\\n\"\n     \"  system=<system>                Specify the system ('drmkms', 'fbdev', etc.)\\n\"\n     \"  wm=<wm>                        Specify the window manager module ('default', etc.)\\n\"\n     \"  [no-]banner                    Show DirectFB banner at startup (default enabled)\\n\"\n     \"  [no-]sync                      Flush all disk buffers before initializing DirectFB\\n\"\n     \"  [no-]always-indirect           Use purely indirect Flux calls (for secure master)\\n\"\n     \"  [no-]block-all-signals         Block all signals\\n\"\n     \"  [no-]core-sighandler           Enable core signal handler, for emergency shutdowns (default enabled)\\n\"\n     \"  [no-]ownership-check           Check privileges when calling GetSurface() or GetWindow() (default enabled)\\n\"\n     \"  [no-]deinit-check              Check if all allocated resources have been released on exit (default enabled)\\n\"\n     \"  resource-manager=<impl>        Specify a resource manager implementation\\n\"\n     \"  session=<num>                  Select the multi application world which is joined or created\\n\"\n     \"                                 -1 forces the creation of a new world using the lowest unused session number\\n\"\n     \"  screen-frame-interval=<us>     Screen refresh interval used if not defined by the encoder (default = 16666)\\n\"\n     \"  [no-]primary-only              Tell application only about the primary layer\\n\"\n     \"  primary-id=<surface-id>        Set ID of primary surface to use\\n\"\n     \"  primary-layer=<layer-id>       Select the primary layer (default is the first)\\n\"\n     \"  mode=<width>x<height>          Set the default screen resolution\\n\"\n     \"  depth=<pixeldepth>             Set the default pixel depth in bits per pixel\\n\"\n     \"  pixelformat=<pixelformat>      Set the default pixel format\\n\"\n     \"  [no-]init-layer=<id>           Initialize layer with ID\\n\"\n     \"  [layer-]size=<width>x<height>  Set the pixel resolution\\n\"\n     \"  [layer-]depth=<pixeldepth>     Set the pixel depth\\n\"\n     \"  [layer-]format=<pixelformat>   Set the pixel format\\n\"\n     \"  [layer-]buffer-mode=<mode>     Specify the buffer mode\\n\"\n     \"                                 [ auto | triple | backvideo | backsystem | frontonly | windows ]\\n\"\n     \"                                 auto:       DirectFB decides depending on hardware capabilities\\n\"\n     \"                                 triple:     Triple buffering (allocations in video memory only)\\n\"\n     \"                                 backvideo:  Front and back buffer are allocated in video memory\\n\"\n     \"                                 backsystem: The back buffer is allocated in system memory\\n\"\n     \"                                 frontonly:  There is no back buffer\\n\"\n     \"                                 windows:    Special mode with window buffers directly displayed\\n\"\n     \"  [layer-]src-key=<AARRGGBB>     Enable color keying (hexadecimal)\\n\"\n     \"  [layer-]src-key-index=<index>  Enable color keying index (decimal)\\n\"\n     \"  [layer-]bg-none                Disable background handling\\n\"\n     \"  [layer-]bg-image=<filename>    Use background image\\n\"\n     \"  [layer-]bg-tile=<filename>     Use tiled background image\\n\"\n     \"  [layer-]bg-color=<AARRGGBB>    Use background color (hexadecimal)\\n\"\n     \"  [layer-]bg-color-index=<index> Use background color index (decimal)\\n\"\n     \"  [layer-]stacking=<classes>     Set stacking classes\\n\"\n     \"  [layer-]palette-<i>=<AARRGGBB> Set palette entry at decimal index 'i' (hexadecimal)\\n\"\n     \"  [layer-]rotate=<degree>        Set the layer rotation for double buffer mode (0,90,180,270)\\n\"\n     \"  graphics-state-call-limit=<n>  Set FusionCall quota for graphics state object (default = 5000)\\n\"\n     \"  [no-]hardware                  Turn hardware acceleration on (default enabled)\\n\"\n     \"  [no-]software                  Enable software fallbacks (default enabled)\\n\"\n     \"  [no-]software-warn             Show warnings when doing/dropping software operations\\n\"\n     \"  [no-]software-trace            Show every stage of the software rendering pipeline\\n\"\n     \"  [no-]gfxcard-stats=[<ms>]      Print GPU usage statistics periodically (1000 ms if no period is specified)\\n\"\n     \"  videoram-limit=<amount>        Limit the amount of Video RAM used (kilobytes)\\n\"\n     \"  [no-]gfx-emit-early            Early emit GFX commands to prevent being IDLE\\n\"\n     \"  [no-]startstop                 Issue StartDrawing/StopDrawing to driver\\n\"\n     \"  [no-]smooth-upscale            Enable smooth upscaling\\n\"\n     \"  [no-]smooth-downscale          Enable smooth downscaling\\n\"\n     \"  keep-accumulators=<limit>      Free accumulators above the limit (default = 1024)\\n\"\n     \"                                 Setting -1 never frees accumulators until the state is destroyed\\n\"\n     \"  [no-]mmx                       Enable MMX assembly support (enabled by default if available)\\n\"\n     \"  [no-]neon                      Enable NEON assembly support (enabled by default if available)\\n\"\n     \"  warn=<type[:<width>x<height>]> Print warnings on surface/window creations or surface buffer allocations\\n\"\n     \"                                 [ create-surface | create-window | allocate-buffer ]\\n\"\n     \"  [no-]surface-clear             Clear all surface buffers after creation\\n\"\n     \"  [no-]thrifty-surface-buffers   Release system instance while video instance is alive\\n\"\n     \"  surface-shmpool-size=<kb>      Set the size of the shared memory pool used for shared system memory surfaces\\n\"\n     \"  system-surface-base-alignment=<byte alignment>\\n\"\n     \"                                 If GPU supports system memory, set the byte alignment for system memory based\\n\"\n     \"                                 surface's base address (value must be a positive power of two that is four or\\n\"\n     \"                                 greater), or zero for no alignment: aligning the base address (along with the\\n\"\n     \"                                 pitch) allows the data to travel more efficiently through the CPU and memory\\n\"\n     \"                                 bus to increase performance, and meet GPU requirements\\n\"\n     \"  system-surface-pitch-alignment=<byte alignment>\\n\"\n     \"                                 If GPU supports system memory, set the pitch alignment for system memory based\\n\"\n     \"                                 system memory based surface's pitch (value must be a positive power of two),\\n\"\n     \"                                 or zero for no alignment\\n\"\n     \"  max-frame-advance=<us>         Set the maximum time ahead for rendering frames (default 100000)\\n\"\n     \"  [no-]force-frametime           Call GetFrameTime() before each Flip() automatically\\n\"\n     \"  [no-]subsurface-caching        Optimize the recreation of sub-surfaces\\n\"\n     \"  window-surface-policy=<policy> Specify the swapping policy for window surfaces (default = auto)\\n\"\n     \"                                 [ auto | videohigh | videolow | systemonly | videoonly ]\\n\"\n     \"                                 auto:       DirectFB decides depending on hardware capabilities\\n\"\n     \"                                 videohigh:  Swapping system/video with high priority\\n\"\n     \"                                 videolow:   Swapping system/video with low priority\\n\"\n     \"                                 systemonly: Window surfaces are stored in system memory\\n\"\n     \"                                 videoonly:  Window surfaces are stored in video memory\\n\"\n     \"  [no-]single-window             Set configuration on region when window changes its attributes\\n\"\n     \"  [no-]translucent-windows       Allow translucent windows (default enabled)\\n\"\n     \"  [no-]force-windowed            Force the primary surface to be a window\\n\"\n     \"  scaled=<width>x<height>        Scale the window to this size for 'force-windowed' apps\\n\"\n     \"  [no-]autoflip-window           Auto flip non-flipping windowed primary surfaces (default enabled)\\n\"\n     \"  [no-]cursor                    Create a cursor when an application makes use of windows (default enabled)\\n\"\n     \"  [no-]cursor-videoonly          Make the cursor a video only surface\\n\"\n     \"  cursor-resource-id=<id>        Specify a resource id for the cursor surface\\n\"\n     \"  [no-]cursor-automation         Automated cursor show/hide for windowed primary surfaces\\n\"\n     \"  [no-]discard-repeat-events     Discard repeat events\\n\"\n     \"  [no-]capslock-meta             Map the CapsLock key to Meta\\n\"\n     \"  [no-]lefty                     Swap left and right mouse buttons\\n\"\n     \"  screenshot-dir=<directory>     Dump screen content on <Print> key presses\\n\"\n     \"  font-format=<pixelformat>      Set the preferred font format (default is 8 bit alpha)\\n\"\n     \"  [no-]font-premult              Enable premultiplied glyph images in ARGB format (default enabled)\\n\"\n     \"  font-resource-id=<id>          Resource ID to use for font cache row surfaces\\n\"\n     \"  max-font-rows=<number>         Maximum number of glyph cache rows (default = 99)\\n\"\n     \"  max-font-row-width=<pixels>    Maximum width of glyph cache row surface (default = 2048)\\n\"\n     \"\\n\";\n\n/**********************************************************************************************************************/\n\nstatic void\nprint_config_usage( void )\n{\n    fprintf( stderr, \"DirectFB version %d.%d.%d\\n\",\n             DIRECTFB_MAJOR_VERSION, DIRECTFB_MINOR_VERSION, DIRECTFB_MICRO_VERSION );\n\n    fprintf( stderr, \"%s\", dfb_config_usage );\n\n    fprintf( stderr, \"%s%s\", fusion_config_usage, direct_config_usage );\n}\n\nstatic DFBResult\nparse_args( const char *args )\n{\n     int   len = strlen( args );\n     char *name, *buf;\n\n     buf = D_MALLOC( len + 1 );\n     if (!buf)\n          return D_OOM();\n\n     name = buf;\n\n     direct_memcpy( name, args, len + 1 );\n\n     while (name && name[0]) {\n          DFBResult  ret;\n          char      *value;\n          char      *next;\n\n          if ((next = strchr( name, ',' )) != NULL)\n               *next++ = '\\0';\n\n          if (strcmp( name, \"help\" ) == 0) {\n               print_config_usage();\n               exit( 1 );\n          }\n\n          if (strcmp( name, \"memcpy=help\" ) == 0) {\n               direct_print_memcpy_routines();\n               exit( 1 );\n          }\n\n          if ((value = strchr( name, '=' )) != NULL)\n               *value++ = '\\0';\n\n          ret = dfb_config_set( name, value );\n          switch (ret) {\n               case DFB_OK:\n                    break;\n               default:\n                    D_ERROR( \"DirectFB/Config: Invalid option '%s' in args!\\n\", name );\n                    D_FREE( buf );\n                    return ret;\n          }\n\n          name = next;\n     }\n\n     D_FREE( buf );\n\n     return DFB_OK;\n}\n\nstatic int\nconfig_read_cmdline( char       *cmdbuf,\n                     int         size,\n                     DirectFile *f )\n{\n     size_t bytes;\n     int    len = 0;\n\n     direct_file_read( f, cmdbuf, 1, &bytes );\n\n     if (bytes == 1 && *cmdbuf == 0) {\n          direct_file_read( f, cmdbuf, 1, &bytes );\n     }\n\n     while (bytes == 1 && len < (size - 1)) {\n          len++;\n          direct_file_read( f, ++cmdbuf, 1, &bytes );\n          if (*cmdbuf == 0)\n               break;\n     }\n\n     if (len) {\n          cmdbuf[len]=0;\n     }\n\n     return len != 0;\n}\n\nstatic void\nconfig_allocate( void )\n{\n     int i;\n\n     if (dfb_config)\n          return;\n\n     dfb_config = D_CALLOC( 1, sizeof(DFBConfig) );\n\n     if (direct_access( \"/dev/dri/card0\", W_OK ) == DR_OK)\n          dfb_config->system                           = D_STRDUP( \"drmkms\" );\n     else if (direct_access( \"/dev/fb0\", W_OK ) == DR_OK)\n          dfb_config->system                           = D_STRDUP( \"fbdev\" );\n\n     dfb_config->banner                                = true;\n\n     dfb_config->core_sighandler                       = true;\n\n     dfb_config->ownership_check                       = true;\n     dfb_config->deinit_check                          = true;\n\n     dfb_config->screen_frame_interval                 = 16666;\n\n     dfb_config->layers[0].init                        = true;\n     dfb_config->layers[0].stacking                    = (1 << DWSC_UPPER) | (1 << DWSC_MIDDLE) | (1 << DWSC_LOWER);\n     for (i = 0; i < D_ARRAY_SIZE(dfb_config->layers); i++) {\n          dfb_config->layers[i].src_key_index          = -1;\n          dfb_config->layers[i].background.mode        = DLBM_COLOR;\n          dfb_config->layers[i].background.color_index = -1;\n     }\n\n     dfb_config->graphics_state_call_limit             = 5000;\n\n     dfb_config->keep_accumulators                     = 1024;\n\n     dfb_config->mmx                                   = true;\n     dfb_config->neon                                  = true;\n\n     dfb_config->surface_shmpool_size                  = 64 * 1024 * 1024;\n\n     dfb_config->max_frame_advance                     = 100000;\n\n     dfb_config->window_policy                         = -1;\n     dfb_config->translucent_windows                   = true;\n     dfb_config->autoflip_window                       = true;\n\n     dfb_config->font_format                           = DSPF_A8;\n     dfb_config->font_premult                          = true;\n     dfb_config->max_font_rows                         = 99;\n     dfb_config->max_font_row_width                    = 2048;\n}\n\nstatic DFBResult\nconfig_read( const char *filename )\n{\n     DFBResult   ret;\n     DirectFile  f;\n     char        line[400];\n     char       *slash = NULL;\n     char       *cwd   = NULL;\n\n     config_allocate();\n\n     dfb_config->config_layer = &dfb_config->layers[0];\n\n     ret = direct_file_open( &f, filename, O_RDONLY, 0 );\n     if (ret) {\n          D_DEBUG_AT( DirectFB_Config, \"Unable to open config file '%s'!\\n\", filename );\n          return DFB_IO;\n     }\n     else {\n          D_DEBUG_AT( DirectFB_Config, \"Parsing config file '%s'\\n\", filename );\n     }\n\n     /* Store the current working directory for the 'include' command. */\n     slash = strrchr( filename, '/' );\n     if (slash) {\n          char nwd[strlen( filename )];\n\n          cwd = D_MALLOC( PATH_MAX );\n          if (!cwd) {\n               direct_file_close( &f );\n               return D_OOM();\n          }\n\n          ret = direct_dir_get_current( cwd, PATH_MAX );\n          if (ret) {\n               D_FREE( cwd );\n               direct_file_close( &f );\n               return ret;\n          }\n\n          strcpy( nwd, filename );\n          nwd[slash-filename] = 0;\n          ret = direct_dir_change( nwd );\n          if (ret)\n               D_WARN( \"failed to change directory to %s\", nwd );\n          else\n               D_DEBUG_AT( DirectFB_Config, \"Changing configuration lookup directory to '%s'\\n\", nwd );\n     }\n\n     while (!direct_file_get_string( &f, line, 400 )) {\n          char *name    = line;\n          char *comment = strchr( line, '#' );\n          char *value;\n\n          if (comment) {\n               *comment = 0;\n          }\n\n          value = strchr( line, '=' );\n\n          if (value) {\n               *value++ = 0;\n               direct_trim( &value );\n          }\n\n          direct_trim( &name );\n\n          if (!*name || *name == '#')\n               continue;\n\n          ret = dfb_config_set( name, value );\n          if (ret) {\n               D_ERROR( \"DirectFB/Config: Invalid option '%s' in config file '%s'!\\n\", name, filename );\n               break;\n          }\n     }\n\n     direct_file_close( &f );\n\n     /* Restore the original current working directory. */\n     if (cwd) {\n          if (direct_dir_change( cwd ))\n               D_WARN( \"failed to change directory to %s\", cwd );\n          else\n               D_DEBUG_AT( DirectFB_Config, \"Back to directory '%s'\\n\", cwd );\n\n          D_FREE( cwd );\n     }\n\n     return ret;\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\ndfb_config_set( const char *name,\n                const char *value )\n{\n     bool dfboption = true;\n\n     if (strcmp( name, \"include\" ) == 0) {\n          if (value) {\n               DFBResult ret;\n\n               ret = config_read( value );\n               if (ret)\n                    return ret;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No include file name specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"system\" ) == 0) {\n          if (value) {\n               if (dfb_config->system)\n                    D_FREE( dfb_config->system );\n\n               dfb_config->system = D_STRDUP( value );\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No system specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"wm\" ) == 0) {\n          if (value) {\n               if (dfb_config->wm)\n                    D_FREE( dfb_config->wm );\n\n               dfb_config->wm = D_STRDUP( value );\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No window manager module specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"banner\" ) == 0) {\n          dfb_config->banner = true;\n     } else\n     if (strcmp( name, \"no-banner\" ) == 0) {\n          dfb_config->banner = false;\n     } else\n     if (strcmp( name, \"sync\" ) == 0) {\n          dfb_config->sync = true;\n     } else\n     if (strcmp( name, \"no-sync\" ) == 0) {\n          dfb_config->sync = false;\n     } else\n     if (strcmp( name, \"always-indirect\" ) == 0) {\n          dfb_config->call_nodirect = FCEF_NODIRECT;\n     } else\n     if (strcmp( name, \"no-always-indirect\" ) == 0) {\n          dfb_config->call_nodirect = FCEF_NONE;\n     } else\n     if (strcmp( name, \"block-all-signals\" ) == 0) {\n          dfb_config->block_all_signals = true;\n     } else\n     if (strcmp( name, \"no-block-all-signals\" ) == 0) {\n          dfb_config->block_all_signals = false;\n     } else\n     if (strcmp( name, \"core-sighandler\" ) == 0) {\n          dfb_config->core_sighandler = true;\n     } else\n     if (strcmp( name, \"no-core-sighandler\" ) == 0) {\n          dfb_config->core_sighandler = false;\n     } else\n     if (strcmp( name, \"ownership-check\" ) == 0) {\n          dfb_config->ownership_check = true;\n     } else\n     if (strcmp( name, \"no-ownership-check\" ) == 0) {\n          dfb_config->ownership_check = false;\n     } else\n     if (strcmp( name, \"deinit-check\" ) == 0) {\n          dfb_config->deinit_check = true;\n     } else\n     if (strcmp( name, \"no-deinit-check\" ) == 0) {\n          dfb_config->deinit_check = false;\n     } else\n     if (strcmp( name, \"resource-manager\" ) == 0) {\n          if (value) {\n               if (dfb_config->resource_manager)\n                    D_FREE( dfb_config->resource_manager );\n\n               dfb_config->resource_manager = D_STRDUP( value );\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No implementation specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"session\" ) == 0) {\n          if (value) {\n               int session;\n\n               if (sscanf( value, \"%d\", &session ) < 1) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse value!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               dfb_config->session = session;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No value specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"screen-frame-interval\" ) == 0) {\n          if (value) {\n               long long interval;\n\n               if (sscanf( value, \"%lld\", &interval ) < 1) {\n                    D_ERROR(\"DirectFB/Config '%s': Could not parse value!\\n\", name);\n                    return DFB_INVARG;\n               }\n\n               dfb_config->screen_frame_interval = interval;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No value specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"primary-id\" ) == 0) {\n          if (value) {\n               unsigned int id;\n\n               if (sscanf( value, \"%u\", &id ) < 1) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse id!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               dfb_config->primary_id = id;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No id specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"primary-layer\" ) == 0) {\n          if (value) {\n               int id;\n\n               if (sscanf( value, \"%d\", &id ) < 1) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse id!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               dfb_config->primary_layer = id;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No id specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"primary-only\" ) == 0) {\n          dfb_config->primary_only = true;\n     } else\n     if (strcmp( name, \"no-primary-only\" ) == 0) {\n          dfb_config->primary_only = false;\n     } else\n     if (strcmp( name, \"init-layer\" ) == 0) {\n          if (value) {\n               int id;\n\n               if (sscanf( value, \"%d\", &id ) < 1) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse id!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               if (id < 0 || id > D_ARRAY_SIZE(dfb_config->layers)) {\n                    D_ERROR( \"DirectFB/Config: '%s': id %d out of bounds!\\n\", name, id );\n                    return DFB_INVARG;\n               }\n\n               dfb_config->layers[id].init = true;\n\n               dfb_config->config_layer = &dfb_config->layers[id];\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No id specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"no-init-layer\" ) == 0) {\n          if (value) {\n               int id;\n\n               if (sscanf( value, \"%d\", &id ) < 1) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse id!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               if (id < 0 || id > D_ARRAY_SIZE(dfb_config->layers)) {\n                    D_ERROR( \"DirectFB/Config: '%s': id %d out of bounds!\\n\", name, id );\n                    return DFB_INVARG;\n               }\n\n               dfb_config->layers[id].init = false;\n\n               dfb_config->config_layer = &dfb_config->layers[id];\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No id specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"mode\" ) == 0 || strcmp( name, \"layer-size\" ) == 0) {\n          DFBConfigLayer *conf = dfb_config->config_layer;\n\n          if (value) {\n               int width, height;\n\n               if (sscanf( value, \"%dx%d\", &width, &height ) < 2) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse size!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               if (conf == &dfb_config->layers[0]) {\n                    dfb_config->mode.width  = width;\n                    dfb_config->mode.height = height;\n               }\n\n               conf->config.width   = width;\n               conf->config.height  = height;\n               conf->config.flags  |= DLCONF_WIDTH | DLCONF_HEIGHT;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No size specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"depth\" ) == 0 || strcmp( name, \"layer-depth\" ) == 0) {\n          DFBConfigLayer *conf = dfb_config->config_layer;\n\n          if (value) {\n               int depth;\n\n               if (sscanf( value, \"%d\", &depth ) < 1) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse depth!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               if (conf == &dfb_config->layers[0]) {\n                    dfb_config->mode.depth = depth;\n               }\n\n               conf->config.pixelformat  = dfb_pixelformat_for_depth( depth );\n               conf->config.flags       |= DLCONF_PIXELFORMAT;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No depth specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"pixelformat\" ) == 0 || strcmp( name, \"layer-format\" ) == 0) {\n          DFBConfigLayer *conf = dfb_config->config_layer;\n\n          if (value) {\n               DFBSurfacePixelFormat format;\n\n               format = dfb_pixelformat_parse( value );\n               if (format == DSPF_UNKNOWN) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse format!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               if (conf == &dfb_config->layers[0])\n                    dfb_config->mode.format = format;\n\n               conf->config.pixelformat  = format;\n               conf->config.flags       |= DLCONF_PIXELFORMAT;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No format specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp (name, \"buffer-mode\" ) == 0 || strcmp( name, \"layer-buffer-mode\" ) == 0) {\n          DFBConfigLayer *conf = dfb_config->config_layer;\n\n          if (value) {\n               if (!strcmp( value, \"auto\" )) {\n                    conf->config.flags      &= ~DLCONF_BUFFERMODE;\n               } else\n               if (!strcmp( value, \"triple\" )) {\n                    conf->config.buffermode  = DLBM_TRIPLE;\n                    conf->config.flags      |= DLCONF_BUFFERMODE;\n               } else\n               if (!strcmp( value, \"backvideo\" )) {\n                    conf->config.buffermode  = DLBM_BACKVIDEO;\n                    conf->config.flags      |= DLCONF_BUFFERMODE;\n               } else\n               if (!strcmp( value, \"backsystem\" )) {\n                    conf->config.buffermode  = DLBM_BACKSYSTEM;\n                    conf->config.flags      |= DLCONF_BUFFERMODE;\n               } else\n               if (!strcmp( value, \"frontonly\" )) {\n                    conf->config.buffermode  = DLBM_FRONTONLY;\n                    conf->config.flags      |= DLCONF_BUFFERMODE;\n               } else\n               if (!strcmp( value, \"windows\" )) {\n                    conf->config.buffermode  = DLBM_WINDOWS;\n                    conf->config.flags      |= DLCONF_BUFFERMODE;\n               }\n               else {\n                    D_ERROR( \"DirectFB/Config: '%s': Unknown buffer mode '%s'!\\n\", name, value );\n                    return DFB_INVARG;\n               }\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No buffer mode specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp (name, \"src-key\" ) == 0 || strcmp( name, \"layer-src-key\" ) == 0) {\n          DFBConfigLayer *conf = dfb_config->config_layer;\n\n          if (value) {\n               char *error;\n               u32   argb;\n\n               argb = strtoul( value, &error, 16 );\n\n               if (*error) {\n                    D_ERROR( \"DirectFB/Config: '%s': Error in color '%s'!\\n\", name, error );\n                    return DFB_INVARG;\n               }\n\n               conf->src_key.b = argb & 0xff;\n               argb >>= 8;\n               conf->src_key.g = argb & 0xff;\n               argb >>= 8;\n               conf->src_key.r = argb & 0xff;\n               argb >>= 8;\n               conf->src_key.a = argb & 0xff;\n\n               conf->config.options |= DLOP_SRC_COLORKEY;\n               conf->config.flags   |= DLCONF_OPTIONS;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No color specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp (name, \"src-key-index\" ) == 0 || strcmp( name, \"layer-src-key-index\" ) == 0) {\n          DFBConfigLayer *conf = dfb_config->config_layer;\n\n          if (value) {\n               char *error;\n               u32   index;\n\n               index = strtoul( value, &error, 10 );\n\n               if (*error) {\n                    D_ERROR( \"DirectFB/Config: '%s': Error in index '%s'!\\n\", name, error );\n                    return DFB_INVARG;\n               }\n\n               conf->src_key_index = index;\n\n               conf->config.options |= DLOP_SRC_COLORKEY;\n               conf->config.flags   |= DLCONF_OPTIONS;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No index specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"bg-none\" ) == 0 || strcmp( name, \"layer-bg-none\" ) == 0) {\n          DFBConfigLayer *conf = dfb_config->config_layer;\n\n          conf->background.mode = DLBM_DONTCARE;\n     } else\n     if (strcmp( name, \"bg-image\" ) == 0 || strcmp( name, \"bg-tile\" ) == 0 ||\n         strcmp( name, \"layer-bg-image\" ) == 0 || strcmp( name, \"layer-bg-tile\" ) == 0) {\n          DFBConfigLayer *conf = dfb_config->config_layer;\n\n          if (value) {\n               if (conf->background.filename)\n                    D_FREE( conf->background.filename );\n\n               conf->background.filename = D_STRDUP( value );\n               conf->background.mode     = strstr( name, \"bg-image\" ) ? DLBM_IMAGE : DLBM_TILE;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No file name specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"bg-color\" ) == 0 || strcmp( name, \"layer-bg-color\" ) == 0) {\n          DFBConfigLayer *conf = dfb_config->config_layer;\n\n          if (value) {\n               char *error;\n               u32   argb;\n\n               argb = strtoul( value, &error, 16 );\n\n               if (*error) {\n                    D_ERROR( \"DirectFB/Config: '%s': Error in color '%s'!\\n\", name, error );\n                    return DFB_INVARG;\n               }\n\n               conf->background.color.b     = argb & 0xff;\n               argb >>= 8;\n               conf->background.color.g     = argb & 0xff;\n               argb >>= 8;\n               conf->background.color.r     = argb & 0xff;\n               argb >>= 8;\n               conf->background.color.a     = argb & 0xff;\n               conf->background.color_index = -1;\n               conf->background.mode        = DLBM_COLOR;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No color specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"bg-color-index\" ) == 0 || strcmp( name, \"layer-bg-color-index\" ) == 0) {\n          DFBConfigLayer *conf = dfb_config->config_layer;\n\n          if (value) {\n               char *error;\n               u32   index;\n\n               index = strtoul( value, &error, 10 );\n\n               if (*error) {\n                    D_ERROR( \"DirectFB/Config: '%s': Error in index '%s'!\\n\", name, error );\n                    return DFB_INVARG;\n               }\n\n               conf->background.color_index = index;\n               conf->background.mode        = DLBM_COLOR;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No index specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"stacking\" ) == 0 || strcmp( name, \"layer-stacking\" ) == 0) {\n          DFBConfigLayer *conf = dfb_config->config_layer;\n\n          if (value) {\n               char *stackings = D_STRDUP( value );\n               char *p = NULL, *r, *s = stackings;\n\n               conf->stacking = 0;\n\n               while ((r = direct_strtok_r( s, \",\", &p ))) {\n                    direct_trim( &r );\n\n                    if (!strcmp( r, \"lower\" ))  conf->stacking |= (1 << DWSC_LOWER);  else\n                    if (!strcmp( r, \"middle\" )) conf->stacking |= (1 << DWSC_MIDDLE); else\n                    if (!strcmp( r, \"upper\" ))  conf->stacking |= (1 << DWSC_UPPER);\n                    else {\n                         D_ERROR( \"DirectFB/Config: '%s': Unknown stacking class '%s'!\\n\", name, r );\n                         D_FREE( stackings );\n                         return DFB_INVARG;\n                    }\n\n                    s = NULL;\n               }\n\n               D_FREE( stackings );\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No stacking classes specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strncmp( name, \"palette-\", 8 ) == 0 || strncmp (name, \"layer-palette-\", 14 ) == 0) {\n          char           *error;\n          int             index;\n          DFBConfigLayer *conf = dfb_config->config_layer;\n\n          index = (name[0] == 'p') ? strtoul( name + 8, &error, 10 ) : strtoul( name + 14, &error, 10 );\n\n          if (*error) {\n               D_ERROR( \"DirectFB/Config: '%s': Error in index '%s'!\\n\", name, error );\n               return DFB_INVARG;\n          }\n\n          if (index < 0 || index > 255) {\n               D_ERROR( \"DirectFB/Config: '%s': Index %d out of bounds!\\n\", name, index );\n               return DFB_INVARG;\n          }\n\n          if (value) {\n               u32 argb;\n\n               argb = strtoul( value, &error, 16 );\n\n               if (*error) {\n                    D_ERROR( \"DirectFB/Config: '%s': Error in color '%s'!\\n\", name, error );\n                    return DFB_INVARG;\n               }\n\n               if (!conf->palette) {\n                    conf->palette = D_CALLOC( 256, sizeof(DFBColor) );\n                    if (!conf->palette)\n                         return D_OOM();\n               }\n\n               conf->palette[index].a = (argb & 0xff000000) >> 24;\n               conf->palette[index].r = (argb & 0xff0000) >> 16;\n               conf->palette[index].g = (argb & 0xff00) >> 8;\n               conf->palette[index].b = (argb & 0xff);\n               conf->palette_set      = true;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No color specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp (name, \"rotate\" ) == 0 || strcmp( name, \"layer-rotate\" ) == 0) {\n          DFBConfigLayer *conf = dfb_config->config_layer;\n\n          if (value) {\n               int rotate;\n\n               if (sscanf( value, \"%d\", &rotate ) < 1) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse value!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               if (rotate != 0 && rotate != 90 && rotate != 180 && rotate != 270) {\n                    D_ERROR( \"DirectFB/Config: '%s': Only 0, 90, 180 or 270 supported!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               conf->rotate     = rotate;\n               conf->rotate_set = true;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No value specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"graphics-state-call-limit\" ) == 0) {\n          if (value) {\n               unsigned int limit;\n\n               if (sscanf( value, \"%u\", &limit ) < 1) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse value!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               dfb_config->graphics_state_call_limit = limit;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No value specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"hardware\" ) == 0) {\n          dfb_config->software_only = false;\n     } else\n     if (strcmp( name, \"no-hardware\" ) == 0) {\n          dfb_config->software_only = true;\n     } else\n     if (strcmp( name, \"software\" ) == 0) {\n          dfb_config->hardware_only = false;\n     } else\n     if (strcmp( name, \"no-software\" ) == 0) {\n          dfb_config->hardware_only = true;\n     } else\n     if (strcmp( name, \"software-warn\" ) == 0) {\n          dfb_config->software_warn = true;\n     } else\n     if (strcmp( name, \"no-software-warn\" ) == 0) {\n          dfb_config->software_warn = false;\n     } else\n     if (strcmp( name, \"software-trace\" ) == 0) {\n          dfb_config->software_trace = true;\n     } else\n     if (strcmp( name, \"no-software-trace\" ) == 0) {\n          dfb_config->software_trace = false;\n     } else\n     if (strcmp( name, \"gfxcard-stats\" ) == 0) {\n          if (value) {\n               unsigned int interval;\n\n               if (sscanf( value, \"%u\", &interval ) < 1) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse value!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               dfb_config->gfxcard_stats = interval;\n          }\n          else\n               dfb_config->gfxcard_stats = 1000;\n     } else\n     if (strcmp( name, \"no-gfxcard-stats\" ) == 0) {\n          dfb_config->gfxcard_stats = 0;\n     } else\n     if (strcmp( name, \"videoram-limit\" ) == 0) {\n          if (value) {\n               unsigned int limit;\n\n               if (sscanf( value, \"%u\", &limit ) < 1) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse value!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               dfb_config->videoram_limit = limit << 10;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No value specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"gfx-emit-early\" ) == 0) {\n          dfb_config->gfx_emit_early = true;\n     } else\n     if (strcmp( name, \"no-gfx-emit-early\" ) == 0) {\n          dfb_config->gfx_emit_early = false;\n     } else\n     if (strcmp( name, \"startstop\" ) == 0) {\n          dfb_config->startstop = true;\n     } else\n     if (strcmp( name, \"no-startstop\" ) == 0) {\n          dfb_config->startstop = false;\n     } else\n     if (strcmp( name, \"smooth-upscale\" ) == 0) {\n          dfb_config->render_options |= DSRO_SMOOTH_UPSCALE;\n     } else\n     if (strcmp( name, \"no-smooth-upscale\" ) == 0) {\n          dfb_config->render_options &= ~DSRO_SMOOTH_UPSCALE;\n     } else\n     if (strcmp( name, \"smooth-downscale\" ) == 0) {\n          dfb_config->render_options |= DSRO_SMOOTH_DOWNSCALE;\n     } else\n     if (strcmp( name, \"no-smooth-downscale\" ) == 0) {\n          dfb_config->render_options &= ~DSRO_SMOOTH_DOWNSCALE;\n     } else\n     if (strcmp( name, \"keep-accumulators\" ) == 0) {\n          if (value) {\n               int limit;\n\n               if (sscanf( value, \"%d\", &limit ) < 1) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse value!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               dfb_config->keep_accumulators = limit;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No value specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"mmx\" ) == 0) {\n          dfb_config->mmx = true;\n     } else\n     if (strcmp( name, \"no-mmx\" ) == 0) {\n          dfb_config->mmx = false;\n     } else\n     if (strcmp( name, \"neon\" ) == 0) {\n          dfb_config->neon = true;\n     } else\n     if (strcmp( name, \"no-neon\" ) == 0) {\n          dfb_config->neon = false;\n     } else\n     if (strcmp( name, \"warn\" ) == 0 || strcmp( name, \"no-warn\" ) == 0) {\n          DFBConfigWarnFlags flags = DCWF_ALL;\n\n          if (value) {\n               char *opt = strchr( value, ':' );\n\n               if (opt)\n                    opt++;\n\n               if (!strncmp( value, \"create-surface\", 14 )) {\n                    flags = DCWF_CREATE_SURFACE;\n\n                    if (opt)\n                         sscanf( opt, \"%dx%d\",\n                                 &dfb_config->warn.create_surface.min_size.w,\n                                 &dfb_config->warn.create_surface.min_size.h );\n               } else\n               if (!strncmp( value, \"create-window\", 13 )) {\n                    flags = DCWF_CREATE_WINDOW;\n               } else\n               if (!strncmp( value, \"allocate-buffer\", 15 )) {\n                    flags = DCWF_ALLOCATE_BUFFER;\n\n                    if (opt)\n                         sscanf( opt, \"%dx%d\",\n                                 &dfb_config->warn.allocate_buffer.min_size.w,\n                                 &dfb_config->warn.allocate_buffer.min_size.h );\n               }\n               else {\n                    D_ERROR( \"DirectFB/Config: '%s': Unknown warning type '%s'!\\n\", name, value );\n                    return DFB_INVARG;\n               }\n          }\n\n          if (name[0] == 'w')\n               dfb_config->warn.flags |= flags;\n          else\n               dfb_config->warn.flags &= ~flags;\n     } else\n     if (strcmp( name, \"surface-clear\" ) == 0) {\n          dfb_config->surface_clear = true;\n     } else\n     if (strcmp( name, \"no-surface-clear\" ) == 0) {\n          dfb_config->surface_clear = false;\n     } else\n     if (strcmp( name, \"thrifty-surface-buffers\" ) == 0) {\n          dfb_config->thrifty_surface_buffers = true;\n     } else\n     if (strcmp( name, \"no-thrifty-surface-buffers\" ) == 0) {\n          dfb_config->thrifty_surface_buffers = false;\n     } else\n     if (!strcmp( name, \"surface-shmpool-size\" )) {\n          if (value) {\n               int size_kb;\n\n               if (sscanf( value, \"%d\", &size_kb ) < 1) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse value!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               dfb_config->surface_shmpool_size = size_kb * 1024;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No value specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"system-surface-base-alignment\" ) == 0) {\n          if (value) {\n               unsigned int base_align;\n\n               if (sscanf( value, \"%u\", &base_align ) < 1) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse value!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               if (base_align && (base_align < 4 || (base_align & (base_align - 1)) != 0)) {\n                   D_ERROR( \"DirectFB/Config: '%s': Value must be a positive power of two that is four or greater!\\n\",\n                            name );\n                   return DFB_INVARG;\n               }\n\n               dfb_config->system_surface_align_base = base_align;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No value specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"system-surface-pitch-alignment\" ) == 0) {\n          if (value) {\n               unsigned int pitch_align;\n\n               if (sscanf( value, \"%u\", &pitch_align ) < 1) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse value!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               if (pitch_align && (pitch_align == 1 || (pitch_align & (pitch_align - 1)) != 0)) {\n                   D_ERROR( \"DirectFB/Config: '%s': Value must be a positive power of two!\\n\", name );\n                   return DFB_INVARG;\n               }\n\n               dfb_config->system_surface_align_pitch = pitch_align;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No value specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"max-frame-advance\" ) == 0) {\n          if (value) {\n               long long advance;\n\n               if (sscanf( value, \"%lld\", &advance ) < 1) {\n                    D_ERROR(\"DirectFB/Config '%s': Could not parse value!\\n\", name);\n                    return DFB_INVARG;\n               }\n\n               dfb_config->max_frame_advance = advance;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No value specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"force-frametime\" ) == 0) {\n          dfb_config->force_frametime = true;\n     } else\n     if (strcmp( name, \"no-force-frametime\" ) == 0) {\n          dfb_config->force_frametime = false;\n     } else\n     if (strcmp( name, \"subsurface-caching\" ) == 0) {\n          dfb_config->subsurface_caching = true;\n     } else\n     if (strcmp( name, \"no-subsurface-caching\" ) == 0) {\n          dfb_config->subsurface_caching = false;\n     } else\n     if (strcmp( name, \"window-surface-policy\" ) == 0) {\n          if (value) {\n               if (!strcmp( value, \"auto\" ))       dfb_config->window_policy = -1;              else\n               if (!strcmp( value, \"videohigh\" ))  dfb_config->window_policy = DWSP_VIDEOHIGH;  else\n               if (!strcmp( value, \"videolow\" ))   dfb_config->window_policy = DWSP_VIDEOLOW;   else\n               if (!strcmp( value, \"systemonly\" )) dfb_config->window_policy = DWSP_SYSTEMONLY; else\n               if (!strcmp( value, \"videoonly\" ))  dfb_config->window_policy = DWSP_VIDEOONLY; \n               else {\n                    D_ERROR( \"DirectFB/Config: '%s': Unknown window surface policy '%s'!\\n\", name, value );\n                    return DFB_INVARG;\n               }\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No window surface policy specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"single-window\" ) == 0) {\n          dfb_config->single_window = true;\n     } else\n     if (strcmp( name, \"no-single-window\" ) == 0) {\n          dfb_config->single_window = false;\n     } else\n     if (strcmp( name, \"translucent-windows\" ) == 0) {\n          dfb_config->translucent_windows = true;\n     } else\n     if (strcmp( name, \"no-translucent-windows\" ) == 0) {\n          dfb_config->translucent_windows = false;\n     } else\n     if (strcmp( name, \"force-windowed\" ) == 0) {\n          dfb_config->force_windowed = true;\n     } else\n     if (strcmp( name, \"no-force-windowed\" ) == 0) {\n          dfb_config->force_windowed = false;\n     } else\n     if (strcmp( name, \"scaled\" ) == 0) {\n          if (value) {\n               int width, height;\n\n               if (sscanf( value, \"%dx%d\", &width, &height ) < 2) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse size!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               dfb_config->scaled.width  = width;\n               dfb_config->scaled.height = height;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No size specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"autoflip-window\" ) == 0) {\n          dfb_config->autoflip_window = true;\n     } else\n     if (strcmp( name, \"no-autoflip-window\" ) == 0) {\n          dfb_config->autoflip_window = false;\n     } else\n     if (strcmp( name, \"cursor\" ) == 0) {\n          dfb_config->no_cursor = false;\n     } else\n     if (strcmp( name, \"no-cursor\" ) == 0) {\n          dfb_config->no_cursor = true;\n     } else\n     if (strcmp( name, \"cursor-videoonly\" ) == 0) {\n          dfb_config->cursor_videoonly = true;\n     } else\n     if (strcmp( name, \"no-cursor-videoonly\" ) == 0) {\n          dfb_config->cursor_videoonly = false;\n     } else\n     if (strcmp( name, \"cursor-resource-id\" ) == 0) {\n          if (value) {\n               unsigned long resource_id;\n\n               if (sscanf( value, \"%lu\", &resource_id ) < 1) {\n                    D_ERROR(\"DirectFB/Config '%s': Could not parse id!\\n\", name);\n                    return DFB_INVARG;\n               }\n\n               dfb_config->cursor_resource_id = resource_id;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No id specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"cursor-automation\" ) == 0) {\n          dfb_config->cursor_automation = true;\n     } else\n     if (strcmp( name, \"no-cursor-automation\" ) == 0) {\n          dfb_config->cursor_automation = false;\n     } else\n     if (strcmp( name, \"discard-repeat-events\" ) == 0) {\n          dfb_config->discard_repeat_events = true;\n     } else\n     if (strcmp( name, \"no-discard-repeat-events\" ) == 0) {\n          dfb_config->discard_repeat_events = false;\n     } else\n     if (strcmp( name, \"lefty\" ) == 0) {\n          dfb_config->lefty = true;\n     } else\n     if (strcmp( name, \"no-lefty\" ) == 0) {\n          dfb_config->lefty = false;\n     } else\n     if (strcmp( name, \"capslock-meta\" ) == 0) {\n          dfb_config->capslock_meta = true;\n     } else\n     if (strcmp( name, \"no-capslock-meta\" ) == 0) {\n          dfb_config->capslock_meta = false;\n     } else\n     if (strcmp( name, \"screenshot-dir\" ) == 0) {\n          if (value) {\n               if (dfb_config->screenshot_dir)\n                    D_FREE( dfb_config->screenshot_dir );\n\n               dfb_config->screenshot_dir = D_STRDUP( value );\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No directory name specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"font-format\" ) == 0) {\n          if (value) {\n               DFBSurfacePixelFormat format;\n\n               format = dfb_pixelformat_parse( value );\n               if (format == DSPF_UNKNOWN) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse format!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               dfb_config->font_format = format;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No format specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"font-premult\" ) == 0) {\n          dfb_config->font_premult = true;\n     } else\n     if (strcmp( name, \"no-font-premult\" ) == 0) {\n          dfb_config->font_premult = false;\n     } else\n     if (strcmp( name, \"font-resource-id\" ) == 0) {\n          if (value) {\n               unsigned long resource_id;\n\n               if (sscanf( value, \"%lu\", &resource_id ) < 1) {\n                    D_ERROR(\"DirectFB/Config '%s': Could not parse id!\\n\", name);\n                    return DFB_INVARG;\n               }\n\n               dfb_config->font_resource_id = resource_id;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No id specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"max-font-rows\" ) == 0) {\n          if (value) {\n               int rows;\n\n               if (sscanf( value, \"%d\", &rows ) < 1) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse value!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n               dfb_config->max_font_rows = rows;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No value specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     } else\n     if (strcmp( name, \"max-font-row-width\" ) == 0) {\n          if (value) {\n               int row_width;\n\n               if (sscanf( value, \"%d\", &row_width ) < 1) {\n                    D_ERROR( \"DirectFB/Config: '%s': Could not parse value!\\n\", name );\n                    return DFB_INVARG;\n               }\n\n\n               dfb_config->max_font_row_width = row_width;\n          }\n          else {\n               D_ERROR( \"DirectFB/Config: '%s': No value specified!\\n\", name );\n               return DFB_INVARG;\n          }\n     }\n     else {\n          dfboption = false;\n          if (fusion_config_set( name, value ) && direct_config_set( name, value ))\n               return DFB_INVARG;\n     }\n\n     if (dfboption)\n          D_DEBUG_AT( DirectFB_Config, \"Set %s '%s'\\n\", name, value ?: \"\" );\n\n     return DFB_OK;\n}\n\nDFBResult\ndfb_config_init( int   *argc,\n                 char **argv[] )\n{\n     DFBResult  ret;\n     char      *home = direct_getenv( \"HOME\" );\n     char      *prog = NULL;\n     char      *session;\n     char      *dfbargs;\n     char       cmdbuf[1024];\n\n     if (dfb_config) {\n          /* Check again for session environment setting. */\n          session = direct_getenv( \"DIRECTFB_SESSION\" );\n          if (session)\n               dfb_config_set( \"session\", session );\n\n          return DFB_OK;\n     }\n\n     config_allocate();\n\n     /* Read system settings. */\n     ret = config_read( SYSCONFDIR\"/directfbrc\" );\n     if (ret && ret != DFB_IO)\n          return ret;\n\n     /* Read user settings. */\n     if (home) {\n          int  len = strlen( home ) + strlen( \"/.directfbrc\" ) + 1;\n          char buf[len];\n\n          snprintf( buf, len, \"%s/.directfbrc\", home );\n\n          ret = config_read( buf );\n          if (ret && ret != DFB_IO)\n               return ret;\n     }\n\n     /* Get application name. */\n     if (argc && *argc && argv && *argv) {\n          prog = strrchr( (*argv)[0], '/' );\n\n          if (prog)\n               prog++;\n          else\n               prog = (*argv)[0];\n     }\n     else {\n          /* If we didn't receive argc/argv, we try the procfs interface. */\n          DirectFile f;\n          size_t     len;\n\n          ret = direct_file_open( &f, \"/proc/self/cmdline\", O_RDONLY, 0 );\n          if (!ret) {\n               ret = direct_file_read( &f, cmdbuf, sizeof(cmdbuf) - 1, &len );\n               if (!ret && len) {\n                    cmdbuf[len] = 0;\n                    prog = strrchr( cmdbuf, '/' );\n                    if (prog)\n                         prog++;\n                    else\n                         prog = cmdbuf;\n               }\n\n               direct_file_close( &f );\n          }\n     }\n\n     /* Read global application settings. */\n     if (prog && prog[0]) {\n          int  len = strlen( SYSCONFDIR\"/directfbrc.\" ) + strlen( prog ) + 1;\n          char buf[len];\n\n          snprintf( buf, len, SYSCONFDIR\"/directfbrc.%s\", prog );\n\n          ret = config_read( buf );\n          if (ret && ret != DFB_IO)\n               return ret;\n     }\n\n     /* Read user application settings. */\n     if (home && prog && prog[0]) {\n          int  len = strlen( home ) + strlen( \"/.directfbrc.\" ) + strlen( prog ) + 1;\n          char buf[len];\n\n          snprintf( buf, len, \"%s/.directfbrc.%s\", home, prog );\n\n          ret = config_read( buf );\n          if (ret && ret != DFB_IO)\n               return ret;\n     }\n\n     /* Read settings from environment variable. */\n     dfbargs = direct_getenv( \"DFBARGS\" );\n     if (dfbargs) {\n          ret = parse_args( dfbargs );\n          if (ret)\n               return ret;\n     }\n\n     /* Active session is used if present, only command line can override. */\n     session = direct_getenv( \"DIRECTFB_SESSION\" );\n     if (session)\n          dfb_config_set( \"session\", session );\n\n     /* Read settings from command line. */\n     if (argc && argv) {\n          int i;\n\n          for (i = 1; i < *argc; i++) {\n               if (strcmp( (*argv)[i], \"--dfb-help\" ) == 0) {\n                    print_config_usage();\n                    exit( 1 );\n               }\n\n               if (strncmp( (*argv)[i], \"--dfb:\", 6 ) == 0) {\n                    ret = parse_args( (*argv)[i] + 6 );\n                    if (ret)\n                         return ret;\n\n                    (*argv)[i] = NULL;\n               }\n          }\n\n          for (i = 1; i < *argc; i++) {\n               int k;\n\n               for (k = i; k < *argc; k++)\n                    if ((*argv)[k] != NULL)\n                         break;\n\n               if (k > i) {\n                    int j;\n\n                    k -= i;\n\n                    for (j = i + k; j < *argc; j++)\n                         (*argv)[j-k] = (*argv)[j];\n\n                    *argc -= k;\n               }\n          }\n     }\n     else if (prog) {\n          /* We have prog, so we try again the proc filesystem. */\n          DirectFile f;\n          size_t     len = strlen( cmdbuf );\n\n          ret = direct_file_open( &f, \"/proc/self/cmdline\", O_RDONLY, 0 );\n          if (!ret) {\n               direct_file_read( &f, cmdbuf, len, &len );\n\n               while (config_read_cmdline( cmdbuf, 1024, &f )) {\n                    if (strcmp( cmdbuf, \"--dfb-help\" ) == 0) {\n                         print_config_usage();\n                         exit( 1 );\n                    }\n\n                    if (strncmp( cmdbuf, \"--dfb:\", 6 ) == 0) {\n                         ret = parse_args( cmdbuf + 6 );\n                         if (ret) {\n                              direct_file_close( &f );\n                              return ret;\n                         }\n                    }\n               }\n\n               direct_file_close( &f );\n          }\n     }\n\n     return DFB_OK;\n}\n\nvoid\ndfb_config_deinit()\n{\n     if (!dfb_config) {\n          return;\n     }\n\n     if (dfb_config->screenshot_dir)\n          D_FREE( dfb_config->screenshot_dir );\n\n     DFBConfigLayer *conf = dfb_config->config_layer;\n     if (conf->palette)\n          D_FREE( conf->palette );\n\n     if (dfb_config->wm)\n          D_FREE( dfb_config->wm );\n\n     if (dfb_config->system)\n          D_FREE( dfb_config->system );\n\n     D_FREE( dfb_config );\n     dfb_config = NULL;\n}\n"
  },
  {
    "path": "src/misc/conf.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __MISC__CONF_H__\n#define __MISC__CONF_H__\n\n#include <core/coredefs.h>\n#include <core/coretypes.h>\n#include <fusion/types.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     bool                                init;\n\n     DFBDisplayLayerConfig               config;\n\n     DFBColor                            src_key;\n     int                                 src_key_index;\n\n     struct {\n          DFBDisplayLayerBackgroundMode  mode;\n          DFBColor                       color;\n          int                            color_index;\n          char                          *filename;\n     } background;\n\n     DFBWindowStackingClass              stacking;\n\n     DFBColor                           *palette;\n     bool                                palette_set;\n\n     int                                 rotate;\n     bool                                rotate_set;\n} DFBConfigLayer;\n\ntypedef enum {\n     DCWF_NONE            = 0x00000000,\n\n     DCWF_CREATE_SURFACE  = 0x00000001,\n     DCWF_CREATE_WINDOW   = 0x00000002,\n\n     DCWF_ALLOCATE_BUFFER = 0x00000010,\n\n     DCWF_ALL             = 0x00000013\n} DFBConfigWarnFlags;\n\ntypedef struct\n{\n     char                       *system;\n     char                       *wm;\n     bool                        banner;\n     bool                        sync;\n     FusionCallExecFlags         call_nodirect;\n     bool                        block_all_signals;\n     bool                        core_sighandler;\n     bool                        ownership_check;\n     bool                        deinit_check;\n     char                       *resource_manager;\n     int                         session;\n     long long                   screen_frame_interval;\n     DFBSurfaceID                primary_id;\n     int                         primary_layer;\n     bool                        primary_only;\n     struct {\n          int                    width;\n          int                    height;\n          int                    depth;\n          DFBSurfacePixelFormat  format;\n     } mode;\n     DFBConfigLayer              layers[MAX_LAYERS];\n     DFBConfigLayer             *config_layer;\n     unsigned int                graphics_state_call_limit;\n     bool                        software_only;\n     bool                        hardware_only;\n     bool                        software_warn;\n     bool                        software_trace;\n     unsigned int                gfxcard_stats;\n     unsigned int                videoram_limit;\n     bool                        gfx_emit_early;\n     bool                        startstop;\n     DFBSurfaceRenderOptions     render_options;\n     int                         keep_accumulators;\n     bool                        mmx;\n     bool                        neon;\n     struct {\n          DFBConfigWarnFlags     flags;\n          struct {\n               DFBDimension      min_size;\n          } create_surface;\n          struct {\n               DFBDimension      min_size;\n          } allocate_buffer;\n     } warn;\n     bool                        surface_clear;\n     bool                        thrifty_surface_buffers;\n     int                         surface_shmpool_size;\n     unsigned int                system_surface_align_base;\n     unsigned int                system_surface_align_pitch;\n     long long                   max_frame_advance;\n     bool                        force_frametime;\n     bool                        subsurface_caching;\n     int                         window_policy;\n     bool                        single_window;\n     bool                        translucent_windows;\n     bool                        force_windowed;\n     struct {\n          int                    width;\n          int                    height;\n     } scaled;\n     bool                        autoflip_window;\n     bool                        no_cursor;\n     bool                        cursor_videoonly;\n     unsigned long               cursor_resource_id;\n     bool                        cursor_automation;\n     bool                        discard_repeat_events;\n     bool                        lefty;\n     bool                        capslock_meta;\n     char                       *screenshot_dir;\n     DFBSurfacePixelFormat       font_format;\n     bool                        font_premult;\n     unsigned long               font_resource_id;\n     int                         max_font_rows;\n     int                         max_font_row_width;\n} DFBConfig;\n\n/**********************************************************************************************************************/\n\nextern DFBConfig  *dfb_config;\n\nextern const char *dfb_config_usage;\n\n/*\n * Set indiviual option.\n */\nDFBResult dfb_config_set   ( const char  *name,\n                             const char  *value );\n\n/*\n * Allocate config struct, fill with defaults and parse command line options for overrides.\n */\nDFBResult dfb_config_init  ( int         *argc,\n                             char       **argv[] );\n\n/*\n * Free config struct.\n */\nvoid      dfb_config_deinit( void );\n\n#endif\n"
  },
  {
    "path": "src/misc/gfx_util.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <config.h>\n#include <core/palette.h>\n#include <core/surface.h>\n#include <direct/memcpy.h>\n#include <gfx/clip.h>\n#include <gfx/convert.h>\n#include <misc/gfx_util.h>\n\n/**********************************************************************************************************************/\n\n#define SUBSAMPLE_BITS 4\n#define SUBSAMPLE       (1 << SUBSAMPLE_BITS)\n#define SUBSAMPLE_MASK ((1 << SUBSAMPLE_BITS) - 1)\n\n#define SCALE_SHIFT 16\n\n#define LINE_PTR(dst,caps,y,h,pitch)                                                                      \\\n     ((caps & DSCAPS_SEPARATED) ? ((u8*) (dst) + (y) / 2 * (pitch) + ((y) % 2 ? (h) / 2 * (pitch) : 0)) : \\\n                                  ((u8*) (dst) + (y) * (pitch)))\n\ntypedef struct {\n     int   *weights;\n     int    n_x;\n     int    n_y;\n     float  x_offset;\n     float  y_offset;\n} PixopsFilter;\n\n/**********************************************************************************************************************/\n\nstatic void\nwrite_argb_span( u32         *src,\n                 u8          *dst[],\n                 int          len,\n                 int          x,\n                 int          y,\n                 CoreSurface *dst_surface )\n{\n     int          i, j;\n     u32          a, y0, u0, v0, y1, u1, v1;\n     u8          *d       = dst[0];\n     u8          *d1      = dst[1];\n     u8          *d2      = dst[2];\n     CorePalette *palette = dst_surface->palette;\n\n     if (dst_surface->config.caps & DSCAPS_PREMULTIPLIED) {\n          for (i = 0; i < len; i++) {\n               u32 s = src[i];\n\n               a = (s >> 24) + 1;\n\n               src[i] = ((((s & 0x00ff00ff) * a) >> 8) & 0x00ff00ff) |\n                        ((((s & 0x0000ff00) * a) >> 8) & 0x0000ff00) |\n                        (   s & 0xff000000                         );\n          }\n     }\n\n#define RGB_TO_YCBCR(r,g,b,y,cb,cr)                          \\\n     if (dst_surface->config.colorspace == DSCS_BT601)       \\\n          RGB_TO_YCBCR_BT601(r,g,b,y,cb,cr);                 \\\n     else if (dst_surface->config.colorspace == DSCS_BT709)  \\\n          RGB_TO_YCBCR_BT709(r,g,b,y,cb,cr);                 \\\n     else if (dst_surface->config.colorspace == DSCS_BT2020) \\\n          RGB_TO_YCBCR_BT2020(r,g,b,y,cb,cr);                \\\n     else {                                                  \\\n          y = 16;                                            \\\n          cb = cr = 128;                                     \\\n     }\n\n     switch (dst_surface->config.format) {\n          case DSPF_A1:\n               for (i = 0; i < len; i++) {\n                    if (i & 7)\n                         d[i>>3] |= (src[i] >> 31) << (7 - (i & 7));\n                    else\n                         d[i>>3]  = (src[i] >> 24) & 0x80;\n               }\n               break;\n\n          case DSPF_A1_LSB:\n               for (i = 0; i < len; i++) {\n                    if (i & 7)\n                         d[i>>3] |= (src[i] >> 31) << (i & 7);\n                    else\n                         d[i>>3]  = (src[i] >> 31);\n               }\n               break;\n\n          case DSPF_A4:\n               for (i = 0, j = 0; i < len; i += 2, j++)\n                    d[j] = ((src[i] >> 24) & 0xf0) | (src[i+1] >> 28);\n               break;\n\n          case DSPF_A8:\n               for (i = 0; i < len; i++)\n                    d[i] = src[i] >> 24;\n               break;\n\n          case DSPF_RGB332:\n               for (i = 0; i < len; i++)\n                    d[i] = ARGB_TO_RGB332( src[i] );\n               break;\n\n          case DSPF_ARGB1555:\n               for (i = 0; i < len; i++)\n                    ((u16*) d)[i] = ARGB_TO_ARGB1555( src[i] );\n               break;\n\n          case DSPF_ARGB2554:\n               for (i = 0; i < len; i++)\n                    ((u16*) d)[i] = ARGB_TO_ARGB2554( src[i] );\n               break;\n\n          case DSPF_ARGB4444:\n               for (i = 0; i < len; i++)\n                    ((u16*) d)[i] = ARGB_TO_ARGB4444( src[i] );\n               break;\n\n          case DSPF_RGBA4444:\n               for (i = 0; i < len; i++)\n                    ((u16*) d)[i] = ARGB_TO_RGBA4444( src[i] );\n               break;\n\n          case DSPF_ARGB8565:\n               for (i = 0, j = -1; i < len; i++) {\n                    u32 pixel = ARGB_TO_ARGB8565 ( src[i] );\n#ifdef WORDS_BIGENDIAN\n                    d[++j] = (pixel >> 16) & 0xff;\n                    d[++j] = (pixel >>  8) & 0xff;\n                    d[++j] =  pixel        & 0xff;\n#else\n                    d[++j] =  pixel        & 0xff;\n                    d[++j] = (pixel >>  8) & 0xff;\n                    d[++j] = (pixel >> 16) & 0xff;\n#endif\n               }\n               break;\n\n          case DSPF_RGB16:\n               for (i = 0; i < len; i++)\n                    ((u16*) d)[i] = ARGB_TO_RGB16( src[i] );\n               break;\n\n          case DSPF_ARGB1666:\n               for (i = 0; i < len; i++) {\n                    u32 pixel = PIXEL_ARGB1666( src[i] >> 24, src[i] >> 16, src[i] >> 8, src[i] );\n                    *d++ = pixel;\n                    *d++ = pixel >>  8;\n                    *d++ = pixel >> 16;\n               }\n               break;\n\n          case DSPF_ARGB6666:\n               for (i = 0; i < len; i++) {\n                    u32 pixel = PIXEL_ARGB6666( src[i] >> 24, src[i] >> 16, src[i] >> 8, src[i] );\n                    *d++ = pixel;\n                    *d++ = pixel >>  8;\n                    *d++ = pixel >> 16;\n               }\n               break;\n\n          case DSPF_RGB18:\n               for (i = 0; i < len; i++) {\n                    u32 pixel = PIXEL_RGB18( src[i] >> 16, src[i] >> 8, src[i] );\n                    *d++ = pixel;\n                    *d++ = pixel >>  8;\n                    *d++ = pixel >> 16;\n               }\n               break;\n\n          case DSPF_RGB24:\n               for (i = 0; i < len; i++) {\n#ifdef WORDS_BIGENDIAN\n                    *d++ = src[i] >> 16;\n                    *d++ = src[i] >>  8;\n                    *d++ = src[i];\n#else\n                    *d++ = src[i];\n                    *d++ = src[i] >>  8;\n                    *d++ = src[i] >> 16;\n#endif\n               }\n               break;\n\n          case DSPF_BGR24:\n               for (i = 0; i < len; i++) {\n#ifdef WORDS_BIGENDIAN\n                    *d++ = src[i];\n                    *d++ = src[i] >>  8;\n                    *d++ = src[i] >> 16;\n#else\n                    *d++ = src[i] >> 16;\n                    *d++ = src[i] >>  8;\n                    *d++ = src[i];\n#endif\n               }\n               break;\n\n          case DSPF_RGB32:\n          case DSPF_ARGB:\n               direct_memcpy( d, src, len * 4 );\n               break;\n\n          case DSPF_ABGR:\n               for (i = 0; i < len; i++)\n                    ((u32*) d)[i] = ARGB_TO_ABGR( src[i] );\n               break;\n\n          case DSPF_AiRGB:\n               for (i = 0; i < len; i++)\n                    ((u32*) d)[i] = src[i] ^ 0xff000000;\n               break;\n\n          case DSPF_LUT8:\n               if (palette) {\n                    for (i = 0; i < len; i++) {\n                         d[i] = dfb_palette_search( palette, (src[i] >> 16) & 0xff,\n                                                             (src[i] >>  8) & 0xff,\n                                                              src[i]        & 0xff,\n                                                             (src[i] >> 24) & 0xff );\n                    }\n               }\n               break;\n\n          case DSPF_ALUT44:\n               if (palette) {\n                    for (i = 0; i < len; i++) {\n                         d[i] = ((src[i] >> 24) & 0xf0) + dfb_palette_search( palette, (src[i] >> 16) & 0xff,\n                                                                                       (src[i] >>  8) & 0xff,\n                                                                                        src[i]        & 0xff,\n                                                                                       0x80 );\n                    }\n               }\n               break;\n\n          case DSPF_YUY2:\n               if (x & 1) {\n                    RGB_TO_YCBCR( (src[0] >> 16) & 0xff, (src[0] >> 8) & 0xff, src[0] & 0xff, y0, u0, v0 );\n                    *((u16*) d) = y0 | (v0 << 8);\n                    d += 2;\n                    src++;\n                    len--;\n               }\n               for (i = 0; i < (len - 1); i += 2) {\n                    RGB_TO_YCBCR( (src[i]   >> 16) & 0xff, (src[i]   >> 8) & 0xff, src[i]   & 0xff, y0, u0, v0 );\n                    RGB_TO_YCBCR( (src[i+1] >> 16) & 0xff, (src[i+1] >> 8) & 0xff, src[i+1] & 0xff, y1, u1, v1 );\n                    u0 = (u0 + u1) >> 1;\n                    v1 = (v0 + v1) >> 1;\n                    ((u16*) d)[i]   = y0 | (u0 << 8);\n                    ((u16*) d)[i+1] = y1 | (v1 << 8);\n               }\n               if (len & 1) {\n                    src += len - 1;\n                    d   += (len - 1) * 2;\n                    RGB_TO_YCBCR( (*src >> 16) & 0xff, (*src >> 8) & 0xff, *src & 0xff, y0, u0, v0 );\n                    *((u16*) d) = y0 | (u0 << 8);\n               }\n               break;\n\n          case DSPF_UYVY:\n               if (x & 1) {\n                    RGB_TO_YCBCR( (src[0] >> 16) & 0xff, (src[0] >> 8) & 0xff, src[0] & 0xff, y0, u0, v0 );\n                    *((u16*) d) = v0 | (y0 << 8);\n                    d += 2;\n                    src++;\n                    len--;\n               }\n               for (i = 0; i < (len - 1); i += 2) {\n                    RGB_TO_YCBCR( (src[i]   >> 16) & 0xff, (src[i]   >> 8) & 0xff, src[i]   & 0xff, y0, u0, v0 );\n                    RGB_TO_YCBCR( (src[i+1] >> 16) & 0xff, (src[i+1] >> 8) & 0xff, src[i+1] & 0xff, y1, u1, v1 );\n                    u0 = (u0 + u1) >> 1;\n                    v1 = (v0 + v1) >> 1;\n                    ((u16*) d)[i]   = u0 | (y0 << 8);\n                    ((u16*) d)[i+1] = v1 | (y1 << 8);\n               }\n               if (len & 1) {\n                    src += len - 1;\n                    d   += (len - 1) * 2;\n                    RGB_TO_YCBCR( (*src >> 16) & 0xff, (*src >> 8) & 0xff, *src & 0xff, y0, u0, v0 );\n                    *((u16*) d) = u0 | (y0 << 8);\n               }\n               break;\n\n          case DSPF_AYUV:\n               for (i = 0; i < len; i++) {\n                    RGB_TO_YCBCR( (src[i] >> 16) & 0xff, (src[i] >> 8) & 0xff, src[i] & 0xff, y0, u0, v0 );\n                    a = (src[i] >> 24) & 0xff;\n                    ((u32*) d)[i] = PIXEL_AYUV( a, y0, u0, v0 );\n               }\n               break;\n\n          case DSPF_AVYU:\n               for (i = 0; i < len; i++) {\n                    RGB_TO_YCBCR( (src[i] >> 16) & 0xff, (src[i] >> 8) & 0xff, src[i] & 0xff, y0, u0, v0 );\n                    a = (src[i] >> 24) & 0xff;\n                    ((u32*) d)[i] = PIXEL_AVYU( a, y0, u0, v0 );\n               }\n               break;\n\n          case DSPF_VYU:\n               for (i = 0, j = -1; i < len; i++) {\n                    RGB_TO_YCBCR( (src[i] >> 16) & 0xff, (src[i] >> 8) & 0xff, src[i] & 0xff, y0, u0, v0 );\n#ifdef WORDS_BIGENDIAN\n                    d[++j] = v0;\n                    d[++j] = y0;\n                    d[++j] = u0;\n#else\n                    d[++j] = u0;\n                    d[++j] = y0;\n                    d[++j] = v0;\n#endif\n               }\n               break;\n\n          case DSPF_I420:\n          case DSPF_YV12:\n          case DSPF_Y42B:\n          case DSPF_YV16:\n               for (i = 0; i < (len - 1); i += 2) {\n                    RGB_TO_YCBCR( (src[i]   >> 16) & 0xff, (src[i]   >> 8) & 0xff, src[i]   & 0xff, y0, u0, v0 );\n                    RGB_TO_YCBCR( (src[i+1] >> 16) & 0xff, (src[i+1] >> 8) & 0xff, src[i+1] & 0xff, y1, u1, v1 );\n                    d[i]   = y0;\n                    d[i+1] = y1;\n                    if (y & 1) {\n                         d1[i>>1] = (u0 + u1) >> 1;\n                         d2[i>>1] = (v0 + v1) >> 1;\n                    }\n               }\n               if (len & 1) {\n                    i = len - 1;\n                    RGB_TO_YCBCR( (src[i] >> 16) & 0xff, (src[i] >> 8) & 0xff, src[i] & 0xff, y0, u0, v0 );\n                    d[i] = y0;\n                    if (y & 1) {\n                         d1[i>>1] = u0;\n                         d2[i>>1] = v0;\n                    }\n               }\n               break;\n\n          case DSPF_Y444:\n          case DSPF_YV24: {\n               for (i = 0; i < len; i++)\n                    RGB_TO_YCBCR( (src[i] >> 16) & 0xff, (src[i] >> 8) & 0xff, src[i] & 0xff, d[i], d1[i], d2[i] );\n               break;\n          }\n\n          case DSPF_NV12:\n          case DSPF_NV16:\n               for (i = 0; i < (len - 1); i += 2) {\n                    RGB_TO_YCBCR( (src[i]   >> 16) & 0xff, (src[i]   >> 8) & 0xff, src[i]   & 0xff, y0, u0, v0 );\n                    RGB_TO_YCBCR( (src[i+1] >> 16) & 0xff, (src[i+1] >> 8) & 0xff, src[i+1] & 0xff, y1, u1, v1 );\n                    d[i]   = y0;\n                    d[i+1] = y1;\n                    if (dst_surface->config.format == DSPF_NV16 || y & 1) {\n#ifdef WORDS_BIGENDIAN\n                         ((u16*) d1)[i>>1] = ((v0 + v1) >> 1) | (((u0 + u1) >> 1) << 8);\n#else\n                         ((u16*) d1)[i>>1] = ((u0 + u1) >> 1) | (((v0 + v1) >> 1) << 8);\n#endif\n                    }\n               }\n               if (len & 1) {\n                    i = len - 1;\n                    RGB_TO_YCBCR( (src[i] >> 16) & 0xff, (src[i] >> 8) & 0xff, src[i] & 0xff, y0, u0, v0 );\n                    d[i] = y0;\n                    if (dst_surface->config.format == DSPF_NV16 || y & 1)\n#ifdef WORDS_BIGENDIAN\n                         ((u16*) d1)[i>>1] = v0 | (u0 << 8);\n#else\n                         ((u16*) d1)[i>>1] = u0 | (v0 << 8);\n#endif\n               }\n               break;\n\n          case DSPF_NV21:\n          case DSPF_NV61:\n               for (i = 0; i < (len - 1); i += 2) {\n                    RGB_TO_YCBCR( (src[i]   >> 16) & 0xff, (src[i]   >> 8) & 0xff, src[i]   & 0xff, y0, u0, v0 );\n                    RGB_TO_YCBCR( (src[i+1] >> 16) & 0xff, (src[i+1] >> 8) & 0xff, src[i+1] & 0xff, y1, u1, v1 );\n                    d[i]   = y0;\n                    d[i+1] = y1;\n                    if (dst_surface->config.format == DSPF_NV61 || y & 1) {\n#ifdef WORDS_BIGENDIAN\n                         ((u16*) d1)[i>>1] = ((u0 + u1) >> 1) | (((v0 + v1) >> 1) << 8);\n#else\n                         ((u16*) d1)[i>>1] = ((v0 + v1) >> 1) | (((u0 + u1) >> 1) << 8);\n#endif\n                    }\n               }\n               if (len & 1) {\n                    i = len - 1;\n                    RGB_TO_YCBCR( (src[i] >> 16) & 0xff, (src[i] >> 8) & 0xff, src[i] & 0xff, y0, u0, v0 );\n                    d[i] = y0;\n                    if (dst_surface->config.format == DSPF_NV61 || y & 1)\n#ifdef WORDS_BIGENDIAN\n                         ((u16*) d1)[i>>1] = u0 | (v0 << 8);\n#else\n                         ((u16*) d1)[i>>1] = v0 | (u0 << 8);\n#endif\n               }\n               break;\n\n          case DSPF_NV24:\n               for (i = 0; i < len; i++) {\n                    RGB_TO_YCBCR( (src[i] >> 16) & 0xff, (src[i] >> 8) & 0xff, src[i] & 0xff, y0, u0, v0 );\n                    d[i]      = y0;\n                    d1[2*i]   = u0;\n                    d1[2*i+1] = v0;\n               }\n               break;\n\n          case DSPF_NV42:\n               for (i = 0; i < len; i++) {\n                    RGB_TO_YCBCR( (src[i] >> 16) & 0xff, (src[i] >> 8) & 0xff, src[i] & 0xff, y0, u0, v0 );\n                    d[i]      = y0;\n                    d1[2*i]   = v0;\n                    d1[2*i+1] = u0;\n               }\n               break;\n\n          case DSPF_RGB555:\n               for (i = 0; i < len; i++)\n                    ((u16*) d)[i] = ARGB_TO_RGB555( src[i] );\n               break;\n\n          case DSPF_BGR555:\n               for (i = 0; i < len; i++)\n                    ((u16*) d)[i] = ARGB_TO_BGR555( src[i] );\n               break;\n\n          case DSPF_RGB444:\n               for (i = 0; i < len; i++)\n                    ((u16*) d)[i] = ARGB_TO_RGB444( src[i] );\n               break;\n\n          case DSPF_RGBA5551:\n               for (i = 0; i < len; i++)\n                    ((u16*) d)[i] = ARGB_TO_RGBA5551( src[i] );\n               break;\n\n          case DSPF_RGBAF88871:\n               for (i = 0; i < len; i++)\n                    ((u32*) d)[i] = ARGB_TO_RGBAF88871( src[i] );\n               break;\n\n          default:\n               D_ONCE( \"unimplemented destination format (0x%08x)\", (unsigned int) dst_surface->config.format );\n               break;\n     }\n\n#undef RGB_TO_YCBCR\n}\n\nvoid\ndfb_copy_buffer_32( u32             *src,\n                    void            *dst,\n                    int              dpitch,\n                    DFBRectangle    *drect,\n                    CoreSurface     *dst_surface,\n                    const DFBRegion *dst_clip )\n{\n     int  x, y;\n     u8  *dst1 = NULL;\n     u8  *dst2 = NULL;\n\n     if (dst_clip) {\n          int sx = 0, sy = 0;\n\n          if (drect->x < dst_clip->x1) {\n               sx = dst_clip->x1 - drect->x;\n               drect->w -= sx;\n               drect->x += sx;\n          }\n\n          if (drect->y < dst_clip->y1) {\n               sy = dst_clip->y1 - drect->y;\n               drect->h -= sy;\n               drect->y += sy;\n          }\n\n          if ((drect->x + drect->w - 1) > dst_clip->x2) {\n               drect->w -= drect->x + drect->w - 1 - dst_clip->x2;\n          }\n\n          if ((drect->y + drect->h - 1) > dst_clip->y2) {\n               drect->h -= drect->y + drect-> h - 1 - dst_clip->y2;\n          }\n\n          src += sy * drect->w + sx;\n     }\n\n     if (drect->w < 1 || drect->h < 1)\n          return;\n\n     switch (dst_surface->config.format) {\n          case DSPF_I420:\n               dst1 = (u8*) dst + dpitch * dst_surface->config.size.h;\n               dst2 = dst1 + dpitch / 2 * dst_surface->config.size.h / 2;\n               break;\n          case DSPF_YV12:\n               dst2 = (u8*) dst + dpitch * dst_surface->config.size.h;\n               dst1 = dst2 + dpitch / 2 * dst_surface->config.size.h / 2;\n               break;\n          case DSPF_Y42B:\n               dst1 = (u8*) dst + dpitch * dst_surface->config.size.h;\n               dst2 = dst1 + dpitch / 2 * dst_surface->config.size.h;\n               break;\n          case DSPF_YV16:\n               dst2 = (u8*) dst + dpitch * dst_surface->config.size.h;\n               dst1 = dst2 + dpitch / 2 * dst_surface->config.size.h;\n               break;\n          case DSPF_Y444:\n               dst1 = (u8*) dst + dpitch * dst_surface->config.size.h;\n               dst2 = dst1 + dpitch * dst_surface->config.size.h;\n               break;\n          case DSPF_YV24:\n               dst2 = (u8*) dst + dpitch * dst_surface->config.size.h;\n               dst1 = dst2 + dpitch * dst_surface->config.size.h;\n               break;\n          case DSPF_NV12:\n          case DSPF_NV21:\n          case DSPF_NV16:\n          case DSPF_NV61:\n          case DSPF_NV24:\n          case DSPF_NV42:\n               dst1 = (u8*) dst + dpitch * dst_surface->config.size.h;\n               break;\n          default:\n               break;\n     }\n\n     x = drect->x;\n\n     for (y = drect->y; y < drect->y + drect->h; y++) {\n          u8 *d[3];\n\n          d[0] = LINE_PTR( dst, dst_surface->config.caps, y, dst_surface->config.size.h, dpitch ) +\n                 DFB_BYTES_PER_LINE( dst_surface->config.format, x );\n\n          switch (dst_surface->config.format) {\n               case DSPF_I420:\n               case DSPF_YV12:\n                    d[1] = LINE_PTR( dst1, dst_surface->config.caps, y / 2, dst_surface->config.size.h / 2,\n                                     dpitch / 2 ) + x / 2;\n                    d[2] = LINE_PTR( dst2, dst_surface->config.caps, y / 2, dst_surface->config.size.h / 2,\n                                     dpitch / 2 ) + x / 2;\n                    break;\n               case DSPF_Y42B:\n               case DSPF_YV16:\n                    d[1] = LINE_PTR( dst1, dst_surface->config.caps, y, dst_surface->config.size.h,\n                                     dpitch / 2 ) + x / 2;\n                    d[2] = LINE_PTR( dst2, dst_surface->config.caps, y, dst_surface->config.size.h,\n                                     dpitch / 2 ) + x / 2;\n                    break;\n               case DSPF_Y444:\n               case DSPF_YV24:\n                    d[1] = LINE_PTR( dst1, dst_surface->config.caps, y, dst_surface->config.size.h,\n                                     dpitch ) + x;\n                    d[2] = LINE_PTR( dst2, dst_surface->config.caps, y, dst_surface->config.size.h,\n                                     dpitch ) + x;\n                 break;\n               case DSPF_NV12:\n               case DSPF_NV21:\n                    d[1] = LINE_PTR( dst1, dst_surface->config.caps, y / 2, dst_surface->config.size.h / 2,\n                                     dpitch ) + (x & ~1);\n                    break;\n               case DSPF_NV16:\n               case DSPF_NV61:\n                    d[1] = LINE_PTR( dst1, dst_surface->config.caps, y, dst_surface->config.size.h,\n                                     dpitch ) + (x & ~1);\n                    break;\n               case DSPF_NV24:\n               case DSPF_NV42:\n                    d[1] = LINE_PTR( dst1, dst_surface->config.caps, y, dst_surface->config.size.h,\n                                     dpitch * 2 ) + x * 2;\n                    break;\n               default:\n                    break;\n          }\n\n          write_argb_span( src, d, drect->w, x, y, dst_surface );\n\n          src += drect->w;\n     }\n}\n\nstatic int\nbilinear_make_fast_weights( PixopsFilter *filter,\n                            float         x_scale,\n                            float         y_scale )\n{\n     int    i_offset, j_offset;\n     float *x_weights, *y_weights;\n     int    n_x, n_y;\n\n     if (x_scale > 1.0) { /* Bilinear */\n          n_x = 2;\n          filter->x_offset = 0.5 * (1.0 / x_scale - 1);\n     }\n     else {               /* Tile */\n          n_x = D_ICEIL ( 1.0 + 1.0 / x_scale );\n          filter->x_offset = 0.0;\n     }\n\n     if (y_scale > 1.0) { /* Bilinear */\n          n_y = 2;\n          filter->y_offset = 0.5 * (1.0 / y_scale - 1);\n     }\n     else {               /* Tile */\n          n_y = D_ICEIL ( 1.0 + 1.0 / y_scale );\n          filter->y_offset = 0.0;\n     }\n\n     if (n_x > 64)\n          n_x = 64;\n\n     if (n_y > 64)\n          n_y = 64;\n\n     filter->n_y = n_y;\n     filter->n_x = n_x;\n     filter->weights = D_MALLOC( SUBSAMPLE * SUBSAMPLE * n_x * n_y * sizeof(int) );\n     if (!filter->weights) {\n          D_WARN( \"couldn't allocate memory for scaling\" );\n          return 0;\n     }\n\n     x_weights = alloca( n_x * sizeof(float) );\n     y_weights = alloca( n_y * sizeof(float) );\n     if (!x_weights || !y_weights) {\n          D_FREE( filter->weights );\n          D_WARN( \"couldn't allocate memory for scaling\" );\n          return 0;\n     }\n\n     for (i_offset = 0; i_offset < SUBSAMPLE; i_offset++)\n          for (j_offset = 0; j_offset < SUBSAMPLE; j_offset++) {\n               int    i, j;\n               float  x             = j_offset / 16.0;\n               float  y             = i_offset / 16.0;\n               int   *pixel_weights = filter->weights + ((i_offset * SUBSAMPLE) + j_offset) * n_x * n_y;\n\n               if (x_scale > 1.0) { /* Bilinear */\n                    for (j = 0; j < n_x; j++) {\n                         x_weights[j] = ((j == 0) ? (1 - x) : x) / x_scale;\n                    }\n               }\n               else {               /* Tile */\n                    for (j = 0; j < n_x; j++) {\n                         if (j < x) {\n                              if (j + 1 > x)\n                                   x_weights[j] = MIN( j + 1, x + 1.0 / x_scale ) - x;\n                              else\n                                   x_weights[j] = 0;\n                         }\n                         else {\n                              if (x + 1 / x_scale > j)\n                                   x_weights[j] = MIN( j + 1, x + 1.0 / x_scale ) - j;\n                              else\n                                   x_weights[j] = 0;\n                         }\n                    }\n               }\n\n               if (y_scale > 1.0) { /* Bilinear */\n                    for (i = 0; i < n_y; i++) {\n                         y_weights[i] = ((i == 0) ? (1 - y) : y) / y_scale;\n                    }\n               }\n               else {               /* Tile */\n                    for (i = 0; i < n_y; i++) {\n                         if (i < y) {\n                              if (i + 1 > y)\n                                   y_weights[i] = MIN( i + 1, y + 1.0 / y_scale ) - y;\n                              else\n                                   y_weights[i] = 0;\n                         }\n                         else {\n                              if (y + 1 / y_scale > i)\n                                   y_weights[i] = MIN( i + 1, y + 1.0 / y_scale ) - i;\n                              else\n                                   y_weights[i] = 0;\n                         }\n                    }\n               }\n\n               for (i = 0; i < n_y; i++) {\n                    for (j = 0; j < n_x; j++) {\n                         pixel_weights[n_x * i + j] = 65536 * x_weights[j] * x_scale * y_weights[i] * y_scale;\n                    }\n               }\n          }\n\n     return 1;\n}\n\nstatic void\nscale_pixel( const int  *weights,\n             int         n_x,\n             int         n_y,\n             u32        *dst,\n             const u32 **src,\n             int         x,\n             int         sw )\n{\n     int i, j;\n     u32 r = 0, g = 0, b = 0, a = 0;\n\n     for (i = 0; i < n_y; i++) {\n          const int *pixel_weights = weights + n_x * i;\n\n          for (j = 0; j < n_x; j++) {\n               const u32 *q;\n\n               if (x + j < 0)\n                    q = src[i];\n               else if (x + j < sw)\n                    q = src[i] + x + j;\n               else\n                    q = src[i] + sw - 1;\n\n               b += pixel_weights[j] * ( *q & 0xff             );\n               g += pixel_weights[j] * ((*q & 0xff00)     >>  8);\n               r += pixel_weights[j] * ((*q & 0xff0000)   >> 16);\n               a += pixel_weights[j] * ((*q & 0xff000000) >> 24);\n          }\n     }\n\n     r = (r >> 16) == 0xff ? 0xff : (r + 0x8000) >> 16;\n     g = (g >> 16) == 0xff ? 0xff : (g + 0x8000) >> 16;\n     b = (b >> 16) == 0xff ? 0xff : (b + 0x8000) >> 16;\n     a = (a >> 16) == 0xff ? 0xff : (a + 0x8000) >> 16;\n\n     *dst = (a << 24) | (r << 16) | (g << 8) | b;\n}\n\nstatic u32 *\nscale_line( const int  *weights,\n            int         n_x,\n            int         n_y,\n            u32        *dst,\n            u32        *dst_end,\n            const u32 **src,\n            int         x,\n            int         x_step,\n            int         sw )\n{\n     while (dst < dst_end) {\n          int        i, j;\n          u32        r, g, b, a;\n          int        x_scaled      = x >> SCALE_SHIFT;\n          const int *pixel_weights = weights + ((x >> (SCALE_SHIFT - SUBSAMPLE_BITS)) & SUBSAMPLE_MASK) * n_x * n_y;\n\n          r = g = b = a = 0;\n\n          for (i = 0; i < n_y; i++) {\n               const int *line_weights = pixel_weights + n_x * i;\n               const u32 *q            = src[i] + x_scaled;\n\n               for (j = 0; j < n_x; j++) {\n                    b += line_weights[j] * ( *q & 0xff             );\n                    g += line_weights[j] * ((*q & 0xff00)     >>  8);\n                    r += line_weights[j] * ((*q & 0xff0000)   >> 16);\n                    a += line_weights[j] * ((*q & 0xff000000) >> 24);\n\n                    if (x_scaled + j < sw - 1)\n                         q++;\n               }\n          }\n\n          r = (r >> 16) == 0xff ? 0xff : (r + 0x8000) >> 16;\n          g = (g >> 16) == 0xff ? 0xff : (g + 0x8000) >> 16;\n          b = (b >> 16) == 0xff ? 0xff : (b + 0x8000) >> 16;\n          a = (a >> 16) == 0xff ? 0xff : (a + 0x8000) >> 16;\n\n          *dst++ = (a << 24) | (r << 16) | (g << 8) | b;\n\n          x += x_step;\n     }\n\n     return dst;\n}\n\nvoid\ndfb_scale_linear_32( u32             *src,\n                     int              sw,\n                     int              sh,\n                     void            *dst,\n                     int              dpitch,\n                     DFBRectangle    *drect,\n                     CoreSurface     *dst_surface,\n                     const DFBRegion *dst_clip )\n{\n     float         scale_x, scale_y;\n     int           x, y;\n     int           sx, sy;\n     int           x_step, y_step;\n     int           scaled_x_offset;\n     PixopsFilter  filter;\n     u32          *scaled_src;\n     u8           *dst1  = NULL;\n     u8           *dst2  = NULL;\n     int           dw    = drect->w;\n     int           dh    = drect->h;\n     DFBRectangle  srect = { 0, 0, sw, sh };\n\n     if (dw == sw && dh == sh) {\n          dfb_copy_buffer_32( src, dst, dpitch, drect, dst_surface, dst_clip );\n          return;\n     }\n\n     if (dst_clip)\n          dfb_clip_stretchblit( dst_clip, &srect, drect );\n\n     if (srect.w < 1 || srect.h < 1 || drect->w < 1 || drect->h < 1)\n          return;\n\n     src += srect.y * sw + srect.x;\n\n     scale_x = (float) drect->w / srect.w;\n     scale_y = (float) drect->h / srect.h;\n\n     x_step = (1 << SCALE_SHIFT) / scale_x;\n     y_step = (1 << SCALE_SHIFT) / scale_y;\n\n     if (!bilinear_make_fast_weights( &filter, scale_x, scale_y ))\n          return;\n\n     scaled_x_offset = D_IFLOOR( filter.x_offset * (1 << SCALE_SHIFT) );\n     sy              = D_IFLOOR( filter.y_offset * (1 << SCALE_SHIFT) );\n\n     scaled_src = alloca( drect->w * 4 );\n\n     switch (dst_surface->config.format) {\n          case DSPF_I420:\n               dst1 = (u8*) dst + dpitch * dst_surface->config.size.h;\n               dst2 = dst1 + dpitch / 2 * dst_surface->config.size.h / 2;\n               break;\n          case DSPF_YV12:\n               dst2 = (u8*) dst + dpitch * dst_surface->config.size.h;\n               dst1 = dst2 + dpitch / 2 * dst_surface->config.size.h / 2;\n               break;\n          case DSPF_Y42B:\n               dst1 = (u8*) dst + dpitch * dst_surface->config.size.h;\n               dst2 = dst1 + dpitch / 2 * dst_surface->config.size.h;\n               break;\n          case DSPF_YV16:\n               dst2 = (u8*) dst + dpitch * dst_surface->config.size.h;\n               dst1 = dst2 + dpitch / 2 * dst_surface->config.size.h;\n               break;\n          case DSPF_Y444:\n               dst1 = (u8*) dst + dpitch * dst_surface->config.size.h;\n               dst2 = dst1 + dpitch * dst_surface->config.size.h;\n               break;\n          case DSPF_YV24:\n               dst2 = (u8*) dst + dpitch * dst_surface->config.size.h;\n               dst1 = dst2 + dpitch * dst_surface->config.size.h;\n               break;\n          case DSPF_NV12:\n          case DSPF_NV21:\n          case DSPF_NV16:\n          case DSPF_NV61:\n          case DSPF_NV24:\n          case DSPF_NV42:\n               dst1 = (u8*) dst + dpitch * dst_surface->config.size.h;\n               break;\n          default:\n               break;\n     }\n\n     x = drect->x;\n\n     for (y = drect->y; y < drect->y + drect->h; y++) {\n          int         i;\n          int         x_start, y_start;\n          const int  *run_weights;\n          u8         *d[3];\n          const u32 **bufs;\n          u32        *buf     = scaled_src;\n          u32        *buf_end = scaled_src + drect->w;\n          u32        *new_buf;\n\n          y_start = sy >> SCALE_SHIFT;\n\n          run_weights = filter.weights +\n                        ((sy >> (SCALE_SHIFT - SUBSAMPLE_BITS)) & SUBSAMPLE_MASK) * filter.n_x * filter.n_y * SUBSAMPLE;\n\n          bufs = alloca( filter.n_y * sizeof(void*) );\n\n          for (i = 0; i < filter.n_y; i++) {\n               if (y_start <  0)\n                    bufs[i] = src;\n               else if (y_start < sh)\n                    bufs[i] = src + sw * y_start;\n               else\n                    bufs[i] = src + sw * (sh - 1);\n\n               y_start++;\n          }\n\n          sx = scaled_x_offset;\n          x_start = sx >> SCALE_SHIFT;\n\n          while (x_start < 0 && buf < buf_end) {\n               scale_pixel( run_weights +\n                            ((sx >> (SCALE_SHIFT - SUBSAMPLE_BITS)) & SUBSAMPLE_MASK) * filter.n_x * filter.n_y,\n                            filter.n_x, filter.n_y, buf, bufs, sx >> SCALE_SHIFT, sw );\n               sx += x_step;\n               x_start = sx >> SCALE_SHIFT;\n               buf++;\n          }\n\n          new_buf = scale_line( run_weights,\n                                filter.n_x, filter.n_y, buf, buf_end, bufs, sx >> SCALE_SHIFT, x_step, sw );\n\n          sx = ((buf_end - buf) >> 2) * x_step + scaled_x_offset;\n          buf = new_buf;\n\n          while (buf < buf_end) {\n               scale_pixel( run_weights +\n                            ((sx >> (SCALE_SHIFT - SUBSAMPLE_BITS)) & SUBSAMPLE_MASK) * filter.n_x * filter.n_y,\n                            filter.n_x, filter.n_y, buf, bufs, sx >> SCALE_SHIFT, sw );\n               sx += x_step;\n               buf++;\n          }\n\n          sy += y_step;\n\n          d[0] = LINE_PTR( dst, dst_surface->config.caps, y, dst_surface->config.size.h, dpitch ) +\n                 DFB_BYTES_PER_LINE( dst_surface->config.format, x );\n\n          switch (dst_surface->config.format) {\n               case DSPF_I420:\n               case DSPF_YV12:\n                    d[1] = LINE_PTR( dst1, dst_surface->config.caps, y / 2, dst_surface->config.size.h / 2,\n                                     dpitch / 2 ) + x / 2;\n                    d[2] = LINE_PTR( dst2, dst_surface->config.caps, y / 2, dst_surface->config.size.h / 2,\n                                     dpitch / 2 ) + x / 2;\n                    break;\n               case DSPF_Y42B:\n               case DSPF_YV16:\n                    d[1] = LINE_PTR( dst1, dst_surface->config.caps, y, dst_surface->config.size.h,\n                                     dpitch / 2 ) + x / 2;\n                    d[2] = LINE_PTR( dst2, dst_surface->config.caps, y, dst_surface->config.size.h,\n                                     dpitch / 2 ) + x / 2;\n                    break;\n               case DSPF_Y444:\n               case DSPF_YV24:\n                    d[1] = LINE_PTR( dst1, dst_surface->config.caps, y, dst_surface->config.size.h,\n                                     dpitch ) + x;\n                    d[2] = LINE_PTR( dst2, dst_surface->config.caps, y, dst_surface->config.size.h,\n                                     dpitch ) + x;\n                    break;\n               case DSPF_NV12:\n               case DSPF_NV21:\n                    d[1] = LINE_PTR( dst1, dst_surface->config.caps, y / 2, dst_surface->config.size.h / 2,\n                                     dpitch ) + (x & ~1);\n                    break;\n               case DSPF_NV16:\n               case DSPF_NV61:\n                    d[1] = LINE_PTR( dst1, dst_surface->config.caps, y, dst_surface->config.size.h,\n                                     dpitch ) + (x & ~1);\n                    break;\n               case DSPF_NV24:\n               case DSPF_NV42:\n                    d[1] = LINE_PTR( dst1, dst_surface->config.caps, y, dst_surface->config.size.h,\n                                     dpitch * 2 ) + (x * 2);\n                    break;\n               default:\n                    break;\n          }\n\n          write_argb_span( scaled_src, d, drect->w, x, y, dst_surface );\n     }\n\n     D_FREE( filter.weights );\n}\n"
  },
  {
    "path": "src/misc/gfx_util.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __MISC__GFX_UTIL_H__\n#define __MISC__GFX_UTIL_H__\n\n#include <core/coretypes.h>\n\n/**********************************************************************************************************************/\n\nvoid dfb_copy_buffer_32 ( u32             *src,\n                          void            *dst,\n                          int              dpitch,\n                          DFBRectangle    *drect,\n                          CoreSurface     *dst_surface,\n                          const DFBRegion *dst_clip );\n\nvoid dfb_scale_linear_32( u32             *src,\n                          int              sw,\n                          int              sh,\n                          void            *dst,\n                          int              dpitch,\n                          DFBRectangle    *drect,\n                          CoreSurface     *dst_surface,\n                          const DFBRegion *dst_clip );\n\n#endif\n"
  },
  {
    "path": "src/misc/util.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/util.h>\n#include <directfb_strings.h>\n#include <directfb_util.h>\n\nD_DEBUG_DOMAIN( DirectFB_Updates, \"DirectFB/Updates\", \"DirectFB Updates\" );\n\n/**********************************************************************************************************************/\n\nstatic const DirectFBPixelFormatNames(dfb_pixelformat_names)\nstatic const DirectFBColorSpaceNames(dfb_colorspace_names)\n\n/**********************************************************************************************************************/\n\nbool\ndfb_region_rectangle_intersect( DFBRegion          *region,\n                                const DFBRectangle *rect )\n{\n     int x2 = rect->x + rect->w - 1;\n     int y2 = rect->y + rect->h - 1;\n\n     if (region->x2 < rect->x || region->y2 < rect->y || region->x1 > x2 || region->y1 > y2)\n          return false;\n\n     if (region->x1 < rect->x)\n          region->x1 = rect->x;\n\n     if (region->y1 < rect->y)\n          region->y1 = rect->y;\n\n     if (region->x2 > x2)\n          region->x2 = x2;\n\n     if (region->y2 > y2)\n          region->y2 = y2;\n\n     return true;\n}\n\nbool\ndfb_unsafe_region_intersect( DFBRegion *region,\n                             int        x1,\n                             int        y1,\n                             int        x2,\n                             int        y2 )\n{\n     if (region->x1 > region->x2) {\n          int temp = region->x1;\n          region->x1 = region->x2;\n          region->x2 = temp;\n     }\n\n     if (region->y1 > region->y2) {\n          int temp = region->y1;\n          region->y1 = region->y2;\n          region->y2 = temp;\n     }\n\n     return dfb_region_intersect( region, x1, y1, x2, y2 );\n}\n\nbool\ndfb_unsafe_region_rectangle_intersect( DFBRegion          *region,\n                                       const DFBRectangle *rect )\n{\n     if (region->x1 > region->x2) {\n          int temp = region->x1;\n          region->x1 = region->x2;\n          region->x2 = temp;\n     }\n\n     if (region->y1 > region->y2) {\n          int temp = region->y1;\n          region->y1 = region->y2;\n          region->y2 = temp;\n     }\n\n     return dfb_region_rectangle_intersect( region, rect );\n}\n\nbool\ndfb_rectangle_intersect_by_unsafe_region( DFBRectangle *rectangle,\n                                          DFBRegion    *region )\n{\n     /* Validate region. */\n\n     if (region->x1 > region->x2) {\n          int temp = region->x1;\n          region->x1 = region->x2;\n          region->x2 = temp;\n     }\n\n     if (region->y1 > region->y2) {\n          int temp = region->y1;\n          region->y1 = region->y2;\n          region->y2 = temp;\n     }\n\n     /* Adjust position. */\n\n     if (region->x1 > rectangle->x) {\n          rectangle->w -= region->x1 - rectangle->x;\n          rectangle->x  = region->x1;\n     }\n\n     if (region->y1 > rectangle->y) {\n          rectangle->h -= region->y1 - rectangle->y;\n          rectangle->y  = region->y1;\n     }\n\n     /* Adjust size. */\n\n     if (region->x2 < rectangle->x + rectangle->w - 1)\n          rectangle->w = region->x2 - rectangle->x + 1;\n\n     if (region->y2 < rectangle->y + rectangle->h - 1)\n          rectangle->h = region->y2 - rectangle->y + 1;\n\n     /* Set size to zero if there's no intersection. */\n     if (rectangle->w <= 0 || rectangle->h <= 0) {\n          rectangle->w = 0;\n          rectangle->h = 0;\n\n          return false;\n     }\n\n     return true;\n}\n\nbool\ndfb_rectangle_intersect_by_region( DFBRectangle    *rectangle,\n                                   const DFBRegion *region )\n{\n     /* Adjust position. */\n\n     if (region->x1 > rectangle->x) {\n          rectangle->w -= region->x1 - rectangle->x;\n          rectangle->x  = region->x1;\n     }\n\n     if (region->y1 > rectangle->y) {\n          rectangle->h -= region->y1 - rectangle->y;\n          rectangle->y  = region->y1;\n     }\n\n     /* Adjust size. */\n\n     if (region->x2 < rectangle->x + rectangle->w - 1)\n        rectangle->w = region->x2 - rectangle->x + 1;\n\n     if (region->y2 < rectangle->y + rectangle->h - 1)\n        rectangle->h = region->y2 - rectangle->y + 1;\n\n     /* Set size to zero if there's no intersection. */\n     if (rectangle->w <= 0 || rectangle->h <= 0) {\n          rectangle->w = 0;\n          rectangle->h = 0;\n\n          return false;\n     }\n\n     return true;\n}\n\nbool dfb_rectangle_intersect( DFBRectangle       *rectangle,\n                              const DFBRectangle *clip )\n{\n     DFBRegion region = { clip->x, clip->y, clip->x + clip->w - 1, clip->y + clip->h - 1 };\n\n     /* Adjust position. */\n\n     if (region.x1 > rectangle->x) {\n          rectangle->w -= region.x1 - rectangle->x;\n          rectangle->x = region.x1;\n     }\n\n     if (region.y1 > rectangle->y) {\n          rectangle->h -= region.y1 - rectangle->y;\n          rectangle->y = region.y1;\n     }\n\n     /* Adjust size. */\n\n     if (region.x2 < rectangle->x + rectangle->w - 1)\n          rectangle->w = region.x2 - rectangle->x + 1;\n\n     if (region.y2 < rectangle->y + rectangle->h - 1)\n          rectangle->h = region.y2 - rectangle->y + 1;\n\n     /* Set size to zero if there's no intersection. */\n     if (rectangle->w <= 0 || rectangle->h <= 0) {\n          rectangle->w = 0;\n          rectangle->h = 0;\n\n          return false;\n     }\n\n     return true;\n}\n\nvoid\ndfb_rectangle_union ( DFBRectangle       *rect1,\n                      const DFBRectangle *rect2 )\n{\n     if (!rect2->w || !rect2->h)\n          return;\n\n     /* Returns the result in the first rectangle. */\n\n     if (rect1->w) {\n          int temp = MIN( rect1->x, rect2->x );\n          rect1->w = MAX( rect1->x + rect1->w, rect2->x + rect2->w ) - temp;\n          rect1->x = temp;\n     }\n     else {\n          rect1->x = rect2->x;\n          rect1->w = rect2->w;\n     }\n\n     if (rect1->h) {\n          int temp = MIN( rect1->y, rect2->y );\n          rect1->h = MAX( rect1->y + rect1->h, rect2->y + rect2->h ) - temp;\n          rect1->y = temp;\n     }\n     else {\n          rect1->y = rect2->y;\n          rect1->h = rect2->h;\n     }\n}\n\n/**********************************************************************************************************************/\n\nvoid\ndfb_updates_init( DFBUpdates *updates,\n                  DFBRegion  *regions,\n                  int         max_regions )\n{\n     D_ASSERT( updates != NULL );\n     D_ASSERT( regions != NULL );\n     D_ASSERT( max_regions > 0 );\n\n     D_DEBUG_AT( DirectFB_Updates, \"%s( %p )\\n\", __FUNCTION__, updates );\n\n     updates->regions     = regions;\n     updates->max_regions = max_regions;\n     updates->num_regions = 0;\n\n     D_MAGIC_SET( updates, DFBUpdates );\n}\n\nvoid\ndfb_updates_deinit( DFBUpdates *updates )\n{\n     D_MAGIC_ASSERT( updates, DFBUpdates );\n\n     D_DEBUG_AT( DirectFB_Updates, \"%s( %p )\\n\", __FUNCTION__, updates );\n\n     D_MAGIC_CLEAR( updates );\n}\n\nvoid\ndfb_updates_add( DFBUpdates      *updates,\n                 const DFBRegion *region )\n{\n     int i;\n\n     D_MAGIC_ASSERT( updates, DFBUpdates );\n     D_ASSERT( updates->regions != NULL );\n     D_ASSERT( updates->num_regions >= 0 );\n     D_ASSERT( updates->num_regions <= updates->max_regions );\n     DFB_REGION_ASSERT( region );\n\n     D_DEBUG_AT( DirectFB_Updates, \"%s( %p, %4d,%4d-%4dx%4d )\\n\", __FUNCTION__, updates,\n                 DFB_RECTANGLE_VALS_FROM_REGION( region ) );\n\n     if (updates->num_regions == 0) {\n          D_DEBUG_AT( DirectFB_Updates, \"  -> added as first\\n\" );\n\n          updates->regions[0]  = updates->bounding = *region;\n          updates->num_regions = 1;\n\n          return;\n     }\n\n     for (i = 0; i < updates->num_regions; i++) {\n          if (dfb_region_region_extends( &updates->regions[i], region ) ||\n              dfb_region_region_intersects( &updates->regions[i], region )) {\n               D_DEBUG_AT( DirectFB_Updates, \"  -> combined with [%d] %4d,%4d-%4dx%4d\\n\", i,\n                           DFB_RECTANGLE_VALS_FROM_REGION( &updates->regions[i] ) );\n\n               dfb_region_region_union( &updates->regions[i], region );\n\n               dfb_region_region_union( &updates->bounding, region );\n\n               D_DEBUG_AT( DirectFB_Updates, \"  -> resulting in  [%d] %4d,%4d-%4dx%4d\\n\", i,\n                           DFB_RECTANGLE_VALS_FROM_REGION( &updates->regions[i] ) );\n\n               return;\n          }\n     }\n\n     if (updates->num_regions == updates->max_regions) {\n          dfb_region_region_union( &updates->bounding, region );\n\n          updates->regions[0]  = updates->bounding;\n          updates->num_regions = 1;\n\n          D_DEBUG_AT( DirectFB_Updates, \"  -> collapsing to [0] %4d,%4d-%4dx%4d\\n\",\n                      DFB_RECTANGLE_VALS_FROM_REGION( &updates->regions[0] ) );\n     }\n     else {\n          updates->regions[updates->num_regions++] = *region;\n\n          dfb_region_region_union( &updates->bounding, region );\n\n          D_DEBUG_AT( DirectFB_Updates, \"  -> added as      [%d] %4d,%4d-%4dx%4d\\n\", updates->num_regions - 1,\n                      DFB_RECTANGLE_VALS_FROM_REGION( &updates->regions[updates->num_regions-1] ) );\n     }\n}\n\nvoid\ndfb_updates_add_rect( DFBUpdates      *updates,\n                      int              x,\n                      int              y,\n                      int              w,\n                      int              h )\n{\n     DFBRegion region = { x, y, x + w - 1, y + h - 1 };\n\n     D_DEBUG_AT( DirectFB_Updates, \"%s( %p, %4d,%4d-%4d,%4d )\\n\", __FUNCTION__, updates, DFB_REGION_VALS( &region ) );\n\n     dfb_updates_add( updates, &region );\n}\n\nvoid\ndfb_updates_stat( DFBUpdates *updates,\n                  int        *ret_total,\n                  int        *ret_bounding )\n{\n     int i;\n\n     D_MAGIC_ASSERT( updates, DFBUpdates );\n     D_ASSERT( updates->regions != NULL );\n     D_ASSERT( updates->num_regions >= 0 );\n     D_ASSERT( updates->num_regions <= updates->max_regions );\n\n     D_DEBUG_AT( DirectFB_Updates, \"%s( %p )\\n\", __FUNCTION__, updates );\n\n     if (updates->num_regions == 0) {\n          if (ret_total)\n               *ret_total = 0;\n\n          if (ret_bounding)\n               *ret_bounding = 0;\n\n          return;\n     }\n\n     if (ret_total) {\n          int total = 0;\n\n          for (i = 0; i < updates->num_regions; i++) {\n               const DFBRegion *r = &updates->regions[i];\n\n               total += (r->x2 - r->x1 + 1) * (r->y2 - r->y1 + 1);\n          }\n\n          *ret_total = total;\n     }\n\n     if (ret_bounding)\n          *ret_bounding = (updates->bounding.x2 - updates->bounding.x1 + 1) *\n                          (updates->bounding.y2 - updates->bounding.y1 + 1);\n}\n\nvoid\ndfb_updates_get_rectangles( DFBUpdates   *updates,\n                            DFBRectangle *ret_rects,\n                            int          *ret_num )\n{\n     D_MAGIC_ASSERT( updates, DFBUpdates );\n     D_ASSERT( updates->regions != NULL );\n     D_ASSERT( updates->num_regions >= 0 );\n     D_ASSERT( updates->num_regions <= updates->max_regions );\n\n     D_DEBUG_AT( DirectFB_Updates, \"%s( %p )\\n\", __FUNCTION__, updates );\n\n     switch (updates->num_regions) {\n          case 0:\n               *ret_num = 0;\n               break;\n\n          default: {\n               int n, d, total, bounding;\n\n               dfb_updates_stat( updates, &total, &bounding );\n\n               n = updates->max_regions - updates->num_regions + 1;\n               d = n + 1;\n\n               if (total < bounding * n / d) {\n                    *ret_num = updates->num_regions;\n\n                    for (n = 0; n < updates->num_regions; n++) {\n                         ret_rects[n].x = updates->regions[n].x1;\n                         ret_rects[n].y = updates->regions[n].y1;\n                         ret_rects[n].w = updates->regions[n].x2 - updates->regions[n].x1 + 1;\n                         ret_rects[n].h = updates->regions[n].y2 - updates->regions[n].y1 + 1;\n                    }\n\n                    break;\n               }\n          }\n          /* fall through */\n\n          case 1:\n               *ret_num = 1;\n               ret_rects[0].x = updates->bounding.x1;\n               ret_rects[0].y = updates->bounding.y1;\n               ret_rects[0].w = updates->bounding.x2 - updates->bounding.x1 + 1;\n               ret_rects[0].h = updates->bounding.y2 - updates->bounding.y1 + 1;\n               break;\n     }\n}\n\nvoid\ndfb_updates_reset( DFBUpdates *updates )\n{\n     D_MAGIC_ASSERT( updates, DFBUpdates );\n\n     D_DEBUG_AT( DirectFB_Updates, \"%s( %p )\\n\", __FUNCTION__, updates );\n\n     updates->num_regions = 0;\n}\n\n/**********************************************************************************************************************/\n\nconst char *\ndfb_input_event_type_name( DFBInputEventType type )\n{\n     switch (type) {\n          case DIET_UNKNOWN:\n               return \"UNKNOWN\";\n\n          case DIET_KEYPRESS:\n               return \"KEYPRESS\";\n\n          case DIET_KEYRELEASE:\n               return \"KEYRELEASE\";\n\n          case DIET_BUTTONPRESS:\n               return \"BUTTONPRESS\";\n\n          case DIET_BUTTONRELEASE:\n               return \"BUTTONRELEASE\";\n\n          case DIET_AXISMOTION:\n               return \"AXISMOTION\";\n\n          default:\n               break;\n     }\n\n     return \"<invalid>\";\n}\n\nconst char *\ndfb_pixelformat_name( DFBSurfacePixelFormat format )\n{\n     int i = 0;\n\n     do {\n          if (format == dfb_pixelformat_names[i].format)\n               return dfb_pixelformat_names[i].name;\n     } while (dfb_pixelformat_names[i++].format != DSPF_UNKNOWN);\n\n     return \"<invalid>\";\n}\n\nconst char *\ndfb_colorspace_name( DFBSurfaceColorSpace colorspace )\n{\n     int i = 0;\n\n     do {\n          if (colorspace == dfb_colorspace_names[i].colorspace)\n               return dfb_colorspace_names[i].name;\n     } while (dfb_colorspace_names[i++].colorspace != DSCS_UNKNOWN);\n\n     return \"<invalid>\";\n}\n\nconst char *\ndfb_window_event_type_name( DFBWindowEventType type )\n{\n     switch (type) {\n          case DWET_POSITION:\n               return \"POSITION\";\n\n          case DWET_SIZE:\n               return \"SIZE\";\n\n          case DWET_CLOSE:\n               return \"CLOSE\";\n\n          case DWET_DESTROYED:\n               return \"DESTROYED\";\n\n          case DWET_GOTFOCUS:\n               return \"GOTFOCUS\";\n\n          case DWET_LOSTFOCUS:\n               return \"LOSTFOCUS\";\n\n          case DWET_KEYDOWN:\n               return \"KEYDOWN\";\n\n          case DWET_KEYUP:\n               return \"KEYUP\";\n\n          case DWET_BUTTONDOWN:\n               return \"BUTTONDOWN\";\n\n          case DWET_BUTTONUP:\n               return \"BUTTONUP\";\n\n          case DWET_MOTION:\n               return \"MOTION\";\n\n          case DWET_ENTER:\n               return \"ENTER\";\n\n          case DWET_LEAVE:\n               return \"LEAVE\";\n\n          case DWET_WHEEL:\n               return \"WHEEL\";\n\n          case DWET_POSITION_SIZE:\n               return \"POSITION_SIZE\";\n\n          case DWET_UPDATE:\n               return \"UPDATE\";\n\n          default:\n               break;\n     }\n\n     return \"<invalid>\";\n}\n\n/**********************************************************************************************************************/\n\nDFBSurfacePixelFormat\ndfb_pixelformat_for_depth( int depth )\n{\n     switch (depth) {\n          case 1:\n               return DSPF_LUT1;\n          case 2:\n               return DSPF_LUT2;\n          case 8:\n               return DSPF_LUT8;\n          case 12:\n               return DSPF_ARGB4444;\n          case 14:\n               return DSPF_ARGB2554;\n          case 15:\n               return DSPF_ARGB1555;\n          case 16:\n               return DSPF_RGB16;\n          case 18:\n               return DSPF_RGB18;\n          case 24:\n               return DSPF_RGB24;\n          case 32:\n               return DSPF_RGB32;\n     }\n\n     return DSPF_UNKNOWN;\n}\n\nDFBSurfacePixelFormat\ndfb_pixelformat_parse( const char *format )\n{\n     int i;\n\n     for (i = 0; dfb_pixelformat_names[i].format != DSPF_UNKNOWN; i++) {\n          if (!strcasecmp( format, dfb_pixelformat_names[i].name ))\n               return dfb_pixelformat_names[i].format;\n     }\n\n     return DSPF_UNKNOWN;\n}\n\nDFBSurfaceColorSpace\ndfb_colorspace_parse( const char *colorspace )\n{\n     int i;\n\n     for (i = 0; dfb_colorspace_names[i].colorspace != DSCS_UNKNOWN; i++) {\n          if (!strcasecmp( colorspace, dfb_colorspace_names[i].name ))\n               return dfb_colorspace_names[i].colorspace;\n     }\n\n     return DSCS_UNKNOWN;\n}\n"
  },
  {
    "path": "src/windows/idirectfbwindow.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/CoreSurface.h>\n#include <core/CoreWindow.h>\n#include <core/palette.h>\n#include <core/windows.h>\n#include <core/windowstack.h>\n#include <core/wm.h>\n#include <display/idirectfbsurface.h>\n#include <display/idirectfbsurface_window.h>\n#include <gfx/convert.h>\n#include <idirectfb.h>\n#include <input/idirectfbeventbuffer.h>\n#include <windows/idirectfbwindow.h>\n\nD_DEBUG_DOMAIN( Window, \"IDirectFBWindow\", \"IDirectFBWindow Interface\" );\n\n/**********************************************************************************************************************/\n\n/*\n * private data struct of IDirectFBWindow\n */\ntypedef struct {\n     int                   ref;          /* reference counter */\n\n     CoreWindow           *window;       /* the window object */\n     CoreLayer            *layer;        /* the layer object */\n\n     IDirectFBSurface     *surface;      /* backing store surface */\n\n     Reaction              reaction;     /* window reaction */\n\n     bool                  detached;\n     bool                  destroyed;\n\n     CoreDFB              *core;\n     IDirectFB            *idirectfb;\n\n     bool                  created;\n\n     DFBWindowCursorFlags  cursor_flags;\n} IDirectFBWindow_data;\n\n/**********************************************************************************************************************/\n\nstatic void\nIDirectFBWindow_Destruct( IDirectFBWindow *thiz )\n{\n     IDirectFBWindow_data *data = thiz->priv;\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!data->detached) {\n          D_DEBUG_AT( Window, \"  -> detaching...\\n\" );\n\n          dfb_window_detach( data->window, &data->reaction );\n     }\n\n     if (data->created) {\n          D_DEBUG_AT( Window, \"  -> destroying...\\n\" );\n\n          CoreWindow_Destroy( data->window );\n     }\n\n     D_DEBUG_AT( Window, \"  -> unrefing...\\n\" );\n\n     dfb_window_unref( data->window );\n\n     D_DEBUG_AT( Window, \"  -> releasing surface...\\n\" );\n\n     if (data->surface)\n          data->surface->Release( data->surface );\n\n     D_DEBUG_AT( Window, \"  -> done\\n\" );\n\n     DIRECT_DEALLOCATE_INTERFACE( thiz );\n}\n\nstatic DirectResult\nIDirectFBWindow_AddRef( IDirectFBWindow *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     data->ref++;\n\n     return DFB_OK;\n}\n\nstatic DirectResult\nIDirectFBWindow_Release( IDirectFBWindow *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (--data->ref == 0)\n          IDirectFBWindow_Destruct( thiz );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBWindow_GetID( IDirectFBWindow *thiz,\n                       DFBWindowID     *ret_window_id )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (!ret_window_id)\n          return DFB_INVARG;\n\n     *ret_window_id = data->window->id;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBWindow_GetPosition( IDirectFBWindow *thiz,\n                             int             *ret_x,\n                             int             *ret_y )\n{\n     DFBInsets insets;\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (!ret_x && !ret_y)\n          return DFB_INVARG;\n\n     CoreWindow_GetInsets( data->window, &insets );\n\n     if (ret_x)\n          *ret_x = data->window->config.bounds.x - insets.l;\n\n     if (ret_y)\n          *ret_y = data->window->config.bounds.y - insets.t;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBWindow_GetSize( IDirectFBWindow *thiz,\n                         int             *ret_width,\n                         int             *ret_height )\n{\n     DFBInsets insets;\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (!ret_width && !ret_height)\n          return DFB_INVARG;\n\n     CoreWindow_GetInsets( data->window, &insets );\n\n     if (ret_width)\n          *ret_width = data->window->config.bounds.w - insets.l - insets.r;\n\n     if (ret_height)\n          *ret_height = data->window->config.bounds.h - insets.t - insets.b;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBWindow_Close( IDirectFBWindow *thiz )\n{\n     DFBWindowEvent evt;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     evt.type = DWET_CLOSE;\n\n     dfb_window_post_event( data->window, &evt );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBWindow_Destroy( IDirectFBWindow *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     CoreWindow_Destroy( data->window );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBWindow_GetSurface( IDirectFBWindow   *thiz,\n                            IDirectFBSurface **ret_interface )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (!ret_interface)\n          return DFB_INVARG;\n\n     if (data->window->caps & (DWCAPS_INPUTONLY | DWCAPS_COLOR))\n          return DFB_UNSUPPORTED;\n\n     if (!data->surface) {\n          DFBResult ret;\n\n          DIRECT_ALLOCATE_INTERFACE( *ret_interface, IDirectFBSurface );\n\n          ret = IDirectFBSurface_Window_Construct( *ret_interface, NULL, NULL, NULL, data->window,\n                                                   DSCAPS_DOUBLE, data->core, data->idirectfb );\n          if (ret)\n               return ret;\n\n          data->surface = *ret_interface;\n     }\n     else\n          *ret_interface = data->surface;\n\n     data->surface->AddRef( data->surface );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBWindow_ResizeSurface( IDirectFBWindow *thiz,\n                               int              width,\n                               int              height )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (!data->window->surface)\n          return DFB_UNSUPPORTED;\n\n     if (width < 1 || width > 4096 || height < 1 || height > 4096)\n          return DFB_INVARG;\n\n     data->window->surface->config.size.w = width;\n     data->window->surface->config.size.h = height;\n\n     return CoreSurface_SetConfig( data->window->surface, &data->window->surface->config );\n}\n\nstatic DFBResult\nIDirectFBWindow_CreateEventBuffer( IDirectFBWindow       *thiz,\n                                   IDirectFBEventBuffer **ret_interface )\n{\n     IDirectFBEventBuffer *iface;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBEventBuffer );\n\n     IDirectFBEventBuffer_Construct( iface, NULL, NULL );\n\n     IDirectFBEventBuffer_AttachWindow( iface, data->window );\n\n     dfb_window_send_configuration( data->window );\n\n     *ret_interface = iface;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBWindow_AttachEventBuffer( IDirectFBWindow      *thiz,\n                                   IDirectFBEventBuffer *buffer )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     IDirectFBEventBuffer_AttachWindow( buffer, data->window );\n\n     dfb_window_send_configuration( data->window );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBWindow_DetachEventBuffer( IDirectFBWindow      *thiz,\n                                   IDirectFBEventBuffer *buffer )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return IDirectFBEventBuffer_DetachWindow( buffer, data->window );\n}\n\nstatic DFBResult\nIDirectFBWindow_EnableEvents( IDirectFBWindow    *thiz,\n                              DFBWindowEventType  mask )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (mask & ~DWET_ALL)\n          return DFB_INVARG;\n\n     return CoreWindow_ChangeEvents( data->window, DWET_NONE, mask );\n}\n\nstatic DFBResult\nIDirectFBWindow_DisableEvents( IDirectFBWindow    *thiz,\n                               DFBWindowEventType  mask )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (mask & ~DWET_ALL)\n          return DFB_INVARG;\n\n     return CoreWindow_ChangeEvents( data->window, mask, DWET_NONE );\n}\n\nstatic DFBResult\nIDirectFBWindow_SetOptions( IDirectFBWindow  *thiz,\n                            DFBWindowOptions  options )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (options & ~DWOP_ALL)\n          return DFB_INVARG;\n\n     if (!(data->window->caps & DWCAPS_ALPHACHANNEL))\n          options &= ~DWOP_ALPHACHANNEL;\n\n     return CoreWindow_ChangeOptions( data->window, DWOP_ALL, options );\n}\n\nstatic DFBResult\nIDirectFBWindow_GetOptions( IDirectFBWindow  *thiz,\n                            DFBWindowOptions *ret_options )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (!ret_options)\n          return DFB_INVARG;\n\n     *ret_options = data->window->config.options;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBWindow_SetColor( IDirectFBWindow *thiz,\n                          u8               r,\n                          u8               g,\n                          u8               b,\n                          u8               a )\n{\n     DFBColor color = { a, r, g, b };\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     CoreWindow_SetColor( data->window, &color );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBWindow_SetColorKey( IDirectFBWindow *thiz,\n                             u8               r,\n                             u8               g,\n                             u8               b )\n{\n     u32 key;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (data->window->caps & DWCAPS_INPUTONLY)\n          return DFB_UNSUPPORTED;\n\n     if (DFB_PIXELFORMAT_IS_INDEXED( data->window->surface->config.format ))\n          key = dfb_palette_search( data->window->surface->palette, r, g, b, 0x80 );\n     else {\n          DFBColor color = { 0, r, g, b };\n\n          key = dfb_pixel_from_color( data->window->surface->config.format, data->window->surface->config.colorspace,\n                                      &color );\n     }\n\n     return CoreWindow_SetColorKey( data->window, key );\n}\n\nstatic DFBResult\nIDirectFBWindow_SetColorKeyIndex( IDirectFBWindow *thiz,\n                                  unsigned int     index )\n{\n     u32 key = index;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (data->window->caps & DWCAPS_INPUTONLY)\n          return DFB_UNSUPPORTED;\n\n     return CoreWindow_SetColorKey( data->window, key );\n}\n\nstatic DFBResult\nIDirectFBWindow_SetOpacity( IDirectFBWindow *thiz,\n                            u8               opacity )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_SetOpacity( data->window, opacity );\n}\n\nstatic DFBResult\nIDirectFBWindow_SetOpaqueRegion( IDirectFBWindow *thiz,\n                                 int              x1,\n                                 int              y1,\n                                 int              x2,\n                                 int              y2 )\n{\n     DFBRegion region;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (x1 > x2 || y1 > y2)\n          return DFB_INVAREA;\n\n     region = (DFBRegion) { x1, y1, x2, y2 };\n\n     return CoreWindow_SetOpaque( data->window, &region );\n}\n\nstatic DFBResult\nIDirectFBWindow_GetOpacity( IDirectFBWindow *thiz,\n                            u8              *ret_opacity )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (!ret_opacity)\n          return DFB_INVARG;\n\n     *ret_opacity = data->window->config.opacity;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBWindow_SetCursorShape( IDirectFBWindow  *thiz,\n                                IDirectFBSurface *shape,\n                                int               hot_x,\n                                int               hot_y )\n{\n     DFBPoint         hotspot;\n     CoreWindowConfig config;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (!shape && !(data->window->config.cursor_flags & DWCF_INVISIBLE)) {\n          config.cursor_flags = data->cursor_flags | DWCF_INVISIBLE;\n\n          CoreWindow_SetConfig( data->window, &config, NULL, 0, DWCONF_CURSOR_FLAGS );\n     }\n\n     if (shape) {\n          IDirectFBSurface_data *shape_data = shape->priv;\n\n          if (!shape_data)\n               return DFB_DEAD;\n\n          if (!shape_data->surface)\n               return DFB_DESTROYED;\n\n          hotspot.x = hot_x;\n          hotspot.y = hot_y;\n\n          CoreWindow_SetCursorShape( data->window, shape_data->surface, &hotspot );\n     }\n     else {\n          hotspot.x = 0;\n          hotspot.y = 0;\n\n          CoreWindow_SetCursorShape( data->window, NULL, &hotspot );\n     }\n\n     if (shape && !(data->cursor_flags & DWCF_INVISIBLE) && (data->window->config.cursor_flags & DWCF_INVISIBLE)) {\n          config.cursor_flags = data->cursor_flags;\n\n          CoreWindow_SetConfig( data->window, &config, NULL, 0, DWCONF_CURSOR_FLAGS );\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBWindow_Move( IDirectFBWindow *thiz,\n                      int              dx,\n                      int              dy )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (dx == 0 && dy == 0)\n          return DFB_OK;\n\n     return CoreWindow_Move( data->window, dx, dy );\n}\n\nstatic DFBResult\nIDirectFBWindow_MoveTo( IDirectFBWindow *thiz,\n                        int              x,\n                        int              y )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_MoveTo( data->window, x, y );\n}\n\nstatic DFBResult\nIDirectFBWindow_Resize( IDirectFBWindow *thiz,\n                        int              width,\n                        int              height )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (width < 1 || width > 4096 || height < 1 || height > 4096)\n          return DFB_INVARG;\n\n     return CoreWindow_Resize( data->window, width, height );\n}\n\nstatic DFBResult\nIDirectFBWindow_SetBounds( IDirectFBWindow *thiz,\n                           int              x,\n                           int              y,\n                           int              width,\n                           int              height )\n{\n     DFBRectangle rect = { x, y, width, height };\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p, %4d,%4d-%4dx%4d )\\n\", __FUNCTION__, thiz, DFB_RECTANGLE_VALS( &rect ) );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_SetBounds( data->window, &rect );\n}\n\nstatic DFBResult\nIDirectFBWindow_SetStackingClass( IDirectFBWindow        *thiz,\n                                  DFBWindowStackingClass  stacking_class )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     switch (stacking_class) {\n          case DWSC_MIDDLE:\n          case DWSC_UPPER:\n          case DWSC_LOWER:\n               break;\n          default:\n               return DFB_INVARG;\n     }\n\n     return CoreWindow_SetStacking( data->window, stacking_class );\n}\n\nstatic DFBResult\nIDirectFBWindow_Raise( IDirectFBWindow *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_Restack( data->window, data->window, 1 );\n}\n\nstatic DFBResult\nIDirectFBWindow_Lower( IDirectFBWindow *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_Restack( data->window, data->window, -1 );\n}\n\nstatic DFBResult\nIDirectFBWindow_RaiseToTop( IDirectFBWindow *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_Restack( data->window, NULL, 1 );\n}\n\nstatic DFBResult\nIDirectFBWindow_LowerToBottom( IDirectFBWindow *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_Restack( data->window, NULL, 0 );\n}\n\nstatic DFBResult\nIDirectFBWindow_PutAtop( IDirectFBWindow *thiz,\n                         IDirectFBWindow *lower )\n{\n     IDirectFBWindow_data *lower_data;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (!lower)\n          return DFB_INVARG;\n\n     lower_data = lower->priv;\n     if (!lower_data)\n          return DFB_DEAD;\n\n     if (!lower_data->window)\n          return DFB_DESTROYED;\n\n     return CoreWindow_Restack( data->window, lower_data->window, 1 );\n}\n\nstatic DFBResult\nIDirectFBWindow_PutBelow( IDirectFBWindow *thiz,\n                          IDirectFBWindow *upper )\n{\n     IDirectFBWindow_data *upper_data;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (!upper)\n          return DFB_INVARG;\n\n     upper_data = upper->priv;\n     if (!upper_data)\n          return DFB_DEAD;\n\n     if (!upper_data->window)\n          return DFB_DESTROYED;\n\n     return CoreWindow_Restack( data->window, upper_data->window, -1 );\n}\n\nstatic DFBResult\nIDirectFBWindow_Bind( IDirectFBWindow *thiz,\n                      IDirectFBWindow *window,\n                      int              x,\n                      int              y )\n{\n     IDirectFBWindow_data *source_data;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     source_data = window->priv;\n     if (!source_data)\n          return DFB_DEAD;\n\n     if (source_data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_Bind( data->window, source_data->window, x, y );\n}\n\nstatic DFBResult\nIDirectFBWindow_Unbind( IDirectFBWindow *thiz,\n                        IDirectFBWindow *window )\n{\n     IDirectFBWindow_data *source_data;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     source_data = window->priv;\n     if (!source_data)\n          return DFB_DEAD;\n\n     if (source_data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_Unbind( data->window, source_data->window );\n}\n\nstatic DFBResult\nIDirectFBWindow_RequestFocus( IDirectFBWindow *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (data->window->config.options & DWOP_GHOST)\n          return DFB_UNSUPPORTED;\n\n     if (!data->window->config.opacity && !(data->window->caps & DWCAPS_INPUTONLY))\n          return DFB_UNSUPPORTED;\n\n     return CoreWindow_RequestFocus( data->window );\n}\n\nstatic DFBResult\nIDirectFBWindow_GrabKeyboard( IDirectFBWindow *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_ChangeGrab( data->window, CWMGT_KEYBOARD, true );\n}\n\nstatic DFBResult\nIDirectFBWindow_UngrabKeyboard( IDirectFBWindow *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_ChangeGrab( data->window, CWMGT_KEYBOARD, false );\n}\n\nstatic DFBResult\nIDirectFBWindow_GrabPointer( IDirectFBWindow *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_ChangeGrab( data->window, CWMGT_POINTER, true );\n}\n\nstatic DFBResult\nIDirectFBWindow_UngrabPointer( IDirectFBWindow *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_ChangeGrab( data->window, CWMGT_POINTER, false );\n}\n\nstatic DFBResult\nIDirectFBWindow_GrabKey( IDirectFBWindow            *thiz,\n                         DFBInputDeviceKeySymbol     symbol,\n                         DFBInputDeviceModifierMask  modifiers )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_GrabKey( data->window, symbol, modifiers );\n}\n\nstatic DFBResult\nIDirectFBWindow_UngrabKey( IDirectFBWindow            *thiz,\n                           DFBInputDeviceKeySymbol     symbol,\n                           DFBInputDeviceModifierMask  modifiers )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_UngrabKey( data->window, symbol, modifiers );\n}\n\nstatic DFBResult\nIDirectFBWindow_SetKeySelection( IDirectFBWindow               *thiz,\n                                 DFBWindowKeySelection          selection,\n                                 const DFBInputDeviceKeySymbol *keys,\n                                 unsigned int                   num_keys )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     switch (selection) {\n         case DWKS_ALL:\n         case DWKS_NONE:\n             break;\n         case DWKS_LIST:\n             if (!keys || num_keys == 0)\n         default:\n                 return DFB_INVARG;\n     }\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_SetKeySelection( data->window, selection, keys, num_keys );\n}\n\nstatic DFBResult\nIDirectFBWindow_GrabUnselectedKeys( IDirectFBWindow *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_ChangeGrab( data->window, CWMGT_UNSELECTED_KEYS, true );\n}\n\nstatic DFBResult\nIDirectFBWindow_UngrabUnselectedKeys( IDirectFBWindow *thiz )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_ChangeGrab( data->window, CWMGT_UNSELECTED_KEYS, false );\n}\n\nstatic DFBResult\nCheckGeometry( const DFBWindowGeometry *geometry )\n{\n     if (!geometry)\n          return DFB_INVARG;\n\n     switch (geometry->mode) {\n          case DWGM_DEFAULT:\n          case DWGM_FOLLOW:\n               break;\n\n          case DWGM_RECTANGLE:\n               if (geometry->rectangle.x < 0 ||\n                   geometry->rectangle.y < 0 ||\n                   geometry->rectangle.w < 1 ||\n                   geometry->rectangle.h < 1)\n                    return DFB_INVARG;\n               break;\n\n          case DWGM_LOCATION:\n               if (geometry->location.x <  0.0f                       ||\n                   geometry->location.y <  0.0f                       ||\n                   geometry->location.w >  1.0f                       ||\n                   geometry->location.h >  1.0f                       ||\n                   geometry->location.w <= 0.0f                       ||\n                   geometry->location.h <= 0.0f                       ||\n                   geometry->location.x + geometry->location.w > 1.0f ||\n                   geometry->location.y + geometry->location.h > 1.0f)\n                    return DFB_INVARG;\n               break;\n\n          default:\n               return DFB_INVARG;\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBWindow_SetSrcGeometry( IDirectFBWindow         *thiz,\n                                const DFBWindowGeometry *geometry )\n{\n     DFBResult        ret;\n     CoreWindowConfig config;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     ret = CheckGeometry( geometry );\n     if (ret)\n          return ret;\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     config.src_geometry = *geometry;\n\n     return CoreWindow_SetConfig( data->window, &config, NULL, 0, DWCONF_SRC_GEOMETRY );\n}\n\nstatic DFBResult\nIDirectFBWindow_SetDstGeometry( IDirectFBWindow         *thiz,\n                                const DFBWindowGeometry *geometry )\n{\n     DFBResult        ret;\n     CoreWindowConfig config;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     ret = CheckGeometry( geometry );\n     if (ret)\n          return ret;\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     config.dst_geometry = *geometry;\n\n     return CoreWindow_SetConfig( data->window, &config, NULL, 0, DWCONF_DST_GEOMETRY );\n}\n\nstatic DFBResult\nIDirectFBWindow_GetStereoDepth( IDirectFBWindow *thiz,\n                                int             *ret_z )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (!(data->window->caps & DWCAPS_LR_MONO) && !(data->window->caps & DWCAPS_STEREO))\n          return DFB_INVARG;\n\n     if (!ret_z)\n          return DFB_INVARG;\n\n     *ret_z = data->window->config.z;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBWindow_SetStereoDepth( IDirectFBWindow *thiz,\n                                int              z )\n{\n     CoreWindowConfig config;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (z < -DLSO_FIXED_LIMIT || z > DLSO_FIXED_LIMIT)\n          return DFB_INVARG;\n\n     if (!(data->window->caps & DWCAPS_LR_MONO) && !(data->window->caps & DWCAPS_STEREO))\n          return DFB_INVARG;\n\n     config.z = z;\n\n     return CoreWindow_SetConfig( data->window, &config, NULL, 0, DWCONF_STEREO_DEPTH );\n}\n\nstatic DFBResult\nIDirectFBWindow_SetProperty( IDirectFBWindow  *thiz,\n                             const char       *key,\n                             void             *value,\n                             void            **ret_old_value )\n{\n     DFBResult ret;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (!key)\n          return DFB_INVARG;\n\n     dfb_windowstack_lock( data->window->stack );\n\n     ret = dfb_wm_set_window_property( data->window->stack, data->window, key, value, ret_old_value );\n\n     dfb_windowstack_unlock( data->window->stack );\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBWindow_GetProperty( IDirectFBWindow  *thiz,\n                             const char       *key,\n                             void            **ret_value )\n{\n     DFBResult ret;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (!key)\n          return DFB_INVARG;\n\n     if (!ret_value)\n          return DFB_INVARG;\n\n     dfb_windowstack_lock( data->window->stack );\n\n     ret = dfb_wm_get_window_property( data->window->stack, data->window, key, ret_value );\n\n     dfb_windowstack_unlock( data->window->stack );\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBWindow_RemoveProperty( IDirectFBWindow  *thiz,\n                                const char       *key,\n                                void            **ret_value )\n{\n     DFBResult ret;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (!key)\n          return DFB_INVARG;\n\n     dfb_windowstack_lock( data->window->stack );\n\n     ret = dfb_wm_remove_window_property( data->window->stack, data->window, key, ret_value );\n\n     dfb_windowstack_unlock( data->window->stack );\n\n     return ret;\n}\n\nstatic DFBResult\nIDirectFBWindow_SetRotation( IDirectFBWindow *thiz,\n                             int              rotation )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     return CoreWindow_SetRotation( data->window, rotation % 360 );\n}\n\nstatic DFBResult\nIDirectFBWindow_SetAssociation( IDirectFBWindow *thiz,\n                                DFBWindowID      window_id )\n{\n     CoreWindowConfig config;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     config.association = window_id;\n\n     return CoreWindow_SetConfig( data->window, &config, NULL, 0, DWCONF_ASSOCIATION );\n}\n\nstatic DFBResult\nIDirectFBWindow_SetApplicationID( IDirectFBWindow *thiz,\n                                  unsigned long    application_id )\n\n{\n     CoreWindowConfig config;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     config.application_id = application_id;\n\n     return CoreWindow_SetConfig( data->window, &config, NULL, 0, DWCONF_APPLICATION_ID );\n}\n\nstatic DFBResult\nIDirectFBWindow_GetApplicationID( IDirectFBWindow *thiz,\n                                  unsigned long   *ret_application_id )\n\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (!ret_application_id)\n          return DFB_INVARG;\n\n     *ret_application_id = data->window->config.application_id;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBWindow_BeginUpdates( IDirectFBWindow *thiz,\n                              const DFBRegion *update )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_BeginUpdates( data->window, update );\n}\n\nstatic DFBResult\nIDirectFBWindow_SendEvent( IDirectFBWindow      *thiz,\n                           const DFBWindowEvent *event )\n{\n     DFBWindowEvent evt;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (!event)\n          return DFB_INVARG;\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     evt = *event;\n\n     CoreWindow_PostEvent( data->window, &evt );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nIDirectFBWindow_SetCursorFlags( IDirectFBWindow      *thiz,\n                                DFBWindowCursorFlags  flags )\n{\n     CoreWindowConfig config;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p, 0x%04x )\\n\", __FUNCTION__, thiz, flags );\n\n     if (flags & ~DWCF_ALL)\n          return DFB_INVARG;\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     data->cursor_flags = flags;\n\n     config.cursor_flags = flags;\n\n     if (!data->window->cursor.surface)\n          config.cursor_flags |= DWCF_INVISIBLE;\n\n     return CoreWindow_SetConfig( data->window, &config, NULL, 0, DWCONF_CURSOR_FLAGS );\n}\n\nstatic DFBResult\nIDirectFBWindow_SetCursorResolution( IDirectFBWindow    *thiz,\n                                     const DFBDimension *resolution )\n{\n     CoreWindowConfig config;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     if (resolution)\n          D_DEBUG_AT( Window, \"%s( %p, %dx%d )\\n\", __FUNCTION__, thiz, resolution->w, resolution->h );\n     else\n          D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (resolution)\n          config.cursor_resolution = *resolution;\n     else {\n          config.cursor_resolution.w = 0;\n          config.cursor_resolution.h = 0;\n     }\n\n     return CoreWindow_SetConfig( data->window, &config, NULL, 0, DWCONF_CURSOR_RESOLUTION );\n}\n\nstatic DFBResult\nIDirectFBWindow_SetCursorPosition( IDirectFBWindow *thiz,\n                                   int              x,\n                                   int              y )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p, %d,%d )\\n\", __FUNCTION__, thiz, x, y );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_SetCursorPosition( data->window, x, y );\n}\n\nstatic DFBResult\nIDirectFBWindow_SetGeometry( IDirectFBWindow         *thiz,\n                             const DFBWindowGeometry *src,\n                             const DFBWindowGeometry *dst )\n{\n     DFBResult        ret;\n     CoreWindowConfig config;\n\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     ret = CheckGeometry( src );\n     if (ret)\n          return ret;\n\n     ret = CheckGeometry( dst );\n     if (ret)\n          return ret;\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     config.src_geometry = *src;\n     config.dst_geometry = *dst;\n\n     return CoreWindow_SetConfig( data->window, &config, NULL, 0, DWCONF_SRC_GEOMETRY | DWCONF_DST_GEOMETRY );\n}\n\nstatic DFBResult\nIDirectFBWindow_SetTypeHint( IDirectFBWindow   *thiz,\n                             DFBWindowTypeHint  type_hint )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_SetTypeHint( data->window, type_hint );\n}\n\nstatic DFBResult\nIDirectFBWindow_ChangeHintFlags( IDirectFBWindow    *thiz,\n                                 DFBWindowHintFlags  clear,\n                                 DFBWindowHintFlags  set )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     return CoreWindow_ChangeHintFlags( data->window, clear, set );\n}\n\nstatic DFBResult\nIDirectFBWindow_GetPolicy( IDirectFBWindow        *thiz,\n                           DFBWindowSurfacePolicy *ret_policy )\n{\n     DIRECT_INTERFACE_GET_DATA( IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p )\\n\", __FUNCTION__, thiz );\n\n     if (data->destroyed)\n          return DFB_DESTROYED;\n\n     if (!ret_policy)\n          return DFB_INVARG;\n\n     *ret_policy = data->window->policy;\n\n     return DFB_OK;\n}\n\nstatic ReactionResult\nIDirectFBWindow_React( const void *msg_data,\n                       void       *ctx )\n{\n     const DFBWindowEvent *evt  = msg_data;\n     IDirectFBWindow_data *data = ctx;\n\n     D_DEBUG_AT( Window, \"%s( %p, %p )\\n\", __FUNCTION__, evt, data );\n\n     switch (evt->type) {\n          case DWET_DESTROYED:\n               D_DEBUG_AT( Window, \"  -> window destroyed\\n\" );\n\n               data->detached = true;\n               data->destroyed = true;\n\n               return RS_REMOVE;\n\n          case DWET_GOTFOCUS:\n          case DWET_LOSTFOCUS:\n               IDirectFB_SetAppFocus( data->idirectfb, evt->type == DWET_GOTFOCUS );\n\n          default:\n               break;\n     }\n\n     return RS_OK;\n}\n\nDFBResult\nIDirectFBWindow_Construct( IDirectFBWindow *thiz,\n                           CoreWindow      *window,\n                           CoreLayer       *layer,\n                           CoreDFB         *core,\n                           IDirectFB       *idirectfb,\n                           bool             created )\n{\n     DFBResult ret;\n\n     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBWindow )\n\n     D_DEBUG_AT( Window, \"%s( %p ) <- %4d,%4d-%4dx%4d\\n\", __FUNCTION__,\n                 thiz, DFB_RECTANGLE_VALS( &window->config.bounds ) );\n\n     data->ref          = 1;\n     data->window       = window;\n     data->layer        = layer;\n     data->core         = core;\n     data->idirectfb    = idirectfb;\n     data->created      = created;\n     data->cursor_flags = DWCF_INVISIBLE;\n\n     ret = dfb_window_attach( window, IDirectFBWindow_React, data, &data->reaction );\n     if (ret) {\n          D_DERROR( ret, \"IDirectFBWindow: Could not attach to reactor!\\n\" );\n          DIRECT_DEALLOCATE_INTERFACE( thiz );\n          return ret;\n     }\n\n     thiz->AddRef               = IDirectFBWindow_AddRef;\n     thiz->Release              = IDirectFBWindow_Release;\n     thiz->GetID                = IDirectFBWindow_GetID;\n     thiz->GetPosition          = IDirectFBWindow_GetPosition;\n     thiz->GetSize              = IDirectFBWindow_GetSize;\n     thiz->Close                = IDirectFBWindow_Close;\n     thiz->Destroy              = IDirectFBWindow_Destroy;\n     thiz->GetSurface           = IDirectFBWindow_GetSurface;\n     thiz->ResizeSurface        = IDirectFBWindow_ResizeSurface;\n     thiz->CreateEventBuffer    = IDirectFBWindow_CreateEventBuffer;\n     thiz->AttachEventBuffer    = IDirectFBWindow_AttachEventBuffer;\n     thiz->DetachEventBuffer    = IDirectFBWindow_DetachEventBuffer;\n     thiz->EnableEvents         = IDirectFBWindow_EnableEvents;\n     thiz->DisableEvents        = IDirectFBWindow_DisableEvents;\n     thiz->SetOptions           = IDirectFBWindow_SetOptions;\n     thiz->GetOptions           = IDirectFBWindow_GetOptions;\n     thiz->SetColor             = IDirectFBWindow_SetColor;\n     thiz->SetColorKey          = IDirectFBWindow_SetColorKey;\n     thiz->SetColorKeyIndex     = IDirectFBWindow_SetColorKeyIndex;\n     thiz->SetOpacity           = IDirectFBWindow_SetOpacity;\n     thiz->SetOpaqueRegion      = IDirectFBWindow_SetOpaqueRegion;\n     thiz->GetOpacity           = IDirectFBWindow_GetOpacity;\n     thiz->SetCursorShape       = IDirectFBWindow_SetCursorShape;\n     thiz->Move                 = IDirectFBWindow_Move;\n     thiz->MoveTo               = IDirectFBWindow_MoveTo;\n     thiz->Resize               = IDirectFBWindow_Resize;\n     thiz->SetBounds            = IDirectFBWindow_SetBounds;\n     thiz->SetStackingClass     = IDirectFBWindow_SetStackingClass;\n     thiz->Raise                = IDirectFBWindow_Raise;\n     thiz->Lower                = IDirectFBWindow_Lower;\n     thiz->RaiseToTop           = IDirectFBWindow_RaiseToTop;\n     thiz->LowerToBottom        = IDirectFBWindow_LowerToBottom;\n     thiz->PutAtop              = IDirectFBWindow_PutAtop;\n     thiz->PutBelow             = IDirectFBWindow_PutBelow;\n     thiz->Bind                 = IDirectFBWindow_Bind;\n     thiz->Unbind               = IDirectFBWindow_Unbind;\n     thiz->RequestFocus         = IDirectFBWindow_RequestFocus;\n     thiz->GrabKeyboard         = IDirectFBWindow_GrabKeyboard;\n     thiz->UngrabKeyboard       = IDirectFBWindow_UngrabKeyboard;\n     thiz->GrabPointer          = IDirectFBWindow_GrabPointer;\n     thiz->UngrabPointer        = IDirectFBWindow_UngrabPointer;\n     thiz->GrabKey              = IDirectFBWindow_GrabKey;\n     thiz->UngrabKey            = IDirectFBWindow_UngrabKey;\n     thiz->SetKeySelection      = IDirectFBWindow_SetKeySelection;\n     thiz->GrabUnselectedKeys   = IDirectFBWindow_GrabUnselectedKeys;\n     thiz->UngrabUnselectedKeys = IDirectFBWindow_UngrabUnselectedKeys;\n     thiz->SetSrcGeometry       = IDirectFBWindow_SetSrcGeometry;\n     thiz->SetDstGeometry       = IDirectFBWindow_SetDstGeometry;\n     thiz->GetStereoDepth       = IDirectFBWindow_GetStereoDepth;\n     thiz->SetStereoDepth       = IDirectFBWindow_SetStereoDepth;\n     thiz->SetProperty          = IDirectFBWindow_SetProperty;\n     thiz->GetProperty          = IDirectFBWindow_GetProperty;\n     thiz->RemoveProperty       = IDirectFBWindow_RemoveProperty;\n     thiz->SetRotation          = IDirectFBWindow_SetRotation;\n     thiz->SetAssociation       = IDirectFBWindow_SetAssociation;\n     thiz->SetApplicationID     = IDirectFBWindow_SetApplicationID;\n     thiz->GetApplicationID     = IDirectFBWindow_GetApplicationID;\n     thiz->BeginUpdates         = IDirectFBWindow_BeginUpdates;\n     thiz->SendEvent            = IDirectFBWindow_SendEvent;\n     thiz->SetCursorFlags       = IDirectFBWindow_SetCursorFlags;\n     thiz->SetCursorResolution  = IDirectFBWindow_SetCursorResolution;\n     thiz->SetCursorPosition    = IDirectFBWindow_SetCursorPosition;\n     thiz->SetGeometry          = IDirectFBWindow_SetGeometry;\n     thiz->SetTypeHint          = IDirectFBWindow_SetTypeHint;\n     thiz->ChangeHintFlags      = IDirectFBWindow_ChangeHintFlags;\n     thiz->GetPolicy            = IDirectFBWindow_GetPolicy;\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "src/windows/idirectfbwindow.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __WINDOWS__IDIRECTFBWINDOW_H__\n#define __WINDOWS__IDIRECTFBWINDOW_H__\n\n#include <core/coretypes.h>\n\n/*\n * initializes interface struct and private data\n */\nDFBResult IDirectFBWindow_Construct( IDirectFBWindow *thiz,\n                                     CoreWindow      *window,\n                                     CoreLayer       *layer,\n                                     CoreDFB         *core,\n                                     IDirectFB       *idirectfb,\n                                     bool             created );\n\n#endif\n"
  },
  {
    "path": "systems/drmkms/drmkms_layer.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/layers.h>\n#include <direct/thread.h>\n\n#include \"drmkms_system.h\"\n\nD_DEBUG_DOMAIN( DRMKMS_Layer, \"DRMKMS/Layer\", \"DRM/KMS Layer\" );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int                    primary_index;\n     int                    plane_index;\n\n     drmModePlane          *plane;\n     uint32_t               colorkey_propid;\n     uint32_t               zpos_propid;\n     uint32_t               alpha_propid;\n\n     int                    level;\n\n     CoreLayerRegionConfig *config;\n     bool                   muted;\n\n     CoreSurface           *surface;\n     int                    surfacebuffer_index;\n     bool                   flip_pending;\n\n     DirectMutex            lock;\n     DirectWaitQueue        wq_event;\n} DRMKMSLayerData;\n\nstatic void\ndrmkms_page_flip_handler( int           fd,\n                          unsigned int  frame,\n                          unsigned int  sec,\n                          unsigned int  usec,\n                          void         *layer_data )\n{\n     DRMKMSLayerData *data = layer_data;\n\n     D_DEBUG_AT( DRMKMS_Layer, \"%s()\\n\", __FUNCTION__ );\n\n     direct_mutex_lock( &data->lock );\n\n     if (data->flip_pending) {\n          dfb_surface_notify_display2( data->surface, data->surfacebuffer_index );\n\n          dfb_surface_unref( data->surface );\n     }\n\n     data->flip_pending = false;\n\n     direct_waitqueue_broadcast( &data->wq_event );\n\n     direct_mutex_unlock( &data->lock );\n\n     D_DEBUG_AT( DRMKMS_Layer, \"%s() done\\n\", __FUNCTION__ );\n}\n\nstatic void *\ndrmkms_buffer_thread( DirectThread *thread,\n                      void         *arg )\n{\n     DRMKMSData *drmkms = arg;\n\n     D_DEBUG_AT( DRMKMS_Layer, \"%s()\\n\", __FUNCTION__ );\n\n     while (true)\n          drmHandleEvent( drmkms->fd, &drmkms->event_context );\n\n     return NULL;\n}\n\n/**********************************************************************************************************************/\n\nstatic int\ndrmkmsPrimaryLayerDataSize( void )\n{\n     return sizeof(DRMKMSLayerData);\n}\n\nstatic DFBResult\ndrmkmsPrimaryInitLayer( CoreLayer                  *layer,\n                        void                       *driver_data,\n                        void                       *layer_data,\n                        DFBDisplayLayerDescription *description,\n                        DFBDisplayLayerConfig      *config,\n                        DFBColorAdjustment         *adjustment )\n{\n     DRMKMSData       *drmkms = driver_data;\n     DRMKMSDataShared *shared;\n     DRMKMSLayerData  *data   = layer_data;\n\n     D_DEBUG_AT( DRMKMS_Layer, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n     D_ASSERT( data != NULL );\n\n     shared = drmkms->shared;\n\n     /* Initialize the layer data. */\n     data->primary_index = shared->primary_index_count++;\n\n     /* Set type and capabilities. */\n     description->type             = DLTF_GRAPHICS;\n     description->caps             = DLCAPS_SURFACE;\n     description->surface_accessor = CSAID_LAYER0;\n\n     /* Set name. */\n     snprintf( description->name, DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, \"DRMKMS Primary Layer\" );\n\n     /* Fill out the default configuration. */\n     config->flags       = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE;\n     config->width       = shared->mode[data->primary_index].hdisplay;\n     config->height      = shared->mode[data->primary_index].vdisplay;\n     config->pixelformat = dfb_config->mode.format ?: shared->primary_format;\n     config->buffermode  = DLBM_FRONTONLY;\n\n     direct_mutex_init( &data->lock );\n     direct_waitqueue_init( &data->wq_event );\n\n     drmkms->event_context.version           = DRM_EVENT_CONTEXT_VERSION;\n     drmkms->event_context.vblank_handler    = drmkms_page_flip_handler;\n     drmkms->event_context.page_flip_handler = drmkms_page_flip_handler;\n\n     drmkms->thread = direct_thread_create( DTT_CRITICAL, drmkms_buffer_thread, drmkms, \"DRMKMS Buffer\" );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsPrimaryTestRegion( CoreLayer                  *layer,\n                         void                       *driver_data,\n                         void                       *layer_data,\n                         CoreLayerRegionConfig      *config,\n                         CoreLayerRegionConfigFlags *ret_failed )\n{\n\n     DRMKMSData                 *drmkms = driver_data;\n     DRMKMSDataShared           *shared;\n     DRMKMSLayerData            *data   = layer_data;\n     CoreLayerRegionConfigFlags  failed = CLRCF_NONE;\n\n     D_DEBUG_AT( DRMKMS_Layer, \"%s( %dx%d, %s )\\n\", __FUNCTION__,\n                 config->width, config->height, dfb_pixelformat_name( config->format ) );\n\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n     D_ASSERT( data != NULL );\n\n     shared = drmkms->shared;\n\n     if (shared->primary_dimension[data->primary_index].w > config->width ||\n         shared->primary_dimension[data->primary_index].h > config->height) {\n          failed = CLRCF_WIDTH | CLRCF_HEIGHT;\n\n          D_DEBUG_AT( DRMKMS_Layer, \"  -> rejection of layers smaller than the current primary layer\\n\" );\n     }\n\n     if (ret_failed)\n          *ret_failed = failed;\n\n     if (failed)\n          return DFB_UNSUPPORTED;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsPrimarySetRegion( CoreLayer                  *layer,\n                        void                       *driver_data,\n                        void                       *layer_data,\n                        void                       *region_data,\n                        CoreLayerRegionConfig      *config,\n                        CoreLayerRegionConfigFlags  updated,\n                        CoreSurface                *surface,\n                        CorePalette                *palette,\n                        CoreSurfaceBufferLock      *left_lock,\n                        CoreSurfaceBufferLock      *right_lock )\n{\n     DFBResult         ret;\n     int               err;\n     DRMKMSData       *drmkms = driver_data;\n     DRMKMSDataShared *shared;\n     DRMKMSLayerData  *data   = layer_data;\n\n     D_DEBUG_AT( DRMKMS_Layer, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n     D_ASSERT( data != NULL );\n\n     shared = drmkms->shared;\n\n     if (updated & (CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_BUFFERMODE | CLRCF_SOURCE)) {\n          int i;\n          int index = data->primary_index;\n\n          for (i = 0; i < drmkms->enabled_crtcs; i++) {\n               if (shared->mirror_outputs)\n                    index = i;\n\n               err = drmModeSetCrtc( drmkms->fd, drmkms->encoder[index]->crtc_id,\n                                     (uint32_t)(long) left_lock->handle, config->source.x, config->source.y,\n                                     &drmkms->connector[index]->connector_id, 1, &shared->mode[index] );\n               if (err) {\n                    ret = errno2result( errno );\n                    D_PERROR( \"DRMKMS/Layer: \"\n                              \"drmModeSetCrtc( crtc_id %u, fb_id %u, xy %d,%d, connector_id %u, mode %ux%u@%uHz )\"\n                              \" failed at index %d!\\n\", drmkms->encoder[index]->crtc_id,\n                              (uint32_t)(long) left_lock->handle, config->source.x, config->source.y,\n                              drmkms->connector[index]->connector_id,\n                              shared->mode[index].hdisplay, shared->mode[index].vdisplay, shared->mode[index].vrefresh,\n                              index);\n                    return ret;\n               }\n\n               if (!shared->mirror_outputs)\n                    break;\n          }\n\n          shared->primary_dimension[data->primary_index] = surface->config.size;\n          shared->primary_rect                           = config->source;\n          shared->primary_fb                             = (uint32_t)(long) left_lock->handle;\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsPrimaryUpdateFlipRegion( void                  *driver_data,\n                               void                  *layer_data,\n                               CoreSurface           *surface,\n                               DFBSurfaceFlipFlags    flags,\n                               CoreSurfaceBufferLock *left_lock,\n                               bool                   flip )\n{\n     DFBResult         ret;\n     int               err;\n     DRMKMSData       *drmkms = driver_data;\n     DRMKMSDataShared *shared;\n     DRMKMSLayerData  *data   = layer_data;\n\n     D_DEBUG_AT( DRMKMS_Layer, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n     D_ASSERT( data != NULL );\n\n     shared = drmkms->shared;\n\n     direct_mutex_lock( &data->lock );\n\n     while (data->flip_pending) {\n          D_DEBUG_AT( DRMKMS_Layer, \"  -> waiting for pending flip (previous)\\n\" );\n\n          if (direct_waitqueue_wait_timeout( &data->wq_event, &data->lock, 30000 ) == DR_TIMEOUT)\n               break;\n     }\n\n     dfb_surface_ref( surface );\n\n     data->surface             = surface;\n     data->surfacebuffer_index = left_lock->buffer->index;\n     data->flip_pending        = true;\n\n     D_DEBUG_AT( DRMKMS_Layer, \"  -> calling drmModePageFlip()\\n\" );\n\n     err = drmModePageFlip( drmkms->fd, drmkms->encoder[data->primary_index]->crtc_id,\n                            (uint32_t)(long) left_lock->handle, DRM_MODE_PAGE_FLIP_EVENT, data );\n     if (err) {\n          ret = errno2result( errno );\n          D_PERROR( \"DRMKMS/Layer: drmModePageFlip() failed!\\n\" );\n          direct_mutex_unlock( &data->lock );\n          return ret;\n     }\n\n     if (shared->mirror_outputs) {\n          int i;\n\n          for (i = 1; i < drmkms->enabled_crtcs; i++) {\n               err = drmModePageFlip( drmkms->fd, drmkms->encoder[i]->crtc_id,\n                                      (uint32_t)(long) left_lock->handle, DRM_MODE_PAGE_FLIP_ASYNC, NULL );\n               if (err)\n                    D_WARN( \"page-flip failed for mirror on crtc id %u\", drmkms->encoder[i]->crtc_id );\n          }\n     }\n\n     if (flip)\n          dfb_surface_flip( surface, false );\n\n     if ((flags & DSFLIP_WAITFORSYNC) == DSFLIP_WAITFORSYNC) {\n          while (data->flip_pending) {\n               D_DEBUG_AT( DRMKMS_Layer, \"  -> waiting for pending flip (WAITFORSYNC)\\n\" );\n\n               if (direct_waitqueue_wait_timeout( &data->wq_event, &data->lock, 30000 ) == DR_TIMEOUT)\n                    break;\n          }\n     }\n\n     direct_mutex_unlock( &data->lock );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsPrimaryFlipRegion( CoreLayer             *layer,\n                         void                  *driver_data,\n                         void                  *layer_data,\n                         void                  *region_data,\n                         CoreSurface           *surface,\n                         DFBSurfaceFlipFlags    flags,\n                         const DFBRegion       *left_update,\n                         CoreSurfaceBufferLock *left_lock,\n                         const DFBRegion       *right_update,\n                         CoreSurfaceBufferLock *right_lock )\n{\n     return drmkmsPrimaryUpdateFlipRegion( driver_data, layer_data, surface, flags, left_lock, true );\n}\n\nstatic DFBResult\ndrmkmsPrimaryUpdateRegion( CoreLayer             *layer,\n                           void                  *driver_data,\n                           void                  *layer_data,\n                           void                  *region_data,\n                           CoreSurface           *surface,\n                           const DFBRegion       *left_update,\n                           CoreSurfaceBufferLock *left_lock,\n                           const DFBRegion       *right_update,\n                           CoreSurfaceBufferLock *right_lock )\n{\n     return drmkmsPrimaryUpdateFlipRegion( driver_data, layer_data, surface, DSFLIP_ONSYNC, left_lock, false );\n}\n\nstatic int\ndrmkmsPlaneLayerDataSize( void )\n{\n     return sizeof(DRMKMSLayerData);\n}\n\nstatic DFBResult\ndrmkmsPlaneInitLayer( CoreLayer                  *layer,\n                      void                       *driver_data,\n                      void                       *layer_data,\n                      DFBDisplayLayerDescription *description,\n                      DFBDisplayLayerConfig      *config,\n                      DFBColorAdjustment         *adjustment )\n{\n     DRMKMSData              *drmkms = driver_data;\n     DRMKMSDataShared        *shared;\n     DRMKMSLayerData         *data   = layer_data;\n     drmModeObjectProperties *props;\n     drmModePropertyRes      *prop;\n     int                      i;\n\n     D_DEBUG_AT( DRMKMS_Layer, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n     D_ASSERT( data != NULL );\n\n     shared = drmkms->shared;\n\n     /* Initialize the layer data. */\n     data->plane_index = ++shared->plane_index_count;\n     data->level       = data->plane_index;\n     i                 = shared->layer_indices[data->plane_index];\n     data->plane       = drmModeGetPlane( drmkms->fd, drmkms->plane_resources->planes[i] );\n\n     D_DEBUG_AT( DRMKMS_Layer, \"  -> getting plane with index %d\\n\", data->plane_index );\n     D_DEBUG_AT( DRMKMS_Layer, \"    => plane_id is %u\\n\", data->plane->plane_id );\n\n     /* Set type and capabilities. */\n     description->type             = DLTF_GRAPHICS;\n     description->caps             = DLCAPS_SURFACE | DLCAPS_SCREEN_POSITION | DLCAPS_ALPHACHANNEL;\n     description->surface_accessor = CSAID_LAYER0;\n\n     /* Set name. */\n     snprintf( description->name, DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, \"DRMKMS Plane Layer %d\", data->plane_index );\n\n     /* Fill out the default configuration. */\n     config->flags       = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE;\n     config->width       = shared->mode[0].hdisplay;\n     config->height      = shared->mode[0].vdisplay;\n     config->pixelformat = dfb_config->mode.format ?: DSPF_ARGB;\n     config->buffermode  = DLBM_FRONTONLY;\n\n     props = drmModeObjectGetProperties( drmkms->fd, data->plane->plane_id, DRM_MODE_OBJECT_PLANE );\n     if (props) {\n          D_INFO( \"DRMKMS/Layer: Supported properties for layer id %u\\n\", data->plane->plane_id );\n          for (i = 0; i < props->count_props; i++) {\n               prop = drmModeGetProperty( drmkms->fd, props->props[i] );\n\n               if (!strcmp( prop->name, \"colorkey\" )) {\n                    description->caps |= DLCAPS_SRC_COLORKEY;\n                    data->colorkey_propid = prop->prop_id;\n                    D_INFO( \"     colorkey\\n\" );\n               }\n               else if (!strcmp( prop->name, \"zpos\" )) {\n                    description->caps |= DLCAPS_LEVELS;\n                    data->zpos_propid = prop->prop_id;\n                    D_INFO( \"     zpos\\n\" );\n\n                    drmModeObjectSetProperty( drmkms->fd, data->plane->plane_id, DRM_MODE_OBJECT_PLANE,\n                                              data->zpos_propid, data->level );\n               }\n               else if (!strcmp( prop->name, \"alpha\" )) {\n                    description->caps |= DLCAPS_OPACITY;\n                    data->alpha_propid = prop->prop_id;\n                    D_INFO( \"     alpha\\n\" );\n               }\n\n               drmModeFreeProperty( prop );\n          }\n\n          drmModeFreeObjectProperties( props );\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsPlaneGetLevel( CoreLayer *layer,\n                     void      *driver_data,\n                     void      *layer_data,\n                     int       *level )\n{\n     DRMKMSLayerData *data = layer_data;\n\n     D_DEBUG_AT( DRMKMS_Layer, \"%s()\\n\", __FUNCTION__ );\n\n     if (level)\n          *level = data->level;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsPlaneSetLevel( CoreLayer *layer,\n                     void      *driver_data,\n                     void      *layer_data,\n                     int        level )\n{\n     DFBResult         ret;\n     int               err;\n     DRMKMSData       *drmkms = driver_data;\n     DRMKMSDataShared *shared;\n     DRMKMSLayerData  *data   = layer_data;\n\n     D_DEBUG_AT( DRMKMS_Layer, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n     D_ASSERT( data != NULL );\n\n     shared = drmkms->shared;\n\n     if (!data->zpos_propid)\n          return DFB_UNSUPPORTED;\n\n     if (level < 1 || level > shared->plane_index_count)\n          return DFB_INVARG;\n\n     err = drmModeObjectSetProperty( drmkms->fd, data->plane->plane_id, DRM_MODE_OBJECT_PLANE,\n                                     data->zpos_propid, level );\n     if (err) {\n          ret = errno2result( errno );\n          D_PERROR( \"DRMKMS/Layer: drmModeObjectSetProperty() failed setting zpos!\\n\" );\n          return ret;\n     }\n\n     data->level = level;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsPlaneTestRegion( CoreLayer                  *layer,\n                       void                       *driver_data,\n                       void                       *layer_data,\n                       CoreLayerRegionConfig      *config,\n                       CoreLayerRegionConfigFlags *ret_failed )\n{\n     DRMKMSLayerData            *data   = layer_data;\n     CoreLayerRegionConfigFlags  failed = CLRCF_NONE;\n\n     D_DEBUG_AT( DRMKMS_Layer, \"%s()\\n\", __FUNCTION__ );\n\n     if ((config->options & DLOP_SRC_COLORKEY) && !data->colorkey_propid)\n          failed |= CLRCF_OPTIONS;\n\n     if (ret_failed)\n          *ret_failed = failed;\n\n     if (failed)\n          return DFB_UNSUPPORTED;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsPlaneSetRegion( CoreLayer                  *layer,\n                      void                       *driver_data,\n                      void                       *layer_data,\n                      void                       *region_data,\n                      CoreLayerRegionConfig      *config,\n                      CoreLayerRegionConfigFlags  updated,\n                      CoreSurface                *surface,\n                      CorePalette                *palette,\n                      CoreSurfaceBufferLock      *left_lock,\n                      CoreSurfaceBufferLock      *right_lock )\n{\n     DFBResult        ret;\n     int              err;\n     DRMKMSData      *drmkms = driver_data;\n     DRMKMSLayerData *data   = layer_data;\n\n     D_DEBUG_AT( DRMKMS_Layer, \"%s()\\n\", __FUNCTION__ );\n\n     if (( updated & (CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_BUFFERMODE | CLRCF_DEST | CLRCF_SOURCE)) ||\n         ((updated & CLRCF_OPACITY) && data->muted && config->opacity)) {\n          err = drmModeSetPlane( drmkms->fd, data->plane->plane_id, drmkms->encoder[0]->crtc_id,\n                                 (uint32_t)(long) left_lock->handle, 0,\n                                 config->dest.x, config->dest.y, config->dest.w, config->dest.h,\n                                 config->source.x << 16, config->source.y << 16,\n                                 config->source.w << 16, config->source.h << 16 );\n          if (err) {\n               ret = errno2result( errno );\n               D_PERROR( \"DRMKMS/Layer: \"\n                         \"drmModeSetPlane( plane_id %u, fb_id %u, dest %4d,%4d-%4dx%4d, source %4d,%4d-%4dx%4d )\"\n                         \" failed!\\n\", data->plane->plane_id, (u32)(long) left_lock->handle,\n                         DFB_RECTANGLE_VALS( &config->dest ), DFB_RECTANGLE_VALS( &config->source ) );\n               return ret;\n          }\n\n          data->config = config;\n          data->muted  = false;\n     }\n\n     if ((updated & (CLRCF_SRCKEY | CLRCF_OPTIONS)) && data->colorkey_propid) {\n          uint32_t colorkey = config->src_key.r << 16 | config->src_key.g << 8 | config->src_key.b;\n\n          if (config->options & DLOP_SRC_COLORKEY)\n               colorkey |= 0x01000000;\n\n          err = drmModeObjectSetProperty( drmkms->fd, data->plane->plane_id, DRM_MODE_OBJECT_PLANE,\n                                          data->colorkey_propid, colorkey );\n          if (err) {\n               ret = errno2result( errno );\n               D_PERROR( \"DRMKMS/Layer: drmModeObjectSetProperty() failed setting colorkey\\n\" );\n               return ret;\n          }\n     }\n\n     if (updated & CLRCF_OPACITY) {\n          if (config->opacity == 0) {\n               err = drmModeSetPlane( drmkms->fd, data->plane->plane_id, drmkms->encoder[0]->crtc_id, 0, 0,\n                                      0, 0, 0, 0, 0, 0, 0, 0 );\n               if (err) {\n                    ret = errno2result( errno );\n                    D_PERROR( \"DRMKMS/Layer: drmModeSetPlane() failed disabling plane!\\n\" );\n                    return DFB_FAILURE;\n               }\n\n               data->muted = true;\n          }\n          else if (data->alpha_propid) {\n               err = drmModeObjectSetProperty( drmkms->fd, data->plane->plane_id, DRM_MODE_OBJECT_PLANE,\n                                               data->alpha_propid, (65535 * config->opacity + 127) / 255 );\n               if (err) {\n                    ret = errno2result( errno );\n                    D_PERROR( \"DRMKMS/Layer: drmModeObjectSetProperty() failed setting alpha!\\n\" );\n                    return ret;\n               }\n          }\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsPlaneRemoveRegion( CoreLayer *layer,\n                         void      *driver_data,\n                         void      *layer_data,\n                         void      *region_data )\n{\n     DFBResult        ret;\n     int              err;\n     DRMKMSData      *drmkms = driver_data;\n     DRMKMSLayerData *data   = layer_data;\n\n     D_DEBUG_AT( DRMKMS_Layer, \"%s()\\n\", __FUNCTION__ );\n\n     if (!data->muted) {\n          err = drmModeSetPlane( drmkms->fd, data->plane->plane_id, drmkms->encoder[0]->crtc_id, 0, 0,\n                                 0, 0, 0, 0, 0, 0, 0, 0 );\n          if (err) {\n               ret = errno2result( errno );\n               D_PERROR( \"DRMKMS/Layer: drmModeSetPlane() failed removing plane!\\n\" );\n               return ret;\n          }\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsPlaneUpdateFlipRegion( void                  *driver_data,\n                             void                  *layer_data,\n                             CoreSurface           *surface,\n                             DFBSurfaceFlipFlags    flags,\n                             CoreSurfaceBufferLock *left_lock,\n                             bool                   flip )\n{\n     DFBResult              ret;\n     int                    err;\n     DRMKMSData            *drmkms = driver_data;\n     DRMKMSLayerData       *data   = layer_data;\n     CoreLayerRegionConfig *config = data->config;\n     drmVBlank              vbl;\n\n     D_DEBUG_AT( DRMKMS_Layer, \"%s()\\n\", __FUNCTION__ );\n\n     if (!config->source.w || !config->source.h || !config->dest.w || !config->dest.h)\n          return DFB_INVARG;\n\n     direct_mutex_lock( &data->lock );\n\n     while (data->flip_pending) {\n          D_DEBUG_AT( DRMKMS_Layer, \"  -> waiting for plane pending flip (previous)\\n\" );\n\n          if (direct_waitqueue_wait_timeout( &data->wq_event, &data->lock, 30000 ) == DR_TIMEOUT)\n               break;\n     }\n\n     dfb_surface_ref( surface );\n\n     data->surface             = surface;\n     data->surfacebuffer_index = left_lock->buffer->index;\n     data->flip_pending        = true;\n\n     if (!data->muted) {\n          err = drmModeSetPlane( drmkms->fd, data->plane->plane_id, drmkms->encoder[0]->crtc_id,\n                                 (uint32_t)(long) left_lock->handle, 0,\n                                 config->dest.x, config->dest.y, config->dest.w, config->dest.h,\n                                 config->source.x << 16, config->source.y << 16,\n                                 config->source.w << 16, config->source.h << 16 );\n          if (err) {\n               ret = errno2result( errno );\n               D_PERROR( \"DRMKMS/Layer: Failed setting plane configuration!\\n\" );\n               direct_mutex_unlock( &data->lock );\n               return ret;\n          }\n     }\n\n     if (flip)\n          dfb_surface_flip( surface, false );\n\n     vbl.request.type     = DRM_VBLANK_EVENT | DRM_VBLANK_RELATIVE;\n     vbl.request.sequence = 1;\n     vbl.request.signal   = (unsigned long) data;\n\n     drmWaitVBlank( drmkms->fd, &vbl );\n\n     if ((flags & DSFLIP_WAITFORSYNC) == DSFLIP_WAITFORSYNC) {\n          while (data->flip_pending) {\n               D_DEBUG_AT( DRMKMS_Layer, \"  -> waiting for plane pending flip (WAITFORSYNC)\\n\" );\n\n               if (direct_waitqueue_wait_timeout( &data->wq_event, &data->lock, 30000 ) == DR_TIMEOUT)\n                    break;\n          }\n     }\n\n     direct_mutex_unlock( &data->lock );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsPlaneFlipRegion( CoreLayer             *layer,\n                       void                  *driver_data,\n                       void                  *layer_data,\n                       void                  *region_data,\n                       CoreSurface           *surface,\n                       DFBSurfaceFlipFlags    flags,\n                       const DFBRegion       *left_update,\n                       CoreSurfaceBufferLock *left_lock,\n                       const DFBRegion       *right_update,\n                       CoreSurfaceBufferLock *right_lock )\n{\n     return drmkmsPlaneUpdateFlipRegion( driver_data, layer_data, surface, flags, left_lock, true );\n}\n\nstatic DFBResult\ndrmkmsPlaneUpdateRegion( CoreLayer             *layer,\n                         void                  *driver_data,\n                         void                  *layer_data,\n                         void                  *region_data,\n                         CoreSurface           *surface,\n                         const DFBRegion       *left_update,\n                         CoreSurfaceBufferLock *left_lock,\n                         const DFBRegion       *right_update,\n                         CoreSurfaceBufferLock *right_lock )\n{\n     return drmkmsPlaneUpdateFlipRegion( driver_data, layer_data, surface, DSFLIP_ONSYNC, left_lock, false );\n}\n\nconst DisplayLayerFuncs drmkmsPrimaryLayerFuncs = {\n     .LayerDataSize = drmkmsPrimaryLayerDataSize,\n     .InitLayer     = drmkmsPrimaryInitLayer,\n     .TestRegion    = drmkmsPrimaryTestRegion,\n     .SetRegion     = drmkmsPrimarySetRegion,\n     .FlipRegion    = drmkmsPrimaryFlipRegion,\n     .UpdateRegion  = drmkmsPrimaryUpdateRegion\n};\n\nconst DisplayLayerFuncs drmkmsPlaneLayerFuncs = {\n     .LayerDataSize = drmkmsPlaneLayerDataSize,\n     .InitLayer     = drmkmsPlaneInitLayer,\n     .GetLevel      = drmkmsPlaneGetLevel,\n     .SetLevel      = drmkmsPlaneSetLevel,\n     .TestRegion    = drmkmsPlaneTestRegion,\n     .SetRegion     = drmkmsPlaneSetRegion,\n     .RemoveRegion  = drmkmsPlaneRemoveRegion,\n     .FlipRegion    = drmkmsPlaneFlipRegion,\n     .UpdateRegion  = drmkmsPlaneUpdateRegion\n};\n"
  },
  {
    "path": "systems/drmkms/drmkms_mode.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <direct/util.h>\n\n#include \"drmkms_mode.h\"\n\nD_DEBUG_DOMAIN( DRMKMS_Mode, \"DRMKMS/Mode\", \"DRM/KMS Mode\" );\n\n/**********************************************************************************************************************/\n\nstatic int xres_table[] = {\n      640,  720,  720,  800, 1024, 1152, 1280, 1280, 1280, 1280, 1400, 1600, 1920, 960, 1440, 800, 1024, 1366, 1920,\n     2560, 2560, 3840, 4096\n};\n\nstatic int yres_table[] = {\n      480,  480,  576,  600,  768,  864,  720,  768,  960, 1024, 1050, 1200, 1080, 540,  540, 480,  600,  768, 1200,\n     1440, 1600, 2160, 2160\n};\n\nstatic int freq_table[] = { 25, 30, 50, 59, 60, 75, 30, 24, 23 };\n\nDFBScreenOutputResolution\ndrmkms_modes_to_dsor_bitmask( DRMKMSData *drmkms,\n                              int         connector )\n{\n     int                        i, j;\n     drmModeModeInfo           *mode = drmkms->connector[connector]->modes;\n     DFBScreenOutputResolution  dsor = DSOR_UNKNOWN;\n\n     D_DEBUG_AT( DRMKMS_Mode, \"%s()\\n\", __FUNCTION__ );\n\n     for (i = 0; i < drmkms->connector[connector]->count_modes; i++) {\n          for (j = 0; j < D_ARRAY_SIZE(xres_table); j++) {\n               if (mode[i].hdisplay == xres_table[j] && mode[i].vdisplay == yres_table[j]) {\n                    dsor |= (1 << j);\n                    break;\n               }\n          }\n     }\n\n     return dsor;\n}\n\ndrmModeModeInfo *\ndrmkms_find_mode( DRMKMSData   *drmkms,\n                  int           connector,\n                  int           width,\n                  int           height,\n                  unsigned int  freq )\n{\n     int              i;\n     drmModeModeInfo *mode       = drmkms->connector[connector]->modes;\n     drmModeModeInfo *found_mode = NULL;\n\n     D_DEBUG_AT( DRMKMS_Mode, \"%s()\\n\", __FUNCTION__ );\n\n     for (i = 0; i < drmkms->connector[connector]->count_modes; i++) {\n          if (mode[i].hdisplay == width && mode[i].vdisplay == height && ((mode[i].vrefresh == freq) || (freq == 0))) {\n               found_mode = &mode[i];\n               D_DEBUG_AT( DRMKMS_Mode, \"  -> found mode %dx%d@%uHz\\n\", width, height, mode[i].vrefresh );\n               break;\n          }\n          else\n               D_DEBUG_AT( DRMKMS_Mode, \"  -> mode %dx%d@%uHz does not match requested %dx%d@%uHz\\n\",\n                           mode[i].hdisplay, mode[i].vdisplay, mode[i].vrefresh, width, height, freq );\n\n     }\n\n     if (!found_mode)\n          D_ONCE( \"no mode found for %dx%d at %u Hz\\n\", width, height, freq );\n\n     return found_mode;\n}\n\ndrmModeModeInfo *\ndrmkms_dsor_dsef_to_mode( DRMKMSData                *drmkms,\n                          int                        connector,\n                          DFBScreenOutputResolution  dsor,\n                          DFBScreenEncoderFrequency  dsef )\n{\n     unsigned int res  = D_BITn32( dsor );\n     unsigned int freq = D_BITn32( dsef );\n\n     D_DEBUG_AT( DRMKMS_Mode, \"%s( dsor %x, dsef %x)\\n\", __FUNCTION__, dsor, dsef );\n\n     if (res == -1 || res >= D_ARRAY_SIZE(xres_table) || freq >= D_ARRAY_SIZE(freq_table))\n          return NULL;\n\n     if (freq == -1)\n          freq = 0;\n\n     return drmkms_find_mode( drmkms, connector, xres_table[res], yres_table[res], freq_table[freq] );\n}\n\nDFBResult\ndrmkms_mode_to_dsor_dsef( const drmModeModeInfo     *mode,\n                          DFBScreenOutputResolution *dsor,\n                          DFBScreenEncoderFrequency *dsef )\n{\n     int j;\n\n     D_DEBUG_AT( DRMKMS_Mode, \"%s()\\n\", __FUNCTION__ );\n\n     if (dsor)\n          *dsor = DSOR_UNKNOWN;\n\n     if (dsef)\n          *dsef = DSEF_UNKNOWN;\n\n     if (dsor) {\n          for (j = 0; j < D_ARRAY_SIZE(xres_table); j++) {\n               if (mode->hdisplay == xres_table[j] && mode->vdisplay == yres_table[j]) {\n                    *dsor = 1 << j;\n                    break;\n               }\n          }\n     }\n\n     if (dsef) {\n          for (j = 0; j < D_ARRAY_SIZE(freq_table); j++) {\n               if (mode->vrefresh == freq_table[j]) {\n                    *dsef = 1 << j;\n                    break;\n               }\n          }\n     }\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "systems/drmkms/drmkms_mode.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DRMKMS_MODE_H__\n#define __DRMKMS_MODE_H__\n\n#include \"drmkms_system.h\"\n\n/**********************************************************************************************************************/\n\nDFBScreenOutputResolution  drmkms_modes_to_dsor_bitmask( DRMKMSData                *drmkms,\n                                                         int                        connector );\n\ndrmModeModeInfo           *drmkms_find_mode            ( DRMKMSData                *drmkms,\n                                                         int                        connector,\n                                                         int                        width,\n                                                         int                        height,\n                                                         unsigned int               freq );\n\ndrmModeModeInfo           *drmkms_dsor_dsef_to_mode    ( DRMKMSData                *drmkms,\n                                                         int                        connector,\n                                                         DFBScreenOutputResolution  dsor,\n                                                         DFBScreenEncoderFrequency  dsef );\n\nDFBResult                  drmkms_mode_to_dsor_dsef    ( const drmModeModeInfo     *videomode,\n                                                         DFBScreenOutputResolution *dsor,\n                                                         DFBScreenEncoderFrequency *dsef );\n\n#endif\n"
  },
  {
    "path": "systems/drmkms/drmkms_screen.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/layers.h>\n#include <core/screens.h>\n\n#include \"drmkms_mode.h\"\n\nD_DEBUG_DOMAIN( DRMKMS_Screen, \"DRMKMS/Screen\", \"DRM/KMS Screen\" );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int rotation;\n} DRMKMSScreenData;\n\nstatic const char *panel_orientation_table[] = {\n     \"Normal\", \"Upside Down\", \"Left Side Up\", \"Right Side Up\"\n};\n\n/**********************************************************************************************************************/\n\nstatic int\ndrmkmsScreenDataSize( void )\n{\n     return sizeof(DRMKMSScreenData);\n}\n\nstatic DFBResult\ndrmkmsInitScreen( CoreScreen           *screen,\n                  void                 *driver_data,\n                  void                 *screen_data,\n                  DFBScreenDescription *description )\n{\n     int                      i;\n     DRMKMSData              *drmkms = driver_data;\n     DRMKMSDataShared        *shared;\n     DRMKMSScreenData        *data   = screen_data;\n     drmModeModeInfo         *mode;\n     drmModeObjectProperties *props;\n     drmModePropertyRes      *prop;\n\n     D_DEBUG_AT( DRMKMS_Screen, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n\n     shared = drmkms->shared;\n\n     /* Set capabilities. */\n     description->caps = DSCCAPS_MIXERS | DSCCAPS_ENCODERS | DSCCAPS_OUTPUTS;\n\n     /* Set name. */\n     snprintf( description->name, DFB_SCREEN_DESC_NAME_LENGTH, \"DRMKMS Screen\" );\n\n     if (dfb_config->mode.width && dfb_config->mode.height) {\n          mode = drmkms_find_mode( drmkms, 0, dfb_config->mode.width, dfb_config->mode.height, 0 );\n          if (mode)\n               shared->mode[0] = *mode;\n\n          for (i = 1; i < drmkms->enabled_crtcs; i++)\n               shared->mode[i] = shared->mode[0];\n     }\n\n     description->mixers   = drmkms->enabled_crtcs;\n     description->encoders = drmkms->enabled_crtcs;\n     description->outputs  = drmkms->enabled_crtcs;\n\n     D_INFO( \"DRMKMS/Screen: Default mode is %ux%u (%d modes in total)\\n\",\n             shared->mode[0].hdisplay, shared->mode[0].vdisplay, drmkms->connector[0]->count_modes );\n\n     /* Get panel orientation. */\n     data->rotation = 0;\n\n     props = drmModeObjectGetProperties( drmkms->fd, drmkms->connector[0]->connector_id, DRM_MODE_OBJECT_CONNECTOR );\n     if (props) {\n          for (i = 0; i < props->count_props; i++) {\n               prop = drmModeGetProperty( drmkms->fd, props->props[i] );\n\n               if (!strcmp( prop->name, \"panel orientation\" )) {\n                    D_ASSUME( props->prop_values[i] >= 0 && props->prop_values[i] <= 3 );\n\n                    if (!strcmp( panel_orientation_table[props->prop_values[i]], \"Upside Down\" ))\n                         data->rotation = 180;\n                    else if (!strcmp( panel_orientation_table[props->prop_values[i]], \"Left Side Up\" ))\n                         data->rotation = 270;\n                    else if (!strcmp( panel_orientation_table[props->prop_values[i]], \"Right Side Up\" ))\n                         data->rotation = 90;\n\n                    D_INFO( \"DRMKMS/Screen: Using %s panel orientation (rotation = %d)\\n\",\n                            panel_orientation_table[props->prop_values[i]], data->rotation );\n                    break;\n               }\n\n               drmModeFreeProperty( prop );\n          }\n\n          drmModeFreeObjectProperties( props );\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsInitMixer( CoreScreen                *screen,\n                 void                      *driver_data,\n                 void                      *screen_data,\n                 int                        mixer,\n                 DFBScreenMixerDescription *description,\n                 DFBScreenMixerConfig      *config )\n{\n     DRMKMSData *drmkms = driver_data;\n\n     D_DEBUG_AT( DRMKMS_Screen, \"%s()\\n\", __FUNCTION__ );\n\n     /* Set capabilities. */\n     description->caps   = DSMCAPS_FULL;\n     description->layers = drmkms->layer_ids[mixer];\n\n     /* Set name. */\n     snprintf( description->name, DFB_SCREEN_MIXER_DESC_NAME_LENGTH, \"DRMKMS Mixer\" );\n\n     config->flags  = DSMCONF_LAYERS;\n     config->layers = description->layers;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsInitEncoder( CoreScreen                  *screen,\n                   void                        *driver_data,\n                   void                        *screen_data,\n                   int                          encoder,\n                   DFBScreenEncoderDescription *description,\n                   DFBScreenEncoderConfig      *config )\n{\n     DRMKMSData       *drmkms = driver_data;\n     DRMKMSDataShared *shared;\n\n     D_DEBUG_AT( DRMKMS_Screen, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n\n     shared = drmkms->shared;\n\n     /* Set capabilities. */\n     description->caps = DSECAPS_RESOLUTION | DSECAPS_FREQUENCY;\n\n     /* Set name. */\n     snprintf( description->name, DFB_SCREEN_ENCODER_DESC_NAME_LENGTH, \"DRMKMS Encoder\" );\n\n     config->flags = DSECONF_RESOLUTION | DSECONF_FREQUENCY | DSECONF_MIXER;\n     config->mixer = encoder;\n\n     if (drmkms->encoder[encoder]) {\n          drmkms_mode_to_dsor_dsef( &shared->mode[encoder], &config->resolution, &config->frequency );\n\n          switch (drmkms->encoder[encoder]->encoder_type) {\n               case DRM_MODE_ENCODER_DAC:\n                    description->type = DSET_CRTC;\n                    break;\n               case DRM_MODE_ENCODER_LVDS:\n               case DRM_MODE_ENCODER_TMDS:\n                    description->type = DSET_DIGITAL;\n                    break;\n               case DRM_MODE_ENCODER_TVDAC:\n                    description->type = DSET_TV;\n                    break;\n               default:\n                    description->type = DSET_UNKNOWN;\n          }\n\n          description->all_resolutions = drmkms_modes_to_dsor_bitmask( drmkms, encoder );\n     }\n     else\n          return DFB_INVARG;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsInitOutput( CoreScreen                 *screen,\n                  void                       *driver_data,\n                  void                       *screen_data,\n                  int                         output,\n                  DFBScreenOutputDescription *description,\n                  DFBScreenOutputConfig      *config )\n{\n     DRMKMSData       *drmkms = driver_data;\n     DRMKMSDataShared *shared;\n\n     D_DEBUG_AT( DRMKMS_Screen, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n\n     shared = drmkms->shared;\n\n     /* Set capabilities. */\n     description->caps = DSOCAPS_RESOLUTION;\n\n     /* Set name. */\n     snprintf( description->name, DFB_SCREEN_OUTPUT_DESC_NAME_LENGTH, \"DRMKMS Output\" );\n\n     config->flags   = DSOCONF_RESOLUTION | DSOCONF_ENCODER;\n     config->encoder = output;\n\n     if (drmkms->connector[output]) {\n          drmkms_mode_to_dsor_dsef( &shared->mode[output], &config->resolution, NULL );\n\n          switch (drmkms->connector[output]->connector_type) {\n               case DRM_MODE_CONNECTOR_VGA:\n                    description->all_connectors = DSOC_VGA;\n                    description->all_signals    = DSOS_VGA;\n                    break;\n               case DRM_MODE_CONNECTOR_SVIDEO:\n                    description->all_connectors = DSOC_YC;\n                    description->all_signals    = DSOS_YC;\n                    break;\n               case DRM_MODE_CONNECTOR_Composite:\n                    description->all_connectors = DSOC_CVBS;\n                    description->all_signals    = DSOS_CVBS;\n                    break;\n               case DRM_MODE_CONNECTOR_Component:\n                    description->all_connectors = DSOC_COMPONENT;\n                    description->all_signals    = DSOS_YCBCR;\n                    break;\n               case DRM_MODE_CONNECTOR_HDMIA:\n               case DRM_MODE_CONNECTOR_HDMIB:\n                    description->all_connectors = DSOC_HDMI;\n                    description->all_signals    = DSOS_HDMI;\n                    break;\n               case DRM_MODE_CONNECTOR_DSI:\n                    description->all_connectors = DSOC_DSI;\n                    description->all_signals    = DSOS_DSI;\n                    break;\n               default:\n                    description->all_connectors = DSOC_UNKNOWN;\n                    description->all_signals    = DSOC_UNKNOWN;\n          }\n\n          description->all_resolutions = drmkms_modes_to_dsor_bitmask( drmkms, output );\n     }\n     else\n          return DFB_INVARG;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsTestMixerConfig( CoreScreen                 *screen,\n                       void                       *driver_data,\n                       void                       *screen_data,\n                       int                         mixer,\n                       const DFBScreenMixerConfig *config,\n                       DFBScreenMixerConfigFlags  *ret_failed )\n{\n     D_DEBUG_AT( DRMKMS_Screen, \"%s()\\n\", __FUNCTION__ );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsSetMixerConfig( CoreScreen                 *screen,\n                      void                       *driver_data,\n                      void                       *screen_data,\n                      int                         mixer,\n                      const DFBScreenMixerConfig *config )\n{\n     D_DEBUG_AT( DRMKMS_Screen, \"%s()\\n\", __FUNCTION__ );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsTestEncoderConfig( CoreScreen                   *screen,\n                         void                         *driver_data,\n                         void                         *screen_data,\n                         int                           encoder,\n                         const DFBScreenEncoderConfig *config,\n                         DFBScreenEncoderConfigFlags  *ret_failed )\n{\n     DRMKMSData                *drmkms = driver_data;\n     DRMKMSDataShared          *shared;\n     drmModeModeInfo           *mode;\n     DFBScreenEncoderFrequency  dsef;\n     DFBScreenOutputResolution  dsor;\n\n     D_DEBUG_AT( DRMKMS_Screen, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n\n     shared = drmkms->shared;\n\n     if (!(config->flags & (DSECONF_FREQUENCY | DSECONF_RESOLUTION)))\n          return DFB_UNSUPPORTED;\n\n     drmkms_mode_to_dsor_dsef( &shared->mode[encoder], &dsor, &dsef );\n\n     if (config->flags & DSECONF_FREQUENCY)\n          dsef = config->frequency;\n\n     if (config->flags & DSECONF_RESOLUTION)\n          dsor = config->resolution;\n\n     mode = drmkms_dsor_dsef_to_mode( drmkms, encoder, dsor, dsef );\n     if (!mode) {\n          *ret_failed = config->flags & (DSECONF_RESOLUTION | DSECONF_FREQUENCY);\n          return DFB_UNSUPPORTED;\n     }\n\n     if ((shared->primary_dimension[encoder].w && (shared->primary_dimension[encoder].w < mode->hdisplay) ) ||\n         (shared->primary_dimension[encoder].h && (shared->primary_dimension[encoder].h < mode->vdisplay ))) {\n          D_DEBUG_AT( DRMKMS_Screen, \"  -> rejection of modes bigger than the current primary layer\\n\" );\n          *ret_failed = config->flags & (DSECONF_RESOLUTION | DSECONF_FREQUENCY);\n          return DFB_UNSUPPORTED;\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsSetEncoderConfig( CoreScreen                   *screen,\n                        void                         *driver_data,\n                        void                         *screen_data,\n                        int                           encoder,\n                        const DFBScreenEncoderConfig *config )\n{\n     DFBResult                  ret;\n     int                        err;\n     DRMKMSData                *drmkms = driver_data;\n     DRMKMSDataShared          *shared;\n     drmModeModeInfo           *mode;\n     DFBScreenEncoderFrequency  dsef;\n     DFBScreenOutputResolution  dsor;\n\n     D_DEBUG_AT( DRMKMS_Screen, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n\n     shared = drmkms->shared;\n\n     if (!(config->flags & (DSECONF_FREQUENCY | DSECONF_RESOLUTION)))\n          return DFB_INVARG;\n\n     drmkms_mode_to_dsor_dsef( &shared->mode[encoder], &dsor, &dsef );\n\n     if (config->flags & DSECONF_FREQUENCY) {\n          D_DEBUG_AT( DRMKMS_Screen, \"  -> requested frequency change \\n\" );\n          dsef = config->frequency;\n     }\n\n     if (config->flags & DSECONF_RESOLUTION) {\n          D_DEBUG_AT( DRMKMS_Screen, \"  -> requested resolution change \\n\" );\n          dsor = config->resolution;\n     }\n\n     mode = drmkms_dsor_dsef_to_mode( drmkms, encoder, dsor, dsef );\n     if (!mode)\n          return DFB_INVARG;\n\n     if ((shared->primary_dimension[encoder].w && (shared->primary_dimension[encoder].w < mode->hdisplay) ) ||\n         (shared->primary_dimension[encoder].h && (shared->primary_dimension[encoder].h < mode->vdisplay ))) {\n          D_DEBUG_AT( DRMKMS_Screen, \"  -> rejection of modes bigger than the current primary layer\\n\" );\n          return DFB_INVARG;\n     }\n\n     if (shared->primary_fb) {\n          err = drmModeSetCrtc( drmkms->fd, drmkms->encoder[encoder]->crtc_id,\n                                shared->primary_fb, shared->primary_rect.x, shared->primary_rect.y,\n                                &drmkms->connector[encoder]->connector_id, 1, mode );\n          if (err) {\n               ret = errno2result( errno );\n               D_PERROR( \"DRMKMS/Screen: \"\n                         \"drmModeSetCrtc( crtc_id %u, fb_id %u, xy %d,%d, connector_id %u, mode %ux%u@%uHz )\"\n                         \" failed for encoder %d!\\n\", drmkms->encoder[encoder]->crtc_id,\n                         shared->primary_fb, shared->primary_rect.x, shared->primary_rect.y,\n                         drmkms->connector[encoder]->connector_id,\n                         mode->hdisplay, mode->vdisplay, mode->vrefresh, encoder);\n               return ret;\n          }\n     }\n\n     shared->mode[encoder] = *mode;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsTestOutputConfig( CoreScreen                  *screen,\n                        void                        *driver_data,\n                        void                        *screen_data,\n                        int                          output,\n                        const DFBScreenOutputConfig *config,\n                        DFBScreenOutputConfigFlags  *ret_failed )\n{\n     DRMKMSData                *drmkms = driver_data;\n     DRMKMSDataShared          *shared;\n     drmModeModeInfo           *mode;\n     DFBScreenEncoderFrequency  dsef;\n     DFBScreenOutputResolution  dsor;\n\n     D_DEBUG_AT( DRMKMS_Screen, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n\n     shared = drmkms->shared;\n\n     if (!(config->flags & DSOCONF_RESOLUTION))\n          return DFB_UNSUPPORTED;\n\n     drmkms_mode_to_dsor_dsef( &shared->mode[output], &dsor, &dsef );\n\n     dsor = config->resolution;\n\n     mode = drmkms_dsor_dsef_to_mode( drmkms, output, dsor, dsef );\n     if (!mode) {\n          *ret_failed = config->flags & DSOCONF_RESOLUTION;\n          return DFB_UNSUPPORTED;\n     }\n\n     if ((shared->primary_dimension[output].w && (shared->primary_dimension[output].w < mode->hdisplay) ) ||\n         (shared->primary_dimension[output].h && (shared->primary_dimension[output].h < mode->vdisplay ))) {\n          D_DEBUG_AT( DRMKMS_Screen, \"  -> rejection of modes bigger than the current primary layer\\n\" );\n          *ret_failed = config->flags & DSOCONF_RESOLUTION;\n          return DFB_UNSUPPORTED;\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsSetOutputConfig( CoreScreen                  *screen,\n                       void                        *driver_data,\n                       void                        *screen_data,\n                       int                          output,\n                       const DFBScreenOutputConfig *config )\n{\n     DFBResult                  ret;\n     int                        err;\n     DRMKMSData                *drmkms = driver_data;\n     DRMKMSDataShared          *shared;\n     drmModeModeInfo           *mode;\n     DFBScreenEncoderFrequency  dsef;\n     DFBScreenOutputResolution  dsor;\n\n     D_DEBUG_AT( DRMKMS_Screen, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n\n     shared = drmkms->shared;\n\n     if (!(config->flags & DSOCONF_RESOLUTION))\n          return DFB_INVARG;\n\n     drmkms_mode_to_dsor_dsef( &shared->mode[output], &dsor, &dsef );\n\n     dsor = config->resolution;\n\n     mode = drmkms_dsor_dsef_to_mode( drmkms, output, dsor, dsef );\n     if (!mode)\n          return DFB_INVARG;\n\n     if ((shared->primary_dimension[output].w && (shared->primary_dimension[output].w < mode->hdisplay) ) ||\n         (shared->primary_dimension[output].h && (shared->primary_dimension[output].h < mode->vdisplay ))) {\n          D_DEBUG_AT( DRMKMS_Screen, \"  -> rejection of modes bigger than the current primary layer\\n\" );\n          return DFB_INVARG;\n     }\n\n     if (shared->primary_fb) {\n          err = drmModeSetCrtc( drmkms->fd, drmkms->encoder[output]->crtc_id,\n                                shared->primary_fb, shared->primary_rect.x, shared->primary_rect.y,\n                                &drmkms->connector[output]->connector_id, 1, mode );\n          if (err) {\n               ret = errno2result( errno );\n               D_PERROR( \"DRMKMS/Screen: \"\n                         \"drmModeSetCrtc( crtc_id %u, fb_id %u, xy %d,%d, connector_id %u, mode %ux%u@%uHz )\"\n                         \" failed for output %d!\\n\", drmkms->encoder[output]->crtc_id,\n                         shared->primary_fb, shared->primary_rect.x, shared->primary_rect.y,\n                         drmkms->connector[output]->connector_id,\n                         mode->hdisplay, mode->vdisplay, mode->vrefresh, output);\n               return ret;\n          }\n     }\n\n     shared->mode[output] = *mode;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsGetScreenSize( CoreScreen *screen,\n                     void       *driver_data,\n                     void       *screen_data,\n                     int        *ret_width,\n                     int        *ret_height )\n{\n     DRMKMSData       *drmkms = driver_data;\n     DRMKMSDataShared *shared;\n\n     D_DEBUG_AT( DRMKMS_Screen, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n\n     shared = drmkms->shared;\n\n     *ret_width  = shared->mode[0].hdisplay;\n     *ret_height = shared->mode[0].vdisplay;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsGetScreenRotation( CoreScreen *screen,\n                         void       *driver_data,\n                         void       *screen_data,\n                         int        *ret_rotation )\n{\n     DRMKMSScreenData *data = screen_data;\n\n     D_DEBUG_AT( DRMKMS_Screen, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( data != NULL );\n\n     *ret_rotation = data->rotation;\n\n     return DFB_OK;\n}\n\nconst ScreenFuncs drmkmsScreenFuncs = {\n     .ScreenDataSize    = drmkmsScreenDataSize,\n     .InitScreen        = drmkmsInitScreen,\n     .InitMixer         = drmkmsInitMixer,\n     .InitEncoder       = drmkmsInitEncoder,\n     .InitOutput        = drmkmsInitOutput,\n     .TestMixerConfig   = drmkmsTestMixerConfig,\n     .SetMixerConfig    = drmkmsSetMixerConfig,\n     .TestEncoderConfig = drmkmsTestEncoderConfig,\n     .SetEncoderConfig  = drmkmsSetEncoderConfig,\n     .TestOutputConfig  = drmkmsTestOutputConfig,\n     .SetOutputConfig   = drmkmsSetOutputConfig,\n     .GetScreenSize     = drmkmsGetScreenSize,\n     .GetScreenRotation = drmkmsGetScreenRotation\n};\n"
  },
  {
    "path": "systems/drmkms/drmkms_surface_pool.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core.h>\n#include <core/gfxcard.h>\n#include <core/surface_allocation.h>\n#include <core/surface_buffer.h>\n#include <core/surface_pool.h>\n#include <direct/hash.h>\n#include <drm_fourcc.h>\n\n#include \"drmkms_system.h\"\n\nD_DEBUG_DOMAIN( DRMKMS_Surfaces, \"DRMKMS/Surfaces\", \"DRM/KMS Surface Pool\" );\nD_DEBUG_DOMAIN( DRMKMS_SurfLock, \"DRMKMS/SurfLock\", \"DRM/KMS Surface Pool Locks\" );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int          magic;\n\n     DRMKMSData  *drmkms;\n\n     CoreDFB     *core;\n\n     DirectHash  *hash;\n     DirectMutex  lock;\n} DRMKMSPoolLocalData;\n\ntypedef struct {\n     int           magic;\n\n     unsigned int  handle;\n     unsigned int  pitch;\n     int           size;\n\n     int           prime_fd;\n\n     uint32_t      name;\n\n     uint32_t      fb_id;\n\n     void         *addr;\n} DRMKMSAllocationData;\n\ntypedef struct {\n     int                  magic;\n\n     DRMKMSPoolLocalData *pool_local;\n\n     FusionObjectID       alloc_id;\n\n     unsigned int         handle;\n     unsigned int         pitch;\n     int                  size;\n\n     void                *addr;\n\n     Reaction             reaction;\n} DRMKMSAllocationLocalData;\n\n/**********************************************************************************************************************/\n\nstatic int\ndrmkmsPoolLocalDataSize( void )\n{\n     return sizeof(DRMKMSPoolLocalData);\n}\n\nstatic int\ndrmkmsAllocationDataSize( void )\n{\n     return sizeof(DRMKMSAllocationData);\n}\n\nstatic DFBResult\ndrmkmsInitPool( CoreDFB                    *core,\n                CoreSurfacePool            *pool,\n                void                       *pool_data,\n                void                       *pool_local,\n                void                       *system_data,\n                CoreSurfacePoolDescription *ret_desc )\n{\n     DRMKMSPoolLocalData *local  = pool_local;\n     DRMKMSData          *drmkms = system_data;\n\n     D_DEBUG_AT( DRMKMS_Surfaces, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( core != NULL );\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_ASSERT( local != NULL );\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n     D_ASSERT( ret_desc != NULL );\n\n     ret_desc->caps              = CSPCAPS_VIRTUAL;\n     ret_desc->access[CSAID_CPU] = CSAF_READ | CSAF_WRITE | CSAF_SHARED;\n     ret_desc->access[CSAID_GPU] = CSAF_READ | CSAF_WRITE | CSAF_SHARED;\n     ret_desc->types             = CSTF_LAYER | CSTF_WINDOW | CSTF_CURSOR | CSTF_FONT | CSTF_SHARED | CSTF_EXTERNAL;\n     ret_desc->priority          = CSPP_ULTIMATE;\n\n     /* For hardware layers. */\n     ret_desc->access[CSAID_LAYER0]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER1]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER2]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER3]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER4]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER5]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER6]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER7]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER8]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER9]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER10] = CSAF_READ;\n     ret_desc->access[CSAID_LAYER11] = CSAF_READ;\n     ret_desc->access[CSAID_LAYER12] = CSAF_READ;\n     ret_desc->access[CSAID_LAYER13] = CSAF_READ;\n     ret_desc->access[CSAID_LAYER14] = CSAF_READ;\n     ret_desc->access[CSAID_LAYER15] = CSAF_READ;\n\n     snprintf( ret_desc->name, DFB_SURFACE_POOL_DESC_NAME_LENGTH, \"DRMKMS Surface Pool\" );\n\n     local->drmkms = drmkms;\n     local->core   = core;\n\n     direct_hash_create( 17, &local->hash );\n     direct_mutex_init( &local->lock );\n\n     D_MAGIC_SET( local, DRMKMSPoolLocalData );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsJoinPool( CoreDFB         *core,\n                CoreSurfacePool *pool,\n                void            *pool_data,\n                void            *pool_local,\n                void            *system_data )\n{\n     DRMKMSPoolLocalData *local  = pool_local;\n     DRMKMSData          *drmkms = system_data;\n\n     D_DEBUG_AT( DRMKMS_Surfaces, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( core != NULL );\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_ASSERT( local != NULL );\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n\n     local->drmkms = drmkms;\n     local->core   = core;\n\n     direct_hash_create( 17, &local->hash );\n     direct_mutex_init( &local->lock );\n\n     D_MAGIC_SET( local, DRMKMSPoolLocalData );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsDestroyPool( CoreSurfacePool *pool,\n                   void            *pool_data,\n                   void            *pool_local )\n{\n     DRMKMSPoolLocalData *local = pool_local;\n\n     D_DEBUG_AT( DRMKMS_Surfaces, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( local, DRMKMSPoolLocalData );\n\n     direct_mutex_deinit( &local->lock );\n     direct_hash_destroy( local->hash );\n\n     D_MAGIC_CLEAR( local );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsLeavePool( CoreSurfacePool *pool,\n                 void            *pool_data,\n                 void            *pool_local )\n{\n     DRMKMSPoolLocalData *local = pool_local;\n\n     D_DEBUG_AT( DRMKMS_Surfaces, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( local, DRMKMSPoolLocalData );\n\n     direct_mutex_deinit( &local->lock );\n     direct_hash_destroy( local->hash );\n\n     D_MAGIC_CLEAR( local );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsTestConfig( CoreSurfacePool         *pool,\n                  void                    *pool_data,\n                  void                    *pool_local,\n                  CoreSurfaceBuffer       *buffer,\n                  const CoreSurfaceConfig *config )\n{\n     CoreSurface         *surface;\n     DRMKMSPoolLocalData *local = pool_local;\n\n     D_UNUSED_P( local );\n\n     D_DEBUG_AT( DRMKMS_Surfaces, \"%s( %p )\\n\", __FUNCTION__, buffer );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( local, DRMKMSPoolLocalData );\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n\n     surface = buffer->surface;\n\n     switch (surface->config.format) {\n          case DSPF_ARGB:\n          case DSPF_RGB32:\n          case DSPF_RGB16:\n          case DSPF_RGB555:\n          case DSPF_ARGB1555:\n          case DSPF_RGB332:\n          case DSPF_RGB24:\n          case DSPF_A8:\n          case DSPF_UYVY:\n          case DSPF_YUY2:\n          case DSPF_NV12:\n          case DSPF_NV21:\n          case DSPF_NV16:\n          case DSPF_NV61:\n          case DSPF_NV24:\n          case DSPF_NV42:\n               break;\n          default:\n               D_DEBUG_AT( DRMKMS_Surfaces, \"  -> unsupported pixel format!\\n\" );\n               return DFB_UNSUPPORTED;\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsAllocateBuffer( CoreSurfacePool       *pool,\n                      void                  *pool_data,\n                      void                  *pool_local,\n                      CoreSurfaceBuffer     *buffer,\n                      CoreSurfaceAllocation *allocation,\n                      void                  *alloc_data )\n{\n     DFBResult                     ret;\n     int                           pitch;\n     int                           length;\n     CoreSurface                  *surface;\n     DRMKMSPoolLocalData          *local = pool_local;\n     DRMKMSAllocationData         *alloc = alloc_data;\n     DRMKMSData                   *drmkms;\n     DRMKMSDataShared             *shared;\n     u32                           width;\n     u32                           height;\n     u32                           format;\n     struct drm_mode_create_dumb   creq;\n     struct drm_mode_destroy_dumb  dreq;\n     struct drm_mode_map_dumb      mreq;\n\n     D_DEBUG_AT( DRMKMS_Surfaces, \"%s( %p )\\n\", __FUNCTION__, buffer );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( local, DRMKMSPoolLocalData );\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n\n     drmkms = local->drmkms;\n     D_ASSERT( drmkms != NULL );\n\n     shared = drmkms->shared;\n     D_ASSERT( shared != NULL );\n\n     surface = buffer->surface;\n\n     dfb_gfxcard_calc_buffer_size( buffer, &pitch, &length );\n\n     width  = (pitch + 3) >> 2;\n     height = surface->config.size.h;\n\n     switch (surface->config.format) {\n          case DSPF_ARGB:\n               format = DRM_FORMAT_ARGB8888;\n               break;\n          case DSPF_RGB32:\n               format = DRM_FORMAT_XRGB8888;\n               break;\n          case DSPF_RGB16:\n               format = DRM_FORMAT_RGB565;\n               break;\n          case DSPF_RGB555:\n               format = DRM_FORMAT_XRGB1555;\n               break;\n          case DSPF_ARGB1555:\n               format = DRM_FORMAT_ARGB1555;\n               break;\n          case DSPF_RGB332:\n               format = DRM_FORMAT_RGB332;\n               break;\n          case DSPF_RGB24:\n               format = DRM_FORMAT_RGB888;\n               break;\n          case DSPF_A8:\n               format = DRM_FORMAT_C8;\n               break;\n          case DSPF_UYVY:\n               format = DRM_FORMAT_UYVY;\n               break;\n          case DSPF_YUY2:\n               format = DRM_FORMAT_YUYV;\n               break;\n          case DSPF_NV12:\n               format = DRM_FORMAT_NV12;\n               height = (surface->config.size.h * 3 + 1) >> 1;\n               break;\n          case DSPF_NV21:\n               format = DRM_FORMAT_NV21;\n               height = (surface->config.size.h * 3 + 1) >> 1;\n               break;\n          case DSPF_NV16:\n               format = DRM_FORMAT_NV16;\n               height = surface->config.size.h * 2;\n               break;\n          case DSPF_NV61:\n               format = DRM_FORMAT_NV61;\n               height = surface->config.size.h * 2;\n               break;\n          case DSPF_NV24:\n               format = DRM_FORMAT_NV24;\n               height = surface->config.size.h * 3;\n               break;\n          case DSPF_NV42:\n               format = DRM_FORMAT_NV42;\n               height = surface->config.size.h * 3;\n               break;\n          default:\n               D_ERROR( \"DRMKMS/Surfaces: Unsupported pixel format!\\n\" );\n               ret = DFB_FAILURE;\n               goto error;\n     }\n\n     memset( &creq, 0, sizeof(creq) );\n     creq.width  = width;\n     creq.height = height;\n     creq.bpp    = 32;\n     if (drmIoctl( drmkms->fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq ) < 0) {\n          ret = errno2result( errno );\n          D_PERROR( \"DRMKMS/Surfaces: DRM_IOCTL_MODE_CREATE_DUMB( %ux%u ) failed!\\n\", width, height );\n          goto error;\n     }\n\n     alloc->handle = creq.handle;\n     alloc->pitch  = creq.pitch;\n     alloc->size   = creq.size;\n\n     D_DEBUG_AT( DRMKMS_Surfaces, \"  -> handle   %u\\n\", alloc->handle );\n     D_DEBUG_AT( DRMKMS_Surfaces, \"  -> pitch    %u\\n\", alloc->pitch );\n     D_DEBUG_AT( DRMKMS_Surfaces, \"  -> size     %d\\n\", alloc->size );\n\n     alloc->prime_fd = -1;\n\n     if (shared->use_prime_fd) {\n          if (drmPrimeHandleToFD( drmkms->fd, alloc->handle, DRM_CLOEXEC, &alloc->prime_fd ) < 0) {\n               ret = errno2result( errno );\n               D_PERROR( \"DRMKMS/Surfaces: drmPrimeHandleToFD( %u ) failed!\\n\", alloc->handle );\n               goto error;\n          }\n\n          D_DEBUG_AT( DRMKMS_Surfaces, \"  -> prime_fd %d\\n\", alloc->prime_fd );\n     }\n\n     if (!alloc->name) {\n          struct drm_gem_flink fl;\n\n          memset( &fl, 0, sizeof(fl) );\n          fl.handle = alloc->handle;\n          if (drmIoctl( drmkms->fd, DRM_IOCTL_GEM_FLINK, &fl ) < 0) {\n               ret = errno2result( errno );\n               D_PERROR( \"DRMKMS/Surfaces: DRM_IOCTL_GEM_FLINK( %u ) failed!\\n\", alloc->handle );\n               goto error;\n          }\n\n          alloc->name = fl.name;\n\n          D_DEBUG_AT( DRMKMS_Surfaces, \"  -> name     %u\\n\", alloc->name );\n     }\n\n     allocation->size   = alloc->size;\n     allocation->offset = alloc->prime_fd;\n\n     if (surface->type & (CSTF_LAYER | CSTF_WINDOW) && Core_GetIdentity() == local->core->fusion_id) {\n          u32 handles[4] = { 0, 0, 0, 0 };\n          u32 pitches[4] = { 0, 0, 0, 0 };\n          u32 offsets[4] = { 0, 0, 0, 0 };\n\n          handles[0] = handles[1] = handles[2] = handles[3] = alloc->handle;\n          pitches[0] = pitches[1] = pitches[2] = pitches[3] = alloc->pitch;\n          offsets[1] = surface->config.size.h * alloc->pitch;\n\n          if (drmModeAddFB2( drmkms->fd, surface->config.size.w, surface->config.size.h, format,\n                             handles, pitches, offsets, &alloc->fb_id, 0 ) < 0) {\n               ret = errno2result( errno );\n               D_PERROR( \"DRMKMS/Surfaces: drmModeAddFB2( %u ) failed!\\n\", alloc->handle );\n               goto error;\n          }\n\n          D_DEBUG_AT( DRMKMS_Surfaces, \"  -> fb_id    %u\\n\", alloc->fb_id );\n     }\n\n     memset( &mreq, 0, sizeof(mreq) );\n     mreq.handle = alloc->handle;\n     if (drmIoctl( drmkms->fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq ) < 0) {\n          ret = errno2result( errno );\n          D_PERROR( \"DRMKMS/Surfaces: DRM_IOCTL_MODE_MAP_DUMB( %u ) failed!\\n\", alloc->handle );\n          goto error;\n     }\n\n     alloc->addr = mmap( NULL, alloc->size, PROT_READ | PROT_WRITE, MAP_SHARED, drmkms->fd, mreq.offset );\n     if (alloc->addr == MAP_FAILED) {\n          ret = errno2result( errno );\n          D_PERROR( \"DRMKMS/Surfaces: Could not mmap dumb buffer!\\n\" );\n          goto error;\n     }\n\n     D_DEBUG_AT( DRMKMS_Surfaces, \"  -> addr     %p\\n\", alloc->addr );\n\n     D_MAGIC_SET( alloc, DRMKMSAllocationData );\n\n     return DFB_OK;\n\nerror:\n     if (alloc->fb_id) {\n          drmModeRmFB( local->drmkms->fd, alloc->fb_id );\n          alloc->fb_id = 0;\n     }\n\n     if (alloc->prime_fd != -1) {\n          close( alloc->prime_fd );\n          alloc->prime_fd = -1;\n     }\n\n     if (alloc->handle) {\n          memset( &dreq, 0, sizeof(dreq) );\n          dreq.handle = alloc->handle;\n          drmIoctl( local->drmkms->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq );\n          alloc->handle = 0;\n     }\n\n     return ret;\n}\n\nstatic DFBResult\ndrmkmsDeallocateBuffer( CoreSurfacePool       *pool,\n                        void                  *pool_data,\n                        void                  *pool_local,\n                        CoreSurfaceBuffer     *buffer,\n                        CoreSurfaceAllocation *allocation,\n                        void                  *alloc_data )\n{\n     DRMKMSPoolLocalData  *local = pool_local;\n     DRMKMSAllocationData *alloc = alloc_data;\n\n     D_DEBUG_AT( DRMKMS_Surfaces, \"%s( %p )\\n\", __FUNCTION__, buffer );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( local, DRMKMSPoolLocalData );\n     D_MAGIC_ASSERT( alloc, DRMKMSAllocationData );\n\n     dfb_gfxcard_sync();\n\n     D_DEBUG_AT( DRMKMS_Surfaces, \"  -> handle   %u\\n\", alloc->handle );\n     D_DEBUG_AT( DRMKMS_Surfaces, \"  -> pitch    %u\\n\", alloc->pitch );\n     D_DEBUG_AT( DRMKMS_Surfaces, \"  -> size     %d\\n\", alloc->size );\n     D_DEBUG_AT( DRMKMS_Surfaces, \"  -> prime_fd %d\\n\", alloc->prime_fd );\n     D_DEBUG_AT( DRMKMS_Surfaces, \"  -> name     %u\\n\", alloc->name );\n     D_DEBUG_AT( DRMKMS_Surfaces, \"  -> fb_id    %u\\n\", alloc->fb_id );\n     D_DEBUG_AT( DRMKMS_Surfaces, \"  -> addr     %p\\n\", alloc->addr );\n\n     if (alloc->addr) {\n          munmap( alloc->addr, alloc->size );\n          alloc->addr = NULL;\n     }\n\n     if (alloc->fb_id) {\n          drmModeRmFB( local->drmkms->fd, alloc->fb_id );\n          alloc->fb_id = 0;\n     }\n\n     if (alloc->prime_fd != -1) {\n          close( alloc->prime_fd );\n          alloc->prime_fd = -1;\n     }\n\n     if (alloc->handle) {\n          struct drm_mode_destroy_dumb dreq;\n\n          memset( &dreq, 0, sizeof(dreq) );\n          dreq.handle = alloc->handle;\n          drmIoctl( local->drmkms->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq );\n          alloc->handle = 0;\n     }\n\n     D_MAGIC_CLEAR( alloc );\n\n     return DFB_OK;\n}\n\nstatic ReactionResult\ndrmkmsAllocationReaction( const void *msg_data,\n                          void       *ctx )\n{\n     const CoreSurfaceAllocationNotification *notification = msg_data;\n     DRMKMSAllocationLocalData               *alloc_local  = ctx;\n\n     D_DEBUG_AT( DRMKMS_Surfaces, \"%s() -> unmap dumb buffer (local)\\n\", __FUNCTION__ );\n\n     D_ASSERT( notification != NULL );\n     D_MAGIC_ASSERT( alloc_local, DRMKMSAllocationLocalData );\n\n     if (notification->flags & CSANF_DEALLOCATED) {\n          struct drm_gem_close cl;\n\n          D_DEBUG_AT( DRMKMS_Surfaces, \"  -> handle   %u\\n\", alloc_local->handle );\n          D_DEBUG_AT( DRMKMS_Surfaces, \"  -> addr     %p\\n\", alloc_local->addr );\n\n          memset( &cl, 0, sizeof(cl) );\n          cl.handle = alloc_local->handle;\n          drmIoctl( alloc_local->pool_local->drmkms->fd, DRM_IOCTL_GEM_CLOSE, &cl );\n\n          if (alloc_local->addr)\n               munmap( alloc_local->addr, alloc_local->size );\n\n          direct_mutex_lock( &alloc_local->pool_local->lock );\n          direct_hash_remove( alloc_local->pool_local->hash, alloc_local->alloc_id );\n          direct_mutex_unlock( &alloc_local->pool_local->lock );\n\n          D_MAGIC_CLEAR( alloc_local );\n          D_FREE( alloc_local );\n     }\n\n     return RS_OK;\n}\n\nstatic DFBResult\ndrmkmsLock( CoreSurfacePool       *pool,\n            void                  *pool_data,\n            void                  *pool_local,\n            CoreSurfaceAllocation *allocation,\n            void                  *alloc_data,\n            CoreSurfaceBufferLock *lock )\n{\n     DRMKMSPoolLocalData  *local = pool_local;\n     DRMKMSAllocationData *alloc = alloc_data;\n     DRMKMSData           *drmkms;\n     DRMKMSDataShared     *shared;\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( local, DRMKMSPoolLocalData );\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( alloc, DRMKMSAllocationData );\n     D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );\n\n     D_DEBUG_AT( DRMKMS_SurfLock, \"%s( %p, %p )\\n\", __FUNCTION__, allocation, lock->buffer );\n\n     drmkms = local->drmkms;\n     D_ASSERT( drmkms != NULL );\n\n     shared = drmkms->shared;\n     D_ASSERT( shared != NULL );\n\n     lock->pitch  = alloc->pitch;\n     lock->offset = ~0;\n     lock->addr   = dfb_core_is_master( local->core ) ? alloc->addr : NULL;\n     lock->phys   = 0;\n\n     switch (lock->accessor) {\n          case CSAID_LAYER0:\n               lock->handle = (void*)(long) alloc->fb_id;\n               D_DEBUG_AT( DRMKMS_Surfaces, \"  -> primary layer buffer (handle %u)\\n\", alloc->fb_id );\n               break;\n\n          case CSAID_GPU:\n               if (shared->use_prime_fd)\n                    lock->offset = alloc->prime_fd;\n\n               lock->handle = (void*)(long) alloc->handle;\n               D_DEBUG_AT( DRMKMS_Surfaces, \"  -> primary accelerator buffer (handle %u)\\n\", alloc->handle );\n               break;\n\n          case CSAID_CPU:\n               lock->handle = (void*)(long) alloc->name;\n               D_DEBUG_AT( DRMKMS_Surfaces, \"  -> local processor buffer (handle %u)\\n\", alloc->name );\n\n               if (!dfb_core_is_master( local->core )) {\n                    DRMKMSAllocationLocalData *alloc_local;\n\n                    alloc_local = direct_hash_lookup( local->hash, allocation->object.id );\n                    if (!alloc_local) {\n                         DFBResult                ret;\n                         struct drm_gem_open      op;\n                         struct drm_gem_close     cl;\n                         struct drm_mode_map_dumb mreq;\n\n                         D_DEBUG_AT( DRMKMS_Surfaces, \"  -> map dumb buffer (local)\\n\" );\n\n                         alloc_local = D_CALLOC( 1, sizeof(DRMKMSAllocationLocalData) );\n                         if (!alloc_local)\n                              return D_OOM();\n\n                         alloc_local->pool_local = local;\n                         alloc_local->alloc_id   = allocation->object.id;\n\n                         memset( &op, 0, sizeof(op) );\n                         op.name = alloc->name;\n                         if (drmIoctl( drmkms->fd, DRM_IOCTL_GEM_OPEN, &op ) < 0) {\n                              ret = errno2result( errno );\n                              D_PERROR( \"DRMKMS/Surfaces: DRM_IOCTL_GEM_OPEN( %u ) failed!\\n\", alloc->name );\n                              D_FREE( alloc_local );\n                              return ret;\n                         }\n\n                         D_DEBUG_AT( DRMKMS_Surfaces, \"  -> name     %u => handle %u\\n\", alloc->name, op.handle );\n\n                         alloc_local->handle = op.handle;\n                         alloc_local->pitch  = alloc->pitch;\n                         alloc_local->size   = alloc->size;\n\n                         memset( &mreq, 0, sizeof(mreq) );\n                         mreq.handle = alloc_local->handle;\n                         if (drmIoctl( drmkms->fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq ) < 0) {\n                              ret = errno2result( errno );\n                              D_PERROR( \"DRMKMS/Surfaces: DRM_IOCTL_MODE_MAP_DUMB( %u ) failed!\\n\",\n                                        alloc_local->handle );\n                              memset( &cl, 0, sizeof(cl) );\n                              cl.handle = alloc_local->handle;\n                              drmIoctl( drmkms->fd, DRM_IOCTL_GEM_CLOSE, &cl );\n                              D_FREE( alloc_local );\n                              return ret;\n                         }\n\n                         alloc_local->addr = mmap( NULL, alloc_local->size, PROT_READ | PROT_WRITE, MAP_SHARED,\n                                                   drmkms->fd, mreq.offset );\n                         if (alloc->addr == MAP_FAILED) {\n                              ret = errno2result( errno );\n                              D_PERROR( \"DRMKMS/Surfaces: Could not mmap dumb buffer!\\n\" );\n                              memset( &cl, 0, sizeof(cl) );\n                              cl.handle = alloc_local->handle;\n                              drmIoctl( drmkms->fd, DRM_IOCTL_GEM_CLOSE, &cl );\n                              D_FREE( alloc_local );\n                              return ret;\n                         }\n\n                         D_DEBUG_AT( DRMKMS_Surfaces, \"  -> addr     %p\\n\", alloc_local->addr );\n\n                         D_MAGIC_SET( alloc_local, DRMKMSAllocationLocalData );\n\n                         direct_hash_insert( local->hash, allocation->object.id, alloc_local );\n\n                         dfb_surface_allocation_attach( allocation, drmkmsAllocationReaction, alloc_local,\n                                                        &alloc_local->reaction );\n                    }\n                    else\n                         D_MAGIC_ASSERT( alloc_local, DRMKMSAllocationLocalData );\n\n                    lock->addr = alloc_local->addr;\n               }\n               break;\n\n          default:\n               D_BUG( \"unsupported accessor %u\", lock->accessor );\n               break;\n     }\n\n     D_DEBUG_AT( DRMKMS_SurfLock, \"  -> offset %lu, pitch %u, addr %p, phys 0x%08lx\\n\",\n                 lock->offset, lock->pitch, lock->addr, lock->phys );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndrmkmsUnlock( CoreSurfacePool       *pool,\n              void                  *pool_data,\n              void                  *pool_local,\n              CoreSurfaceAllocation *allocation,\n              void                  *alloc_data,\n              CoreSurfaceBufferLock *lock )\n{\n     DRMKMSAllocationData *alloc = alloc_data;\n\n     D_UNUSED_P( alloc );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( alloc, DRMKMSAllocationData );\n     D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );\n\n     D_DEBUG_AT( DRMKMS_SurfLock, \"%s( %p, %p )\\n\", __FUNCTION__, allocation, lock->buffer );\n\n     return DFB_OK;\n}\n\nconst SurfacePoolFuncs drmkmsSurfacePoolFuncs = {\n     .PoolLocalDataSize  = drmkmsPoolLocalDataSize,\n     .AllocationDataSize = drmkmsAllocationDataSize,\n     .InitPool           = drmkmsInitPool,\n     .JoinPool           = drmkmsJoinPool,\n     .DestroyPool        = drmkmsDestroyPool,\n     .LeavePool          = drmkmsLeavePool,\n     .TestConfig         = drmkmsTestConfig,\n     .AllocateBuffer     = drmkmsAllocateBuffer,\n     .DeallocateBuffer   = drmkmsDeallocateBuffer,\n     .Lock               = drmkmsLock,\n     .Unlock             = drmkmsUnlock\n};\n"
  },
  {
    "path": "systems/drmkms/drmkms_system.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core.h>\n#include <core/core_system.h>\n#include <core/layers.h>\n#include <core/screens.h>\n#include <core/surface_pool.h>\n#include <fusion/shmalloc.h>\n\n#include \"drmkms_system.h\"\n#include \"drmkms_vt.h\"\n\nD_DEBUG_DOMAIN( DRMKMS_System, \"DRMKMS/System\", \"DRM/KMS System Module\" );\n\nDFB_CORE_SYSTEM( drmkms )\n\n/**********************************************************************************************************************/\n\nextern const ScreenFuncs       drmkmsScreenFuncs;\nextern const DisplayLayerFuncs drmkmsPrimaryLayerFuncs;\nextern const DisplayLayerFuncs drmkmsPlaneLayerFuncs;\nextern const SurfacePoolFuncs  drmkmsSurfacePoolFuncs;\n\nstruct DFBFourCCName {\n     DFBSurfacePixelFormat  format;\n     const char            *name;\n};\n\nstatic const struct DFBFourCCName dfb_fourcc_names[] = {\n     { DSPF_ARGB,     \"AR24\" },\n     { DSPF_RGB32,    \"XR24\" },\n     { DSPF_RGB24,    \"RG24\" },\n     { DSPF_RGB16,    \"RG16\" },\n     { DSPF_ARGB1555, \"AR15\" },\n     { DSPF_RGB555,   \"XR15\" },\n     { DSPF_A8,       \"C8\"   }\n};\n\nstatic DFBResult\nlocal_init( const char *device_name,\n            bool        mirror_outputs,\n            bool        multihead_outputs,\n            DRMKMSData *drmkms )\n{\n     int               busy, i, j, k;\n     CoreScreen       *screen;\n     drmModeConnector *connector;\n     drmModeEncoder   *encoder;\n     uint64_t          has_dumb = 0;\n\n     /* Open DRM/KMS device. */\n     drmkms->fd = open( device_name, O_RDWR );\n     if (drmkms->fd < 0) {\n          D_PERROR( \"DRMKMS/System: Failed to open '%s'!\\n\", device_name );\n          return DFB_INIT;\n     }\n\n     /* Retrieve display configuration and planes information. */\n     drmSetClientCap( drmkms->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1 );\n\n     drmkms->resources = drmModeGetResources( drmkms->fd );\n     if (!drmkms->resources) {\n          D_PERROR( \"DRMKMS/System: Could not retrieve resources!\\n\" );\n          return DFB_INIT;\n     }\n\n     drmkms->plane_resources = drmModeGetPlaneResources( drmkms->fd );\n     if (!drmkms->plane_resources || !drmkms->plane_resources->count_planes) {\n          D_PERROR( \"DRMKMS/System: Could not retrieve plane resources!\\n\" );\n          return DFB_INIT;\n     }\n\n     D_INFO( \"DRMKMS/System: Found %d connectors, %d encoders, %u planes\\n\",\n             drmkms->resources->count_connectors, drmkms->resources->count_encoders,\n             drmkms->plane_resources->count_planes );\n\n     /* Check for the dumb buffer capability. */\n     if (drmGetCap( drmkms->fd, DRM_CAP_DUMB_BUFFER, &has_dumb ) < 0 || !has_dumb) {\n          D_PERROR( \"DRMKMS/System: Could not create dumb buffers!\\n\" );\n          return DFB_INIT;\n     }\n\n     screen = dfb_screens_register( drmkms, &drmkmsScreenFuncs );\n\n     dfb_layers_register( screen, drmkms, &drmkmsPrimaryLayerFuncs );\n\n     DFB_DISPLAYLAYER_IDS_ADD( drmkms->layer_ids[0], drmkms->layer_id++ );\n\n     for (i = 0; i < drmkms->resources->count_connectors; i++) {\n          connector = drmModeGetConnector( drmkms->fd, drmkms->resources->connectors[i] );\n          if (!connector)\n               continue;\n\n          encoder = NULL;\n\n          if (connector->count_modes > 0) {\n               D_DEBUG_AT( DRMKMS_System, \"  -> found connector %u\\n\", connector->connector_id );\n\n               if (connector->encoder_id) {\n                    D_DEBUG_AT( DRMKMS_System, \"  -> connector is bound to encoder %u\\n\", connector->encoder_id );\n\n                    encoder = drmModeGetEncoder( drmkms->fd, connector->encoder_id );\n                    if (!encoder)\n                         continue;\n               }\n               else {\n                    D_DEBUG_AT( DRMKMS_System, \"  -> searching for appropriate encoder\\n\" );\n\n                    for (j = 0; j < drmkms->resources->count_encoders; j++) {\n                         encoder = drmModeGetEncoder( drmkms->fd, drmkms->resources->encoders[j] );\n                         if (!encoder)\n                              continue;\n\n                         busy = 0;\n\n                         for (k = 0; k < drmkms->enabled_crtcs; k++) {\n                              if (drmkms->encoder[k]->encoder_id == encoder->encoder_id) {\n                                   D_DEBUG_AT( DRMKMS_System, \"  -> encoder %u is already in use by connector %u\\n\",\n                                               encoder->encoder_id, drmkms->connector[k]->connector_id );\n                                   busy = 1;\n                              }\n                         }\n\n                         if (busy)\n                              continue;\n\n                         D_DEBUG_AT( DRMKMS_System, \"  -> found encoder %u\\n\", encoder->encoder_id );\n                         break;\n                    }\n               }\n\n               if (encoder) {\n                    if (encoder->crtc_id) {\n                         D_DEBUG_AT( DRMKMS_System, \"  -> encoder is bound to crtc %u\\n\", encoder->crtc_id );\n\n                         drmkms->crtc = drmModeGetCrtc( drmkms->fd, encoder->crtc_id );\n                    }\n                    else {\n                         D_DEBUG_AT( DRMKMS_System, \"  -> searching for appropriate crtc\\n\" );\n\n                         for (j = 0; j < drmkms->resources->count_crtcs; j++) {\n                              if (!(encoder->possible_crtcs & (1 << j)))\n                                   continue;\n\n                              busy = 0;\n\n                              for (k = 0; k < drmkms->enabled_crtcs; k++) {\n                                   if (drmkms->encoder[k]->crtc_id == drmkms->resources->crtcs[j]) {\n                                        D_DEBUG_AT( DRMKMS_System, \"  -> crtc %u is already in use by encoder %u\\n\",\n                                                    drmkms->resources->crtcs[j], drmkms->encoder[k]->encoder_id );\n                                        busy = 1;\n                                   }\n                              }\n\n                              if (busy)\n                                   continue;\n\n                              encoder->crtc_id = drmkms->resources->crtcs[j];\n\n                              D_DEBUG_AT( DRMKMS_System, \"  -> found crtc %u\\n\", encoder->crtc_id );\n\n                              drmkms->crtc = drmModeGetCrtc( drmkms->fd, encoder->crtc_id );\n                              break;\n                         }\n\n                         if (!encoder->crtc_id) {\n                              D_DEBUG_AT( DRMKMS_System, \"  -> cannot find crtc for encoder %u\\n\", encoder->encoder_id );\n                              break;\n                         }\n                    }\n\n                    drmkms->connector[drmkms->enabled_crtcs] = connector;\n                    drmkms->encoder[drmkms->enabled_crtcs]   = encoder;\n\n                    for (j = 0; j < connector->count_modes; j++)\n                         D_DEBUG_AT( DRMKMS_System, \"    => modes[%2d] is %ux%u@%uHz\\n\", j,\n                                     connector->modes[j].hdisplay, connector->modes[j].vdisplay,\n                                     connector->modes[j].vrefresh );\n\n                    drmkms->enabled_crtcs++;\n\n                    if ((!mirror_outputs && !multihead_outputs) || (drmkms->enabled_crtcs == 8))\n                         break;\n\n                    if (multihead_outputs && drmkms->enabled_crtcs > 1) {\n                         dfb_layers_register( screen, drmkms, &drmkmsPrimaryLayerFuncs );\n\n                         DFB_DISPLAYLAYER_IDS_ADD( drmkms->layer_ids[drmkms->enabled_crtcs-1], drmkms->layer_id++ );\n                    }\n               }\n          }\n     }\n\n     if (dfb_core_is_master( drmkms->core )) {\n          for (i = 0; i < drmkms->plane_resources->count_planes; i++) {\n               drmModePlane *plane;\n\n               plane = drmModeGetPlane( drmkms->fd, drmkms->plane_resources->planes[i] );\n\n               if ((plane->possible_crtcs & drmkms->encoder[0]->possible_crtcs) &&\n                   (plane->crtc_id != drmkms->encoder[0]->crtc_id)) {\n                    drmkms->shared->layer_indices[drmkms->layer_id] = i;\n\n                    dfb_layers_register( screen, drmkms, &drmkmsPlaneLayerFuncs );\n\n                    DFB_DISPLAYLAYER_IDS_ADD( drmkms->layer_ids[0], drmkms->layer_id++ );\n               }\n          }\n     }\n     else {\n          for (i = 0; i < drmkms->plane_resources->count_planes; i++) {\n               if (i == drmkms->shared->layer_indices[drmkms->layer_id]) {\n                    dfb_layers_register( screen, drmkms, &drmkmsPlaneLayerFuncs );\n\n                    DFB_DISPLAYLAYER_IDS_ADD( drmkms->layer_ids[0], drmkms->layer_id++ );\n               }\n          }\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nlocal_deinit( DRMKMSData *drmkms )\n{\n     if (drmkms->plane_resources)\n          drmModeFreePlaneResources( drmkms->plane_resources );\n\n     if (drmkms->resources)\n          drmModeFreeResources( drmkms->resources );\n\n     if (drmkms->fd != -1)\n          close( drmkms->fd );\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic void\nsystem_get_info( CoreSystemInfo *info )\n{\n     info->version.major = 0;\n     info->version.minor = 1;\n\n     info->caps = CSCAPS_ACCELERATION | CSCAPS_NOTIFY_DISPLAY | CSCAPS_SYSMEM_EXTERNAL;\n\n     snprintf( info->name,   DFB_CORE_SYSTEM_INFO_NAME_LENGTH,   \"DRM/KMS\" );\n     snprintf( info->vendor, DFB_CORE_SYSTEM_INFO_VENDOR_LENGTH, \"DirectFB\" );\n}\n\nstatic DFBResult\nsystem_initialize( CoreDFB  *core,\n                   void    **ret_data )\n{\n     DFBResult                ret;\n     int                      i, j, p;\n     uint32_t                 fourcc;\n     uint64_t                 plane_type = 0;\n     char                     name[5];\n     DRMKMSData              *drmkms;\n     DRMKMSDataShared        *shared;\n     FusionSHMPoolShared     *pool;\n     const char              *value;\n     drmModePlane            *plane;\n     drmModeObjectProperties *props;\n     drmModePropertyRes      *prop;\n     VideoMode               *prev_mode       = NULL;\n     DFBSurfacePixelFormat    fallback_format = DSPF_UNKNOWN;\n\n     D_DEBUG_AT( DRMKMS_System, \"%s()\\n\", __FUNCTION__ );\n\n     drmkms = D_CALLOC( 1, sizeof(DRMKMSData) );\n     if (!drmkms)\n          return D_OOM();\n\n     drmkms->core = core;\n\n     pool = dfb_core_shmpool( core );\n\n     shared = SHCALLOC( pool, 1, sizeof(DRMKMSDataShared) );\n     if (!shared) {\n          D_FREE( drmkms );\n          return D_OOSHM();\n     }\n\n     shared->shmpool = pool;\n\n     drmkms->shared = shared;\n\n     if ((value = direct_config_get_value( \"drmkms\" ))) {\n          direct_snputs( shared->device_name, value, 255 );\n          D_INFO( \"DRMKMS/System: Using device %s as specified in DirectFB configuration\\n\", shared->device_name );\n     }\n     else if (getenv( \"DRICARD\" ) && *getenv( \"DRICARD\" ) != '\\0') {\n          direct_snputs( shared->device_name, getenv( \"DRICARD\" ), 255 );\n          D_INFO( \"DRMKMS/System: Using device %s as set in DRICARD environment variable\\n\", shared->device_name );\n     }\n     else {\n          snprintf( shared->device_name, 255, \"/dev/dri/card0\" );\n          D_INFO( \"DRMKMS/System: Using device %s (default)\\n\", shared->device_name );\n     }\n\n     if (direct_config_has_name( \"drmkms-use-prime-fd\" ) && !direct_config_has_name( \"no-drmkms-use-prime-fd\" )) {\n          shared->use_prime_fd = true;\n          D_INFO( \"DRMKMS/System: Using PRIME file descriptor\\n\" );\n     }\n\n     if (direct_config_has_name( \"no-vt\" ) && !direct_config_has_name( \"vt\" ))\n          D_INFO( \"DRMKMS/System: Don't use VT handling\\n\" );\n     else\n          shared->vt = true;\n\n     if ((value = direct_config_get_value( \"connected-outputs\" ))) {\n          if (strcmp( value, \"mirror\" ) == 0) {\n               shared->mirror_outputs = true;\n               D_INFO( \"DRMKMS/System: Mirror display\\n\" );\n          }\n          else if (strcmp( value, \"multihead\" ) == 0) {\n               shared->multihead_outputs = true;\n               D_INFO( \"DRMKMS/System: Multi-head display\\n\" );\n          }\n          else if (strcmp( value, \"single\" ) == 0) {\n               D_INFO( \"DRMKMS/System: Single display\\n\" );\n          }\n          else {\n               D_ERROR( \"DRMKMS/System: 'connected-outputs': Unknown connected outputs setting '%s'!\\n\", value );\n               SHFREE( pool, shared );\n               D_FREE( drmkms );\n               return DFB_INIT;\n          }\n     }\n\n     ret = local_init( shared->device_name, shared->mirror_outputs, shared->multihead_outputs, drmkms );\n     if (ret)\n          goto error;\n\n     if (shared->vt) {\n          ret = drmkms_vt_initialize( core );\n          if (ret)\n               goto error;\n     }\n\n     for (i = 0; i < drmkms->enabled_crtcs; i++)\n          shared->mode[i] = drmkms->connector[0]->modes[0];\n\n     for (p = 0; p < drmkms->plane_resources->count_planes; p++) {\n          plane = drmModeGetPlane( drmkms->fd, drmkms->plane_resources->planes[p] );\n\n          props = drmModeObjectGetProperties( drmkms->fd, plane->plane_id, DRM_MODE_OBJECT_PLANE );\n\n          for (i = 0; i < props->count_props; i++) {\n               prop = drmModeGetProperty( drmkms->fd, props->props[i] );\n               if (!prop)\n                    continue;\n\n               if (!strcmp( prop->name, \"type\" )) {\n                    plane_type = props->prop_values[i];\n                    break;\n               }\n\n               drmModeFreeProperty( prop );\n          }\n\n          for (i = 0; i < plane->count_formats; i++) {\n               fourcc = plane->formats[i];\n               snprintf( name, sizeof(name), \"%c%c%c%c\", fourcc, fourcc >> 8, fourcc >> 16, fourcc >> 24 );\n\n               if (!strcmp( name, \"AR24\" ) && plane_type == DRM_PLANE_TYPE_PRIMARY) {\n                    shared->primary_format = DSPF_ARGB;\n                    break;\n               }\n               else if (fallback_format == DSPF_UNKNOWN) {\n                    for (j = 1; j < D_ARRAY_SIZE(dfb_fourcc_names); j++) {\n                         if (!strcmp( name, dfb_fourcc_names[j].name ) && plane_type == DRM_PLANE_TYPE_PRIMARY) {\n                              fallback_format = dfb_fourcc_names[j].format;\n                              break;\n                         }\n                    }\n               }\n          }\n     }\n\n     if (shared->primary_format != DSPF_ARGB && fallback_format == DSPF_UNKNOWN) {\n          D_ERROR( \"DRMKMS/System: No supported format!\\n\" );\n          ret = DFB_INIT;\n          goto error;\n     }\n     else if (shared->primary_format != DSPF_ARGB)\n          shared->primary_format = fallback_format;\n\n     /* Initialize the mode table. */\n     for (i = 0; i < drmkms->connector[0]->count_modes; i++) {\n          VideoMode *mode;\n\n          if (!prev_mode ||\n              (prev_mode &&\n               prev_mode->xres != drmkms->connector[0]->modes[i].hdisplay &&\n               prev_mode->yres != drmkms->connector[0]->modes[i].vdisplay)) {\n               mode = SHCALLOC( shared->shmpool, 1, sizeof(VideoMode) );\n               if (!mode) {\n                    D_OOSHM();\n                    continue;\n               }\n\n               mode->xres = drmkms->connector[0]->modes[i].hdisplay;\n               mode->yres = drmkms->connector[0]->modes[i].vdisplay;\n               mode->bpp  = DFB_BITS_PER_PIXEL( dfb_config->mode.format ?: shared->primary_format );\n          }\n          else\n               continue;\n\n          if (!prev_mode)\n               shared->modes = mode;\n          else\n               prev_mode->next = mode;\n\n          prev_mode = mode;\n     }\n\n     *ret_data = drmkms;\n\n     ret = dfb_surface_pool_initialize( core, &drmkmsSurfacePoolFuncs, &shared->pool );\n     if (ret)\n          goto error;\n\n     ret = core_arena_add_shared_field( core, \"drmkms\", shared );\n     if (ret)\n          goto error;\n\n     return DFB_OK;\n\nerror:\n     if (shared->vt)\n          drmkms_vt_shutdown( false );\n\n     local_deinit( drmkms );\n\n     SHFREE( pool, shared );\n\n     D_FREE( drmkms );\n\n     return ret;\n}\n\nstatic DFBResult\nsystem_join( CoreDFB  *core,\n             void    **ret_data )\n{\n     DFBResult         ret;\n     DRMKMSData       *drmkms;\n     DRMKMSDataShared *shared;\n\n     D_DEBUG_AT( DRMKMS_System, \"%s()\\n\", __FUNCTION__ );\n\n     drmkms = D_CALLOC( 1, sizeof(DRMKMSData) );\n     if (!drmkms)\n          return D_OOM();\n\n     drmkms->core = core;\n\n     ret = core_arena_get_shared_field( core, \"drmkms\", (void**) &shared );\n     if (ret) {\n          D_FREE( drmkms );\n          return ret;\n     }\n\n     drmkms->shared = shared;\n\n     ret = local_init( shared->device_name, shared->mirror_outputs, shared->multihead_outputs, drmkms );\n     if (ret)\n          goto error;\n\n     *ret_data = drmkms;\n\n     ret = dfb_surface_pool_join( core, shared->pool, &drmkmsSurfacePoolFuncs );\n     if (ret)\n          goto error;\n\n     return DFB_OK;\n\nerror:\n     local_deinit( drmkms );\n\n     D_FREE( drmkms );\n\n     return ret;\n}\n\nstatic DFBResult\nsystem_shutdown( bool emergency )\n{\n     DRMKMSData       *drmkms = dfb_system_data();\n     DRMKMSDataShared *shared;\n     VideoMode        *mode;\n\n     D_DEBUG_AT( DRMKMS_System, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n\n     shared = drmkms->shared;\n\n     dfb_surface_pool_destroy( shared->pool );\n\n     mode = shared->modes;\n     while (mode) {\n          VideoMode *next = mode->next;\n          SHFREE( shared->shmpool, mode );\n          mode = next;\n     }\n\n     if (drmkms->crtc) {\n          drmModeSetCrtc( drmkms->fd, drmkms->crtc->crtc_id, drmkms->crtc->buffer_id, drmkms->crtc->x, drmkms->crtc->y,\n                          &drmkms->connector[0]->connector_id, 1, &drmkms->crtc->mode );\n\n          drmModeFreeCrtc( drmkms->crtc );\n     }\n\n     if (shared->vt)\n          drmkms_vt_shutdown( emergency );\n\n     local_deinit( drmkms );\n\n     SHFREE( shared->shmpool, shared );\n\n     D_FREE( drmkms );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsystem_leave( bool emergency )\n{\n     DRMKMSData       *drmkms = dfb_system_data();\n     DRMKMSDataShared *shared;\n\n     D_DEBUG_AT( DRMKMS_System, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n\n     shared = drmkms->shared;\n\n     dfb_surface_pool_leave( shared->pool );\n\n     local_deinit( drmkms );\n\n     D_FREE( drmkms );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsystem_suspend()\n{\n     return DFB_OK;\n}\n\nstatic DFBResult\nsystem_resume()\n{\n     return DFB_OK;\n}\n\nstatic VideoMode *\nsystem_get_modes()\n{\n     DRMKMSData       *drmkms = dfb_system_data();\n     DRMKMSDataShared *shared;\n\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n\n     shared = drmkms->shared;\n\n     return shared->modes;\n}\n\nstatic VideoMode *\nsystem_get_current_mode()\n{\n     DRMKMSData       *drmkms = dfb_system_data();\n     DRMKMSDataShared *shared;\n     VideoMode        *mode;\n\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n\n     shared = drmkms->shared;\n\n     mode = shared->modes;\n     while (mode) {\n          if (mode->xres == shared->mode[0].hdisplay && mode->yres == shared->mode[0].vdisplay)\n               break;\n\n          mode = mode->next;\n     }\n\n     return mode;\n}\n\nstatic DFBResult\nsystem_thread_init()\n{\n     return DFB_OK;\n}\n\nstatic bool\nsystem_input_filter( CoreInputDevice *device,\n                     DFBInputEvent   *event )\n{\n     DRMKMSData       *drmkms = dfb_system_data();\n     DRMKMSDataShared *shared;\n\n     D_ASSERT( drmkms != NULL );\n     D_ASSERT( drmkms->shared != NULL );\n\n     shared = drmkms->shared;\n\n     if (shared->vt) {\n          if (DFB_KEY_TYPE( event->key_symbol ) == DIKT_FUNCTION && event->modifiers == (DIMM_CONTROL | DIMM_ALT) &&\n              (event->type == DIET_KEYPRESS || event->type == DIET_KEYRELEASE))\n               return drmkms_vt_switch_num( event->key_symbol - DIKS_F1 + 1, event->type == DIET_KEYPRESS );\n     }\n\n     return false;\n}\n\nstatic volatile void *\nsystem_map_mmio( unsigned int offset,\n                 int          length )\n{\n     return NULL;\n}\n\nstatic void\nsystem_unmap_mmio( volatile void *addr,\n                   int            length )\n{\n}\n\nstatic unsigned int\nsystem_get_accelerator()\n{\n     return direct_config_get_int_value( \"accelerator\" );\n}\n\nstatic unsigned long\nsystem_video_memory_physical( unsigned int offset )\n{\n     unsigned long  video_phys;\n     const char    *value;\n\n     /* Physical start of video memory. */\n     if ((value = direct_config_get_value( \"video-phys\" ))) {\n          char *error;\n\n          video_phys = strtoul( value, &error, 16 );\n\n          if (*error) {\n               D_ERROR( \"DRMKMS/System: 'video-phys': Error in value '%s'!\\n\", error );\n               video_phys = 0;\n          }\n     }\n     else\n          video_phys = 0;\n\n     return video_phys + offset;\n}\n\nstatic void *\nsystem_video_memory_virtual( unsigned int offset )\n{\n     return NULL;\n}\n\nstatic unsigned int\nsystem_videoram_length()\n{\n     /* Length of video memory. */\n     unsigned int video_length = direct_config_get_int_value( \"video-length\" );\n\n     return video_length;\n}\n\nstatic void\nsystem_get_busid( int *ret_bus,\n                  int *ret_dev,\n                  int *ret_func )\n{\n}\n\nstatic void\nsystem_get_deviceid( unsigned int *ret_vendor_id,\n                     unsigned int *ret_device_id )\n{\n}\n"
  },
  {
    "path": "systems/drmkms/drmkms_system.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DRMKMS_SYSTEM_H__\n#define __DRMKMS_SYSTEM_H__\n\n#include <core/coredefs.h>\n#include <core/coretypes.h>\n#include <core/video_mode.h>\n#include <fusion/types.h>\n#include <xf86drm.h>\n#include <xf86drmMode.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     FusionSHMPoolShared   *shmpool;\n\n     CoreSurfacePool       *pool;\n\n     char                   device_name[256];          /* DRM/KMS device name, e.g. /dev/dri/card0 */\n     bool                   use_prime_fd;              /* DRM/KMS PRIME file descriptor enabled */\n\n     bool                   vt;                        /* use VT handling */\n\n     bool                   mirror_outputs;            /* enable mirror display */\n     bool                   multihead_outputs;         /* enable multi-head display */\n\n     VideoMode             *modes;                     /* linked list of valid video modes */\n     drmModeModeInfo        mode[8];                   /* current video mode (for each available CRTC) */\n\n     DFBDimension           primary_dimension[8];\n     DFBRectangle           primary_rect;\n     uint32_t               primary_fb;\n     DFBSurfacePixelFormat  primary_format;\n\n     int                    primary_index_count;\n     int                    plane_index_count;\n\n     int                    layer_indices[MAX_LAYERS];\n} DRMKMSDataShared;\n\ntypedef struct {\n     DRMKMSDataShared   *shared;\n\n     CoreDFB            *core;\n\n     int                 fd;              /* DRM/KMS file descriptor */\n\n     drmModeRes         *resources;       /* display configuration information */\n     drmModePlaneRes    *plane_resources; /* planes information */\n     drmModeConnector   *connector[8];\n     drmModeEncoder     *encoder[8];\n     drmModeCrtc        *crtc;\n     int                 enabled_crtcs;   /* CRTCs enabled (limiting to 8) */\n\n     DFBDisplayLayerIDs  layer_ids[8];\n     DFBDisplayLayerID   layer_id;\n\n     drmEventContext     event_context;\n     DirectThread       *thread;\n} DRMKMSData;\n\n#endif\n"
  },
  {
    "path": "systems/drmkms/drmkms_vt.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core.h>\n#include <direct/system.h>\n#include <direct/thread.h>\n#include <linux/vt.h>\n#include <sys/kd.h>\n#include <termios.h>\n\n#include \"drmkms_vt.h\"\n\nD_DEBUG_DOMAIN( VT, \"DRMKMS/VT\", \"DRM/KMS VT Handling\" );\n\n/**********************************************************************************************************************/\n\n#define SIG_SWITCH_FROM SIGUSR1\n#define SIG_SWITCH_TO   SIGUSR2\n\ntypedef struct {\n     CoreDFB          *core;\n\n     int               fd0;       /* file descriptor of /dev/tty0 */\n     int               fd;        /* file descriptor of /dev/ttyN where N is the VT number where DirectFB runs */\n\n     int               prev;      /* VT number from which DirectFB was started */\n     int               num;       /* VT number where DirectFB runs (use the given VT number instead of the current or a\n                                     new one allocated for a VT switch), num = prev if no VT switch */\n     bool              graphics;  /* put terminal into graphics mode */\n     bool              vt_switch; /* allocate a new VT or use the given VT, and then switch to it */\n     bool              switching; /* allow VT switching by pressing Ctrl+Alt+<F?> */\n\n     struct termios    old_ts;    /* original termios */\n     struct vt_mode    old_vtm;   /* original vt mode */\n\n     struct sigaction  sig_usr1;  /* previous action for SIGUSR1 */\n     struct sigaction  sig_usr2;  /* previous action for SIGUSR2 */\n     int               sig;       /* signal signum */\n\n     DirectMutex       lock;\n     DirectWaitQueue   wait;\n     DirectThread     *thread;\n\n     bool              flush;\n     DirectThread     *flush_thread;\n} VirtualTerminal;\n\n/**********************************************************************************************************************/\n\nstatic VirtualTerminal *vt = NULL;\n\nstatic void *\nvt_switcher( DirectThread *thread,\n             void         *arg )\n{\n     D_DEBUG_AT( VT, \"%s( %p, %p )\\n\", __FUNCTION__, thread, arg );\n\n     direct_mutex_lock( &vt->lock );\n\n     while (true) {\n          direct_thread_testcancel( thread );\n\n          D_DEBUG_AT( VT, \"%s() <- signal %d\\n\", __FUNCTION__, vt->sig );\n\n          switch (vt->sig) {\n               default:\n                    D_BUG( \"unexpected sig\" );\n                    /* fall through */\n\n               case -1:\n                    direct_waitqueue_wait( &vt->wait, &vt->lock );\n                    continue;\n\n               case SIG_SWITCH_FROM:\n                    if (dfb_core_suspend( vt->core ) == DFB_OK) {\n                         if (ioctl( vt->fd, VT_RELDISP, VT_ACKACQ ) < 0)\n                              D_PERROR( \"DRMKMS/VT: VT_RELDISP failed!\\n\" );\n                    }\n\n                    break;\n\n               case SIG_SWITCH_TO:\n                    if (dfb_core_resume( vt->core ) == DFB_OK) {\n                         if (ioctl( vt->fd, VT_RELDISP, VT_ACKACQ ) < 0)\n                              D_PERROR( \"DRMKMS/VT: VT_RELDISP failed!\\n\" );\n\n                         if (vt->graphics) {\n                              if (ioctl( vt->fd, KDSETMODE, KD_GRAPHICS ) < 0)\n                                   D_PERROR( \"DRMKMS/VT: KD_GRAPHICS failed!\\n\" );\n                         }\n                    }\n                    break;\n          }\n\n          vt->sig = -1;\n\n          direct_waitqueue_signal( &vt->wait );\n     }\n\n     return NULL;\n}\n\nstatic void\nvt_switch_handler( int signum )\n{\n     D_DEBUG_AT( VT, \"%s( %d )\\n\", __FUNCTION__, signum );\n\n     direct_mutex_lock( &vt->lock );\n\n     while (vt->sig != -1)\n          direct_waitqueue_wait( &vt->wait, &vt->lock );\n\n     vt->sig = signum;\n\n     direct_waitqueue_signal( &vt->wait );\n\n     direct_mutex_unlock( &vt->lock );\n}\n\nstatic DFBResult\nvt_init_switching( void )\n{\n     char           buf[32];\n     struct termios ts;\n     const char     blankoff_str[]  = \"\\033[9;0]\";\n     const char     cursoroff_str[] = \"\\033[?1;0;0c\";\n     ssize_t        sz;\n\n     D_UNUSED_P( sz );\n\n     D_DEBUG_AT( VT, \"%s()\\n\", __FUNCTION__ );\n\n     snprintf( buf, sizeof(buf), \"/dev/tty%d\", vt->num );\n     vt->fd = open( buf, O_RDWR | O_NOCTTY );\n     if (vt->fd < 0) {\n          if (errno == ENOENT) {\n               snprintf( buf, sizeof(buf), \"/dev/vc/%d\", vt->num );\n               vt->fd = open( buf, O_RDWR | O_NOCTTY );\n               if (vt->fd < 0) {\n                    if (errno == ENOENT) {\n                         D_PERROR( \"DRMKMS/VT: Couldn't open neither '/dev/tty%d' nor '/dev/vc/%d'!\\n\",\n                                    vt->num, vt->num );\n                    }\n                    else\n                         D_PERROR( \"DRMKMS/VT: Error opening '%s'!\\n\", buf );\n\n                    return DFB_INIT;\n               }\n          }\n          else {\n               D_PERROR( \"DRMKMS/VT: Error opening '%s'!\\n\", buf );\n\n               return DFB_INIT;\n          }\n     }\n\n     ioctl( vt->fd, TIOCSCTTY, 0 );\n\n     if (ioctl( vt->fd, KDSKBMODE, K_MEDIUMRAW ) < 0) {\n          D_PERROR( \"DRMKMS/VT: K_MEDIUMRAW failed!\\n\" );\n          close( vt->fd );\n          return DFB_INIT;\n     }\n\n     if (tcgetattr( vt->fd, &vt->old_ts ) < 0) {\n          D_PERROR( \"DRMKMS/VT: tcgetattr() failed!\\n\" );\n          ioctl( vt->fd, KDSKBMODE, K_XLATE );\n          close( vt->fd );\n          return DFB_INIT;\n     }\n\n     ts = vt->old_ts;\n     ts.c_iflag      = 0;\n     ts.c_lflag     &= ~(ICANON | ECHO | ISIG);\n     ts.c_cc[VTIME]  = 0;\n     ts.c_cc[VMIN]   = 1;\n\n     if (tcsetattr( vt->fd, TCSAFLUSH, &ts ) < 0) {\n          D_PERROR( \"DRMKMS/VT: tcsetattr() failed!\\n\" );\n          ioctl( vt->fd, KDSKBMODE, K_XLATE );\n          close( vt->fd );\n          return DFB_INIT;\n     }\n\n     sz = write( vt->fd, cursoroff_str, sizeof(cursoroff_str) );\n\n     if (vt->graphics) {\n          if (ioctl( vt->fd, KDSETMODE, KD_GRAPHICS ) < 0) {\n               D_PERROR( \"DRMKMS/VT: KD_GRAPHICS failed!\\n\" );\n               tcsetattr( vt->fd, TCSAFLUSH, &vt->old_ts );\n               ioctl( vt->fd, KDSKBMODE, K_XLATE );\n               close( vt->fd );\n               return DFB_INIT;\n          }\n     }\n     else {\n          sz = write( vt->fd, blankoff_str, sizeof(blankoff_str) );\n     }\n\n     if (vt->switching) {\n          struct vt_mode   vtm;\n          struct sigaction sig_tty;\n\n          memset( &sig_tty, 0, sizeof(sig_tty) );\n          sig_tty.sa_handler = vt_switch_handler;\n          sigfillset( &sig_tty.sa_mask );\n\n          if (sigaction( SIG_SWITCH_FROM, &sig_tty, &vt->sig_usr1 ) ||\n              sigaction( SIG_SWITCH_TO, &sig_tty, &vt->sig_usr2 )) {\n               D_PERROR( \"DRMKMS/VT: sigaction() failed!\\n\" );\n               tcsetattr( vt->fd, TCSAFLUSH, &vt->old_ts );\n               ioctl( vt->fd, KDSKBMODE, K_XLATE );\n               close( vt->fd );\n               return DFB_INIT;\n          }\n\n          if (ioctl( vt->fd, VT_GETMODE, &vt->old_vtm )) {\n               D_PERROR( \"DRMKMS/VT: VT_GETMODE failed!\\n\" );\n               sigaction( SIG_SWITCH_FROM, &vt->sig_usr1, NULL );\n               sigaction( SIG_SWITCH_TO, &vt->sig_usr2, NULL );\n               tcsetattr( vt->fd, TCSAFLUSH, &vt->old_ts );\n               ioctl( vt->fd, KDSKBMODE, K_XLATE );\n               close( vt->fd );\n               return DFB_INIT;\n          }\n\n          memset( &vtm, 0, sizeof(vtm) );\n          vtm.mode   = VT_PROCESS;\n          vtm.relsig = SIG_SWITCH_FROM;\n          vtm.acqsig = SIG_SWITCH_TO;\n\n          if (ioctl( vt->fd, VT_SETMODE, &vtm ) < 0) {\n               D_PERROR( \"DRMKMS/VT: VT_SETMODE failed!\\n\" );\n               ioctl( vt->fd, VT_SETMODE, &vt->old_vtm );\n               sigaction( SIG_SWITCH_FROM, &vt->sig_usr1, NULL );\n               sigaction( SIG_SWITCH_TO, &vt->sig_usr2, NULL );\n               tcsetattr( vt->fd, TCSAFLUSH, &vt->old_ts );\n               ioctl( vt->fd, KDSKBMODE, K_XLATE );\n               close( vt->fd );\n               return DFB_INIT;\n          }\n\n          direct_recursive_mutex_init( &vt->lock );\n\n          direct_waitqueue_init( &vt->wait );\n\n          vt->sig = -1;\n\n          vt->thread = direct_thread_create( DTT_CRITICAL, vt_switcher, NULL, \"VT Switcher\" );\n     }\n\n     return DFB_OK;\n}\n\nstatic void *\nvt_flusher( DirectThread *thread,\n            void         *arg )\n{\n     D_DEBUG_AT( VT, \"%s( %p, %p )\\n\", __FUNCTION__, thread, arg );\n\n     while (vt->flush) {\n          int    err;\n          fd_set set;\n\n          FD_ZERO( &set );\n          FD_SET( vt->fd, &set );\n\n          err = select( vt->fd + 1, &set, NULL, NULL, NULL );\n\n          if (err < 0 && errno == EINTR)\n               continue;\n\n          if (err < 0 || !vt->flush)\n               break;\n\n          tcflush( vt->fd, TCIFLUSH );\n     }\n\n     return NULL;\n}\n\nstatic void\nvt_start_flushing( void )\n{\n     vt->flush        = true;\n     vt->flush_thread = direct_thread_create( DTT_DEFAULT, vt_flusher, NULL, \"VT Flusher\" );\n}\n\nDFBResult\ndrmkms_vt_initialize( CoreDFB *core )\n{\n     DFBResult       ret;\n     struct vt_stat  vs;\n\n     D_DEBUG_AT( VT, \"%s()\\n\", __FUNCTION__ );\n\n     vt = D_CALLOC( 1, sizeof(VirtualTerminal) );\n     if (!vt)\n          return D_OOM();\n\n     vt->core = core;\n\n     vt->num = direct_config_get_int_value_with_default( \"vt-num\", -1 );\n\n     /* Check root privileges for the VT switch. */\n     if (!direct_geteuid()) {\n          if (direct_config_has_name( \"no-vt-switch\" ) && !direct_config_has_name( \"vt-switch\" ))\n               D_INFO( \"DRMKMS/VT: Don't switch to a new VT or to the given VT\\n\" );\n          else\n               vt->vt_switch = true;\n     }\n\n     /* Always put terminal into graphics mode if no VT switch. */\n     if (!vt->vt_switch)\n          vt->graphics = true;\n     else {\n          if (direct_config_has_name( \"no-vt-graphics\" ) && !direct_config_has_name( \"vt-graphics\" ))\n               D_INFO( \"DRMKMS/VT: Don't put terminal into graphics mode\\n\" );\n          else\n               vt->graphics = true;\n     }\n\n     /* Check if VT switching is allowed. */\n     if (direct_config_has_name( \"no-vt-switching\" ) && !direct_config_has_name( \"vt-switching\" ))\n          D_INFO( \"DRMKMS/VT: Don't allow VT switching by pressing Ctrl+Alt+<F?>\\n\" );\n     else\n          vt->switching = true;\n\n     setsid();\n\n     vt->fd0 = open( \"/dev/tty0\", O_RDONLY | O_NOCTTY );\n     if (vt->fd0 < 0) {\n          if (errno == ENOENT) {\n               vt->fd0 = open( \"/dev/vc/0\", O_RDONLY | O_NOCTTY );\n               if (vt->fd0 < 0) {\n                    if (errno == ENOENT) {\n                         D_PERROR( \"DRMKMS/VT: Couldn't open neither '/dev/tty0' nor '/dev/vc/0'!\\n\" );\n                    }\n                    else\n                         D_PERROR( \"DRMKMS/VT: Error opening '/dev/vc/0'!\\n\" );\n\n                    D_FREE( vt );\n                    vt = NULL;\n\n                    return DFB_INIT;\n               }\n          }\n          else {\n               D_PERROR( \"DRMKMS/VT: Error opening '/dev/tty0'!\\n\" );\n\n               D_FREE( vt );\n               vt = NULL;\n\n               return DFB_INIT;\n          }\n     }\n\n     if (ioctl( vt->fd0, VT_GETSTATE, &vs ) < 0) {\n          D_PERROR( \"DRMKMS/VT: VT_GETSTATE failed!\\n\" );\n          close( vt->fd0 );\n          D_FREE( vt );\n          vt = NULL;\n          return DFB_INIT;\n     }\n\n     vt->prev = vs.v_active;\n\n     if (!vt->vt_switch) {\n          vt->num = vt->prev;\n     }\n     else {\n          if (vt->num == -1) {\n               int err;\n\n               err = ioctl( vt->fd0, VT_OPENQRY, &vt->num );\n               if (err < 0 || vt->num == -1) {\n                    D_PERROR( \"DRMKMS/VT: Cannot allocate VT!\\n\" );\n                    close( vt->fd0 );\n                    D_FREE( vt );\n                    vt = NULL;\n                    return DFB_INIT;\n               }\n          }\n\n          D_DEBUG_AT( VT, \"  -> switching to vt %d\\n\", vt->num );\n\n          while (ioctl( vt->fd0, VT_ACTIVATE, vt->num ) < 0) {\n               if (errno == EINTR)\n                    continue;\n               D_PERROR( \"DRMKMS/VT: VT_ACTIVATE failed!\\n\" );\n               close( vt->fd0 );\n               D_FREE( vt );\n               vt = NULL;\n               return DFB_INIT;\n          }\n\n          while (ioctl( vt->fd0, VT_WAITACTIVE, vt->num ) < 0) {\n               if (errno == EINTR)\n                    continue;\n               D_PERROR( \"DRMKMS/VT: VT_WAITACTIVE failed!\\n\" );\n               close( vt->fd0 );\n               D_FREE( vt );\n               vt = NULL;\n               return DFB_INIT;\n          }\n\n          usleep( 40000 );\n     }\n\n     ret = vt_init_switching();\n     if (ret) {\n          if (vt->vt_switch) {\n               D_DEBUG_AT( VT, \"  -> switching back...\\n\" );\n               ioctl( vt->fd0, VT_ACTIVATE, vt->prev );\n               ioctl( vt->fd0, VT_WAITACTIVE, vt->prev );\n               D_DEBUG_AT( VT, \"  -> ...switched back\\n\" );\n               ioctl( vt->fd0, VT_DISALLOCATE, vt->num );\n          }\n\n          close( vt->fd0 );\n          D_FREE( vt );\n          vt = NULL;\n          return ret;\n     }\n\n     vt_start_flushing();\n\n     return DFB_OK;\n}\n\nstatic void\nvt_stop_flushing( void )\n{\n     vt->flush = false;\n     direct_thread_cancel( vt->flush_thread );\n     direct_thread_join( vt->flush_thread );\n     direct_thread_destroy( vt->flush_thread );\n     vt->flush_thread = NULL;\n}\n\nDFBResult\ndrmkms_vt_shutdown( bool emergency )\n{\n     const char blankon_str[]  = \"\\033[9;10]\";\n     const char cursoron_str[] = \"\\033[?0;0;0c\";\n     ssize_t    sz;\n\n     D_UNUSED_P( sz );\n\n     D_DEBUG_AT( VT, \"%s()\\n\", __FUNCTION__ );\n\n     if (!vt)\n          return DFB_OK;\n\n     vt_stop_flushing();\n\n     if (vt->switching) {\n          if (ioctl( vt->fd, VT_SETMODE, &vt->old_vtm ) < 0)\n               D_PERROR( \"DRMKMS/VT: VT_SETMODE for original values failed!\\n\" );\n\n          sigaction( SIG_SWITCH_FROM, &vt->sig_usr1, NULL );\n          sigaction( SIG_SWITCH_TO, &vt->sig_usr2, NULL );\n\n          direct_thread_cancel( vt->thread );\n          direct_thread_join( vt->thread );\n          direct_thread_destroy( vt->thread );\n\n          direct_mutex_deinit( &vt->lock );\n          direct_waitqueue_deinit( &vt->wait );\n     }\n\n     if (vt->graphics) {\n          if (ioctl( vt->fd, KDSETMODE, KD_TEXT ) < 0)\n               D_PERROR( \"DRMKMS/VT: KD_TEXT failed!\\n\" );\n     }\n     else\n          sz = write( vt->fd, blankon_str, sizeof(blankon_str) );\n\n     sz = write( vt->fd, cursoron_str, sizeof(cursoron_str) );\n\n     if (tcsetattr( vt->fd, TCSAFLUSH, &vt->old_ts ) < 0)\n          D_PERROR( \"DRMKMS/VT: tcsetattr() for original values failed!\\n\" );\n\n     if (ioctl( vt->fd, KDSKBMODE, K_XLATE ) < 0)\n          D_PERROR( \"DRMKMS/VT: K_XLATE failed!\\n\" );\n\n     if (vt->vt_switch) {\n          D_DEBUG_AT( VT, \"  -> switching back...\\n\" );\n\n          if (ioctl( vt->fd0, VT_ACTIVATE, vt->prev ) < 0)\n               D_PERROR( \"DRMKMS/VT: VT_ACTIVATE failed!\\n\" );\n\n          if (ioctl( vt->fd0, VT_WAITACTIVE, vt->prev ) < 0)\n               D_PERROR( \"DRMKMS/VT: VT_WAITACTIVE failed!\\n\" );\n\n          D_DEBUG_AT( VT, \"  -> ...switched back\\n\" );\n\n          usleep( 40000 );\n\n          if (close( vt->fd ) < 0)\n               D_PERROR( \"DRMKMS/VT: Unable to close file descriptor of allocated VT!\\n\" );\n\n          ioctl( vt->fd0, VT_DISALLOCATE, vt->num );\n     }\n     else {\n          if (close( vt->fd ) < 0)\n               D_PERROR( \"DRMKMS/VT: Unable to close file descriptor of current VT!\\n\" );\n     }\n\n     if (close( vt->fd0 ) < 0)\n          D_PERROR( \"DRMKMS/VT: Unable to close file descriptor of tty0!\\n\" );\n\n     D_FREE( vt );\n     vt = NULL;\n\n     return DFB_OK;\n}\n\nbool\ndrmkms_vt_switch_num( int  num,\n                      bool key_pressed )\n{\n     D_DEBUG_AT( VT, \"%s( %d )\\n\", __FUNCTION__, num );\n\n     if (!vt->switching)\n          return false;\n\n     if (!key_pressed)\n          return true;\n\n     D_DEBUG_AT( VT, \"  -> switching to vt %d\\n\", num );\n\n     if (ioctl( vt->fd0, VT_ACTIVATE, num ) < 0)\n          D_PERROR( \"DRMKMS/VT: VT_ACTIVATE failed!\\n\" );\n\n     return true;\n}\n"
  },
  {
    "path": "systems/drmkms/drmkms_vt.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __DRMKMS_VT_H__\n#define __DRMKMS_VT_H__\n\n#include <core/coretypes.h>\n\n/**********************************************************************************************************************/\n\nDFBResult drmkms_vt_initialize( CoreDFB *core );\n\nDFBResult drmkms_vt_shutdown  ( bool     emergency );\n\nbool      drmkms_vt_switch_num( int      num,\n                                bool     key_pressed );\n\n#endif\n"
  },
  {
    "path": "systems/drmkms/meson.build",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\ndrmkms_dep = dependency('libdrm', required: false)\n\nif not drmkms_dep.found()\n  warning('Building without DRM/KMS support.')\n  subdir_done()\nendif\n\ndrmkms_sources = [\n  'drmkms_layer.c',\n  'drmkms_mode.c',\n  'drmkms_screen.c',\n  'drmkms_surface_pool.c',\n  'drmkms_system.c',\n  'drmkms_vt.c'\n]\n\nlibrary('directfb_drmkms',\n        drmkms_sources,\n        build_rpath: get_option('prefix') / get_option('libdir'),\n        dependencies: [directfb_dep, drmkms_dep],\n        install: true,\n        install_dir: moduledir / 'systems',\n        install_rpath: get_option('prefix') / get_option('libdir'))\n\nif get_option('default_library') == 'static'\n  pkgconfig.generate(filebase: 'directfb-system-drmkms',\n                     variables: 'moduledir=' + moduledir,\n                     name: 'DirectFB-system-drmkms',\n                     description: 'DRM/KMS system module',\n                     requires_private: 'libdrm',\n                     libraries_private: ['-L${moduledir}/systems',\n                                         '-Wl,--whole-archive -ldirectfb_drmkms -Wl,--no-whole-archive'])\nendif\n"
  },
  {
    "path": "systems/dummy/dummy.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/layers.h>\n#include <core/screens.h>\n#include <core/core_system.h>\n\nD_DEBUG_DOMAIN( Dummy_System, \"Dummy/System\", \"Dummy System Module\" );\n\nDFB_CORE_SYSTEM( dummy )\n\n/**********************************************************************************************************************/\n\n#define DUMMY_WIDTH  8\n#define DUMMY_HEIGHT 8\n#define DUMMY_FORMAT DSPF_ARGB\n\nstatic DFBResult\ndummyInitScreen( CoreScreen           *screen,\n                 void                 *driver_data,\n                 void                 *screen_data,\n                 DFBScreenDescription *description )\n{\n     /* Set name. */\n     snprintf( description->name, DFB_SCREEN_DESC_NAME_LENGTH, \"Dummy Screen\" );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndummyGetScreenSize( CoreScreen *screen,\n                    void       *driver_data,\n                    void       *screen_data,\n                    int        *ret_width,\n                    int        *ret_height )\n{\n     *ret_width  = dfb_config->mode.width  ?: DUMMY_WIDTH;\n     *ret_height = dfb_config->mode.height ?: DUMMY_HEIGHT;\n\n     return DFB_OK;\n}\n\nstatic ScreenFuncs dummyScreenFuncs = {\n     .InitScreen    = dummyInitScreen,\n     .GetScreenSize = dummyGetScreenSize\n};\n\n/**********************************************************************************************************************/\n\nstatic DFBResult\ndummyPrimaryInitLayer( CoreLayer                  *layer,\n                       void                       *driver_data,\n                       void                       *layer_data,\n                       DFBDisplayLayerDescription *description,\n                       DFBDisplayLayerConfig      *config,\n                       DFBColorAdjustment         *adjustment )\n{\n     /* Set type and capabilities. */\n     description->type             = DLTF_GRAPHICS;\n     description->caps             = DLCAPS_SURFACE;\n     description->surface_caps     = DSCAPS_SYSTEMONLY;\n     description->surface_accessor = CSAID_CPU;\n\n     /* Set name. */\n     snprintf( description->name, DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, \"Dummy Primary Layer\" );\n\n     /* Fill out the default configuration. */\n     config->flags       = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE;\n     config->width       = dfb_config->mode.width  ?: DUMMY_WIDTH;\n     config->height      = dfb_config->mode.height ?: DUMMY_HEIGHT;\n     config->pixelformat = dfb_config->mode.format ?: DUMMY_FORMAT;\n     config->buffermode  = DLBM_FRONTONLY;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndummyPrimaryTestRegion( CoreLayer                  *layer,\n                        void                       *driver_data,\n                        void                       *layer_data,\n                        CoreLayerRegionConfig      *config,\n                        CoreLayerRegionConfigFlags *ret_failed )\n{\n     if (ret_failed)\n          *ret_failed = DLCONF_NONE;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndummyPrimarySetRegion( CoreLayer                  *layer,\n                       void                       *driver_data,\n                       void                       *layer_data,\n                       void                       *region_data,\n                       CoreLayerRegionConfig      *config,\n                       CoreLayerRegionConfigFlags  updated,\n                       CoreSurface                *surface,\n                       CorePalette                *palette,\n                       CoreSurfaceBufferLock      *left_lock,\n                       CoreSurfaceBufferLock      *right_lock )\n{\n     return DFB_OK;\n}\n\nstatic DFBResult\ndummyPrimaryFlipRegion( CoreLayer             *layer,\n                        void                  *driver_data,\n                        void                  *layer_data,\n                        void                  *region_data,\n                        CoreSurface           *surface,\n                        DFBSurfaceFlipFlags    flags,\n                        const DFBRegion       *left_update,\n                        CoreSurfaceBufferLock *left_lock,\n                        const DFBRegion       *right_update,\n                        CoreSurfaceBufferLock *right_lock )\n{\n     dfb_surface_notify_display( surface, left_lock->buffer );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ndummyPrimaryUpdateRegion( CoreLayer             *layer,\n                          void                  *driver_data,\n                          void                  *layer_data,\n                          void                  *region_data,\n                          CoreSurface           *surface,\n                          const DFBRegion       *left_update,\n                          CoreSurfaceBufferLock *left_lock,\n                          const DFBRegion       *right_update,\n                          CoreSurfaceBufferLock *right_lock )\n{\n     dfb_surface_notify_display( surface, left_lock->buffer );\n\n     return DFB_OK;\n}\n\nstatic DisplayLayerFuncs dummyPrimaryLayerFuncs = {\n     .InitLayer    = dummyPrimaryInitLayer,\n     .TestRegion   = dummyPrimaryTestRegion,\n     .SetRegion    = dummyPrimarySetRegion,\n     .FlipRegion   = dummyPrimaryFlipRegion,\n     .UpdateRegion = dummyPrimaryUpdateRegion\n};\n\n/**********************************************************************************************************************/\n\nstatic void\nsystem_get_info( CoreSystemInfo *info )\n{\n     info->version.major = 0;\n     info->version.minor = 1;\n\n     info->caps = CSCAPS_ACCELERATION | CSCAPS_NOTIFY_DISPLAY | CSCAPS_SYSMEM_EXTERNAL;\n\n     snprintf( info->name,   DFB_CORE_SYSTEM_INFO_NAME_LENGTH,   \"Dummy\" );\n     snprintf( info->vendor, DFB_CORE_SYSTEM_INFO_VENDOR_LENGTH, \"DirectFB\" );\n}\n\nstatic DFBResult\nsystem_initialize( CoreDFB  *core,\n                   void    **ret_data )\n{\n     CoreScreen *screen;\n\n     D_DEBUG_AT( Dummy_System, \"%s()\\n\", __FUNCTION__ );\n\n     D_INFO( \"Dummy/System: Using offscreen\\n\" );\n\n     screen = dfb_screens_register( NULL, &dummyScreenFuncs );\n\n     dfb_layers_register( screen, NULL, &dummyPrimaryLayerFuncs );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsystem_join( CoreDFB  *core,\n             void    **ret_data )\n{\n     CoreScreen *screen;\n\n     D_DEBUG_AT( Dummy_System, \"%s()\\n\", __FUNCTION__ );\n\n     D_INFO( \"Dummy/System: Using offscreen\\n\" );\n\n     screen = dfb_screens_register( NULL, &dummyScreenFuncs );\n\n     dfb_layers_register( screen, NULL, &dummyPrimaryLayerFuncs );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsystem_shutdown( bool emergency )\n{\n     D_DEBUG_AT( Dummy_System, \"%s()\\n\", __FUNCTION__ );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsystem_leave( bool emergency )\n{\n     D_DEBUG_AT( Dummy_System, \"%s()\\n\", __FUNCTION__ );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsystem_suspend()\n{\n     return DFB_OK;\n}\n\nstatic DFBResult\nsystem_resume()\n{\n     return DFB_OK;\n}\n\nstatic VideoMode *\nsystem_get_modes()\n{\n     return NULL;\n}\n\nstatic VideoMode *\nsystem_get_current_mode()\n{\n     return NULL;\n}\n\nstatic DFBResult\nsystem_thread_init()\n{\n     return DFB_OK;\n}\n\nstatic bool\nsystem_input_filter( CoreInputDevice *device,\n                     DFBInputEvent   *event )\n{\n     return false;\n}\n\nstatic volatile void *\nsystem_map_mmio( unsigned int    offset,\n                 int             length )\n{\n     return NULL;\n}\n\nstatic void\nsystem_unmap_mmio( volatile void  *addr,\n                   int             length )\n{\n}\n\nstatic unsigned int\nsystem_get_accelerator()\n{\n     return direct_config_get_int_value( \"accelerator\" );\n}\n\nstatic unsigned long\nsystem_video_memory_physical( unsigned int offset )\n{\n     return 0;\n}\n\nstatic void *\nsystem_video_memory_virtual( unsigned int offset )\n{\n     return NULL;\n}\n\nstatic unsigned int\nsystem_videoram_length()\n{\n     return 0;\n}\n\nstatic void\nsystem_get_busid( int *ret_bus,\n                  int *ret_dev,\n                  int *ret_func )\n{\n}\n\nstatic void\nsystem_get_deviceid( unsigned int *ret_vendor_id,\n                     unsigned int *ret_device_id )\n{\n}\n"
  },
  {
    "path": "systems/dummy/meson.build",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\ndummy_sources = [\n  'dummy.c'\n]\n\nlibrary('directfb_dummy',\n        dummy_sources,\n        build_rpath: get_option('prefix') / get_option('libdir'),\n        dependencies: directfb_dep,\n        install: true,\n        install_dir: moduledir / 'systems',\n        install_rpath: get_option('prefix') / get_option('libdir'))\n\nif get_option('default_library') == 'static'\n  pkgconfig.generate(filebase: 'directfb-system-dummy',\n                     variables: 'moduledir=' + moduledir,\n                     name: 'DirectFB-system-dummy',\n                     description: 'Dummy system module',\n                     libraries_private: ['-L${moduledir}/systems',\n                                         '-Wl,--whole-archive -ldirectfb_dummy -Wl,--no-whole-archive'])\nendif\n"
  },
  {
    "path": "systems/fbdev/fbdev_layer.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/layers.h>\n#include <core/palette.h>\n#include <core/screen.h>\n#include <core/screens.h>\n\n#include \"fbdev_mode.h\"\n\nD_DEBUG_DOMAIN( FBDev_Layer, \"FBDev/Layer\", \"FBDev Layer\" );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     CoreLayerRegionConfig config;\n} FBDevLayerData;\n\nstatic DFBResult\npan_display( FBDevData *fbdev,\n             int        xoffset,\n             int        yoffset,\n             bool       onsync )\n{\n     DFBResult                 ret;\n     FBDevDataShared          *shared;\n     struct fb_var_screeninfo *var;\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     var = &shared->current_var;\n\n     if (!fbdev->fix->xpanstep && !fbdev->fix->ypanstep && !fbdev->fix->ywrapstep)\n          return DFB_OK;\n\n     if (var->xres_virtual < xoffset + var->xres) {\n          D_ERROR( \"FBDev/Layer: Panning buffer out of range (xres %u, virtual xres %u, xoffset %d)!\\n\",\n                   var->xres, var->xres_virtual, xoffset );\n          return DFB_BUG;\n     }\n\n     if (var->yres_virtual < yoffset + var->yres) {\n          D_ERROR( \"FBDev/Layer: Panning buffer out of range (yres %u, virtual yres %u, yoffset %d)!\\n\",\n                    var->yres, var->yres_virtual, yoffset );\n          return DFB_BUG;\n     }\n\n     if (fbdev->fix->xpanstep)\n          var->xoffset = xoffset - (xoffset % fbdev->fix->xpanstep);\n     else\n          var->xoffset = 0;\n\n     if (fbdev->fix->ywrapstep) {\n          var->yoffset  = yoffset - (yoffset % fbdev->fix->ywrapstep);\n          var->vmode   |= FB_VMODE_YWRAP;\n     }\n     else if (fbdev->fix->ypanstep) {\n          var->yoffset  = yoffset - (yoffset % fbdev->fix->ypanstep);\n          var->vmode   &= ~FB_VMODE_YWRAP;\n     }\n     else\n          var->yoffset = 0;\n\n     var->activate = onsync ? FB_ACTIVATE_VBL : FB_ACTIVATE_NOW;\n\n     if (fbdev_ioctl( fbdev, FBIOPAN_DISPLAY, var, sizeof(*var) ) < 0) {\n          ret = errno2result( errno );\n          D_PERROR( \"FBDev/Layer: Panning display failed (xoffset = %u, yoffset = %u, ywrap = %d, vbl = %d)!\\n\",\n                    var->xoffset, var->yoffset,\n                    (var->vmode & FB_VMODE_YWRAP) ? 1 : 0, (var->activate & FB_ACTIVATE_VBL) ? 1 : 0);\n          return ret;\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nset_palette( FBDevData   *fbdev,\n             CorePalette *palette )\n{\n     DFBResult        ret;\n     int              i;\n     FBDevDataShared *shared;\n     struct fb_cmap  *cmap;\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n     D_ASSERT( palette != NULL );\n\n     shared = fbdev->shared;\n\n     cmap = &shared->current_cmap;\n\n     cmap->len = palette->num_entries <= 256 ? palette->num_entries : 256;\n\n     for (i = 0; i < cmap->len; i++) {\n          cmap->red[i]     = palette->entries[i].r;\n          cmap->green[i]   = palette->entries[i].g;\n          cmap->blue[i]    = palette->entries[i].b;\n          cmap->transp[i]  = 0xff - palette->entries[i].a;\n\n          cmap->red[i]    |= cmap->red[i] << 8;\n          cmap->green[i]  |= cmap->green[i] << 8;\n          cmap->blue[i]   |= cmap->blue[i] << 8;\n          cmap->transp[i] |= cmap->transp[i] << 8;\n     }\n\n     if (fbdev_ioctl( fbdev, FBIOPUTCMAP, cmap, sizeof(*cmap) ) < 0) {\n          ret = errno2result( errno );\n          D_PERROR( \"FBDev/Layer: Could not set the palette!\\n\" );\n          return ret;\n     }\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic int\nfbdevPrimaryLayerDataSize( void )\n{\n     return sizeof(FBDevLayerData);\n}\n\nstatic DFBResult\nfbdevPrimaryInitLayer( CoreLayer                  *layer,\n                       void                       *driver_data,\n                       void                       *layer_data,\n                       DFBDisplayLayerDescription *description,\n                       DFBDisplayLayerConfig      *config,\n                       DFBColorAdjustment         *adjustment )\n{\n     FBDevData       *fbdev = driver_data;\n     FBDevDataShared *shared;\n\n     D_DEBUG_AT( FBDev_Layer, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     /* Set type and capabilities. */\n     description->type = DLTF_GRAPHICS;\n     description->caps = DLCAPS_SURFACE | DLCAPS_BRIGHTNESS | DLCAPS_CONTRAST | DLCAPS_SATURATION;\n\n     /* Set name. */\n     snprintf( description->name, DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, \"FBDev Primary Layer\" );\n\n     /* Fill out default color adjustment. */\n     adjustment->flags      = DCAF_BRIGHTNESS | DCAF_CONTRAST | DCAF_SATURATION;\n     adjustment->brightness = 0x8000;\n     adjustment->contrast   = 0x8000;\n     adjustment->saturation = 0x8000;\n\n     /* Fill out the default configuration. */\n     config->flags       = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE;\n     config->width       = shared->mode.xres;\n     config->height      = shared->mode.yres;\n     config->pixelformat = dfb_config->mode.format ?: dfb_pixelformat_for_depth( shared->mode.bpp );\n     config->buffermode  = DLBM_FRONTONLY;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nfbdevPrimarySetColorAdjustment( CoreLayer          *layer,\n                                void               *driver_data,\n                                void               *layer_data,\n                                DFBColorAdjustment *adjustment )\n{\n     DFBResult        ret;\n     FBDevData       *fbdev      = driver_data;\n     FBDevDataShared *shared;\n     struct fb_cmap  *cmap;\n     struct fb_cmap  *temp;\n     int              brightness = (adjustment->brightness >> 8) - 128;\n     int              contrast   =  adjustment->contrast   >> 8;\n     int              saturation =  adjustment->saturation >> 8;\n     int              r, g, b, i;\n\n     D_DEBUG_AT( FBDev_Layer, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     cmap = &shared->current_cmap;\n     temp = &shared->temp_cmap;\n\n     if (fbdev->fix->visual != FB_VISUAL_DIRECTCOLOR)\n          return DFB_UNIMPLEMENTED;\n\n     /* Use gamma ramp to set color attributes. */\n     for (i = 0; i < cmap->len; i++) {\n          r = cmap->red[i];\n          g = cmap->green[i];\n          b = cmap->blue[i];\n          r >>= 8;\n          g >>= 8;\n          b >>= 8;\n\n          /* Brightness adjustment: increase/decrease each color channel by a constant amount as specified by the\n             brightness value. */\n          if (adjustment->flags & DCAF_BRIGHTNESS) {\n               r += brightness;\n               g += brightness;\n               b += brightness;\n\n               r = CLAMP( r, 0, 255 );\n               g = CLAMP( g, 0, 255 );\n               b = CLAMP( b, 0, 255 );\n          }\n\n          /* Contrast adjustment: increase/decrease the \"separation\" between colors in proportion to the value specified\n             by the contrast control. */\n          if (adjustment->flags & DCAF_CONTRAST) {\n               /* Increase contrast */\n               if (contrast > 128) {\n                    int c = contrast - 128;\n\n                    r = ((r + c / 2) / c) * c;\n                    g = ((g + c / 2) / c) * c;\n                    b = ((b + c / 2) / c) * c;\n               }\n               /* Decrease contrast */\n               else if (contrast < 127) {\n                    r = (r * contrast) >> 7;\n                    g = (g * contrast) >> 7;\n                    b = (b * contrast) >> 7;\n               }\n\n               r = CLAMP( r, 0, 255 );\n               g = CLAMP( g, 0, 255 );\n               b = CLAMP( b, 0, 255 );\n          }\n\n          /* Saturation adjustment: mix a proportion of medium gray to the color value. */\n          if (adjustment->flags & DCAF_SATURATION) {\n               if (saturation > 128) {\n                    int gray = saturation - 128;\n                    int color = 128 - gray;\n\n                    r = ((r - gray) << 7) / color;\n                    g = ((g - gray) << 7) / color;\n                    b = ((b - gray) << 7) / color;\n               }\n               else if (saturation < 128) {\n                    int color = saturation;\n                    int gray = 128 - color;\n\n                    r = ((r * color) >> 7) + gray;\n                    g = ((g * color) >> 7) + gray;\n                    b = ((b * color) >> 7) + gray;\n               }\n\n               r = CLAMP( r, 0, 255 );\n               g = CLAMP( g, 0, 255 );\n               b = CLAMP( b, 0, 255 );\n          }\n\n          r |= r << 8;\n          g |= g << 8;\n          b |= b << 8;\n\n          temp->red[i]   = r;\n          temp->green[i] = g;\n          temp->blue[i]  = b;\n     }\n\n     temp->start = cmap->start;\n     temp->len   = cmap->len;\n\n     if (fbdev_ioctl( fbdev, FBIOPUTCMAP, temp, sizeof(*temp) ) < 0) {\n          ret = errno2result( errno );\n          D_PERROR( \"FBDev/Layer: Could not set the palette!\\n\" );\n          return ret;\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nfbdevPrimaryTestRegion( CoreLayer                  *layer,\n                        void                       *driver_data,\n                        void                       *layer_data,\n                        CoreLayerRegionConfig      *config,\n                        CoreLayerRegionConfigFlags *ret_failed )\n{\n     CoreLayerRegionConfigFlags  failed = CLRCF_NONE;\n     FBDevData                  *fbdev  = driver_data;\n     FBDevDataShared            *shared;\n     VideoMode                  *mode, dummy;\n\n     D_DEBUG_AT( FBDev_Layer, \"%s( %dx%d, %s )\\n\", __FUNCTION__,\n                 config->source.w, config->source.h, dfb_pixelformat_name( config->format ) );\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     mode = fbdev_find_mode( fbdev, config->source.w, config->source.h );\n     if (!mode) {\n          dummy = shared->mode;\n\n          dummy.xres = config->source.w;\n          dummy.yres = config->source.h;\n          dummy.bpp  = DFB_BITS_PER_PIXEL( config->format );\n\n          mode = &dummy;\n     }\n\n     if (fbdev_test_mode( fbdev, mode, config ))\n          failed |= CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_FORMAT | CLRCF_BUFFERMODE;\n\n     if (config->options)\n          failed |= CLRCF_OPTIONS;\n\n     if ((config->source.x && !fbdev->fix->xpanstep) ||\n         (config->source.y && !fbdev->fix->ypanstep && !fbdev->fix->ywrapstep))\n          failed |= CLRCF_SOURCE;\n\n     if (ret_failed)\n          *ret_failed = failed;\n\n     if (failed)\n          return DFB_UNSUPPORTED;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nfbdevPrimarySetRegion( CoreLayer                  *layer,\n                       void                       *driver_data,\n                       void                       *layer_data,\n                       void                       *region_data,\n                       CoreLayerRegionConfig      *config,\n                       CoreLayerRegionConfigFlags  updated,\n                       CoreSurface                *surface,\n                       CorePalette                *palette,\n                       CoreSurfaceBufferLock      *left_lock,\n                       CoreSurfaceBufferLock      *right_lock )\n{\n     DFBResult        ret;\n     FBDevData       *fbdev = driver_data;\n     FBDevDataShared *shared;\n     FBDevLayerData  *data  = layer_data;\n\n     D_DEBUG_AT( FBDev_Layer, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n     D_ASSERT( data != NULL );\n\n     shared = fbdev->shared;\n\n     if (updated & (CLRCF_SOURCE | CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_FORMAT | CLRCF_BUFFERMODE)) {\n          if (updated & (CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_FORMAT | CLRCF_BUFFERMODE) ||\n              config->source.w != shared->current_var.xres || config->source.h != shared->current_var.yres) {\n               VideoMode *mode, dummy;\n\n               D_INFO( \"FBDev/Mode: Setting %dx%d %s\\n\", config->source.w, config->source.h,\n                       dfb_pixelformat_name( surface->config.format ) );\n\n               mode = fbdev_find_mode( fbdev, config->source.w, config->source.h );\n               if (!mode) {\n                    dummy = shared->mode;\n\n                    dummy.xres = config->source.w;\n                    dummy.yres = config->source.h;\n                    dummy.bpp  = DFB_BITS_PER_PIXEL( config->format );\n\n                    mode = &dummy;\n               }\n\n               ret = fbdev_set_mode( fbdev, mode, surface,\n                                     config->source.x, left_lock->offset / left_lock->pitch + config->source.y );\n               if (ret)\n                    return ret;\n          }\n          else {\n               ret = pan_display( fbdev, config->source.x, left_lock->offset / left_lock->pitch + config->source.y,\n                                  true );\n               if (ret)\n                    return ret;\n          }\n     }\n\n     if ((updated & CLRCF_PALETTE) && palette)\n          set_palette( fbdev, palette );\n\n     data->config = *config;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nfbdevPrimaryFlipRegion( CoreLayer             *layer,\n                        void                  *driver_data,\n                        void                  *layer_data,\n                        void                  *region_data,\n                        CoreSurface           *surface,\n                        DFBSurfaceFlipFlags    flags,\n                        const DFBRegion       *left_update,\n                        CoreSurfaceBufferLock *left_lock,\n                        const DFBRegion       *right_update,\n                        CoreSurfaceBufferLock *right_lock )\n{\n     DFBResult              ret;\n     FBDevData             *fbdev = driver_data;\n     FBDevDataShared       *shared;\n     FBDevLayerData        *data  = layer_data;\n     CoreLayerRegionConfig *config;\n\n     D_DEBUG_AT( FBDev_Layer, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n     D_ASSERT( data != NULL );\n\n     shared = fbdev->shared;\n\n     config = &data->config;\n\n     if (((flags & DSFLIP_WAITFORSYNC) == DSFLIP_WAITFORSYNC) && !shared->pollvsync_after)\n          dfb_screen_wait_vsync( dfb_screen_at( DSCID_PRIMARY ) );\n\n     ret = pan_display( fbdev, config->source.x, left_lock->offset / left_lock->pitch + config->source.y,\n                        (flags & DSFLIP_WAITFORSYNC) == DSFLIP_ONSYNC );\n     if (ret)\n          return ret;\n\n     if ((flags & DSFLIP_WAIT) && (shared->pollvsync_after || !(flags & DSFLIP_ONSYNC)))\n          dfb_screen_wait_vsync( dfb_screen_at( DSCID_PRIMARY ) );\n\n     dfb_surface_flip( surface, false );\n\n     return DFB_OK;\n}\n\nconst DisplayLayerFuncs fbdevPrimaryLayerFuncs = {\n     .LayerDataSize      = fbdevPrimaryLayerDataSize,\n     .InitLayer          = fbdevPrimaryInitLayer,\n     .SetColorAdjustment = fbdevPrimarySetColorAdjustment,\n     .TestRegion         = fbdevPrimaryTestRegion,\n     .SetRegion          = fbdevPrimarySetRegion,\n     .FlipRegion         = fbdevPrimaryFlipRegion\n};\n"
  },
  {
    "path": "systems/fbdev/fbdev_mode.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/gfxcard.h>\n#include <core/surface_buffer.h>\n#include <direct/memcpy.h>\n#include <directfb_util.h>\n#include <fusion/shmalloc.h>\n\n#include \"fbdev_mode.h\"\n\nD_DEBUG_DOMAIN( FBDev_Mode, \"FBDev/Mode\", \"FBDev Mode\" );\n\n/**********************************************************************************************************************/\n\nstatic DFBResult\nmode_to_var( const VideoMode           *mode,\n             DFBSurfacePixelFormat      pixelformat,\n             unsigned int               vxres,\n             unsigned int               vyres,\n             unsigned short             xpanstep,\n             unsigned short             ypanstep,\n             unsigned short             ywrapstep,\n             unsigned int               xoffset,\n             unsigned int               yoffset,\n             DFBDisplayLayerBufferMode  buffermode,\n             struct fb_var_screeninfo  *ret_var )\n{\n     struct fb_var_screeninfo var;\n\n     D_DEBUG_AT( FBDev_Mode, \"%s( %p )\\n\", __FUNCTION__, mode );\n\n     D_ASSERT( mode != NULL );\n     D_ASSERT( ret_var != NULL );\n\n     D_DEBUG_AT( FBDev_Mode, \"  -> resolution   %dx%d\\n\", mode->xres, mode->yres );\n     D_DEBUG_AT( FBDev_Mode, \"  -> virtual      %ux%u\\n\", vxres, vyres );\n     D_DEBUG_AT( FBDev_Mode, \"  -> pixelformat  %s\\n\", dfb_pixelformat_name( pixelformat ) );\n     D_DEBUG_AT( FBDev_Mode, \"  -> buffermode   %s\\n\",\n                 buffermode == DLBM_FRONTONLY  ? \"FRONTONLY\"  :\n                 buffermode == DLBM_BACKVIDEO  ? \"BACKVIDEO\"  :\n                 buffermode == DLBM_BACKSYSTEM ? \"BACKSYSTEM\" :\n                 buffermode == DLBM_TRIPLE     ? \"TRIPLE\"     : \"invalid!\" );\n\n     /* Start from current information. */\n     var = *ret_var;\n\n     /* Set values now. */\n     var.activate = FB_ACTIVATE_NOW;\n\n     /* Set timings. */\n     var.pixclock     = mode->pixclock;\n     var.left_margin  = mode->left_margin;\n     var.right_margin = mode->right_margin;\n     var.upper_margin = mode->upper_margin;\n     var.lower_margin = mode->lower_margin;\n     var.hsync_len    = mode->hsync_len;\n     var.vsync_len    = mode->vsync_len;\n\n     /* Set resolution. */\n     var.xres         = mode->xres;\n     var.yres         = mode->yres;\n     var.xres_virtual = vxres;\n     var.yres_virtual = vyres;\n\n     if (xpanstep)\n          var.xoffset = xoffset - (xoffset % xpanstep);\n     else\n          var.xoffset = 0;\n\n     if (ywrapstep)\n          var.yoffset = yoffset - (yoffset % ywrapstep);\n     else if (ypanstep)\n          var.yoffset = yoffset - (yoffset % ypanstep);\n     else\n          var.yoffset = 0;\n\n     /* Set buffer mode. */\n     switch (buffermode) {\n          case DLBM_TRIPLE:\n               if (ypanstep == 0 && ywrapstep == 0)\n                    return DFB_UNSUPPORTED;\n\n               var.yres_virtual *= 3;\n               break;\n\n          case DLBM_BACKVIDEO:\n               if (ypanstep == 0 && ywrapstep == 0)\n                    return DFB_UNSUPPORTED;\n\n               var.yres_virtual *= 2;\n               break;\n\n          case DLBM_BACKSYSTEM:\n          case DLBM_FRONTONLY:\n               break;\n\n          default:\n               return DFB_UNSUPPORTED;\n     }\n\n     /* Set pixel format. */\n     var.bits_per_pixel = DFB_BITS_PER_PIXEL( pixelformat );\n     var.transp.length  = var.transp.offset = 0;\n\n     switch (pixelformat) {\n          case DSPF_ARGB1555:\n               var.transp.length = 1;\n               var.red.length    = 5;\n               var.green.length  = 5;\n               var.blue.length   = 5;\n               var.transp.offset = 15;\n               var.red.offset    = 10;\n               var.green.offset  = 5;\n               var.blue.offset   = 0;\n               break;\n\n          case DSPF_RGBA5551:\n               var.transp.length = 1;\n               var.red.length    = 5;\n               var.green.length  = 5;\n               var.blue.length   = 5;\n               var.red.offset    = 11;\n               var.green.offset  = 6;\n               var.blue.offset   = 1;\n               var.transp.offset = 0;\n               break;\n\n          case DSPF_RGB555:\n               var.red.length    = 5;\n               var.green.length  = 5;\n               var.blue.length   = 5;\n               var.red.offset    = 10;\n               var.green.offset  = 5;\n               var.blue.offset   = 0;\n               break;\n\n          case DSPF_BGR555:\n               var.red.length    = 5;\n               var.green.length  = 5;\n               var.blue.length   = 5;\n               var.red.offset    = 0;\n               var.green.offset  = 5;\n               var.blue.offset   = 10;\n               break;\n\n          case DSPF_ARGB4444:\n               var.transp.length = 4;\n               var.red.length    = 4;\n               var.green.length  = 4;\n               var.blue.length   = 4;\n               var.transp.offset = 12;\n               var.red.offset    = 8;\n               var.green.offset  = 4;\n               var.blue.offset   = 0;\n               break;\n\n          case DSPF_RGBA4444:\n               var.transp.length = 4;\n               var.red.length    = 4;\n               var.green.length  = 4;\n               var.blue.length   = 4;\n               var.transp.offset = 0;\n               var.red.offset    = 12;\n               var.green.offset  = 8;\n               var.blue.offset   = 4;\n               break;\n\n         case DSPF_RGB444:\n               var.red.length    = 4;\n               var.green.length  = 4;\n               var.blue.length   = 4;\n               var.red.offset    = 8;\n               var.green.offset  = 4;\n               var.blue.offset   = 0;\n               break;\n\n         case DSPF_RGB32:\n               var.red.length    = 8;\n               var.green.length  = 8;\n               var.blue.length   = 8;\n               var.red.offset    = 16;\n               var.green.offset  = 8;\n               var.blue.offset   = 0;\n               break;\n\n          case DSPF_ARGB8565:\n               var.transp.length = 8;\n               var.transp.offset = 16;\n               /* fall through */\n\n          case DSPF_RGB16:\n               var.red.length    = 5;\n               var.green.length  = 6;\n               var.blue.length   = 5;\n               var.red.offset    = 11;\n               var.green.offset  = 5;\n               var.blue.offset   = 0;\n               break;\n\n          case DSPF_ARGB:\n          case DSPF_AiRGB:\n               var.transp.length = 8;\n               var.red.length    = 8;\n               var.green.length  = 8;\n               var.blue.length   = 8;\n               var.transp.offset = 24;\n               var.red.offset    = 16;\n               var.green.offset  = 8;\n               var.blue.offset   = 0;\n               break;\n\n          case DSPF_ABGR:\n               var.transp.length = 8;\n               var.red.length    = 8;\n               var.green.length  = 8;\n               var.blue.length   = 8;\n               var.transp.offset = 24;\n               var.red.offset    = 0;\n               var.green.offset  = 8;\n               var.blue.offset   = 16;\n               break;\n\n          case DSPF_LUT8:\n          case DSPF_RGB24:\n          case DSPF_RGB332:\n               break;\n\n          case DSPF_ARGB1666:\n               var.transp.length = 1;\n               var.red.length    = 6;\n               var.green.length  = 6;\n               var.blue.length   = 6;\n               var.transp.offset = 18;\n               var.red.offset    = 12;\n               var.green.offset  = 6;\n               var.blue.offset   = 0;\n               break;\n\n          case DSPF_ARGB6666:\n               var.transp.length = 6;\n               var.red.length    = 6;\n               var.green.length  = 6;\n               var.blue.length   = 6;\n               var.transp.offset = 18;\n               var.red.offset    = 12;\n               var.green.offset  = 6;\n               var.blue.offset   = 0;\n               break;\n\n          case DSPF_RGB18:\n               var.red.length    = 6;\n               var.green.length  = 6;\n               var.blue.length   = 6;\n               var.red.offset    = 12;\n               var.green.offset  = 6;\n               var.blue.offset   = 0;\n               break;\n\n          case DSPF_RGBAF88871:\n               var.transp.length = 7;\n               var.red.length    = 8;\n               var.green.length  = 8;\n               var.blue.length   = 8;\n               var.transp.offset = 1;\n               var.red.offset    = 24;\n               var.green.offset  = 16;\n               var.blue.offset   = 8;\n               break;\n\n          default:\n               return DFB_UNSUPPORTED;\n     }\n\n     /* Set sync options. */\n     var.sync = 0;\n     if (mode->hsync_high)\n          var.sync |= FB_SYNC_HOR_HIGH_ACT;\n     if (mode->vsync_high)\n          var.sync |= FB_SYNC_VERT_HIGH_ACT;\n     if (mode->csync_high)\n          var.sync |= FB_SYNC_COMP_HIGH_ACT;\n     if (mode->sync_on_green)\n          var.sync |= FB_SYNC_ON_GREEN;\n     if (mode->external_sync)\n          var.sync |= FB_SYNC_EXT;\n     if (mode->broadcast)\n          var.sync |= FB_SYNC_BROADCAST;\n\n     /* Set interlace/linedouble. */\n     var.vmode = 0;\n     if (mode->laced)\n          var.vmode |= FB_VMODE_INTERLACED;\n     if (mode->doubled)\n          var.vmode |= FB_VMODE_DOUBLE;\n\n     *ret_var = var;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ntest_mode_simple( FBDevData       *fbdev,\n                  const VideoMode *mode )\n{\n     DFBResult                 ret;\n     FBDevDataShared          *shared;\n     struct fb_var_screeninfo  var;\n\n     D_DEBUG_AT( FBDev_Mode, \"%s( %p )\\n\", __FUNCTION__, mode );\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n     D_ASSERT( mode != NULL );\n\n     shared = fbdev->shared;\n\n     var = shared->current_var;\n     ret = mode_to_var( mode, dfb_pixelformat_for_depth( mode->bpp ), mode->xres, mode->yres,\n                        fbdev->fix->xpanstep, fbdev->fix->ypanstep, fbdev->fix->ywrapstep, 0, 0, DLBM_FRONTONLY,\n                        &var );\n     if (ret)\n          return ret;\n\n     /* Enable test mode. */\n     var.activate = FB_ACTIVATE_TEST;\n\n     if (fbdev_ioctl( fbdev, FBIOPUT_VSCREENINFO, &var, sizeof(var) ) < 0) {\n          ret = errno2result( errno );\n          D_DEBUG_AT( FBDev_Mode, \"  -> FBIOPUT_VSCREENINFO failed!\\n\" );\n          return ret;\n     }\n\n     return DFB_OK;\n}\n\nstatic void\nread_modes( FBDevData *fbdev )\n{\n     FBDevDataShared *shared;\n     FILE            *fp;\n     char             line[80], label[32], value[16];\n     int              geometry, timings, dummy;\n     VideoMode        temp_mode;\n     VideoMode       *prev_mode = NULL;\n\n     D_DEBUG_AT( FBDev_Mode, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     if (!(fp = fopen( shared->modes_file, \"r\" )))\n          return;\n\n     while (fgets( line, 79, fp )) {\n          if (sscanf( line, \"mode \\\"%31[^\\\"]\\\"\", label ) == 1) {\n               memset( &temp_mode, 0, sizeof(VideoMode) );\n\n               geometry = 0;\n               timings = 0;\n\n               while (fgets( line, 79, fp ) && !(strstr( line, \"endmode\" ))) {\n                    if (5 == sscanf( line, \" geometry %d %d %d %d %d\",\n                                     &temp_mode.xres, &temp_mode.yres, &dummy, &dummy, &temp_mode.bpp )) {\n                         geometry = 1;\n                    }\n                    else if (7 == sscanf( line, \" timings %d %d %d %d %d %d %d\",\n                                          &temp_mode.pixclock,\n                                          &temp_mode.left_margin, &temp_mode.right_margin,\n                                          &temp_mode.upper_margin, &temp_mode.lower_margin,\n                                          &temp_mode.hsync_len, &temp_mode.vsync_len )) {\n                         timings = 1;\n                    }\n                    else if (1 == sscanf( line, \" hsync %15s\", value ) && 0 == strcasecmp( value, \"high\" )) {\n                         temp_mode.hsync_high = 1;\n                    }\n                    else if (1 == sscanf( line, \" vsync %15s\", value ) && 0 == strcasecmp( value, \"high\" )) {\n                         temp_mode.vsync_high = 1;\n                    }\n                    else if (1 == sscanf( line, \" csync %15s\", value ) && 0 == strcasecmp( value, \"high\" )) {\n                         temp_mode.csync_high = 1;\n                    }\n                    else if (1 == sscanf( line, \" laced %15s\", value ) && 0 == strcasecmp( value, \"true\" )) {\n                         temp_mode.laced = 1;\n                    }\n                    else if (1 == sscanf( line, \" double %15s\", value) && 0 == strcasecmp( value, \"true\" )) {\n                         temp_mode.doubled = 1;\n                    }\n                    else if (1 == sscanf( line, \" gsync %15s\", value ) && 0 == strcasecmp( value, \"true\" )) {\n                         temp_mode.sync_on_green = 1;\n                    }\n                    else if (1 == sscanf( line, \" extsync %15s\", value ) && 0 == strcasecmp( value, \"true\" )) {\n                         temp_mode.external_sync = 1;\n                    }\n                    else if (1 == sscanf( line, \" bcast %15s\", value ) && 0 == strcasecmp( value, \"true\" )) {\n                         temp_mode.broadcast = 1;\n                    }\n               }\n\n               if (geometry && timings && !test_mode_simple( fbdev, &temp_mode )) {\n                    VideoMode *mode = SHCALLOC( shared->shmpool, 1, sizeof(VideoMode) );\n                    if (!mode) {\n                         D_OOSHM();\n                         continue;\n                    }\n\n                    if (!prev_mode)\n                         shared->modes = mode;\n                    else\n                         prev_mode->next = mode;\n\n                    direct_memcpy( mode, &temp_mode, sizeof(VideoMode) );\n\n                    prev_mode = mode;\n\n                    D_DEBUG_AT( FBDev_Mode, \"  -> %16s %4dx%4d  %s%s\\n\", label, temp_mode.xres, temp_mode.yres,\n                                temp_mode.laced ? \"interlaced \" : \"\", temp_mode.doubled ? \"doublescan\" : \"\" );\n               }\n          }\n     }\n\n     fclose( fp );\n}\n\nstatic unsigned short\ncalc_gamma( int n,\n            int max )\n{\n     int res = 65535 * n / max;\n\n     return CLAMP( res, 0, 65535 );\n}\n\nstatic void\nset_rgb332_gamma_ramp( FBDevData *fbdev )\n{\n     FBDevDataShared *shared;\n     struct fb_cmap  *cmap;\n     int              i;\n     int              red_val;\n     int              green_val;\n     int              blue_val;\n\n     D_DEBUG_AT( FBDev_Mode, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     cmap = &shared->current_cmap;\n\n     i = 0;\n     cmap->len = 256;\n\n     for (red_val = 0; red_val < 8 ; red_val++) {\n          for (green_val = 0; green_val < 8 ; green_val++) {\n               for (blue_val = 0; blue_val < 4 ; blue_val++) {\n                    cmap->red[i]    = calc_gamma( red_val, 7 );\n                    cmap->green[i]  = calc_gamma( green_val, 7 );\n                    cmap->blue[i]   = calc_gamma( blue_val, 3 );\n                    cmap->transp[i] = (i ? 0x2000 : 0xffff);\n                    i++;\n               }\n          }\n     }\n\n     fbdev_ioctl( fbdev, FBIOPUTCMAP, cmap, sizeof(*cmap) );\n}\n\nstatic void\nset_gamma_ramp( FBDevData             *fbdev,\n                DFBSurfacePixelFormat  format )\n{\n     FBDevDataShared *shared;\n     struct fb_cmap  *cmap;\n     int              i;\n     int              red_size   = 0;\n     int              green_size = 0;\n     int              blue_size  = 0;\n     int              red_max    = 0;\n     int              green_max  = 0;\n     int              blue_max   = 0;\n\n     D_DEBUG_AT( FBDev_Mode, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     cmap = &shared->current_cmap;\n\n     switch (format) {\n          case DSPF_ARGB1555:\n          case DSPF_RGBA5551:\n          case DSPF_RGB555:\n          case DSPF_BGR555:\n               red_size   = 32;\n               green_size = 32;\n               blue_size  = 32;\n               break;\n          case DSPF_ARGB4444:\n          case DSPF_RGBA4444:\n          case DSPF_RGB444:\n               red_size   = 16;\n               green_size = 16;\n               blue_size  = 16;\n               break;\n          case DSPF_RGB16:\n          case DSPF_ARGB8565:\n               red_size   = 32;\n               green_size = 64;\n               blue_size  = 32;\n               break;\n          case DSPF_RGB24:\n          case DSPF_RGB32:\n          case DSPF_ARGB:\n          case DSPF_ABGR:\n          case DSPF_RGBAF88871:\n               red_size   = 256;\n               green_size = 256;\n               blue_size  = 256;\n               break;\n          default:\n               return;\n     }\n\n     /* The gamma ramp must be set differently if in DirectColor. */\n     if (fbdev->fix->visual == FB_VISUAL_DIRECTCOLOR) {\n          red_max   = 65536 / (256 / red_size);\n          green_max = 65536 / (256 / green_size);\n          blue_max  = 65536 / (256 / blue_size);\n     }\n     else {\n          red_max   = red_size;\n          green_max = green_size;\n          blue_max  = blue_size;\n     }\n\n     /* Assume green to have most weight. */\n     cmap->len = green_size;\n\n     for (i = 0; i < red_size; i++)\n          cmap->red[i] = calc_gamma( i, red_max );\n\n     for (i = 0; i < green_size; i++)\n          cmap->green[i] = calc_gamma( i, green_max );\n\n     for (i = 0; i < blue_size; i++)\n          cmap->blue[i] = calc_gamma( i, blue_max );\n\n     /* Some drivers use the upper byte, some use the lower. */\n     if (fbdev->fix->visual == FB_VISUAL_DIRECTCOLOR) {\n          for (i = 0; i < red_size; i++)\n               cmap->red[i] |= cmap->red[i] << 8;\n\n          for (i = 0; i < green_size; i++)\n               cmap->green[i] |= cmap->green[i] << 8;\n\n          for (i = 0; i < blue_size; i++)\n               cmap->blue[i] |= cmap->blue[i] << 8;\n     }\n\n     fbdev_ioctl( fbdev, FBIOPUTCMAP, cmap, sizeof(*cmap) );\n}\n\n/**********************************************************************************************************************/\n\nDFBResult\nfbdev_init_modes( FBDevData *fbdev )\n{\n     FBDevDataShared *shared;\n\n     D_DEBUG_AT( FBDev_Mode, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     read_modes( fbdev );\n\n     if (!shared->modes) {\n          /* Try to use current mode. */\n          shared->modes = SHCALLOC( shared->shmpool, 1, sizeof(VideoMode) );\n          if (!shared->modes)\n               return D_OOSHM();\n\n          *shared->modes = shared->mode;\n\n          if (test_mode_simple( fbdev, shared->modes )) {\n               D_ERROR( \"FBDev/Layer: No supported modes found and current mode not supported!\\n\"\n                        \"  -> RGBA %u/%u, %u/%u, %u/%u, %u/%u (%u bits)\\n\",\n                        shared->orig_var.red.length,    shared->orig_var.red.offset,\n                        shared->orig_var.green.length,  shared->orig_var.green.offset,\n                        shared->orig_var.blue.length,   shared->orig_var.blue.offset,\n                        shared->orig_var.transp.length, shared->orig_var.transp.offset,\n                        shared->orig_var.bits_per_pixel );\n\n               return DFB_INIT;\n          }\n     }\n\n     return DFB_OK;\n}\n\nVideoMode *\nfbdev_find_mode( FBDevData *fbdev,\n                 int        width,\n                 int        height )\n{\n     FBDevDataShared *shared;\n     VideoMode       *mode;\n\n     D_DEBUG_AT( FBDev_Mode, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     mode = shared->modes;\n\n     while (mode) {\n          if (mode->xres == width && mode->yres == height)\n               break;\n\n          mode = mode->next;\n     }\n\n     if (!mode)\n          D_ONCE( \"no mode found for %dx%d\", width, height );\n\n     return mode;\n}\n\nvoid\nfbdev_var_to_mode( const struct fb_var_screeninfo *var,\n                   VideoMode                      *mode )\n{\n     D_DEBUG_AT( FBDev_Mode, \"%s()\\n\", __FUNCTION__ );\n\n     mode->xres          = var->xres;\n     mode->yres          = var->yres;\n     mode->bpp           = var->bits_per_pixel;\n     mode->pixclock      = var->pixclock;\n     mode->left_margin   = var->left_margin;\n     mode->right_margin  = var->right_margin;\n     mode->upper_margin  = var->upper_margin;\n     mode->lower_margin  = var->lower_margin;\n     mode->hsync_len     = var->hsync_len;\n     mode->vsync_len     = var->vsync_len;\n     mode->hsync_high    = (var->sync  & FB_SYNC_HOR_HIGH_ACT)  ? 1 : 0;\n     mode->vsync_high    = (var->sync  & FB_SYNC_VERT_HIGH_ACT) ? 1 : 0;\n     mode->csync_high    = (var->sync  & FB_SYNC_COMP_HIGH_ACT) ? 1 : 0;\n     mode->laced         = (var->vmode & FB_VMODE_INTERLACED)   ? 1 : 0;\n     mode->doubled       = (var->vmode & FB_VMODE_DOUBLE)       ? 1 : 0;\n     mode->sync_on_green = (var->sync  & FB_SYNC_ON_GREEN)      ? 1 : 0;\n     mode->external_sync = (var->sync  & FB_SYNC_EXT)           ? 1 : 0;\n     mode->broadcast     = (var->sync  & FB_SYNC_BROADCAST)     ? 1 : 0;\n}\n\nDFBResult\nfbdev_test_mode( FBDevData                   *fbdev,\n                 const VideoMode             *mode,\n                 const CoreLayerRegionConfig *config )\n{\n     DFBResult                 ret;\n     FBDevDataShared          *shared;\n     const DFBRectangle       *source;\n     struct fb_var_screeninfo  var;\n     unsigned int              need_mem;\n\n     D_DEBUG_AT( FBDev_Mode, \"%s( %p, %p )\\n\", __FUNCTION__, mode, config );\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     source = &config->source;\n\n     /* Panning support. */\n     if (source->w != mode->xres && fbdev->fix->xpanstep == 0)\n          return DFB_UNSUPPORTED;\n     if (source->h != mode->yres && fbdev->fix->ypanstep == 0 && fbdev->fix->ywrapstep == 0)\n          return DFB_UNSUPPORTED;\n\n     var = shared->current_var;\n     ret = mode_to_var( mode, config->format, config->width, config->height,\n                        fbdev->fix->xpanstep, fbdev->fix->ypanstep, fbdev->fix->ywrapstep, 0, 0, config->buffermode,\n                        &var );\n     if (ret)\n          return ret;\n\n     need_mem = DFB_BYTES_PER_LINE( config->format, var.xres_virtual ) *\n                DFB_PLANE_MULTIPLY( config->format, var.yres_virtual );\n     if (fbdev->fix->smem_len < need_mem) {\n          D_DEBUG_AT( FBDev_Mode, \"  -> not enough framebuffer memory (%u < %u)\\n\", fbdev->fix->smem_len, need_mem );\n\n          return DFB_LIMITEXCEEDED;\n     }\n\n     /* Enable test mode. */\n     var.activate = FB_ACTIVATE_TEST;\n\n     dfb_gfxcard_lock( GDLF_WAIT | GDLF_SYNC | GDLF_RESET | GDLF_INVALIDATE );\n\n     if (fbdev_ioctl( fbdev, FBIOPUT_VSCREENINFO, &var, sizeof(var) ) < 0) {\n          ret = errno2result( errno );\n          dfb_gfxcard_unlock();\n          D_DEBUG_AT( FBDev_Mode, \"  -> FBIOPUT_VSCREENINFO failed!\\n\" );\n          return ret;\n     }\n\n     dfb_gfxcard_unlock();\n\n     return DFB_OK;\n}\n\nDFBResult\nfbdev_set_mode( FBDevData         *fbdev,\n                const VideoMode   *mode,\n                const CoreSurface *surface,\n                unsigned int       xoffset,\n                unsigned int       yoffset )\n{\n     DFBResult                  ret;\n     FBDevDataShared           *shared;\n     const CoreSurfaceConfig   *config;\n     int                        num;\n     struct fb_var_screeninfo   var;\n     struct fb_var_screeninfo   var2;\n     DFBDisplayLayerBufferMode  buffermode;\n\n     D_DEBUG_AT( FBDev_Mode, \"%s( %p, %p )\\n\", __FUNCTION__, mode, surface );\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n     D_ASSERT( mode != NULL );\n     D_ASSERT( surface != NULL );\n\n     shared = fbdev->shared;\n\n     config = &surface->config;\n\n     for (num = 0; num < surface->num_buffers; num++) {\n          if (surface->buffers[num]->policy == CSP_SYSTEMONLY)\n               break;\n     }\n\n     switch (num) {\n          case 3:\n               buffermode = DLBM_TRIPLE;\n               break;\n          case 2:\n               buffermode = DLBM_BACKVIDEO;\n               break;\n          case 1:\n               buffermode = DLBM_FRONTONLY;\n               break;\n          default:\n               D_BUG( \"unexpected video buffers number %d\", num );\n               return DFB_BUG;\n     }\n\n     var = shared->current_var;\n     ret = mode_to_var( mode, config->format, config->size.w, config->size.h,\n                        fbdev->fix->xpanstep, fbdev->fix->ypanstep, fbdev->fix->ywrapstep, xoffset, yoffset, buffermode,\n                        &var );\n     if (ret) {\n          D_ERROR( \"FBDev/Mode: Failed to switch to %dx%d (%s) with buffermode %u!\\n\",\n                   config->size.w, config->size.h, dfb_pixelformat_name( config->format ), buffermode );\n          return ret;\n     }\n\n     dfb_gfxcard_lock( GDLF_WAIT | GDLF_SYNC | GDLF_RESET | GDLF_INVALIDATE );\n\n     if (fbdev_ioctl( fbdev, FBIOPUT_VSCREENINFO, &var, sizeof(var) )) {\n          ret = errno2result( errno );\n          D_DEBUG_AT( FBDev_Mode, \"  -> FBIOPUT_VSCREENINFO failed!\\n\" );\n          goto error;\n     }\n\n     if (fbdev_ioctl( fbdev, FBIOGET_VSCREENINFO, &var2, sizeof(var2) )) {\n          ret = errno2result( errno );\n          D_DEBUG_AT( FBDev_Mode, \"  -> FBIOGET_VSCREENINFO failed!\\n\" );\n          goto error;\n     }\n\n     if (var.xres != var2.xres || var.xres_virtual != var2.xres_virtual ||\n         var.yres != var2.yres || var.yres_virtual != var2.yres_virtual) {\n          D_DEBUG_AT( FBDev_Mode, \"  -> Variable screen information mismatch (%ux%u [%ux%u] should be %ux%u [%ux%u])\\n\",\n                      var2.xres, var2.yres, var2.xres_virtual, var2.yres_virtual,\n                      var.xres, var.yres, var.xres_virtual, var.yres_virtual );\n          ret = DFB_IO;\n          goto error;\n     }\n\n     shared->current_var = var;\n     fbdev_var_to_mode( &var, &shared->mode );\n     fbdev_ioctl( fbdev, FBIOGET_FSCREENINFO, fbdev->fix, sizeof(*fbdev->fix) );\n\n     D_INFO( \"FBDev/Mode: Switched to %ux%u (virtual %ux%u) at %u bits (%s), pitch %u\\n\",\n             var.xres, var.yres, var.xres_virtual, var.yres_virtual, var.bits_per_pixel,\n             dfb_pixelformat_name( config->format ), fbdev->fix->line_length );\n\n     /* Some drivers use the palette as gamma ramp, so the gamme ramp has to be initialized to have correct colors. */\n     if (config->format == DSPF_RGB332)\n          set_rgb332_gamma_ramp( fbdev );\n     else\n          set_gamma_ramp( fbdev, config->format );\n\n     /* Invalidate original pan offset. */\n     shared->orig_var.xoffset = 0;\n     shared->orig_var.yoffset = 0;\n\n     surfacemanager_adjust_heap_offset( shared->manager, var.yres_virtual * fbdev->fix->line_length );\n\n     dfb_gfxcard_after_set_var();\n\n     dfb_gfxcard_unlock();\n\n     return DFB_OK;\n\nerror:\n     dfb_gfxcard_unlock();\n\n     D_ERROR( \"FBDev/Mode: Failed to switch to %ux%u (virtual %ux%u) at %u bits (%s)!\\n\",\n              var.xres, var.yres, var.xres_virtual, var.yres_virtual, var.bits_per_pixel,\n              dfb_pixelformat_name( config->format ) );\n\n     return ret;\n}\n"
  },
  {
    "path": "systems/fbdev/fbdev_mode.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FBDEV_MODE_H__\n#define __FBDEV_MODE_H__\n\n#include <core/layer_region.h>\n\n#include \"fbdev_system.h\"\n\n/**********************************************************************************************************************/\n\nDFBResult        fbdev_init_modes ( FBDevData                      *fbdev );\n\nVideoMode       *fbdev_find_mode  ( FBDevData                      *fbdev,\n                                    int                             width,\n                                    int                             height );\n\nvoid             fbdev_var_to_mode( const struct fb_var_screeninfo *var,\n                                    VideoMode                      *mode );\n\nDFBResult        fbdev_test_mode  ( FBDevData                      *fbdev,\n                                    const VideoMode                *mode,\n                                    const CoreLayerRegionConfig    *config );\n\nDFBResult        fbdev_set_mode   ( FBDevData                      *fbdev,\n                                    const VideoMode                *mode,\n                                    const CoreSurface              *surface,\n                                    unsigned int                    xoffset,\n                                    unsigned int                    yoffset );\n\n#endif\n"
  },
  {
    "path": "systems/fbdev/fbdev_screen.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/screens.h>\n#include <misc/conf.h>\n\n#include \"fbdev_mode.h\"\n\nD_DEBUG_DOMAIN( FBDev_Screen, \"FBDev/Screen\", \"FBDev Screen\" );\n\n/**********************************************************************************************************************/\n\nstatic DFBResult\nfbdevInitScreen( CoreScreen           *screen,\n                 void                 *driver_data,\n                 void                 *screen_data,\n                 DFBScreenDescription *description )\n{\n     FBDevData       *fbdev = driver_data;\n     FBDevDataShared *shared;\n     VideoMode       *mode;\n     int              count = 0;\n\n     D_DEBUG_AT( FBDev_Screen, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     mode = shared->modes;\n\n     /* Set capabilities. */\n     description->caps = DSCCAPS_VSYNC | DSCCAPS_POWER_MANAGEMENT;\n\n     /* Set name. */\n     snprintf( description->name, DFB_SCREEN_DESC_NAME_LENGTH, \"FBDev Screen\" );\n\n     while (mode) {\n          count++;\n          mode = mode->next;\n     }\n\n     if (dfb_config->mode.width && dfb_config->mode.height) {\n          mode = fbdev_find_mode( fbdev, dfb_config->mode.width, dfb_config->mode.height );\n          if (mode)\n               shared->mode = *mode;\n     }\n\n     D_INFO( \"FBDev/Screen: Default mode is %dx%d (%d modes in total)\\n\",\n             shared->mode.xres, shared->mode.yres, count );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nfbdevSetPowerMode( CoreScreen         *screen,\n                   void               *driver_data,\n                   void               *screen_data,\n                   DFBScreenPowerMode  mode )\n{\n     FBDevData *fbdev = driver_data;\n     int        level;\n\n     D_DEBUG_AT( FBDev_Screen, \"%s()\\n\", __FUNCTION__ );\n\n     switch (mode) {\n          case DSPM_OFF:\n               level = 4;\n               break;\n          case DSPM_SUSPEND:\n               level = 3;\n               break;\n          case DSPM_STANDBY:\n               level = 2;\n               break;\n          case DSPM_ON:\n               level = 0;\n               break;\n          default:\n               return DFB_INVARG;\n     }\n\n     return fbdev_ioctl( fbdev, FBIOBLANK, (void*)(long) level, sizeof(void*) );\n}\n\nstatic inline void\nwaitretrace( void )\n{\n#if defined(__i386__) || defined(__x86_64__)\n     if (iopl( 3 ))\n          return;\n\n     if (!(inb( 0x3cc ) & 1)) {\n          while (  inb( 0x3ba ) & 0x8);\n          while (!(inb( 0x3ba ) & 0x8)) ;\n     }\n     else {\n          while (  inb( 0x3da ) & 0x8);\n          while (!(inb( 0x3da ) & 0x8));\n     }\n#endif\n}\n\nstatic DFBResult\nfbdevWaitVSync( CoreScreen *screen,\n                void       *driver_data,\n                void       *screen_data )\n{\n     static unsigned int  zero  = 0;\n     FBDevData           *fbdev = driver_data;\n     FBDevDataShared     *shared;\n\n     D_DEBUG_AT( FBDev_Screen, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     if (shared->pollvsync_none)\n          return DFB_OK;\n\n     if (fbdev_ioctl( fbdev, FBIO_WAITFORVSYNC, &zero, sizeof(zero) ))\n          waitretrace();\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nfbdevGetScreenSize( CoreScreen *screen,\n                    void       *driver_data,\n                    void       *screen_data,\n                    int        *ret_width,\n                    int        *ret_height )\n{\n     FBDevData       *fbdev = driver_data;\n     FBDevDataShared *shared;\n\n     D_DEBUG_AT( FBDev_Screen, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     *ret_width  = shared->mode.xres;\n     *ret_height = shared->mode.yres;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nfbdevGetVSyncCount( CoreScreen    *screen,\n                    void          *driver_data,\n                    void          *screen_data,\n                    unsigned long *ret_count )\n{\n     FBDevData        *fbdev = driver_data;\n     struct fb_vblank  vblank;\n\n     D_DEBUG_AT( FBDev_Screen, \"%s()\\n\", __FUNCTION__ );\n\n     if (!ret_count)\n          return DFB_INVARG;\n\n     if (fbdev_ioctl( fbdev, FBIOGET_VBLANK, &vblank, sizeof(vblank) ))\n          return errno2result( errno );\n\n     if (!D_FLAGS_IS_SET( vblank.flags, FB_VBLANK_HAVE_COUNT ))\n          return DFB_UNSUPPORTED;\n\n     *ret_count = vblank.count;\n\n     return DFB_OK;\n}\n\nconst ScreenFuncs fbdevScreenFuncs = {\n     .InitScreen    = fbdevInitScreen,\n     .SetPowerMode  = fbdevSetPowerMode,\n     .WaitVSync     = fbdevWaitVSync,\n     .GetScreenSize = fbdevGetScreenSize,\n     .GetVSyncCount = fbdevGetVSyncCount\n};\n"
  },
  {
    "path": "systems/fbdev/fbdev_surface_pool.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/surface_allocation.h>\n#include <core/surface_buffer.h>\n#include <core/surface_pool.h>\n\n#include \"fbdev_system.h\"\n\nD_DEBUG_DOMAIN( FBDev_Surfaces, \"FBDev/Surfaces\", \"FBDev Surface Pool\" );\nD_DEBUG_DOMAIN( FBDev_SurfLock, \"FBDev/SurfLock\", \"FBDev Surface Pool Locks\" );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int             magic;\n\n     SurfaceManager *manager;\n} FBDevPoolData;\n\ntypedef struct {\n     int        magic;\n\n     FBDevData *fbdev;\n\n     CoreDFB   *core;\n} FBDevPoolLocalData;\n\ntypedef struct {\n     int    magic;\n\n     Chunk *chunk;\n} FBDevAllocationData;\n\n/**********************************************************************************************************************/\n\nstatic int\nfbdevPoolDataSize( void )\n{\n     return sizeof(FBDevPoolData);\n}\n\nstatic int\nfbdevPoolLocalDataSize( void )\n{\n     return sizeof(FBDevPoolLocalData);\n}\n\nstatic int\nfbdevAllocationDataSize( void )\n{\n     return sizeof(FBDevAllocationData);\n}\n\nstatic DFBResult\nfbdevInitPool( CoreDFB                    *core,\n               CoreSurfacePool            *pool,\n               void                       *pool_data,\n               void                       *pool_local,\n               void                       *system_data,\n               CoreSurfacePoolDescription *ret_desc )\n{\n     DFBResult           ret;\n     FBDevPoolData      *data  = pool_data;\n     FBDevPoolLocalData *local = pool_local;\n     FBDevData          *fbdev = system_data;\n\n     D_DEBUG_AT( FBDev_Surfaces, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( core != NULL );\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_ASSERT( data != NULL );\n     D_ASSERT( local != NULL );\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n     D_ASSERT( ret_desc != NULL );\n\n     ret_desc->caps              = CSPCAPS_PHYSICAL | CSPCAPS_VIRTUAL;\n     ret_desc->access[CSAID_CPU] = CSAF_READ | CSAF_WRITE | CSAF_SHARED;\n     ret_desc->access[CSAID_GPU] = CSAF_READ | CSAF_WRITE | CSAF_SHARED;\n     ret_desc->types             = CSTF_LAYER | CSTF_WINDOW | CSTF_CURSOR | CSTF_FONT | CSTF_SHARED | CSTF_EXTERNAL;\n     ret_desc->priority          = CSPP_DEFAULT;\n\n     /* For hardware layers. */\n     ret_desc->access[CSAID_LAYER0]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER1]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER2]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER3]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER4]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER5]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER6]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER7]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER8]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER9]  = CSAF_READ;\n     ret_desc->access[CSAID_LAYER10] = CSAF_READ;\n     ret_desc->access[CSAID_LAYER11] = CSAF_READ;\n     ret_desc->access[CSAID_LAYER12] = CSAF_READ;\n     ret_desc->access[CSAID_LAYER13] = CSAF_READ;\n     ret_desc->access[CSAID_LAYER14] = CSAF_READ;\n     ret_desc->access[CSAID_LAYER15] = CSAF_READ;\n\n     snprintf( ret_desc->name, DFB_SURFACE_POOL_DESC_NAME_LENGTH, \"FBDev Surface Pool\" );\n\n     ret = surfacemanager_create( core, fbdev->fix->smem_len, &data->manager );\n     if (ret)\n          return ret;\n\n     fbdev->shared->manager = data->manager;\n\n     local->fbdev = fbdev;\n     local->core  = core;\n\n     D_MAGIC_SET( data, FBDevPoolData );\n     D_MAGIC_SET( local, FBDevPoolLocalData );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nfbdevJoinPool( CoreDFB         *core,\n               CoreSurfacePool *pool,\n               void            *pool_data,\n               void            *pool_local,\n               void            *system_data )\n{\n     FBDevPoolData      *data  = pool_data;\n     FBDevPoolLocalData *local = pool_local;\n     FBDevData          *fbdev = system_data;\n\n     D_UNUSED_P( data );\n\n     D_DEBUG_AT( FBDev_Surfaces, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( core != NULL );\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( data, FBDevPoolData );\n     D_ASSERT( local != NULL );\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     local->fbdev = fbdev;\n     local->core  = core;\n\n     D_MAGIC_SET( local, FBDevPoolLocalData );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nfbdevDestroyPool( CoreSurfacePool *pool,\n                  void            *pool_data,\n                  void            *pool_local )\n{\n     FBDevPoolData      *data  = pool_data;\n     FBDevPoolLocalData *local = pool_local;\n\n     D_UNUSED_P( local );\n\n     D_DEBUG_AT( FBDev_Surfaces, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( data, FBDevPoolData );\n     D_MAGIC_ASSERT( local, FBDevPoolLocalData );\n\n     surfacemanager_destroy( data->manager );\n\n     D_MAGIC_CLEAR( data );\n     D_MAGIC_CLEAR( local );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nfbdevLeavePool( CoreSurfacePool *pool,\n                void            *pool_data,\n                void            *pool_local )\n{\n     FBDevPoolData      *data  = pool_data;\n     FBDevPoolLocalData *local = pool_local;\n\n     D_UNUSED_P( data );\n     D_UNUSED_P( local );\n\n     D_DEBUG_AT( FBDev_Surfaces, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( data, FBDevPoolData );\n     D_MAGIC_ASSERT( local, FBDevPoolLocalData );\n\n     D_MAGIC_CLEAR( local );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nfbdevTestConfig( CoreSurfacePool         *pool,\n                 void                    *pool_data,\n                 void                    *pool_local,\n                 CoreSurfaceBuffer       *buffer,\n                 const CoreSurfaceConfig *config )\n{\n     DFBResult           ret;\n     CoreSurface        *surface;\n     FBDevPoolData      *data  = pool_data;\n     FBDevPoolLocalData *local = pool_local;\n\n     D_DEBUG_AT( FBDev_Surfaces, \"%s( %p )\\n\", __FUNCTION__, buffer );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( data, FBDevPoolData );\n     D_MAGIC_ASSERT( local, FBDevPoolLocalData );\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n\n     surface = buffer->surface;\n\n     if ((surface->type & CSTF_LAYER) && surface->resource_id == DLID_PRIMARY)\n          return DFB_OK;\n\n     ret = surfacemanager_allocate( local->core, data->manager, buffer, NULL, NULL );\n\n     return ret;\n}\n\nstatic DFBResult\nfbdevAllocateBuffer( CoreSurfacePool       *pool,\n                     void                  *pool_data,\n                     void                  *pool_local,\n                     CoreSurfaceBuffer     *buffer,\n                     CoreSurfaceAllocation *allocation,\n                     void                  *alloc_data )\n{\n     DFBResult            ret;\n     CoreSurface         *surface;\n     FBDevPoolData       *data  = pool_data;\n     FBDevPoolLocalData  *local = pool_local;\n     FBDevAllocationData *alloc = alloc_data;\n\n     D_DEBUG_AT( FBDev_Surfaces, \"%s( %p )\\n\", __FUNCTION__, buffer );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( data, FBDevPoolData );\n     D_MAGIC_ASSERT( local, FBDevPoolLocalData );\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n\n     surface = buffer->surface;\n\n     if (surface->type & CSTF_LAYER && surface->resource_id == DLID_PRIMARY) {\n          D_DEBUG_AT( FBDev_Surfaces, \"  -> primary layer buffer (index %d)\\n\", dfb_surface_buffer_index( buffer ) );\n\n          dfb_surface_calc_buffer_size( surface, 8, 1, NULL, &allocation->size );\n     }\n     else {\n          ret = surfacemanager_allocate( local->core, data->manager, buffer, allocation, &alloc->chunk );\n          if (ret)\n               return ret;\n\n          allocation->size   = surfacemanager_chunk_length( alloc->chunk );\n          allocation->offset = surfacemanager_chunk_offset( alloc->chunk );\n     }\n\n     D_MAGIC_SET( alloc, FBDevAllocationData );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nfbdevDeallocateBuffer( CoreSurfacePool       *pool,\n                       void                  *pool_data,\n                       void                  *pool_local,\n                       CoreSurfaceBuffer     *buffer,\n                       CoreSurfaceAllocation *allocation,\n                       void                  *alloc_data )\n{\n     FBDevPoolData       *data  = pool_data;\n     FBDevPoolLocalData  *local = pool_local;\n     FBDevAllocationData *alloc = alloc_data;\n\n     D_UNUSED_P( local );\n\n     D_DEBUG_AT( FBDev_Surfaces, \"%s( %p )\\n\", __FUNCTION__, buffer );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( data, FBDevPoolData );\n     D_MAGIC_ASSERT( local, FBDevPoolLocalData );\n     D_MAGIC_ASSERT( alloc, FBDevAllocationData );\n\n     if (alloc->chunk)\n          surfacemanager_deallocate( data->manager, alloc->chunk );\n\n     D_MAGIC_CLEAR( alloc );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nfbdevLock( CoreSurfacePool       *pool,\n           void                  *pool_data,\n           void                  *pool_local,\n           CoreSurfaceAllocation *allocation,\n           void                  *alloc_data,\n           CoreSurfaceBufferLock *lock )\n{\n     FBDevPoolLocalData  *local = pool_local;\n     FBDevAllocationData *alloc = alloc_data;\n     FBDevData           *fbdev;\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( local, FBDevPoolLocalData );\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( alloc, FBDevAllocationData );\n     D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );\n\n     D_DEBUG_AT( FBDev_SurfLock, \"%s( %p, %p )\\n\", __FUNCTION__, allocation, lock->buffer );\n\n     fbdev = local->fbdev;\n     D_ASSERT( fbdev != NULL );\n\n     if (allocation->type & CSTF_LAYER && allocation->resource_id == DLID_PRIMARY) {\n          int index = allocation->index;\n\n          D_DEBUG_AT( FBDev_SurfLock, \"  -> primary layer buffer (index %d)\\n\", index );\n\n          lock->pitch  = fbdev->fix->line_length;\n          lock->offset = index * allocation->config.size.h * lock->pitch;\n     }\n     else {\n          lock->pitch  = surfacemanager_chunk_pitch( alloc->chunk );\n          lock->offset = surfacemanager_chunk_offset( alloc->chunk );\n     }\n\n     lock->addr = fbdev->addr            + lock->offset;\n     lock->phys = fbdev->fix->smem_start + lock->offset;\n\n     D_DEBUG_AT( FBDev_SurfLock, \"  -> offset %lu, pitch %u, addr %p, phys 0x%08lx\\n\",\n                 lock->offset, lock->pitch, lock->addr, lock->phys );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nfbdevUnlock( CoreSurfacePool       *pool,\n             void                  *pool_data,\n             void                  *pool_local,\n             CoreSurfaceAllocation *allocation,\n             void                  *alloc_data,\n             CoreSurfaceBufferLock *lock )\n{\n     FBDevAllocationData *alloc = alloc_data;\n\n     D_UNUSED_P( alloc );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( alloc, FBDevAllocationData );\n     D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );\n\n     D_DEBUG_AT( FBDev_SurfLock, \"%s( %p, %p )\\n\", __FUNCTION__, allocation, lock->buffer );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nfbdevMuckOut( CoreSurfacePool   *pool,\n              void              *pool_data,\n              void              *pool_local,\n              CoreSurfaceBuffer *buffer )\n{\n     FBDevPoolData      *data  = pool_data;\n     FBDevPoolLocalData *local = pool_local;\n\n     D_DEBUG_AT( FBDev_Surfaces, \"%s( %p )\\n\", __FUNCTION__, buffer );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( data, FBDevPoolData );\n     D_MAGIC_ASSERT( local, FBDevPoolLocalData );\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n\n     return surfacemanager_displace( local->core, data->manager, buffer );\n}\n\nconst SurfacePoolFuncs fbdevSurfacePoolFuncs = {\n     .PoolDataSize       = fbdevPoolDataSize,\n     .PoolLocalDataSize  = fbdevPoolLocalDataSize,\n     .AllocationDataSize = fbdevAllocationDataSize,\n     .InitPool           = fbdevInitPool,\n     .JoinPool           = fbdevJoinPool,\n     .DestroyPool        = fbdevDestroyPool,\n     .LeavePool          = fbdevLeavePool,\n     .TestConfig         = fbdevTestConfig,\n     .AllocateBuffer     = fbdevAllocateBuffer,\n     .DeallocateBuffer   = fbdevDeallocateBuffer,\n     .Lock               = fbdevLock,\n     .Unlock             = fbdevUnlock,\n     .MuckOut            = fbdevMuckOut\n};\n"
  },
  {
    "path": "systems/fbdev/fbdev_surfacemanager.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core.h>\n#include <core/gfxcard.h>\n#include <core/surface_allocation.h>\n#include <core/surface_buffer.h>\n#include <directfb_util.h>\n#include <fusion/shmalloc.h>\n\n#include \"fbdev_surfacemanager.h\"\n\nD_DEBUG_DOMAIN( SurfMan, \"FBDev/SurfaceManager\", \"FBDev Surface Manager\" );\n\n/**********************************************************************************************************************/\n\nstruct _Chunk {\n     int                    magic;\n\n     int                    offset;      /* offset in memory, greater or equal to the heap offset */\n     int                    length;      /* length of this chunk */\n     int                    pitch;       /* pitch of this chunk */\n\n     CoreSurfaceBuffer     *buffer;      /* pointer to the surface buffer occupying this chunk,\n                                            or NULL if the chunk is free */\n     CoreSurfaceAllocation *allocation;  /* pointer to the surface allocation object */\n\n     int                    tolerations; /* number of times this chunk was scanned occupied */\n\n     Chunk                 *prev;\n     Chunk                 *next;\n};\n\nstruct _SurfaceManager {\n     int                  magic;\n\n     FusionSHMPoolShared *shmpool;\n\n     Chunk               *chunks;\n\n     int                  offset;         /* offset in heap */\n     int                  length;         /* length of the heap */\n     int                  avail;          /* amount of available memory */\n\n     int                  min_toleration;\n};\n\nstatic Chunk *free_chunk  ( SurfaceManager        *manager,\n                            Chunk                 *chunk );\n\nstatic Chunk *occupy_chunk( SurfaceManager        *manager,\n                            Chunk                 *chunk,\n                            CoreSurfaceAllocation *allocation,\n                            int                    length,\n                            int                    pitch );\n\n/**********************************************************************************************************************/\n\nDFBResult\nsurfacemanager_create( CoreDFB         *core,\n                       unsigned int     length,\n                       SurfaceManager **ret_manager )\n{\n     DFBResult            ret;\n     FusionSHMPoolShared *pool;\n     SurfaceManager      *manager;\n     Chunk               *chunk;\n\n     D_DEBUG_AT( SurfMan, \"%s( %p, %u )\\n\", __FUNCTION__, core, length );\n\n     D_ASSERT( core != NULL );\n     D_ASSERT( ret_manager != NULL );\n\n     pool = dfb_core_shmpool( core );\n\n     manager = SHCALLOC( pool, 1, sizeof(SurfaceManager) );\n     if (!manager)\n          return D_OOSHM();\n\n     /* Initially there is one big free chunk, chunks are splitted into a free and an occupied chunk if memory is\n        allocated, two chunks are merged to one free chunk if memory is deallocated. */\n\n     chunk = SHCALLOC( pool, 1, sizeof(Chunk) );\n     if (!chunk) {\n          ret = D_OOSHM();\n          SHFREE( pool, manager );\n          return ret;\n     }\n\n     chunk->length = length;\n\n     D_MAGIC_SET( chunk, Chunk );\n\n     manager->shmpool = pool;\n     manager->chunks  = chunk;\n     manager->length  = length;\n     manager->avail   = manager->length;\n\n     D_MAGIC_SET( manager, SurfaceManager );\n\n     D_DEBUG_AT( SurfMan, \"  -> %p\\n\", manager );\n\n     *ret_manager = manager;\n\n     return DFB_OK;\n}\n\nvoid\nsurfacemanager_destroy( SurfaceManager *manager )\n{\n     Chunk *chunk;\n     void  *next;\n\n     D_DEBUG_AT( SurfMan, \"%s( %p )\\n\", __FUNCTION__, manager );\n\n     D_MAGIC_ASSERT( manager, SurfaceManager );\n\n     /* Deallocate all chunks. */\n     chunk = manager->chunks;\n     while (chunk) {\n          next = chunk->next;\n\n          D_MAGIC_CLEAR( chunk );\n\n          SHFREE( manager->shmpool, chunk );\n\n          chunk = next;\n     }\n\n     D_MAGIC_CLEAR( manager );\n\n     /* Deallocate manager. */\n     SHFREE( manager->shmpool, manager );\n}\n\nvoid\nsurfacemanager_adjust_heap_offset( SurfaceManager *manager,\n                                   int             offset )\n{\n     D_DEBUG_AT( SurfMan, \"%s( %p, %d )\\n\", __FUNCTION__, manager, offset );\n\n     D_MAGIC_ASSERT( manager, SurfaceManager );\n     D_ASSERT( offset >= 0 );\n\n     /* Adjust the offset of the heap. */\n     if (manager->chunks->buffer == NULL) {\n          /* First chunk is free. */\n          if (offset <= manager->chunks->offset + manager->chunks->length) {\n               /* Recalculate offset and length. */\n               manager->chunks->length = manager->chunks->offset + manager->chunks->length - offset;\n               manager->chunks->offset = offset;\n          }\n          else {\n               D_WARN( \"unable to adjust heap offset\" );\n          }\n     }\n     else {\n          D_WARN( \"unable to adjust heap offset\" );\n     }\n\n     manager->avail  -= offset - manager->offset;\n     manager->offset  = offset;\n}\n\nDFBResult\nsurfacemanager_allocate( CoreDFB                *core,\n                         SurfaceManager         *manager,\n                         CoreSurfaceBuffer      *buffer,\n                         CoreSurfaceAllocation  *allocation,\n                         Chunk                 **ret_chunk )\n{\n     int    pitch;\n     int    length;\n     Chunk *chunk;\n     Chunk *best_free = NULL;\n\n     D_MAGIC_ASSERT( manager, SurfaceManager );\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n\n     D_DEBUG_AT( SurfMan, \"%s( %p ) <- %dx%d %s\\n\", __FUNCTION__, buffer,\n                 buffer->surface->config.size.w, buffer->surface->config.size.h,\n                 dfb_pixelformat_name( buffer->surface->config.format ) );\n\n     if (ret_chunk)\n          D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     else\n          D_ASSUME( allocation == NULL );\n\n     dfb_gfxcard_calc_buffer_size( buffer, &pitch, &length );\n\n     D_DEBUG_AT( SurfMan, \"  -> pitch %d, length %d, available %d\\n\", pitch, length, manager->avail );\n\n     if (manager->avail < length)\n          return DFB_TEMPUNAVAIL;\n\n     /* Examine chunks. */\n     chunk = manager->chunks;\n     D_MAGIC_ASSERT( chunk, Chunk );\n\n     if (!chunk->next) {\n          int memory_length = dfb_gfxcard_memory_length();\n\n          if (chunk->length != memory_length - manager->offset) {\n               D_WARN( \"workaround creation happening before graphics driver initialization\" );\n\n               manager->length = memory_length;\n               manager->avail  = memory_length - manager->offset;\n\n               chunk->length = manager->avail;\n          }\n     }\n\n     while (chunk) {\n          D_MAGIC_ASSERT( chunk, Chunk );\n\n          if (!chunk->buffer && chunk->length >= length) {\n               /* NULL means check only. */\n               if (!ret_chunk)\n                    return DFB_OK;\n\n               if (!best_free || best_free->length > chunk->length)\n                    best_free = chunk;\n\n               if (chunk->length == length)\n                    break;\n          }\n\n          chunk = chunk->next;\n     }\n\n     if (best_free) {\n          D_DEBUG_AT( SurfMan, \"  -> found free (%d)\\n\", best_free->length );\n\n          /* NULL means check only. */\n          if (ret_chunk)\n               *ret_chunk = occupy_chunk( manager, best_free, allocation, length, pitch );\n\n          return DFB_OK;\n     }\n\n     D_DEBUG_AT( SurfMan, \"  -> failed (%d/%d)\\n\", manager->avail, manager->length );\n\n     return DFB_NOVIDEOMEMORY;\n}\n\nint\nsurfacemanager_chunk_offset( Chunk *chunk )\n{\n     return chunk->offset;\n}\n\nint\nsurfacemanager_chunk_length( Chunk *chunk )\n{\n     return chunk->length;\n}\n\nint\nsurfacemanager_chunk_pitch( Chunk *chunk )\n{\n     return chunk->pitch;\n}\n\nDFBResult\nsurfacemanager_displace( CoreDFB           *core,\n                         SurfaceManager    *manager,\n                         CoreSurfaceBuffer *buffer )\n{\n     int                    length;\n     int                    min_toleration;\n     Chunk                 *chunk;\n     CoreSurfaceAllocation *smallest    = NULL;\n     Chunk                 *multi_start = NULL;\n     int                    multi_tsize = 0;\n     int                    multi_size  = 0;\n     int                    multi_count = 0;\n     Chunk                 *bestm_start = NULL;\n     int                    bestm_count = 0;\n     int                    bestm_size  = 0;\n\n     D_MAGIC_ASSERT( manager, SurfaceManager );\n     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( buffer->surface, CoreSurface );\n\n     D_DEBUG_AT( SurfMan, \"%s( %p ) <- %dx%d %s\\n\", __FUNCTION__, buffer,\n                 buffer->surface->config.size.w, buffer->surface->config.size.h,\n                 dfb_pixelformat_name( buffer->surface->config.format ) );\n\n     dfb_gfxcard_calc_buffer_size( buffer, NULL, &length );\n\n     min_toleration = manager->min_toleration / 8 + 2;\n\n     D_DEBUG_AT( SurfMan, \"  -> %7d required, min toleration %d\\n\", length, min_toleration );\n\n     chunk = manager->chunks;\n     while (chunk) {\n          CoreSurfaceAllocation *allocation;\n\n          D_MAGIC_ASSERT( chunk, Chunk );\n\n          allocation = chunk->allocation;\n          if (allocation) {\n               CoreSurfaceBuffer *other;\n               int                size, locks;\n\n               D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n               D_ASSERT( chunk->buffer == allocation->buffer );\n               D_ASSERT( chunk->length >= allocation->size );\n\n               other = allocation->buffer;\n               D_MAGIC_ASSERT( other, CoreSurfaceBuffer );\n\n               locks = dfb_surface_allocation_locks( allocation );\n               if (locks) {\n                    D_DEBUG_AT( SurfMan, \"  ++ %7d locked %d\\n\", allocation->size, locks );\n                    goto next_reset;\n               }\n\n               if (other->policy > buffer->policy) {\n                    D_DEBUG_AT( SurfMan, \"  ++ %7d policy %u > %u\\n\", allocation->size, other->policy, buffer->policy );\n                    goto next_reset;\n               }\n\n               if (other->policy == CSP_VIDEOONLY) {\n                    D_DEBUG_AT( SurfMan, \"  ++ %7d policy videoonly\\n\", allocation->size );\n                    goto next_reset;\n               }\n\n               chunk->tolerations++;\n               if (chunk->tolerations > 0xff)\n                    chunk->tolerations = 0xff;\n\n               if (other->policy == buffer->policy && chunk->tolerations < min_toleration) {\n                    D_DEBUG_AT( SurfMan, \"  ++ %7d tolerations %d/%d\\n\", allocation->size,\n                                chunk->tolerations, min_toleration );\n                    goto next_reset;\n               }\n\n               size = allocation->size;\n\n               if (chunk->prev && !chunk->prev->allocation)\n                    size += chunk->prev->length;\n\n               if (chunk->next && !chunk->next->allocation)\n                    size += chunk->next->length;\n\n               if (size >= length) {\n                    if (!smallest || smallest->size > allocation->size) {\n                         D_DEBUG_AT( SurfMan, \"  -> %7d [%d] < %d, tolerations %d\\n\",\n                                     allocation->size, size, smallest ? smallest->size : 0, chunk->tolerations );\n\n                         smallest = allocation;\n                    }\n                    else\n                         D_DEBUG_AT( SurfMan, \"  -> %7d [%d] > %d\\n\", allocation->size, size, smallest->size );\n               }\n               else\n                    D_DEBUG_AT( SurfMan, \"  -> %7d [%d]\\n\", allocation->size, size );\n          }\n          else\n               D_DEBUG_AT( SurfMan, \"  -> %7d free\\n\", chunk->length );\n\n\n          if (!smallest) {\n               if (!multi_start) {\n                    multi_start = chunk;\n                    multi_tsize = chunk->length;\n                    multi_size  = chunk->allocation ? chunk->length : 0;\n                    multi_count = chunk->allocation ? 1 : 0;\n               }\n               else {\n                    multi_tsize += chunk->length;\n                    multi_size  += chunk->allocation ? chunk->length : 0;\n                    multi_count += chunk->allocation ? 1 : 0;\n\n                    while (multi_tsize >= length && multi_count > 1) {\n                         if (!bestm_start || bestm_size > multi_size * multi_count / bestm_count) {\n                              D_DEBUG_AT( SurfMan, \"                =====> %7d, %7d %2d used [%7d %2d]\\n\",\n                                          multi_tsize, multi_size, multi_count, bestm_size, bestm_count );\n\n                              bestm_size  = multi_size;\n                              bestm_start = multi_start;\n                              bestm_count = multi_count;\n                         }\n                         else\n                              D_DEBUG_AT( SurfMan, \"                =====> %7d, %7d %2d used\\n\",\n                                          multi_tsize, multi_size, multi_count );\n\n                         if (multi_count <= 2)\n                              break;\n\n                         if (!multi_start->allocation) {\n                              multi_tsize -= multi_start->length;\n                              multi_start  = multi_start->next;\n                         }\n\n                         multi_tsize -= multi_start->length;\n                         multi_size  -= multi_start->allocation ? multi_start->length : 0;\n                         multi_count -= multi_start->allocation ? 1 : 0;\n                         multi_start  = multi_start->next;\n                    }\n               }\n          }\n\n          chunk = chunk->next;\n\n          continue;\n\nnext_reset:\n          multi_start = NULL;\n          chunk = chunk->next;\n     }\n\n     if (smallest) {\n          D_MAGIC_ASSERT( smallest, CoreSurfaceAllocation );\n          D_MAGIC_ASSERT( smallest->buffer, CoreSurfaceBuffer );\n\n          smallest->flags |= CSALF_MUCKOUT;\n\n          D_DEBUG_AT( SurfMan, \"  -> offset %lu, size %d\\n\", smallest->offset, smallest->size );\n\n          return DFB_OK;\n     }\n\n     if (bestm_start) {\n          chunk = bestm_start;\n\n          while (bestm_count) {\n               CoreSurfaceAllocation *allocation = chunk->allocation;\n\n               if (allocation) {\n                    D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n                    D_MAGIC_ASSERT( allocation->buffer, CoreSurfaceBuffer );\n\n                    allocation->flags |= CSALF_MUCKOUT;\n\n                    bestm_count--;\n               }\n\n               D_DEBUG_AT( SurfMan, \"  -> offset %d, length %d\\n\", chunk->offset, chunk->length );\n\n               chunk = chunk->next;\n          }\n\n          return DFB_OK;\n     }\n\n     return DFB_NOVIDEOMEMORY;\n}\n\nvoid\nsurfacemanager_deallocate( SurfaceManager *manager,\n                           Chunk          *chunk )\n{\n     D_MAGIC_ASSERT( manager, SurfaceManager );\n     D_MAGIC_ASSERT( chunk, Chunk );\n     D_MAGIC_ASSERT( chunk->buffer, CoreSurfaceBuffer );\n     D_MAGIC_ASSERT( chunk->buffer->surface, CoreSurface );\n\n     D_DEBUG_AT( SurfMan, \"%s( %p ) <- %dx%d %s\\n\", __FUNCTION__, chunk->buffer,\n                 chunk->buffer->surface->config.size.w, chunk->buffer->surface->config.size.h,\n                 dfb_pixelformat_name( chunk->buffer->surface->config.format ) );\n\n     free_chunk( manager, chunk );\n}\n\n/**********************************************************************************************************************/\n\nstatic Chunk *\nsplit_chunk( SurfaceManager *manager,\n             Chunk          *chunk,\n             int             length )\n{\n     Chunk *newchunk;\n\n     D_MAGIC_ASSERT( chunk, Chunk );\n\n     /* No need to be splitted. */\n     if (chunk->length == length)\n          return chunk;\n\n     newchunk = SHCALLOC( manager->shmpool, 1, sizeof(Chunk) );\n     if (!newchunk) {\n          D_OOSHM();\n          return NULL;\n     }\n\n     /* Calculate offsets and lengths of resulting chunks. */\n     newchunk->offset = chunk->offset + chunk->length - length;\n     newchunk->length = length;\n     chunk->length -= newchunk->length;\n\n     /* Insert newchunk after chunk. */\n     newchunk->prev = chunk;\n     newchunk->next = chunk->next;\n     if (chunk->next)\n          chunk->next->prev = newchunk;\n     chunk->next = newchunk;\n\n     D_MAGIC_SET( newchunk, Chunk );\n\n     return newchunk;\n}\n\nstatic Chunk *\nfree_chunk( SurfaceManager *manager,\n            Chunk          *chunk )\n{\n     D_MAGIC_ASSERT( manager, SurfaceManager );\n     D_MAGIC_ASSERT( chunk, Chunk );\n\n     if (!chunk->buffer) {\n          D_BUG( \"freeing free chunk\" );\n          return chunk;\n     }\n\n     D_DEBUG_AT( SurfMan, \"%s( %d bytes at offset %d )\\n\", __FUNCTION__, chunk->length, chunk->offset );\n\n     if (chunk->buffer->policy == CSP_VIDEOONLY)\n          manager->avail += chunk->length;\n\n     D_DEBUG_AT( SurfMan, \"  -> freed %d, available %d\\n\", chunk->length, manager->avail );\n\n     chunk->allocation = NULL;\n     chunk->buffer     = NULL;\n\n     manager->min_toleration--;\n\n     if (chunk->prev && !chunk->prev->buffer) {\n          Chunk *prev = chunk->prev;\n\n          D_DEBUG_AT( SurfMan, \"  -> merging with previous chunk at %d\\n\", prev->offset );\n\n          prev->length += chunk->length;\n\n          prev->next = chunk->next;\n          if (prev->next)\n               prev->next->prev = prev;\n\n          D_DEBUG_AT( SurfMan, \"  -> freeing %p (prev %p, next %p)\\n\", chunk, chunk->prev, chunk->next );\n\n          D_MAGIC_CLEAR( chunk );\n\n          SHFREE( manager->shmpool, chunk );\n          chunk = prev;\n     }\n\n     if (chunk->next && !chunk->next->buffer) {\n          Chunk *next = chunk->next;\n\n          D_DEBUG_AT( SurfMan, \"  -> merging with next chunk at %d\\n\", next->offset );\n\n          chunk->length += next->length;\n\n          chunk->next = next->next;\n          if (chunk->next)\n               chunk->next->prev = chunk;\n\n          D_MAGIC_CLEAR( next );\n\n          SHFREE( manager->shmpool, next );\n     }\n\n     return chunk;\n}\n\nstatic Chunk *\noccupy_chunk( SurfaceManager        *manager,\n              Chunk                 *chunk,\n              CoreSurfaceAllocation *allocation,\n              int                    length,\n              int                    pitch )\n{\n     D_MAGIC_ASSERT( manager, SurfaceManager );\n     D_MAGIC_ASSERT( chunk, Chunk );\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( allocation->buffer, CoreSurfaceBuffer );\n\n     if (allocation->buffer->policy == CSP_VIDEOONLY)\n          manager->avail -= length;\n\n     chunk = split_chunk( manager, chunk, length );\n     if (!chunk)\n          return NULL;\n\n     D_DEBUG_AT( SurfMan, \"%s( %d bytes at offset %d )\\n\", __FUNCTION__, chunk->length, chunk->offset );\n\n     D_DEBUG_AT( SurfMan, \"  -> occupied %d, available %d\\n\", chunk->length, manager->avail );\n\n     chunk->allocation = allocation;\n     chunk->buffer     = allocation->buffer;\n     chunk->pitch      = pitch;\n\n     manager->min_toleration++;\n\n     return chunk;\n}\n"
  },
  {
    "path": "systems/fbdev/fbdev_surfacemanager.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FBDEV_SURFACEMANAGER_H__\n#define __FBDEV_SURFACEMANAGER_H__\n\n#include <core/coretypes.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct _Chunk          Chunk;\ntypedef struct _SurfaceManager SurfaceManager;\n\n/**********************************************************************************************************************/\n\nDFBResult surfacemanager_create            ( CoreDFB                *core,\n                                             unsigned int            length,\n                                             SurfaceManager        **ret_manager );\n\nvoid      surfacemanager_destroy           ( SurfaceManager         *manager );\n\nvoid      surfacemanager_adjust_heap_offset( SurfaceManager         *manager,\n                                             int                     offset );\n\nDFBResult surfacemanager_allocate          ( CoreDFB                *core,\n                                             SurfaceManager         *manager,\n                                             CoreSurfaceBuffer      *buffer,\n                                             CoreSurfaceAllocation  *allocation,\n                                             Chunk                 **ret_chunk );\n\nint       surfacemanager_chunk_offset      ( Chunk                  *chunk );\n\nint       surfacemanager_chunk_length      ( Chunk                  *chunk );\n\nint       surfacemanager_chunk_pitch       ( Chunk                  *chunk );\n\nDFBResult surfacemanager_displace          ( CoreDFB                *core,\n                                             SurfaceManager         *manager,\n                                             CoreSurfaceBuffer      *buffer );\n\nvoid      surfacemanager_deallocate        ( SurfaceManager         *manager,\n                                             Chunk                  *chunk );\n\n#endif\n"
  },
  {
    "path": "systems/fbdev/fbdev_system.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#define _GNU_SOURCE /* To get basename() declaration. */\n\n#include <core/core.h>\n#include <core/core_system.h>\n#include <core/layers.h>\n#include <core/screens.h>\n#include <core/surface_pool.h>\n#include <direct/memcpy.h>\n#include <direct/system.h>\n#include <fusion/shmalloc.h>\n\n#include \"fbdev_mode.h\"\n#include \"fbdev_system.h\"\n#include \"fbdev_vt.h\"\n\nD_DEBUG_DOMAIN( FBDev_System, \"FBDev/System\", \"FBDev System Module\" );\n\nDFB_CORE_SYSTEM( fbdev )\n\n/**********************************************************************************************************************/\n\nextern const ScreenFuncs       fbdevScreenFuncs;\nextern const DisplayLayerFuncs fbdevPrimaryLayerFuncs;\nextern const SurfacePoolFuncs  fbdevSurfacePoolFuncs;\n\n#define SYS_CLASS_GRAPHICS_DEV        \"/sys/class/graphics/%s/device\"\n#define SYS_CLASS_GRAPHICS_DEV_VENDOR \"/sys/class/graphics/%s/device/vendor\"\n#define SYS_CLASS_GRAPHICS_DEV_MODEL  \"/sys/class/graphics/%s/device/device\"\n\nstatic void\nget_pci_info( FBDevDataShared *shared )\n{\n     char          buf[512];\n     int           vendor = -1;\n     int           model  = -1;\n     FILE         *fp;\n     unsigned int  bus;\n     unsigned int  dev;\n     unsigned int  func;\n     char          devname[5] = { 'f', 'b', '0', 0, 0 };\n     char          path[128];\n     int           len;\n\n     /* Try sysfs interface. */\n\n     if (!strncmp( shared->device_name, \"/dev/fb/\", 8 ))\n          snprintf( devname, sizeof(devname), \"fb%s\", shared->device_name + 8 );\n     else if (!strncmp( shared->device_name, \"/dev/fb\", 7 ))\n          snprintf( devname, sizeof(devname), \"fb%s\", shared->device_name + 7 );\n\n     snprintf( path, sizeof(path), SYS_CLASS_GRAPHICS_DEV, devname );\n\n     len = readlink( path, buf, sizeof(buf) );\n     if (len != -1) {\n          buf[len] = '\\0';\n\n          if (sscanf( basename( buf ), \"0000:%02x:%02x.%1x\", &bus, &dev, &func ) == 3) {\n               shared->pci.bus  = bus;\n               shared->pci.dev  = dev;\n               shared->pci.func = func;\n          }\n\n          snprintf( path, sizeof(path), SYS_CLASS_GRAPHICS_DEV_VENDOR, devname );\n\n          fp = fopen( path, \"r\" );\n          if (fp) {\n               if (fgets( buf, sizeof(buf), fp)) {\n                    if (sscanf( buf, \"0x%04x\", (unsigned int*) &vendor ) == 1)\n                         shared->device.vendor = vendor;\n               }\n\n               fclose( fp );\n          }\n          else\n               D_DEBUG_AT( FBDev_System, \"Couldn't access '%s'!\\n\", path );\n\n          snprintf( path, sizeof(path), SYS_CLASS_GRAPHICS_DEV_MODEL, devname );\n\n          fp = fopen( path, \"r\" );\n          if (fp) {\n               if (fgets( buf, sizeof(buf), fp)) {\n                    if (sscanf( buf, \"0x%04x\", (unsigned int*) &model ) == 1)\n                         shared->device.model = model;\n               }\n\n               fclose( fp );\n          }\n          else\n               D_DEBUG_AT( FBDev_System, \"Couldn't access '%s'!\\n\", path );\n     }\n     else\n          D_DEBUG_AT( FBDev_System, \"Couldn't access '%s'!\\n\", path );\n\n     /* Try procfs interface. */\n\n     if (vendor == -1 || model == -1) {\n          const char   *value;\n          int           pci_bus = 1, pci_dev = 0, pci_func = 0;\n          unsigned int  id;\n\n          fp = fopen( \"/proc/bus/pci/devices\", \"r\" );\n          if (!fp) {\n               D_DEBUG_AT( FBDev_System, \"Couldn't access '/proc/bus/pci/devices'!\\n\" );\n               return;\n          }\n\n          /* Get the PCI Bus ID of the graphics card (default 1:0:0) */\n          if ((value = direct_config_get_value( \"busid\" ))) {\n               if (sscanf( value, \"%d:%d:%d\", &pci_bus, &pci_dev, &pci_func ) != 3) {\n                    D_ERROR( \"FBDev/System: Couldn't parse busid!\\n\" );\n                    fclose( fp );\n                    return;\n               }\n          }\n\n          while (fgets( buf, sizeof(buf), fp )) {\n               if (sscanf( buf, \"%04x\\t%04x%04x\", &id, (unsigned int*) &vendor, (unsigned int*) &model ) == 3) {\n                    bus  = (id & 0xff00) >> 8;\n                    dev  = (id & 0x00ff) >> 3;\n                    func =  id & 0x0007 ;\n\n                    if (bus == pci_bus && dev == pci_dev && func == pci_func) {\n                         shared->pci.bus       = bus;\n                         shared->pci.dev       = dev;\n                         shared->pci.func      = func;\n                         shared->device.vendor = vendor;\n                         shared->device.model  = model;\n                         break;\n                    }\n               }\n          }\n\n          fclose( fp );\n     }\n}\n\nstatic FusionCallHandlerResult\nfbdev_ioctl_call_handler( int           caller,\n                          int           call_arg,\n                          void         *call_ptr,\n                          void         *ctx,\n                          unsigned int  serial,\n                          int          *ret_val )\n{\n     int              erno;\n     FBDevData       *fbdev = ctx;\n     FBDevDataShared *shared;\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     if (shared->vt && call_arg == FBIOPUT_VSCREENINFO)\n          fbdev_vt_set_graphics_mode( true );\n\n     erno = ioctl( fbdev->fd, call_arg, call_ptr );\n     if (erno < 0)\n          erno = errno;\n\n     if (shared->vt && call_arg == FBIOPUT_VSCREENINFO)\n          fbdev_vt_set_graphics_mode( false );\n\n     *ret_val = erno;\n\n     return FCHR_RETURN;\n}\n\nint\nfbdev_ioctl( FBDevData *fbdev,\n             int        request,\n             void      *arg,\n             int        arg_size )\n{\n     int              erno;\n     void            *ptr = NULL;\n     FBDevDataShared *shared;\n\n     D_DEBUG_AT( FBDev_System, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     if (request == FBIOPAN_DISPLAY || request == FBIO_WAITFORVSYNC || request == FBIOBLANK)\n          return ioctl( fbdev->fd, request, arg );\n\n     if (dfb_core_is_master( fbdev->core )) {\n          fbdev_ioctl_call_handler( 1, request, arg, fbdev, 0, &erno );\n          errno = erno;\n          return errno ? -1 : 0;\n     }\n\n     if (arg) {\n          if (!fusion_is_shared( dfb_core_world( fbdev->core ), arg )) {\n               ptr = SHMALLOC( shared->shmpool, arg_size );\n               if (!ptr) {\n                    errno = ENOMEM;\n                    return -1;\n               }\n\n               direct_memcpy( ptr, arg, arg_size );\n          }\n     }\n\n     fusion_call_execute( &shared->call, FCEF_NONE, request, ptr ?: arg, &erno );\n\n     if (ptr) {\n          direct_memcpy( arg, ptr, arg_size );\n          SHFREE( shared->shmpool, ptr );\n     }\n\n     errno = erno;\n\n     return errno ? -1 : 0;\n}\n\nstatic DFBResult\nlocal_init( const char *device_name,\n            FBDevData  *fbdev )\n{\n     CoreScreen *screen;\n\n     /* Open framebuffer device. */\n     fbdev->fd = open( device_name, O_RDWR );\n     if (fbdev->fd < 0) {\n          D_PERROR( \"FBDev/System: Failed to open '%s'!\\n\", device_name );\n          return DFB_INIT;\n     }\n\n     if (fcntl( fbdev->fd, F_SETFD, FD_CLOEXEC ) < 0) {\n          D_PERROR( \"FBDev/System: Setting FD_CLOEXEC flag failed!\\n\" );\n          return DFB_INIT;\n     }\n\n     /* Retrieve fixed screen information. */\n     fbdev->fix = D_CALLOC( 1, sizeof(struct fb_fix_screeninfo) );\n     if (!fbdev->fix)\n          return D_OOM();\n\n     if (ioctl( fbdev->fd, FBIOGET_FSCREENINFO, fbdev->fix ) < 0) {\n          D_PERROR( \"FBDev/System: Could not retrieve fixed screen information!\\n\" );\n          return DFB_INIT;\n     }\n\n     D_INFO( \"FBDev/System: Found '%s' (ID %u) with framebuffer at 0x%08lx, %uk (MMIO 0x%08lx, %uk)\\n\",\n             fbdev->fix->id, fbdev->fix->accel,\n             fbdev->fix->smem_start, fbdev->fix->smem_len >> 10, fbdev->fix->mmio_start, fbdev->fix->mmio_len >> 10 );\n\n     /* Map the framebuffer. */\n     fbdev->addr = mmap( NULL, fbdev->fix->smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbdev->fd, 0 );\n     if (fbdev->addr == MAP_FAILED) {\n          D_PERROR( \"FBDev/System: Could not mmap the framebuffer!\\n\" );\n          return DFB_INIT;\n     }\n\n     screen = dfb_screens_register( fbdev, &fbdevScreenFuncs );\n\n     dfb_layers_register( screen, fbdev, &fbdevPrimaryLayerFuncs );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nlocal_deinit( FBDevData *fbdev )\n{\n     if (fbdev->addr)\n          munmap( fbdev->addr, fbdev->fix->smem_len );\n\n     if (fbdev->fix)\n          D_FREE( fbdev->fix );\n\n     if (fbdev->fd != -1)\n          close( fbdev->fd );\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic void\nsystem_get_info( CoreSystemInfo *info )\n{\n     info->version.major = 0;\n     info->version.minor = 1;\n\n     info->caps = CSCAPS_ACCELERATION;\n\n     snprintf( info->name,   DFB_CORE_SYSTEM_INFO_NAME_LENGTH,   \"FBDev\" );\n     snprintf( info->vendor, DFB_CORE_SYSTEM_INFO_VENDOR_LENGTH, \"DirectFB\" );\n}\n\nstatic DFBResult\nsystem_initialize( CoreDFB  *core,\n                   void    **ret_data )\n{\n     DFBResult            ret;\n     FBDevData           *fbdev;\n     FBDevDataShared     *shared;\n     FusionSHMPoolShared *pool;\n     const char          *value;\n\n     D_DEBUG_AT( FBDev_System, \"%s()\\n\", __FUNCTION__ );\n\n     fbdev = D_CALLOC( 1, sizeof(FBDevData) );\n     if (!fbdev)\n          return D_OOM();\n\n     fbdev->core = core;\n\n     pool = dfb_core_shmpool( core );\n\n     shared = SHCALLOC( pool, 1, sizeof(FBDevDataShared) );\n     if (!shared) {\n          D_FREE( fbdev );\n          return D_OOSHM();\n     }\n\n     shared->shmpool = pool;\n\n     fbdev->shared = shared;\n\n     if ((value = direct_config_get_value( \"fbdev\" ))) {\n          direct_snputs( shared->device_name, value, 255 );\n          D_INFO( \"FBDev/System: Using device %s as specified in DirectFB configuration\\n\", shared->device_name );\n     }\n     else if (getenv( \"FRAMEBUFFER\" ) && *getenv( \"FRAMEBUFFER\" ) != '\\0') {\n          direct_snputs( shared->device_name, getenv( \"FRAMEBUFFER\" ), 255 );\n          D_INFO( \"FBDev/System: Using device %s as set in FRAMEBUFFER environment variable\\n\", shared->device_name );\n     }\n     else {\n          snprintf( shared->device_name, 255, \"/dev/fb0\" );\n          D_INFO( \"FBDev/System: Using device %s (default)\\n\", shared->device_name );\n     }\n\n     if ((value = direct_config_get_value( \"fbmodes\" )))\n          direct_snputs( shared->modes_file, value, 255 );\n     else if (getenv( \"MODES\" ) && *getenv( \"MODES\" ) != '\\0')\n          direct_snputs( shared->device_name, getenv( \"MODES\" ), 255 );\n     else\n          snprintf( shared->modes_file, 255, \"/etc/fb.modes\" );\n\n     if (direct_config_has_name( \"no-vt\" ) && !direct_config_has_name( \"vt\" ))\n          D_INFO( \"FBDev/System: Don't use VT handling\\n\" );\n     else\n          shared->vt = true;\n\n     if (direct_config_has_name( \"vsync-after\" ) && !direct_config_has_name( \"no-vsync-after\" ))\n          shared->pollvsync_after = true;\n\n     if (direct_config_has_name( \"vsync-none\" ) && !direct_config_has_name( \"no-vsync-none\" ))\n          shared->pollvsync_none = true;\n\n     ret = local_init( shared->device_name, fbdev );\n     if (ret)\n          goto error;\n\n     if (shared->vt) {\n          ret = fbdev_vt_initialize( core, fbdev->fd );\n          if (ret)\n               goto error;\n     }\n\n     if (ioctl( fbdev->fd, FBIOGET_VSCREENINFO, &shared->orig_var ) < 0) {\n          D_PERROR( \"FBDev/System: Could not get variable screen information!\\n\" );\n          ret = DFB_INIT;\n          goto error;\n     }\n\n     shared->current_var = shared->orig_var;\n     shared->current_var.accel_flags = 0;\n\n     if (ioctl( fbdev->fd, FBIOPUT_VSCREENINFO, &shared->current_var ) < 0) {\n          D_PERROR( \"FBDev/System: Could not disable console acceleration!\\n\" );\n          ret = DFB_INIT;\n          goto error;\n     }\n\n     fbdev_var_to_mode( &shared->current_var, &shared->mode );\n\n     shared->page_mask = direct_pagesize() < 0 ? 0 : (direct_pagesize() - 1);\n\n     shared->shmpool_data = dfb_core_shmpool_data( core );\n\n     shared->orig_cmap_memory = SHMALLOC( shared->shmpool_data, 256 * 2 * 4 );\n     if (!shared->orig_cmap_memory) {\n          ret = D_OOSHM();\n          goto error;\n     }\n\n     shared->orig_cmap.start  = 0;\n     shared->orig_cmap.len    = 256;\n     shared->orig_cmap.red    = shared->orig_cmap_memory + 256 * 2 * 0;\n     shared->orig_cmap.green  = shared->orig_cmap_memory + 256 * 2 * 1;\n     shared->orig_cmap.blue   = shared->orig_cmap_memory + 256 * 2 * 2;\n     shared->orig_cmap.transp = shared->orig_cmap_memory + 256 * 2 * 3;\n\n     if (ioctl( fbdev->fd, FBIOGETCMAP, &shared->orig_cmap ) < 0) {\n          D_DEBUG_AT( FBDev_System, \"  -> Could not retrieve palette for backup\\n\" );\n          shared->orig_cmap.len = 0;\n     }\n\n     shared->current_cmap_memory = SHMALLOC( shared->shmpool_data, 256 * 2 * 4 );\n     if (!shared->current_cmap_memory) {\n          ret = D_OOSHM();\n          goto error;\n     }\n\n     shared->current_cmap.start  = 0;\n     shared->current_cmap.len    = 256;\n     shared->current_cmap.red    = shared->current_cmap_memory + 256 * 2 * 0;\n     shared->current_cmap.green  = shared->current_cmap_memory + 256 * 2 * 1;\n     shared->current_cmap.blue   = shared->current_cmap_memory + 256 * 2 * 2;\n     shared->current_cmap.transp = shared->current_cmap_memory + 256 * 2 * 3;\n\n     shared->temp_cmap_memory = SHMALLOC( shared->shmpool_data, 256 * 2 * 4 );\n     if (!shared->temp_cmap_memory) {\n          ret = D_OOSHM();\n          goto error;\n     }\n\n     shared->temp_cmap.start  = 0;\n     shared->temp_cmap.len    = 256;\n     shared->temp_cmap.red    = shared->temp_cmap_memory + 256 * 2 * 0;\n     shared->temp_cmap.green  = shared->temp_cmap_memory + 256 * 2 * 1;\n     shared->temp_cmap.blue   = shared->temp_cmap_memory + 256 * 2 * 2;\n     shared->temp_cmap.transp = shared->temp_cmap_memory + 256 * 2 * 3;\n\n     /* Initialize the mode table. */\n     ret = fbdev_init_modes( fbdev );\n     if (ret)\n          return ret;\n\n     shared->device.vendor = 0xffff;\n     shared->device.model  = 0xffff;\n     get_pci_info( shared );\n\n     fusion_call_init( &shared->call, fbdev_ioctl_call_handler, fbdev, dfb_core_world( core ) );\n\n     *ret_data = fbdev;\n\n     ret = dfb_surface_pool_initialize( core, &fbdevSurfacePoolFuncs, &shared->pool );\n     if (ret)\n          goto error;\n\n     ret = core_arena_add_shared_field( core, \"fbdev\", shared );\n     if (ret)\n          goto error;\n\n     return DFB_OK;\n\nerror:\n     if (shared->orig_cmap_memory)\n          SHFREE( shared->shmpool_data, shared->orig_cmap_memory );\n\n     if (shared->temp_cmap_memory)\n          SHFREE( shared->shmpool_data, shared->temp_cmap_memory );\n\n     if (shared->current_cmap_memory)\n          SHFREE( shared->shmpool_data, shared->current_cmap_memory );\n\n     if (shared->orig_var.accel_flags)\n          ioctl( fbdev->fd, FBIOPUT_VSCREENINFO, &shared->orig_var );\n\n     if (shared->vt)\n          fbdev_vt_shutdown( false, fbdev->fd );\n\n     local_deinit( fbdev );\n\n     SHFREE( pool, shared );\n\n     D_FREE( fbdev );\n\n     return ret;\n}\n\nstatic DFBResult\nsystem_join( CoreDFB  *core,\n             void    **ret_data )\n{\n     DFBResult        ret;\n     FBDevData       *fbdev;\n     FBDevDataShared *shared;\n\n     D_DEBUG_AT( FBDev_System, \"%s()\\n\", __FUNCTION__ );\n\n     fbdev = D_CALLOC( 1, sizeof(FBDevData) );\n     if (!fbdev)\n          return D_OOM();\n\n     fbdev->core = core;\n\n     ret = core_arena_get_shared_field( core, \"fbdev\", (void**) &shared );\n     if (ret) {\n          D_FREE( fbdev );\n          return ret;\n     }\n\n     fbdev->shared = shared;\n\n     ret = local_init( shared->device_name, fbdev );\n     if (ret)\n          goto error;\n\n     *ret_data = fbdev;\n\n     ret = dfb_surface_pool_join( core, shared->pool, &fbdevSurfacePoolFuncs );\n     if (ret)\n          goto error;\n\n     return DFB_OK;\n\nerror:\n     local_deinit( fbdev );\n\n     D_FREE( fbdev );\n\n     return ret;\n}\n\nstatic DFBResult\nsystem_shutdown( bool emergency )\n{\n     FBDevData       *fbdev = dfb_system_data();\n     FBDevDataShared *shared;\n     VideoMode       *mode;\n\n     D_DEBUG_AT( FBDev_System, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     dfb_surface_pool_destroy( shared->pool );\n\n     fusion_call_destroy( &shared->call );\n\n     mode = shared->modes;\n     while (mode) {\n          VideoMode *next = mode->next;\n          SHFREE( shared->shmpool, mode );\n          mode = next;\n     }\n\n     if (shared->temp_cmap_memory)\n          SHFREE( shared->shmpool_data, shared->temp_cmap_memory );\n\n     if (shared->current_cmap_memory)\n          SHFREE( shared->shmpool_data, shared->current_cmap_memory );\n\n     if (shared->orig_cmap.len)\n          ioctl( fbdev->fd, FBIOPUTCMAP, &shared->orig_cmap );\n\n     if (shared->orig_cmap_memory)\n          SHFREE( shared->shmpool_data, shared->orig_cmap_memory );\n\n     ioctl( fbdev->fd, FBIOPUT_VSCREENINFO, &shared->orig_var );\n\n     if (shared->vt)\n          fbdev_vt_shutdown( emergency, fbdev->fd );\n\n     local_deinit( fbdev );\n\n     SHFREE( shared->shmpool, shared );\n\n     D_FREE( fbdev );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsystem_leave( bool emergency )\n{\n     FBDevData       *fbdev = dfb_system_data();\n     FBDevDataShared *shared;\n\n     D_DEBUG_AT( FBDev_System, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     dfb_surface_pool_leave( shared->pool );\n\n     local_deinit( fbdev );\n\n     D_FREE( fbdev );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsystem_suspend()\n{\n     return DFB_OK;\n}\n\nstatic DFBResult\nsystem_resume()\n{\n     return DFB_OK;\n}\n\nstatic VideoMode *\nsystem_get_modes()\n{\n     FBDevData       *fbdev = dfb_system_data();\n     FBDevDataShared *shared;\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     return shared->modes;\n}\n\nstatic VideoMode *\nsystem_get_current_mode()\n{\n     FBDevData       *fbdev = dfb_system_data();\n     FBDevDataShared *shared;\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     return &shared->mode;\n}\n\nstatic DFBResult\nsystem_thread_init()\n{\n     return DFB_OK;\n}\n\nstatic bool\nsystem_input_filter( CoreInputDevice *device,\n                     DFBInputEvent   *event )\n{\n     FBDevData       *fbdev = dfb_system_data();\n     FBDevDataShared *shared;\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     if (shared->vt) {\n          if (DFB_KEY_TYPE( event->key_symbol ) == DIKT_FUNCTION && event->modifiers == (DIMM_CONTROL | DIMM_ALT) &&\n              (event->type == DIET_KEYPRESS || event->type == DIET_KEYRELEASE))\n               return fbdev_vt_switch_num( event->key_symbol - DIKS_F1 + 1, event->type == DIET_KEYPRESS );\n     }\n\n     return false;\n}\n\nstatic volatile void *\nsystem_map_mmio( unsigned int offset,\n                 int          length )\n{\n     FBDevData       *fbdev = dfb_system_data();\n     FBDevDataShared *shared;\n     void            *addr;\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     if (length <= 0)\n          length = fbdev->fix->mmio_len;\n\n     addr = mmap( NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fbdev->fd, fbdev->fix->smem_len + offset );\n     if (addr == MAP_FAILED) {\n          D_PERROR( \"FBDev/System: Could not mmap MMIO region (offset %u, length %d)!\\n\", offset, length );\n          return NULL;\n     }\n\n     return addr + (fbdev->fix->mmio_start & shared->page_mask);\n}\n\nstatic void\nsystem_unmap_mmio( volatile void *addr,\n                   int            length )\n{\n     FBDevData       *fbdev = dfb_system_data();\n     FBDevDataShared *shared;\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     if (length <= 0)\n          length = fbdev->fix->mmio_len;\n\n     if (munmap( (u8*) addr - (fbdev->fix->mmio_start & shared->page_mask), length ) < 0)\n          D_PERROR( \"FBDev/System: Could not unmap MMIO region at %p (length %d)!\\n\", addr, length );\n}\n\nstatic unsigned int\nsystem_get_accelerator()\n{\n     FBDevData    *fbdev = dfb_system_data();\n     unsigned int  accel;\n\n     D_ASSERT( fbdev != NULL );\n\n     /* Accelerator ID selecting the graphics driver. */\n     accel = direct_config_get_int_value( \"accelerator\" );\n     if (accel)\n          return accel;\n\n     return fbdev->fix->accel;\n}\n\nstatic unsigned long\nsystem_video_memory_physical( unsigned int offset )\n{\n     FBDevData *fbdev = dfb_system_data();\n\n     D_ASSERT( fbdev != NULL );\n\n     return fbdev->fix->smem_start + offset;\n}\n\nstatic void *\nsystem_video_memory_virtual( unsigned int offset )\n{\n     FBDevData *fbdev = dfb_system_data();\n\n     D_ASSERT( fbdev != NULL );\n\n     return fbdev->addr + offset;\n}\n\nstatic unsigned int\nsystem_videoram_length()\n{\n     FBDevData *fbdev = dfb_system_data();\n\n     D_ASSERT( fbdev != NULL );\n\n     return fbdev->fix->smem_len;\n}\n\nstatic void\nsystem_get_busid( int *ret_bus,\n                  int *ret_dev,\n                  int *ret_func )\n{\n     FBDevData       *fbdev = dfb_system_data();\n     FBDevDataShared *shared;\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     *ret_bus  = shared->pci.bus;\n     *ret_dev  = shared->pci.dev;\n     *ret_func = shared->pci.func;\n}\n\nstatic void\nsystem_get_deviceid( unsigned int *ret_vendor_id,\n                     unsigned int *ret_device_id )\n{\n     FBDevData       *fbdev = dfb_system_data();\n     FBDevDataShared *shared;\n\n     D_ASSERT( fbdev != NULL );\n     D_ASSERT( fbdev->shared != NULL );\n\n     shared = fbdev->shared;\n\n     *ret_vendor_id = shared->device.vendor;\n     *ret_device_id = shared->device.model;\n}\n"
  },
  {
    "path": "systems/fbdev/fbdev_system.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FBDEV_SYSTEM_H__\n#define __FBDEV_SYSTEM_H__\n\n#include <core/video_mode.h>\n#include <fusion/call.h>\n#include <linux/fb.h>\n\n#include \"fbdev_surfacemanager.h\"\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     FusionSHMPoolShared      *shmpool;\n\n     CoreSurfacePool          *pool;\n\n     char                      device_name[256];    /* FBDev device name, e.g. /dev/fb0 */\n     char                      modes_file[256];     /* FBDev modes file, e.g. /etc/fb.modes */\n\n     bool                      vt;                  /* use VT handling */\n\n     bool                      pollvsync_after;     /* wait for the vertical retrace after flipping */\n     bool                      pollvsync_none;      /* disable polling for vertical retrace */\n\n     VideoMode                *modes;               /* linked list of valid video modes */\n     VideoMode                 mode;                /* current video mode */\n\n     struct fb_var_screeninfo  orig_var;            /* variable screen information before DirectFB was started */\n     struct fb_var_screeninfo  current_var;         /* variable screen information set by DirectFB */\n\n     unsigned long             page_mask;           /* PAGE_SIZE - 1 */\n\n     FusionSHMPoolShared      *shmpool_data;        /* shared memory pool for palette values defined in a colormap */\n     void                     *orig_cmap_memory;    /* memory to store the values of the original palette */\n     void                     *current_cmap_memory; /* memory to store the values of the current palette */\n     void                     *temp_cmap_memory;    /* memory to store the values of the adjusted palette */\n     struct fb_cmap            orig_cmap;           /* original colormap */\n     struct fb_cmap            current_cmap;        /* current colormap */\n     struct fb_cmap            temp_cmap;           /* adjusted colormap */\n\n     struct {\n          int                  bus;                 /* PCI Bus */\n          int                  dev;                 /* PCI Device */\n          int                  func;                /* PCI Function */\n     } pci;\n\n     struct {\n          unsigned short       vendor;              /* graphics device vendor id */\n          unsigned short       model;               /* graphics device model id */\n     } device;\n\n     FusionCall                call;                /* ioctl rpc */\n\n     SurfaceManager           *manager;             /* surface manager */\n} FBDevDataShared;\n\ntypedef struct {\n     FBDevDataShared          *shared;\n\n     CoreDFB                  *core;\n\n     int                       fd;     /* framebuffer file descriptor */\n\n     struct fb_fix_screeninfo *fix;    /* fixed screen information (infos about memory and type of card) */\n\n     void                     *addr;   /* framebuffer memory address */\n} FBDevData;\n\n/**********************************************************************************************************************/\n\nint fbdev_ioctl( FBDevData *fbdev,\n                 int        request,\n                 void      *arg,\n                 int        arg_size );\n\n#endif\n"
  },
  {
    "path": "systems/fbdev/fbdev_vt.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core.h>\n#include <direct/system.h>\n#include <direct/thread.h>\n#include <linux/fb.h>\n#include <linux/vt.h>\n#include <sys/kd.h>\n#include <termios.h>\n\n#include \"fbdev_vt.h\"\n\nD_DEBUG_DOMAIN( VT, \"FBDev/VT\", \"FBDev VT Handling\" );\n\n/**********************************************************************************************************************/\n\n#define SIG_SWITCH_FROM SIGUSR1\n#define SIG_SWITCH_TO   SIGUSR2\n\ntypedef struct {\n     CoreDFB          *core;\n\n     int               fd0;       /* file descriptor of /dev/tty0 */\n     int               fd;        /* file descriptor of /dev/ttyN where N is the VT number where DirectFB runs */\n\n     int               prev;      /* VT number from which DirectFB was started */\n     int               num;       /* VT number where DirectFB runs (use the given VT number instead of the current or a\n                                     new one allocated for a VT switch), num = prev if no VT switch */\n     bool              graphics;  /* put terminal into graphics mode */\n     bool              vt_switch; /* allocate a new VT or use the given VT, and then switch to it */\n     bool              switching; /* allow VT switching by pressing Ctrl+Alt+<F?> */\n\n\n     int               old_fb;    /* original fb mapped to vt */\n     struct termios    old_ts;    /* original termios */\n     struct vt_mode    old_vtm;   /* original vt mode */\n\n     struct sigaction  sig_usr1;  /* previous action for SIGUSR1 */\n     struct sigaction  sig_usr2;  /* previous action for SIGUSR2 */\n     int               sig;       /* signal signum */\n\n     DirectMutex       lock;\n     DirectWaitQueue   wait;\n     DirectThread     *thread;\n\n     bool              flush;\n     DirectThread     *flush_thread;\n} VirtualTerminal;\n\n/**********************************************************************************************************************/\n\nstatic VirtualTerminal *vt = NULL;\n\nstatic int\nvt_get_fb( int fbdev_fd,\n           int num )\n{\n     struct fb_con2fbmap c2m;\n\n     D_DEBUG_AT( VT, \"%s( %d )\\n\", __FUNCTION__, num );\n\n     c2m.console = num;\n\n     if (ioctl( fbdev_fd, FBIOGET_CON2FBMAP, &c2m )) {\n          D_PERROR( \"FBDev/VT: FBIOGET_CON2FBMAP failed!\\n\" );\n          return -1;\n     }\n\n     D_DEBUG_AT( VT, \"  -> %u\\n\", c2m.framebuffer );\n\n     return c2m.framebuffer;\n}\n\nstatic void\nvt_set_fb( int fbdev_fd,\n           int num,\n           int fb )\n{\n     struct fb_con2fbmap c2m;\n     struct stat         st;\n\n     D_DEBUG_AT( VT, \"%s( %d, %d )\\n\", __FUNCTION__, num, fb );\n\n     if (fstat( fbdev_fd, &st ))\n          return;\n\n     if (fb >= 0)\n          c2m.framebuffer = fb;\n     else\n          c2m.framebuffer = (st.st_rdev & 0xff) >> 5;\n\n     c2m.console = num;\n\n     if (ioctl( fbdev_fd, FBIOPUT_CON2FBMAP, &c2m ) < 0) {\n          D_PERROR( \"FBDev/VT: FBIOPUT_CON2FBMAP failed!\\n\" );\n     }\n}\n\nstatic void *\nvt_switcher( DirectThread *thread,\n             void         *arg )\n{\n     D_DEBUG_AT( VT, \"%s( %p, %p )\\n\", __FUNCTION__, thread, arg );\n\n     direct_mutex_lock( &vt->lock );\n\n     while (true) {\n          direct_thread_testcancel( thread );\n\n          D_DEBUG_AT( VT, \"%s() <- signal %d\\n\", __FUNCTION__, vt->sig );\n\n          switch (vt->sig) {\n               default:\n                    D_BUG( \"unexpected sig\" );\n                    /* fall through */\n\n               case -1:\n                    direct_waitqueue_wait( &vt->wait, &vt->lock );\n                    continue;\n\n               case SIG_SWITCH_FROM:\n                    if (dfb_core_suspend( vt->core ) == DFB_OK) {\n                         if (ioctl( vt->fd, VT_RELDISP, VT_ACKACQ ) < 0)\n                              D_PERROR( \"FBDev/VT: VT_RELDISP failed!\\n\" );\n                    }\n                    break;\n\n               case SIG_SWITCH_TO:\n                    if (dfb_core_resume( vt->core ) == DFB_OK) {\n                         if (ioctl( vt->fd, VT_RELDISP, VT_ACKACQ ) < 0)\n                              D_PERROR( \"FBDev/VT: VT_RELDISP failed!\\n\" );\n\n                         if (vt->graphics) {\n                              if (ioctl( vt->fd, KDSETMODE, KD_GRAPHICS ) < 0)\n                                   D_PERROR( \"FBDev/VT: KD_GRAPHICS failed!\\n\" );\n                         }\n                    }\n                    break;\n          }\n\n          vt->sig = -1;\n\n          direct_waitqueue_signal( &vt->wait );\n     }\n\n     return NULL;\n}\n\nstatic void\nvt_switch_handler( int signum )\n{\n     D_DEBUG_AT( VT, \"%s( %d )\\n\", __FUNCTION__, signum );\n\n     direct_mutex_lock( &vt->lock );\n\n     while (vt->sig != -1)\n          direct_waitqueue_wait( &vt->wait, &vt->lock );\n\n     vt->sig = signum;\n\n     direct_waitqueue_signal( &vt->wait );\n\n     direct_mutex_unlock( &vt->lock );\n}\n\nstatic DFBResult\nvt_init_switching( void )\n{\n     char           buf[32];\n     struct termios ts;\n     const char     blankoff_str[]  = \"\\033[9;0]\";\n     const char     cursoroff_str[] = \"\\033[?1;0;0c\";\n     ssize_t        sz;\n\n     D_UNUSED_P( sz );\n\n     D_DEBUG_AT( VT, \"%s()\\n\", __FUNCTION__ );\n\n     snprintf( buf, sizeof(buf), \"/dev/tty%d\", vt->num );\n     vt->fd = open( buf, O_RDWR | O_NOCTTY );\n     if (vt->fd < 0) {\n          if (errno == ENOENT) {\n               snprintf( buf, sizeof(buf), \"/dev/vc/%d\", vt->num );\n               vt->fd = open( buf, O_RDWR | O_NOCTTY );\n               if (vt->fd < 0) {\n                    if (errno == ENOENT) {\n                         D_PERROR( \"FBDev/VT: Couldn't open neither '/dev/tty%d' nor '/dev/vc/%d'!\\n\",\n                                    vt->num, vt->num );\n                    }\n                    else\n                         D_PERROR( \"FBDev/VT: Error opening '%s'!\\n\", buf );\n\n                    return DFB_INIT;\n               }\n          }\n          else {\n               D_PERROR( \"FBDev/VT: Error opening '%s'!\\n\", buf );\n\n               return DFB_INIT;\n          }\n     }\n\n     ioctl( vt->fd, TIOCSCTTY, 0 );\n\n     if (ioctl( vt->fd, KDSKBMODE, K_MEDIUMRAW ) < 0) {\n          D_PERROR( \"FBDev/VT: K_MEDIUMRAW failed!\\n\" );\n          close( vt->fd );\n          return DFB_INIT;\n     }\n\n     if (tcgetattr( vt->fd, &vt->old_ts ) < 0) {\n          D_PERROR( \"FBDev/VT: tcgetattr() failed!\\n\" );\n          ioctl( vt->fd, KDSKBMODE, K_XLATE );\n          close( vt->fd );\n          return DFB_INIT;\n     }\n\n     ts = vt->old_ts;\n     ts.c_iflag      = 0;\n     ts.c_lflag     &= ~(ICANON | ECHO | ISIG);\n     ts.c_cc[VTIME]  = 0;\n     ts.c_cc[VMIN]   = 1;\n\n     if (tcsetattr( vt->fd, TCSAFLUSH, &ts ) < 0) {\n          D_PERROR( \"FBDev/VT: tcsetattr() failed!\\n\" );\n          ioctl( vt->fd, KDSKBMODE, K_XLATE );\n          close( vt->fd );\n          return DFB_INIT;\n     }\n\n     sz = write( vt->fd, cursoroff_str, sizeof(cursoroff_str) );\n\n     if (vt->graphics) {\n          if (ioctl( vt->fd, KDSETMODE, KD_GRAPHICS ) < 0) {\n               D_PERROR( \"FBDev/VT: KD_GRAPHICS failed!\\n\" );\n               tcsetattr( vt->fd, TCSAFLUSH, &vt->old_ts );\n               ioctl( vt->fd, KDSKBMODE, K_XLATE );\n               close( vt->fd );\n               return DFB_INIT;\n          }\n     }\n     else {\n          sz = write( vt->fd, blankoff_str, sizeof(blankoff_str) );\n     }\n\n     if (vt->switching) {\n          struct vt_mode   vtm;\n          struct sigaction sig_tty;\n\n          memset( &sig_tty, 0, sizeof(sig_tty) );\n          sig_tty.sa_handler = vt_switch_handler;\n          sigfillset( &sig_tty.sa_mask );\n\n          if (sigaction( SIG_SWITCH_FROM, &sig_tty, &vt->sig_usr1 ) ||\n              sigaction( SIG_SWITCH_TO, &sig_tty, &vt->sig_usr2 )) {\n               D_PERROR( \"FBDev/VT: sigaction() failed!\\n\" );\n               tcsetattr( vt->fd, TCSAFLUSH, &vt->old_ts );\n               ioctl( vt->fd, KDSKBMODE, K_XLATE );\n               close( vt->fd );\n               return DFB_INIT;\n          }\n\n          if (ioctl( vt->fd, VT_GETMODE, &vt->old_vtm )) {\n               D_PERROR( \"FBDev/VT: VT_GETMODE failed!\\n\" );\n               sigaction( SIG_SWITCH_FROM, &vt->sig_usr1, NULL );\n               sigaction( SIG_SWITCH_TO, &vt->sig_usr2, NULL );\n               tcsetattr( vt->fd, TCSAFLUSH, &vt->old_ts );\n               ioctl( vt->fd, KDSKBMODE, K_XLATE );\n               close( vt->fd );\n               return DFB_INIT;\n          }\n\n          memset( &vtm, 0, sizeof(vtm) );\n          vtm.mode   = VT_PROCESS;\n          vtm.relsig = SIG_SWITCH_FROM;\n          vtm.acqsig = SIG_SWITCH_TO;\n\n          if (ioctl( vt->fd, VT_SETMODE, &vtm ) < 0) {\n               D_PERROR( \"FBDev/VT: VT_SETMODE failed!\\n\" );\n               ioctl( vt->fd, VT_SETMODE, &vt->old_vtm );\n               sigaction( SIG_SWITCH_FROM, &vt->sig_usr1, NULL );\n               sigaction( SIG_SWITCH_TO, &vt->sig_usr2, NULL );\n               tcsetattr( vt->fd, TCSAFLUSH, &vt->old_ts );\n               ioctl( vt->fd, KDSKBMODE, K_XLATE );\n               close( vt->fd );\n               return DFB_INIT;\n          }\n\n          direct_recursive_mutex_init( &vt->lock );\n\n          direct_waitqueue_init( &vt->wait );\n\n          vt->sig = -1;\n\n          vt->thread = direct_thread_create( DTT_CRITICAL, vt_switcher, NULL, \"VT Switcher\" );\n     }\n\n     return DFB_OK;\n}\n\nstatic void *\nvt_flusher( DirectThread *thread,\n            void         *arg )\n{\n     D_DEBUG_AT( VT, \"%s( %p, %p )\\n\", __FUNCTION__, thread, arg );\n\n     while (vt->flush) {\n          int    err;\n          fd_set set;\n\n          FD_ZERO( &set );\n          FD_SET( vt->fd, &set );\n\n          err = select( vt->fd + 1, &set, NULL, NULL, NULL );\n\n          if (err < 0 && errno == EINTR)\n               continue;\n\n          if (err < 0 || !vt->flush)\n               break;\n\n          tcflush( vt->fd, TCIFLUSH );\n     }\n\n     return NULL;\n}\n\nstatic void\nvt_start_flushing( void )\n{\n     vt->flush        = true;\n     vt->flush_thread = direct_thread_create( DTT_DEFAULT, vt_flusher, NULL, \"VT Flusher\" );\n}\n\nDFBResult\nfbdev_vt_initialize( CoreDFB *core,\n                     int      fbdev_fd )\n{\n     DFBResult       ret;\n     struct vt_stat  vs;\n\n     D_DEBUG_AT( VT, \"%s()\\n\", __FUNCTION__ );\n\n     vt = D_CALLOC( 1, sizeof(VirtualTerminal) );\n     if (!vt)\n          return D_OOM();\n\n     vt->core = core;\n\n     vt->num = direct_config_get_int_value_with_default( \"vt-num\", -1 );\n\n     /* Check root privileges for the VT switch. */\n     if (!direct_geteuid()) {\n          if (direct_config_has_name( \"no-vt-switch\" ) && !direct_config_has_name( \"vt-switch\" ))\n               D_INFO( \"FBDev/VT: Don't switch to a new VT or to the given VT\\n\" );\n          else\n               vt->vt_switch = true;\n     }\n\n     /* Always put terminal into graphics mode if no VT switch. */\n     if (!vt->vt_switch)\n          vt->graphics = true;\n     else {\n          if (direct_config_has_name( \"no-vt-graphics\" ) && !direct_config_has_name( \"vt-graphics\" ))\n               D_INFO( \"FBDev/VT: Don't put terminal into graphics mode\\n\" );\n          else\n               vt->graphics = true;\n     }\n\n     /* Check if VT switching is allowed. */\n     if (direct_config_has_name( \"no-vt-switching\" ) && !direct_config_has_name( \"vt-switching\" ))\n          D_INFO( \"FBDev/VT: Don't allow VT switching by pressing Ctrl+Alt+<F?>\\n\" );\n     else\n          vt->switching = true;\n\n     setsid();\n\n     vt->fd0 = open( \"/dev/tty0\", O_RDONLY | O_NOCTTY );\n     if (vt->fd0 < 0) {\n          if (errno == ENOENT) {\n               vt->fd0 = open( \"/dev/vc/0\", O_RDONLY | O_NOCTTY );\n               if (vt->fd0 < 0) {\n                    if (errno == ENOENT) {\n                         D_PERROR( \"FBDev/VT: Couldn't open neither '/dev/tty0' nor '/dev/vc/0'!\\n\" );\n                    }\n                    else\n                         D_PERROR( \"FBDev/VT: Error opening '/dev/vc/0'!\\n\" );\n\n                    D_FREE( vt );\n                    vt = NULL;\n\n                    return DFB_INIT;\n               }\n          }\n          else {\n               D_PERROR( \"FBDev/VT: Error opening '/dev/tty0'!\\n\" );\n\n               D_FREE( vt );\n               vt = NULL;\n\n               return DFB_INIT;\n          }\n     }\n\n     if (ioctl( vt->fd0, VT_GETSTATE, &vs ) < 0) {\n          D_PERROR( \"FBDev/VT: VT_GETSTATE failed!\\n\" );\n          close( vt->fd0 );\n          D_FREE( vt );\n          vt = NULL;\n          return DFB_INIT;\n     }\n\n     vt->prev = vs.v_active;\n\n     if (!vt->vt_switch) {\n          vt->num = vt->prev;\n\n          /* Move vt to framebuffer. */\n          vt->old_fb = vt_get_fb( fbdev_fd, vt->num );\n          vt_set_fb( fbdev_fd, vt->num, -1 );\n     }\n     else {\n          if (vt->num == -1) {\n               int err;\n\n               err = ioctl( vt->fd0, VT_OPENQRY, &vt->num );\n               if (err < 0 || vt->num == -1) {\n                    D_PERROR( \"FBDev/VT: Cannot allocate VT!\\n\" );\n                    close( vt->fd0 );\n                    D_FREE( vt );\n                    vt = NULL;\n                    return DFB_INIT;\n               }\n          }\n\n          /* Move vt to framebuffer. */\n          vt->old_fb = vt_get_fb( fbdev_fd, vt->num );\n          vt_set_fb( fbdev_fd, vt->num, -1 );\n\n          D_DEBUG_AT( VT, \"  -> switching to vt %d\\n\", vt->num );\n\n          while (ioctl( vt->fd0, VT_ACTIVATE, vt->num ) < 0) {\n               if (errno == EINTR)\n                    continue;\n               D_PERROR( \"FBDev/VT: VT_ACTIVATE failed!\\n\" );\n               close( vt->fd0 );\n               D_FREE( vt );\n               vt = NULL;\n               return DFB_INIT;\n          }\n\n          while (ioctl( vt->fd0, VT_WAITACTIVE, vt->num ) < 0) {\n               if (errno == EINTR)\n                    continue;\n               D_PERROR( \"FBDev/VT: VT_WAITACTIVE failed!\\n\" );\n               close( vt->fd0 );\n               D_FREE( vt );\n               vt = NULL;\n               return DFB_INIT;\n          }\n\n          usleep( 40000 );\n     }\n\n     ret = vt_init_switching();\n     if (ret) {\n          if (vt->vt_switch) {\n               D_DEBUG_AT( VT, \"  -> switching back...\\n\" );\n               ioctl( vt->fd0, VT_ACTIVATE, vt->prev );\n               ioctl( vt->fd0, VT_WAITACTIVE, vt->prev );\n               D_DEBUG_AT( VT, \"  -> ...switched back\\n\" );\n               ioctl( vt->fd0, VT_DISALLOCATE, vt->num );\n          }\n\n          close( vt->fd0 );\n          D_FREE( vt );\n          vt = NULL;\n          return ret;\n     }\n\n     vt_start_flushing();\n\n     return DFB_OK;\n}\n\nstatic void\nvt_stop_flushing( void )\n{\n     vt->flush = false;\n     direct_thread_cancel( vt->flush_thread );\n     direct_thread_join( vt->flush_thread );\n     direct_thread_destroy( vt->flush_thread );\n     vt->flush_thread = NULL;\n}\n\nDFBResult\nfbdev_vt_shutdown( bool emergency,\n                   int  fbdev_fd )\n{\n     const char blankon_str[]  = \"\\033[9;10]\";\n     const char cursoron_str[] = \"\\033[?0;0;0c\";\n     ssize_t    sz;\n\n     D_UNUSED_P( sz );\n\n     D_DEBUG_AT( VT, \"%s()\\n\", __FUNCTION__ );\n\n     if (!vt)\n          return DFB_OK;\n\n     vt_stop_flushing();\n\n     if (vt->switching) {\n          if (ioctl( vt->fd, VT_SETMODE, &vt->old_vtm ) < 0)\n               D_PERROR( \"FBDev/VT: VT_SETMODE for original values failed!\\n\" );\n\n          sigaction( SIG_SWITCH_FROM, &vt->sig_usr1, NULL );\n          sigaction( SIG_SWITCH_TO, &vt->sig_usr2, NULL );\n\n          direct_thread_cancel( vt->thread );\n          direct_thread_join( vt->thread );\n          direct_thread_destroy( vt->thread );\n\n          direct_mutex_deinit( &vt->lock );\n          direct_waitqueue_deinit( &vt->wait );\n     }\n\n     if (vt->graphics) {\n          if (ioctl( vt->fd, KDSETMODE, KD_TEXT ) < 0)\n               D_PERROR( \"FBDev/VT: KD_TEXT failed!\\n\" );\n     }\n     else\n          sz = write( vt->fd, blankon_str, sizeof(blankon_str) );\n\n     sz = write( vt->fd, cursoron_str, sizeof(cursoron_str) );\n\n     if (tcsetattr( vt->fd, TCSAFLUSH, &vt->old_ts ) < 0)\n          D_PERROR( \"FBDev/VT: tcsetattr() for original values failed!\\n\" );\n\n     if (ioctl( vt->fd, KDSKBMODE, K_XLATE ) < 0)\n          D_PERROR( \"FBDev/VT: K_XLATE failed!\\n\" );\n\n     if (vt->vt_switch) {\n          D_DEBUG_AT( VT, \"  -> switching back...\\n\" );\n\n          if (ioctl( vt->fd0, VT_ACTIVATE, vt->prev ) < 0)\n               D_PERROR( \"FBDev/VT: VT_ACTIVATE failed!\\n\" );\n\n          if (ioctl( vt->fd0, VT_WAITACTIVE, vt->prev ) < 0)\n               D_PERROR( \"FBDev/VT: VT_WAITACTIVE failed!\\n\" );\n\n          D_DEBUG_AT( VT, \"  -> ...switched back\\n\" );\n\n          usleep( 40000 );\n\n          /* Restore con2fbmap. */\n          vt_set_fb( fbdev_fd, vt->num, vt->old_fb );\n\n          if (close( vt->fd ) < 0)\n               D_PERROR( \"FBDev/VT: Unable to close file descriptor of allocated VT!\\n\" );\n\n          ioctl( vt->fd0, VT_DISALLOCATE, vt->num );\n     }\n     else {\n          /* Restore con2fbmap. */\n          vt_set_fb( fbdev_fd, vt->num, vt->old_fb );\n\n          if (close( vt->fd ) < 0)\n               D_PERROR( \"FBDev/VT: Unable to close file descriptor of current VT!\\n\" );\n     }\n\n     if (close( vt->fd0 ) < 0)\n          D_PERROR( \"FBDev/VT: Unable to close file descriptor of tty0!\\n\" );\n\n     D_FREE( vt );\n     vt = NULL;\n\n     return DFB_OK;\n}\n\nbool\nfbdev_vt_switch_num( int  num,\n                     bool key_pressed )\n{\n     D_DEBUG_AT( VT, \"%s( %d )\\n\", __FUNCTION__, num );\n\n     if (!vt->switching)\n          return false;\n\n     if (!key_pressed)\n          return true;\n\n     D_DEBUG_AT( VT, \"  -> switching to vt %d\\n\", num );\n\n     if (ioctl( vt->fd0, VT_ACTIVATE, num ) < 0)\n          D_PERROR( \"FBDev/VT: VT_ACTIVATE failed!\\n\" );\n\n     return true;\n}\n\nvoid\nfbdev_vt_set_graphics_mode( bool set )\n{\n     const char blankoff_str[]  = \"\\033[9;0]\";\n     const char cursoroff_str[] = \"\\033[?1;0;0c\";\n     ssize_t    sz;\n\n     D_UNUSED_P( sz );\n\n     if (vt->graphics)\n          return;\n\n     if (set)\n          ioctl( vt->fd, KDSETMODE, KD_GRAPHICS );\n     else {\n          ioctl( vt->fd, KDSETMODE, KD_TEXT );\n          sz = write( vt->fd, cursoroff_str, strlen( cursoroff_str ) );\n          sz = write( vt->fd, blankoff_str,  strlen( blankoff_str ) );\n     }\n}\n"
  },
  {
    "path": "systems/fbdev/fbdev_vt.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __FBDEV_VT_H__\n#define __FBDEV_VT_H__\n\n#include <core/coretypes.h>\n\n/**********************************************************************************************************************/\n\nDFBResult fbdev_vt_initialize       ( CoreDFB *core,\n                                      int      fbdev_fd );\n\nDFBResult fbdev_vt_shutdown         ( bool     emergency,\n                                      int      fbdev_fd );\n\nbool      fbdev_vt_switch_num       ( int      num,\n                                      bool     key_pressed );\n\nvoid      fbdev_vt_set_graphics_mode( bool     set );\n\n#endif\n"
  },
  {
    "path": "systems/fbdev/meson.build",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\nif not cc.has_header('linux/fb.h')\n  warning('Building without FBDev support.')\n  subdir_done()\nendif\n\nfbdev_sources = [\n  'fbdev_layer.c',\n  'fbdev_mode.c',\n  'fbdev_screen.c',\n  'fbdev_surfacemanager.c',\n  'fbdev_surface_pool.c',\n  'fbdev_system.c',\n  'fbdev_vt.c'\n]\n\nlibrary('directfb_fbdev',\n        fbdev_sources,\n        build_rpath: get_option('prefix') / get_option('libdir'),\n        dependencies: directfb_dep,\n        install: true,\n        install_dir: moduledir / 'systems',\n        install_rpath: get_option('prefix') / get_option('libdir'))\n\nif get_option('default_library') == 'static'\n  pkgconfig.generate(filebase: 'directfb-system-fbdev',\n                     variables: 'moduledir=' + moduledir,\n                     name: 'DirectFB-system-fbdev',\n                     description: 'FBDev system module',\n                     libraries_private: ['-L${moduledir}/systems',\n                                         '-Wl,--whole-archive -ldirectfb_fbdev -Wl,--no-whole-archive'])\nendif\n"
  },
  {
    "path": "systems/nuttxfb/nuttxfb_layer.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/layers.h>\n\n#include \"nuttxfb_system.h\"\n\nD_DEBUG_DOMAIN( NuttXFB_Layer, \"NuttXFB/Layer\", \"NuttXFB Layer\" );\n\n/**********************************************************************************************************************/\n\nstatic DFBResult\nnuttxfbPrimaryInitLayer( CoreLayer                  *layer,\n                         void                       *driver_data,\n                         void                       *layer_data,\n                         DFBDisplayLayerDescription *description,\n                         DFBDisplayLayerConfig      *config,\n                         DFBColorAdjustment         *adjustment )\n{\n     NuttXFBData       *nuttxfb = driver_data;\n     NuttXFBDataShared *shared;\n\n     D_DEBUG_AT( NuttXFB_Layer, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( nuttxfb != NULL );\n     D_ASSERT( nuttxfb->shared != NULL );\n\n     shared = nuttxfb->shared;\n\n     /* Set type and capabilities. */\n     description->type = DLTF_GRAPHICS;\n     description->caps = DLCAPS_SURFACE;\n\n     /* Set name. */\n     snprintf( description->name, DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, \"NuttXFB Primary Layer\" );\n\n     /* Fill out the default configuration. */\n     config->flags       = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE;\n     config->width       = shared->mode.xres;\n     config->height      = shared->mode.yres;\n     config->pixelformat = dfb_pixelformat_for_depth( shared->mode.bpp );\n     config->buffermode  = DLBM_FRONTONLY;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nnuttxfbPrimaryTestRegion( CoreLayer                  *layer,\n                          void                       *driver_data,\n                          void                       *layer_data,\n                          CoreLayerRegionConfig      *config,\n                          CoreLayerRegionConfigFlags *ret_failed )\n{\n     CoreLayerRegionConfigFlags failed = CLRCF_NONE;\n\n     D_DEBUG_AT( NuttXFB_Layer, \"%s( %dx%d, %s )\\n\", __FUNCTION__,\n                 config->source.w, config->source.h, dfb_pixelformat_name( config->format ) );\n\n     switch (config->buffermode) {\n          case DLBM_FRONTONLY:\n          case DLBM_BACKSYSTEM:\n               break;\n\n          default:\n               failed |= CLRCF_BUFFERMODE;\n               break;\n     }\n\n     if (config->options)\n          failed |= CLRCF_OPTIONS;\n\n     if (ret_failed)\n          *ret_failed = failed;\n\n     if (failed)\n          return DFB_UNSUPPORTED;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nnuttxfbPrimarySetRegion( CoreLayer                  *layer,\n                         void                       *driver_data,\n                         void                       *layer_data,\n                         void                       *region_data,\n                         CoreLayerRegionConfig      *config,\n                         CoreLayerRegionConfigFlags  updated,\n                         CoreSurface                *surface,\n                         CorePalette                *palette,\n                         CoreSurfaceBufferLock      *left_lock,\n                         CoreSurfaceBufferLock      *right_lock )\n{\n     D_DEBUG_AT( NuttXFB_Layer, \"%s()\\n\", __FUNCTION__ );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nnuttxfbPrimaryUpdateRegion( CoreLayer             *layer,\n                            void                  *driver_data,\n                            void                  *layer_data,\n                            void                  *region_data,\n                            CoreSurface           *surface,\n                            const DFBRegion       *left_update,\n                            CoreSurfaceBufferLock *left_lock,\n                            const DFBRegion       *right_update,\n                            CoreSurfaceBufferLock *right_lock )\n{\n     D_DEBUG_AT( NuttXFB_Layer, \"%s()\\n\", __FUNCTION__ );\n\n     usleep( 1 );\n\n     return DFB_OK;\n}\n\nconst DisplayLayerFuncs nuttxfbPrimaryLayerFuncs = {\n     .InitLayer    = nuttxfbPrimaryInitLayer,\n     .TestRegion   = nuttxfbPrimaryTestRegion,\n     .SetRegion    = nuttxfbPrimarySetRegion,\n     .UpdateRegion = nuttxfbPrimaryUpdateRegion\n};\n"
  },
  {
    "path": "systems/nuttxfb/nuttxfb_screen.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/screens.h>\n\n#include \"nuttxfb_system.h\"\n\nD_DEBUG_DOMAIN( NuttXFB_Screen, \"NuttXFB/Screen\", \"NuttXFB Screen\" );\n\n/**********************************************************************************************************************/\n\nstatic DFBResult\nnuttxfbInitScreen( CoreScreen           *screen,\n                   void                 *driver_data,\n                   void                 *screen_data,\n                   DFBScreenDescription *description )\n{\n     NuttXFBData       *nuttxfb = driver_data;\n     NuttXFBDataShared *shared;\n\n     D_DEBUG_AT( NuttXFB_Screen, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( nuttxfb != NULL );\n     D_ASSERT( nuttxfb->shared != NULL );\n\n     shared = nuttxfb->shared;\n\n     /* Set name. */\n     snprintf( description->name, DFB_SCREEN_DESC_NAME_LENGTH, \"NuttX Screen\" );\n\n     D_INFO( \"NuttXFB/Screen: Default mode is %dx%d\\n\", shared->mode.xres, shared->mode.yres );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nnuttxfbGetScreenSize( CoreScreen *screen,\n                      void       *driver_data,\n                      void       *screen_data,\n                      int        *ret_width,\n                      int        *ret_height )\n{\n     NuttXFBData       *nuttxfb = driver_data;\n     NuttXFBDataShared *shared;\n\n     D_DEBUG_AT( NuttXFB_Screen, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( nuttxfb != NULL );\n     D_ASSERT( nuttxfb->shared != NULL );\n\n     shared = nuttxfb->shared;\n\n     *ret_width  = shared->mode.xres;\n     *ret_height = shared->mode.yres;\n\n     return DFB_OK;\n}\n\nconst ScreenFuncs nuttxfbScreenFuncs = {\n     .InitScreen    = nuttxfbInitScreen,\n     .GetScreenSize = nuttxfbGetScreenSize,\n};\n"
  },
  {
    "path": "systems/nuttxfb/nuttxfb_surface_pool.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/surface_buffer.h>\n#include <core/surface_pool.h>\n\n#include \"nuttxfb_system.h\"\n\nD_DEBUG_DOMAIN( NuttXFB_Surfaces, \"NuttXFB/Surfaces\", \"NuttXFB Surface Pool\" );\nD_DEBUG_DOMAIN( NuttXFB_SurfLock, \"NuttXFB/SurfLock\", \"NuttXFB Surface Pool Locks\" );\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     int          magic;\n\n     NuttXFBData *nuttxfb;\n} NuttXFBPoolLocalData;\n\n/**********************************************************************************************************************/\n\nstatic int\nnuttxfbPoolLocalDataSize( void )\n{\n     return sizeof(NuttXFBPoolLocalData);\n}\n\nstatic DFBResult\nnuttxfbInitPool( CoreDFB                    *core,\n                 CoreSurfacePool            *pool,\n                 void                       *pool_data,\n                 void                       *pool_local,\n                 void                       *system_data,\n                 CoreSurfacePoolDescription *ret_desc )\n{\n     NuttXFBPoolLocalData *local   = pool_local;\n     NuttXFBData          *nuttxfb = system_data;\n\n     D_DEBUG_AT( NuttXFB_Surfaces, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( core != NULL );\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_ASSERT( local != NULL );\n     D_ASSERT( nuttxfb != NULL );\n     D_ASSERT( ret_desc != NULL );\n\n     ret_desc->caps                 = CSPCAPS_PHYSICAL | CSPCAPS_VIRTUAL;\n     ret_desc->access[CSAID_CPU]    = CSAF_READ | CSAF_WRITE | CSAF_SHARED;\n     ret_desc->access[CSAID_LAYER0] = CSAF_READ;\n     ret_desc->types                = CSTF_LAYER | CSTF_WINDOW | CSTF_CURSOR | CSTF_FONT | CSTF_SHARED | CSTF_EXTERNAL;\n     ret_desc->priority             = CSPP_DEFAULT;\n\n     snprintf( ret_desc->name, DFB_SURFACE_POOL_DESC_NAME_LENGTH, \"NuttXFB Surface Pool\" );\n\n     local->nuttxfb = nuttxfb;\n\n     D_MAGIC_SET( local, NuttXFBPoolLocalData );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nnuttxfbJoinPool( CoreDFB         *core,\n                 CoreSurfacePool *pool,\n                 void            *pool_data,\n                 void            *pool_local,\n                 void            *system_data )\n{\n     NuttXFBPoolLocalData *local = pool_local;\n     NuttXFBData          *nuttxfb = system_data;\n\n     D_DEBUG_AT( NuttXFB_Surfaces, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( core != NULL );\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_ASSERT( local != NULL );\n     D_ASSERT( nuttxfb != NULL );\n\n     local->nuttxfb = nuttxfb;\n\n     D_MAGIC_SET( local, NuttXFBPoolLocalData );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nnuttxfbDestroyPool( CoreSurfacePool *pool,\n                    void            *pool_data,\n                    void            *pool_local )\n{\n     NuttXFBPoolLocalData *local = pool_local;\n\n     D_UNUSED_P( local );\n\n     D_DEBUG_AT( NuttXFB_Surfaces, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( local, NuttXFBPoolLocalData );\n\n     D_MAGIC_CLEAR( local );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nnuttxfbLeavePool( CoreSurfacePool *pool,\n                  void            *pool_data,\n                  void            *pool_local )\n{\n     NuttXFBPoolLocalData *local = pool_local;\n\n     D_UNUSED_P( local );\n\n     D_DEBUG_AT( NuttXFB_Surfaces, \"%s()\\n\", __FUNCTION__ );\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( local, NuttXFBPoolLocalData );\n\n     D_MAGIC_CLEAR( local );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nnuttxfbAllocateBuffer( CoreSurfacePool       *pool,\n                       void                  *pool_data,\n                       void                  *pool_local,\n                       CoreSurfaceBuffer     *buffer,\n                       CoreSurfaceAllocation *allocation,\n                       void                  *alloc_data )\n{\n     D_DEBUG_AT( NuttXFB_Surfaces, \"%s( %p )\\n\", __FUNCTION__, buffer );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nnuttxfbDeallocateBuffer( CoreSurfacePool       *pool,\n                         void                  *pool_data,\n                         void                  *pool_local,\n                         CoreSurfaceBuffer     *buffer,\n                         CoreSurfaceAllocation *allocation,\n                         void                  *alloc_data )\n{\n     D_DEBUG_AT( NuttXFB_Surfaces, \"%s( %p )\\n\", __FUNCTION__, buffer );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nnuttxfbLock( CoreSurfacePool       *pool,\n             void                  *pool_data,\n             void                  *pool_local,\n             CoreSurfaceAllocation *allocation,\n             void                  *alloc_data,\n             CoreSurfaceBufferLock *lock )\n{\n     NuttXFBPoolLocalData *local = pool_local;\n     NuttXFBData          *nuttxfb;\n\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( local, NuttXFBPoolLocalData );\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );\n\n     D_DEBUG_AT( NuttXFB_SurfLock, \"%s( %p, %p )\\n\", __FUNCTION__, allocation, lock->buffer );\n\n     nuttxfb = local->nuttxfb;\n     D_ASSERT( nuttxfb != NULL );\n\n     lock->pitch  = nuttxfb->planeinfo->stride;\n     lock->offset = ~0;\n     lock->addr   = nuttxfb->addr;\n     lock->phys   = (unsigned long) nuttxfb->planeinfo->fbmem;\n\n     D_DEBUG_AT( NuttXFB_SurfLock, \"  -> offset %lu, pitch %u, addr %p, phys 0x%08lx\\n\",\n                 lock->offset, lock->pitch, lock->addr, lock->phys );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nnuttxfbUnlock( CoreSurfacePool       *pool,\n               void                  *pool_data,\n               void                  *pool_local,\n               CoreSurfaceAllocation *allocation,\n               void                  *alloc_data,\n               CoreSurfaceBufferLock *lock )\n{\n     D_MAGIC_ASSERT( pool, CoreSurfacePool );\n     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );\n     D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );\n\n     D_DEBUG_AT( NuttXFB_SurfLock, \"%s( %p, %p )\\n\", __FUNCTION__, allocation, lock->buffer );\n\n     return DFB_OK;\n}\n\nconst SurfacePoolFuncs nuttxfbSurfacePoolFuncs = {\n     .PoolLocalDataSize = nuttxfbPoolLocalDataSize,\n     .InitPool          = nuttxfbInitPool,\n     .JoinPool          = nuttxfbJoinPool,\n     .DestroyPool       = nuttxfbDestroyPool,\n     .LeavePool         = nuttxfbLeavePool,\n     .AllocateBuffer    = nuttxfbAllocateBuffer,\n     .DeallocateBuffer  = nuttxfbDeallocateBuffer,\n     .Lock              = nuttxfbLock,\n     .Unlock            = nuttxfbUnlock,\n};\n"
  },
  {
    "path": "systems/nuttxfb/nuttxfb_system.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <core/core.h>\n#include <core/core_system.h>\n#include <core/layers.h>\n#include <core/screens.h>\n#include <core/surface_pool.h>\n#include <direct/system.h>\n#include <fusion/shmalloc.h>\n\n#include \"nuttxfb_system.h\"\n\nD_DEBUG_DOMAIN( NuttXFB_System, \"NuttXFB/System\", \"NuttXFB System Module\" );\n\nDFB_CORE_SYSTEM( nuttxfb )\n\n/**********************************************************************************************************************/\n\nextern const ScreenFuncs       nuttxfbScreenFuncs;\nextern const DisplayLayerFuncs nuttxfbPrimaryLayerFuncs;\nextern const SurfacePoolFuncs  nuttxfbSurfacePoolFuncs;\n\nstatic DFBResult\nlocal_init( const char  *device_name,\n            NuttXFBData *nuttxfb )\n{\n     CoreScreen *screen;\n\n     /* Open framebuffer device. */\n     nuttxfb->fd = open( device_name, O_RDWR );\n     if (nuttxfb->fd < 0) {\n          D_PERROR( \"NuttXFB/System: Failed to open '%s'!\\n\", device_name );\n          return DFB_INIT;\n     }\n\n     /* Retrieve plane information. */\n     nuttxfb->planeinfo = D_CALLOC( 1, sizeof(struct fb_planeinfo_s) );\n     if (!nuttxfb->planeinfo)\n          return D_OOM();\n\n     if (ioctl( nuttxfb->fd, FBIOGET_PLANEINFO, nuttxfb->planeinfo ) < 0) {\n          D_PERROR( \"NuttXFB/System: Could not retrieve plane information!\\n\" );\n          return DFB_INIT;\n     }\n\n     D_INFO( \"NuttXFB/System: Found display with framebuffer at %p, \"_ZU\"k\\n\",\n             nuttxfb->planeinfo->fbmem, nuttxfb->planeinfo->fblen >> 10 );\n\n     /* Map the framebuffer. */\n     nuttxfb->addr = mmap( NULL, nuttxfb->planeinfo->fblen, PROT_READ | PROT_WRITE, MAP_SHARED, nuttxfb->fd, 0 );\n     if (nuttxfb->addr == MAP_FAILED) {\n          D_PERROR( \"NuttXFB/System: Could not mmap the framebuffer!\\n\" );\n          return DFB_INIT;\n     }\n\n     screen = dfb_screens_register( nuttxfb, &nuttxfbScreenFuncs );\n\n     dfb_layers_register( screen, nuttxfb, &nuttxfbPrimaryLayerFuncs );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nlocal_deinit( NuttXFBData *nuttxfb )\n{\n     if (nuttxfb->addr)\n          munmap( nuttxfb->addr, nuttxfb->planeinfo->fblen );\n\n     if (nuttxfb->planeinfo)\n          D_FREE( nuttxfb->planeinfo );\n\n     if (nuttxfb->fd != -1)\n          close( nuttxfb->fd );\n\n     return DFB_OK;\n}\n\n/**********************************************************************************************************************/\n\nstatic void\nsystem_get_info( CoreSystemInfo *info )\n{\n     info->version.major = 0;\n     info->version.minor = 1;\n\n     info->caps = CSCAPS_ACCELERATION;\n\n     snprintf( info->name,   DFB_CORE_SYSTEM_INFO_NAME_LENGTH,   \"NuttXFB\" );\n     snprintf( info->vendor, DFB_CORE_SYSTEM_INFO_VENDOR_LENGTH, \"DirectFB\" );\n}\n\nstatic DFBResult\nsystem_initialize( CoreDFB  *core,\n                   void    **ret_data )\n{\n     DFBResult              ret;\n     struct fb_videoinfo_s  videoinfo;\n     NuttXFBData           *nuttxfb;\n     NuttXFBDataShared     *shared;\n     FusionSHMPoolShared   *pool;\n     const char            *value;\n\n     D_DEBUG_AT( NuttXFB_System, \"%s()\\n\", __FUNCTION__ );\n\n     nuttxfb = D_CALLOC( 1, sizeof(NuttXFBData) );\n     if (!nuttxfb)\n          return D_OOM();\n\n     nuttxfb->core = core;\n\n     pool = dfb_core_shmpool( core );\n\n     shared = SHCALLOC( pool, 1, sizeof(NuttXFBDataShared) );\n     if (!shared) {\n          D_FREE( nuttxfb );\n          return D_OOSHM();\n     }\n\n     shared->shmpool = pool;\n\n     nuttxfb->shared = shared;\n\n     if ((value = direct_config_get_value( \"nuttxfb\" ))) {\n          direct_snputs( shared->device_name, value, 255 );\n          D_INFO( \"NuttXFB/System: Using device %s as specified in DirectFB configuration\\n\", shared->device_name );\n     }\n     else if (getenv( \"FRAMEBUFFER\" ) && *direct_getenv( \"FRAMEBUFFER\" ) != '\\0') {\n          direct_snputs( shared->device_name, direct_getenv( \"FRAMEBUFFER\" ), 255 );\n          D_INFO( \"NuttXFB/System: Using device %s as set in FRAMEBUFFER environment variable\\n\", shared->device_name );\n     }\n     else {\n          snprintf( shared->device_name, 255, \"/dev/fb0\" );\n          D_INFO( \"NuttXFB/System: Using device %s (default)\\n\", shared->device_name );\n     }\n\n     ret = local_init( shared->device_name, nuttxfb );\n     if (ret)\n          goto error;\n\n     if (ioctl( nuttxfb->fd, FBIOGET_VIDEOINFO, &videoinfo ) < 0) {\n          D_PERROR( \"NuttXFB/System: Could not get video information!\\n\" );\n          ret = DFB_INIT;\n          goto error;\n     }\n\n     shared->mode.xres = videoinfo.xres;\n     shared->mode.yres = videoinfo.yres;\n     shared->mode.bpp  = nuttxfb->planeinfo->bpp;\n\n     *ret_data = nuttxfb;\n\n     ret = dfb_surface_pool_initialize( core, &nuttxfbSurfacePoolFuncs, &shared->pool );\n     if (ret)\n          goto error;\n\n     ret = core_arena_add_shared_field( core, \"nuttxfb\", shared );\n     if (ret)\n          goto error;\n\n     return DFB_OK;\n\nerror:\n     local_deinit( nuttxfb );\n\n     SHFREE( pool, shared );\n\n     D_FREE( nuttxfb );\n\n     return ret;\n}\n\nstatic DFBResult\nsystem_join( CoreDFB  *core,\n             void    **ret_data )\n{\n     DFBResult          ret;\n     NuttXFBData       *nuttxfb;\n     NuttXFBDataShared *shared;\n\n     D_DEBUG_AT( NuttXFB_System, \"%s()\\n\", __FUNCTION__ );\n\n     nuttxfb = D_CALLOC( 1, sizeof(NuttXFBData) );\n     if (!nuttxfb)\n          return D_OOM();\n\n     nuttxfb->core = core;\n\n     ret = core_arena_get_shared_field( core, \"nuttxfb\", (void**) &shared );\n     if (ret) {\n          D_FREE( nuttxfb );\n          return ret;\n     }\n\n     nuttxfb->shared = shared;\n\n     ret = local_init( shared->device_name, nuttxfb );\n     if (ret)\n          goto error;\n\n     *ret_data = nuttxfb;\n\n     ret = dfb_surface_pool_join( core, shared->pool, &nuttxfbSurfacePoolFuncs );\n     if (ret)\n          goto error;\n\n     return DFB_OK;\n\nerror:\n     local_deinit( nuttxfb );\n\n     D_FREE( nuttxfb );\n\n     return ret;\n}\n\nstatic DFBResult\nsystem_shutdown( bool emergency )\n{\n     NuttXFBData       *nuttxfb = dfb_system_data();\n     NuttXFBDataShared *shared;\n\n     D_DEBUG_AT( NuttXFB_System, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( nuttxfb != NULL );\n     D_ASSERT( nuttxfb->shared != NULL );\n\n     shared = nuttxfb->shared;\n\n     dfb_surface_pool_destroy( shared->pool );\n\n     local_deinit( nuttxfb );\n\n     SHFREE( shared->shmpool, shared );\n\n     D_FREE( nuttxfb );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsystem_leave( bool emergency )\n{\n     NuttXFBData       *nuttxfb = dfb_system_data();\n     NuttXFBDataShared *shared;\n\n     D_DEBUG_AT( NuttXFB_System, \"%s()\\n\", __FUNCTION__ );\n\n     D_ASSERT( nuttxfb != NULL );\n     D_ASSERT( nuttxfb->shared != NULL );\n\n     shared = nuttxfb->shared;\n\n     dfb_surface_pool_leave( shared->pool );\n\n     local_deinit( nuttxfb );\n\n     D_FREE( nuttxfb );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nsystem_suspend()\n{\n     return DFB_OK;\n}\n\nstatic DFBResult\nsystem_resume()\n{\n     return DFB_OK;\n}\n\nstatic VideoMode *\nsystem_get_modes()\n{\n     NuttXFBData       *nuttx = dfb_system_data();\n     NuttXFBDataShared *shared;\n\n     D_ASSERT( nuttx != NULL );\n     D_ASSERT( nuttx->shared != NULL );\n\n     shared = nuttx->shared;\n\n     return &shared->mode;\n}\n\nstatic VideoMode *\nsystem_get_current_mode()\n{\n     NuttXFBData       *nuttx = dfb_system_data();\n     NuttXFBDataShared *shared;\n\n     D_ASSERT( nuttx != NULL );\n     D_ASSERT( nuttx->shared != NULL );\n\n     shared = nuttx->shared;\n\n     return &shared->mode;\n}\n\nstatic DFBResult\nsystem_thread_init()\n{\n     return DFB_OK;\n}\n\nstatic bool\nsystem_input_filter( CoreInputDevice *device,\n                     DFBInputEvent   *event )\n{\n     return false;\n}\n\nstatic volatile void *\nsystem_map_mmio( unsigned int offset,\n                 int          length )\n{\n     return NULL;\n}\n\nstatic void\nsystem_unmap_mmio( volatile void *addr,\n                   int            length )\n{\n}\n\nstatic unsigned int\nsystem_get_accelerator()\n{\n     return direct_config_get_int_value( \"accelerator\" );\n}\n\nstatic unsigned long\nsystem_video_memory_physical( unsigned int offset )\n{\n     NuttXFBData *nuttxfb = dfb_system_data();\n\n     D_ASSERT( nuttxfb != NULL );\n\n     return (unsigned long) nuttxfb->planeinfo->fbmem;\n}\n\nstatic void *\nsystem_video_memory_virtual( unsigned int offset )\n{\n     NuttXFBData *nuttxfb = dfb_system_data();\n\n     D_ASSERT( nuttxfb != NULL );\n\n     return nuttxfb->addr + offset;\n}\n\nstatic unsigned int\nsystem_videoram_length()\n{\n     NuttXFBData *nuttxfb = dfb_system_data();\n\n     D_ASSERT( nuttxfb != NULL );\n\n     return nuttxfb->planeinfo->fblen;\n}\n\nstatic void\nsystem_get_busid( int *ret_bus,\n                  int *ret_dev,\n                  int *ret_func )\n{\n     return;\n}\n\nstatic void\nsystem_get_deviceid( unsigned int *ret_vendor_id,\n                     unsigned int *ret_device_id )\n{\n     return;\n}\n"
  },
  {
    "path": "systems/nuttxfb/nuttxfb_system.h",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#ifndef __NUTTXFB_SYSTEM_H__\n#define __NUTTXFB_SYSTEM_H__\n\n#include <core/coretypes.h>\n#include <core/video_mode.h>\n#include <fusion/types.h>\n#include <nuttx/video/fb.h>\n\n/**********************************************************************************************************************/\n\ntypedef struct {\n     FusionSHMPoolShared *shmpool;\n\n     CoreSurfacePool     *pool;\n\n     char                 device_name[256]; /* NuttXFB device name, e.g. /dev/fb0 */\n\n     VideoMode            mode;             /* current video mode */\n} NuttXFBDataShared;\n\ntypedef struct {\n     NuttXFBDataShared     *shared;\n\n     CoreDFB               *core;\n\n     int                    fd;        /* framebuffer file descriptor */\n\n     struct fb_planeinfo_s *planeinfo; /* plane information */\n\n     void                  *addr;      /* framebuffer memory address */\n} NuttXFBData;\n\n#endif\n"
  },
  {
    "path": "wm/default/default.c",
    "content": "/*\n   This file is part of DirectFB.\n\n   This library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   This library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with this library; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n*/\n\n#include <config.h>\n#include <core/CoreGraphicsStateClient.h>\n#include <core/core.h>\n#include <core/layer_context.h>\n#include <core/palette.h>\n#include <core/state.h>\n#include <core/windows.h>\n#include <core/windowstack.h>\n#include <core/wm_module.h>\n#include <direct/memcpy.h>\n#include <fusion/conf.h>\n#include <fusion/shmalloc.h>\n#include <gfx/util.h>\n\nD_DEBUG_DOMAIN( Default_WM, \"WM/Default\", \"Default Window Manager Module\" );\n\nDFB_WINDOW_MANAGER( default )\n\n/**********************************************************************************************************************/\n\n#define MAX_UPDATE_REGIONS    8 /* dirty region */\n#define MAX_UPDATING_REGIONS  8 /* updated region to be scheduled for display */\n#define MAX_UPDATED_REGIONS   8 /* updated region scheduled for display */\n#define MAX_KEYS             16 /* maximum number of grabbed keys */\n\ntypedef struct {\n     DirectLink                  link;\n\n     DFBInputDeviceKeySymbol     symbol;\n     DFBInputDeviceModifierMask  modifiers;\n\n     CoreWindow                 *owner;\n} GrabbedKey;\n\ntypedef struct {\n     CoreDFB                 *core;\n\n     int                      refs;\n\n     CardState                state;\n     CoreGraphicsStateClient  client;\n} WMData;\n\ntypedef struct {\n     int                               magic;\n\n     CoreWindowStack                  *stack;\n\n     DFBUpdates                        updates;\n     DFBRegion                         update_regions[MAX_UPDATE_REGIONS];\n\n     DFBUpdates                        updating;\n     DFBRegion                         updating_regions[MAX_UPDATING_REGIONS];\n\n     DFBUpdates                        updated;\n     DFBRegion                         updated_regions[MAX_UPDATED_REGIONS];\n\n     DFBInputDeviceButtonMask          buttons;\n     DFBInputDeviceModifierMask        modifiers;\n     DFBInputDeviceLockState           locks;\n\n     bool                              active;\n\n     int                               wm_level;\n     int                               wm_cycle;\n\n     FusionVector                      windows;\n\n     CoreWindow                       *pointer_window;        /* window grabbing the pointer */\n     CoreWindow                       *keyboard_window;       /* window grabbing the keyboard */\n     CoreWindow                       *focused_window;        /* window having the focus */\n     CoreWindow                       *entered_window;        /* window under the pointer */\n     CoreWindow                       *unselkeys_window;      /* window grabbing unselected keys */\n\n     DirectLink                       *grabbed_keys;          /* list of currently grabbed keys */\n\n     struct {\n          DFBInputDeviceKeySymbol      symbol;\n          DFBInputDeviceKeyIdentifier  id;\n          int                          code;\n          CoreWindow                  *owner;\n     } keys[MAX_KEYS];                                        /* grabbed keys */\n\n     CoreSurface                      *cursor_bs;             /* backing store for region under cursor */\n     bool                              cursor_bs_valid;       /* valid backing store under cursor */\n     DFBRegion                         cursor_region;\n     bool                              cursor_drawn;\n\n     int                               cursor_dx;\n     int                               cursor_dy;\n\n     CoreLayerRegion                  *region;\n     CoreSurface                      *surface;\n     Reaction                          surface_reaction;\n     FusionSkirmish                    update_skirmish;\n     bool                              wm_fullscreen_updates; /* force fullscreen updates in window manager */\n} StackData;\n\ntypedef struct {\n     int                    magic;\n\n     CoreWindow            *window;\n\n     StackData             *stack_data;\n\n     int                    priority;\n\n     CoreLayerRegionConfig  config;\n} WindowData;\n\n/**********************************************************************************************************************/\n\nstatic int\nget_index( const StackData  *data,\n           const CoreWindow *window )\n{\n     D_ASSERT( data != NULL );\n     D_ASSERT( window != NULL );\n\n     D_ASSERT( fusion_vector_contains( &data->windows, window ) );\n\n     return fusion_vector_index_of( &data->windows, window );\n}\n\nstatic int\nget_priority( const CoreWindow *window )\n{\n     D_ASSERT( window != NULL );\n\n     switch (window->config.stacking) {\n          case DWSC_UPPER:\n               return  1;\n\n          case DWSC_MIDDLE:\n               return  0;\n\n          case DWSC_LOWER:\n               return -1;\n\n          default:\n               D_BUG( \"unknown stacking class\" );\n               break;\n     }\n\n     return 0;\n}\n\nstatic void\ntransform_stack_to_dest( CoreWindowStack *stack,\n                         const DFBRegion *region,\n                         DFBRegion       *ret_dest )\n{\n     DFBDimension size = { stack->width, stack->height };\n\n     D_ASSERT( stack != NULL );\n     DFB_REGION_ASSERT( region );\n     D_ASSERT( ret_dest != NULL );\n\n     dfb_region_from_rotated( ret_dest, region, &size, stack->rotation );\n}\n\nstatic void\ntransform_point_in_window( CoreWindow *window,\n                           int        *x,\n                           int        *y )\n{\n     int _x = *x, _y = *y;\n\n     D_ASSERT( window != NULL );\n\n     switch (window->config.rotation) {\n          default:\n               D_BUG( \"invalid rotation %d\", window->config.rotation );\n          case 0:\n               break;\n\n          case 90:\n               *x = window->config.bounds.w - _y - 1;\n               *y = _x;\n               break;\n\n          case 180:\n               *x = window->config.bounds.w - _x - 1;\n               *y = window->config.bounds.h - _y - 1;\n               break;\n\n          case 270:\n               *x = _y;\n               *y = window->config.bounds.h - _x - 1;\n               break;\n     }\n}\n\nstatic void\ntransform_window_to_stack( CoreWindow         *window,\n                           const DFBRectangle *rect,\n                           DFBRectangle       *ret_rect )\n{\n     D_ASSERT( window != NULL );\n     DFB_RECTANGLE_ASSERT( rect );\n     D_ASSERT( ret_rect != NULL );\n\n     ret_rect->x = rect->x;\n     ret_rect->y = rect->y;\n\n     switch (window->config.rotation) {\n          default:\n               D_BUG( \"invalid rotation %d\", window->config.rotation );\n          case 0:\n          case 180:\n               ret_rect->w = rect->w;\n               ret_rect->h = rect->h;\n               break;\n\n          case 90:\n          case 270:\n               ret_rect->w = rect->h;\n               ret_rect->h = rect->w;\n               break;\n     }\n}\n\nstatic void\npost_event( CoreWindow     *window,\n            StackData      *data,\n            DFBWindowEvent *evt )\n{\n     D_ASSERT( window != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( evt != NULL );\n\n     evt->buttons   = data->buttons;\n     evt->modifiers = data->modifiers;\n     evt->locks     = data->locks;\n     evt->cx        = data->stack->cursor.x;\n     evt->cy        = data->stack->cursor.y;\n\n     dfb_window_post_event( window, evt );\n}\n\nstatic void\nsend_key_event( CoreWindow          *window,\n                StackData           *data,\n                const DFBInputEvent *event )\n{\n     DFBWindowEvent we;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( event != NULL );\n\n     we.type       = (event->type == DIET_KEYPRESS) ? DWET_KEYDOWN : DWET_KEYUP;\n     we.flags      = (event->flags & DIEF_REPEAT) ? DWEF_REPEAT : 0;\n     we.key_code   = event->key_code;\n     we.key_id     = event->key_id;\n     we.key_symbol = event->key_symbol;\n\n     post_event( window, data, &we );\n}\n\nstatic void\nsend_button_event( CoreWindow          *window,\n                   StackData           *data,\n                   const DFBInputEvent *event )\n{\n     DFBWindowEvent we;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( event != NULL );\n\n     we.type   = (event->type == DIET_BUTTONPRESS) ? DWET_BUTTONDOWN : DWET_BUTTONUP;\n     we.x      = window->stack->cursor.x - window->config.bounds.x;\n     we.y      = window->stack->cursor.y - window->config.bounds.y;\n     we.button = (data->wm_level & 2) ? (event->button + 2) : event->button;\n\n     transform_point_in_window( window, &we.x, &we.y );\n\n     post_event( window, data, &we );\n}\n\nstatic void\nsend_update_event( CoreWindow      *window,\n                   StackData       *data,\n                   const DFBRegion *update )\n{\n     DFBWindowEvent we;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( update != NULL );\n\n     we.type = DWET_UPDATE;\n     we.x    = update->x1;\n     we.y    = update->y1;\n     we.w    = update->x2 - update->x1 + 1;\n     we.h    = update->y2 - update->y1 + 1;\n\n     post_event( window, data, &we );\n}\n\nstatic int\nkeys_compare( const void *key1,\n              const void *key2 )\n{\n     return *(const DFBInputDeviceKeySymbol*) key1 - *(const DFBInputDeviceKeySymbol*) key2;\n}\n\nstatic CoreWindow *\nget_keyboard_window( CoreWindowStack     *stack,\n                     StackData           *data,\n                     const DFBInputEvent *event )\n{\n     GrabbedKey *key;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( event != NULL );\n     D_ASSERT( event->type == DIET_KEYPRESS || event->type == DIET_KEYRELEASE );\n\n     /* Check explicit key grabs first. */\n     direct_list_foreach (key, data->grabbed_keys) {\n          if (key->symbol    == event->key_symbol &&\n              key->modifiers == data->modifiers)\n               return key->owner;\n     }\n\n     /* Don't do implicit grabs on keys without a hardware index. */\n     if (event->key_code == -1)\n          return data->keyboard_window ?: data->focused_window;\n\n     /* Implicitly grab (press) or ungrab (release) key. */\n     if (event->type == DIET_KEYPRESS) {\n          int         i;\n          int         free_key = -1;\n          CoreWindow *window;\n\n          /* Check active grabs. */\n          for (i = 0; i < MAX_KEYS; i++) {\n               /* Key is grabbed, send to owner (NULL if destroyed). */\n               if (data->keys[i].code == event->key_code)\n                    return data->keys[i].owner;\n\n               /* Remember first free array item. */\n               if (free_key == -1 && data->keys[i].code == -1)\n                    free_key = i;\n          }\n\n          /* Key is not grabbed, check for explicit keyboard grab or focus. */\n          window = data->keyboard_window ?: data->focused_window;\n          if (!window)\n               return NULL;\n\n          /* Check key selection. */\n          switch (window->config.key_selection) {\n               case DWKS_ALL:\n                    break;\n\n               case DWKS_LIST:\n                    D_ASSERT( window->config.keys != NULL );\n                    D_ASSERT( window->config.num_keys > 0 );\n\n                    if (bsearch( &event->key_symbol, window->config.keys, window->config.num_keys,\n                                 sizeof(DFBInputDeviceKeySymbol), keys_compare ))\n                         break;\n                    /* fall through */\n\n               case DWKS_NONE:\n                    return data->unselkeys_window;\n          }\n\n          /* Check if a free array item was found. */\n          if (free_key == -1) {\n               D_WARN( \"maximum number of owned keys reached\" );\n               return NULL;\n          }\n\n          /* Implicitly grab the key. */\n          data->keys[free_key].symbol = event->key_symbol;\n          data->keys[free_key].id     = event->key_id;\n          data->keys[free_key].code   = event->key_code;\n          data->keys[free_key].owner  = window;\n\n          return window;\n     }\n     else {\n          int i;\n\n          /* Lookup owner and ungrab the key. */\n          for (i = 0; i < MAX_KEYS; i++) {\n               if (data->keys[i].code == event->key_code) {\n                    data->keys[i].code = -1;\n\n                    /* Return owner (NULL if destroyed). */\n                    return data->keys[i].owner;\n               }\n          }\n     }\n\n     /* No owner for release event found, discard it. */\n     return NULL;\n}\n\nstatic CoreWindow*\nwindow_at_pointer( CoreWindowStack *stack,\n                   StackData       *data,\n                   int              x,\n                   int              y )\n{\n     int         i;\n     CoreWindow *window;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( data != NULL );\n\n     if (!stack->cursor.enabled) {\n          fusion_vector_foreach_reverse (window, i, data->windows)\n               if (window->config.opacity && !(window->config.options & DWOP_GHOST))\n                    return window;\n\n          return NULL;\n     }\n\n     if (x < 0)\n          x = stack->cursor.x;\n     if (y < 0)\n          y = stack->cursor.y;\n\n     fusion_vector_foreach_reverse (window, i, data->windows) {\n          CoreWindowConfig *config  = &window->config;\n          DFBWindowOptions  options = config->options;\n          DFBRectangle      rotated;\n          DFBRectangle     *bounds  = &rotated;\n\n          transform_window_to_stack( window, &config->bounds, &rotated );\n\n          if (!(options & DWOP_GHOST)                     &&\n              config->opacity                             &&\n              x >= bounds->x && x < bounds->x + bounds->w &&\n              y >= bounds->y && y < bounds->y + bounds->h) {\n               int wx = x - bounds->x;\n               int wy = y - bounds->y;\n\n               if (!(options & DWOP_SHAPED)                           ||\n                   !(options &(DWOP_ALPHACHANNEL | DWOP_COLORKEYING)) ||\n                   !window->surface                                   ||\n                   ((options & DWOP_OPAQUE_REGION)                      &&\n                    (wx >= config->opaque.x1 && wx <= config->opaque.x2 &&\n                     wy >= config->opaque.y1 && wy <= config->opaque.y2))) {\n                    return window;\n               }\n               else {\n                    u8                     buf[8];\n                    u16                    word;\n                    u32                    dword;\n                    CoreSurface           *surface = window->surface;\n                    DFBSurfacePixelFormat  format  = surface->config.format;\n                    DFBRectangle           rect    = { wx, wy, 1, 1 };\n\n                    if (dfb_surface_read_buffer( surface, DSBR_FRONT, buf, 8, &rect ) == DFB_OK) {\n                         if (options & DWOP_ALPHACHANNEL) {\n                              int alpha = -1;\n\n                              D_ASSERT( DFB_PIXELFORMAT_HAS_ALPHA( format ) );\n\n                              switch (format) {\n                                   case DSPF_AiRGB:\n                                        direct_memcpy( &dword, buf, 4 );\n                                        alpha = 0xff - (dword >> 24);\n                                        break;\n                                   case DSPF_ARGB:\n                                   case DSPF_ABGR:\n                                   case DSPF_AYUV:\n                                   case DSPF_AVYU:\n                                        direct_memcpy( &dword, buf, 4 );\n                                        alpha = dword >> 24;\n                                        break;\n                                   case DSPF_ARGB8565:\n#ifdef WORDS_BIGENDIAN\n                                        alpha = buf[0];\n#else\n                                        alpha = buf[2];\n#endif\n                                        break;\n                                   case DSPF_RGBA5551:\n                                        direct_memcpy( &word, buf, 2 );\n                                        alpha = word & 0x1;\n                                        alpha = alpha ? 0xff : 0x00;\n                                        break;\n                                   case DSPF_ARGB1555:\n                                   case DSPF_ARGB2554:\n                                   case DSPF_ARGB4444:\n                                        direct_memcpy( &word, buf, 2 );\n                                        alpha = word & 0x8000;\n                                        alpha = alpha ? 0xff : 0x00;\n                                        break;\n                                   case DSPF_RGBA4444:\n                                        direct_memcpy( &word, buf, 2 );\n                                        alpha = word & 0x0008;\n                                        alpha = alpha ? 0xff : 0x00;\n                                        break;\n                                   case DSPF_RGBAF88871:\n                                        direct_memcpy( &dword, buf, 4 );\n                                        alpha = dword & 0x000000fe;\n                                        alpha |= alpha >> 7;\n                                        break;\n                                   case DSPF_ALUT44:\n                                        alpha = *buf & 0xf0;\n                                        alpha |= alpha >> 4;\n                                        break;\n                                   case DSPF_LUT1:\n                                   case DSPF_LUT2:\n                                   case DSPF_LUT8: {\n                                        CorePalette *palette = surface->palette;\n                                        u8           pix     = *buf;\n\n                                        if (palette && pix < palette->num_entries) {\n                                             alpha = palette->entries[pix].a;\n                                             break;\n                                        }\n                                        /* fall through */\n                                   }\n                                   default:\n                                        D_ONCE( \"unknown format 0x%x\", (unsigned int) surface->config.format );\n                                        break;\n                              }\n\n                              if (alpha)\n                                   return window;\n                         }\n\n                         if (options & DWOP_COLORKEYING) {\n                              int pixel = 0;\n\n                              switch (format) {\n                                   case DSPF_ARGB:\n                                   case DSPF_ABGR:\n                                   case DSPF_AiRGB:\n                                   case DSPF_RGB32:\n                                        direct_memcpy( &dword, buf, 4 );\n                                        pixel = dword & 0x00ffffff;\n                                        break;\n                                   case DSPF_RGBAF88871:\n                                        direct_memcpy( &dword, buf, 4 );\n                                        pixel = dword & 0xffffff00;\n                                        break;\n                                   case DSPF_RGB24:\n#ifdef WORDS_BIGENDIAN\n                                        pixel = (buf[0] << 16) | (buf[1] << 8) | buf[2];\n#else\n                                        pixel = (buf[2] << 16) | (buf[1] << 8) | buf[0];\n#endif\n                                        break;\n                                   case DSPF_RGB16:\n                                        direct_memcpy( &word, buf, 2 );\n                                        pixel = word;\n                                        break;\n                                   case DSPF_ARGB4444:\n                                   case DSPF_RGB444:\n                                        direct_memcpy( &word, buf, 2 );\n                                        pixel = word & 0x0fff;\n                                        break;\n                                   case DSPF_RGBA4444:\n                                        direct_memcpy( &word, buf, 2 );\n                                        pixel = word & 0xfff0;\n                                        break;\n                                   case DSPF_ARGB8565:\n#ifdef WORDS_BIGENDIAN\n                                        pixel = buf[1] << 8 | buf[2];\n#else\n                                        pixel = buf[1] << 8 | buf[0];\n#endif\n                                        break;\n                                   case DSPF_ARGB1555:\n                                   case DSPF_RGB555:\n                                   case DSPF_BGR555:\n                                        direct_memcpy( &word, buf, 2 );\n                                        pixel = word & 0x7fff;\n                                        break;\n                                   case DSPF_RGBA5551:\n                                        direct_memcpy( &word, buf, 2 );\n                                        pixel = word & 0xfffe;\n                                        break;\n                                   case DSPF_RGB332:\n                                   case DSPF_LUT8:\n                                        pixel = *buf;\n                                        break;\n                                   case DSPF_ALUT44:\n                                        pixel = *buf & 0x0f;\n                                        break;\n                                   default:\n                                        D_ONCE( \"unknown format 0x%x\", (unsigned int) surface->config.format );\n                                        break;\n                              }\n\n                              if (pixel != config->color_key)\n                                   return window;\n                         }\n                    }\n               }\n          }\n     }\n\n     return NULL;\n}\n\nstatic void\nswitch_focus( WMData          *wmdata,\n              CoreWindowStack *stack,\n              StackData       *data,\n              CoreWindow      *to )\n{\n     DFBWindowEvent  we;\n     CoreWindow     *from;\n\n     D_ASSERT( wmdata != NULL );\n     D_ASSERT( stack != NULL );\n     D_ASSERT( data != NULL );\n\n     from = data->focused_window;\n\n     if (from == to)\n          return;\n\n     if (to && to->caps & DWCAPS_NOFOCUS)\n          return;\n\n     if (from) {\n          if (from->cursor.surface && !(from->config.cursor_flags & DWCF_INVISIBLE) &&\n              (!to || !to->cursor.surface || (to->cursor.surface && (to->config.cursor_flags & DWCF_INVISIBLE)))) {\n               CoreSurface *shape;\n               int          hot_x, hot_y;\n\n               dfb_layer_context_get_cursor_shape( stack->context, &shape, &hot_x, &hot_y );\n\n               dfb_windowstack_cursor_set_shape( stack, shape, hot_x, hot_y );\n          }\n\n          we.type = DWET_LOSTFOCUS;\n\n          post_event( from, data, &we );\n     }\n\n     if (to) {\n          if (to->surface && to->surface->palette && !stack->hw_mode) {\n               CoreSurface *surface;\n\n               D_ASSERT( to->primary_region != NULL );\n\n               if (dfb_layer_region_get_surface( to->primary_region, &surface ) == DFB_OK) {\n                    if (DFB_PIXELFORMAT_IS_INDEXED( surface->config.format ))\n                         dfb_surface_set_palette( surface, to->surface->palette );\n\n                    dfb_surface_unref( surface );\n               }\n          }\n\n          if (to->cursor.surface && !(to->config.cursor_flags & DWCF_INVISIBLE))\n               dfb_windowstack_cursor_set_shape( stack, to->cursor.surface, to->cursor.hot_x, to->cursor.hot_y );\n\n          we.type = DWET_GOTFOCUS;\n\n          post_event( to, data, &we );\n\n          /* Send notification to windows watchers. */\n          dfb_wm_dispatch_WindowFocus( wmdata->core, to );\n     }\n\n     data->focused_window = to;\n}\n\nstatic DFBResult\nrequest_focus( WMData     *wmdata,\n               CoreWindow *window,\n               WindowData *win )\n{\n     StackData  *data;\n     CoreWindow *entered;\n\n     D_ASSERT( wmdata != NULL );\n     D_ASSERT( window != NULL );\n     D_ASSERT( !(window->config.options & DWOP_GHOST) );\n     D_ASSERT( win != NULL );\n     D_ASSERT( win->stack_data != NULL );\n\n     data = win->stack_data;\n\n     /* Switch focus. */\n     switch_focus( wmdata, data->stack, data, window );\n\n     entered = data->entered_window;\n\n     /* Send leave event. */\n     if (entered && entered != window) {\n          DFBWindowEvent we;\n\n          we.type = DWET_LEAVE;\n          we.x    = data->stack->cursor.x - entered->config.bounds.x;\n          we.y    = data->stack->cursor.y - entered->config.bounds.y;\n\n          transform_point_in_window( entered, &we.x, &we.y );\n\n          post_event( entered, data, &we );\n\n          data->entered_window = NULL;\n     }\n\n     return DFB_OK;\n}\n\nstatic bool\nupdate_focus( CoreWindowStack *stack,\n              StackData       *data,\n              WMData          *wmdata )\n{\n     D_ASSERT( stack != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( wmdata != NULL );\n\n     /* Pointer is not grabbed. */\n     if (!data->pointer_window) {\n          CoreWindow *before = data->entered_window;\n          CoreWindow *after  = window_at_pointer( stack, data, -1, -1 );\n\n          /* The window under the cursor is another now. */\n          if (before != after) {\n               DFBWindowEvent we;\n\n               /* Send leave event. */\n               if (before) {\n                    we.type = DWET_LEAVE;\n                    we.x    = stack->cursor.x - before->config.bounds.x;\n                    we.y    = stack->cursor.y - before->config.bounds.y;\n\n                    transform_point_in_window( before, &we.x, &we.y );\n\n                    post_event( before, data, &we );\n               }\n\n               /* Switch focus. */\n               switch_focus( wmdata, stack, data, after );\n\n               /* Send enter event. */\n               if (after) {\n                    we.type = DWET_ENTER;\n                    we.x    = stack->cursor.x - after->config.bounds.x;\n                    we.y    = stack->cursor.y - after->config.bounds.y;\n\n                    transform_point_in_window( after, &we.x, &we.y );\n\n                    post_event( after, data, &we );\n               }\n\n               /* Update pointer to window under the cursor. */\n               data->entered_window = after;\n\n               return true;\n          }\n     }\n\n     return false;\n}\n\nstatic void\ndraw_cursor( CoreWindowStack *stack,\n             CardState       *state,\n             const DFBRegion *region )\n{\n     DFBRectangle            src;\n     DFBRegion               dest;\n     DFBSurfaceBlittingFlags flags = DSBLIT_BLEND_ALPHACHANNEL;\n\n     D_ASSERT( stack != NULL );\n     D_MAGIC_ASSERT( state, CardState );\n     DFB_REGION_ASSERT( region );\n\n     D_ASSUME( stack->cursor.opacity > 0 );\n\n     /* Initialize destination region. */\n     transform_stack_to_dest( stack, region, &dest );\n\n     /* Initialize source rectangle. */\n     src.x = region->x1 - stack->cursor.x + stack->cursor.hot.x;\n     src.y = region->y1 - stack->cursor.y + stack->cursor.hot.y;\n     src.w = region->x2 - region->x1 + 1;\n     src.h = region->y2 - region->y1 + 1;\n\n     /* Use global alpha blending. */\n     if (stack->cursor.opacity != 0xff) {\n          flags |= DSBLIT_BLEND_COLORALPHA;\n\n          /* Set opacity as blending factor. */\n          if (state->color.a != stack->cursor.opacity) {\n               state->color.a   = stack->cursor.opacity;\n               state->modified |= SMF_COLOR;\n          }\n     }\n\n     /* Different compositing methods depending on destination format. */\n     if (flags & DSBLIT_BLEND_ALPHACHANNEL) {\n          if (DFB_PIXELFORMAT_HAS_ALPHA( state->destination->config.format )) {\n               dfb_state_set_src_blend( state, DSBF_ONE );\n\n               if (!(stack->cursor.surface->config.caps & DSCAPS_PREMULTIPLIED))\n                    flags |= DSBLIT_SRC_PREMULTIPLY;\n               else if (flags & DSBLIT_BLEND_COLORALPHA)\n                    flags |= DSBLIT_SRC_PREMULTCOLOR;\n          }\n          else {\n               if (stack->cursor.surface->config.caps & DSCAPS_PREMULTIPLIED) {\n                    if (flags & DSBLIT_BLEND_COLORALPHA)\n                         flags |= DSBLIT_SRC_PREMULTCOLOR;\n\n                    dfb_state_set_src_blend( state, DSBF_ONE );\n               }\n               else\n                    dfb_state_set_src_blend( state, DSBF_SRCALPHA );\n          }\n     }\n\n     /* Set blitting flags. */\n     dfb_state_set_blitting_flags( state, flags | stack->rotated_blit );\n\n     /* Set blitting source. */\n     state->source    = stack->cursor.surface;\n     state->modified |= SMF_SOURCE;\n\n     /* Blit from the window to the region being updated. */\n     DFBPoint point = { dest.x1, dest.y1 };\n     CoreGraphicsStateClient_Blit( state->client, &src, &point, 1 );\n\n     /* Reset blitting source. */\n     state->source    = NULL;\n     state->modified |= SMF_SOURCE;\n}\n\nstatic void\ndraw_window( CoreWindow      *window,\n             CardState       *state,\n             const DFBRegion *region,\n             bool             alpha_channel )\n{\n     DFBRegion                dest;\n     DFBSurfaceBlittingFlags  flags = DSBLIT_NOFX;\n     CoreWindowConfig        *config;\n     CoreSurface             *surface;\n     int                      rotation;\n\n     D_ASSERT( window != NULL );\n     D_MAGIC_ASSERT( state, CardState );\n     DFB_REGION_ASSERT( region );\n\n     config  = &window->config;\n     surface = window->surface;\n\n     if (window->caps & DWCAPS_COLOR) {\n          D_ONCE( \"colorized windows not supported\" );\n          return;\n     }\n\n     /* Initialize destination region. */\n     transform_stack_to_dest( window->stack, region, &dest );\n\n     /* Use per pixel alpha blending. */\n     if (alpha_channel && (config->options & DWOP_ALPHACHANNEL))\n          flags |= DSBLIT_BLEND_ALPHACHANNEL;\n\n     /* Use global alpha blending. */\n     if (config->opacity != 0xff) {\n          flags |= DSBLIT_BLEND_COLORALPHA;\n\n          /* Set opacity as blending factor. */\n          if (state->color.a != config->opacity) {\n               state->color.a   = config->opacity;\n               state->modified |= SMF_COLOR;\n          }\n     }\n\n     /* Use source color keying. */\n     if (config->options & DWOP_COLORKEYING) {\n          flags |= DSBLIT_SRC_COLORKEY;\n\n          /* Set window color key. */\n          dfb_state_set_src_colorkey( state, config->color_key );\n     }\n\n     /* Use automatic deinterlacing. */\n     if (surface->config.caps & DSCAPS_INTERLACED)\n          flags |= DSBLIT_DEINTERLACE;\n\n     /* Different compositing methods depending on destination format. */\n     if (flags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) {\n          if (DFB_PIXELFORMAT_HAS_ALPHA( state->destination->config.format )) {\n               dfb_state_set_src_blend( state, DSBF_ONE );\n\n               /* Need to premultiply source with As*Ac or only with Ac? */\n               if (!(surface->config.caps & DSCAPS_PREMULTIPLIED))\n                    flags |= DSBLIT_SRC_PREMULTIPLY;\n               else if (flags & DSBLIT_BLEND_COLORALPHA)\n                    flags |= DSBLIT_SRC_PREMULTCOLOR;\n          }\n          else {\n               if (surface->config.caps & DSCAPS_PREMULTIPLIED) {\n                    if (flags & DSBLIT_BLEND_COLORALPHA)\n                         flags |= DSBLIT_SRC_PREMULTCOLOR;\n\n                    dfb_state_set_src_blend( state, DSBF_ONE );\n               }\n               else\n                    dfb_state_set_src_blend( state, DSBF_SRCALPHA );\n          }\n     }\n\n     rotation = (window->config.rotation + window->stack->rotation) % 360;\n\n     switch (rotation) {\n          default:\n               D_BUG( \"invalid rotation %d\", rotation );\n          case 0:\n               break;\n\n          case 90:\n               flags |= DSBLIT_ROTATE90;\n               break;\n\n          case 180:\n               flags |= DSBLIT_ROTATE180;\n               break;\n\n          case 270:\n               flags |= DSBLIT_ROTATE270;\n               break;\n     }\n\n     /* Set blitting flags. */\n     dfb_state_set_blitting_flags( state, flags );\n\n     /* Set blitting source. */\n     state->source    = surface;\n     state->modified |= SMF_SOURCE;\n\n     if (window->config.options & DWOP_SCALE) {\n          DFBDimension size = { window->stack->width, window->stack->height };\n          DFBRegion    clip = state->clip;\n          DFBRectangle src  = { 0, 0, surface->config.size.w, surface->config.size.h };\n          DFBRectangle dst;\n          DFBRectangle bounds;\n\n          transform_window_to_stack( window, &window->config.bounds, &bounds );\n\n          dfb_rectangle_from_rotated( &dst, &bounds, &size, window->stack->rotation );\n\n          /* Change clipping region. */\n          dfb_state_set_clip( state, &dest );\n\n          /* Scale window to the screen clipped by the region being updated. */\n          CoreGraphicsStateClient_StretchBlit( state->client, &src, &dst, 1 );\n\n          /* Restore clipping region. */\n          dfb_state_set_clip( state, &clip );\n     }\n     else {\n          DFBDimension size = { config->bounds.w, config->bounds.h };\n          DFBRectangle rect, src;\n\n          D_ASSERT( surface->config.size.w == config->bounds.w );\n          D_ASSERT( surface->config.size.h == config->bounds.h );\n\n          /* Initialize source rectangle. */\n          dfb_rectangle_from_region( &rect, region );\n\n          /* Subtract window offset. */\n          rect.x -= config->bounds.x;\n          rect.y -= config->bounds.y;\n\n          /* Rotate window surface. */\n          if (window->config.rotation == 90 || window->config.rotation == 270)\n               D_UTIL_SWAP( size.w, size.h );\n\n          dfb_rectangle_from_rotated( &src, &rect, &size, (360 - window->config.rotation) % 360 );\n\n          /* Blit from the window to the region being updated. */\n          DFBPoint point = { dest.x1, dest.y1 };\n          CoreGraphicsStateClient_Blit( state->client, &src, &point, 1 );\n     }\n\n     /* Reset blitting source. */\n     state->source    = NULL;\n     state->modified |= SMF_SOURCE;\n}\n\nstatic void\ndraw_background( CoreWindowStack *stack,\n                 CardState       *state,\n                 const DFBRegion *region )\n{\n     DFBRegion dest;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( stack->bg.image != NULL || (stack->bg.mode != DLBM_IMAGE && stack->bg.mode != DLBM_TILE) );\n     D_MAGIC_ASSERT( state, CardState );\n     DFB_REGION_ASSERT( region );\n\n     /* Initialize destination region. */\n     transform_stack_to_dest( stack, region, &dest );\n\n     if (!dfb_region_intersect( &dest, 0, 0,\n                                state->destination->config.size.w - 1, state->destination->config.size.h - 1 ))\n         return;\n\n     switch (stack->bg.mode) {\n          case DLBM_COLOR: {\n               DFBRectangle  rect  = DFB_RECTANGLE_INIT_FROM_REGION( &dest );\n               CoreSurface  *dst   = state->destination;\n               DFBColor     *color = &stack->bg.color;\n\n               D_MAGIC_ASSERT( dst, CoreSurface );\n\n               /* Set the background color. */\n               if (DFB_PIXELFORMAT_IS_INDEXED( dst->config.format ))\n                    dfb_state_set_color_index( state, dfb_palette_search( dst->palette,\n                                                                          color->r, color->g, color->b, color->a ) );\n               else\n                    dfb_state_set_color( state, color );\n\n               /* Simply fill the background. */\n               CoreGraphicsStateClient_FillRectangles( state->client, &rect, 1 );\n\n               break;\n          }\n\n          case DLBM_IMAGE: {\n               CoreSurface  *bg   = stack->bg.image;\n               DFBRegion     clip = state->clip;\n               DFBRectangle  src  = { 0, 0, bg->config.size.w, bg->config.size.h };\n               DFBRectangle  dst  = { 0, 0, stack->rotated_width, stack->rotated_height };\n\n               D_MAGIC_ASSERT( bg, CoreSurface );\n\n               /* Set blitting source. */\n               state->source    = bg;\n               state->modified |= SMF_SOURCE;\n\n               /* Set blitting flags. */\n               dfb_state_set_blitting_flags( state, stack->rotated_blit );\n\n               /* Set clipping region. */\n               dfb_state_set_clip( state, &dest );\n\n               /* Blit background image. */\n               CoreGraphicsStateClient_StretchBlit( state->client, &src, &dst, 1 );\n\n               /* Restore clipping region. */\n               dfb_state_set_clip( state, &clip );\n\n               /* Reset blitting source. */\n               state->source    = NULL;\n               state->modified |= SMF_SOURCE;\n\n               break;\n          }\n\n          case DLBM_TILE: {\n               CoreSurface  *bg   = stack->bg.image;\n               DFBRegion     clip = state->clip;\n               DFBRectangle  src  = { 0, 0, bg->config.size.w, bg->config.size.h };\n\n               D_MAGIC_ASSERT( bg, CoreSurface );\n\n               /* Set blitting source. */\n               state->source    = bg;\n               state->modified |= SMF_SOURCE;\n\n               /* Set blitting flags. */\n               dfb_state_set_blitting_flags( state, stack->rotated_blit );\n\n               /* Change clipping region. */\n               dfb_state_set_clip( state, &dest );\n\n               /* Tiled blit (aligned). */\n               DFBPoint p1 = { (region->x1 / src.w) * src.w, (region->y1 / src.h) * src.h };\n               DFBPoint p2 = { (region->x2 / src.w + 1) * src.w, (region->y2 / src.h + 1) * src.h };\n               CoreGraphicsStateClient_TileBlit( state->client, &src, &p1, &p2, 1 );\n\n               /* Restore clipping region. */\n               dfb_state_set_clip( state, &clip );\n\n               /* Reset blitting source. */\n               state->source    = NULL;\n               state->modified |= SMF_SOURCE;\n\n               break;\n          }\n\n          case DLBM_DONTCARE:\n               break;\n\n          default:\n               D_BUG( \"unknown background mode\" );\n               break;\n     }\n}\n\nstatic void\nupdate_region( CoreWindowStack *stack,\n               StackData       *data,\n               CardState       *state,\n               int              start,\n               int              x1,\n               int              y1,\n               int              x2,\n               int              y2 )\n{\n     int       i      = start;\n     DFBRegion region = { x1, y1, x2, y2 };\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( data != NULL );\n     D_MAGIC_ASSERT( state, CardState );\n     D_ASSERT( start < fusion_vector_size( &data->windows ) );\n     D_ASSERT( x1 <= x2 );\n     D_ASSERT( y1 <= y2 );\n\n     /* Find next intersecting window. */\n     while (i >= 0) {\n          CoreWindow *window = fusion_vector_at( &data->windows, i );\n\n          if (VISIBLE_WINDOW( window )) {\n               DFBRectangle rotated;\n\n               transform_window_to_stack( window, &window->config.bounds, &rotated );\n\n               if (dfb_region_intersect( &region, DFB_REGION_VALS_FROM_RECTANGLE( &rotated )))\n                    break;\n          }\n\n          i--;\n     }\n\n     /* Intersecting window found. */\n     if (i >= 0) {\n          CoreWindow       *window = fusion_vector_at( &data->windows, i );\n          CoreWindowConfig *config = &window->config;\n\n          if (D_FLAGS_ARE_SET( config->options, DWOP_ALPHACHANNEL | DWOP_OPAQUE_REGION )) {\n               DFBRegion opaque = DFB_REGION_INIT_TRANSLATED( &config->opaque, config->bounds.x, config->bounds.y );\n\n               if (!dfb_region_region_intersect( &opaque, &region )) {\n                    update_region( stack, data, state, i - 1, x1, y1, x2, y2 );\n\n                    draw_window( window, state, &region, true );\n               }\n               else {\n                    if ((config->opacity < 0xff) || (config->options & DWOP_COLORKEYING)) {\n                         /* Draw everything below. */\n                         update_region( stack, data, state, i - 1, x1, y1, x2, y2 );\n                    }\n                    else {\n                         /* left */\n                         if (opaque.x1 != x1)\n                              update_region( stack, data, state, i - 1, x1, opaque.y1, opaque.x1 - 1, opaque.y2 );\n\n                         /* upper */\n                         if (opaque.y1 != y1)\n                              update_region( stack, data, state, i - 1, x1, y1, x2, opaque.y1 - 1 );\n\n                         /* right */\n                         if (opaque.x2 != x2)\n                              update_region( stack, data, state, i - 1, opaque.x2 + 1, opaque.y1, x2, opaque.y2 );\n\n                         /* lower */\n                         if (opaque.y2 != y2)\n                              update_region( stack, data, state, i - 1, x1, opaque.y2 + 1, x2, y2 );\n                    }\n\n                    /* left */\n                    if (opaque.x1 != region.x1) {\n                         DFBRegion r = { region.x1, opaque.y1, opaque.x1 - 1, opaque.y2 };\n                         draw_window( window, state, &r, true );\n                    }\n\n                    /* upper */\n                    if (opaque.y1 != region.y1) {\n                         DFBRegion r = { region.x1, region.y1, region.x2, opaque.y1 - 1 };\n                         draw_window( window, state, &r, true );\n                    }\n\n                    /* right */\n                    if (opaque.x2 != region.x2) {\n                         DFBRegion r = { opaque.x2 + 1, opaque.y1, region.x2, opaque.y2 };\n                         draw_window( window, state, &r, true );\n                    }\n\n                    /* lower */\n                    if (opaque.y2 != region.y2) {\n                         DFBRegion r = { region.x1, opaque.y2 + 1, region.x2, region.y2 };\n                         draw_window( window, state, &r, true );\n                    }\n\n                    /* inner */\n                    draw_window( window, state, &opaque, false );\n               }\n          }\n          else {\n               if (TRANSLUCENT_WINDOW( window )) {\n                    /* Draw everything below. */\n                    update_region( stack, data, state, i - 1, x1, y1, x2, y2 );\n               }\n               else {\n                    /* left */\n                    if (region.x1 != x1)\n                         update_region( stack, data, state, i - 1, x1, region.y1, region.x1 - 1, region.y2 );\n\n                    /* upper */\n                    if (region.y1 != y1)\n                         update_region( stack, data, state, i - 1, x1, y1, x2, region.y1 - 1 );\n\n                    /* right */\n                    if (region.x2 != x2)\n                         update_region( stack, data, state, i - 1, region.x2 + 1, region.y1, x2, region.y2 );\n\n                    /* lower */\n                    if (region.y2 != y2)\n                         update_region( stack, data, state, i - 1, x1, region.y2 + 1, x2, y2 );\n               }\n\n               draw_window( window, state, &region, true );\n          }\n     }\n     else\n          draw_background( stack, state, &region );\n}\n\nstatic void\nflush_updating( StackData *data )\n{\n     int     i;\n     int     left_num_regions  = 0;\n     WMData *wmdata;\n\n     D_ASSERT( data != NULL );\n\n     D_ASSUME( data->updating.num_regions > 0 );\n     D_ASSUME( data->updated.num_regions == 0 );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p )\\n\", __FUNCTION__, data );\n\n     wmdata = dfb_wm_get_data();\n\n     D_ASSERT( wmdata != NULL );\n\n     if (data->updating.num_regions) {\n          left_num_regions = data->updating.num_regions;\n\n          D_DEBUG_AT( Default_WM, \"  -> making updated = updating\\n\" );\n\n          direct_memcpy( &data->updated, &data->updating, sizeof(DFBUpdates) );\n          direct_memcpy( &data->updated_regions[0], &data->updating_regions[0],\n                         sizeof(DFBRegion) * data->updating.num_regions );\n\n          data->updated.regions = &data->updated_regions[0];\n\n          D_DEBUG_AT( Default_WM, \"  -> clearing updating\\n\" );\n\n          dfb_updates_reset( &data->updating );\n     }\n\n     D_DEBUG_AT( Default_WM, \"  -> flipping the region\\n\" );\n\n     CoreGraphicsStateClient_Flush( &wmdata->client );\n\n     /* Flip the whole layer. */\n     dfb_layer_region_flip_update( data->region, &data->updated.bounding, DSFLIP_ONSYNC | DSFLIP_SWAP );\n\n     if (left_num_regions) {\n          D_DEBUG_AT( Default_WM, \"  -> copying %d updated regions\\n\", left_num_regions );\n\n          for (i = 0; i < left_num_regions; i++) {\n               D_DEBUG_AT( Default_WM, \"    -> %4d,%4d-%4dx%4d [%d]\\n\",\n                           DFB_RECTANGLE_VALS_FROM_REGION( &data->updated.regions[i] ), i );\n          }\n\n          dfb_gfx_copy_regions_client( data->region->surface, DSBR_FRONT, DSSE_LEFT, data->region->surface, DSBR_BACK,\n                                       DSSE_LEFT, data->updated.regions, left_num_regions, 0, 0, &wmdata->client );\n     }\n\n     CoreGraphicsStateClient_Flush( &wmdata->client );\n}\n\nstatic void\nrepaint_stack( CoreWindowStack     *stack,\n               StackData           *data,\n               const DFBRegion     *updates,\n               int                  num_updates,\n               DFBSurfaceFlipFlags  flags,\n               const DFBRegion     *bounding,\n               WMData              *wmdata )\n{\n     int              i;\n     CardState       *state;\n     CoreLayerRegion *region;\n     CoreSurface     *surface;\n     DFBRegion        flips[num_updates];\n     int              num_flips = 0;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( updates != NULL );\n     D_ASSERT( num_updates > 0 );\n     D_ASSERT( wmdata != NULL );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %d region(s), flags 0x%x )\\n\", __FUNCTION__,\n                 stack, data, num_updates, flags );\n\n     state   = &wmdata->state;\n     region  = data->region;\n     surface = data->surface;\n\n     if (!data->active || !surface || !(region->state & CLRSF_ENABLED))\n          return;\n\n     fusion_skirmish_prevail( &data->update_skirmish );\n\n     /* Set destination. */\n     state->destination  = surface;\n     state->modified    |= SMF_DESTINATION;\n\n     for (i = 0; i < num_updates; i++) {\n          DFBRegion        dest;\n          const DFBRegion *update = &updates[i];\n\n          DFB_REGION_ASSERT( update );\n\n          D_DEBUG_AT( Default_WM, \"  -> %4d,%4d-%4dx%4d (%d)\\n\", DFB_RECTANGLE_VALS_FROM_REGION( update ), i );\n\n          transform_stack_to_dest( stack, update, &dest );\n\n          if (!dfb_region_intersect( &dest, 0, 0, surface->config.size.w - 1, surface->config.size.h - 1 ))\n               continue;\n\n          /* Set clipping region. */\n          dfb_state_set_clip( state, &dest );\n\n          /* Compose updated region. */\n          update_region( stack, data, state,\n                         fusion_vector_size( &data->windows ) - 1,\n                         DFB_REGION_VALS( update ) );\n\n          CoreGraphicsStateClient_Flush( &wmdata->client );\n\n          flips[num_flips++] = dest;\n\n          /* Update cursor. */\n          if (data->cursor_drawn) {\n               DFBRegion cursor_rotated;\n\n               D_ASSUME( data->cursor_bs_valid );\n\n               transform_stack_to_dest( stack, &data->cursor_region, &cursor_rotated );\n\n               if (dfb_region_region_intersect( &dest, &cursor_rotated )) {\n                    dfb_gfx_copy_regions_client( surface, DSBR_BACK, DSSE_LEFT, data->cursor_bs, DSBR_BACK, DSSE_LEFT,\n                                                 &dest, 1, -cursor_rotated.x1, -cursor_rotated.y1, &wmdata->client );\n\n                    /* Set destination. */\n                    state->destination  = surface;\n                    state->modified    |= SMF_DESTINATION;\n\n                    /* Set clipping region. */\n                    dfb_state_set_clip( state, &dest );\n\n                    draw_cursor( stack, state, &data->cursor_region );\n               }\n          }\n     }\n\n     /* Reset destination. */\n     state->destination  = NULL;\n     state->modified    |= SMF_DESTINATION;\n\n     CoreGraphicsStateClient_Flush( &wmdata->client );\n\n     switch (region->config.buffermode) {\n          case DLBM_TRIPLE:\n               /* Add the updated region. */\n               for (i = 0; i < num_updates; i++) {\n                    const DFBRegion *update = &flips[i];\n\n                    DFB_REGION_ASSERT( update );\n\n                    D_DEBUG_AT( Default_WM, \"  -> adding %4d,%4d-%4dx%4d (%d) to updating\\n\",\n                                DFB_RECTANGLE_VALS_FROM_REGION( update ), i );\n\n                    dfb_updates_add( &data->updating, update );\n               }\n\n               if (!data->updated.num_regions)\n                    flush_updating( data );\n\n               break;\n\n          case DLBM_BACKVIDEO:\n               /* Flip the whole region. */\n               dfb_layer_region_flip_update( region, bounding, flags | DSFLIP_WAITFORSYNC | DSFLIP_SWAP );\n\n               /* Copy the updated region. */\n               if (!data->wm_fullscreen_updates)\n                    dfb_gfx_copy_regions_client( region->surface, DSBR_FRONT, DSSE_LEFT, region->surface, DSBR_BACK,\n                                                 DSSE_LEFT, updates, num_updates, 0, 0, &wmdata->client );\n\n               break;\n\n          default:\n               /* Flip the updated region .*/\n               for (i = 0; i < num_updates; i++) {\n                    const DFBRegion *update = &flips[i];\n\n                    DFB_REGION_ASSERT( update );\n\n                    dfb_layer_region_flip_update( region, update, flags );\n               }\n               break;\n     }\n\n     CoreGraphicsStateClient_Flush( &wmdata->client );\n\n     fusion_skirmish_dismiss( &data->update_skirmish );\n}\n\nstatic DFBResult\nprocess_updates( StackData           *data,\n                 WMData              *wmdata,\n                 CoreWindowStack     *stack,\n                 DFBSurfaceFlipFlags  flags )\n{\n     int n, d;\n     int total;\n     int bounding;\n\n     D_ASSERT( data != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_ASSERT( stack != NULL );\n\n     if (!data->updates.num_regions)\n          return DFB_OK;\n\n     if (data->wm_fullscreen_updates) {\n          DFBRegion reg = { 0, 0, stack->width - 1, stack->height - 1 };\n\n          repaint_stack( stack, data, &reg, 1, flags, &reg, wmdata );\n\n          dfb_updates_reset( &data->updates );\n\n          return DFB_OK;\n     }\n\n     dfb_updates_stat( &data->updates, &total, &bounding );\n\n     n = data->updates.max_regions - data->updates.num_regions + 1;\n     d = n + 1;\n\n     if (total > stack->width * stack->height * 9 / 10) {\n          DFBRegion region = { 0, 0, stack->width - 1, stack->height - 1 };\n          repaint_stack( stack, data, &region, 1, flags, &data->updates.bounding, wmdata );\n     }\n     else if (data->updates.num_regions < 2 || total < bounding * n / d)\n          repaint_stack( stack, data, data->updates.regions, data->updates.num_regions, flags, &data->updates.bounding,\n                         wmdata );\n     else\n          repaint_stack( stack, data, &data->updates.bounding, 1, flags, &data->updates.bounding, wmdata );\n\n     dfb_updates_reset( &data->updates );\n\n     return DFB_OK;\n}\n\nstatic void\nwind_of_change( CoreWindowStack     *stack,\n                StackData           *data,\n                DFBRegion           *update,\n                DFBSurfaceFlipFlags  flags,\n                int                  current,\n                int                  changed )\n{\n     D_ASSERT( stack != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( update != NULL );\n\n     /* Loop through windows above. */\n     for (; current > changed; current--) {\n          CoreWindow       *window;\n          CoreWindowConfig *config;\n          DFBRegion         opaque;\n          DFBRectangle      rotated;\n          DFBRectangle     *bounds = &rotated;\n          DFBWindowOptions  options;\n\n          D_ASSERT( changed >= 0 );\n          D_ASSERT( current >= changed );\n          D_ASSERT( current < fusion_vector_size( &data->windows ) );\n\n          window  = fusion_vector_at( &data->windows, current );\n          config  = &window->config;\n          options = config->options;\n\n          transform_window_to_stack( window, &config->bounds, &rotated );\n\n          /* Can skip all opaque window or opaque region. */\n          if (((config->opacity == 0xff)                           &&\n               !(options & (DWOP_COLORKEYING | DWOP_ALPHACHANNEL)) &&\n               (opaque = *update,dfb_region_intersect( &opaque,\n                                                       bounds->x, bounds->y,\n                                                       bounds->x + bounds->w - 1, bounds->y + bounds->h - 1 ))) ||\n              ((options & DWOP_ALPHACHANNEL)  &&\n               (options & DWOP_OPAQUE_REGION) &&\n               (config->opacity == 0xff)      &&\n               !(options & DWOP_COLORKEYING)  &&\n               (opaque = *update,dfb_region_intersect( &opaque,\n                                                       bounds->x + config->opaque.x1, bounds->y + config->opaque.y1,\n                                                       bounds->x + config->opaque.x2, bounds->y + config->opaque.y2 )))\n             ) {\n               /* left */\n               if (opaque.x1 != update->x1) {\n                    DFBRegion left = { update->x1, opaque.y1, opaque.x1 - 1, opaque.y2 };\n                    wind_of_change( stack, data, &left, flags, current - 1, changed );\n               }\n               /* upper */\n               if (opaque.y1 != update->y1) {\n                    DFBRegion upper = { update->x1, update->y1, update->x2, opaque.y1 - 1 };\n                    wind_of_change( stack, data, &upper, flags, current - 1, changed );\n               }\n               /* right */\n               if (opaque.x2 != update->x2) {\n                    DFBRegion right = { opaque.x2 + 1, opaque.y1, update->x2, opaque.y2 };\n                    wind_of_change( stack, data, &right, flags, current - 1, changed );\n               }\n               /* lower */\n               if (opaque.y2 != update->y2) {\n                    DFBRegion lower = { update->x1, opaque.y2 + 1, update->x2, update->y2 };\n                    wind_of_change( stack, data, &lower, flags, current - 1, changed );\n               }\n\n               return;\n          }\n     }\n\n     dfb_updates_add( &data->updates, update );\n}\n\nstatic DFBResult\nupdate_window( CoreWindow          *window,\n               WindowData          *win,\n               const DFBRegion     *region,\n               DFBSurfaceFlipFlags  flags,\n               bool                 force_complete,\n               bool                 force_invisible,\n               bool                 scale_region )\n{\n     DFBRegion     area;\n     DFBRegion     update;\n     StackData    *data;\n     DFBRectangle *bounds;\n     DFBDimension  size;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( win != NULL );\n     D_ASSERT( win->stack_data != NULL );\n     DFB_REGION_ASSERT_IF( region );\n\n     data = win->stack_data;\n\n     if (!VISIBLE_WINDOW( window ) && !force_invisible)\n          return DFB_OK;\n\n     if (data->stack->hw_mode)\n          return DFB_OK;\n\n     bounds = &window->config.bounds;\n     size.w = bounds->w;\n     size.h = bounds->h;\n\n     if (region) {\n          if (scale_region && (window->config.options & DWOP_SCALE)) {\n               int sw = window->surface->config.size.w;\n               int sh = window->surface->config.size.h;\n\n               /* Horizontal */\n               if (bounds->w > sw) {\n                    /* upscaling */\n                    area.x1 = (region->x1 - 1) * bounds->w / sw;\n                    area.x2 = (region->x2 + 1) * bounds->w / sw;\n               }\n               else {\n                    /* downscaling */\n                    area.x1 = region->x1 * bounds->w / sw - 1;\n                    area.x2 = region->x2 * bounds->w / sw + 1;\n               }\n\n               /* Vertical */\n               if (bounds->h > sh) {\n                    /* upscaling */\n                    area.y1 = (region->y1 - 1) * bounds->h / sh;\n                    area.y2 = (region->y2 + 1) * bounds->h / sh;\n               }\n               else {\n                    /* downscaling */\n                    area.y1 = region->y1 * bounds->h / sh - 1;\n                    area.y2 = region->y2 * bounds->h / sh + 1;\n               }\n\n               /* Limit to window area. */\n               dfb_region_clip( &area, 0, 0, bounds->w - 1, bounds->h - 1 );\n          }\n          else\n               area = *region;\n     }\n     else {\n          area.x1 = area.y1 = 0;\n          area.x2 = bounds->w - 1;\n          area.y2 = bounds->h - 1;\n     }\n\n     dfb_region_from_rotated( &update, &area, &size, window->config.rotation );\n\n     /* Screen offset. */\n     dfb_region_translate( &update, bounds->x, bounds->y );\n\n     if (!dfb_unsafe_region_intersect( &update, 0, 0, data->stack->width - 1, data->stack->height - 1 ))\n          return DFB_OK;\n\n     if (force_complete)\n          dfb_updates_add( &data->updates, &update );\n     else {\n          int window_index = get_index( data, window );\n\n          D_ASSERT( window_index >= 0 );\n          D_ASSERT( window_index < fusion_vector_size( &data->windows ) );\n\n          /* Repaint stack for window. */\n          if (fusion_vector_has_elements( &data->windows ) && window_index >= 0) {\n               int num = fusion_vector_size( &data->windows );\n\n               D_ASSERT( window_index < num );\n\n               wind_of_change( data->stack, data, &update, flags, num - 1, window_index );\n          }\n          else\n               dfb_updates_add( &data->updates, &update );\n     }\n\n     return DFB_OK;\n}\n\nstatic void\ninsert_window( WMData          *wmdata,\n               CoreWindowStack *stack,\n               StackData       *data,\n               CoreWindow      *window,\n               WindowData      *win )\n{\n     int         i;\n     CoreWindow *other;\n\n     D_ASSERT( wmdata != NULL );\n     D_ASSERT( stack != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( window != NULL );\n     D_ASSERT( win != NULL );\n\n     /* Iterate from bottom to top, stopping at the first window with a higher priority. */\n     fusion_vector_foreach (other, i, data->windows) {\n          WindowData *other_win = other->window_data;\n\n          D_ASSERT( other_win != NULL );\n\n          if (other_win->priority > win->priority)\n               break;\n     }\n\n     dfb_wm_dispatch_WindowRestack( wmdata->core, window, i );\n\n     /* Insert the window at the acquired position. */\n     fusion_vector_insert( &data->windows, window, i );\n\n     window->flags |= CWF_INSERTED;\n\n     dfb_wm_dispatch_WindowState( wmdata->core, window );\n}\n\nstatic void\nwithdraw_window( CoreWindowStack *stack,\n                 StackData       *data,\n                 CoreWindow      *window,\n                 WindowData      *win )\n{\n     int i;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( window != NULL );\n     D_ASSERT( DFB_WINDOW_INITIALIZED( window ) );\n     D_ASSERT( win != NULL );\n\n     /* No longer be the 'entered window'. */\n     if (data->entered_window == window)\n          data->entered_window = NULL;\n\n     /* Remove focus from window. */\n     if (data->focused_window == window)\n          data->focused_window = NULL;\n\n     /* Release explicit keyboard grab. */\n     if (data->keyboard_window == window)\n          data->keyboard_window = NULL;\n\n     /* Release explicit pointer grab. */\n     if (data->pointer_window == window)\n          data->pointer_window = NULL;\n\n     /* Release all implicit key grabs. */\n     for (i = 0; i < MAX_KEYS; i++) {\n          if (data->keys[i].code != -1 && data->keys[i].owner == window) {\n               if (!DFB_WINDOW_DESTROYED( window )) {\n                    DFBWindowEvent we;\n\n                    we.type       = DWET_KEYUP;\n                    we.key_code   = data->keys[i].code;\n                    we.key_id     = data->keys[i].id;\n                    we.key_symbol = data->keys[i].symbol;\n\n                    post_event( window, data, &we );\n               }\n\n               data->keys[i].code  = -1;\n               data->keys[i].owner = NULL;\n          }\n     }\n\n     /* Release grab of unselected keys. */\n     if (data->unselkeys_window == window)\n          data->unselkeys_window = NULL;\n}\n\nstatic void\nremove_window( WMData          *wmdata,\n               CoreWindowStack *stack,\n               StackData       *data,\n               CoreWindow      *window,\n               WindowData      *win )\n{\n     GrabbedKey *key, *next;\n\n     D_ASSERT( wmdata != NULL );\n     D_ASSERT( stack != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( window != NULL );\n     D_ASSERT( window->config.opacity == 0 );\n     D_ASSERT( DFB_WINDOW_INITIALIZED( window ) );\n     D_ASSERT( fusion_vector_contains( &data->windows, window ) );\n     D_ASSERT( win != NULL );\n\n     /* Release implicit grabs, focus etc. */\n     withdraw_window( stack, data, window, win );\n\n     /* Release all explicit key grabs. */\n     direct_list_foreach_safe (key, next, data->grabbed_keys) {\n          if (key->owner == window) {\n               direct_list_remove( &data->grabbed_keys, &key->link );\n               SHFREE( stack->shmpool, key );\n          }\n     }\n\n     fusion_vector_remove( &data->windows, fusion_vector_index_of( &data->windows, window ) );\n\n     window->flags &= ~CWF_INSERTED;\n\n     dfb_wm_dispatch_WindowState( wmdata->core, window );\n}\n\nstatic DFBResult\nmove_window( CoreWindow *window,\n             WindowData *win,\n             int         dx,\n             int         dy )\n{\n     DFBResult       ret;\n     DFBWindowEvent  we;\n     StackData      *data;\n     DFBRectangle   *bounds;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( win != NULL );\n     D_ASSERT( win->stack_data != NULL );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p [%u] %d,%d )\\n\", __FUNCTION__, window, window->id, dx, dy );\n\n     data = win->stack_data;\n\n     bounds = &window->config.bounds;\n\n     if (window->region && window->stack->context->config.buffermode == DLBM_WINDOWS) {\n          win->config.dest.x += dx;\n          win->config.dest.y += dy;\n\n          ret = dfb_layer_region_set_configuration( window->region, &win->config, CLRCF_DEST );\n          if (ret) {\n               win->config.dest.x -= dx;\n               win->config.dest.y -= dy;\n\n               return ret;\n          }\n\n          bounds->x += dx;\n          bounds->y += dy;\n     }\n     else {\n          update_window( window, win, NULL, 0, false, false, false );\n\n          bounds->x += dx;\n          bounds->y += dy;\n\n          update_window( window, win, NULL, 0, false, false, false );\n     }\n\n     /* Send new position. */\n     we.type = DWET_POSITION;\n     we.x    = bounds->x;\n     we.y    = bounds->y;\n\n     post_event( window, data, &we );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nresize_window( CoreWindow *window,\n               WMData     *wmdata,\n               WindowData *win,\n               int         width,\n               int         height )\n{\n     DFBResult       ret;\n     DFBWindowEvent  we;\n     StackData      *data;\n     DFBRectangle   *bounds;\n     int             ow, oh;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_ASSERT( win != NULL );\n     D_ASSERT( win->stack_data != NULL );\n     D_ASSERT( width > 0 );\n     D_ASSERT( height > 0 );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p [%u] %dx%d )\\n\", __FUNCTION__, window, window->id, width, height );\n\n     data = win->stack_data;\n\n     bounds = &window->config.bounds;\n     ow     = bounds->w;\n     oh     = bounds->h;\n\n     if (width > 4096 || height > 4096)\n          return DFB_LIMITEXCEEDED;\n\n     if (window->surface && !(window->config.options & DWOP_SCALE)) {\n          CoreSurfaceConfig config;\n\n          config.flags  = CSCONF_SIZE;\n          config.size.w = width;\n          config.size.h = height;\n\n          ret = dfb_surface_reconfig( window->surface, &config );\n          if (ret)\n               return ret;\n     }\n\n     if (window->region && window->stack->context->config.buffermode == DLBM_WINDOWS) {\n          win->config.dest.w = win->config.source.w = win->config.width  = width;\n          win->config.dest.h = win->config.source.h = win->config.height = height;\n\n          ret = dfb_layer_region_set_configuration( window->region, &win->config,\n                                                    CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_SURFACE |\n                                                    CLRCF_DEST  | CLRCF_SOURCE | CLRCF_FREEZE );\n          if (ret) {\n               win->config.dest.w = win->config.source.w = win->config.width  = bounds->w = ow;\n               win->config.dest.h = win->config.source.h = win->config.height = bounds->h = oh;\n\n               return ret;\n          }\n     }\n     else {\n          dfb_region_intersect( &window->config.opaque, 0, 0, width - 1, height - 1 );\n\n          if (VISIBLE_WINDOW( window )) {\n               if (ow > width) {\n                    DFBRegion region = { width, 0, ow - 1, MIN( height, oh ) - 1 };\n\n                    update_window( window, win, &region, 0, false, false, false );\n               }\n\n               if (oh > height) {\n                    DFBRegion region = { 0, height, MAX( width, ow ) - 1, oh - 1 };\n\n                    update_window( window, win, &region, 0, false, false, false );\n               }\n          }\n     }\n\n     bounds->w = width;\n     bounds->h = height;\n\n     /* Send new size. */\n     we.type = DWET_SIZE;\n     we.w    = bounds->w;\n     we.h    = bounds->h;\n\n     post_event( window, data, &we );\n\n     update_focus( window->stack, data, wmdata );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nset_window_bounds( CoreWindow *window,\n                   WMData     *wmdata,\n                   WindowData *win,\n                   int         x,\n                   int         y,\n                   int         width,\n                   int         height )\n{\n     DFBResult       ret;\n     DFBWindowEvent  we;\n     StackData      *data;\n     DFBRegion       old_region;\n     DFBRegion       new_region;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_ASSERT( win != NULL );\n     D_ASSERT( win->stack_data != NULL );\n     D_ASSERT( width > 0 );\n     D_ASSERT( height > 0 );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p [%u] %d,%d-%dx%d )\\n\", __FUNCTION__, window, window->id, x, y, width, height );\n\n     data = win->stack_data;\n\n     if (width > 4096 || height > 4096)\n          return DFB_LIMITEXCEEDED;\n\n     if (window->surface && !(window->config.options & DWOP_SCALE)) {\n          ret = dfb_surface_reformat( window->surface, width, height, window->surface->config.format );\n          if (ret)\n               return ret;\n     }\n\n     old_region.x1 = window->config.bounds.x - x;\n     old_region.y1 = window->config.bounds.y - y;\n     old_region.x2 = old_region.x1 + window->config.bounds.w - 1;\n     old_region.y2 = old_region.y1 + window->config.bounds.h - 1;\n\n     window->config.bounds.x = x;\n     window->config.bounds.y = y;\n     window->config.bounds.w = width;\n     window->config.bounds.h = height;\n\n     new_region.x1 = 0;\n     new_region.y1 = 0;\n     new_region.x2 = width  - 1;\n     new_region.y2 = height - 1;\n\n     if (!dfb_region_region_intersect( &window->config.opaque, &new_region ))\n          window->config.opaque = new_region;\n\n     /* Update exposed area. */\n     if (VISIBLE_WINDOW( window )) {\n          if (dfb_region_region_intersect( &new_region, &old_region )) {\n               /* left */\n               if (new_region.x1 > old_region.x1) {\n                    DFBRegion region = { old_region.x1, old_region.y1, new_region.x1 - 1, new_region.y2 };\n\n                    update_window( window, win, &region, 0, false, false, false );\n               }\n\n               /* upper */\n               if (new_region.y1 > old_region.y1) {\n                    DFBRegion region = { old_region.x1, old_region.y1, old_region.x2, new_region.y1 - 1 };\n\n                    update_window( window, win, &region, 0, false, false, false );\n               }\n\n               /* right */\n               if (new_region.x2 < old_region.x2) {\n                    DFBRegion region = { new_region.x2 + 1, new_region.y1, old_region.x2, new_region.y2 };\n\n                    update_window( window, win, &region, 0, false, false, false );\n               }\n\n               /* lower */\n               if (new_region.y2 < old_region.y2) {\n                    DFBRegion region = { old_region.x1, new_region.y2 + 1, old_region.x2, old_region.y2 };\n\n                    update_window( window, win, &region, 0, false, false, false );\n               }\n          }\n          else\n               update_window( window, win, &old_region, 0, false, false, false );\n     }\n\n     /* Send new position and size. */\n     we.type = DWET_POSITION_SIZE;\n     we.x    = window->config.bounds.x;\n     we.y    = window->config.bounds.y;\n     we.w    = window->config.bounds.w;\n     we.h    = window->config.bounds.h;\n\n     post_event( window, data, &we );\n\n     update_focus( window->stack, data, wmdata );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nrestack_window( WMData                 *wmdata,\n                CoreWindow             *window,\n                WindowData             *win,\n                CoreWindow             *relative,\n                WindowData             *relative_data,\n                int                     relation,\n                DFBWindowStackingClass  stacking )\n{\n     StackData *data;\n     int        old;\n     int        index;\n     int        priority;\n\n     D_ASSERT( wmdata != NULL );\n     D_ASSERT( window != NULL );\n     D_ASSERT( win != NULL );\n     D_ASSERT( win->stack_data != NULL );\n     D_ASSERT( relative == NULL || relative_data != NULL );\n     D_ASSERT( relative == NULL || relative == window || relation != 0);\n\n     data = win->stack_data;\n\n     /* Change stacking class. */\n     if (stacking != window->config.stacking) {\n          window->config.stacking = stacking;\n\n          win->priority = get_priority( window );\n     }\n\n     /* Get the (new) priority. */\n     priority = win->priority;\n\n     /* Get the old index. */\n     old = get_index( data, window );\n\n     /* Calculate the desired index. */\n     if (relative) {\n          index = get_index( data, relative );\n\n          if (relation > 0) {\n               if (old < index)\n                    index--;\n          }\n          else if (relation < 0) {\n               if (old > index)\n                    index++;\n          }\n\n          index += relation;\n\n          if (index < 0)\n               index = 0;\n          else if (index > fusion_vector_size( &data->windows ) - 1)\n               index = fusion_vector_size( &data->windows ) - 1;\n     }\n     else if (relation)\n          index = fusion_vector_size( &data->windows ) - 1;\n     else\n          index = 0;\n\n     /* Assure window won't be above any window with a higher priority. */\n     while (index > 0) {\n          int         below     = (old < index) ? index : index - 1;\n          CoreWindow *other     = fusion_vector_at( &data->windows, below );\n          WindowData *other_win = other->window_data;\n\n          D_ASSERT( other_win != NULL );\n\n          if (priority < other_win->priority)\n               index--;\n          else\n               break;\n     }\n\n     /* Assure window won't be below any window with a lower priority. */\n     while (index < fusion_vector_size( &data->windows ) - 1) {\n          int         above     = (old > index) ? index : index + 1;\n          CoreWindow *other     = fusion_vector_at( &data->windows, above );\n          WindowData *other_win = other->window_data;\n\n          D_ASSERT( other_win != NULL );\n\n          if (priority > other_win->priority)\n               index++;\n          else\n               break;\n     }\n\n     /* Return if index hasn't changed. */\n     if (index == old)\n          return DFB_OK;\n\n     /* Actually change the stacking order now. */\n     fusion_vector_move( &data->windows, old, index );\n\n     dfb_wm_dispatch_WindowRestack( wmdata->core, window, index );\n\n     update_window( window, win, NULL, DSFLIP_NONE, (index < old), false, false );\n\n     return DFB_OK;\n}\n\nstatic void\nset_opacity( CoreWindow *window,\n             WindowData *win,\n             WMData     *wmdata,\n             u8          opacity )\n{\n     StackData *data;\n     u8         old;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( win != NULL );\n     D_ASSERT( win->stack_data != NULL );\n     D_ASSERT( wmdata != NULL );\n\n     data = win->stack_data;\n\n     if (!data->stack->hw_mode && !dfb_config->translucent_windows && opacity)\n          opacity = 0xff;\n\n     old = window->config.opacity;\n\n     if (old != opacity) {\n          bool show = !old && opacity;\n          bool hide = old && !opacity;\n\n          window->config.opacity = opacity;\n\n          if (window->region && window->stack->context->config.buffermode == DLBM_WINDOWS) {\n               win->config.opacity = opacity;\n\n               dfb_layer_region_set_configuration( window->region, &win->config, CLRCF_OPACITY );\n          }\n          else\n               update_window( window, win, NULL, DSFLIP_NONE, false, true, false );\n\n          /* Check focus after window appeared or disappeared. */\n          if (show || hide)\n               update_focus( data->stack, data, wmdata );\n\n          /* Window disappeared. */\n          if (hide) {\n               int         i;\n               CoreWindow *other;\n\n               /* Ungrab pointer/keyboard. */\n               withdraw_window( data->stack, data, window, win );\n\n               /* Always try to have a focused window. */\n               if (data->focused_window)\n                    return;\n\n               fusion_vector_foreach_reverse (other, i, data->windows) {\n                    if (other->config.opacity && !(other->config.options & DWOP_GHOST)) {\n                         switch_focus( wmdata, data->stack, data, other );\n                         break;\n                    }\n               }\n          }\n     }\n}\n\nstatic DFBResult\ngrab_keyboard( CoreWindow *window,\n               WindowData *win )\n{\n     StackData *data;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( win != NULL );\n     D_ASSERT( win->stack_data != NULL );\n\n     data = win->stack_data;\n\n     if (data->keyboard_window)\n          return DFB_LOCKED;\n\n     data->keyboard_window = window;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nungrab_keyboard( CoreWindow *window,\n                 WindowData *win )\n{\n     StackData *data;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( win != NULL );\n     D_ASSERT( win->stack_data != NULL );\n\n     data = win->stack_data;\n\n     if (data->keyboard_window == window)\n          data->keyboard_window = NULL;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ngrab_pointer( CoreWindow *window,\n              WindowData *win )\n{\n     StackData *data;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( win != NULL );\n     D_ASSERT( win->stack_data != NULL );\n\n     data = win->stack_data;\n\n     if (data->pointer_window)\n          return DFB_LOCKED;\n\n     data->pointer_window = window;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nungrab_pointer( CoreWindow *window,\n                WindowData *win,\n                WMData     *wmdata )\n{\n     StackData *data;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( win != NULL );\n     D_ASSERT( win->stack_data != NULL );\n     D_ASSERT( wmdata != NULL );\n\n     data = win->stack_data;\n\n     if (data->pointer_window == window) {\n          data->pointer_window = NULL;\n\n          /* Possibly change focus to window that is now under the cursor. */\n          update_focus( data->stack, data, wmdata );\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\ngrab_key( CoreWindow                 *window,\n          WindowData                 *win,\n          DFBInputDeviceKeySymbol     symbol,\n          DFBInputDeviceModifierMask  modifiers )\n{\n     int         i;\n     StackData  *data;\n     GrabbedKey *grab;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( win != NULL );\n     D_ASSERT( win->stack_data != NULL );\n\n     data = win->stack_data;\n\n     /* Reject if already grabbed. */\n     direct_list_foreach (grab, data->grabbed_keys) {\n          if (grab->symbol == symbol && grab->modifiers == modifiers)\n               return DFB_LOCKED;\n     }\n\n     /* Allocate grab information. */\n     grab = SHCALLOC( data->stack->shmpool, 1, sizeof(GrabbedKey) );\n\n     /* Fill grab information. */\n     grab->symbol    = symbol;\n     grab->modifiers = modifiers;\n     grab->owner     = window;\n\n     /* Add to list of key grabs. */\n     direct_list_append( &data->grabbed_keys, &grab->link );\n\n     /* Remove implicit grabs for this key. */\n     for (i = 0; i < MAX_KEYS; i++)\n          if (data->keys[i].code != -1 && data->keys[i].symbol == symbol)\n               data->keys[i].code = -1;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nungrab_key( CoreWindow                 *window,\n            WindowData                 *win,\n            DFBInputDeviceKeySymbol     symbol,\n            DFBInputDeviceModifierMask  modifiers )\n{\n     GrabbedKey *key;\n     StackData  *data;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( win != NULL );\n     D_ASSERT( win->stack_data != NULL );\n\n     data = win->stack_data;\n\n     direct_list_foreach (key, data->grabbed_keys) {\n          if (key->symbol == symbol && key->modifiers == modifiers && key->owner == window) {\n               direct_list_remove( &data->grabbed_keys, &key->link );\n               SHFREE( data->stack->shmpool, key );\n               return DFB_OK;\n          }\n     }\n\n     return DFB_IDNOTFOUND;\n}\n\nstatic bool\nhandle_wm_key( CoreWindowStack     *stack,\n               StackData           *data,\n               WMData              *wmdata,\n               const DFBInputEvent *event )\n{\n     int         i, num;\n     CoreWindow *entered;\n     CoreWindow *focused;\n     CoreWindow *window;\n     DFBRegion   region;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_ASSERT( event != NULL );\n     D_ASSERT( event->type == DIET_KEYPRESS );\n\n     entered = data->entered_window;\n     focused = data->focused_window;\n\n     /*\n      * While pressing the <Meta> (or Windows) key or alternatively <Caps-Lock> you can do the following:\n      *   - Press X to cycle the focus through the windows.\n      *   - Press D to lower the highest window to the bottom.\n      *   - Press S to raise the lowest window to the top.\n      *   - Press C to close the focused window.\n      *   - Press E to focus the window currently under the mouse cursor.\n      *   - Press A to lower the focused window to the bottom.\n      *   - Press W to raise the focused window to the top.\n      *   - Press P to enable and show the mouse cursor.\n      *   - Press R to rotate the focused window by 90 degree.\n      *   - Press Print to make a screenshot of the focused window.\n      *   - Press F12 to redraw the whole window stack.\n      */\n\n     switch (DFB_LOWER_CASE(event->key_symbol)) {\n          case DIKS_SMALL_X:\n               num = fusion_vector_size( &data->windows );\n\n               if (data->wm_cycle <= 0)\n                    data->wm_cycle = num;\n\n               if (num) {\n                    int looped = 0;\n                    int index  = MIN( num, data->wm_cycle );\n\n                    while (index--) {\n                         window = fusion_vector_at( &data->windows, index );\n\n                         if ((window->config.options & (DWOP_GHOST | DWOP_KEEP_STACKING)) ||\n                             !VISIBLE_WINDOW( window )                                    ||\n                             window == data->focused_window) {\n                              if (index == 0 && !looped) {\n                                   looped = 1;\n                                   index  = num - 1;\n                              }\n\n                              continue;\n                         }\n\n                         restack_window( wmdata, window, window->window_data, NULL, NULL, 1, window->config.stacking );\n                         request_focus( wmdata, window, window->window_data );\n\n                         break;\n                    }\n\n                    data->wm_cycle = index;\n               }\n               break;\n\n          case DIKS_SMALL_D:\n               fusion_vector_foreach_reverse (window, i, data->windows) {\n                    if (VISIBLE_WINDOW( window )               &&\n                        window->config.stacking == DWSC_MIDDLE &&\n                        !(window->config.options & (DWOP_GHOST | DWOP_KEEP_STACKING))) {\n                         restack_window( wmdata, window, window->window_data, NULL, NULL, 0, window->config.stacking );\n                         request_focus( wmdata, window, window->window_data );\n\n                         break;\n                    }\n               }\n               break;\n\n          case DIKS_SMALL_S:\n               fusion_vector_foreach (window, i, data->windows) {\n                    if (VISIBLE_WINDOW( window )               &&\n                        window->config.stacking == DWSC_MIDDLE &&\n                        !(window->config.options & (DWOP_GHOST | DWOP_KEEP_STACKING))) {\n                         restack_window( wmdata, window, window->window_data, NULL, NULL, 1, window->config.stacking );\n                         request_focus( wmdata, window, window->window_data );\n\n                         break;\n                    }\n               }\n               break;\n\n          case DIKS_SMALL_C:\n               if (entered) {\n                    DFBWindowEvent we;\n\n                    we.type = DWET_CLOSE;\n\n                    post_event( entered, data, &we );\n               }\n               break;\n\n          case DIKS_SMALL_E:\n               update_focus( stack, data, wmdata );\n               break;\n\n          case DIKS_SMALL_A:\n               if (focused && !(focused->config.options & DWOP_KEEP_STACKING)) {\n                    restack_window( wmdata, focused, focused->window_data, NULL, NULL, 0, focused->config.stacking );\n                    update_focus( stack, data, wmdata );\n               }\n               break;\n\n          case DIKS_SMALL_W:\n               if (focused && !(focused->config.options & DWOP_KEEP_STACKING))\n                    restack_window( wmdata, focused, focused->window_data, NULL, NULL, 1, focused->config.stacking );\n               break;\n\n          case DIKS_SMALL_P:\n               if (stack->cursor.set) {\n                    dfb_windowstack_cursor_set_opacity( stack, 0xff );\n                    dfb_windowstack_cursor_enable( stack, true );\n               }\n\n               /* Ungrab pointer. */\n               data->pointer_window = NULL;\n               break;\n\n          case DIKS_SMALL_R:\n               if (focused && !(focused->config.options & DWOP_KEEP_POSITION))\n                    dfb_window_set_rotation( focused, (focused->config.rotation + 90) % 360 );\n               break;\n\n          case DIKS_PRINT:\n               if (dfb_config->screenshot_dir && focused && focused->surface)\n                    dfb_surface_dump_buffer( focused->surface, DSBR_FRONT, dfb_config->screenshot_dir, \"dfb_window\" );\n               break;\n\n          case DIKS_F12:\n               region.x1 = 0;\n               region.y1 = 0;\n               region.x2 = stack->width;\n               region.y2 = stack->height;\n\n               dfb_updates_reset( &data->updates );\n               dfb_updates_add( &data->updates, &region );\n               break;\n\n          default:\n               return false;\n     }\n\n     return true;\n}\n\nstatic DFBResult\nhandle_key_press( CoreWindowStack     *stack,\n                  StackData           *data,\n                  WMData              *wmdata,\n                  const DFBInputEvent *event )\n{\n     CoreWindow *window;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_ASSERT( event != NULL );\n     D_ASSERT( event->type == DIET_KEYPRESS );\n\n     if (data->wm_level) {\n          switch (event->key_symbol) {\n               case DIKS_META:\n                    data->wm_level |= 1;\n                    break;\n\n               case DIKS_CONTROL:\n                    data->wm_level |= 2;\n                    break;\n\n               case DIKS_ALT:\n                    data->wm_level |= 4;\n                    break;\n\n               default:\n                    if (handle_wm_key( stack, data, wmdata, event ))\n                         return DFB_OK;\n                    break;\n          }\n     }\n     else if (event->key_symbol == DIKS_META) {\n          data->wm_level |= 1;\n          data->wm_cycle  = 0;\n     }\n\n     window = get_keyboard_window( stack, data, event );\n     if (window)\n          send_key_event( window, data, event );\n\n     return DFB_OK;\n}\n\nstatic bool\nis_wm_key( DFBInputDeviceKeySymbol key_symbol )\n{\n     switch (DFB_LOWER_CASE(key_symbol)) {\n          case DIKS_SMALL_X:\n          case DIKS_SMALL_D:\n          case DIKS_SMALL_S:\n          case DIKS_SMALL_C:\n          case DIKS_SMALL_E:\n          case DIKS_SMALL_A:\n          case DIKS_SMALL_W:\n          case DIKS_SMALL_P:\n          case DIKS_SMALL_R:\n          case DIKS_PRINT:\n          case DIKS_F12:\n               break;\n\n          default:\n               return false;\n     }\n\n     return true;\n}\n\nstatic DFBResult\nhandle_key_release( CoreWindowStack     *stack,\n                    StackData           *data,\n                    const DFBInputEvent *event )\n{\n     CoreWindow *window;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( event != NULL );\n     D_ASSERT( event->type == DIET_KEYRELEASE );\n\n     if (data->wm_level) {\n          switch (event->key_symbol) {\n               case DIKS_META:\n                    data->wm_level &= ~1;\n                    break;\n\n               case DIKS_CONTROL:\n                    data->wm_level &= ~2;\n                    break;\n\n               case DIKS_ALT:\n                    data->wm_level &= ~4;\n                    break;\n\n               default:\n                    if (is_wm_key( event->key_symbol ))\n                         return DFB_OK;\n\n                    break;\n          }\n     }\n\n     window = get_keyboard_window( stack, data, event );\n     if (window)\n          send_key_event( window, data, event );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nhandle_button_press( CoreWindowStack     *stack,\n                     StackData           *data,\n                     const DFBInputEvent *event )\n{\n     CoreWindow *window;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( event != NULL );\n     D_ASSERT( event->type == DIET_BUTTONPRESS );\n\n     if (!stack->cursor.enabled)\n          return DFB_OK;\n\n     switch (data->wm_level) {\n          case 1:\n               window = data->entered_window;\n               if (window && !(window->config.options & DWOP_KEEP_STACKING))\n                    dfb_window_raisetotop( window );\n\n               break;\n\n          default:\n               window = data->pointer_window ?: data->entered_window;\n               if (window)\n                    send_button_event( window, data, event );\n\n               break;\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nhandle_button_release( CoreWindowStack     *stack,\n                       StackData           *data,\n                       const DFBInputEvent *event )\n{\n     CoreWindow *window;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( event != NULL );\n     D_ASSERT( event->type == DIET_BUTTONRELEASE );\n\n     if (!stack->cursor.enabled)\n          return DFB_OK;\n\n     switch (data->wm_level) {\n          case 1:\n               break;\n\n          default:\n               window = data->pointer_window ?: data->entered_window;\n               if (window)\n                    send_button_event( window, data, event );\n\n               break;\n     }\n\n     return DFB_OK;\n}\n\nstatic void\nperform_motion( CoreWindowStack *stack,\n                StackData       *data,\n                WMData          *wmdata,\n                int              dx,\n                int              dy )\n{\n     int               old_cx, old_cy;\n     DFBWindowEvent    we;\n     CoreWindow       *entered;\n     CoreWindowConfig *config = NULL;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( wmdata != NULL );\n\n     if (!stack->cursor.enabled)\n          return;\n\n     old_cx = stack->cursor.x;\n     old_cy = stack->cursor.y;\n\n     dfb_windowstack_cursor_warp( stack, old_cx + dx, old_cy + dy );\n\n     dx = stack->cursor.x - old_cx;\n     dy = stack->cursor.y - old_cy;\n\n     if (!dx && !dy)\n          return;\n\n     entered = data->entered_window;\n     if (entered)\n          config = &entered->config;\n\n     switch (data->wm_level) {\n          case 7:\n          case 6:\n          case 5:\n          case 4:\n               if (entered) {\n                    int opacity = config->opacity + dx;\n\n                    if (opacity < 8)\n                         opacity = 8;\n                    else if (opacity > 0xff)\n                         opacity = 0xff;\n\n                    dfb_window_set_opacity( entered, opacity );\n               }\n\n               break;\n\n          case 3:\n          case 2:\n               if (entered && !(config->options & DWOP_KEEP_SIZE)) {\n                    int width  = config->bounds.w + dx;\n                    int height = config->bounds.h + dy;\n\n                    if (width  <   48) width  = 48;\n                    if (height <   48) height = 48;\n                    if (width  > 2048) width  = 2048;\n                    if (height > 2048) height = 2048;\n\n                    dfb_window_resize( entered, width, height );\n               }\n\n               break;\n\n          case 1:\n               if (entered && !(config->options & DWOP_KEEP_POSITION))\n                    dfb_window_move( entered, dx, dy, true );\n\n               break;\n\n          case 0:\n               if (data->pointer_window) {\n                    CoreWindow *window = data->pointer_window;\n\n                    we.type = DWET_MOTION;\n                    we.x    = stack->cursor.x - window->config.bounds.x;\n                    we.y    = stack->cursor.y - window->config.bounds.y;\n\n                    transform_point_in_window( window, &we.x, &we.y );\n\n                    post_event( window, data, &we );\n               }\n               else if (!update_focus( stack, data, wmdata ) && data->entered_window) {\n                    CoreWindow *window = data->entered_window;\n\n                    we.type = DWET_MOTION;\n                    we.x    = stack->cursor.x - window->config.bounds.x;\n                    we.y    = stack->cursor.y - window->config.bounds.y;\n\n                    transform_point_in_window( window, &we.x, &we.y );\n\n                    post_event( window, data, &we );\n               }\n\n               break;\n\n          default:\n               ;\n     }\n}\n\nstatic void\nflush_motion( CoreWindowStack *stack,\n              StackData       *data,\n              WMData          *wmdata )\n{\n     D_ASSERT( stack != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( wmdata != NULL );\n\n     if (data->cursor_dx || data->cursor_dy) {\n          perform_motion( stack, data, wmdata, data->cursor_dx, data->cursor_dy );\n\n          data->cursor_dx = 0;\n          data->cursor_dy = 0;\n     }\n}\n\nstatic void\nhandle_wheel( CoreWindowStack *stack,\n              StackData       *data,\n              int              dz )\n{\n     DFBWindowEvent  we;\n     CoreWindow     *window = NULL;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( data != NULL );\n\n     if (!stack->cursor.enabled)\n          return;\n\n     window = data->pointer_window ?: data->entered_window;\n\n     if (window) {\n          if (data->wm_level) {\n               int opacity = window->config.opacity + dz * 7;\n\n               if (opacity < 1)\n                    opacity = 1;\n               if (opacity > 0xff)\n                    opacity = 0xff;\n\n               dfb_window_set_opacity( window, opacity );\n          }\n          else {\n               we.type = DWET_WHEEL;\n               we.x    = stack->cursor.x - window->config.bounds.x;\n               we.y    = stack->cursor.y - window->config.bounds.y;\n               we.step = dz;\n\n               transform_point_in_window( window, &we.x, &we.y );\n\n               post_event( window, data, &we );\n          }\n     }\n}\n\nstatic DFBResult\nhandle_axis_motion( CoreWindowStack     *stack,\n                    StackData           *data,\n                    WMData              *wmdata,\n                    const DFBInputEvent *event )\n{\n     DFBInputEvent rotated_event;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( data != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_ASSERT( event != NULL );\n     D_ASSERT( event->type == DIET_AXISMOTION );\n\n     if (event->flags & DIEF_AXISREL) {\n          rotated_event = *event;\n          event         = &rotated_event;\n\n          if (event->axis == DIAI_X) {\n               if (stack->context ->rotation == 90) {\n                    rotated_event.axis = DIAI_Y;\n               }\n               else if (stack->context ->rotation == 180) {\n                    rotated_event.axisrel = -rotated_event.axisrel;\n               }\n               else if (stack->context ->rotation == 270) {\n                    rotated_event.axis = DIAI_Y;\n                    rotated_event.axisrel = -rotated_event.axisrel;\n               }\n          }\n          else if (event->axis == DIAI_Y) {\n               if (stack->context ->rotation == 90) {\n                    rotated_event.axis = DIAI_X;\n                    rotated_event.axisrel = -rotated_event.axisrel;\n               }\n               else if (stack->context ->rotation == 180) {\n                    rotated_event.axisrel = -rotated_event.axisrel;\n               }\n               else if (stack->context ->rotation == 270) {\n                    rotated_event.axis = DIAI_X;\n               }\n          }\n     }\n     else if (event->flags & DIEF_AXISABS) {\n          rotated_event = *event;\n          event = &rotated_event;\n\n          if (event->axis == DIAI_X) {\n               if (stack->context ->rotation == 90) {\n                    rotated_event.axis = DIAI_Y;\n               }\n               else if (stack->context ->rotation == 180) {\n                    rotated_event.axisabs = stack->rotated_width - rotated_event.axisabs;\n               }\n               else if (stack->context ->rotation == 270) {\n                    rotated_event.axis = DIAI_Y;\n                    rotated_event.axisabs = stack->rotated_width - rotated_event.axisabs;\n               }\n          }\n          else if (event->axis == DIAI_Y) {\n               if (stack->context ->rotation == 90) {\n                    rotated_event.axis = DIAI_X;\n                    rotated_event.axisabs = stack->rotated_height - rotated_event.axisabs;\n               }\n               else if (stack->context ->rotation == 180) {\n                    rotated_event.axisabs = stack->rotated_height - rotated_event.axisabs;\n               }\n               else if (stack->context ->rotation == 270) {\n                    rotated_event.axis = DIAI_X;\n               }\n          }\n     }\n\n     if (event->flags & DIEF_AXISREL) {\n          int rel = event->axisrel;\n\n          /* Handle cursor acceleration. */\n          if (rel > stack->cursor.threshold)\n               rel += (rel - stack->cursor.threshold) * stack->cursor.numerator / stack->cursor.denominator;\n          else if (rel < -stack->cursor.threshold)\n               rel += (rel + stack->cursor.threshold) * stack->cursor.numerator / stack->cursor.denominator;\n\n          switch (event->axis) {\n               case DIAI_X:\n                    data->cursor_dx += rel;\n                    break;\n\n               case DIAI_Y:\n                    data->cursor_dy += rel;\n                    break;\n\n               case DIAI_Z:\n                    flush_motion( stack, data, wmdata );\n                    handle_wheel( stack, data, - event->axisrel );\n                    break;\n\n               default:\n                    ;\n          }\n     }\n     else if (event->flags & DIEF_AXISABS) {\n          int axismin = 0;\n          int axisabs = event->axisabs;\n\n          if (event->flags & DIEF_MIN) {\n               axismin = event->min;\n               axisabs -= axismin;\n          }\n\n          switch (event->axis) {\n               case DIAI_X:\n                    if (event->flags & DIEF_MAX)\n                         axisabs = axisabs * stack->width / (event->max - axismin + 1);\n\n                    data->cursor_dx = axisabs - stack->cursor.x;\n                    break;\n\n               case DIAI_Y:\n                    if (event->flags & DIEF_MAX)\n                         axisabs = axisabs * stack->height / (event->max - axismin + 1);\n\n                    data->cursor_dy = axisabs - stack->cursor.y;\n                    break;\n\n               default:\n                    ;\n          }\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nlocal_init( WMData  *wmdata,\n            CoreDFB *core )\n{\n     DFBResult ret;\n\n     wmdata->core = core;\n\n     dfb_state_init( &wmdata->state, core );\n\n     ret = CoreGraphicsStateClient_Init( &wmdata->client, &wmdata->state );\n     if (ret)\n          return ret;\n\n     wmdata->refs++;\n\n     return DFB_OK;\n}\n\nstatic void\nlocal_deinit( WMData *wmdata )\n{\n     CoreGraphicsStateClient_Deinit( &wmdata->client );\n\n     dfb_state_destroy( &wmdata->state );\n}\n\n/**********************************************************************************************************************\n ********************************* WM Module functions ****************************************************************\n **********************************************************************************************************************/\n\nstatic void\nwm_get_info( CoreWMInfo *info )\n{\n     info->version.major  = 0;\n     info->version.minor  = 3;\n\n     snprintf( info->name, DFB_CORE_WM_INFO_NAME_LENGTH,     \"Default\" );\n     snprintf( info->vendor, DFB_CORE_WM_INFO_VENDOR_LENGTH, \"DirectFB\" );\n\n     info->wm_data_size     = sizeof(WMData);\n     info->stack_data_size  = sizeof(StackData);\n     info->window_data_size = sizeof(WindowData);\n}\n\nstatic DFBResult\nwm_initialize( CoreDFB *core,\n               void    *wm_data,\n               void    *shared_data )\n{\n     DFBResult ret;\n\n     ret = local_init( wm_data, core );\n     if (ret)\n          return ret;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_join( CoreDFB *core,\n         void    *wm_data,\n         void    *shared_data )\n{\n     DFBResult ret;\n\n     ret = local_init( wm_data, core );\n     if (ret)\n          return ret;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_shutdown( bool  emergency,\n             void *wm_data,\n             void *shared_data )\n{\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_leave( bool  emergency,\n          void *wm_data,\n          void *shared_data )\n{\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_suspend( void *wm_data,\n            void *shared_data )\n{\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_resume( void *wm_data,\n           void *shared_data )\n{\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_post_init( void *wm_data,\n              void *shared_data )\n{\n     return DFB_OK;\n}\n\nstatic ReactionResult\nwm_surface_react( const void *msg_data,\n                  void       *ctx )\n{\n     int                            i;\n     const CoreSurfaceNotification *notification = msg_data;\n     StackData                     *data         = ctx;\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p )\\n\", __FUNCTION__, notification, data );\n\n     D_ASSERT( notification != NULL );\n     D_MAGIC_ASSERT( data, StackData );\n\n     if (notification->flags & CSNF_DISPLAY) {\n          D_DEBUG_AT( Default_WM, \"  -> DISPLAY [%d]\\n\", notification->index );\n\n          fusion_skirmish_prevail( &data->update_skirmish );\n\n          switch (data->region->config.buffermode) {\n               case DLBM_TRIPLE:\n                    if (data->updated.num_regions) {\n                         if (data->updated.num_regions) {\n                              D_DEBUG_AT( Default_WM, \"  -> copying %d updated regions\\n\",\n                                          data->updated.num_regions );\n\n                              for (i = 0; i < data->updated.num_regions; i++) {\n                                   D_DEBUG_AT( Default_WM, \"    -> %4d,%4d-%4dx%4d [%d]\\n\",\n                                               DFB_RECTANGLE_VALS_FROM_REGION( &data->updated.regions[i] ), i );\n                              }\n\n                              dfb_gfx_copy_regions_client( data->surface, DSBR_FRONT, DSSE_LEFT, data->surface,\n                                                           DSBR_IDLE, DSSE_LEFT, data->updated.regions,\n                                                           data->updated.num_regions, 0, 0, NULL );\n                         }\n\n                         dfb_updates_reset( &data->updated );\n                    }\n\n                    if (data->updating.num_regions) {\n                         D_DEBUG_AT( Default_WM, \"  -> flushing updating regions\\n\" );\n\n                         flush_updating( data );\n                    }\n\n                    break;\n\n               default:\n                    break;\n\n          }\n\n          fusion_skirmish_dismiss( &data->update_skirmish );\n     }\n\n     return RS_OK;\n}\n\nstatic DFBResult\nwm_init_stack( CoreWindowStack *stack,\n               void            *wm_data,\n               void            *stack_data )\n{\n     DFBResult  ret;\n     int        i;\n     WMData    *wmdata = wm_data;\n     StackData *data   = stack_data;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_ASSERT( data != NULL );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p )\\n\", __FUNCTION__, stack, wmdata, data );\n\n     data->stack = stack;\n\n     dfb_updates_init( &data->updates,  data->update_regions,   MAX_UPDATE_REGIONS );\n     dfb_updates_init( &data->updating, data->updating_regions, MAX_UPDATING_REGIONS );\n     dfb_updates_init( &data->updated,  data->updated_regions,  MAX_UPDATED_REGIONS );\n\n     fusion_vector_init( &data->windows, 64, stack->shmpool );\n\n     for (i = 0; i < MAX_KEYS; i++)\n          data->keys[i].code = -1;\n\n     ret = dfb_layer_context_get_primary_region( stack->context, true, &data->region );\n     if (ret)\n          return ret;\n\n     ret = dfb_layer_region_get_surface( data->region, &data->surface );\n     if (ret) {\n          dfb_layer_region_unref( data->region );\n          return ret;\n     }\n\n     dfb_layer_region_globalize( data->region );\n     dfb_surface_globalize( data->surface );\n\n     fusion_skirmish_init2( &data->update_skirmish, \"WM Update\", dfb_core_world(wmdata->core),\n                            fusion_config->secure_fusion );\n\n     dfb_surface_attach( data->surface, wm_surface_react, data, &data->surface_reaction );\n\n     /* Force fullscreen updates in window manager. */\n     if (direct_config_has_name( \"wm-fullscreen-updates\" ) && !direct_config_has_name( \"no-wm-fullscreen-updates\" ))\n          data->wm_fullscreen_updates = true;\n     else\n          data->wm_fullscreen_updates = false;\n\n     D_MAGIC_SET( data, StackData );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_close_stack( CoreWindowStack *stack,\n                void            *wm_data,\n                void            *stack_data )\n{\n     GrabbedKey *key, *next;\n     WMData     *wmdata = wm_data;\n     StackData  *data   = stack_data;\n\n     D_UNUSED_P( wmdata );\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( data, StackData );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p )\\n\", __FUNCTION__, stack, wmdata, data );\n\n     D_ASSUME( fusion_vector_is_empty( &data->windows ) );\n\n     if (fusion_vector_has_elements( &data->windows )) {\n          int         i;\n          CoreWindow *window;\n\n          fusion_vector_foreach (window, i, data->windows) {\n               window->stack = NULL;\n          }\n     }\n\n     fusion_vector_destroy( &data->windows );\n\n     dfb_surface_detach( data->surface, &data->surface_reaction );\n\n     dfb_layer_region_unlink( &data->region );\n\n     dfb_surface_unlink( &data->surface );\n\n     /* Destroy backing store of software cursor. */\n     if (data->cursor_bs)\n          dfb_surface_unlink( &data->cursor_bs );\n\n     /* Free grabbed keys. */\n     direct_list_foreach_safe (key, next, data->grabbed_keys) {\n          SHFREE( stack->shmpool, key );\n     }\n\n     fusion_skirmish_destroy( &data->update_skirmish );\n\n     D_MAGIC_CLEAR( data );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_set_active( CoreWindowStack *stack,\n               void            *wm_data,\n               void            *stack_data,\n               bool             active )\n{\n     WMData    *wmdata = wm_data;\n     StackData *data   = stack_data;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( data, StackData );\n\n     D_ASSUME( data->active != active );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p, %s )\\n\", __FUNCTION__,\n                 stack, wmdata, data, active ? \"active\" : \"inactive\" );\n\n     if (data->active == active)\n          return DFB_OK;\n\n     data->active = active;\n\n     if (active) {\n          if (!wmdata->refs)\n               local_init( wmdata, core_dfb );\n\n          return dfb_windowstack_repaint_all( stack );\n     }\n     else {\n          if (!--wmdata->refs)\n               local_deinit( wmdata );\n     }\n\n     /* Force release of all pressed keys. */\n     return wm_flush_keys( stack, wmdata, stack_data );\n}\n\nstatic DFBResult\nwm_resize_stack( CoreWindowStack *stack,\n                 void            *wm_data,\n                 void            *stack_data,\n                 int              width,\n                 int              height )\n{\n     WMData    *wmdata = wm_data;\n     StackData *data   = stack_data;\n\n     D_UNUSED_P( wmdata );\n     D_UNUSED_P( data );\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( data, StackData );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p, %dx%d )\\n\", __FUNCTION__, stack, wmdata, data, width, height );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_process_input( CoreWindowStack     *stack,\n                  void                *wm_data,\n                  void                *stack_data,\n                  const DFBInputEvent *event )\n{\n     DFBResult  ret;\n     WMData    *wmdata = wm_data;\n     StackData *data   = stack_data;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( data, StackData );\n     D_ASSERT( event != NULL );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p, device %u, type 0x%08x, flags 0x%08x )\\n\", __FUNCTION__,\n                 stack, wmdata, data, event->device_id, event->type, event->flags );\n\n     if (event->flags & DIEF_BUTTONS)\n          data->buttons = event->buttons;\n\n     if (event->flags & DIEF_MODIFIERS)\n          data->modifiers = event->modifiers;\n\n     if (event->flags & DIEF_LOCKS)\n          data->locks = event->locks;\n\n     if (event->type != DIET_AXISMOTION)\n          flush_motion( stack, data, wmdata );\n\n     switch (event->type) {\n          case DIET_KEYPRESS:\n               ret = handle_key_press( stack, data, wmdata, event );\n               break;\n\n          case DIET_KEYRELEASE:\n               ret = handle_key_release( stack, data, event );\n               break;\n\n          case DIET_BUTTONPRESS:\n               ret = handle_button_press( stack, data, event );\n               break;\n\n          case DIET_BUTTONRELEASE:\n               ret = handle_button_release( stack, data, event );\n               break;\n\n          case DIET_AXISMOTION:\n               ret = handle_axis_motion( stack, data, wmdata, event );\n               break;\n\n          default:\n               D_ONCE( \"unknown input event type\" );\n               ret = DFB_UNSUPPORTED;\n               break;\n     }\n\n     if (!D_FLAGS_IS_SET( event->flags, DIEF_FOLLOW ))\n          flush_motion( stack, data, wmdata );\n\n     process_updates( data, wmdata, stack, DSFLIP_NONE );\n\n     return ret;\n}\n\nstatic DFBResult\nwm_flush_keys( CoreWindowStack *stack,\n               void            *wm_data,\n               void            *stack_data )\n{\n     int        i;\n     WMData    *wmdata = wm_data;\n     StackData *data   = stack_data;\n\n     D_UNUSED_P( wmdata );\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( data, StackData );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p )\\n\", __FUNCTION__, stack, wmdata, data );\n\n     for (i = 0; i < MAX_KEYS; i++) {\n          if (data->keys[i].code != -1) {\n               DFBWindowEvent we;\n\n               we.type       = DWET_KEYUP;\n               we.key_code   = data->keys[i].code;\n               we.key_id     = data->keys[i].id;\n               we.key_symbol = data->keys[i].symbol;\n\n               post_event( data->keys[i].owner, data, &we );\n\n               data->keys[i].code = -1;\n          }\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_window_at( CoreWindowStack  *stack,\n              void             *wm_data,\n              void             *stack_data,\n              int               x,\n              int               y,\n              CoreWindow      **ret_window )\n{\n     WMData    *wmdata = wm_data;\n     StackData *data   = stack_data;\n\n     D_UNUSED_P( wmdata );\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( data, StackData );\n     D_ASSERT( ret_window != NULL );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p )\\n\", __FUNCTION__, stack, wmdata, data );\n\n     *ret_window = window_at_pointer( stack, data, x, y );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_window_lookup( CoreWindowStack  *stack,\n                  void             *wm_data,\n                  void             *stack_data,\n                  DFBWindowID       window_id,\n                  CoreWindow      **ret_window )\n{\n     int         i;\n     CoreWindow *window;\n     WMData     *wmdata = wm_data;\n     StackData  *data   = stack_data;\n\n     D_UNUSED_P( wmdata );\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( data, StackData );\n     D_ASSERT( ret_window != NULL );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p )\\n\", __FUNCTION__, stack, wmdata, data );\n\n     fusion_vector_foreach_reverse (window, i, data->windows) {\n          if (window->id == window_id) {\n               *ret_window = window;\n               return DFB_OK;\n          }\n     }\n\n     return DFB_IDNOTFOUND;\n}\n\nstatic DFBResult\nwm_enum_windows( CoreWindowStack      *stack,\n                 void                 *wm_data,\n                 void                 *stack_data,\n                 CoreWMWindowCallback  callback,\n                 void                 *callback_ctx )\n{\n     int         i;\n     CoreWindow *window;\n     WMData     *wmdata = wm_data;\n     StackData  *data   = stack_data;\n\n     D_UNUSED_P( wmdata );\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( data, StackData );\n     D_ASSERT( callback != NULL );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p )\\n\", __FUNCTION__, stack, wmdata, data );\n\n     fusion_vector_foreach_reverse (window, i, data->windows) {\n          if (callback( window, callback_ctx ) != DFENUM_OK)\n               break;\n     }\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_get_insets( CoreWindowStack *stack,\n               CoreWindow      *window,\n               DFBInsets       *insets )\n{\n     D_ASSERT( stack != NULL );\n     D_ASSERT( window != NULL );\n     D_ASSERT( insets != NULL );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p )\\n\", __FUNCTION__, stack, window, insets );\n\n     insets->l = 0;\n     insets->t = 0;\n     insets->r = 0;\n     insets->b = 0;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_preconfigure_window( CoreWindowStack *stack,\n                        void            *wm_data,\n                        void            *stack_data,\n                        CoreWindow      *window,\n                        void            *window_data )\n{\n     WMData     *wmdata = wm_data;\n     StackData  *data   = stack_data;\n     WindowData *win    = window_data;\n\n     D_UNUSED_P( wmdata );\n     D_UNUSED_P( data );\n     D_UNUSED_P( win );\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( data, StackData );\n     D_ASSERT( window != NULL );\n     D_ASSERT( win != NULL );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p, %p, %p )\\n\", __FUNCTION__, stack, wmdata, data, window, win );\n\n     if (window->config.association)\n          return DFB_UNIMPLEMENTED;\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_set_window_property( CoreWindowStack  *stack,\n                        void             *wm_data,\n                        void             *stack_data,\n                        CoreWindow       *window,\n                        void             *window_data,\n                        const char       *key,\n                        void             *value,\n                        void            **ret_old_value )\n{\n     WMData     *wmdata = wm_data;\n     StackData  *data   = stack_data;\n     WindowData *win    = window_data;\n\n     D_UNUSED_P( wmdata );\n     D_UNUSED_P( data );\n     D_UNUSED_P( win );\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( data, StackData );\n     D_ASSERT( window != NULL );\n     D_MAGIC_ASSERT( win, WindowData );\n     D_ASSERT( key != NULL );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p, %p, %p )\\n\", __FUNCTION__, stack, wmdata, data, window, win );\n\n     fusion_object_set_property( (FusionObject*) window, key, value, ret_old_value );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_get_window_property( CoreWindowStack  *stack,\n                        void             *wm_data,\n                        void             *stack_data,\n                        CoreWindow       *window,\n                        void             *window_data,\n                        const char       *key,\n                        void            **ret_value )\n{\n     WMData     *wmdata = wm_data;\n     StackData  *data   = stack_data;\n     WindowData *win    = window_data;\n\n     D_UNUSED_P( wmdata );\n     D_UNUSED_P( data );\n     D_UNUSED_P( win );\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( data, StackData );\n     D_ASSERT( window != NULL );\n     D_MAGIC_ASSERT( win, WindowData );\n     D_ASSERT( key != NULL );\n     D_ASSERT( ret_value != NULL );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p, %p, %p )\\n\", __FUNCTION__, stack, wmdata, data, window, win );\n\n     *ret_value = fusion_object_get_property( (FusionObject*) window,key );\n\n     return DFB_OK;\n}\n\n\nstatic DFBResult\nwm_remove_window_property( CoreWindowStack  *stack,\n                           void             *wm_data,\n                           void             *stack_data,\n                           CoreWindow       *window,\n                           void             *window_data,\n                           const char       *key,\n                           void            **ret_value )\n{\n     WMData    *wmdata = wm_data;\n     StackData *data   = stack_data;\n\n     D_UNUSED_P( wmdata );\n     D_UNUSED_P( data );\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( data, StackData );\n     D_ASSERT( window != NULL );\n     D_ASSERT( window_data != NULL );\n     D_ASSERT( key != NULL );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p )\\n\", __FUNCTION__, stack, wmdata, data );\n\n     fusion_object_remove_property( (FusionObject*) window,key, ret_value );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_add_window( CoreWindowStack *stack,\n               void            *wm_data,\n               void            *stack_data,\n               CoreWindow      *window,\n               void            *window_data )\n{\n     WMData     *wmdata = wm_data;\n     StackData  *data   = stack_data;\n     WindowData *win    = window_data;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( data, StackData );\n     D_ASSERT( window != NULL );\n     D_ASSERT( win != NULL );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p, %p, %p )\\n\", __FUNCTION__, stack, wmdata, data, window, win );\n\n     /* Initialize window data. */\n     win->window     = window;\n     win->stack_data = stack_data;\n     win->priority   = get_priority( window );\n\n     if (window->region && window->stack->context->config.buffermode == DLBM_WINDOWS)\n          dfb_layer_region_get_configuration( window->region, &win->config );\n\n     D_MAGIC_SET( win, WindowData );\n\n     /* Send notification to windows watchers. */\n     dfb_wm_dispatch_WindowAdd( wmdata->core, window );\n\n     /* Actually add the window to the stack. */\n     insert_window( wmdata, stack, data, window, win );\n\n     /* Possibly switch focus to the new window. */\n     update_focus( stack, data, wmdata );\n\n     process_updates( data, wmdata, stack, DSFLIP_NONE );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_remove_window( CoreWindowStack *stack,\n                  void            *wm_data,\n                  void            *stack_data,\n                  CoreWindow      *window,\n                  void            *window_data )\n{\n     WMData     *wmdata = wm_data;\n     StackData  *data   = stack_data;\n     WindowData *win    = window_data;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( data, StackData );\n     D_ASSERT( window != NULL );\n     D_MAGIC_ASSERT( win, WindowData );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p, %p, %p )\\n\", __FUNCTION__, stack, wmdata, data, window, win );\n\n     /* Send notification to windows watchers. */\n     dfb_wm_dispatch_WindowRemove( wmdata->core, window );\n\n     remove_window( wmdata, stack, data, window, win );\n\n     if (window->cursor.surface && !(window->config.cursor_flags & DWCF_INVISIBLE)) {\n          CoreSurface *shape;\n          int          hot_x, hot_y;\n\n          dfb_layer_context_get_cursor_shape( stack->context, &shape, &hot_x, &hot_y );\n\n          dfb_windowstack_cursor_set_shape( stack, shape, hot_x, hot_y );\n     }\n\n     /* Free keys list. */\n     if (window->config.keys) {\n          SHFREE( stack->shmpool, window->config.keys );\n\n          window->config.keys     = NULL;\n          window->config.num_keys = 0;\n     }\n\n     D_MAGIC_CLEAR( win );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_set_window_config( CoreWindow             *window,\n                      void                   *wm_data,\n                      void                   *window_data,\n                      const CoreWindowConfig *config,\n                      DFBWindowConfigFlags    flags )\n{\n     DFBResult   ret;\n     WMData     *wmdata = wm_data;\n     WindowData *win    = window_data;\n     StackData  *data;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( win, WindowData );\n     D_ASSERT( config != NULL );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p, flags 0x%08x )\\n\", __FUNCTION__, window, wmdata, win, flags );\n\n     data = window->stack->stack_data;\n\n     D_MAGIC_ASSERT( data, StackData );\n\n     if (flags & DWCONF_OPTIONS) {\n          if ((window->config.options & DWOP_SCALE) && !(config->options & DWOP_SCALE) && window->surface) {\n               if (window->config.bounds.w != window->surface->config.size.w ||\n                   window->config.bounds.h != window->surface->config.size.h) {\n                    ret = dfb_surface_reformat( window->surface, window->config.bounds.w, window->config.bounds.h,\n                                                window->surface->config.format );\n                    if (ret) {\n                         D_DERROR( ret, \"WM/Default: Failed resizing surface (%dx%d -> %dx%d) to remove DWOP_SCALE!\\n\",\n                                   window->surface->config.size.w, window->surface->config.size.h,\n                                   window->config.bounds.w, window->config.bounds.h );\n                         return ret;\n                    }\n               }\n          }\n\n          window->config.options = config->options;\n     }\n\n     if (flags & DWCONF_EVENTS)\n          window->config.events = config->events;\n\n     if (flags & DWCONF_COLOR)\n          return DFB_UNSUPPORTED;\n\n     if (flags & DWCONF_COLOR_KEY)\n          window->config.color_key = config->color_key;\n\n     if (flags & DWCONF_OPAQUE)\n          window->config.opaque = config->opaque;\n\n     if (flags & DWCONF_OPACITY && !config->opacity)\n          set_opacity( window, win, wmdata, config->opacity );\n\n     if (flags == (DWCONF_POSITION | DWCONF_SIZE)) {\n          ret = set_window_bounds( window, wmdata, win,\n                                   config->bounds.x, config->bounds.y, config->bounds.w, config->bounds.h );\n          if (ret)\n              return ret;\n     }\n     else {\n          if (flags & DWCONF_POSITION) {\n               ret = move_window( window, win,\n                                  config->bounds.x - window->config.bounds.x,\n                                  config->bounds.y - window->config.bounds.y );\n               if (ret)\n                    return ret;\n          }\n\n          if (flags & DWCONF_SIZE) {\n               ret = resize_window( window, wmdata, win, config->bounds.w, config->bounds.h );\n               if (ret)\n                    return ret;\n          }\n     }\n\n     if (flags & DWCONF_ROTATION) {\n          update_window( window, win, NULL, DSFLIP_NONE, false, false, false );\n\n          window->config.rotation = config->rotation;\n\n          update_window( window, win, NULL, DSFLIP_NONE, false, false, false );\n     }\n\n     if (flags & DWCONF_STACKING)\n          restack_window( wmdata, window, win, window, win, 0, config->stacking );\n\n     if (flags & DWCONF_OPACITY && config->opacity)\n          set_opacity( window, win, wmdata, config->opacity );\n\n     if (flags & DWCONF_KEY_SELECTION) {\n          if (config->key_selection == DWKS_LIST) {\n               unsigned int             bytes = sizeof(DFBInputDeviceKeySymbol) * config->num_keys;\n               DFBInputDeviceKeySymbol *keys;\n\n               D_ASSERT( config->keys != NULL );\n               D_ASSERT( config->num_keys > 0 );\n\n               keys = SHMALLOC( window->stack->shmpool, bytes );\n               if (!keys) {\n                    D_ERROR( \"WM/Default: Could not allocate %u bytes for list of selected keys (%u)!\\n\",\n                             bytes, config->num_keys );\n                    return D_OOSHM();\n               }\n\n               direct_memcpy( keys, config->keys, bytes );\n\n               qsort( keys, config->num_keys, sizeof(DFBInputDeviceKeySymbol), keys_compare );\n\n               if (window->config.keys)\n                    SHFREE( window->stack->shmpool, window->config.keys );\n\n               window->config.keys     = keys;\n               window->config.num_keys = config->num_keys;\n          }\n          else if (window->config.keys) {\n               SHFREE( window->stack->shmpool, window->config.keys );\n\n               window->config.keys     = NULL;\n               window->config.num_keys = 0;\n          }\n\n          window->config.key_selection = config->key_selection;\n     }\n\n     if (flags & DWCONF_CURSOR_FLAGS) {\n          if ((config->cursor_flags & DWCF_INVISIBLE) && !(window->config.cursor_flags & DWCF_INVISIBLE)) {\n               CoreSurface *shape;\n               int          hot_x, hot_y;\n\n               dfb_layer_context_get_cursor_shape( window->stack->context, &shape, &hot_x, &hot_y );\n\n               dfb_windowstack_cursor_set_shape( window->stack, shape, hot_x, hot_y );\n          }\n\n          if (!(config->cursor_flags & DWCF_INVISIBLE) && (window->config.cursor_flags & DWCF_INVISIBLE))\n               dfb_windowstack_cursor_set_shape( window->stack,\n                                                 window->cursor.surface, window->cursor.hot_x, window->cursor.hot_y );\n\n          window->config.cursor_flags = config->cursor_flags;\n     }\n\n     /* Send notification to windows watchers. */\n     dfb_wm_dispatch_WindowConfig( wmdata->core, window, flags );\n\n     process_updates( data, wmdata, window->stack, DSFLIP_NONE );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_restack_window( CoreWindow *window,\n                   void       *wm_data,\n                   void       *window_data,\n                   CoreWindow *relative,\n                   void       *relative_data,\n                   int         relation )\n{\n     DFBResult   ret;\n     WMData     *wmdata = wm_data;\n     WindowData *win    = window_data;\n     StackData  *data;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( win, WindowData );\n     D_ASSERT( relative == NULL || relative_data != NULL );\n     D_ASSERT( relative == NULL || relative == window || relation != 0);\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p, %p, %p, %s )\\n\", __FUNCTION__,\n                 window, wmdata, win, relative, relative_data, (relation == 1) ? \"TOP\" : \"BOTTOM\" );\n\n     data = win->stack_data;\n\n     D_MAGIC_ASSERT( data, StackData );\n\n     ret = restack_window( wmdata, window, win, relative, relative_data, relation, window->config.stacking );\n     if (ret)\n          return ret;\n\n     /* Possibly switch focus to window now under the cursor. */\n     update_focus( data->stack, data, wmdata );\n\n     process_updates( data, wmdata, window->stack, DSFLIP_NONE );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_grab( CoreWindow *window,\n         void       *wm_data,\n         void       *window_data,\n         CoreWMGrab *grab )\n{\n     WMData     *wmdata = wm_data;\n     WindowData *win    = window_data;\n     StackData  *data;\n\n     D_UNUSED_P( wmdata );\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( win, WindowData );\n     D_ASSERT( grab != NULL );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p, %p )\\n\", __FUNCTION__, window, wmdata, win, grab );\n\n     data = win->stack_data;\n\n     D_MAGIC_ASSERT( data, StackData );\n\n     switch (grab->target) {\n          case CWMGT_KEYBOARD:\n               return grab_keyboard( window, win );\n\n          case CWMGT_POINTER:\n               return grab_pointer( window, win );\n\n          case CWMGT_KEY:\n               return grab_key( window, win, grab->symbol, grab->modifiers );\n\n          case CWMGT_UNSELECTED_KEYS:\n               if (data->unselkeys_window)\n                    return DFB_LOCKED;\n\n               data->unselkeys_window = window;\n               return DFB_OK;\n\n          default:\n               D_BUG( \"unknown grab target\" );\n               break;\n     }\n\n     return DFB_BUG;\n}\n\nstatic DFBResult\nwm_ungrab( CoreWindow *window,\n           void       *wm_data,\n           void       *window_data,\n           CoreWMGrab *grab )\n{\n     WMData     *wmdata = wm_data;\n     WindowData *win    = window_data;\n     StackData  *data;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( win, WindowData );\n     D_ASSERT( grab != NULL );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p, %p )\\n\", __FUNCTION__, window, wmdata, win, grab );\n\n     data = win->stack_data;\n\n     D_MAGIC_ASSERT( data, StackData );\n\n     switch (grab->target) {\n          case CWMGT_KEYBOARD:\n               return ungrab_keyboard( window, win );\n\n          case CWMGT_POINTER:\n               return ungrab_pointer( window, win, wmdata );\n\n          case CWMGT_KEY:\n               return ungrab_key( window, win, grab->symbol, grab->modifiers );\n\n          case CWMGT_UNSELECTED_KEYS:\n               if (data->unselkeys_window == window)\n                    data->unselkeys_window = NULL;\n\n               return DFB_OK;\n\n          default:\n               D_BUG( \"unknown grab target\" );\n               break;\n     }\n\n     return DFB_BUG;\n}\n\nstatic DFBResult\nwm_request_focus( CoreWindow *window,\n                  void       *wm_data,\n                  void       *window_data )\n{\n     WMData     *wmdata = wm_data;\n     WindowData *win    = window_data;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( win, WindowData );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p )\\n\", __FUNCTION__, window, wmdata, win );\n\n     return request_focus( wmdata, window, win );\n}\n\nstatic DFBResult\nwm_begin_updates( CoreWindow      *window,\n                  void            *wm_data,\n                  void            *window_data,\n                  const DFBRegion *update )\n{\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_set_cursor_position( CoreWindow *window,\n                        void       *wm_data,\n                        void       *window_data,\n                        int         x,\n                        int         y )\n{\n     D_UNIMPLEMENTED();\n\n     return DFB_UNIMPLEMENTED;\n}\n\nstatic DFBResult\nwm_update_stack( CoreWindowStack     *stack,\n                 void                *wm_data,\n                 void                *stack_data,\n                 const DFBRegion     *region,\n                 DFBSurfaceFlipFlags  flags )\n{\n\n     WMData    *wmdata = wm_data;\n     StackData *data   = stack_data;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( data, StackData );\n     D_ASSERT( region != NULL );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p, %4d,%4d-%4dx%4d, flags 0x%08x )\\n\", __FUNCTION__,\n                 stack, wmdata, data, DFB_RECTANGLE_VALS_FROM_REGION( region ), flags );\n\n     dfb_updates_add( &data->updates, region );\n\n     process_updates( data, wmdata, stack, flags );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_update_window( CoreWindow          *window,\n                  void                *wm_data,\n                  void                *window_data,\n                  const DFBRegion     *left_region,\n                  const DFBRegion     *right_region,\n                  DFBSurfaceFlipFlags  flags )\n{\n     WMData     *wmdata = wm_data;\n     WindowData *win = window_data;\n     StackData  *data;\n\n     D_ASSERT( window != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( win, WindowData );\n     DFB_REGION_ASSERT_IF( left_region );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p, %4d,%4d-%4dx%4d, flags 0x%08x )\\n\", __FUNCTION__,\n                 window, wmdata, win, DFB_RECTANGLE_VALS_FROM_REGION( left_region ), flags );\n\n     data = window->stack->stack_data;\n\n     D_MAGIC_ASSERT( data, StackData );\n\n     send_update_event( window, data, left_region );\n\n     update_window( window, win, left_region, flags, false, false, true );\n\n     process_updates( data, wmdata, window->stack, flags );\n\n     return DFB_OK;\n}\n\nstatic DFBResult\nwm_update_cursor( CoreWindowStack       *stack,\n                  void                  *wm_data,\n                  void                  *stack_data,\n                  CoreCursorUpdateFlags  flags )\n{\n     DFBResult        ret;\n     int              i;\n     DFBRegion        old_dest;\n     DFBRegion        united;\n     CoreLayerRegion *primary;\n     DFBRegion        updates[2];\n     int              updates_count = 0;\n     bool             restored      = false;\n     WMData          *wmdata        = wm_data;\n     StackData       *data          = stack_data;\n\n     D_ASSERT( stack != NULL );\n     D_ASSERT( wmdata != NULL );\n     D_MAGIC_ASSERT( data, StackData );\n\n     D_DEBUG_AT( Default_WM, \"%s( %p, %p, %p, flags 0x%08x )\\n\", __FUNCTION__, stack, wmdata, data, flags );\n\n     transform_stack_to_dest( stack, &data->cursor_region, &old_dest );\n\n     if (flags & (CCUF_ENABLE | CCUF_POSITION | CCUF_SIZE)) {\n          data->cursor_bs_valid  = false;\n          data->cursor_region.x1 = stack->cursor.x - stack->cursor.hot.x;\n          data->cursor_region.y1 = stack->cursor.y - stack->cursor.hot.y;\n          data->cursor_region.x2 = data->cursor_region.x1 + stack->cursor.size.w - 1;\n          data->cursor_region.y2 = data->cursor_region.y1 + stack->cursor.size.h - 1;\n\n          if (!dfb_region_intersect( &data->cursor_region, 0, 0, stack->width - 1, stack->height - 1 )) {\n               D_BUG( \"invalid cursor region\" );\n               return DFB_BUG;\n          }\n     }\n\n     /* Optimize case of invisible cursor moving. */\n     if (!(flags & ~(CCUF_POSITION | CCUF_SHAPE)) && (!stack->cursor.opacity || !stack->cursor.enabled))\n          return DFB_OK;\n\n     if (!data->cursor_bs) {\n          CoreSurface            *cursor_bs;\n          DFBSurfaceCapabilities  caps = DSCAPS_NONE;\n          DFBDimension            size = stack->cursor.size;\n\n          D_ASSUME( flags & CCUF_ENABLE );\n\n          dfb_surface_caps_apply_policy( stack->cursor.policy, &caps );\n\n          if (stack->rotation == 90 || stack->rotation == 270)\n               D_UTIL_SWAP( size.w, size.h );\n\n          /* Create the cursor backing store surface. */\n          ret = dfb_surface_create_simple( wmdata->core, size.w, size.h, stack->context->config.pixelformat,\n                                           stack->context->config.colorspace, caps, CSTF_SHARED | CSTF_CURSOR, 0,\n                                           NULL, &cursor_bs );\n          if (ret) {\n               D_ERROR( \"WM/Default: Failed to create backing store for cursor!\\n\" );\n               return ret;\n          }\n\n          dfb_surface_globalize( cursor_bs );\n\n          data->cursor_bs = cursor_bs;\n     }\n\n     /* Get the primary region. */\n     primary = data->region;\n\n     fusion_skirmish_prevail( &data->update_skirmish );\n\n     /* Restore region under cursor. */\n     if (data->cursor_drawn) {\n          D_ASSERT( stack->cursor.opacity || (flags & CCUF_OPACITY) );\n\n          if (data->active) {\n               DFBRegion region = { 0, 0, old_dest.x2 - old_dest.x1, old_dest.y2 - old_dest.y1 };\n\n               dfb_gfx_copy_regions_client( data->cursor_bs, DSBR_BACK, DSSE_LEFT, primary->surface, DSBR_BACK,\n                                            DSSE_LEFT, &region, 1, old_dest.x1, old_dest.y1, &wmdata->client );\n\n               CoreGraphicsStateClient_Flush( &wmdata->client );\n\n               restored = true;\n          }\n\n          data->cursor_drawn = false;\n     }\n\n     if (flags & CCUF_SIZE) {\n          DFBDimension size = stack->cursor.size;\n\n          if (stack->rotation == 90 || stack->rotation == 270)\n               D_UTIL_SWAP( size.w, size.h );\n\n          ret = dfb_surface_reformat( data->cursor_bs, size.w, size.h, data->cursor_bs->config.format );\n          if (ret)\n               D_DERROR( ret, \"WM/Default: Failed resizing backing store for cursor from %dx%d to %dx%d!\\n\",\n                         data->cursor_bs->config.size.w, data->cursor_bs->config.size.h,\n                         stack->cursor.size.w, stack->cursor.size.h );\n     }\n\n     if (flags & CCUF_DISABLE) {\n          dfb_surface_unlink( &data->cursor_bs );\n     }\n     else if (stack->cursor.opacity) {\n          DFBRegion dest;\n\n          transform_stack_to_dest( stack, &data->cursor_region, &dest );\n\n          if (!dfb_region_intersect( &dest, 0, 0,\n                                     primary->surface->config.size.w - 1, primary->surface->config.size.h - 1 )) {\n               if (restored)\n                    updates[updates_count++] = old_dest;\n          }\n          else {\n               CardState *state = &wmdata->state;\n\n               /* Backup region under cursor. */\n               if (!data->cursor_bs_valid) {\n                    dfb_gfx_copy_regions_client( primary->surface, DSBR_BACK, DSSE_LEFT, data->cursor_bs, DSBR_BACK,\n                                                 DSSE_LEFT, &dest, 1, -dest.x1, -dest.y1, &wmdata->client );\n\n                    data->cursor_bs_valid = true;\n               }\n\n               /* Set destination. */\n               state->destination  = primary->surface;\n               state->modified    |= SMF_DESTINATION;\n\n               /* Set clipping region. */\n               dfb_state_set_clip( state, &dest );\n\n               /* Draw cursor. */\n               draw_cursor( stack, state, &data->cursor_region );\n\n               /* Reset destination. */\n               state->destination  = NULL;\n               state->modified    |= SMF_DESTINATION;\n\n               CoreGraphicsStateClient_Flush( &wmdata->client );\n\n               data->cursor_drawn = true;\n\n               if (restored) {\n                    if (dfb_region_region_intersects( &old_dest, &dest ))\n                         dfb_region_region_union( &old_dest, &dest );\n                    else\n                         updates[updates_count++] = dest;\n\n                    updates[updates_count++] = old_dest;\n               }\n               else\n                    updates[updates_count++] = dest;\n\n               /* Pan to follow the cursor. */\n               if (primary->config.source.w < primary->surface->config.size.w ||\n                   primary->config.source.h < primary->surface->config.size.h) {\n                    DFBRectangle source = primary->config.source;\n\n                    if (stack->rotation)\n                         D_UNIMPLEMENTED();\n\n                    if (source.x > stack->cursor.x)\n                         source.x = stack->cursor.x;\n                    else if (source.x + source.w - 1 < stack->cursor.x)\n                         source.x = stack->cursor.x - source.w + 1;\n\n                    if (source.y > stack->cursor.y)\n                         source.y = stack->cursor.y;\n                    else if (source.y + source.h - 1 < stack->cursor.y)\n                         source.y = stack->cursor.y - source.h + 1;\n\n                    dfb_layer_context_set_sourcerectangle( stack->context, &source );\n               }\n          }\n     }\n     else if (restored)\n          updates[updates_count++] = old_dest;\n\n     if (updates_count) {\n          switch (primary->config.buffermode) {\n               case DLBM_TRIPLE:\n                    /* Add the updated region .*/\n                    for (i = 0; i < updates_count; i++) {\n                         const DFBRegion *update = &updates[i];\n                         dfb_updates_add( &data->updating, update );\n                    }\n\n                    if (!data->updated.num_regions)\n                         flush_updating( data );\n\n                    break;\n\n               case DLBM_BACKVIDEO:\n                    /* Flip the united region. */\n                    dfb_regions_unite( &united, updates, updates_count );\n                    dfb_layer_region_flip_update( primary, &united, DSFLIP_BLIT );\n\n                    break;\n\n               default:\n                    /* Flip the updated region .*/\n                    for (i = 0; i < updates_count; i++) {\n                         const DFBRegion *update = &updates[i];\n                         dfb_layer_region_flip_update( primary, update, DSFLIP_NONE );\n                    }\n\n                    break;\n          }\n     }\n\n     CoreGraphicsStateClient_Flush( &wmdata->client );\n\n     fusion_skirmish_dismiss( &data->update_skirmish );\n\n     return DFB_OK;\n}\n"
  },
  {
    "path": "wm/default/meson.build",
    "content": "#  This file is part of DirectFB.\n#\n#  This library is free software; you can redistribute it and/or\n#  modify it under the terms of the GNU Lesser General Public\n#  License as published by the Free Software Foundation; either\n#  version 2.1 of the License, or (at your option) any later version.\n#\n#  This library is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n#  Lesser General Public License for more details.\n#\n#  You should have received a copy of the GNU Lesser General Public\n#  License along with this library; if not, write to the Free Software\n#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\nlibrary('directfbwm_default',\n        'default.c',\n        include_directories: config_inc,\n        build_rpath: get_option('prefix') / get_option('libdir'),\n        dependencies: directfb_dep,\n        install: true,\n        install_dir: moduledir / 'wm',\n        install_rpath: get_option('prefix') / get_option('libdir'))\n\nif get_option('default_library') == 'static'\n  pkgconfig.generate(filebase: 'directfb-wm-default',\n                     variables: 'moduledir=' + moduledir,\n                     name: 'DirectFB-wm-default',\n                     description: 'Default window manager module',\n                     libraries_private: ['-L${moduledir}/wm',\n                                         '-Wl,--whole-archive -ldirectfbwm_default -Wl,--no-whole-archive'])\nendif\n"
  }
]