Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Adding the Gamepad sample project.

  • Loading branch information...
commit adfc0405d749a42d091ccb532f52d7635ef0b805 1 parent 4d6b055
@ablake ablake authored
View
143 Gamepad/.cproject
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?>
+
+<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+ <storageModule moduleId="org.eclipse.cdt.core.settings">
+ <cconfiguration id="com.qnx.qcc.toolChain.390350634">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.qnx.qcc.toolChain.390350634" moduleId="org.eclipse.cdt.core.settings" name="Device-Debug">
+ <externalSettings/>
+ <extensions>
+ <extension id="com.qnx.tools.ide.qde.core.QDEBynaryParser" point="org.eclipse.cdt.core.BinaryParser"/>
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ </extensions>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <configuration artifactName="${ProjName}" buildProperties="" description="" id="com.qnx.qcc.toolChain.390350634" name="Device-Debug" parent="org.eclipse.cdt.build.core.emptycfg">
+ <folderInfo id="com.qnx.qcc.toolChain.390350634.1548013172" name="/" resourcePath="">
+ <toolChain id="com.qnx.qcc.toolChain.1984889761" name="com.qnx.qcc.toolChain" superClass="com.qnx.qcc.toolChain">
+ <option id="com.qnx.qcc.option.os.1090528646" name="Target OS:" superClass="com.qnx.qcc.option.os"/>
+ <option id="com.qnx.qcc.option.cpu.289875851" name="Target CPU:" superClass="com.qnx.qcc.option.cpu" value="com.qnx.qcc.option.gen.cpu.armle-v7" valueType="enumerated"/>
+ <option id="com.qnx.qcc.option.compiler.1681128974" name="Compiler:" superClass="com.qnx.qcc.option.compiler"/>
+ <option id="com.qnx.qcc.option.runtime.1778226308" name="Runtime:" superClass="com.qnx.qcc.option.runtime"/>
+ <targetPlatform archList="all" binaryParser="com.qnx.tools.ide.qde.core.QDEBynaryParser" id="com.qnx.qcc.targetPlatform.1173569877" osList="all" superClass="com.qnx.qcc.targetPlatform"/>
+ <builder id="com.qnx.qcc.toolChain.390350634.1895625102" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
+ <tool id="com.qnx.qcc.tool.compiler.1151256009" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler">
+ <option id="com.qnx.qcc.option.compiler.optlevel.1273515456" name="Optimization Level" superClass="com.qnx.qcc.option.compiler.optlevel" value="com.qnx.qcc.option.compiler.optlevel.0" valueType="enumerated"/>
+ <option id="com.qnx.qcc.option.compiler.includePath.265457507" name="Include Directories (-I)" superClass="com.qnx.qcc.option.compiler.includePath" valueType="includePath">
+ <listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/freetype2"/>
+ <listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/usr/include"/>
+ </option>
+ <inputType id="com.qnx.qcc.inputType.compiler.1987247163" superClass="com.qnx.qcc.inputType.compiler"/>
+ </tool>
+ <tool id="com.qnx.qcc.tool.assembler.1103285507" name="QCC Assembler" superClass="com.qnx.qcc.tool.assembler">
+ <option id="com.qnx.qcc.option.assembler.includePath.2108061316" name="Include Directories (-I)" superClass="com.qnx.qcc.option.assembler.includePath" valueType="includePath"/>
+ <inputType id="com.qnx.qcc.inputType.assembler.408597155" superClass="com.qnx.qcc.inputType.assembler"/>
+ </tool>
+ <tool id="com.qnx.qcc.tool.linker.34746028" name="QCC Linker" superClass="com.qnx.qcc.tool.linker"/>
+ <tool id="com.qnx.qcc.tool.archiver.1256583282" name="QCC Archiver" superClass="com.qnx.qcc.tool.archiver"/>
+ </toolChain>
+ </folderInfo>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ <cconfiguration id="com.qnx.qcc.toolChain.1617467616">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.qnx.qcc.toolChain.1617467616" moduleId="org.eclipse.cdt.core.settings" name="Device-Release">
+ <externalSettings/>
+ <extensions>
+ <extension id="com.qnx.tools.ide.qde.core.QDEBynaryParser" point="org.eclipse.cdt.core.BinaryParser"/>
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ </extensions>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <configuration artifactName="${ProjName}" buildProperties="" description="" id="com.qnx.qcc.toolChain.1617467616" name="Device-Release" parent="org.eclipse.cdt.build.core.emptycfg">
+ <folderInfo id="com.qnx.qcc.toolChain.1617467616.1334455277" name="/" resourcePath="">
+ <toolChain id="com.qnx.qcc.toolChain.1849024898" name="com.qnx.qcc.toolChain" superClass="com.qnx.qcc.toolChain">
+ <option id="com.qnx.qcc.option.os.343907073" name="Target OS:" superClass="com.qnx.qcc.option.os"/>
+ <option id="com.qnx.qcc.option.cpu.273626215" name="Target CPU:" superClass="com.qnx.qcc.option.cpu" value="com.qnx.qcc.option.gen.cpu.armle-v7" valueType="enumerated"/>
+ <option id="com.qnx.qcc.option.compiler.679731616" name="Compiler:" superClass="com.qnx.qcc.option.compiler"/>
+ <option id="com.qnx.qcc.option.runtime.36248023" name="Runtime:" superClass="com.qnx.qcc.option.runtime"/>
+ <targetPlatform archList="all" binaryParser="com.qnx.tools.ide.qde.core.QDEBynaryParser" id="com.qnx.qcc.targetPlatform.1848398365" osList="all" superClass="com.qnx.qcc.targetPlatform"/>
+ <builder id="com.qnx.qcc.toolChain.1617467616.405505895" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
+ <tool id="com.qnx.qcc.tool.compiler.2103104321" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler">
+ <option id="com.qnx.qcc.option.compiler.optlevel.1375075078" name="Optimization Level" superClass="com.qnx.qcc.option.compiler.optlevel" value="com.qnx.qcc.option.compiler.optlevel.0" valueType="enumerated"/>
+ <option id="com.qnx.qcc.option.compiler.includePath.1775163710" name="Include Directories (-I)" superClass="com.qnx.qcc.option.compiler.includePath" valueType="includePath">
+ <listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/freetype2"/>
+ <listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/usr/include"/>
+ </option>
+ <inputType id="com.qnx.qcc.inputType.compiler.968949772" superClass="com.qnx.qcc.inputType.compiler"/>
+ </tool>
+ <tool id="com.qnx.qcc.tool.assembler.435496715" name="QCC Assembler" superClass="com.qnx.qcc.tool.assembler">
+ <inputType id="com.qnx.qcc.inputType.assembler.1498143103" superClass="com.qnx.qcc.inputType.assembler"/>
+ </tool>
+ <tool id="com.qnx.qcc.tool.linker.1099015256" name="QCC Linker" superClass="com.qnx.qcc.tool.linker"/>
+ <tool id="com.qnx.qcc.tool.archiver.2037063939" name="QCC Archiver" superClass="com.qnx.qcc.tool.archiver"/>
+ </toolChain>
+ </folderInfo>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ <cconfiguration id="com.qnx.qcc.toolChain.1476280319">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.qnx.qcc.toolChain.1476280319" moduleId="org.eclipse.cdt.core.settings" name="Simulator-Debug">
+ <externalSettings/>
+ <extensions>
+ <extension id="com.qnx.tools.ide.qde.core.QDEBynaryParser" point="org.eclipse.cdt.core.BinaryParser"/>
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ </extensions>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <configuration artifactName="${ProjName}" buildProperties="" description="" id="com.qnx.qcc.toolChain.1476280319" name="Simulator-Debug" parent="org.eclipse.cdt.build.core.emptycfg">
+ <folderInfo id="com.qnx.qcc.toolChain.1476280319.962562248" name="/" resourcePath="">
+ <toolChain id="com.qnx.qcc.toolChain.1675104964" name="com.qnx.qcc.toolChain" superClass="com.qnx.qcc.toolChain">
+ <option id="com.qnx.qcc.option.os.2055872665" name="Target OS:" superClass="com.qnx.qcc.option.os"/>
+ <option id="com.qnx.qcc.option.cpu.1656311130" name="Target CPU:" superClass="com.qnx.qcc.option.cpu"/>
+ <option id="com.qnx.qcc.option.compiler.1234944239" name="Compiler:" superClass="com.qnx.qcc.option.compiler"/>
+ <option id="com.qnx.qcc.option.runtime.773447680" name="Runtime:" superClass="com.qnx.qcc.option.runtime"/>
+ <targetPlatform archList="all" binaryParser="com.qnx.tools.ide.qde.core.QDEBynaryParser" id="com.qnx.qcc.targetPlatform.48861335" osList="all" superClass="com.qnx.qcc.targetPlatform"/>
+ <builder id="com.qnx.qcc.toolChain.1476280319.552263927" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
+ <tool id="com.qnx.qcc.tool.compiler.1863626225" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler">
+ <option id="com.qnx.qcc.option.compiler.optlevel.1026010810" name="Optimization Level" superClass="com.qnx.qcc.option.compiler.optlevel" value="com.qnx.qcc.option.compiler.optlevel.0" valueType="enumerated"/>
+ <option id="com.qnx.qcc.option.compiler.includePath.1250297703" name="Include Directories (-I)" superClass="com.qnx.qcc.option.compiler.includePath" valueType="includePath">
+ <listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/freetype2"/>
+ <listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/usr/include"/>
+ </option>
+ <inputType id="com.qnx.qcc.inputType.compiler.187001612" superClass="com.qnx.qcc.inputType.compiler"/>
+ </tool>
+ <tool id="com.qnx.qcc.tool.assembler.348260754" name="QCC Assembler" superClass="com.qnx.qcc.tool.assembler">
+ <inputType id="com.qnx.qcc.inputType.assembler.1980902194" superClass="com.qnx.qcc.inputType.assembler"/>
+ </tool>
+ <tool id="com.qnx.qcc.tool.linker.203162122" name="QCC Linker" superClass="com.qnx.qcc.tool.linker"/>
+ <tool id="com.qnx.qcc.tool.archiver.919906706" name="QCC Archiver" superClass="com.qnx.qcc.tool.archiver"/>
+ </toolChain>
+ </folderInfo>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <project id="Gamepad.null.1921710151" name="Gamepad"/>
+ </storageModule>
+ <storageModule moduleId="scannerConfiguration">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+ <scannerConfigBuildInfo instanceId="com.qnx.qcc.toolChain.1617467616">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+ </scannerConfigBuildInfo>
+ <scannerConfigBuildInfo instanceId="com.qnx.qcc.toolChain.1476280319">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+ </scannerConfigBuildInfo>
+ <scannerConfigBuildInfo instanceId="com.qnx.qcc.toolChain.390350634">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+ </scannerConfigBuildInfo>
+ </storageModule>
+ <storageModule moduleId="refreshScope" versionNumber="1">
+ <resource resourceType="PROJECT" workspacePath="/Gamepad"/>
+ </storageModule>
+</cproject>
View
84 Gamepad/.project
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>Gamepad</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+ <triggers>clean,full,incremental,</triggers>
+ <arguments>
+ <dictionary>
+ <key>?name?</key>
+ <value></value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.append_environment</key>
+ <value>true</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.autoBuildTarget</key>
+ <value>all</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.buildArguments</key>
+ <value></value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.buildCommand</key>
+ <value>make</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
+ <value>clean</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.contents</key>
+ <value>org.eclipse.cdt.make.core.activeConfigSettings</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.enableAutoBuild</key>
+ <value>false</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.enableCleanBuild</key>
+ <value>true</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.enableFullBuild</key>
+ <value>true</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.fullBuildTarget</key>
+ <value>all</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.stopOnError</key>
+ <value>true</value>
+ </dictionary>
+ <dictionary>
+ <key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
+ <value>true</value>
+ </dictionary>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+ <triggers>full,incremental,</triggers>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.qnx.tools.bbt.xml.core.bbtXMLValidationBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.cdt.core.cnature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+ <nature>com.qnx.tools.ide.bbt.core.bbtnature</nature>
+ </natures>
+</projectDescription>
View
232 Gamepad/LICENSE
@@ -0,0 +1,232 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+--------------------------------------------------
+For png.h and pngconf.h
+
+ The PNG Reference Library is supplied "AS IS". The Contributing Authors
+ and Group 42, Inc. disclaim all warranties, expressed or implied,
+ including, without limitation, the warranties of merchantability and of
+ fitness for any purpose. The Contributing Authors and Group 42, Inc.
+ assume no liability for direct, indirect, incidental, special, exemplary,
+ or consequential damages, which may result from the use of the PNG
+ Reference Library, even if advised of the possibility of such damage.
+
+ Permission is hereby granted to use, copy, modify, and distribute this
+ source code, or portions hereof, for any purpose, without fee, subject
+ to the following restrictions:
+
+ 1. The origin of this source code must not be misrepresented.
+
+ 2. Altered versions must be plainly marked as such and
+ must not be misrepresented as being the original source.
+
+ 3. This Copyright notice may not be removed or altered from
+ any source or altered source distribution.
+
+ The Contributing Authors and Group 42, Inc. specifically permit, without
+ fee, and encourage the use of this source code as a component to
+ supporting the PNG file format in commercial products. If you use this
+ source code in a product, acknowledgment is not required but would be
+ appreciated.
View
8 Gamepad/Makefile
@@ -0,0 +1,8 @@
+LIST=CPU
+ifndef QRECURSE
+QRECURSE=recurse.mk
+ifdef QCONFIG
+QRDIR=$(dir $(QCONFIG))
+endif
+endif
+include $(QRDIR)$(QRECURSE)
View
73 Gamepad/NOTICE
@@ -0,0 +1,73 @@
+Gamepad
+Copyright (c) 2011-2012 Research In Motion Limited.
+
+This product includes software developed at
+Research In Motion Limited (http://www.rim.com/).
+
+This product includes libpng http://www.libpng.org/
+ Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+
+ If you modify libpng you may insert additional notices immediately following
+ this sentence.
+
+ This code is released under the libpng license.
+
+ libpng versions 1.2.6, August 15, 2004, through 1.4.8, July 7, 2011, are
+ Copyright (c) 2004, 2006-2010 Glenn Randers-Pehrson, and are
+ distributed according to the same disclaimer and license as libpng-1.2.5
+ with the following individual added to the list of Contributing Authors:
+
+ Cosmin Truta
+
+ libpng versions 1.0.7, July 1, 2000, through 1.2.5, October 3, 2002, are
+ Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are
+ distributed according to the same disclaimer and license as libpng-1.0.6
+ with the following individuals added to the list of Contributing Authors:
+
+ Simon-Pierre Cadieux
+ Eric S. Raymond
+ Gilles Vollant
+
+ and with the following additions to the disclaimer:
+ There is no warranty against interference with your enjoyment of the
+ library or against infringement. There is no warranty that our
+ efforts or the library will fulfill any of your particular purposes
+ or needs. This library is provided with all faults, and the entire
+ risk of satisfactory quality, performance, accuracy, and effort is with
+ the user.
+
+ libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
+ Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson, and are
+ distributed according to the same disclaimer and license as libpng-0.96,
+ with the following individuals added to the list of Contributing Authors:
+
+ Tom Lane
+ Glenn Randers-Pehrson
+ Willem van Schaik
+
+ libpng versions 0.89, June 1996, through 0.96, May 1997, are
+ Copyright (c) 1996, 1997 Andreas Dilger
+ Distributed according to the same disclaimer and license as libpng-0.88,
+ with the following individuals added to the list of Contributing Authors:
+
+ John Bowler
+ Kevin Bracey
+ Sam Bushell
+ Magnus Holmgren
+ Greg Roelofs
+ Tom Tanner
+
+ libpng versions 0.5, May 1995, through 0.88, January 1996, are
+ Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
+
+ For the purposes of this copyright and license, "Contributing Authors"
+ is defined as the following set of individuals:
+
+ Andreas Dilger
+ Dave Martindale
+ Guy Eric Schalnat
+ Paul Schmidt
+ Tim Wegner
+
View
8 Gamepad/arm/Makefile
@@ -0,0 +1,8 @@
+LIST=VARIANT
+ifndef QRECURSE
+QRECURSE=recurse.mk
+ifdef QCONFIG
+QRDIR=$(dir $(QCONFIG))
+endif
+endif
+include $(QRDIR)$(QRECURSE)
View
1  Gamepad/arm/o.le-v7-g/Makefile
@@ -0,0 +1 @@
+include ../../common.mk
View
1  Gamepad/arm/o.le-v7/Makefile
@@ -0,0 +1 @@
+include ../../common.mk
View
68 Gamepad/bar-descriptor.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<qnx xmlns="http://www.qnx.com/schemas/application/1.0">
+
+<!-- BlackBerry® 10 application descriptor file.
+
+ Specifies parameters for identifying, installing, and launching native applications on BlackBerry® 10 OS.
+-->
+
+ <!-- A universally unique application identifier. Must be unique across all BlackBerry applications.
+ Using a reverse DNS-style name as the id is recommended. (Eg. com.example.ExampleApplication.) Required. -->
+ <id>com.example.Gamepad</id>
+
+ <!-- The name that is displayed in the BlackBerry application installer.
+ May have multiple values for each language. See samples or xsd schema file. Optional. -->
+ <name>Gamepad</name>
+
+ <!-- A string value of the format <0-999>.<0-999>.<0-999> that represents application version which can be used to check for application upgrade.
+ Values can also be 1-part or 2-part. It is not necessary to have a 3-part value.
+ An updated version of application must have a versionNumber value higher than the previous version. Required. -->
+ <versionNumber>1.0.0</versionNumber>
+
+ <!-- Fourth digit segment of the package version. First three segments are taken from the
+ <versionNumber> element. Must be an integer from 0 to 2^16-1 -->
+ <buildId>1</buildId>
+
+ <!-- Description, displayed in the BlackBerry application installer.
+ May have multiple values for each language. See samples or xsd schema file. Optional. -->
+ <description>The Gamepad application</description>
+
+ <!-- Name of author which is used for signing. Must match the developer name of your development certificate. -->
+ <author>Example Inc.</author>
+
+ <!-- Unique author ID assigned by signing authority. Required if using debug tokens. -->
+ <!-- <authorId>ABC1234YjsnUk235h</authorId> -->
+
+ <initialWindow>
+ <aspectRatio>landscape</aspectRatio>
+ <autoOrients>false</autoOrients>
+ <systemChrome>none</systemChrome>
+ <transparent>false</transparent>
+ </initialWindow>
+
+ <!-- The category where the application appears. Either core.games or core.media. -->
+ <category>core.games</category>
+ <asset path="icon.png">icon.png</asset>
+ <asset path="gamepad.png">gamepad.png</asset>
+ <configuration name="Device-Debug">
+ <platformArchitecture>armle-v7</platformArchitecture>
+ <asset path="arm/o.le-v7-g/Gamepad" entry="true" type="Qnx/Elf">Gamepad</asset>
+ </configuration>
+ <configuration name="Device-Release">
+ <platformArchitecture>armle-v7</platformArchitecture>
+ <asset path="arm/o.le-v7/Gamepad" entry="true" type="Qnx/Elf">Gamepad</asset>
+ </configuration>
+ <configuration name="Simulator-Debug">
+ <platformArchitecture>x86</platformArchitecture>
+ <asset path="x86/o-g/Gamepad" entry="true" type="Qnx/Elf">Gamepad</asset>
+ </configuration>
+
+ <!-- The icon for the application. -->
+ <icon>
+ <image>icon.png</image>
+ </icon>
+
+ <!-- Ensure that shared libraries in the package are found at run-time. -->
+ <env var="LD_LIBRARY_PATH" value="app/native/lib"/>
+
+</qnx>
View
1,018 Gamepad/bbutil.c
@@ -0,0 +1,1018 @@
+/*
+ * Copyright (c) 2011-2012 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <ctype.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/keycodes.h>
+#include <time.h>
+#include <stdbool.h>
+#include <math.h>
+
+#include "bbutil.h"
+
+#ifdef USING_GL11
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#elif defined(USING_GL20)
+#include <GLES2/gl2.h>
+#else
+#error bbutil must be compiled with either USING_GL11 or USING_GL20 flags
+#endif
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#include "png.h"
+
+EGLDisplay egl_disp;
+EGLSurface egl_surf;
+
+static EGLConfig egl_conf;
+static EGLContext egl_ctx;
+
+static screen_context_t screen_ctx;
+static screen_window_t screen_win;
+static screen_display_t screen_disp;
+static int nbuffers = 2;
+static int initialized = 0;
+
+#ifdef USING_GL20
+static GLuint text_rendering_program;
+static int text_program_initialized = 0;
+static GLint positionLoc;
+static GLint texcoordLoc;
+static GLint textureLoc;
+static GLint colorLoc;
+#endif
+
+struct font_t {
+ unsigned int font_texture;
+ float pt;
+ float advance[128];
+ float width[128];
+ float height[128];
+ float tex_x1[128];
+ float tex_x2[128];
+ float tex_y1[128];
+ float tex_y2[128];
+ float offset_x[128];
+ float offset_y[128];
+ int initialized;
+};
+
+
+static void
+bbutil_egl_perror(const char *msg) {
+ static const char *errmsg[] = {
+ "function succeeded",
+ "EGL is not initialized, or could not be initialized, for the specified display",
+ "cannot access a requested resource",
+ "failed to allocate resources for the requested operation",
+ "an unrecognized attribute or attribute value was passed in an attribute list",
+ "an EGLConfig argument does not name a valid EGLConfig",
+ "an EGLContext argument does not name a valid EGLContext",
+ "the current surface of the calling thread is no longer valid",
+ "an EGLDisplay argument does not name a valid EGLDisplay",
+ "arguments are inconsistent",
+ "an EGLNativePixmapType argument does not refer to a valid native pixmap",
+ "an EGLNativeWindowType argument does not refer to a valid native window",
+ "one or more argument values are invalid",
+ "an EGLSurface argument does not name a valid surface configured for rendering",
+ "a power management event has occurred",
+ "unknown error code"
+ };
+
+ int message_index = eglGetError() - EGL_SUCCESS;
+
+ if (message_index < 0 || message_index > 14)
+ message_index = 15;
+
+ fprintf(stderr, "%s: %s\n", msg, errmsg[message_index]);
+}
+
+int
+bbutil_init_egl(screen_context_t ctx) {
+ int usage;
+ int format = SCREEN_FORMAT_RGBX8888;
+ EGLint interval = 1;
+ int rc, num_configs;
+
+ EGLint attrib_list[]= { EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, 0,
+ EGL_NONE};
+
+#ifdef USING_GL11
+ usage = SCREEN_USAGE_OPENGL_ES1 | SCREEN_USAGE_ROTATION;
+ attrib_list[9] = EGL_OPENGL_ES_BIT;
+#elif defined(USING_GL20)
+ usage = SCREEN_USAGE_OPENGL_ES2 | SCREEN_USAGE_ROTATION;
+ attrib_list[9] = EGL_OPENGL_ES2_BIT;
+ EGLint attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+#else
+ fprintf(stderr, "bbutil should be compiled with either USING_GL11 or USING_GL20 -D flags\n");
+ return EXIT_FAILURE;
+#endif
+
+ //Simple egl initialization
+ screen_ctx = ctx;
+
+ egl_disp = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (egl_disp == EGL_NO_DISPLAY) {
+ bbutil_egl_perror("eglGetDisplay");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = eglInitialize(egl_disp, NULL, NULL);
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglInitialize");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = eglBindAPI(EGL_OPENGL_ES_API);
+
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglBindApi");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ if(!eglChooseConfig(egl_disp, attrib_list, &egl_conf, 1, &num_configs)) {
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+#ifdef USING_GL20
+ egl_ctx = eglCreateContext(egl_disp, egl_conf, EGL_NO_CONTEXT, attributes);
+#elif defined(USING_GL11)
+ egl_ctx = eglCreateContext(egl_disp, egl_conf, EGL_NO_CONTEXT, NULL);
+#endif
+
+ if (egl_ctx == EGL_NO_CONTEXT) {
+ bbutil_egl_perror("eglCreateContext");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_create_window(&screen_win, screen_ctx);
+ if (rc) {
+ perror("screen_create_window");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_FORMAT, &format);
+ if (rc) {
+ perror("screen_set_window_property_iv(SCREEN_PROPERTY_FORMAT)");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage);
+ if (rc) {
+ perror("screen_set_window_property_iv(SCREEN_PROPERTY_USAGE)");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_DISPLAY, (void **)&screen_disp);
+ if (rc) {
+ perror("screen_get_window_property_pv");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ const char *env = getenv("WIDTH");
+
+ if (0 == env) {
+ perror("failed getenv for WIDTH");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ int width = atoi(env);
+
+ env = getenv("HEIGHT");
+
+ if (0 == env) {
+ perror("failed getenv for HEIGHT");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ int height = atoi(env);
+ int size[2] = { width, height };
+
+ rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size);
+ if (rc) {
+ perror("screen_set_window_property_iv");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_create_window_buffers(screen_win, nbuffers);
+ if (rc) {
+ perror("screen_create_window_buffers");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ egl_surf = eglCreateWindowSurface(egl_disp, egl_conf, screen_win, NULL);
+ if (egl_surf == EGL_NO_SURFACE) {
+ bbutil_egl_perror("eglCreateWindowSurface");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = eglMakeCurrent(egl_disp, egl_surf, egl_surf, egl_ctx);
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglMakeCurrent");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = eglSwapInterval(egl_disp, interval);
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglSwapInterval");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ initialized = 1;
+
+ return EXIT_SUCCESS;
+}
+
+void
+bbutil_terminate() {
+ //Typical EGL cleanup
+ if (egl_disp != EGL_NO_DISPLAY) {
+ eglMakeCurrent(egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (egl_surf != EGL_NO_SURFACE) {
+ eglDestroySurface(egl_disp, egl_surf);
+ egl_surf = EGL_NO_SURFACE;
+ }
+ if (egl_ctx != EGL_NO_CONTEXT) {
+ eglDestroyContext(egl_disp, egl_ctx);
+ egl_ctx = EGL_NO_CONTEXT;
+ }
+ if (screen_win != NULL) {
+ screen_destroy_window(screen_win);
+ screen_win = NULL;
+ }
+ eglTerminate(egl_disp);
+ egl_disp = EGL_NO_DISPLAY;
+ }
+ eglReleaseThread();
+
+ initialized = 0;
+}
+
+void
+bbutil_swap() {
+ int rc = eglSwapBuffers(egl_disp, egl_surf);
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglSwapBuffers");
+ }
+}
+
+/* Finds the next power of 2 */
+static inline int
+nextp2(int x)
+{
+ int val = 1;
+ while(val < x) val <<= 1;
+ return val;
+}
+
+font_t* bbutil_load_font(const char* path, int point_size, int dpi) {
+ FT_Library library;
+ FT_Face face;
+ int c;
+ int i, j;
+ font_t* font;
+
+ if (!initialized) {
+ fprintf(stderr, "EGL has not been initialized\n");
+ return NULL;
+ }
+
+ if (!path){
+ fprintf(stderr, "Invalid path to font file\n");
+ return NULL;
+ }
+
+ if(FT_Init_FreeType(&library)) {
+ fprintf(stderr, "Error loading Freetype library\n");
+ return NULL;
+ }
+ if (FT_New_Face(library, path,0,&face)) {
+ fprintf(stderr, "Error loading font %s\n", path);
+ return NULL;
+ }
+
+ if(FT_Set_Char_Size ( face, point_size * 64, point_size * 64, dpi, dpi)) {
+ fprintf(stderr, "Error initializing character parameters\n");
+ return NULL;
+ }
+
+ font = (font_t*) malloc(sizeof(font_t));
+
+ if (!font) {
+ fprintf(stderr, "Unable to allocate memory for font structure\n");
+ return NULL;
+ }
+
+ font->initialized = 0;
+ font->pt = point_size;
+
+ glGenTextures(1, &(font->font_texture));
+
+ //Let each glyph reside in 32x32 section of the font texture
+ int segment_size_x = 0, segment_size_y = 0;
+ int num_segments_x = 16;
+ int num_segments_y = 8;
+
+ FT_GlyphSlot slot;
+ FT_Bitmap bmp;
+ int glyph_width, glyph_height;
+
+ //First calculate the max width and height of a character in a passed font
+ for(c = 0; c < 128; c++) {
+ if(FT_Load_Char(face, c, FT_LOAD_RENDER)) {
+ fprintf(stderr, "FT_Load_Char failed\n");
+ free(font);
+ return NULL;
+ }
+
+ slot = face->glyph;
+ bmp = slot->bitmap;
+
+ glyph_width = bmp.width;
+ glyph_height = bmp.rows;
+
+ if (glyph_width > segment_size_x) {
+ segment_size_x = glyph_width;
+ }
+
+ if (glyph_height > segment_size_y) {
+ segment_size_y = glyph_height;
+ }
+ }
+
+ int font_tex_width = nextp2(num_segments_x * segment_size_x);
+ int font_tex_height = nextp2(num_segments_y * segment_size_y);
+
+ int bitmap_offset_x = 0, bitmap_offset_y = 0;
+
+ GLubyte* font_texture_data = (GLubyte*) calloc(2 * font_tex_width * font_tex_height, sizeof(GLubyte));
+
+ if (!font_texture_data) {
+ fprintf(stderr, "Failed to allocate memory for font texture\n");
+ free(font);
+ return NULL;
+ }
+
+ // Fill font texture bitmap with individual bmp data and record appropriate size, texture coordinates and offsets for every glyph
+ for(c = 0; c < 128; c++) {
+ if(FT_Load_Char(face, c, FT_LOAD_RENDER)) {
+ fprintf(stderr, "FT_Load_Char failed\n");
+ free(font);
+ return NULL;
+ }
+
+ slot = face->glyph;
+ bmp = slot->bitmap;
+
+ glyph_width = bmp.width;
+ glyph_height = bmp.rows;
+
+ div_t temp = div(c, num_segments_x);
+
+ bitmap_offset_x = segment_size_x * temp.rem;
+ bitmap_offset_y = segment_size_y * temp.quot;
+
+ for (j = 0; j < glyph_height; j++) {
+ for (i = 0; i < glyph_width; i++) {
+ font_texture_data[2 * ((bitmap_offset_x + i) + (j + bitmap_offset_y) * font_tex_width) + 0] =
+ font_texture_data[2 * ((bitmap_offset_x + i) + (j + bitmap_offset_y) * font_tex_width) + 1] =
+ (i >= bmp.width || j >= bmp.rows)? 0 : bmp.buffer[i + bmp.width * j];
+ }
+ }
+
+ font->advance[c] = (float)(slot->advance.x >> 6);
+ font->tex_x1[c] = (float)bitmap_offset_x / (float) font_tex_width;
+ font->tex_x2[c] = (float)(bitmap_offset_x + bmp.width) / (float)font_tex_width;
+ font->tex_y1[c] = (float)bitmap_offset_y / (float) font_tex_height;
+ font->tex_y2[c] = (float)(bitmap_offset_y + bmp.rows) / (float)font_tex_height;
+ font->width[c] = bmp.width;
+ font->height[c] = bmp.rows;
+ font->offset_x[c] = (float)slot->bitmap_left;
+ font->offset_y[c] = (float)((slot->metrics.horiBearingY-face->glyph->metrics.height) >> 6);
+ }
+
+ glBindTexture(GL_TEXTURE_2D, font->font_texture);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, font_tex_width, font_tex_height, 0, GL_LUMINANCE_ALPHA , GL_UNSIGNED_BYTE, font_texture_data);
+
+ free(font_texture_data);
+
+ FT_Done_Face(face);
+ FT_Done_FreeType(library);
+
+ font->initialized = 1;
+ return font;
+}
+
+void bbutil_render_text(font_t* font, const char* msg, float x, float y, float r, float g, float b, float a) {
+ int i, c;
+ GLfloat *vertices;
+ GLfloat *texture_coords;
+ GLushort* indices;
+
+ float pen_x = 0.0f;
+
+ if (!font) {
+ fprintf(stderr, "Font must not be null\n");
+ return;
+ }
+
+ if (!font->initialized) {
+ fprintf(stderr, "Font has not been loaded\n");
+ return;
+ }
+
+ if (!msg) {
+ return;
+ }
+
+ const int msg_len = strlen(msg);
+
+ vertices = (GLfloat*) malloc(sizeof(GLfloat) * 8 * msg_len);
+ texture_coords = (GLfloat*) malloc(sizeof(GLfloat) * 8 * msg_len);
+
+ indices = (GLushort*) malloc(sizeof(GLushort) * 6 * msg_len);
+
+ for(i = 0; i < msg_len; ++i) {
+ c = msg[i];
+
+ vertices[8 * i + 0] = x + pen_x + font->offset_x[c];
+ vertices[8 * i + 1] = y + font->offset_y[c];
+ vertices[8 * i + 2] = vertices[8 * i + 0] + font->width[c];
+ vertices[8 * i + 3] = vertices[8 * i + 1];
+ vertices[8 * i + 4] = vertices[8 * i + 0];
+ vertices[8 * i + 5] = vertices[8 * i + 1] + font->height[c];
+ vertices[8 * i + 6] = vertices[8 * i + 2];
+ vertices[8 * i + 7] = vertices[8 * i + 5];
+
+ texture_coords[8 * i + 0] = font->tex_x1[c];
+ texture_coords[8 * i + 1] = font->tex_y2[c];
+ texture_coords[8 * i + 2] = font->tex_x2[c];
+ texture_coords[8 * i + 3] = font->tex_y2[c];
+ texture_coords[8 * i + 4] = font->tex_x1[c];
+ texture_coords[8 * i + 5] = font->tex_y1[c];
+ texture_coords[8 * i + 6] = font->tex_x2[c];
+ texture_coords[8 * i + 7] = font->tex_y1[c];
+
+ indices[i * 6 + 0] = 4 * i + 0;
+ indices[i * 6 + 1] = 4 * i + 1;
+ indices[i * 6 + 2] = 4 * i + 2;
+ indices[i * 6 + 3] = 4 * i + 2;
+ indices[i * 6 + 4] = 4 * i + 1;
+ indices[i * 6 + 5] = 4 * i + 3;
+
+ //Assume we are only working with typewriter fonts
+ pen_x += font->advance[c];
+ }
+#ifdef USING_GL11
+ glEnable(GL_TEXTURE_2D);
+ glEnable(GL_BLEND);
+
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glColor4f(r, g, b, a);
+
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+ glTexCoordPointer(2, GL_FLOAT, 0, texture_coords);
+ glBindTexture(GL_TEXTURE_2D, font->font_texture);
+
+ glDrawElements(GL_TRIANGLES, 6 * msg_len, GL_UNSIGNED_SHORT, indices);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+#elif defined USING_GL20
+ if (!text_program_initialized) {
+ GLint status;
+
+ // Create shaders if this hasn't been done already
+ const char* v_source =
+ "precision mediump float;"
+ "attribute vec2 a_position;"
+ "attribute vec2 a_texcoord;"
+ "varying vec2 v_texcoord;"
+ "void main()"
+ "{"
+ " gl_Position = vec4(a_position, 0.0, 1.0);"
+ " v_texcoord = a_texcoord;"
+ "}";
+
+ const char* f_source =
+ "precision lowp float;"
+ "varying vec2 v_texcoord;"
+ "uniform sampler2D u_font_texture;"
+ "uniform vec4 u_col;"
+ "void main()"
+ "{"
+ " vec4 temp = texture2D(u_font_texture, v_texcoord);"
+ " gl_FragColor = u_col * temp;"
+ "}";
+
+ // Compile the vertex shader
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+
+ if (!vs) {
+ fprintf(stderr, "Failed to create vertex shader: %d\n", glGetError());
+ return;
+ } else {
+ glShaderSource(vs, 1, &v_source, 0);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &status);
+ if (GL_FALSE == status) {
+ GLchar log[256];
+ glGetShaderInfoLog(vs, 256, NULL, log);
+
+ fprintf(stderr, "Failed to compile vertex shader: %s\n", log);
+
+ glDeleteShader(vs);
+ }
+ }
+
+ // Compile the fragment shader
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+
+ if (!fs) {
+ fprintf(stderr, "Failed to create fragment shader: %d\n", glGetError());
+ return;
+ } else {
+ glShaderSource(fs, 1, &f_source, 0);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &status);
+ if (GL_FALSE == status) {
+ GLchar log[256];
+ glGetShaderInfoLog(fs, 256, NULL, log);
+
+ fprintf(stderr, "Failed to compile fragment shader: %s\n", log);
+
+ glDeleteShader(vs);
+ glDeleteShader(fs);
+
+ return;
+ }
+ }
+
+ // Create and link the program
+ text_rendering_program = glCreateProgram();
+ if (text_rendering_program)
+ {
+ glAttachShader(text_rendering_program, vs);
+ glAttachShader(text_rendering_program, fs);
+ glLinkProgram(text_rendering_program);
+
+ glGetProgramiv(text_rendering_program, GL_LINK_STATUS, &status);
+ if (status == GL_FALSE) {
+ GLchar log[256];
+ glGetProgramInfoLog(fs, 256, NULL, log);
+
+ fprintf(stderr, "Failed to link text rendering shader program: %s\n", log);
+
+ glDeleteProgram(text_rendering_program);
+ text_rendering_program = 0;
+
+ return;
+ }
+ } else {
+ fprintf(stderr, "Failed to create a shader program\n");
+
+ glDeleteShader(vs);
+ glDeleteShader(fs);
+ return;
+ }
+
+ // We don't need the shaders anymore - the program is enough
+ glDeleteShader(fs);
+ glDeleteShader(vs);
+
+ glUseProgram(text_rendering_program);
+
+ // Store the locations of the shader variables we need later
+ positionLoc = glGetAttribLocation(text_rendering_program, "a_position");
+ texcoordLoc = glGetAttribLocation(text_rendering_program, "a_texcoord");
+ textureLoc = glGetUniformLocation(text_rendering_program, "u_font_texture");
+ colorLoc = glGetUniformLocation(text_rendering_program, "u_col");
+
+ text_program_initialized = 1;
+ }
+
+ glEnable(GL_BLEND);
+
+ //Map text coordinates from (0...surface width, 0...surface height) to (-1...1, -1...1)
+ //this make our vertex shader very simple and also works irrespective of orientation changes
+ EGLint surface_width, surface_height;
+
+ eglQuerySurface(egl_disp, egl_surf, EGL_WIDTH, &surface_width);
+ eglQuerySurface(egl_disp, egl_surf, EGL_HEIGHT, &surface_height);
+
+ for(i = 0; i < 4 * msg_len; ++i) {
+ vertices[2 * i + 0] = 2 * vertices[2 * i + 0] / surface_width - 1.0f;
+ vertices[2 * i + 1] = 2 * vertices[2 * i + 1] / surface_height - 1.0f;
+ }
+
+ //Render text
+ glUseProgram(text_rendering_program);
+
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, font->font_texture);
+ glUniform1i(textureLoc, 0);
+
+ glUniform4f(colorLoc, r, g, b, a);
+
+ glEnableVertexAttribArray(positionLoc);
+ glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, vertices);
+
+ glEnableVertexAttribArray(texcoordLoc);
+ glVertexAttribPointer(texcoordLoc, 2, GL_FLOAT, GL_FALSE, 0, texture_coords);
+
+ //Draw the string
+ glDrawElements(GL_TRIANGLES, 6 * msg_len, GL_UNSIGNED_SHORT, indices);
+
+ glDisableVertexAttribArray(positionLoc);
+ glDisableVertexAttribArray(texcoordLoc);
+#else
+ fprintf(stderr, "bbutil should be compiled with either USING_GL11 or USING_GL20 -D flags\n");
+#endif
+
+ free(vertices);
+ free(texture_coords);
+ free(indices);
+}
+
+void bbutil_destroy_font(font_t* font) {
+ if (!font) {
+ return;
+ }
+
+ glDeleteTextures(1, &(font->font_texture));
+
+ free(font);
+}
+
+void bbutil_measure_text(font_t* font, const char* msg, float* width, float* height) {
+ int i, c;
+
+ if (!msg) {
+ return;
+ }
+
+ const int msg_len =strlen(msg);
+
+ if (width) {
+ //Width of a text rectangle is a sum advances for every glyph in a string
+ *width = 0.0f;
+
+ for(i = 0; i < msg_len; ++i) {
+ c = msg[i];
+ *width += font->advance[c];
+ }
+ }
+
+ if (height) {
+ //Height of a text rectangle is a high of a tallest glyph in a string
+ *height = 0.0f;
+
+ for(i = 0; i < msg_len; ++i) {
+ c = msg[i];
+
+ if (*height < font->height[c]) {
+ *height = font->height[c];
+ }
+ }
+ }
+}
+
+int bbutil_load_texture(const char* filename, int* width, int* height, float* tex_x, float* tex_y, unsigned int *tex) {
+ int i;
+ GLuint format;
+ //header for testing if it is a png
+ png_byte header[8];
+
+ if (!tex) {
+ return EXIT_FAILURE;
+ }
+
+ //open file as binary
+ FILE *fp = fopen(filename, "rb");
+ if (!fp) {
+ return EXIT_FAILURE;
+ }
+
+ //read the header
+ fread(header, 1, 8, fp);
+
+ //test if png
+ int is_png = !png_sig_cmp(header, 0, 8);
+ if (!is_png) {
+ fclose(fp);
+ return EXIT_FAILURE;
+ }
+
+ //create png struct
+ png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_ptr) {
+ fclose(fp);
+ return EXIT_FAILURE;
+ }
+
+ //create png info struct
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr) {
+ png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
+ fclose(fp);
+ return EXIT_FAILURE;
+ }
+
+ //create png info struct
+ png_infop end_info = png_create_info_struct(png_ptr);
+ if (!end_info) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
+ fclose(fp);
+ return EXIT_FAILURE;
+ }
+
+ //setup error handling (required without using custom error handlers above)
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ fclose(fp);
+ return EXIT_FAILURE;
+ }
+
+ //init png reading
+ png_init_io(png_ptr, fp);
+
+ //let libpng know you already read the first 8 bytes
+ png_set_sig_bytes(png_ptr, 8);
+
+ // read all the info up to the image data
+ png_read_info(png_ptr, info_ptr);
+
+ //variables to pass to get info
+ int bit_depth, color_type;
+ png_uint_32 image_width, image_height;
+
+ // get info about png
+ png_get_IHDR(png_ptr, info_ptr, &image_width, &image_height, &bit_depth, &color_type, NULL, NULL, NULL);
+
+ switch (color_type)
+ {
+ case PNG_COLOR_TYPE_RGBA:
+ format = GL_RGBA;
+ break;
+ case PNG_COLOR_TYPE_RGB:
+ format = GL_RGB;
+ break;
+ default:
+ fprintf(stderr,"Unsupported PNG color type (%d) for texture: %s", (int)color_type, filename);
+ fclose(fp);
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ return NULL;
+ }
+
+ // Update the png info struct.
+ png_read_update_info(png_ptr, info_ptr);
+
+ // Row size in bytes.
+ int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+
+ // Allocate the image_data as a big block, to be given to opengl
+ png_byte *image_data = (png_byte*) malloc(sizeof(png_byte) * rowbytes * image_height);
+
+ if (!image_data) {
+ //clean up memory and close stuff
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ fclose(fp);
+ return EXIT_FAILURE;
+ }
+
+ //row_pointers is for pointing to image_data for reading the png with libpng
+ png_bytep *row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * image_height);
+ if (!row_pointers) {
+ //clean up memory and close stuff
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ free(image_data);
+ fclose(fp);
+ return EXIT_FAILURE;
+ }
+
+ // set the individual row_pointers to point at the correct offsets of image_data
+ for (i = 0; i < image_height; i++) {
+ row_pointers[image_height - 1 - i] = image_data + i * rowbytes;
+ }
+
+ //read the png into image_data through row_pointers
+ png_read_image(png_ptr, row_pointers);
+
+ int tex_width, tex_height;
+
+ tex_width = nextp2(image_width);
+ tex_height = nextp2(image_height);
+
+ glGenTextures(1, tex);
+ glBindTexture(GL_TEXTURE_2D, (*tex));
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ if ((tex_width != image_width) || (tex_height != image_height) ) {
+ glTexImage2D(GL_TEXTURE_2D, 0, format, tex_width, tex_height, 0, format, GL_UNSIGNED_BYTE, NULL);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image_width, image_height, format, GL_UNSIGNED_BYTE, image_data);
+ } else {
+ glTexImage2D(GL_TEXTURE_2D, 0, format, tex_width, tex_height, 0, format, GL_UNSIGNED_BYTE, image_data);
+ }
+
+ GLint err = glGetError();
+
+ //clean up memory and close stuff
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ free(image_data);
+ free(row_pointers);
+ fclose(fp);
+
+ if (err == 0) {
+ //Return physical with and height of texture if pointers are not null
+ if(width) {
+ *width = image_width;
+ }
+ if (height) {
+ *height = image_height;
+ }
+ //Return modified texture coordinates if pointers are not null
+ if(tex_x) {
+ *tex_x = ((float) image_width - 0.5f) / ((float)tex_width);
+ }
+ if(tex_y) {
+ *tex_y = ((float) image_height - 0.5f) / ((float)tex_height);
+ }
+ return EXIT_SUCCESS;
+ } else {
+ fprintf(stderr, "GL error %i \n", err);
+ return EXIT_FAILURE;
+ }
+}
+
+int bbutil_calculate_dpi(screen_context_t ctx) {
+ int rc;
+ int screen_phys_size[2];
+
+ rc = screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_PHYSICAL_SIZE, screen_phys_size);
+ if (rc) {
+ perror("screen_get_display_property_iv");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ //Simulator will return 0,0 for physical size of the screen, so use 170 as default dpi
+ if ((screen_phys_size[0] == 0) && (screen_phys_size[1] == 0)) {
+ return 170;
+ } else {
+ int screen_resolution[2];
+ rc = screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_SIZE, screen_resolution);
+ if (rc) {
+ perror("screen_get_display_property_iv");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+ double diagonal_pixels = sqrt(screen_resolution[0] * screen_resolution[0] + screen_resolution[1] * screen_resolution[1]);
+ double diagonal_inches = 0.0393700787 * sqrt(screen_phys_size[0] * screen_phys_size[0] + screen_phys_size[1] * screen_phys_size[1]);
+ return (int)(diagonal_pixels / diagonal_inches + 0.5);
+
+ }
+}
+
+int bbutil_rotate_screen_surface(int angle) {
+ int rc, rotation, skip = 1, temp;;
+ EGLint interval = 1;
+ int size[2];
+
+ if ((angle != 0) && (angle != 90) && (angle != 180) && (angle != 270)) {
+ fprintf(stderr, "Invalid angle\n");
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &rotation);
+ if (rc) {
+ perror("screen_set_window_property_iv");
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size);
+ if (rc) {
+ perror("screen_set_window_property_iv");
+ return EXIT_FAILURE;
+ }
+
+ switch (angle - rotation) {
+ case -270:
+ case -90:
+ case 90:
+ case 270:
+ temp = size[0];
+ size[0] = size[1];
+ size[1] = temp;
+ skip = 0;
+ break;
+ }
+
+ if (!skip) {
+ rc = eglMakeCurrent(egl_disp, NULL, NULL, NULL);
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglMakeCurrent");
+ return EXIT_FAILURE;
+ }
+
+ rc = eglDestroySurface(egl_disp, egl_surf);
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglMakeCurrent");
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_SOURCE_SIZE, size);
+ if (rc) {
+ perror("screen_set_window_property_iv");
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size);
+ if (rc) {
+ perror("screen_set_window_property_iv");
+ return EXIT_FAILURE;
+ }
+ egl_surf = eglCreateWindowSurface(egl_disp, egl_conf, screen_win, NULL);
+ if (egl_surf == EGL_NO_SURFACE) {
+ bbutil_egl_perror("eglCreateWindowSurface");
+ return EXIT_FAILURE;
+ }
+
+ rc = eglMakeCurrent(egl_disp, egl_surf, egl_surf, egl_ctx);
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglMakeCurrent");
+ return EXIT_FAILURE;
+ }
+
+ rc = eglSwapInterval(egl_disp, interval);
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglSwapInterval");
+ return EXIT_FAILURE;
+ }
+ }
+
+ rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &angle);
+ if (rc) {
+ perror("screen_set_window_property_iv");
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
View
126 Gamepad/bbutil.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2011-2012 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UTILITY_H_INCLUDED
+#define _UTILITY_H_INCLUDED
+
+#include <EGL/egl.h>
+#include <screen/screen.h>
+#include <sys/platform.h>
+
+extern EGLDisplay egl_disp;
+extern EGLSurface egl_surf;
+
+typedef struct font_t font_t;
+
+#define BBUTIL_DEFAULT_FONT "/usr/fonts/font_repository/monotype/arial.ttf"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Initializes EGL
+ *
+ * @param libscreen context that will be used for EGL setup
+ * @return EXIT_SUCCESS if initialization succeeded otherwise EXIT_FAILURE
+ */
+int bbutil_init_egl(screen_context_t ctx);
+
+/**
+ * Terminates EGL
+ */
+void bbutil_terminate();
+
+/**
+ * Swaps default bbutil window surface to the screen
+ */
+void bbutil_swap();
+
+/**
+ * Loads the font from the specified font file.
+ * NOTE: should be called after a successful return from bbutil_init() or bbutil_init_egl() call
+ *
+ * @param font_file string indicating the absolute path of the font file
+ * @param point_size used for glyph generation
+ * @param dpi used for glyph generation
+ * @return pointer to font_t structure on success or NULL on failure
+ */
+font_t* bbutil_load_font(const char* font_file, int point_size, int dpi);
+
+/**
+ * Destroys the passed font
+ * @param font to be destroyed
+ */
+void bbutil_destroy_font(font_t* font);
+
+/**
+ * Renders the specified message using current font starting from the specified
+ * bottom left coordinates.
+ * NOTE: must be called after a successful return from bbutil_init() or bbutil_init_egl() call
+ *
+ * @param font to use for rendering
+ * @param msg the message to display
+ * @param x, y position of the bottom-left corner of text string in world coordinate space
+ * @param rgba color for the text to render with
+ */
+void bbutil_render_text(font_t* font, const char* msg, float x, float y, float r, float g, float b, float a);
+
+/**
+ * Returns the non-scaled width and height of a string
+ * NOTE: must be called after a successful return from bbutil_init() or bbutil_init_egl() call
+ *
+ * @param font to use for measurement of a string size
+ * @param msg the message to get the size of
+ * @param return pointer for width of a string
+ * @param return pointer for height of a string
+ */
+void bbutil_measure_text(font_t* font, const char* msg, float* width, float* height);
+
+/**
+ * Creates and loads a texture from a png file
+ * NOTE: must be called after a successful return from bbutil_init() or bbutil_init_egl() call
+ *
+ * @param filename path to texture png
+ * @param return width of texture
+ * @param return height of texture
+ * @param return gl texture handle
+ * @return EXIT_SUCCESS if texture loading succeeded otherwise EXIT_FAILURE
+ */
+int bbutil_load_texture(const char* filename, int* width, int* height, float* tex_x, float* tex_y, unsigned int* tex);
+
+/**
+ * Returns dpi for a given screen
+ *
+ * @param ctx path libscreen context that corresponds to display of interest
+ * @return dpi for a given screen
+ */
+int bbutil_calculate_dpi(screen_context_t ctx);
+
+/**
+ * Rotates the screen to a given angle
+ *
+ * @param angle to rotate screen surface to, must by 0, 90, 180, or 270
+ * @return EXIT_SUCCESS if texture loading succeeded otherwise EXIT_FAILURE
+ */
+
+int bbutil_rotate_screen_surface(int angle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
View
40 Gamepad/common.mk
@@ -0,0 +1,40 @@
+ifndef QCONFIG
+QCONFIG=qconfig.mk
+endif
+include $(QCONFIG)
+
+USEFILE=
+
+# Extra include path for libfreetype and for target overrides and patches
+EXTRA_INCVPATH+=$(QNX_TARGET)/usr/include/freetype2 \
+ $(QNX_TARGET)/../target-override/usr/include
+
+# Extra library search path for target overrides and patches
+EXTRA_LIBVPATH+=$(QNX_TARGET)/../target-override/$(CPUVARDIR)/lib \
+ $(QNX_TARGET)/../target-override/$(CPUVARDIR)/usr/lib
+
+# Add USING_GL11 to build bbutil for gles 1.1 use
+CCFLAGS+=-DUSING_GL11
+
+# Compiler options for enhanced security and recording the compiler options in release builds
+CCFLAGS+=-fstack-protector-strong -D_FORTIFY_SOURCE=2 \
+ $(if $(filter g so shared,$(VARIANTS)),,-fPIE) \
+ $(if $(filter g,$(VARIANTS)),,-frecord-gcc-switches)
+
+# Linker options for enhanced security
+LDFLAGS+=-Wl,-z,relro -Wl,-z,now $(if $(filter g so shared,$(VARIANTS)),,-pie)
+
+# Add your required library names, here
+LIBS+=bps screen EGL GLESv1_CM m png freetype
+
+include $(MKFILES_ROOT)/qmacros.mk
+
+# Suppress the _g suffix from the debug variant
+BUILDNAME=$(IMAGE_PREF_$(BUILD_TYPE))$(NAME)$(IMAGE_SUFF_$(BUILD_TYPE))
+
+include $(MKFILES_ROOT)/qtargets.mk
+
+OPTIMIZE_TYPE_g=none
+OPTIMIZE_TYPE=$(OPTIMIZE_TYPE_$(filter g, $(VARIANTS)))
+
+-include $(PROJECT_ROOT)/../samples.mk
View
BIN  Gamepad/gamepad.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  Gamepad/icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
1,016 Gamepad/main.c
@@ -0,0 +1,1016 @@
+/*
+* Copyright (c) 2011-2012 Research In Motion Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <fcntl.h>
+
+#include <bps/bps.h>
+#include <bps/event.h>
+#include <bps/navigator.h>
+#include <bps/screen.h>
+
+#include <png.h>
+#include <errno.h>
+
+#include <screen/screen.h>
+#include <sys/keycodes.h>
+
+#include <EGL/egl.h>
+#include <GLES/gl.h>
+
+#include <math.h>
+#include <time.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "bbutil.h"
+
+// This macro provides error checking for all calls to libscreen APIs.
+static int rc;
+#define SCREEN_API(x, y) rc = x; \
+ if (rc) fprintf(stderr, "\n%s in %s: %d", y, __FUNCTION__, errno)
+
+// Constants used when allocating memory for our graphical data.
+static const int QUAD_COUNT = 41;
+static const int VERTEX_COORD_COUNT = 328; // QUAD_COUNT * 4 vertices per image * 2 vertex coords per vertex.
+static const int INDEX_COUNT = 246; // QUAD_COUNT * 6 indices per quad.
+static const int TEXCOORD_COUNT = 328; // QUAD_COUNT * 8 UVs per quad.
+
+// Size and positions of all the controls.
+static const float ANALOG0_X = 75.0f;
+static const float ANALOG1_X = 460.0f;
+static const float ANALOG_Y = 75.0f;
+static const float ANALOG_SIZE = 100.0f;
+
+static const float DPAD_X = 25.0f;
+static const float DPAD_Y = 275.0f;
+static const float DPAD_LONG = 112.5f;
+static const float DPAD_SHORT = 75.0f;
+
+static const float BUTTONS_X = 400.0f;
+static const float BUTTONS_Y = 275.0f;
+static const float BUTTON_SIZE = 75.0f;
+
+static const float LEFT_TRIGGERS_X = 25.0f;
+static const float RIGHT_TRIGGERS_X = 450.0f;
+static const float TRIGGERS_Y = 525.0f;
+static const float TRIGGER_WIDTH = 175.0f;
+static const float TRIGGER_HEIGHT = 50.0f;
+
+static const float SELECT_X = 237.5f;
+static const float SELECT_Y = 450.0f;
+
+// Other constants.
+static const int FONT_SIZE = 4;
+
+// Texture coordinates for each image in our texture atlas.
+static GLfloat _outerUVs[4] = { 0.0f, 1.0f, 0.25f, 0.75f };
+static GLfloat _innerUVs[4] = { 0.25f, 1.0f, 0.5f, 0.75f };
+static GLfloat _buttonDownUVs[4] = { 0.0f, 0.7109375f, 0.166015625f, 0.544921875f };
+static GLfloat _buttonUpUVs[4] = { 0.166015625f, 0.7109375f, 0.33203125f, 0.544921875f };
+static GLfloat _triggerDownUVs[4] = { 0.0f, 0.51171875f, 0.1474609375f, 0.466796875f };
+static GLfloat _triggerUpUVs[4] = { 0.17578125f, 0.51171875f, 0.3232421875f, 0.466796875f };
+static GLfloat _upDPadDownUVs[4] = { 0.0f, 0.267578125f, 0.1005859375f, 0.1201171875f };
+static GLfloat _upDPadUpUVs[4] = { 0.390625f, 0.267578125f, 0.4912109375f, 0.1201171875f };
+static GLfloat _downDPadDownUVs[4] = { 0.17578125f, 0.267578125f, 0.2763671875f, 0.1201171875f };
+static GLfloat _downDPadUpUVs[4] = { 0.56640625f, 0.267578125f, 0.6669921875f, 0.1201171875f };
+static GLfloat _leftDPadDownUVs[4] = { 0.0f, 0.4140625f, 0.1474609375f, 0.3125f };
+static GLfloat _leftDPadUpUVs[4] = { 0.390625f, 0.4140625f, 0.5380859375f, 0.3125f };
+static GLfloat _rightDPadDownUVs[4] = { 0.17578125f, 0.4140625f, 0.3232421875f, 0.3125f };
+static GLfloat _rightDPadUpUVs[4] = { 0.56640625f, 0.4140625f, 0.7138671875f, 0.3125f } ;
+
+// Each button type corresponds to a set of texture coordinates from those defined above.
+typedef enum ButtonType_t {
+ DPAD_UP,
+ DPAD_DOWN,
+ DPAD_LEFT,
+ DPAD_RIGHT,
+ TRIGGER,
+ BUTTON
+} ButtonType;
+
+// This structure defines a quad that can be drawn to the screen.
+typedef struct Quad_t {
+ GLfloat x;
+ GLfloat y;
+ GLfloat width;
+ GLfloat height;
+ GLfloat* uvs;
+} Quad;
+
+// This structure contains everything needed to map a physical button on a device to a virtual button on the screen.
+typedef struct Button_t {
+ // A button's type determines which set of UVs it uses.
+ ButtonType type;
+ int mapping;
+ Quad* quad;
+ char* label;
+} Button;
+
+// The possible values for Button.mapping.
+static int _buttonMappings[32];
+
+// Objects used by the application.
+static screen_context_t _screen_ctx;
+static font_t* _font;
+
+// Miscellaneous variables used by the application.
+static bool _shutdown;
+static bool _polling;
+static float _surfaceHeight;
+static float _surfaceWidth;
+
+// Storage for our graphical data.
+static unsigned int _gamepadTexture;
+static GLfloat* _vertices;
+static GLushort* _indices;
+static GLfloat* _textureCoords;
+static Quad _quads[41];
+
+// Pointers to the quads and buttons we'll need to modify during frame updates.
+static Quad* _analog0Inner[2];
+static Quad* _analog1Inner[2];
+static Button _buttons[2][16];
+
+// Tapping an on-screen button will make it 'active', and the next gamepad button-press will map that gamepad button to this on-screen button.
+static Button* _activeButton[2];
+
+static Button _pollingButton;
+
+// Structure representing a game controller.
+typedef struct GameController_t {
+ // Static device info.
+ screen_device_t handle;
+ int type;
+ int buttonCount;
+ char id[64];
+ char vendor[64];
+ char product[64];
+
+ // Current state.
+ int buttons;
+ int analog0[3];
+ int analog1[3];
+
+ // Text to display to the user about this controller.
+ char deviceString0[256];
+ char deviceString1[256]; // bbutil.c does not handle line-breaks
+ char buttonsString[128];
+ char analog0String[128];
+ char analog1String[128];
+} GameController;
+
+// Controller information.
+static int MAX_CONTROLLERS = 2;
+static int MAX_BUTTONS = 16;
+static GameController _controllers[2];
+
+static void initController(GameController* controller, int player)
+{
+ // Initialize controller values.
+ controller->handle = 0;
+ controller->type = 0;
+ controller->buttonCount = 0;
+ controller->buttons = 0;
+ controller->analog0[0] = controller->analog0[1] = controller->analog0[2] = 0;
+ controller->analog1[0] = controller->analog1[1] = controller->analog1[2] = 0;
+ sprintf(controller->deviceString0, "Player %d: No device detected.", player + 1);
+}
+
+int init()
+{
+ // Initialize our static variables and controllers.
+ _font = NULL;
+ _shutdown = false;
+ _polling = false;
+
+ int i;
+ for (i = 0; i < MAX_CONTROLLERS; ++i) {
+ initController(&_controllers[i], i);
+ _activeButton[i] = NULL;
+ }
+
+ // Populate an array of button mappings.
+ for (i = 0; i < 32; ++i) {
+ _buttonMappings[i] = 1 << i;
+ }
+
+ EGLint surface_width, surface_height;
+
+ // Query width and height of the window surface created by utility code.
+ eglQuerySurface(egl_disp, egl_surf, EGL_WIDTH, &surface_width);
+ eglQuerySurface(egl_disp, egl_surf, EGL_HEIGHT, &surface_height);
+
+ EGLint err = eglGetError();
+ if (err != EGL_SUCCESS) {
+ fprintf(stderr, "Unable to query EGL surface dimensions\n");
+ return EXIT_FAILURE;
+ }
+
+ _surfaceHeight = (float) surface_height;
+ _surfaceWidth = (float) surface_width;
+
+ // Calculate our display's DPI and load our font using utility code.
+ int dpi = bbutil_calculate_dpi(_screen_ctx);
+ _font = bbutil_load_font("/usr/fonts/font_repository/monotype/cour.ttf", FONT_SIZE, dpi);
+
+ if (!_font) {
+ fprintf(stderr, "Unable to load font.\n");
+ return EXIT_FAILURE;
+ }
+
+ // Load our gamepad texture atlas.
+ int w, h;
+ float tx, ty;
+ if (bbutil_load_texture("./app/native/gamepad.png", &w, &h, &tx, &ty, &_gamepadTexture) == EXIT_FAILURE) {
+ fprintf(stderr, "Unable to load texture.\n");
+ return EXIT_FAILURE;
+ }
+
+ // Set the initial positions of all joysticks and buttons.
+ for (i = 0; i < MAX_CONTROLLERS; ++i) {
+ /**
+ * Quads | Buttons
+ *
+ * 0-3 | Analog sticks.
+ * 4-7 | D-Pad. Up, Down, Left, Right.
+ * 8-11 | A, B, X, Y Buttons.
+ * 12,13 | Analog stick triggers (L3, R3) -- represented as buttons below the sticks.
+ * 14-17 | Triggers: L1, L2, R1, R2.
+ * 18,19 | Select, Start.
+ */
+ int controllerIndex = 20*i;
+ float xOffset = (_surfaceWidth * 0.5f)*i;
+
+ Quad* analog0Outer = &_quads[0 + controllerIndex];
+ analog0Outer->x = ANALOG0_X + xOffset;
+ analog0Outer->y = ANALOG_Y;
+ analog0Outer->width = analog0Outer->height = ANALOG_SIZE;
+ analog0Outer->uvs = _outerUVs;
+
+ _analog0Inner[i] = &_quads[1 + controllerIndex];
+ _analog0Inner[i]->x = ANALOG0_X + xOffset;
+ _analog0Inner[i]->y = ANALOG_Y;
+ _analog0Inner[i]->width = _analog0Inner[i]->height = ANALOG_SIZE;
+ _analog0Inner[i]->uvs = _innerUVs;
+
+ Quad* analog1Outer = &_quads[2 + controllerIndex];
+ analog1Outer->x = ANALOG1_X + xOffset;
+ analog1Outer->y = ANALOG_Y;
+ analog1Outer->width = analog1Outer->height = ANALOG_SIZE;
+ analog1Outer->uvs = _outerUVs;
+
+ _analog1Inner[i] = &_quads[3 + controllerIndex];
+ _analog1Inner[i]->x = ANALOG1_X + xOffset;
+ _analog1Inner[i]->y = ANALOG_Y;
+ _analog1Inner[i]->width = _analog1Inner[i]->height = ANALOG_SIZE;
+ _analog1Inner[i]->uvs = _innerUVs;
+
+ // Common to all buttons.
+ int j;
+ for (j = 0; j < 16; ++j) {
+ // Default mappings.
+ _buttons[i][j].mapping = _buttonMappings[j];
+ // Assign quads.
+ _buttons[i][j].quad = &_quads[j+4 + controllerIndex];
+ }
+
+ // D-Pad.
+ for (j = 0; j < 4; ++j) {
+ _buttons[i][j].type = DPAD_UP + j;
+ }
+
+ // Buttons.
+ for (j = 4; j < 10; ++j) {
+ _buttons[i][j].type = BUTTON;
+ _buttons[i][j].quad->width = BUTTON_SIZE;
+ _buttons[i][j].quad->height = BUTTON_SIZE;
+ _buttons[i][j].quad->uvs = _buttonUpUVs;
+ }
+
+ // Triggers
+ for (j = 10; j < 16; ++j) {
+ _buttons[i][j].type = TRIGGER;
+ _buttons[i][j].quad->width = TRIGGER_WIDTH;
+ _buttons[i][j].quad->height = TRIGGER_HEIGHT;
+ _buttons[i][j].quad->uvs = _triggerUpUVs;
+ }
+
+ // Set quad positions and sizes.
+ // Up
+ _buttons[i][0].label = "U";
+ _buttons[i][0].quad->x = DPAD_X + DPAD_SHORT + xOffset;
+ _buttons[i][0].quad->y = DPAD_Y + DPAD_LONG;
+ _buttons[i][0].quad->width = DPAD_SHORT;
+ _buttons[i][0].quad->height = DPAD_LONG;
+ _buttons[i][0].quad->uvs = _upDPadUpUVs;
+ _buttons[i][0].mapping = SCREEN_DPAD_UP_GAME_BUTTON;
+
+ // Down
+ _buttons[i][1].label = "D";
+ _buttons[i][1].quad->x = DPAD_X + DPAD_SHORT + xOffset;
+ _buttons[i][1].quad->y = DPAD_Y;
+ _buttons[i][1].quad->width = DPAD_SHORT;
+ _buttons[i][1].quad->height = DPAD_LONG;
+ _buttons[i][1].quad->uvs = _downDPadUpUVs;
+ _buttons[i][1].mapping = SCREEN_DPAD_DOWN_GAME_BUTTON;
+
+ // Left
+ _buttons[i][2].label = "L";
+ _buttons[i][2].quad->x = DPAD_X + xOffset;
+ _buttons[i][2].quad->y = DPAD_Y + DPAD_SHORT;
+ _buttons[i][2].quad->width = DPAD_LONG;
+ _buttons[i][2].quad->height = DPAD_SHORT;
+ _buttons[i][2].quad->uvs = _leftDPadUpUVs;
+ _buttons[i][2].mapping = SCREEN_DPAD_LEFT_GAME_BUTTON;
+
+ // Right
+ _buttons[i][3].label = "R";
+ _buttons[i][3].quad->x = DPAD_X + DPAD_LONG + xOffset;
+ _buttons[i][3].quad->y = DPAD_Y + DPAD_SHORT;
+ _buttons[i][3].quad->width = DPAD_LONG;
+ _buttons[i][3].quad->height = DPAD_SHORT;
+ _buttons[i][3].quad->uvs = _rightDPadUpUVs;
+ _buttons[i][3].mapping = SCREEN_DPAD_RIGHT_GAME_BUTTON;
+
+ // A, B, X, Y
+ _buttons[i][4].label = "A";
+ _buttons[i][4].quad->x = BUTTONS_X + BUTTON_SIZE + xOffset;
+ _buttons[i][4].quad->y = BUTTONS_Y;
+ _buttons[i][4].mapping = SCREEN_A_GAME_BUTTON;
+
+ _buttons[i][5].label = "B";
+ _buttons[i][5].quad->x = BUTTONS_X + 2*BUTTON_SIZE + xOffset;
+ _buttons[i][5].quad->y = BUTTONS_Y + BUTTON_SIZE;
+ _buttons[i][5].mapping = SCREEN_B_GAME_BUTTON;
+
+ _buttons[i][6].label = "X";
+ _buttons[i][6].quad->x = BUTTONS_X + xOffset;
+ _buttons[i][6].quad->y = BUTTONS_Y + BUTTON_SIZE;
+ _buttons[i][6].mapping = SCREEN_X_GAME_BUTTON;
+
+ _buttons[i][7].label = "Y";
+ _buttons[i][7].quad->x = BUTTONS_X + BUTTON_SIZE + xOffset;
+ _buttons[i][7].quad->y = BUTTONS_Y + 2*BUTTON_SIZE;
+ _buttons[i][7].mapping = SCREEN_Y_GAME_BUTTON;
+
+ // L3, R3
+ _buttons[i][8].label = "L3";
+ _buttons[i][8].quad->x = ANALOG0_X + BUTTON_SIZE*2.0f + xOffset;
+ _buttons[i][8].quad->y = ANALOG_Y + BUTTON_SIZE;
+ _buttons[i][8].mapping = SCREEN_L3_GAME_BUTTON;
+
+ _buttons[i][9].label = "R3";
+ _buttons[i][9].quad->x = ANALOG1_X - BUTTON_SIZE*2.0f + xOffset;
+ _buttons[i][9].quad->y = ANALOG_Y + BUTTON_SIZE;
+ _buttons[i][9].mapping = SCREEN_R3_GAME_BUTTON;
+
+ // Triggers: L1, L2, R1, R2
+ _buttons[i][10].label = "L1";
+ _buttons[i][10].quad->x = LEFT_TRIGGERS_X + xOffset;
+ _buttons[i][10].quad->y = TRIGGERS_Y;
+ _buttons[i][10].mapping = SCREEN_L1_GAME_BUTTON;
+
+ _buttons[i][11].label = "L2";
+ _buttons[i][11].quad->x = LEFT_TRIGGERS_X + xOffset;
+ _buttons[i][11].quad->y = TRIGGERS_Y + TRIGGER_HEIGHT + 25.0f;
+ _buttons[i][11].mapping = SCREEN_L2_GAME_BUTTON;
+
+ _buttons[i][12].label = "R1";
+ _buttons[i][12].quad->x = RIGHT_TRIGGERS_X + xOffset;
+ _buttons[i][12].quad->y = TRIGGERS_Y;
+ _buttons[i][12].mapping = SCREEN_R1_GAME_BUTTON;
+
+ _buttons[i][13].label = "R2";
+ _buttons[i][13].quad->x = RIGHT_TRIGGERS_X + xOffset;
+ _buttons[i][13].quad->y = TRIGGERS_Y + TRIGGER_HEIGHT + 25.0f;
+ _buttons[i][13].mapping = SCREEN_R2_GAME_BUTTON;
+
+ // Select, Start
+ _buttons[i][14].label = "Select";
+ _buttons[i][14].quad->x = SELECT_X + xOffset;
+ _buttons[i][14].quad->y = SELECT_Y;
+ _buttons[i][14].mapping = SCREEN_MENU1_GAME_BUTTON;
+
+ _buttons[i][15].label = "Start";
+ _buttons[i][15].quad->x = SELECT_X + xOffset;
+ _buttons[i][15].quad->y = SELECT_Y + TRIGGER_HEIGHT + 25.0f;
+ _buttons[i][15].mapping = SCREEN_MENU2_GAME_BUTTON;
+ }
+
+ // Finally, one last quad is used for the "polling" button.
+ Quad* pollingQuad = &_quads[40];
+ pollingQuad->x = (surface_width * 0.5f) - TRIGGER_WIDTH * 0.5f;
+ pollingQuad->y = 5.0f;
+ pollingQuad->width = TRIGGER_WIDTH;
+ pollingQuad->height = TRIGGER_HEIGHT;
+ pollingQuad->uvs = _triggerUpUVs;
+
+ _pollingButton.quad = pollingQuad;
+ _pollingButton.type = TRIGGER;
+ _pollingButton.label = "Polling";
+
+ // Create our vertex and texture coordinate arrays.
+ _vertices = (GLfloat*) calloc(VERTEX_COORD_COUNT, sizeof(GLfloat));
+ _textureCoords = (GLfloat*) calloc(TEXCOORD_COUNT, sizeof(GLfloat));
+
+ // Create and initialize our index array.
+ _indices = (GLushort*) calloc(INDEX_COUNT, sizeof(GLushort));
+ _indices[0] = 0;
+ _indices[1] = 1;
+ _indices[2] = 2;
+ _indices[3] = 3;
+ _indices[4] = 3;
+ _indices[5] = 4;
+
+ int vertexCount = 4;
+ for (i = 1; i < QUAD_COUNT; ++i) {
+ _indices[i*6] = vertexCount;
+ _indices[i*6 + 1] = 1 + vertexCount;
+ _indices[i*6 + 2] = 2 + vertexCount;
+ _indices[i*6 + 3] = 3 + vertexCount;
+ _indices[i*6 + 4] = 3 + vertexCount;
+ vertexCount += 4;
+ _indices[i*6 + 5] = vertexCount;
+ }
+
+ // Initialize OpenGL for 2D rendering.
+ glViewport(0, 0, surface_width, surface_height);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ glOrthof(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ // Set world coordinates to coincide with screen pixels.
+ glScalef(1.0f / (float)surface_width, 1.0f / _surfaceHeight, 1.0f);
+
+ return EXIT_SUCCESS;
+}
+
+void finalize()
+{
+ // Free allocated resources.
+ if (_vertices) {
+ free(_vertices);
+ _vertices = NULL;
+ }
+
+ if (_indices) {
+ free(_indices);
+ _indices = NULL;
+ }
+
+ if (_textureCoords) {
+ free(_textureCoords);
+ _textureCoords = NULL;
+ }
+
+ // Destroy the font.
+ bbutil_destroy_font(_font);
+
+ // Stop requesting events from libscreen.
+ SCREEN_API(screen_stop_events(_screen_ctx), "stop_events");
+
+ // Shut down BPS library for this process.
+ bps_shutdown();
+
+ // Use utility code to terminate EGL setup.
+ bbutil_terminate();
+
+ // Destroy libscreen context.
+ SCREEN_API(screen_destroy_context(_screen_ctx), "destroy_context");
+}
+
+static void loadController(GameController* controller)
+{
+ // Query libscreen for information about this device.
+ SCREEN_API(screen_get_device_property_iv(controller->handle, SCREEN_PROPERTY_TYPE, &controller->type), "SCREEN_PROPERTY_TYPE");
+ SCREEN_API(screen_get_device_property_cv(controller->handle, SCREEN_PROPERTY_ID_STRING, sizeof(controller->id), controller->id), "SCREEN_PROPERTY_ID_STRING");
+ SCREEN_API(screen_get_device_property_cv(controller->handle, SCREEN_PROPERTY_VENDOR, sizeof(controller->vendor), controller->vendor), "SCREEN_PROPERTY_VENDOR");
+ SCREEN_API(screen_get_device_property_cv(controller->handle, SCREEN_PROPERTY_PRODUCT, sizeof(controller->product), controller->product), "SCREEN_PROPERTY_PRODUCT");
+ SCREEN_API(screen_get_device_property_iv(controller->handle, SCREEN_PROPERTY_BUTTON_COUNT, &controller->buttonCount), "SCREEN_PROPERTY_BUTTON_COUNT");
+
+ if (controller->type == SCREEN_EVENT_GAMEPAD) {
+ sprintf(controller->deviceString0, "Gamepad device ID: %s", controller->id);
+ } else {
+ sprintf(controller->deviceString0, "Joystick device: %s", controller->id);
+ }
+
+ if (strcmp(controller->vendor, "") == 0) {
+ strcat(controller->vendor, "Unknown");
+ }
+
+ if (strcmp(controller->product, "") == 0) {
+ strcat(controller->product, "Unknown");
+ }
+
+ sprintf(controller->deviceString1, "Vendor: %s, Product: %s, Button count: %d", controller->vendor, controller->product, controller->buttonCount);
+}
+
+static void pollDevices()
+{
+ int i;
+ for (i = 0; i < MAX_CONTROLLERS; i++) {
+ GameController* controller = &_controllers[i];
+
+ if (controller->handle) {
+ // Get the current state of a gamepad device.
+ SCREEN_API(screen_get_device_property_iv(controller->handle, SCREEN_PROPERTY_BUTTONS, &controller->buttons), "SCREEN_PROPERTY_BUTTONS");
+ SCREEN_API(screen_get_device_property_iv(controller->handle, SCREEN_PROPERTY_ANALOG0, controller->analog0), "SCREEN_PROPERTY_ANALOG0");
+ SCREEN_API(screen_get_device_property_iv(controller->handle, SCREEN_PROPERTY_ANALOG1, controller->analog1), "SCREEN_PROPERTY_ANALOG1");
+ }
+ }
+}
+
+static void handleScreenEvent(bps_event_t *event)
+{
+ int eventType;
+
+ screen_event_t screen_event = screen_event_get_event(event);
+ screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &eventType);
+
+ switch (eventType) {
+ case SCREEN_EVENT_GAMEPAD:
+ case SCREEN_EVENT_JOYSTICK:
+ {
+ if (!_polling) {
+ // Determine which controller this is.
+ screen_device_t device;
+ SCREEN_API(screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_DEVICE, (void**)&device), "SCREEN_PROPERTY_DEVICE");
+
+ GameController* controller = NULL;
+ int i;
+ for (i = 0; i < MAX_CONTROLLERS; ++i) {
+ if (device == _controllers[i].handle) {
+ controller = &_controllers[i];