Compare commits

..

260 Commits

Author SHA1 Message Date
Julian Eisel
792f0aaad5 Merge branch 'master' into HMD_viewport
Conflicts:
	source/blender/editors/gpencil/gpencil_paint.c
2017-04-18 13:18:49 +02:00
bc6f689448 Moved opening and closing the HMD drivers to the HMD window creation to solve issues with Windows 10 for some devices.
This solves i.e the DK2/CV1 screen being accessible when opening a window for configuration (since the DK2 needs rotation).
2017-04-18 12:50:46 +02:00
6814b392eb Implemented new Vive distortion coefficient values based on approximated lenswrap 2017-04-18 12:09:59 +02:00
Julian Eisel
9e17c831eb Move HMD operators to wm_hmd.c 2017-04-16 00:04:11 +02:00
Julian Eisel
2d9f41b1bd Replace wm_device.c with wm_hmd.c, rename functions appropriately 2017-04-15 23:48:12 +02:00
Julian Eisel
1a0b5c3a99 Merge branch 'master' into HMD_viewport 2017-04-15 23:14:15 +02:00
Julian Eisel
dd2bdd2ca0 Fix closing HMD window not exiting HMD session correctly 2017-04-15 17:30:09 +02:00
Julian Eisel
d4dd0184a8 Fix virtual cursor not being removed correctly when stopping hmd session 2017-04-15 16:26:07 +02:00
Julian Eisel
a61b751972 Avoid view setup function prototypes, move them to top of file 2017-04-13 19:47:42 +02:00
Julian Eisel
01acc0d59f Move drawing matrix setup into own function 2017-04-13 19:26:35 +02:00
Julian Eisel
3113329f79 Fix manipulator interaction not using correct projection matrix
Moved matrix setup for interaction into own util function now. Also did
cleanup in related code.
2017-04-13 01:25:42 +02:00
Julian Eisel
a07ca22a99 Force using HMD parameters instead of camera ones in camera perspective 2017-04-13 00:09:27 +02:00
Julian Eisel
8437c6e28e Fix lens separation applied wrongly onto projection matrix 2017-04-12 23:56:51 +02:00
Julian Eisel
a993466b22 Fix projection matrices not taking focal length of HMD into account 2017-04-12 19:55:42 +02:00
a21130f737 Re calibrated the vertical position for the Vive lens distortion shader 2017-04-12 18:18:14 +02:00
Julian Eisel
0b4e2631d2 Fix crash when closing HMD window during running session 2017-04-12 12:27:36 +02:00
Julian Eisel
623841e7df Fix HMD view drawing black if device is set to 'None' 2017-04-12 01:09:18 +02:00
Julian Eisel
b3cdca4a0a Cleanup: Naming, use util function 2017-04-12 00:04:11 +02:00
Julian Eisel
511347ff30 Remove unnecessary check
Avoids having to pass around window-manager
2017-04-11 23:41:48 +02:00
Julian Eisel
8e4b4881c8 Fix Multi-view drawing interfering with HMD view drawing
Don't do any multi-view drawing in HMD view, it doesn't make any sense.
2017-04-11 23:19:11 +02:00
Julian Eisel
3c51b670c5 Make interactions in HMD view work nicely
This should make any interactions in HMD views work like users would
expect. Talking about things like selecting, using tools, placing 3D
cursor, ...
Same goes for HMD mirror views, their interactions should work fine
now.

I'm not so happy how we pass info about HMD state to
ED_view3d_draw_depth and ED_view3d_draw_depth_gpencil, would like to
figure out a nicer way to do that. Also continuous grab works a bit
glitchy.
2017-04-11 21:25:22 +02:00
Julian Eisel
c87925469b Add WM level utility check for active HMD view 2017-04-11 21:13:20 +02:00
Julian Eisel
2fa9fceba0 Special Blender-managed cursor drawing for HMD view
Since OSes only draw one cursor, we need to draw our own cursor for both
eyes.
Note that the interaction coordinates are still incorrect as they ignore
the split screen. Will fix that separately.
2017-04-11 21:13:20 +02:00
2cd6dfe86e Cleanup: tabs 2017-04-03 22:19:47 +10:00
f38dc5c06b Merge branch 'master' into HMD_viewport 2017-04-03 22:14:12 +10:00
66a20c9ad7 Clear hmd window when no loaded
Without this, the window could be saved in an invalid state.
2017-04-03 03:12:16 +10:00
c68fabee47 Remove ifdef check for file versioning
File patching shouldn't depend on build options
2017-04-03 02:54:59 +10:00
e53d432787 Sync with master and minor formatting 2017-04-03 02:50:56 +10:00
355bbb1d49 use 'use_' as an RNA prefix 2017-04-03 02:24:11 +10:00
1b81d776d7 Correct last commit, also quiet warnings 2017-04-03 02:05:44 +10:00
ea85e2fad3 Use max_ff 2017-04-03 02:03:20 +10:00
52e007dbb2 Fix for building without HMD 2017-04-03 01:43:54 +10:00
9327880109 Merge branch 'master' into HMD_viewport 2017-04-03 01:20:08 +10:00
7e4a96f0ab Fixes for Windows compile, fixes crashes when trying to open locked devices 2017-04-01 12:59:29 +02:00
06e9f3304c Numeral small fixes from upstream 0.3rc 2017-03-31 17:29:17 +02:00
9d1b98d383 Updated Vive lens correction values, is a decent approximation, needs extra sample points when looking down
Fixed lens seperation
2017-03-31 17:29:17 +02:00
Julian Eisel
3d7ca99c89 Disable zooming/pannig of HMD view while in camera perspective
Applying zoom to projection matrix wouldn't be correct, applying it to
the view matrix would work, but not easy to do it nicely. We'd also
still miss vertical/horizontal offset since it's realized using lens
shifting (= modifiying projection matrix), so that had to be applyied
onto view matrix as well.
Decided to just disallow paning and zooming completely for now, I don't
think it would make much sense in camera perspective.
2017-03-26 01:47:21 +01:00
Julian Eisel
66952dabe8 Fix HMD panel not visible after recent changes in master 2017-03-25 23:03:37 +01:00
Julian Eisel
8081480a86 Merge branch 'master' into HMD_viewport
Conflicts:
	source/blender/blenloader/intern/writefile.c
	source/blender/windowmanager/intern/wm_window.c
2017-03-25 22:15:29 +01:00
4deff6951d msvc fix in packet.c in PSVR driver 2017-03-24 23:24:30 +01:00
43a1310508 Fixes Oculus CV1 Lens Correction 2017-03-24 05:57:03 +01:00
634067f442 OpenHMD update, disables OVRService upon starting the device, only when run with administrator.
Requires custom build of hidapi for now (github TheOnlyJoey/hidapi)
2017-03-24 02:07:07 +01:00
Julian Eisel
abe2669720 Use projection matrix from OpenHMD even if "Rotation from HMD" is disabled
Was actually applying IPD wrongly, should be correct now.
2017-03-07 17:26:36 +01:00
Julian Eisel
cecbb727ac Merge branch 'master' into HMD_viewport 2017-03-07 12:41:10 +01:00
Julian Eisel
08870e72bc Draw additional viewport info in HMD view again (3D-cursor, mini-axis, etc)
On most (if not all) devices the stuff close to view borders won't be
visible because it's out of the field of view. Ideally we'd calculate their
positions based on the FOV, but that's for later.
2017-03-06 22:34:05 +01:00
Julian Eisel
66026afd69 Correction to previous commit, unset shader after session end
Also two other minor correcions.
2017-03-06 22:28:08 +01:00
Julian Eisel
fc0fb35df5 Don't draw HMD view lens shader if session is not running 2017-03-06 21:15:13 +01:00
Julian Eisel
96ef1beb58 Fixup Python UI definition after lens shader removal 2017-03-06 21:03:58 +01:00
Julian Eisel
af3917049b Refactor split-view drawing to make popups readable 2017-03-06 20:58:43 +01:00
Julian Eisel
982c41b549 Fix fragment shader compile error on Intel GPUs 2017-03-06 20:58:43 +01:00
bed9bf1907 Bunch of small HMD fixes, removed old now unused preferences 2017-03-06 02:18:16 +01:00
Julian Eisel
5605db8611 Merge branch 'master' into HMD_viewport
Conflicts:
	source/blender/windowmanager/wm.h
2017-03-06 02:13:55 +01:00
Julian Eisel
7015b229d1 Fixup for python UI definition 2017-03-06 02:13:22 +01:00
a5d19a22b7 Fixes for HMD support windows build (thanks LazyDodo) 2017-03-06 01:34:32 +01:00
1d1ba540bb New OpenHMD 0.3rc version with PSVR, Oculus CV1 and better Vive tracking support.
Also introduces global shader, which will be adjusted based on the variables of the HMD drivers, this will make the manual selection of lens correction shaders obsolete, will be removed in next commit.

The hmd window is currently black before started (due to shader not having the hmd data yet), will be fixed as well.
2017-03-06 01:23:14 +01:00
Julian Eisel
edd74baa15 Merge branch 'master' into HMD_viewport 2017-03-06 00:08:01 +01:00
Julian Eisel
20763919a1 Fix issues changing HMD device 2017-03-05 23:48:43 +01:00
Julian Eisel
d5f0807c63 Fix python UI for building without HMD 2017-03-05 23:39:34 +01:00
Julian Eisel
6907aa26c6 Disable OpenHMD dummy device for release builds
Also fixing warning.
2017-03-05 22:32:46 +01:00
Julian Eisel
4950ce4cd9 Don't allow orthographic view in HMD view
Displaying camera in orthographic mode is still allowed. We don't want
to mess with render data and forcing perspective viewport rendering in
HMD view even if the camera is set to be orthographic might be
confusing.
2017-03-05 21:56:49 +01:00
Julian Eisel
07706a28d0 "Only Render" option for HMD view 2017-03-05 20:36:30 +01:00
Julian Eisel
2f0d8e799a Use view orientation data from current 3D view for creating HMD view 2017-03-05 18:31:17 +01:00
Julian Eisel
b3c156927a Mirror mode support (sync HMD viewpoint with regular 3D view)
Adds option "Mirror HMD View" to the HMD panel in the 3D view.

In this implementation we update/redraw the mirrored 3D views with the
HMD view, which can actually cause some extra slowdown (drawing the
viewport at least once more). We decided that this would be the best
solution for now, as the other option would be opening a separate window
showing the mirrored result, which is a bit too much against the
non-overlapping paradigma IMHO.
We could also draw the HMD view into some buffer and reuse this for
mirrored displays, but that would mess up projection matrices.
In Blender 2.8 we'll probably be able to use multi-threaded drawing
anyway, for which this would be the perfect use case.

3D View regions mirroring the HMD view are locked, for quadview we only
use the non-locked region for mirroring.
2017-03-05 17:19:51 +01:00
284c7f72a1 Fix Vive compile option 2017-03-04 15:56:06 +01:00
Julian Eisel
724a991b7f Fix changing device activates it unintentionally
Activating in this context means that OpenHMD starts polling the device
for rotation values. That can slow down things, so we only do it when
actually starting an HMD session.
2017-02-27 17:19:55 +01:00
Julian Eisel
3a79183097 Don't check if HMD returns valid IPD
OpenHMD always returns a valid value, so this check is just a waste of
resources.
2017-02-27 17:05:11 +01:00
Julian Eisel
f705c53cfa Use solid draw mode by default for HMD view 2017-02-27 16:37:11 +01:00
Julian Eisel
a8a93f000a Fix wrong modelview matrices
Was wrongly applying modelview matrices from HMD onto Blender's.
2017-02-27 16:23:45 +01:00
Julian Eisel
3ef07b29c5 Minor UI message fixes 2017-02-26 22:54:42 +01:00
Julian Eisel
8f55592e77 Use "General" as default lens distortion shader 2017-02-26 17:46:05 +01:00
Julian Eisel
926b9ea918 Fix driver for DeePoon HMD
Patch by @TheOnlyJoey, thx for fixing (and breaking!) this ;)
2017-02-26 17:36:51 +01:00
Julian Eisel
0261a18677 Merge branch 'master' into HMD_viewport 2017-02-26 17:18:25 +01:00
3e486c19ff Merge branch 'HMD_viewport' of git.blender.org:blender into HMD_viewport 2017-02-23 20:06:03 +01:00
22570c0ab4 - Updated OpenHMD with fixes from their master (commit 2379647) 2017-02-23 20:04:56 +01:00
Julian Eisel
3fb0674a1a Merge branch 'master' into HMD_viewport
Conflicts:
	source/blender/makesdna/DNA_scene_types.h
2017-02-23 15:38:52 +01:00
ef017ec9d0 Added support for correct Oculus DK1 and DK2 shaders with additional Generic shader (which could/should work for most other HMD's)
Shaders can be changed in options so you can pick a shader that matches your device
2017-02-10 22:11:48 +01:00
3318e7bd13 Fixed small oops with copy paste 2017-02-10 17:28:50 +01:00
0bbbeead7d Fixed HMD branch for current master 2017-02-10 17:20:27 +01:00
68f931fd90 Merge branch 'master' of git.blender.org:blender into HMD_viewport 2017-02-10 16:50:30 +01:00
Dalai Felinto
f81ead6c38 Fix blenderplayer build 2017-01-18 16:34:01 +01:00
Julian Eisel
c8d1319452 Fix wrong logic in HMD device toggling 2016-11-24 19:45:23 +01:00
Julian Eisel
0c86cebeb2 Merge branch 'master' into HMD_viewport 2016-11-24 19:08:40 +01:00
Julian Eisel
129955e34b Give info on why "Use Device IPD" is disabled
Also renamed RNA properties and removed unneeded update function.
2016-11-23 23:11:00 +01:00
Julian Eisel
67847067b9 Couple of fix for case no device is available/active
Fixes:
* HMD device option using invalid value
* HMD view drawing on-screen info and using wrong matrices
* Hardly usable 3D view due to projection and modelview matrix being unit matrices
All issues where only visible when the HMD device option is set to 'None'
2016-11-23 18:08:26 +01:00
Julian Eisel
6a696c5bb4 Fixes for build options 2016-11-23 17:53:57 +01:00
Julian Eisel
1ea4d4362d Merge branch 'master' into HMD_viewport 2016-11-23 11:58:34 +01:00
Julian Eisel
a757065875 Fix KM_CLICK events broken 2016-11-23 02:26:43 +01:00
Julian Eisel
911fd31894 Fix HMD device set to 'none' after loading factory settings
We now use the last input device if available.
2016-11-23 02:09:30 +01:00
Julian Eisel
585c5e72ab Fix no active HMD when opening file that was saved during HMD session 2016-11-23 01:58:31 +01:00
Julian Eisel
d0000ef6fc Several minor corrections 2016-11-23 01:24:50 +01:00
Julian Eisel
91d0198d0e Make "Use Device Rotation" toggle work again
When this is disabled we just manually calculate the camera offsets. Actually I have no idea if math is correct but it doesn't seem totally wrong at least :P Don't have an HMD to test right now.
2016-11-23 00:52:22 +01:00
Julian Eisel
e2dd63eb55 Allow zooming/panning while HMD view is in camera perspective 2016-11-22 17:04:28 +01:00
Julian Eisel
48b38797c6 Merge branch 'master' into HMD_viewport
Conflicts:
	source/blender/makesrna/intern/rna_userdef.c
2016-11-20 19:32:02 +01:00
Julian Eisel
e06fa55a48 Add a dropdown to support multiple lens-distortion shaders 2016-11-20 00:11:41 +01:00
Julian Eisel
d9428f7a03 Merge branch 'master' into HMD_viewport
Conflicts:
	source/blender/blenloader/intern/versioning_270.c
2016-11-19 21:09:48 +01:00
Julian Eisel
c2b72626bf Replace low-level HMD check with higher level API call 2016-11-19 19:25:13 +01:00
Julian Eisel
8bfc10ce66 Make HMD window a proper 'restricted' window
A restricted window is a new concept that doesn't allow changing the screen of a window in any way. This way we can ensure the HMD window is only used for displaying the 3D View, so users can't accidentally change it without knowing how to get back. This also fixes some issues we had when using temp screens like they're used for UserPrefs.
Fixes:
* Could open toolbar/properties in HMD view
* HMD window used when opening UserPrefs through menu/shortcut
* Could easily change editor to non-3D-View
2016-11-19 13:38:17 +01:00
Julian Eisel
a29c325c83 Move HMD view shading option to window manager level
Was a bit ugly to have this in scene level, window manager isn't perfect either, but prefer it there.
2016-11-18 00:12:57 +01:00
Julian Eisel
509945633b Move HMD panel into 3D View properties
Still not a really perfect place since this is global, but can't think of a better one. More options will be added later on, so worth having an own panel.
2016-11-17 23:06:30 +01:00
Julian Eisel
fdb0d37bdf Remove scene level HMDVIEW_SESSION_RUNNING flag
Also separated HMD view drawing from stereo3d drawing some more.
2016-11-15 23:30:05 +01:00
Julian Eisel
ccf5de8a71 Merge branch 'master' into HMD_viewport
Conflicts:
	source/blender/blenloader/intern/versioning_270.c
	source/blender/editors/interface/resources.c
2016-11-15 16:18:56 +01:00
Julian Eisel
9ce9540afd Move HMD options to User Preferences 2016-11-11 17:45:46 +01:00
Julian Eisel
fdd4c5a98d Merge branch 'master' into HMD_viewport
Conflicts:
	source/blender/blenloader/intern/versioning_270.c
2016-11-11 16:22:40 +01:00
e2ccfdaa29 Fix bplayer (c) 2016-11-03 20:28:48 +01:00
8e1cf5237f Merge branch 'master' into HMD_viewport
Conflicts:
	source/blender/blenloader/intern/versioning_270.c
2016-11-03 20:10:55 +01:00
994795c1ed Add libhidapi to install_deps.sh script.
Note: only tested (both package and source compilation) with Debian
testing distro, others (fedora-like, arch-like) might not be working,
especially the compilation option.
2016-11-03 20:05:18 +01:00
TheOnlyJoey
54ed6f8918 Fixed deepoon variables for vc2013 compile 2016-10-31 14:21:47 +01:00
TheOnlyJoey
ce4f04f268 Fixed cmake option for htc vive in OpenHMD 2016-10-29 16:58:09 +02:00
TheOnlyJoey
e7670e9bb0 - Added initial HTC Vive support, still uses complimentary sensor fusion, could drift a bit 2016-10-29 16:21:56 +02:00
TheOnlyJoey
46bc9bcbba - Updated Oculus CV1 support 2016-10-29 16:01:03 +02:00
TheOnlyJoey
1a0d1064ee Removed cordinate frame from OpenHMD Deepoon driver 2016-10-29 01:19:39 +02:00
Julian Eisel
bebd1fbcd8 Own panel for HMD stuff
No need to enable "Views" option anymore now.
2016-10-28 23:56:22 +02:00
459f922484 Updated OpenHMD to match their latest master (1c984fb)
Adds support for Oculus Rift CV1 and Deepoon E2
2016-10-28 23:41:39 +02:00
Julian Eisel
913903af74 Fix warning with WITH_OPENHMD enabled 2016-10-28 23:23:25 +02:00
Julian Eisel
1a1b51f329 Fall back to return unit matrix 2016-10-28 23:11:20 +02:00
Julian Eisel
b7beb76211 Fix compiling without WITH_INPUT_HMD 2016-10-28 20:52:30 +02:00
Julian Eisel
2d2d44ca71 No need to apply HMD rotation in operator anymore
Now done by requesting modelview/projection matrices from OpenHMD.
2016-10-28 20:35:38 +02:00
Julian Eisel
14b9e0a933 Use projection matrix from HMD, don't add to Blender's 2016-10-28 20:03:34 +02:00
Julian Eisel
6d52d7e32d Merge branch 'master' into HMD_viewport 2016-10-12 20:17:24 +02:00
Julian Eisel
bf426bdf1e Proper default value for custom HMD IPD 2016-10-12 20:08:37 +02:00
Julian Eisel
a1562bbb53 Use modelview matrix from OpenHMD, get custom IPD to work
Also renamed interocular distance to IPD in UI (slightly different things), removed unused matrix getters and made sure enabling/disabling custom IPD behaves nicely. Note that both projection and modelview matrices from OpenHMD get the Blender equivalents applied on top, so they act as relative transformations. Rotating, zooming and panning in HMD view works properly too now.
2016-10-12 19:53:03 +02:00
Julian Eisel
505b1fdcb2 Always use projection matrix from OpenHMD
Was previously only used while in camera view.
Right now, you can't zoom during HMD session, should be fixable though. Custom interocular distance and optional HMD rotation don't work now either, need to check if we want to keep them.
2016-10-12 13:05:41 +02:00
Julian Eisel
b95a7c0af3 Fix disabling lens distortion shader causing OpenGL shader error
Also cleanup.
2016-10-12 01:06:09 +02:00
Julian Eisel
f8cfffec4f Use center as pivot for rotating views, avoid passing around arg 2016-10-11 22:44:14 +02:00
Julian Eisel
17a7c6a140 Fix warning without WITH_INPUT_HMD 2016-10-11 22:21:53 +02:00
Julian Eisel
e4a82a1e39 Make HMD IPD work properly with Multi-view format 2016-10-11 22:18:41 +02:00
Julian Eisel
7a4138a5b9 Toggle into scene camera when opening HMD window 2016-10-11 21:53:06 +02:00
Julian Eisel
99a29209b4 Fix crashes with HMD view in scenes without camera 2016-10-11 18:54:29 +02:00
Julian Eisel
637ca57ce9 Init proper default settings when creating new scene 2016-10-11 18:43:42 +02:00
Julian Eisel
9d9db8f748 Fix checkbox for getting IPD from device always disabled while no HMD session runs 2016-10-11 18:41:26 +02:00
Julian Eisel
ed34f17604 Refactor HMD->Camera relation, avoid low-level call 2016-10-11 18:05:11 +02:00
Julian Eisel
3db824b617 Show info in tooltip on why HMD session can't be started 2016-10-11 15:50:11 +02:00
Julian Eisel
24f4c98cc2 Move interocular distance settings out of camera data
These aren't just for the camera, but for entire HMD session.
2016-10-09 03:08:03 +02:00
Julian Eisel
c1846b18b1 Move HMD view settings into own scene level struct
For some reason I placed this in RenderData earlier.
2016-10-09 02:41:43 +02:00
Julian Eisel
f40b22365d HMD view doesn't require own multiview mode anymore
HMD view buttons and options are always visible in "Views" panel now (Properties Editor -> Render Layers context).
2016-10-09 01:22:25 +02:00
Julian Eisel
ebc32889be Return info in tooltip on why IPD button is disabled 2016-10-08 23:14:49 +02:00
Julian Eisel
ddb2a36a4d Merge branch 'master' into HMD_viewport
Conflicts:
	source/blender/blenloader/intern/versioning_270.c
	source/blender/editors/interface/resources.c
2016-10-08 23:06:51 +02:00
Julian Eisel
17cbaf5d16 Merge branch 'master' into HMD_viewport
Conflicts:
	intern/ghost/intern/GHOST_System.cpp
	intern/ghost/intern/GHOST_System.h
	source/blender/blenkernel/BKE_blender_version.h
	source/blender/blenloader/CMakeLists.txt
	source/blender/blenloader/intern/versioning_270.c
	source/blender/windowmanager/CMakeLists.txt
	source/blender/windowmanager/intern/wm_window.c
	source/blenderplayer/bad_level_call_stubs/CMakeLists.txt
2016-09-08 13:30:20 +02:00
Julian Eisel
2ccdd0be51 Fix non-HMD window not drawing viewport in camera view
Also added WITH_INPUT_HMD checks
2016-08-03 16:48:04 +02:00
Julian Eisel
753dbee557 Merge branch 'HMD_viewport' of git.blender.org:blender into HMD_viewport 2016-08-02 01:23:33 +02:00
Julian Eisel
495e99fbc1 Undo accidental change 2016-08-02 01:19:46 +02:00
Julian Eisel
2924c09298 Viewport HMD integration using OpenHMD
= Viewport HMD integration using OpenHMD =

This adds initial support for controlling the viewport view using a head mounted display (HMD).

To use it, go to the Properties Editor, Render Layers context. Enable Views, select "HMD View". You can then open a new HMD Window from there and start a HMD session.

**TODOs:**
* Move HMD options to a better place, they are not Render Layer related (Maybe properties region?)
* Zoom and pan don't work in HMD window while in camera view
* View streched vertically in HMD window while not in camera view
* TODOs/XXXs marked in code (esp. WM_ calls in BKE_)
* Apply D1350 for better mouse interaction while in HMD view

Reviewers: sergey, dfelinto

Differential Revision: https://developer.blender.org/D2133
2016-08-02 01:10:28 +02:00
Julian Eisel
3d9fca040b Update/correct version patching 2016-08-02 00:42:19 +02:00
Julian Eisel
122e479fe7 Fixes for WITH_OPENHMD and WITH_INPUT_HMD options
And cleanup.
2016-08-02 00:39:07 +02:00
Julian Eisel
d0fce1c992 Cleanup: Undo whitespace changes, comments, etc 2016-08-02 00:28:11 +02:00
Julian Eisel
eb9f4d233c Merge branch 'master' into HMD_viewport 2016-08-01 23:01:40 +02:00
Julian Eisel
e1b662f017 Adjust opening position and size of HMD window 2016-08-01 22:30:53 +02:00
Julian Eisel
a68db93fc2 Fix streched viewport in camera view 2016-08-01 22:06:33 +02:00
Julian Eisel
6e30e9b16d Various cleanup 2016-08-01 21:58:21 +02:00
Julian Eisel
7cf31cb048 Cleanup: Use 4x4 matrices, naming, compiler hints, use API function 2016-08-01 02:49:36 +02:00
Julian Eisel
8f025c41e4 Merge branch 'master' into HMD_viewport
Conflicts:
	intern/ghost/intern/GHOST_System.h
	source/blender/blenkernel/intern/camera.c
	source/blender/blenkernel/intern/screen.c
	source/blender/editors/space_view3d/drawobject.c
	source/blender/editors/space_view3d/space_view3d.c
2016-08-01 02:23:40 +02:00
Julian Eisel
28d4cdaffc Reset writefile.c to earlier state to avoid merge hell
Was caused by whitespace auto-cleaning.
2016-08-01 01:49:38 +02:00
Julian Eisel
d90aec52ff Fix linking with Blenderplayer enabled 2016-08-01 01:11:06 +02:00
3774a424ea Implemented initial support for using HMD projection matrices in blender viewport.
Also did some general cleaning
2016-07-31 21:24:55 +02:00
Julian Eisel
95074bcd12 Always use parallel convergence in HMD mode
Previously it was just using whatever was set in non-HMD mode.
I guess using parallel convergence for usage with HMDs is correct, could be wrong though ;)
2016-06-08 20:07:52 +02:00
Julian Eisel
506dfd65eb Only allow using Device IPD if it's available 2016-06-08 19:44:32 +02:00
Julian Eisel
eebc41ec4f Don't display "Set Stereo 3D" button for HMD mode 2016-06-08 18:49:56 +02:00
185619229c Fixed locks when opening/closing HMD sessions
Spaces to Tabs
2016-06-08 16:57:18 +02:00
b99acd7338 Merge branch 'HMD_viewport' of git.blender.org:blender into HMD_viewport 2016-06-08 14:09:38 +02:00
Julian Eisel
699df00847 Make branch compile with blenderplayer 2016-06-07 20:16:23 +02:00
Julian Eisel
dbd5663c26 Merge branch 'master' into HMD_viewport
Conflicts:
	build_files/cmake/macros.cmake
	intern/ghost/intern/GHOST_SystemX11.cpp
	source/blender/editors/space_view3d/view3d_ops.c
2016-06-07 20:14:35 +02:00
90746deeec Merge branch 'HMD_viewport' of git.blender.org:blender into HMD_viewport 2016-05-21 03:08:27 +02:00
Julian Eisel
c2fe571634 Merge branch 'master' into HMD_viewport 2016-05-20 23:21:07 +02:00
Julian Eisel
bf4fe3c84f Add compiler hints to WM_device API 2016-05-20 23:16:34 +02:00
Julian Eisel
4c4333e06c Add asserts for total device number 2016-05-20 23:13:35 +02:00
Julian Eisel
18f050f951 Fix all HMDs in UserPref device option showing same name 2016-05-20 22:56:17 +02:00
53bf3e1d84 Merge branch 'HMD_viewport' of git.blender.org:blender into HMD_viewport 2016-05-20 17:58:29 +02:00
Julian Eisel
072f453448 Merge branch 'master' into HMD_viewport
Conflicts:
	release/scripts/startup/bl_ui/properties_data_camera.py
	source/blender/blenkernel/BKE_blender.h
	source/blender/blenloader/intern/versioning_270.c
	source/blender/editors/interface/interface_handlers.c
	source/blender/editors/space_view3d/view3d_view.c
	source/blender/makesdna/DNA_camera_types.h
	source/blender/windowmanager/intern/wm_event_system.c
	source/blender/windowmanager/intern/wm_operators.c
2016-05-20 01:17:29 +02:00
Julian Eisel
cc160fb0a2 Fix compilation with OPENHMD_DRIVER_EXTERNAL or OPENHMD_DRIVER_ANDROID 2016-05-20 01:01:51 +02:00
b90f3b1982 Updated OpenHMD to latest git version
Now uses threading for updating the hmd, better polling rates for performance on heavy scenes/low framerates
2016-05-19 00:46:44 +02:00
Julian Eisel
a32710fd90 Merge branch 'master' into HMD_viewport 2016-04-13 19:59:45 +02:00
Julian Eisel
a742abfafb Fix crash when stopping HMD session
OpenHMD context should only be closed when deleting GHOST_OpenHMDManager, forgot to change that in rB0c029b7f86a0.
2016-04-13 19:56:35 +02:00
Julian Eisel
deb3e28954 Don't split view in lens distortion shader
We don't want to do this in lens distortion shader since we can't add the view offset needed for the 3D effect.
2016-04-13 19:41:41 +02:00
Julian Eisel
077e3109c8 Correction to previos commit: Use int for region size 2016-04-13 00:51:32 +02:00
Julian Eisel
4424a8e844 Use non-fixed screen size for lens distortion shader
Was assuming 1920x1080. Also minor cleanup.
2016-04-13 00:45:14 +02:00
Julian Eisel
6485c25c0e Fix compile error with WITH_INPUT_HMD disabled 2016-04-10 21:40:31 +02:00
Julian Eisel
8ec1bb0966 Corrections for WITH_INPUT_HMD 2016-04-10 21:07:12 +02:00
Julian Eisel
1a3c402585 Display HMD vendor name in UserPref HMD device option
And minor cleanup.
2016-04-10 20:47:51 +02:00
Julian Eisel
088e381ae2 Quiet warnings without WITH_OPENHMD 2016-04-10 20:18:55 +02:00
Julian Eisel
21fc36fbc8 Bring back version patch
Without it building with WITH_OPENHMD disabled will activate an invalid UserPref HMD device item.
2016-04-10 20:10:24 +02:00
Julian Eisel
d81b2309bc Automate selecting HMD device
This automates setting of HMD device UserPref option a bit, so that it's ready to go without manual adjustments.
We use the last device plugged in on startup (if one is available). On runtime, plugging in a device makes it active if 'None' was previously selected in the UserPref option.
Saving HMD in UserPrefs should also be supported, but can't test.
Also removes EVT_HMD_DEVICENUM_CHANGE and version patch, they're not needed anymore.
2016-04-10 19:57:45 +02:00
Julian Eisel
16af40cc36 Send an event when a HMD was plugged in/out
It's not used for now, will commit separately.
2016-04-10 19:17:56 +02:00
Julian Eisel
691e8b135c More minor cleanup 2016-04-10 15:50:27 +02:00
Julian Eisel
60645b4030 Minor cleanup 2016-04-10 02:23:10 +02:00
Julian Eisel
30723504be Fix crash opening UserPrefs on some systems. 2016-04-10 02:13:51 +02:00
Julian Eisel
4bb2efcb6e Merge branch 'master' into HMD_viewport 2016-04-10 01:42:21 +02:00
Julian Eisel
0c029b7f86 Cleanup & fixes in GHOST_OpenHMDManager
Fix crash opening UserPrefs->System with HMD session running, fix OpenHMD context being re-created on each redraw of UserPrefs->System, get rid of m_available (can use m_device NULL check instead), other minor cleanup.
2016-04-10 01:40:31 +02:00
b189710cd8 - Fixed getting device information for the user preferences
- Defaulting to device 0 in openhmd which is the last plugged in (will fallback on Dummy Device)
2016-04-06 16:41:24 +02:00
Julian Eisel
88879dfae1 Add assert to ensure HMD view is always fullscreen 2016-03-29 02:19:11 +02:00
Julian Eisel
eec5ac5927 Cleanup: Unused variable/unused value 2016-03-29 01:58:01 +02:00
Julian Eisel
bacadeb8c4 Add build option WITH_INPUT_HMD
If we later want to support other drivers aside from OpenHMD, we only want OpenHMD to work at the low GHOST level. The new option is for the higher, driver independent level.
Since currently only OpenHMD is supported, I added a compile warning for the case HMD input is enabled and OpenHMD is disabled. Also added a compile error for the case OpenHMD is enabled and HMD input is disabled.

This means we now have 3 HMD build options:
* WITH_INPUT_HMD - General HMD support
* WITH_OPENHMD - OpenHMD driver support
* WITH_OPENHMD_DYNLOAD - Dynamic runtime OpenHMD deps loading

Actually, _INPUT_HMD isn't totally correct since it does more than just input, but wanted to stick to naming conventions.
2016-03-29 01:42:40 +02:00
Julian Eisel
85759e74ab Merge branch 'master' into HMD_viewport 2016-03-29 00:00:51 +02:00
Julian Eisel
0b41972dca Fix compiling with WITH_OPENHMD disabled 2016-03-28 23:51:10 +02:00
Julian Eisel
c04031e94f Fix reading HMD window from file causing crash on session start 2016-03-28 23:40:46 +02:00
Julian Eisel
45397af24a Some hacks to disallow toggeling out of fullscreen in an HMD window 2016-03-28 23:02:50 +02:00
Julian Eisel
2f4148d833 Remove unused storage for lens distortion shader
Also removes unneeded button from UI and unneeded RNA defines.
2016-03-28 21:38:04 +02:00
Julian Eisel
c8eb1c93af Fix memory leak in lens distortion shader
Also, the shader itself wasn't drawing previously, which it does now (but still incorrect).
2016-03-28 21:13:45 +02:00
Julian Eisel
8f9b30610b Sync Cycles UI code 2016-03-28 20:55:46 +02:00
Julian Eisel
410b681d1f Option for HMD view lens distortion shader
Enabled by default. Note that shader is currently broken though.
2016-03-28 20:50:56 +02:00
Julian Eisel
b6174113c9 Fix HMD session not ended correctly when closing HMD view during session 2016-03-28 19:09:13 +02:00
Julian Eisel
72e5ee8471 Cleanup: Tweak operator names 2016-03-28 19:06:24 +02:00
Julian Eisel
c5fc10ba3f Add UserPref option to change HMD device
A new file wm_device.c is added with this, think this is good to have.

NOTE: Couldn't really test if changing device actually works as I don't have one. Without a device available everything seems to work though.
2016-03-28 15:15:41 +02:00
Julian Eisel
03e8afdb8d Option to request interocular distance from HMD driver
Adds a new camera option to request the interocular distance (IPD) from the HMD device/driver. It's still an open design question if it's even worth to support a custom distance though.

Also hides convergence options for HMD mode, not sure if those are needed.
2016-03-28 12:43:11 +02:00
Julian Eisel
2d57a89629 Show option for interocular distance for HMD mode
Just as for stereo 3D, available in properties editor, camera context.
2016-03-27 15:00:52 +02:00
Julian Eisel
f83eba6011 Merge branch 'master' into HMD_viewport 2016-03-27 14:09:22 +02:00
Julian Eisel
367b6f1646 Merge branch 'master' into HMD_viewport 2016-03-26 01:16:44 +01:00
c0ddaefb5d HMD: Cleanup of CMake file 2016-03-25 10:42:03 +01:00
58568d1bd3 HMD: Add support of lazil loading udev library
This way we can statically link against hidapi libraries but dont'
require static linking against udev or even having specific ABI
version of this library installed on the client machine.

For now the following libraries will try to be loaded:
  libudev.so, libudev.so.0, libudev.so.1 and libudev.so.2

Not future proof since it might be version 3 of udev releases
eventually, good enough for the beginning. We can simply do a
for-loop to query like 100 of ABIs.

Udev wrangler is a bit different from other wranglers we've got,
it has wrapper functions around dlopen-ed symbols, so you can't
check directly if function was loaded or not, but this is the
only way to make external libraries working fine with wrangler
without need of re-compiling the library.
2016-03-25 10:31:10 +01:00
b811750153 HMD: Quick and dirty way to make sort of portable builds on Linux
It will require having libudev.so.1 which isn't ideal but should work for
most distros for now.

Will be worked around later with udev wrangler.
2016-03-24 20:01:16 +01:00
Julian Eisel
9f145cd1b4 Merge branch 'master' into HMD_viewport 2016-03-22 01:26:07 +01:00
Julian Eisel
0751953efd Option for HMD view shading mode 2016-03-22 01:25:01 +01:00
ad502106e4 - Fixed correct event polling for all operating systems
- Fixed up openhmd cmake for windows builds
2016-03-18 17:18:46 +01:00
Julian Eisel
9e1583a0a9 Fix inner manipulator circle not aligned to viewplane 2016-03-18 03:12:12 +01:00
d8239304de Open/close HMD device based on session status 2016-03-18 03:07:40 +01:00
Julian Eisel
d04b6a7cda Fix anaglyph viewport drawing with HMD view open 2016-03-17 23:13:34 +01:00
Julian Eisel
49d9131ebd Fix stopping session not exiting fullscreen 2016-03-17 22:58:42 +01:00
Julian Eisel
599355304d Fix camera not being reset when stopping session by closing HMD window 2016-03-17 22:53:57 +01:00
Julian Eisel
5a8e1c28c8 Reset camera on HMD session end
Added utility functions for getting/setting rotation from quaterion.
2016-03-17 22:50:00 +01:00
134be85218 Fixed memory addressing, should work on every system now 2016-03-17 22:03:13 +01:00
3609e8868c Added check for nan events from OpenHMD 2016-03-17 21:05:45 +01:00
Julian Eisel
53d36ad280 All camera rotation modes work now 2016-03-17 20:38:05 +01:00
12ee739cbc Fixed warnings for compiling OpenHMD, added static flag for windows compile 2016-03-17 20:06:05 +01:00
Julian Eisel
e56fda407c Fix: Image editor window opened when trying to open UserPref window 2016-03-17 18:48:20 +01:00
Julian Eisel
85cde2a444 Fix start session button not grayed out if HMD window was closed using window handlers 2016-03-17 18:38:28 +01:00
Julian Eisel
9c4e06fcc4 Make HMD session non-modal and move it to WM level 2016-03-17 18:14:56 +01:00
062d66156b Expanded OpenHMDManager with additional features 2016-03-17 18:04:07 +01:00
b7ff6efaf2 Fixed hmd event despatching for all operating systems 2016-03-17 17:24:45 +01:00
Julian Eisel
38c6437df7 Use initial camera rotation as starting rotation for HMD
We have to store the previous orientation quaternion so we can get the delta rotation to apply to the object. For now I added a global variable - ugly but works ;)

Currently, you have to set the camera to use quaternion rotation mode, others aren't really usable yet.
2016-03-17 15:56:44 +01:00
53d1c4ed05 Added compile static to OpenHMD cmake on windows 2016-03-17 15:46:48 +01:00
fcaf81cf2d Moved updating the OpenHMD events in the ghost system to a GHOST_System base class wich get called by the derived for OS independent updating 2016-03-17 15:24:27 +01:00
Julian Eisel
98535f578a Draw second camera with offset (actual 3D effect)
We're simply reusing stereo 3D pipeline here.
2016-03-17 00:17:45 +01:00
Julian Eisel
13d06fa38b Fix viewplane drawn with wrong offset 2016-03-17 00:15:49 +01:00
Julian Eisel
164a1af8cd Use a more common way to open the HMD window 2016-03-16 20:18:57 +01:00
f35c1a339d Added OpenHMD in the build structure, uses WITH_OPENHMD so it can be disabled
Has a requirement on libhidapi, cmake checks for that (should be added to install-deps)
2016-03-16 19:48:05 +01:00
Julian Eisel
a9d0ca72c6 Fix cycles not drawing correct settings for HMD UI 2016-03-16 17:24:32 +01:00
Julian Eisel
b0f91cc221 Merge remote-tracking branch 'github/vr_experiments' into HMD_viewport 2016-03-16 16:52:56 +01:00
Julian Eisel
c3b1c5d026 Merge remote-tracking branch 'github/vr_experiments' into HMD_viewport 2016-03-16 16:09:39 +01:00
Julian Eisel
1863ebcacc Fix outliner not recieving events while HMD session is running 2016-03-11 18:28:08 +01:00
Julian Eisel
5ff399d69a Let button to open HMD window close the win if it's already opened 2016-03-11 18:10:18 +01:00
Julian Eisel
30647c0d5c Custom title for HMD window ("Blender HMD View") 2016-03-11 17:03:45 +01:00
Julian Eisel
5ec1249769 Store HMD Window in Window Manager, avoids lookups and screen flag 2016-03-11 16:25:27 +01:00
Julian Eisel
a3d4644996 UI: Minor adjustments 2016-03-11 14:56:12 +01:00
163e978be1 Fixed lens distortion orientation 2016-03-11 06:24:11 +01:00
Julian Eisel
4f38d44eb2 Fix HMD updating even if HMD session is not running 2016-03-11 04:55:56 +01:00
Julian Eisel
cde072b618 Cleanup: Style, removed debug prints 2016-03-11 04:55:56 +01:00
713829c8e4 Merge branch 'vr_experiments' of https://github.com/julianeisel/blender into vr_experiments 2016-03-11 04:46:52 +01:00
e806f478e5 Finished lens distortion shader, removed some unused variables and cleaned up a bit 2016-03-11 04:45:52 +01:00
Julian Eisel
5b8c1da845 Fix HMD update events missing window 2016-03-11 04:43:33 +01:00
Julian Eisel
b8d2c0da47 Allow cursor to be in any window without stopping HMD update 2016-03-11 04:18:48 +01:00
Julian Eisel
c5a75b8647 Fix modal HMD session handler only called while cursor is in main window 2016-03-11 03:30:19 +01:00
Julian Eisel
409154f1f8 Don't allow to open multiple HMD views
And cleanup.
2016-03-11 03:24:23 +01:00
Julian Eisel
994e0b04d9 Fix missing play button 2016-03-11 03:17:52 +01:00
Julian Eisel
e4bc3bac37 Use modal handler for HMD session
Also some cleanup.
2016-03-11 03:05:14 +01:00
Julian Eisel
fe520b7688 Initial side-by-side HMD view support 2016-03-11 01:32:07 +01:00
d737b41a47 Added lens distortion glsl shader for use with HMD (Head Mounted Display) functionality
NOTE: Still has some debug information and test buttons
2016-03-10 20:02:02 +01:00
Julian Eisel
759be70ab4 Couple of fixes and make stuff working 2016-03-10 07:25:06 +01:00
Julian Eisel
8b701bb913 Hook up HMD with camera 2016-03-10 06:22:54 +01:00
Julian Eisel
764a878938 Get operator to open HMD window to work 2016-03-10 03:58:09 +01:00
Galadus
408cbe918b minor changes
ui patches copied from Severin
2016-03-10 01:38:26 +01:00
Galadus
57424a2401 Added OpenHMD Ghost manager
Added OpenHMD Ghost event
Added OpenHMD windowmanager event type for vr camera transform updates
Began integration if the OpenHMDManager with the ghost system (only updated from the GHOST_SystemX11 for now)
2016-03-09 21:44:53 +01:00
475 changed files with 17698 additions and 16778 deletions

View File

@@ -192,7 +192,7 @@ endif()
#-----------------------------------------------------------------------------
# Options
# First platform specific non-cached vars
# First platform spesific non-cached vars
if(UNIX AND NOT APPLE)
set(WITH_X11 ON)
endif()
@@ -363,12 +363,6 @@ option(WITH_LIBMV "Enable Libmv structure from motion library" ON)
option(WITH_LIBMV_SCHUR_SPECIALIZATIONS "Enable fixed-size schur specializations." OFF)
mark_as_advanced(WITH_LIBMV_SCHUR_SPECIALIZATIONS)
# Logging/unbit test libraries.
option(WITH_SYSTEM_GFLAGS "Use system-wide Gflags instead of a bundled one" OFF)
option(WITH_SYSTEM_GLOG "Use system-wide Glog instead of a bundled one" OFF)
mark_as_advanced(WITH_SYSTEM_GFLAGS)
mark_as_advanced(WITH_SYSTEM_GLOG)
# Freestyle
option(WITH_FREESTYLE "Enable Freestyle (advanced edges rendering)" ON)
@@ -377,6 +371,13 @@ if(WIN32)
option(WITH_INPUT_IME "Enable Input Method Editor (IME) for complex Asian character input" ON)
endif()
option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ${_init_INPUT_NDOF})
# HMD - actually not really input, there's also some other stuff for it
option(WITH_INPUT_HMD "Enable HMD support in Blender (Head Mounted Displays for VR support)" ON)
option(WITH_OPENHMD "Enable OpenHMD driver library" ON)
option(WITH_OPENHMD_DYNLOAD "Dynamically load OpenHMD dependencies at runtime" OFF)
mark_as_advanced(WITH_OPENHMD_DYNLOAD)
option(WITH_RAYOPTIMIZATION "Enable use of SIMD (SSE) optimizations for the raytracer" ON)
if(UNIX AND NOT APPLE)
option(WITH_INSTALL_PORTABLE "Install redistributeable runtime, otherwise install into CMAKE_INSTALL_PREFIX" ON)
@@ -566,7 +567,113 @@ endif()
# Apple
if(APPLE)
include(platform_apple_xcode)
# require newer cmake on osx because of version handling,
# older cmake cannot handle 2 digit subversion!
cmake_minimum_required(VERSION 3.0.0)
if(NOT CMAKE_OSX_ARCHITECTURES)
set(CMAKE_OSX_ARCHITECTURES x86_64 CACHE STRING
"Choose the architecture you want to build Blender for: i386, x86_64 or ppc"
FORCE)
endif()
if(NOT DEFINED OSX_SYSTEM)
execute_process(
COMMAND xcodebuild -version -sdk macosx SDKVersion
OUTPUT_VARIABLE OSX_SYSTEM
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
# workaround for incorrect cmake xcode lookup for developer previews - XCODE_VERSION does not
# take xcode-select path into account but would always look into /Applications/Xcode.app
# while dev versions are named Xcode<version>-DP<preview_number>
execute_process(
COMMAND xcode-select --print-path
OUTPUT_VARIABLE XCODE_CHECK OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REPLACE "/Contents/Developer" "" XCODE_BUNDLE ${XCODE_CHECK}) # truncate to bundlepath in any case
if(${CMAKE_GENERATOR} MATCHES "Xcode")
# earlier xcode has no bundled developer dir, no sense in getting xcode path from
if(${XCODE_VERSION} VERSION_GREATER 4.2)
# reduce to XCode name without dp extension
string(SUBSTRING "${XCODE_CHECK}" 14 6 DP_NAME)
if(${DP_NAME} MATCHES Xcode5)
set(XCODE_VERSION 5)
endif()
endif()
##### cmake incompatibility with xcode 4.3 and higher #####
if(${XCODE_VERSION} MATCHES '') # cmake fails due looking for xcode in the wrong path, thus will be empty var
message(FATAL_ERROR "Xcode 4.3 and higher must be used with cmake 2.8-8 or higher")
endif()
### end cmake incompatibility with xcode 4.3 and higher ###
if(${XCODE_VERSION} VERSION_EQUAL 4 OR ${XCODE_VERSION} VERSION_GREATER 4 AND ${XCODE_VERSION} VERSION_LESS 4.3)
# Xcode 4 defaults to the Apple LLVM Compiler.
# Override the default compiler selection because Blender only compiles with gcc up to xcode 4.2
set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvmgcc42")
message(STATUS "Setting compiler to: " ${CMAKE_XCODE_ATTRIBUTE_GCC_VERSION})
endif()
else() # unix makefile generator does not fill XCODE_VERSION var, so we get it with a command
execute_process(COMMAND xcodebuild -version OUTPUT_VARIABLE XCODE_VERS_BUILD_NR)
string(SUBSTRING "${XCODE_VERS_BUILD_NR}" 6 3 XCODE_VERSION) # truncate away build-nr
unset(XCODE_VERS_BUILD_NR)
endif()
message(STATUS "Detected OS X ${OSX_SYSTEM} and Xcode ${XCODE_VERSION} at ${XCODE_BUNDLE}")
if(${XCODE_VERSION} VERSION_LESS 4.3)
# use guaranteed existing sdk
set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk CACHE PATH "" FORCE)
else()
# note: xcode-select path could be ambigous,
# cause /Applications/Xcode.app/Contents/Developer or /Applications/Xcode.app would be allowed
# so i use a selfcomposed bundlepath here
set(OSX_SYSROOT_PREFIX ${XCODE_BUNDLE}/Contents/Developer/Platforms/MacOSX.platform)
message(STATUS "OSX_SYSROOT_PREFIX: " ${OSX_SYSROOT_PREFIX})
set(OSX_DEVELOPER_PREFIX /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk) # use guaranteed existing sdk
set(CMAKE_OSX_SYSROOT ${OSX_SYSROOT_PREFIX}/${OSX_DEVELOPER_PREFIX} CACHE PATH "" FORCE)
if(${CMAKE_GENERATOR} MATCHES "Xcode")
# to silence sdk not found warning, just overrides CMAKE_OSX_SYSROOT
set(CMAKE_XCODE_ATTRIBUTE_SDKROOT macosx${OSX_SYSTEM})
endif()
# QuickTime framework is no longer available in SDK 10.12+
if(WITH_CODEC_QUICKTIME AND ${OSX_SYSTEM} VERSION_GREATER 10.11)
set(WITH_CODEC_QUICKTIME OFF)
message(STATUS "QuickTime not supported by SDK ${OSX_SYSTEM}, disabling WITH_CODEC_QUICKTIME")
endif()
endif()
if(OSX_SYSTEM MATCHES 10.9)
# make sure syslibs and headers are looked up in sdk ( expecially for 10.9 openGL atm. )
set(CMAKE_FIND_ROOT_PATH ${CMAKE_OSX_SYSROOT})
endif()
if(WITH_CXX11)
# 10.9 is our min. target, if you use higher sdk, weak linking happens
if(CMAKE_OSX_DEPLOYMENT_TARGET)
if(${CMAKE_OSX_DEPLOYMENT_TARGET} VERSION_LESS 10.9)
message(STATUS "Setting deployment target to 10.9, lower versions are incompatible with WITH_CXX11")
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "" FORCE)
endif()
else()
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "" FORCE)
endif()
else()
if(NOT CMAKE_OSX_DEPLOYMENT_TARGET)
# 10.6 is our min. target, if you use higher sdk, weak linking happens
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.6" CACHE STRING "" FORCE)
endif()
endif()
if(NOT ${CMAKE_GENERATOR} MATCHES "Xcode")
# force CMAKE_OSX_DEPLOYMENT_TARGET for makefiles, will not work else ( cmake bug ? )
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
add_definitions("-DMACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}")
endif()
endif()
@@ -609,6 +716,15 @@ if(WITH_PYTHON_MODULE AND WITH_PYTHON_INSTALL)
message(FATAL_ERROR "WITH_PYTHON_MODULE requires WITH_PYTHON_INSTALL to be OFF")
endif()
if(WITH_INPUT_HMD AND NOT WITH_OPENHMD)
message(WARNING "WITH_INPUT_HMD is enabled, but OpenHMD driver (WITH_OPENHMD) is disabled. "
"Only a limited set of HMD features will be available.")
endif()
if(WITH_OPENHMD AND NOT WITH_INPUT_HMD)
message(FATAL_ERROR "WITH_OPENHMD requires WITH_INPUT_HMD")
endif()
# may as well build python module without a UI
if(WITH_PYTHON_MODULE)
@@ -736,10 +852,6 @@ if(WITH_AUDASPACE)
endif()
endif()
if(APPLE)
apple_check_quicktime()
endif()
#-----------------------------------------------------------------------------
# Check for valid directories
# ... a partial checkout may cause this.
@@ -917,16 +1029,16 @@ endif()
if(MSVC)
# for some reason this fails on msvc
add_definitions(-D__LITTLE_ENDIAN__)
# OSX-Note: as we do cross-compiling with specific set architecture,
# endianess-detection and auto-setting is counterproductive
# OSX-Note: as we do crosscompiling with specific set architecture,
# endianess-detection and autosetting is counterproductive
# so we just set endianess according CMAKE_OSX_ARCHITECTURES
elseif(CMAKE_OSX_ARCHITECTURES MATCHES i386 OR CMAKE_OSX_ARCHITECTURES MATCHES x86_64)
add_definitions(-D__LITTLE_ENDIAN__)
elseif(CMAKE_OSX_ARCHITECTURES MATCHES ppc OR CMAKE_OSX_ARCHITECTURES MATCHES ppc64)
elseif(CMAKE_OSX_ARCHITECTURES MATCHES ppc OR CMAKE_OSX_ARCHITECTURES MATCHES ppc64)
add_definitions(-D__BIG_ENDIAN__)
else()
include(TestBigEndian)
test_big_endian(_SYSTEM_BIG_ENDIAN)
@@ -1221,42 +1333,15 @@ endif()
# Configure GLog/GFlags
if(WITH_LIBMV OR WITH_GTESTS OR (WITH_CYCLES AND WITH_CYCLES_LOGGING))
if(WITH_SYSTEM_GFLAGS)
find_package(Gflags)
if(NOT GFLAGS_FOUND)
message(FATAL_ERROR "System wide Gflags is requested but was not found")
endif()
# FindGflags does not define this, and we are not even sure what to use here.
set(GFLAGS_DEFINES)
else()
set(GFLAGS_DEFINES
-DGFLAGS_DLL_DEFINE_FLAG=
-DGFLAGS_DLL_DECLARE_FLAG=
-DGFLAGS_DLL_DECL=
)
set(GFLAGS_NAMESPACE "gflags")
set(GFLAGS_LIBRARIES extern_gflags)
set(GFLAGS_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/extern/gflags/src")
endif()
set(GLOG_DEFINES
-DGOOGLE_GLOG_DLL_DECL=
)
if(WITH_SYSTEM_GLOG)
find_package(Glog)
if(NOT GLOG_FOUND)
message(FATAL_ERROR "System wide Glog is requested but was not found")
endif()
# FindGlog does not define this, and we are not even sure what to use here.
set(GLOG_DEFINES)
else()
set(GLOG_DEFINES
-DGOOGLE_GLOG_DLL_DECL=
)
set(GLOG_LIBRARIES extern_glog)
if(WIN32)
set(GLOG_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/glog/src/windows)
else()
set(GLOG_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/glog/src)
endif()
endif()
set(GFLAGS_DEFINES
-DGFLAGS_DLL_DEFINE_FLAG=
-DGFLAGS_DLL_DECLARE_FLAG=
-DGFLAGS_DLL_DECL=
)
endif()
#-----------------------------------------------------------------------------
@@ -1538,7 +1623,7 @@ endif()
set(CMAKE_C_FLAGS "${C_WARNINGS} ${CMAKE_C_FLAGS} ${PLATFORM_CFLAGS}")
set(CMAKE_CXX_FLAGS "${CXX_WARNINGS} ${CMAKE_CXX_FLAGS} ${PLATFORM_CFLAGS}")
# defined above, platform specific but shared names
# defined above, platform spesific but shared names
mark_as_advanced(
CYCLES_OSL
OSL_LIB_EXEC

View File

@@ -30,13 +30,13 @@ with-all,with-opencollada,\
ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,ver-osd:,ver-openvdb:,\
force-all,force-python,force-numpy,force-boost,\
force-ocio,force-openexr,force-oiio,force-llvm,force-osl,force-osd,force-openvdb,\
force-ffmpeg,force-opencollada,force-alembic,\
force-ffmpeg,force-opencollada,force-alembic,force-hidapi\
build-all,build-python,build-numpy,build-boost,\
build-ocio,build-openexr,build-oiio,build-llvm,build-osl,build-osd,build-openvdb,\
build-ffmpeg,build-opencollada,build-alembic,\
build-ffmpeg,build-opencollada,build-alembic,build-hidapi\
skip-python,skip-numpy,skip-boost,\
skip-ocio,skip-openexr,skip-oiio,skip-llvm,skip-osl,skip-osd,skip-openvdb,\
skip-ffmpeg,skip-opencollada,skip-alembic \
skip-ffmpeg,skip-opencollada,skip-alembic,skip-hidapi \
-- "$@" \
)
@@ -182,6 +182,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
--build-ffmpeg
Force the build of FFMpeg.
--build-hidapi
Force the build of hidapi.
Note about the --build-foo options:
* They force the script to prefer building dependencies rather than using available packages.
This may make things simpler and allow working around some distribution bugs, but on the other hand it will
@@ -234,6 +237,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
--force-ffmpeg
Force the rebuild of FFMpeg.
--force-hidapi
Force the rebuild of hidapi.
Note about the --force-foo options:
* They obviously only have an effect if those libraries are built by this script
(i.e. if there is no available and satisfactory package)!
@@ -277,7 +283,10 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
Unconditionally skip OpenCOLLADA installation/building.
--skip-ffmpeg
Unconditionally skip FFMpeg installation/building.\""
Unconditionally skip FFMpeg installation/building.
--skip-hidapi
Unconditionally skip hidapi installation/building.\""
##### Main Vars #####
@@ -399,6 +408,12 @@ MP3LAME_DEV=""
OPENJPEG_USE=false
OPENJPEG_DEV=""
HIDAPI_VERSION="0.8.0"
HIDAPI_VERSION_MIN="0.8.0"
HIDAPI_FORCE_BUILD=false
HIDAPI_FORCE_REBUILD=false
HIDAPI_SKIP=false
# Whether to use system GLEW or not (OpenSubDiv needs recent glew to work).
NO_SYSTEM_GLEW=false
@@ -597,6 +612,9 @@ while true; do
--build-alembic)
ALEMBIC_FORCE_BUILD=true; shift; continue
;;
--build-hidapi)
HIDAPI_FORCE_BUILD=true; shift; continue
;;
--force-all)
PYTHON_FORCE_REBUILD=true
NUMPY_FORCE_REBUILD=true
@@ -611,6 +629,7 @@ while true; do
OPENCOLLADA_FORCE_REBUILD=true
FFMPEG_FORCE_REBUILD=true
ALEMBIC_FORCE_REBUILD=true
HIDAPI_FORCE_REBUILD=true
shift; continue
;;
--force-python)
@@ -654,6 +673,9 @@ while true; do
--force-alembic)
ALEMBIC_FORCE_REBUILD=true; shift; continue
;;
--force-hidapi)
HIDAPI_FORCE_REBUILD=true; shift; continue
;;
--skip-python)
PYTHON_SKIP=true; shift; continue
;;
@@ -693,6 +715,9 @@ while true; do
--skip-alembic)
ALEMBIC_SKIP=true; shift; continue
;;
--skip-hidapi)
HIDAPI_SKIP=true; shift; continue
;;
--)
# no more arguments to parse
break
@@ -791,6 +816,8 @@ OPENCOLLADA_REPO_BRANCH="master"
FFMPEG_SOURCE=( "http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2" )
HIDAPI_SOURCE=( "https://github.com/signal11/hidapi/archive/hidapi-0.8.0-rc1.tar.gz" )
CXXFLAGS_BACK=$CXXFLAGS
if [ "$USE_CXX11" = true ]; then
WARNING "You are trying to use c++11, this *should* go smoothely with any very recent distribution
@@ -839,7 +866,8 @@ You may also want to build them yourself (optional ones are [between brackets]):
* [OpenSubDiv $OSD_VERSION_MIN] (from $OSD_SOURCE_REPO, branch $OSD_SOURCE_REPO_BRANCH, commit $OSD_SOURCE_REPO_UID).
* [OpenVDB $OPENVDB_VERSION_MIN] (from $OPENVDB_SOURCE), [Blosc $OPENVDB_BLOSC_VERSION] (from $OPENVDB_BLOSC_SOURCE).
* [OpenCollada] (from $OPENCOLLADA_SOURCE, branch $OPENCOLLADA_REPO_BRANCH, commit $OPENCOLLADA_REPO_UID).
* [Alembic $ALEMBIC_VERSION] (from $ALEMBIC_SOURCE).\""
* [Alembic $ALEMBIC_VERSION] (from $ALEMBIC_SOURCE).
* [HIDAPI $HIDAPI_VERSION] (from $HIDAPI_SOURCE).\""
if [ "$DO_SHOW_DEPS" = true ]; then
PRINT ""
@@ -2511,6 +2539,75 @@ compile_FFmpeg() {
fi
}
#### Build HIDAPI ####
_init_hidapi() {
_src=$SRC/hidapi-$HIDAPI_VERSION
_inst=$INST/hidapi-$HIDAPI_VERSION
_inst_shortcut=$INST/hidapi
}
clean_hidapi() {
_init_hidapi
_clean
}
compile_hidapi() {
if [ "$NO_BUILD" = true ]; then
WARNING "--no-build enabled, HIDAPI will not be compiled!"
return
fi
# To be changed each time we make edits that would modify the compiled result!
hidapi_magic=1
_init_hidapi
# Clean install if needed!
magic_compile_check hidapi-$HIDAPI_VERSION $hidapi_magic
if [ $? -eq 1 -o "$HIDAPI_FORCE_REBUILD" = true ]; then
clean_hidapi
fi
if [ ! -d $_inst ]; then
INFO "Building hidapi-$HIDAPI_VERSION"
prepare_opt
if [ ! -d $_src -o true ]; then
mkdir -p $SRC
download HIDAPI_SOURCE[@] "$_src.tar.gz"
INFO "Unpacking hidapi-$HIDAPI_VERSION"
tar -C $SRC --transform "s,(/?)hidapi-[^/]*(.*),\1hidapi-$HIDAPI_VERSION\2,x" -xf $_src.tar.gz
fi
cd $_src
./bootstrap
./configure --prefix=$_inst
make -j$THREADS install
make clean
if [ -d $_inst ]; then
_create_inst_shortcut
else
ERROR "hidapi-$HIDAPI_VERSION failed to compile, exiting"
exit 1
fi
magic_compile_set hidapi-$HIDAPI_VERSION $hidapi_magic
cd $CWD
INFO "Done compiling hidapi-$HIDAPI_VERSION!"
else
INFO "Own hidapi-$HIDAPI_VERSION is up to date, nothing to do!"
INFO "If you want to force rebuild of this lib, use the --force-hidapi option."
fi
run_ldconfig "hidapi"
}
#### Install on DEB-like ####
get_package_version_DEB() {
@@ -2601,6 +2698,7 @@ install_DEB() {
fi
# These libs should always be available in debian/ubuntu official repository...
OPENJPEG_DEV="libopenjpeg-dev"
VORBIS_DEV="libvorbis-dev"
OGG_DEV="libogg-dev"
THEORA_DEV="libtheora-dev"
@@ -2608,24 +2706,16 @@ install_DEB() {
_packages="gawk cmake cmake-curses-gui build-essential libjpeg-dev libpng-dev libtiff-dev \
git libfreetype6-dev libx11-dev flex bison libtbb-dev libxxf86vm-dev \
libxcursor-dev libxi-dev wget libsqlite3-dev libxrandr-dev libxinerama-dev \
libbz2-dev libncurses5-dev libssl-dev liblzma-dev libreadline-dev \
libbz2-dev libncurses5-dev libssl-dev liblzma-dev libreadline-dev $OPENJPEG_DEV \
libopenal-dev libglew-dev yasm $THEORA_DEV $VORBIS_DEV $OGG_DEV \
libsdl1.2-dev libfftw3-dev patch bzip2 libxml2-dev libtinyxml-dev libjemalloc-dev"
# libglewmx-dev (broken in deb testing currently...)
OPENJPEG_USE=true
VORBIS_USE=true
OGG_USE=true
THEORA_USE=true
PRINT ""
# New Ubuntu crap (17.04 and more) have no openjpeg lib!
OPENJPEG_DEV="libopenjpeg-dev"
check_package_DEB $OPENJPEG_DEV
if [ $? -eq 0 ]; then
_packages="$_packages $OPENJPEG_DEV"
OPENJPEG_USE=true
fi
PRINT ""
# Some not-so-old distro (ubuntu 12.4) do not have it, do not fail in this case, just warn.
YAMLCPP_DEV="libyaml-cpp-dev"
@@ -2989,6 +3079,34 @@ install_DEB() {
compile_FFmpeg
fi
fi
PRINT ""
_do_compile_hidapi=false
if [ "$HIDAPI_SKIP" = true ]; then
WARNING "Skipping hidapi installation, as requested..."
elif [ "$HIDAPI_FORCE_BUILD" = true ]; then
INFO "Forced hidapi building, as requested..."
_do_compile_hidapi=true
else
check_package_DEB libhidapi-dev
if [ $? -eq 0 ]; then
check_package_version_ge_DEB libhidapi-dev $HIDAPI_VERSION_MIN
if [ $? -eq 0 ]; then
install_packages_DEB libhidapi-dev
clean_hidapi
else
_do_compile_hidapi=true
fi
else
_do_compile_hidapi=true
fi
fi
if [ "$_do_compile_hidapi" = true ]; then
install_packages_DEB libudev-dev libusb-1.0-0-dev
compile_hidapi
fi
}
@@ -3530,6 +3648,33 @@ install_RPM() {
compile_FFmpeg
fi
fi
PRINT ""
_do_compile_hidapi=false
if [ "$HIDAPI_SKIP" = true ]; then
WARNING "Skipping hidapi installation, as requested..."
elif [ "$HIDAPI_FORCE_BUILD" = true ]; then
INFO "Forced hidapi building, as requested..."
_do_compile_hidapi=true
else
check_package_RPM hidapi-devel
if [ $? -eq 0 ]; then
check_package_version_ge_RPM hidapi-devel $HIDAPI_VERSION_MIN
if [ $? -eq 0 ]; then
install_packages_RPM hidapi-devel
clean_hidapi
else
_do_compile_hidapi=true
fi
else
_do_compile_hidapi=true
fi
fi
if [ "$_do_compile_hidapi" = true ]; then
install_packages_RPM libusbx-devel # No libudev in fedora?
compile_hidapi
fi
}
@@ -3955,6 +4100,33 @@ install_ARCH() {
compile_FFmpeg
fi
fi
PRINT ""
_do_compile_hidapi=false
if [ "$HIDAPI_SKIP" = true ]; then
WARNING "Skipping hidapi installation, as requested..."
elif [ "$HIDAPI_FORCE_BUILD" = true ]; then
INFO "Forced hidapi building, as requested..."
_do_compile_hidapi=true
else
check_package_ARCH hidapi
if [ $? -eq 0 ]; then
check_package_version_ge_ARCH hidapi $HIDAPI_VERSION_MIN
if [ $? -eq 0 ]; then
install_packages_ARCH hidapi
clean_hidapi
else
_do_compile_hidapi=true
fi
else
_do_compile_hidapi=true
fi
fi
if [ "$_do_compile_hidapi" = true ]; then
install_packages_ARCH libusb # No libudev in arch?
compile_hidapi
fi
}
@@ -4118,6 +4290,16 @@ install_OTHER() {
INFO "Forced FFMpeg building, as requested..."
compile_FFmpeg
fi
PRINT ""
_do_compile_hidapi=false
if [ "$HIDAPI_SKIP" = true ]; then
WARNING "Skipping hidapi installation, as requested..."
elif [ "$HIDAPI_FORCE_BUILD" = true ]; then
INFO "Forced hidapi building, as requested..."
compile_hidapi
fi
}
#### Printing User Info ####
@@ -4199,7 +4381,7 @@ print_info() {
_buildargs="-U *SNDFILE* -U *PYTHON* -U *BOOST* -U *Boost*"
_buildargs="$_buildargs -U *OPENCOLORIO* -U *OPENEXR* -U *OPENIMAGEIO* -U *LLVM* -U *CYCLES*"
_buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *COLLADA* -U *FFMPEG* -U *ALEMBIC*"
_buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *COLLADA* -U *FFMPEG* -U *ALEMBIC* -U *OPENHMD* -U *HIDAPI*"
if [ "$USE_CXX11" = true ]; then
_1="-D WITH_CXX11=ON"
@@ -4341,6 +4523,17 @@ print_info() {
fi
fi
if [ "$HIDAPI_SKIP" = false ]; then
_1="-D WITH_OPENHMD=ON"
PRINT " $_1"
_buildargs="$_buildargs $_1"
if [ -d $INST/hidapi ]; then
_1="-D HIDAPI_ROOT_DIR=$INST/hidapi"
PRINT " $_1"
_buildargs="$_buildargs $_1"
fi
fi
PRINT ""
PRINT "Or even simpler, just run (in your blender-source dir):"
PRINT " make -j$THREADS BUILD_CMAKE_ARGS=\"$_buildargs\""

View File

@@ -144,5 +144,14 @@ set(OPENVDB_LIBRARY
CACHE BOOL "" FORCE
)
# OpenHMD
if(GLIBC EQUAL "2.19")
set(HIDAPI_LIBRARY
/usr/lib${MULTILIB}/libhidapi-hidraw.a
CACHE STRING "" FORCE
)
set(WITH_OPENHMD_DYNLOAD ON CACHE BOOL "" FORCE)
endif()
# Additional linking libraries
set(CMAKE_EXE_LINKER_FLAGS "-lrt -static-libstdc++" CACHE STRING "" FORCE)

View File

@@ -1,603 +0,0 @@
# Ceres Solver - A fast non-linear least squares minimizer
# Copyright 2015 Google Inc. All rights reserved.
# http://ceres-solver.org/
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Google Inc. nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# Author: alexs.mac@gmail.com (Alex Stewart)
#
# FindGflags.cmake - Find Google gflags logging library.
#
# This module will attempt to find gflags, either via an exported CMake
# configuration (generated by gflags >= 2.1 which are built with CMake), or
# by performing a standard search for all gflags components. The order of
# precedence for these two methods of finding gflags is controlled by:
# GFLAGS_PREFER_EXPORTED_GFLAGS_CMAKE_CONFIGURATION.
#
# This module defines the following variables:
#
# GFLAGS_FOUND: TRUE iff gflags is found.
# GFLAGS_INCLUDE_DIRS: Include directories for gflags.
# GFLAGS_LIBRARIES: Libraries required to link gflags.
# GFLAGS_NAMESPACE: The namespace in which gflags is defined. In versions of
# gflags < 2.1, this was google, for versions >= 2.1 it is
# by default gflags, although can be configured when building
# gflags to be something else (i.e. google for legacy
# compatibility).
#
# The following variables control the behaviour of this module when an exported
# gflags CMake configuration is not found.
#
# GFLAGS_PREFER_EXPORTED_GFLAGS_CMAKE_CONFIGURATION: TRUE/FALSE, iff TRUE then
# then prefer using an exported CMake configuration
# generated by gflags >= 2.1 over searching for the
# gflags components manually. Otherwise (FALSE)
# ignore any exported gflags CMake configurations and
# always perform a manual search for the components.
# Default: TRUE iff user does not define this variable
# before we are called, and does NOT specify either
# GFLAGS_INCLUDE_DIR_HINTS or GFLAGS_LIBRARY_DIR_HINTS
# otherwise FALSE.
# GFLAGS_INCLUDE_DIR_HINTS: List of additional directories in which to
# search for gflags includes, e.g: /timbuktu/include.
# GFLAGS_LIBRARY_DIR_HINTS: List of additional directories in which to
# search for gflags libraries, e.g: /timbuktu/lib.
# GFLAGS_ROOT_DIR, The base directory to search for Gflags.
# This can also be an environment variable.
#
# The following variables are also defined by this module, but in line with
# CMake recommended FindPackage() module style should NOT be referenced directly
# by callers (use the plural variables detailed above instead). These variables
# do however affect the behaviour of the module via FIND_[PATH/LIBRARY]() which
# are NOT re-called (i.e. search for library is not repeated) if these variables
# are set with valid values _in the CMake cache_. This means that if these
# variables are set directly in the cache, either by the user in the CMake GUI,
# or by the user passing -DVAR=VALUE directives to CMake when called (which
# explicitly defines a cache variable), then they will be used verbatim,
# bypassing the HINTS variables and other hard-coded search locations.
#
# GFLAGS_INCLUDE_DIR: Include directory for gflags, not including the
# include directory of any dependencies.
# GFLAGS_LIBRARY: gflags library, not including the libraries of any
# dependencies.
# If GFLAGS_ROOT_DIR was defined in the environment, use it.
if(NOT GFLAGS_ROOT_DIR AND NOT $ENV{GFLAGS_ROOT_DIR} STREQUAL "")
set(GFLAGS_ROOT_DIR $ENV{GFLAGS_ROOT_DIR})
endif()
if(DEFINED GFLAGS_ROOT_DIR)
set(GFLAGS_ROOT_DIR_INCLUDE "${GFLAGS_ROOT_DIR}/include")
set(GFLAGS_ROOT_DIR_LIB "${GFLAGS_ROOT_DIR}/lib")
endif()
# Reset CALLERS_CMAKE_FIND_LIBRARY_PREFIXES to its value when FindGflags was
# invoked, necessary for MSVC.
macro(GFLAGS_RESET_FIND_LIBRARY_PREFIX)
if(MSVC)
set(CMAKE_FIND_LIBRARY_PREFIXES "${CALLERS_CMAKE_FIND_LIBRARY_PREFIXES}")
endif()
endmacro()
# Called if we failed to find gflags or any of it's required dependencies,
# unsets all public (designed to be used externally) variables and reports
# error message at priority depending upon [REQUIRED/QUIET/<NONE>] argument.
macro(GFLAGS_REPORT_NOT_FOUND REASON_MSG)
unset(GFLAGS_FOUND)
unset(GFLAGS_INCLUDE_DIRS)
unset(GFLAGS_LIBRARIES)
# Do not use unset, as we want to keep GFLAGS_NAMESPACE in the cache,
# but simply clear its value.
set(GFLAGS_NAMESPACE "" CACHE STRING
"gflags namespace (google or gflags)" FORCE)
# Make results of search visible in the CMake GUI if gflags has not
# been found so that user does not have to toggle to advanced view.
mark_as_advanced(CLEAR GFLAGS_INCLUDE_DIR
GFLAGS_LIBRARY
GFLAGS_NAMESPACE)
gflags_reset_find_library_prefix()
# Note <package>_FIND_[REQUIRED/QUIETLY] variables defined by FindPackage()
# use the camelcase library name, not uppercase.
if(Gflags_FIND_QUIETLY)
message(STATUS "Failed to find gflags - " ${REASON_MSG} ${ARGN})
elseif(Gflags_FIND_REQUIRED)
message(FATAL_ERROR "Failed to find gflags - " ${REASON_MSG} ${ARGN})
else()
# Neither QUIETLY nor REQUIRED, use no priority which emits a message
# but continues configuration and allows generation.
message("-- Failed to find gflags - " ${REASON_MSG} ${ARGN})
endif()
return()
endmacro()
# Verify that all variable names passed as arguments are defined (can be empty
# but must be defined) or raise a fatal error.
macro(GFLAGS_CHECK_VARS_DEFINED)
foreach(CHECK_VAR ${ARGN})
if(NOT DEFINED ${CHECK_VAR})
message(FATAL_ERROR "Ceres Bug: ${CHECK_VAR} is not defined.")
endif()
endforeach()
endmacro()
# Use check_cxx_source_compiles() to compile trivial test programs to determine
# the gflags namespace. This works on all OSs except Windows. If using Visual
# Studio, it fails because msbuild forces check_cxx_source_compiles() to use
# CMAKE_BUILD_TYPE=Debug for the test project, which usually breaks detection
# because MSVC requires that the test project use the same build type as gflags,
# which would normally be built in Release.
#
# Defines: GFLAGS_NAMESPACE in the caller's scope with the detected namespace,
# which is blank (empty string, will test FALSE is CMake conditionals)
# if detection failed.
function(GFLAGS_CHECK_GFLAGS_NAMESPACE_USING_TRY_COMPILE)
# Verify that all required variables are defined.
gflags_check_vars_defined(
GFLAGS_INCLUDE_DIR GFLAGS_LIBRARY)
# Ensure that GFLAGS_NAMESPACE is always unset on completion unless
# we explicitly set if after having the correct namespace.
set(GFLAGS_NAMESPACE "" PARENT_SCOPE)
include(CheckCXXSourceCompiles)
# Setup include path & link library for gflags for CHECK_CXX_SOURCE_COMPILES.
set(CMAKE_REQUIRED_INCLUDES ${GFLAGS_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${GFLAGS_LIBRARY} ${GFLAGS_LINK_LIBRARIES})
# First try the (older) google namespace. Note that the output variable
# MUST be unique to the build type as otherwise the test is not repeated as
# it is assumed to have already been performed.
check_cxx_source_compiles(
"#include <gflags/gflags.h>
int main(int argc, char * argv[]) {
google::ParseCommandLineFlags(&argc, &argv, true);
return 0;
}"
GFLAGS_IN_GOOGLE_NAMESPACE)
if(GFLAGS_IN_GOOGLE_NAMESPACE)
set(GFLAGS_NAMESPACE google PARENT_SCOPE)
return()
endif()
# Try (newer) gflags namespace instead. Note that the output variable
# MUST be unique to the build type as otherwise the test is not repeated as
# it is assumed to have already been performed.
set(CMAKE_REQUIRED_INCLUDES ${GFLAGS_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${GFLAGS_LIBRARY} ${GFLAGS_LINK_LIBRARIES})
check_cxx_source_compiles(
"#include <gflags/gflags.h>
int main(int argc, char * argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
return 0;
}"
GFLAGS_IN_GFLAGS_NAMESPACE)
if(GFLAGS_IN_GFLAGS_NAMESPACE)
set(GFLAGS_NAMESPACE gflags PARENT_SCOPE)
return()
endif()
endfunction()
# Use regex on the gflags headers to attempt to determine the gflags namespace.
# Checks both gflags.h (contained namespace on versions < 2.1.2) and
# gflags_declare.h, which contains the namespace on versions >= 2.1.2.
# In general, this method should only be used when
# GFLAGS_CHECK_GFLAGS_NAMESPACE_USING_TRY_COMPILE() cannot be used, or has
# failed.
#
# Defines: GFLAGS_NAMESPACE in the caller's scope with the detected namespace,
# which is blank (empty string, will test FALSE is CMake conditionals)
# if detection failed.
function(GFLAGS_CHECK_GFLAGS_NAMESPACE_USING_REGEX)
# Verify that all required variables are defined.
gflags_check_vars_defined(GFLAGS_INCLUDE_DIR)
# Ensure that GFLAGS_NAMESPACE is always undefined on completion unless
# we explicitly set if after having the correct namespace.
set(GFLAGS_NAMESPACE "" PARENT_SCOPE)
# Scan gflags.h to identify what namespace gflags was built with. On
# versions of gflags < 2.1.2, gflags.h was configured with the namespace
# directly, on >= 2.1.2, gflags.h uses the GFLAGS_NAMESPACE #define which
# is defined in gflags_declare.h, we try each location in turn.
set(GFLAGS_HEADER_FILE ${GFLAGS_INCLUDE_DIR}/gflags/gflags.h)
if(NOT EXISTS ${GFLAGS_HEADER_FILE})
gflags_report_not_found(
"Could not find file: ${GFLAGS_HEADER_FILE} "
"containing namespace information in gflags install located at: "
"${GFLAGS_INCLUDE_DIR}.")
endif()
file(READ ${GFLAGS_HEADER_FILE} GFLAGS_HEADER_FILE_CONTENTS)
string(REGEX MATCH "namespace [A-Za-z]+"
GFLAGS_NAMESPACE "${GFLAGS_HEADER_FILE_CONTENTS}")
string(REGEX REPLACE "namespace ([A-Za-z]+)" "\\1"
GFLAGS_NAMESPACE "${GFLAGS_NAMESPACE}")
if(NOT GFLAGS_NAMESPACE)
gflags_report_not_found(
"Failed to extract gflags namespace from header file: "
"${GFLAGS_HEADER_FILE}.")
endif()
if(GFLAGS_NAMESPACE STREQUAL "google" OR
GFLAGS_NAMESPACE STREQUAL "gflags")
# Found valid gflags namespace from gflags.h.
set(GFLAGS_NAMESPACE "${GFLAGS_NAMESPACE}" PARENT_SCOPE)
return()
endif()
# Failed to find gflags namespace from gflags.h, gflags is likely a new
# version, check gflags_declare.h, which in newer versions (>= 2.1.2) contains
# the GFLAGS_NAMESPACE #define, which is then referenced in gflags.h.
set(GFLAGS_DECLARE_FILE ${GFLAGS_INCLUDE_DIR}/gflags/gflags_declare.h)
if(NOT EXISTS ${GFLAGS_DECLARE_FILE})
gflags_report_not_found(
"Could not find file: ${GFLAGS_DECLARE_FILE} "
"containing namespace information in gflags install located at: "
"${GFLAGS_INCLUDE_DIR}.")
endif()
file(READ ${GFLAGS_DECLARE_FILE} GFLAGS_DECLARE_FILE_CONTENTS)
string(REGEX MATCH "#define GFLAGS_NAMESPACE [A-Za-z]+"
GFLAGS_NAMESPACE "${GFLAGS_DECLARE_FILE_CONTENTS}")
string(REGEX REPLACE "#define GFLAGS_NAMESPACE ([A-Za-z]+)" "\\1"
GFLAGS_NAMESPACE "${GFLAGS_NAMESPACE}")
if(NOT GFLAGS_NAMESPACE)
gflags_report_not_found(
"Failed to extract gflags namespace from declare file: "
"${GFLAGS_DECLARE_FILE}.")
endif()
if(GFLAGS_NAMESPACE STREQUAL "google" OR
GFLAGS_NAMESPACE STREQUAL "gflags")
# Found valid gflags namespace from gflags.h.
set(GFLAGS_NAMESPACE "${GFLAGS_NAMESPACE}" PARENT_SCOPE)
return()
endif()
endfunction()
# -----------------------------------------------------------------
# By default, if the user has expressed no preference for using an exported
# gflags CMake configuration over performing a search for the installed
# components, and has not specified any hints for the search locations, then
# prefer a gflags exported configuration if available.
if(NOT DEFINED GFLAGS_PREFER_EXPORTED_GFLAGS_CMAKE_CONFIGURATION
AND NOT GFLAGS_INCLUDE_DIR_HINTS
AND NOT GFLAGS_LIBRARY_DIR_HINTS)
message(STATUS "No preference for use of exported gflags CMake configuration "
"set, and no hints for include/library directories provided. "
"Defaulting to preferring an installed/exported gflags CMake configuration "
"if available.")
set(GFLAGS_PREFER_EXPORTED_GFLAGS_CMAKE_CONFIGURATION TRUE)
endif()
if(GFLAGS_PREFER_EXPORTED_GFLAGS_CMAKE_CONFIGURATION)
# Try to find an exported CMake configuration for gflags, as generated by
# gflags versions >= 2.1.
#
# We search twice, s/t we can invert the ordering of precedence used by
# find_package() for exported package build directories, and installed
# packages (found via CMAKE_SYSTEM_PREFIX_PATH), listed as items 6) and 7)
# respectively in [1].
#
# By default, exported build directories are (in theory) detected first, and
# this is usually the case on Windows. However, on OS X & Linux, the install
# path (/usr/local) is typically present in the PATH environment variable
# which is checked in item 4) in [1] (i.e. before both of the above, unless
# NO_SYSTEM_ENVIRONMENT_PATH is passed). As such on those OSs installed
# packages are usually detected in preference to exported package build
# directories.
#
# To ensure a more consistent response across all OSs, and as users usually
# want to prefer an installed version of a package over a locally built one
# where both exist (esp. as the exported build directory might be removed
# after installation), we first search with NO_CMAKE_PACKAGE_REGISTRY which
# means any build directories exported by the user are ignored, and thus
# installed directories are preferred. If this fails to find the package
# we then research again, but without NO_CMAKE_PACKAGE_REGISTRY, so any
# exported build directories will now be detected.
#
# To prevent confusion on Windows, we also pass NO_CMAKE_BUILDS_PATH (which
# is item 5) in [1]), to not preferentially use projects that were built
# recently with the CMake GUI to ensure that we always prefer an installed
# version if available.
#
# [1] http://www.cmake.org/cmake/help/v2.8.11/cmake.html#command:find_package
find_package(gflags QUIET
NO_MODULE
NO_CMAKE_PACKAGE_REGISTRY
NO_CMAKE_BUILDS_PATH)
if(gflags_FOUND)
message(STATUS "Found installed version of gflags: ${gflags_DIR}")
else()
# Failed to find an installed version of gflags, repeat search allowing
# exported build directories.
message(STATUS "Failed to find installed gflags CMake configuration, "
"searching for gflags build directories exported with CMake.")
# Again pass NO_CMAKE_BUILDS_PATH, as we know that gflags is exported and
# do not want to treat projects built with the CMake GUI preferentially.
find_package(gflags QUIET
NO_MODULE
NO_CMAKE_BUILDS_PATH)
if(gflags_FOUND)
message(STATUS "Found exported gflags build directory: ${gflags_DIR}")
endif()
endif()
set(FOUND_INSTALLED_GFLAGS_CMAKE_CONFIGURATION ${gflags_FOUND})
# gflags v2.1 - 2.1.2 shipped with a bug in their gflags-config.cmake [1]
# whereby gflags_LIBRARIES = "gflags", but there was no imported target
# called "gflags", they were called: gflags[_nothreads]-[static/shared].
# As this causes linker errors when gflags is not installed in a location
# on the current library paths, detect if this problem is present and
# fix it.
#
# [1] https://github.com/gflags/gflags/issues/110
if(gflags_FOUND)
# NOTE: This is not written as additional conditions in the outer
# if(gflags_FOUND) as the NOT TARGET "${gflags_LIBRARIES}"
# condition causes problems if gflags is not found.
if(${gflags_VERSION} VERSION_LESS 2.1.3 AND
NOT TARGET "${gflags_LIBRARIES}")
message(STATUS "Detected broken gflags install in: ${gflags_DIR}, "
"version: ${gflags_VERSION} <= 2.1.2 which defines gflags_LIBRARIES = "
"${gflags_LIBRARIES} which is not an imported CMake target, see: "
"https://github.com/gflags/gflags/issues/110. Attempting to fix by "
"detecting correct gflags target.")
# Ordering here expresses preference for detection, specifically we do not
# want to use the _nothreads variants if the full library is available.
list(APPEND CHECK_GFLAGS_IMPORTED_TARGET_NAMES
gflags-shared gflags-static
gflags_nothreads-shared gflags_nothreads-static)
foreach(CHECK_GFLAGS_TARGET ${CHECK_GFLAGS_IMPORTED_TARGET_NAMES})
if(TARGET ${CHECK_GFLAGS_TARGET})
message(STATUS "Found valid gflags target: ${CHECK_GFLAGS_TARGET}, "
"updating gflags_LIBRARIES.")
set(gflags_LIBRARIES ${CHECK_GFLAGS_TARGET})
break()
endif()
endforeach()
if(NOT TARGET ${gflags_LIBRARIES})
message(STATUS "Failed to fix detected broken gflags install in: "
"${gflags_DIR}, version: ${gflags_VERSION} <= 2.1.2, none of the "
"imported targets for gflags: ${CHECK_GFLAGS_IMPORTED_TARGET_NAMES} "
"are defined. Will continue with a manual search for gflags "
"components. We recommend you build/install a version of gflags > "
"2.1.2 (or master).")
set(FOUND_INSTALLED_GFLAGS_CMAKE_CONFIGURATION FALSE)
endif()
endif()
endif()
if(FOUND_INSTALLED_GFLAGS_CMAKE_CONFIGURATION)
message(STATUS "Detected gflags version: ${gflags_VERSION}")
set(GFLAGS_FOUND ${gflags_FOUND})
set(GFLAGS_INCLUDE_DIR ${gflags_INCLUDE_DIR})
set(GFLAGS_LIBRARY ${gflags_LIBRARIES})
# gflags does not export the namespace in their CMake configuration, so
# use our function to determine what it should be, as it can be either
# gflags or google dependent upon version & configuration.
#
# NOTE: We use the regex method to determine the namespace here, as
# check_cxx_source_compiles() will not use imported targets, which
# is what gflags will be in this case.
gflags_check_gflags_namespace_using_regex()
if(NOT GFLAGS_NAMESPACE)
gflags_report_not_found(
"Failed to determine gflags namespace using regex for gflags "
"version: ${gflags_VERSION} exported here: ${gflags_DIR} using CMake.")
endif()
else()
message(STATUS "Failed to find an installed/exported CMake configuration "
"for gflags, will perform search for installed gflags components.")
endif()
endif()
if(NOT GFLAGS_FOUND)
# Either failed to find an exported gflags CMake configuration, or user
# told us not to use one. Perform a manual search for all gflags components.
# Handle possible presence of lib prefix for libraries on MSVC, see
# also GFLAGS_RESET_FIND_LIBRARY_PREFIX().
if(MSVC)
# Preserve the caller's original values for CMAKE_FIND_LIBRARY_PREFIXES
# s/t we can set it back before returning.
set(CALLERS_CMAKE_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}")
# The empty string in this list is important, it represents the case when
# the libraries have no prefix (shared libraries / DLLs).
set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "" "${CMAKE_FIND_LIBRARY_PREFIXES}")
endif()
# Search user-installed locations first, so that we prefer user installs
# to system installs where both exist.
list(APPEND GFLAGS_CHECK_INCLUDE_DIRS
${GFLAGS_ROOT_DIR_INCLUDE}
/usr/local/include
/usr/local/homebrew/include # Mac OS X
/opt/local/var/macports/software # Mac OS X.
/opt/local/include
/usr/include
/sw/include # Fink
/opt/csw/include # Blastwave
/opt/lib/gflags/include)
list(APPEND GFLAGS_CHECK_PATH_SUFFIXES
gflags/include # Windows (for C:/Program Files prefix).
gflags/Include) # Windows (for C:/Program Files prefix).
list(APPEND GFLAGS_CHECK_LIBRARY_DIRS
${GFLAGS_ROOT_DIR_LIB}
/usr/local/lib
/usr/local/homebrew/lib # Mac OS X.
/opt/local/lib
/usr/lib
/sw/lib # Fink
/opt/csw/lib # Blastwave
/opt/lib/gflags/lib)
list(APPEND GFLAGS_CHECK_LIBRARY_SUFFIXES
gflags/lib # Windows (for C:/Program Files prefix).
gflags/Lib) # Windows (for C:/Program Files prefix).
# Search supplied hint directories first if supplied.
find_path(GFLAGS_INCLUDE_DIR
NAMES gflags/gflags.h
PATHS ${GFLAGS_INCLUDE_DIR_HINTS}
${GFLAGS_CHECK_INCLUDE_DIRS}
PATH_SUFFIXES ${GFLAGS_CHECK_PATH_SUFFIXES})
if(NOT GFLAGS_INCLUDE_DIR OR
NOT EXISTS ${GFLAGS_INCLUDE_DIR})
gflags_report_not_found(
"Could not find gflags include directory, set GFLAGS_INCLUDE_DIR "
"to directory containing gflags/gflags.h")
endif(NOT GFLAGS_INCLUDE_DIR OR
NOT EXISTS ${GFLAGS_INCLUDE_DIR})
find_library(GFLAGS_LIBRARY NAMES gflags
PATHS ${GFLAGS_LIBRARY_DIR_HINTS}
${GFLAGS_CHECK_LIBRARY_DIRS}
PATH_SUFFIXES ${GFLAGS_CHECK_LIBRARY_SUFFIXES})
if(NOT GFLAGS_LIBRARY OR
NOT EXISTS ${GFLAGS_LIBRARY})
gflags_report_not_found(
"Could not find gflags library, set GFLAGS_LIBRARY "
"to full path to libgflags.")
endif(NOT GFLAGS_LIBRARY OR
NOT EXISTS ${GFLAGS_LIBRARY})
# gflags typically requires a threading library (which is OS dependent), note
# that this defines the CMAKE_THREAD_LIBS_INIT variable. If we are able to
# detect threads, we assume that gflags requires it.
find_package(Threads QUIET)
set(GFLAGS_LINK_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
# On Windows (including MinGW), the Shlwapi library is used by gflags if
# available.
if(WIN32)
include(CheckIncludeFileCXX)
check_include_file_cxx("shlwapi.h" HAVE_SHLWAPI)
if(HAVE_SHLWAPI)
list(APPEND GFLAGS_LINK_LIBRARIES shlwapi.lib)
endif()
endif()
# Mark internally as found, then verify. GFLAGS_REPORT_NOT_FOUND() unsets
# if called.
set(GFLAGS_FOUND TRUE)
# Identify what namespace gflags was built with.
if(GFLAGS_INCLUDE_DIR AND NOT GFLAGS_NAMESPACE)
# To handle Windows peculiarities / CMake bugs on MSVC we try two approaches
# to detect the gflags namespace:
#
# 1) Try to use check_cxx_source_compiles() to compile a trivial program
# with the two choices for the gflags namespace.
#
# 2) [In the event 1) fails] Use regex on the gflags headers to try to
# determine the gflags namespace. Whilst this is less robust than 1),
# it does avoid any interaction with msbuild.
gflags_check_gflags_namespace_using_try_compile()
if(NOT GFLAGS_NAMESPACE)
# Failed to determine gflags namespace using check_cxx_source_compiles()
# method, try and obtain it using regex on the gflags headers instead.
message(STATUS "Failed to find gflags namespace using using "
"check_cxx_source_compiles(), trying namespace regex instead, "
"this is expected on Windows.")
gflags_check_gflags_namespace_using_regex()
if(NOT GFLAGS_NAMESPACE)
gflags_report_not_found(
"Failed to determine gflags namespace either by "
"check_cxx_source_compiles(), or namespace regex.")
endif()
endif()
endif()
# Make the GFLAGS_NAMESPACE a cache variable s/t the user can view it, and could
# overwrite it in the CMake GUI.
set(GFLAGS_NAMESPACE "${GFLAGS_NAMESPACE}" CACHE STRING
"gflags namespace (google or gflags)" FORCE)
# gflags does not seem to provide any record of the version in its
# source tree, thus cannot extract version.
# Catch case when caller has set GFLAGS_NAMESPACE in the cache / GUI
# with an invalid value.
if(GFLAGS_NAMESPACE AND
NOT GFLAGS_NAMESPACE STREQUAL "google" AND
NOT GFLAGS_NAMESPACE STREQUAL "gflags")
gflags_report_not_found(
"Caller defined GFLAGS_NAMESPACE:"
" ${GFLAGS_NAMESPACE} is not valid, not google or gflags.")
endif()
# Catch case when caller has set GFLAGS_INCLUDE_DIR in the cache / GUI and
# thus FIND_[PATH/LIBRARY] are not called, but specified locations are
# invalid, otherwise we would report the library as found.
if(GFLAGS_INCLUDE_DIR AND
NOT EXISTS ${GFLAGS_INCLUDE_DIR}/gflags/gflags.h)
gflags_report_not_found(
"Caller defined GFLAGS_INCLUDE_DIR:"
" ${GFLAGS_INCLUDE_DIR} does not contain gflags/gflags.h header.")
endif(GFLAGS_INCLUDE_DIR AND
NOT EXISTS ${GFLAGS_INCLUDE_DIR}/gflags/gflags.h)
# TODO: This regex for gflags library is pretty primitive, we use lowercase
# for comparison to handle Windows using CamelCase library names, could
# this check be better?
string(TOLOWER "${GFLAGS_LIBRARY}" LOWERCASE_GFLAGS_LIBRARY)
if(GFLAGS_LIBRARY AND
NOT "${LOWERCASE_GFLAGS_LIBRARY}" MATCHES ".*gflags[^/]*")
gflags_report_not_found(
"Caller defined GFLAGS_LIBRARY: "
"${GFLAGS_LIBRARY} does not match gflags.")
endif(GFLAGS_LIBRARY AND
NOT "${LOWERCASE_GFLAGS_LIBRARY}" MATCHES ".*gflags[^/]*")
gflags_reset_find_library_prefix()
endif()
# Set standard CMake FindPackage variables if found.
if(GFLAGS_FOUND)
set(GFLAGS_INCLUDE_DIRS ${GFLAGS_INCLUDE_DIR})
set(GFLAGS_LIBRARIES ${GFLAGS_LIBRARY} ${GFLAGS_LINK_LIBRARIES})
endif()
# Handle REQUIRED / QUIET optional arguments.
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(GFLAGS DEFAULT_MSG
GFLAGS_INCLUDE_DIRS GFLAGS_LIBRARIES GFLAGS_NAMESPACE)
# Only mark internal variables as advanced if we found gflags, otherwise
# leave them visible in the standard GUI for the user to set manually.
if(GFLAGS_FOUND)
mark_as_advanced(FORCE GFLAGS_INCLUDE_DIR
GFLAGS_LIBRARY
GFLAGS_NAMESPACE
gflags_DIR) # Autogenerated by find_package(gflags)
endif()

View File

@@ -1,226 +0,0 @@
# Ceres Solver - A fast non-linear least squares minimizer
# Copyright 2015 Google Inc. All rights reserved.
# http://ceres-solver.org/
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Google Inc. nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# Author: alexs.mac@gmail.com (Alex Stewart)
#
# FindGlog.cmake - Find Google glog logging library.
#
# This module defines the following variables:
#
# GLOG_FOUND: TRUE iff glog is found.
# GLOG_INCLUDE_DIRS: Include directories for glog.
# GLOG_LIBRARIES: Libraries required to link glog.
#
# The following variables control the behaviour of this module:
#
# GLOG_INCLUDE_DIR_HINTS: List of additional directories in which to
# search for glog includes, e.g: /timbuktu/include.
# GLOG_LIBRARY_DIR_HINTS: List of additional directories in which to
# search for glog libraries, e.g: /timbuktu/lib.
# GFLOG_ROOT_DIR, The base directory to search for Glog.
# This can also be an environment variable.
#
# The following variables are also defined by this module, but in line with
# CMake recommended FindPackage() module style should NOT be referenced directly
# by callers (use the plural variables detailed above instead). These variables
# do however affect the behaviour of the module via FIND_[PATH/LIBRARY]() which
# are NOT re-called (i.e. search for library is not repeated) if these variables
# are set with valid values _in the CMake cache_. This means that if these
# variables are set directly in the cache, either by the user in the CMake GUI,
# or by the user passing -DVAR=VALUE directives to CMake when called (which
# explicitly defines a cache variable), then they will be used verbatim,
# bypassing the HINTS variables and other hard-coded search locations.
#
# GLOG_INCLUDE_DIR: Include directory for glog, not including the
# include directory of any dependencies.
# GLOG_LIBRARY: glog library, not including the libraries of any
# dependencies.
# If GLOG_ROOT_DIR was defined in the environment, use it.
if(NOT GLOG_ROOT_DIR AND NOT $ENV{GLOG_ROOT_DIR} STREQUAL "")
set(GLOG_ROOT_DIR $ENV{GLOG_ROOT_DIR})
endif()
if(DEFINED GLOG_ROOT_DIR)
set(GLOG_ROOT_DIR_INCLUDE "${GLOG_ROOT_DIR}/include")
set(GLOG_ROOT_DIR_LIB "${GLOG_ROOT_DIR}/lib")
endif()
# Reset CALLERS_CMAKE_FIND_LIBRARY_PREFIXES to its value when
# FindGlog was invoked.
macro(GLOG_RESET_FIND_LIBRARY_PREFIX)
if(MSVC)
set(CMAKE_FIND_LIBRARY_PREFIXES "${CALLERS_CMAKE_FIND_LIBRARY_PREFIXES}")
endif()
endmacro()
# Called if we failed to find glog or any of it's required dependencies,
# unsets all public (designed to be used externally) variables and reports
# error message at priority depending upon [REQUIRED/QUIET/<NONE>] argument.
macro(GLOG_REPORT_NOT_FOUND REASON_MSG)
unset(GLOG_FOUND)
unset(GLOG_INCLUDE_DIRS)
unset(GLOG_LIBRARIES)
# Make results of search visible in the CMake GUI if glog has not
# been found so that user does not have to toggle to advanced view.
mark_as_advanced(CLEAR GLOG_INCLUDE_DIR
GLOG_LIBRARY)
glog_reset_find_library_prefix()
# Note <package>_FIND_[REQUIRED/QUIETLY] variables defined by FindPackage()
# use the camelcase library name, not uppercase.
if(Glog_FIND_QUIETLY)
message(STATUS "Failed to find glog - " ${REASON_MSG} ${ARGN})
elseif(Glog_FIND_REQUIRED)
message(FATAL_ERROR "Failed to find glog - " ${REASON_MSG} ${ARGN})
else()
# Neither QUIETLY nor REQUIRED, use no priority which emits a message
# but continues configuration and allows generation.
message("-- Failed to find glog - " ${REASON_MSG} ${ARGN})
endif()
return()
endmacro()
# Handle possible presence of lib prefix for libraries on MSVC, see
# also GLOG_RESET_FIND_LIBRARY_PREFIX().
if(MSVC)
# Preserve the caller's original values for CMAKE_FIND_LIBRARY_PREFIXES
# s/t we can set it back before returning.
set(CALLERS_CMAKE_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}")
# The empty string in this list is important, it represents the case when
# the libraries have no prefix (shared libraries / DLLs).
set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "" "${CMAKE_FIND_LIBRARY_PREFIXES}")
endif()
# Search user-installed locations first, so that we prefer user installs
# to system installs where both exist.
list(APPEND GLOG_CHECK_INCLUDE_DIRS
${GLOG_ROOT_DIR_INCLUDE}
/usr/local/include
/usr/local/homebrew/include # Mac OS X
/opt/local/var/macports/software # Mac OS X.
/opt/local/include
/usr/include
/sw/include # Fink
/opt/csw/include # Blastwave
/opt/lib/glog/include)
# Windows (for C:/Program Files prefix).
list(APPEND GLOG_CHECK_PATH_SUFFIXES
glog/include
glog/Include
Glog/include
Glog/Include)
list(APPEND GLOG_CHECK_LIBRARY_DIRS
${GLOG_ROOT_DIR_LIB}
/usr/local/lib
/usr/local/homebrew/lib # Mac OS X.
/opt/local/lib
/usr/lib
/sw/lib # Fink
/opt/csw/lib # Blastwave
/opt/lib/gflags/lib)
# Windows (for C:/Program Files prefix).
list(APPEND GLOG_CHECK_LIBRARY_SUFFIXES
glog/lib
glog/Lib
Glog/lib
Glog/Lib)
# Search supplied hint directories first if supplied.
find_path(GLOG_INCLUDE_DIR
NAMES glog/logging.h
PATHS ${GLOG_INCLUDE_DIR_HINTS}
${GLOG_CHECK_INCLUDE_DIRS}
PATH_SUFFIXES ${GLOG_CHECK_PATH_SUFFIXES})
if(NOT GLOG_INCLUDE_DIR OR
NOT EXISTS ${GLOG_INCLUDE_DIR})
glog_report_not_found(
"Could not find glog include directory, set GLOG_INCLUDE_DIR "
"to directory containing glog/logging.h")
endif()
find_library(GLOG_LIBRARY NAMES glog
PATHS ${GLOG_LIBRARY_DIR_HINTS}
${GLOG_CHECK_LIBRARY_DIRS}
PATH_SUFFIXES ${GLOG_CHECK_LIBRARY_SUFFIXES})
if(NOT GLOG_LIBRARY OR
NOT EXISTS ${GLOG_LIBRARY})
glog_report_not_found(
"Could not find glog library, set GLOG_LIBRARY "
"to full path to libglog.")
endif()
# Mark internally as found, then verify. GLOG_REPORT_NOT_FOUND() unsets
# if called.
set(GLOG_FOUND TRUE)
# Glog does not seem to provide any record of the version in its
# source tree, thus cannot extract version.
# Catch case when caller has set GLOG_INCLUDE_DIR in the cache / GUI and
# thus FIND_[PATH/LIBRARY] are not called, but specified locations are
# invalid, otherwise we would report the library as found.
if(GLOG_INCLUDE_DIR AND
NOT EXISTS ${GLOG_INCLUDE_DIR}/glog/logging.h)
glog_report_not_found(
"Caller defined GLOG_INCLUDE_DIR:"
" ${GLOG_INCLUDE_DIR} does not contain glog/logging.h header.")
endif()
# TODO: This regex for glog library is pretty primitive, we use lowercase
# for comparison to handle Windows using CamelCase library names, could
# this check be better?
string(TOLOWER "${GLOG_LIBRARY}" LOWERCASE_GLOG_LIBRARY)
if(GLOG_LIBRARY AND
NOT "${LOWERCASE_GLOG_LIBRARY}" MATCHES ".*glog[^/]*")
glog_report_not_found(
"Caller defined GLOG_LIBRARY: "
"${GLOG_LIBRARY} does not match glog.")
endif()
# Set standard CMake FindPackage variables if found.
if(GLOG_FOUND)
set(GLOG_INCLUDE_DIRS ${GLOG_INCLUDE_DIR})
set(GLOG_LIBRARIES ${GLOG_LIBRARY})
endif()
glog_reset_find_library_prefix()
# Handle REQUIRED / QUIET optional arguments.
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(GLOG DEFAULT_MSG
GLOG_INCLUDE_DIRS GLOG_LIBRARIES)
# Only mark internal variables as advanced if we found glog, otherwise
# leave them visible in the standard GUI for the user to set manually.
if(GLOG_FOUND)
mark_as_advanced(FORCE GLOG_INCLUDE_DIR
GLOG_LIBRARY)
endif()

View File

@@ -0,0 +1,71 @@
# - Find HIDAPI library from http://www.signal11.us/oss/hidapi/
# Find the native HIDAPI includes and library
# This module defines
# HIDAPI_INCLUDE_DIRS, where to find hidapi.h, Set when
# HIDAPI_INCLUDE_DIR is found.
# HIDAPI_LIBRARIES, libraries to link against to use HIDAPI.
# HIDAPI_ROOT_DIR, The base directory to search for HIDAPI.
# This can also be an environment variable.
# HIDAPI_FOUND, If false, do not try to use HIDAPI.
#
# also defined, but not for general use are
# HIDAPI_LIBRARY, where to find the HIDAPI library.
#=============================================================================
# Copyright 2016 Blender Foundation.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# If HIDAPI_ROOT_DIR was defined in the environment, use it.
IF(NOT HIDAPI_ROOT_DIR AND NOT $ENV{HIDAPI_ROOT_DIR} STREQUAL "")
SET(HIDAPI_ROOT_DIR $ENV{HIDAPI_ROOT_DIR})
ENDIF()
SET(_hidapi_SEARCH_DIRS
${HIDAPI_ROOT_DIR}
/usr/local
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
/opt/lib/hidapi
)
FIND_PATH(HIDAPI_INCLUDE_DIR
NAMES
hidapi.h
HINTS
${_hidapi_SEARCH_DIRS}
PATH_SUFFIXES
include/hidapi
)
FIND_LIBRARY(HIDAPI_LIBRARY
NAMES
hidapi hidapi-libusb
HINTS
${_hidapi_SEARCH_DIRS}
PATH_SUFFIXES
lib64 lib
)
# Handle the QUIETLY and REQUIRED arguments and set HIDAPI_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(HIDAPI DEFAULT_MSG
HIDAPI_LIBRARY HIDAPI_INCLUDE_DIR)
IF(HIDAPI_FOUND)
SET(HIDAPI_LIBRARIES ${HIDAPI_LIBRARY})
SET(HIDAPI_INCLUDE_DIRS ${HIDAPI_INCLUDE_DIR})
ENDIF(HIDAPI_FOUND)
MARK_AS_ADVANCED(
HIDAPI_INCLUDE_DIR
HIDAPI_LIBRARY
)

View File

@@ -20,8 +20,8 @@ macro(BLENDER_SRC_GTEST_EX NAME SRC EXTRA_LIBS DO_ADD_TEST)
set(TEST_INC
${_current_include_directories}
${CMAKE_SOURCE_DIR}/tests/gtests
${GLOG_INCLUDE_DIRS}
${GFLAGS_INCLUDE_DIRS}
${CMAKE_SOURCE_DIR}/extern/glog/src
${CMAKE_SOURCE_DIR}/extern/gflags/src
${CMAKE_SOURCE_DIR}/extern/gtest/include
${CMAKE_SOURCE_DIR}/extern/gmock/include
)
@@ -37,8 +37,8 @@ macro(BLENDER_SRC_GTEST_EX NAME SRC EXTRA_LIBS DO_ADD_TEST)
extern_gmock
# needed for glog
${PTHREADS_LIBRARIES}
${GLOG_LIBRARIES}
${GFLAGS_LIBRARIES})
extern_glog
extern_gflags)
if(WITH_OPENMP_STATIC)
target_link_libraries(${NAME}_test ${OpenMP_LIBRARIES})
endif()

View File

@@ -84,7 +84,7 @@ def create_nb_project_main():
make_exe = cmake_cache_var("CMAKE_MAKE_PROGRAM")
make_exe_basename = os.path.basename(make_exe)
# --------------- NB specific
# --------------- NB spesific
defines = [("%s=%s" % cdef) if cdef[1] else cdef[0] for cdef in defines]
defines += [cdef.replace("#define", "").strip() for cdef in cmake_compiler_defines()]

View File

@@ -73,9 +73,6 @@ elseif(WIN32)
endif()
elseif(APPLE)
set(WITH_JACK ON CACHE BOOL "" FORCE)
set(WITH_CODEC_QUICKTIME OFF CACHE BOOL "" FORCE)
set(WITH_CODEC_QUICKTIME ON CACHE BOOL "" FORCE)
set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
# include("${CMAKE_CURRENT_SOURCE_DIR}/../platform/platform_apple_xcode.cmake")
# apple_check_quicktime()
endif()

View File

@@ -74,9 +74,6 @@ elseif(WIN32)
endif()
elseif(APPLE)
set(WITH_JACK ON CACHE BOOL "" FORCE)
set(WITH_CODEC_QUICKTIME OFF CACHE BOOL "" FORCE)
set(WITH_CODEC_QUICKTIME ON CACHE BOOL "" FORCE)
set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
# include("${CMAKE_CURRENT_SOURCE_DIR}/../platform/platform_apple_xcode.cmake")
# apple_check_quicktime()
endif()

View File

@@ -491,11 +491,9 @@ function(setup_liblinks
target_link_libraries(${target} ${NDOF_LIBRARIES})
endif()
endif()
if(WITH_SYSTEM_GLOG)
target_link_libraries(${target} ${GLOG_LIBRARIES})
endif()
if(WITH_SYSTEM_GFLAGS)
target_link_libraries(${target} ${GFLAGS_LIBRARIES})
if(WITH_OPENHMD)
target_link_libraries(${target} ${OPENHMD_LIBRARIES} ${HIDAPI_LIBRARY})
endif()
# We put CLEW and CUEW here because OPENSUBDIV_LIBRARIES dpeends on them..
@@ -507,6 +505,9 @@ function(setup_liblinks
target_link_libraries(${target} ${CUDA_CUDA_LIBRARY})
endif()
endif()
if(WITH_OPENHMD AND WITH_OPENHMD_DYNLOAD)
target_link_libraries(${target} "extern_udew")
endif()
target_link_libraries(
${target}
@@ -664,19 +665,13 @@ function(SETUP_BLENDER_SORTED_LIBS)
extern_rangetree
extern_wcwidth
bf_intern_libmv
extern_glog
extern_gflags
extern_sdlew
bf_intern_glew_mx
)
if(NOT WITH_SYSTEM_GLOG)
list(APPEND BLENDER_SORTED_LIBS extern_glog)
endif()
if(NOT WITH_SYSTEM_GFLAGS)
list(APPEND BLENDER_SORTED_LIBS extern_gflags)
endif()
if(WITH_COMPOSITOR)
# added for opencl compositor
list_insert_before(BLENDER_SORTED_LIBS "bf_blenkernel" "bf_compositor")
@@ -719,6 +714,10 @@ function(SETUP_BLENDER_SORTED_LIBS)
list(APPEND BLENDER_SORTED_LIBS bf_quicktime)
endif()
if(WITH_OPENHMD)
list(APPEND BLENDER_SORTED_LIBS extern_openhmd)
endif()
if(WITH_MOD_BOOLEAN)
list(APPEND BLENDER_SORTED_LIBS extern_carve)
endif()

View File

@@ -23,10 +23,6 @@
# Libraries configuration for Apple.
macro(find_package_wrapper)
# do nothing, just satisfy the macro
endmacro()
if(NOT DEFINED LIBDIR)
if(WITH_CXX11)
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin)
@@ -56,7 +52,6 @@ if(WITH_ALEMBIC)
set(ALEMBIC_INCLUDE_DIRS ${ALEMBIC_INCLUDE_DIR})
set(ALEMBIC_LIBPATH ${ALEMBIC}/lib)
set(ALEMBIC_LIBRARIES Alembic)
set(ALEMBIC_FOUND ON)
endif()
if(WITH_OPENSUBDIV OR WITH_CYCLES_OPENSUBDIV)

View File

@@ -1,135 +0,0 @@
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# The Original Code is Copyright (C) 2016, Blender Foundation
# All rights reserved.
#
# Contributor(s): Jacques Beaurain.
#
# ***** END GPL LICENSE BLOCK *****
# Xcode and system configuration for Apple.
# require newer cmake on osx because of version handling,
# older cmake cannot handle 2 digit subversion!
cmake_minimum_required(VERSION 3.0.0)
if(NOT CMAKE_OSX_ARCHITECTURES)
set(CMAKE_OSX_ARCHITECTURES x86_64 CACHE STRING
"Choose the architecture you want to build Blender for: i386, x86_64 or ppc"
FORCE)
endif()
if(NOT DEFINED OSX_SYSTEM)
execute_process(
COMMAND xcodebuild -version -sdk macosx SDKVersion
OUTPUT_VARIABLE OSX_SYSTEM
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
# workaround for incorrect cmake xcode lookup for developer previews - XCODE_VERSION does not
# take xcode-select path into account but would always look into /Applications/Xcode.app
# while dev versions are named Xcode<version>-DP<preview_number>
execute_process(
COMMAND xcode-select --print-path
OUTPUT_VARIABLE XCODE_CHECK OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REPLACE "/Contents/Developer" "" XCODE_BUNDLE ${XCODE_CHECK}) # truncate to bundlepath in any case
if(${CMAKE_GENERATOR} MATCHES "Xcode")
# earlier xcode has no bundled developer dir, no sense in getting xcode path from
if(${XCODE_VERSION} VERSION_GREATER 4.2)
# reduce to XCode name without dp extension
string(SUBSTRING "${XCODE_CHECK}" 14 6 DP_NAME)
if(${DP_NAME} MATCHES Xcode5)
set(XCODE_VERSION 5)
endif()
endif()
##### cmake incompatibility with xcode 4.3 and higher #####
if(${XCODE_VERSION} MATCHES '') # cmake fails due looking for xcode in the wrong path, thus will be empty var
message(FATAL_ERROR "Xcode 4.3 and higher must be used with cmake 2.8-8 or higher")
endif()
### end cmake incompatibility with xcode 4.3 and higher ###
if(${XCODE_VERSION} VERSION_EQUAL 4 OR ${XCODE_VERSION} VERSION_GREATER 4 AND ${XCODE_VERSION} VERSION_LESS 4.3)
# Xcode 4 defaults to the Apple LLVM Compiler.
# Override the default compiler selection because Blender only compiles with gcc up to xcode 4.2
set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvmgcc42")
message(STATUS "Setting compiler to: " ${CMAKE_XCODE_ATTRIBUTE_GCC_VERSION})
endif()
else() # unix makefile generator does not fill XCODE_VERSION var, so we get it with a command
execute_process(COMMAND xcodebuild -version OUTPUT_VARIABLE XCODE_VERS_BUILD_NR)
string(SUBSTRING "${XCODE_VERS_BUILD_NR}" 6 3 XCODE_VERSION) # truncate away build-nr
unset(XCODE_VERS_BUILD_NR)
endif()
message(STATUS "Detected OS X ${OSX_SYSTEM} and Xcode ${XCODE_VERSION} at ${XCODE_BUNDLE}")
if(${XCODE_VERSION} VERSION_LESS 4.3)
# use guaranteed existing sdk
set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk CACHE PATH "" FORCE)
else()
# note: xcode-select path could be ambigous,
# cause /Applications/Xcode.app/Contents/Developer or /Applications/Xcode.app would be allowed
# so i use a selfcomposed bundlepath here
set(OSX_SYSROOT_PREFIX ${XCODE_BUNDLE}/Contents/Developer/Platforms/MacOSX.platform)
message(STATUS "OSX_SYSROOT_PREFIX: " ${OSX_SYSROOT_PREFIX})
set(OSX_DEVELOPER_PREFIX /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk) # use guaranteed existing sdk
set(CMAKE_OSX_SYSROOT ${OSX_SYSROOT_PREFIX}/${OSX_DEVELOPER_PREFIX} CACHE PATH "" FORCE)
if(${CMAKE_GENERATOR} MATCHES "Xcode")
# to silence sdk not found warning, just overrides CMAKE_OSX_SYSROOT
set(CMAKE_XCODE_ATTRIBUTE_SDKROOT macosx${OSX_SYSTEM})
endif()
endif()
if(OSX_SYSTEM MATCHES 10.9)
# make sure syslibs and headers are looked up in sdk ( expecially for 10.9 openGL atm. )
set(CMAKE_FIND_ROOT_PATH ${CMAKE_OSX_SYSROOT})
endif()
if(WITH_CXX11)
# 10.9 is our min. target, if you use higher sdk, weak linking happens
if(CMAKE_OSX_DEPLOYMENT_TARGET)
if(${CMAKE_OSX_DEPLOYMENT_TARGET} VERSION_LESS 10.9)
message(STATUS "Setting deployment target to 10.9, lower versions are incompatible with WITH_CXX11")
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "" FORCE)
endif()
else()
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "" FORCE)
endif()
else()
if(NOT CMAKE_OSX_DEPLOYMENT_TARGET)
# 10.6 is our min. target, if you use higher sdk, weak linking happens
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.6" CACHE STRING "" FORCE)
endif()
endif()
if(NOT ${CMAKE_GENERATOR} MATCHES "Xcode")
# force CMAKE_OSX_DEPLOYMENT_TARGET for makefiles, will not work else ( cmake bug ? )
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
add_definitions("-DMACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}")
endif()
macro(apple_check_quicktime)
# QuickTime framework is no longer available in SDK 10.12+
if(WITH_CODEC_QUICKTIME AND ${OSX_SYSTEM} VERSION_GREATER 10.11)
set(WITH_CODEC_QUICKTIME OFF CACHE BOOL "" FORCE)
message(STATUS "QuickTime not supported by SDK ${OSX_SYSTEM}, disabling WITH_CODEC_QUICKTIME")
endif()
endmacro()

View File

@@ -37,12 +37,6 @@ macro(windows_find_package package_name
endif(WITH_WINDOWS_FIND_MODULES)
endmacro()
macro(find_package_wrapper)
if(WITH_WINDOWS_FIND_MODULES)
find_package(${ARGV})
endif()
endmacro()
add_definitions(-DWIN32)
# Minimum MSVC Version
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
@@ -72,7 +66,7 @@ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO")
list(APPEND PLATFORM_LINKLIBS
ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32
advapi32 shfolder shell32 ole32 oleaut32 uuid psapi Dbghelp
advapi32 shfolder shell32 ole32 oleaut32 uuid psapi Dbghelp setupapi
)
if(WITH_INPUT_IME)
@@ -438,7 +432,6 @@ if(WITH_ALEMBIC)
set(ALEMBIC_INCLUDE_DIRS ${ALEMBIC_INCLUDE_DIR})
set(ALEMBIC_LIBPATH ${ALEMBIC}/lib)
set(ALEMBIC_LIBRARIES optimized alembic debug alembic_d)
set(ALEMBIC_FOUND 1)
endif()
if(WITH_MOD_CLOTH_ELTOPO)

View File

@@ -1,81 +0,0 @@
"""
Extending the Button Context Menu
+++++++++++++++++++++++++++++++++
This example enables you to insert your own menu entry into the common
right click menu that you get while hovering over a value field,
color, string, etc.
To make the example work, you have to first select an object
then right click on an user interface element (maybe a color in the
material properties) and choose *Execute Custom Action*.
Executing the operator will then print all values.
"""
import bpy
from bpy.types import Menu
def dump(obj, text):
for attr in dir(obj):
print("%r.%s = %s" % (obj, attr, getattr(obj, attr)))
class WM_OT_button_context_test(bpy.types.Operator):
"""Right click entry test"""
bl_idname = "wm.button_context_test"
bl_label = "Run Context Test"
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
value = getattr(context, "button_pointer", None)
if value is not None:
dump(value, "button_pointer")
value = getattr(context, "button_prop", None)
if value is not None:
dump(value, "button_prop")
value = getattr(context, "button_operator", None)
if value is not None:
dump(value, "button_operator")
return {'FINISHED'}
# This class has to be exactly named like that to insert an entry in the right click menu
class WM_MT_button_context(Menu):
bl_label = "Unused"
def draw(self, context):
pass
def menu_func(self, context):
layout = self.layout
layout.separator()
layout.operator(WM_OT_button_context_test.bl_idname)
classes = (
WM_OT_button_context_test,
WM_MT_button_context,
)
def register():
for cls in classes:
bpy.utils.register_class(cls)
bpy.types.WM_MT_button_context.append(menu_func)
def unregister():
for cls in classes:
bpy.utils.unregister_class(cls)
bpy.types.WM_MT_button_context.remove(menu_func)
if __name__ == "__main__":
register()

12
extern/CMakeLists.txt vendored
View File

@@ -86,6 +86,10 @@ if(WITH_CYCLES OR WITH_COMPOSITOR OR WITH_OPENSUBDIV)
endif()
endif()
if(WITH_OPENHMD AND WITH_OPENHMD_DYNLOAD)
add_subdirectory(udew)
endif()
if(WITH_MOD_BOOLEAN)
add_subdirectory(carve)
endif()
@@ -99,9 +103,7 @@ if(WITH_LIBMV)
endif()
if(WITH_LIBMV OR WITH_GTESTS OR (WITH_CYCLES AND WITH_CYCLES_LOGGING))
if (NOT WITH_SYSTEM_GFLAGS)
add_subdirectory(gflags)
endif()
add_subdirectory(gflags)
add_subdirectory(glog)
endif()
@@ -113,3 +115,7 @@ endif()
if(WITH_SDL AND WITH_SDL_DYNLOAD)
add_subdirectory(sdlew)
endif()
if(WITH_OPENHMD)
add_subdirectory(openhmd)
endif()

View File

@@ -36,7 +36,7 @@
/* curve_fit_cubic.c */
/**
* Takes a flat array of points and evaluates that to calculate a bezier spline.
* Takes a flat array of points and evalues that to calculate a bezier spline.
*
* \param points, points_len: The array of points to calculate a cubics from.
* \param dims: The number of dimensions for for each element in \a points.
@@ -82,7 +82,7 @@ int curve_fit_cubic_to_points_fl(
unsigned int **r_corners_index_array, unsigned int *r_corners_index_len);
/**
* Takes a flat array of points and evaluates that to calculate handle lengths.
* Takes a flat array of points and evalues that to calculate handle lengths.
*
* \param points, points_len: The array of points to calculate a cubics from.
* \param dims: The number of dimensions for for each element in \a points.
@@ -107,8 +107,7 @@ int curve_fit_cubic_to_points_single_db(
double r_handle_l[],
double r_handle_r[],
double *r_error_sq,
unsigned int *r_error_index);
double *r_error_sq);
int curve_fit_cubic_to_points_single_fl(
const float *points,
@@ -121,8 +120,7 @@ int curve_fit_cubic_to_points_single_fl(
float r_handle_l[],
float r_handle_r[],
float *r_error_sq,
unsigned int *r_error_index);
float *r_error_sq);
enum {
CURVE_FIT_CALC_HIGH_QUALIY = (1 << 0),

View File

@@ -554,8 +554,8 @@ static void cubic_from_points_fallback(
r_cubic->orig_span = (points_offset_len - 1);
#endif
/* p1 = p0 - (tan_l * alpha);
* p2 = p3 + (tan_r * alpha);
/* p1 = p0 - (tan_l * alpha_l);
* p2 = p3 + (tan_r * alpha_r);
*/
msub_vn_vnvn_fl(p1, p0, tan_l, alpha, dims);
madd_vn_vnvn_fl(p2, p3, tan_r, alpha, dims);
@@ -1436,11 +1436,12 @@ int curve_fit_cubic_to_points_single_db(
double r_handle_l[],
double r_handle_r[],
double *r_error_max_sq,
uint *r_error_index)
double *r_error_max_sq)
{
Cubic *cubic = alloca(cubic_alloc_size(dims));
uint split_index;
/* in this instance theres no advantage in using length cache,
* since we're not recursively calculating values. */
#ifdef USE_LENGTH_CACHE
@@ -1461,7 +1462,7 @@ int curve_fit_cubic_to_points_single_db(
#endif
tan_l, tan_r, error_threshold, dims,
cubic, r_error_max_sq, r_error_index);
cubic, r_error_max_sq, &split_index);
#ifdef USE_LENGTH_CACHE
if (points_length_cache_alloc) {
@@ -1486,8 +1487,7 @@ int curve_fit_cubic_to_points_single_fl(
float r_handle_l[],
float r_handle_r[],
float *r_error_sq,
uint *r_error_index)
float *r_error_sq)
{
const uint points_flat_len = points_len * dims;
double *points_db = malloc(sizeof(double) * points_flat_len);
@@ -1521,8 +1521,7 @@ int curve_fit_cubic_to_points_single_fl(
(double)error_threshold,
tan_l_db, tan_r_db,
r_handle_l_db, r_handle_r_db,
&r_error_sq_db,
r_error_index);
&r_error_sq_db);
free(points_db);

View File

@@ -207,7 +207,7 @@ struct KnotCornerState {
/* Utility functions */
#if defined(USE_KNOT_REFIT) && !defined(USE_KNOT_REFIT_REMOVE)
#ifdef USE_KNOT_REFIT
/**
* Find the most distant point between the 2 knots.
*/
@@ -269,7 +269,7 @@ static uint knot_find_split_point(
return split_point;
}
#endif /* USE_KNOT_REFIT && !USE_KNOT_REFIT_REMOVE */
#endif /* USE_KNOT_REFIT */
#ifdef USE_CORNER_DETECT
@@ -322,7 +322,7 @@ static double knot_remove_error_value(
const double *points_offset_length_cache,
const uint dims,
/* Avoid having to re-calculate again */
double r_handle_factors[2], uint *r_error_index)
double r_handle_factors[2])
{
double error_sq = FLT_MAX;
@@ -338,7 +338,7 @@ static double knot_remove_error_value(
points_offset, points_offset_len, points_offset_length_cache, dims, 0.0,
tan_l, tan_r,
handle_factor_l, handle_factor_r,
&error_sq, r_error_index);
&error_sq);
assert(error_sq != FLT_MAX);
@@ -363,7 +363,6 @@ static double knot_calc_curve_error_value(
((knot_r->index + pd->points_len) - knot_l->index)) + 1;
if (points_offset_len != 2) {
uint error_index_dummy;
return knot_remove_error_value(
tan_l, tan_r,
&pd->points[knot_l->index * dims], points_offset_len,
@@ -373,7 +372,7 @@ static double knot_calc_curve_error_value(
NULL,
#endif
dims,
r_handle_factors, &error_index_dummy);
r_handle_factors);
}
else {
/* No points between, use 1/3 handle length with no error as a fallback. */
@@ -389,56 +388,6 @@ static double knot_calc_curve_error_value(
}
}
#ifdef USE_KNOT_REFIT_REMOVE
static double knot_calc_curve_error_value_and_index(
const struct PointData *pd,
const struct Knot *knot_l, const struct Knot *knot_r,
const double *tan_l, const double *tan_r,
const uint dims,
double r_handle_factors[2],
uint *r_error_index)
{
const uint points_offset_len = ((knot_l->index < knot_r->index) ?
(knot_r->index - knot_l->index) :
((knot_r->index + pd->points_len) - knot_l->index)) + 1;
if (points_offset_len != 2) {
const double error_sq = knot_remove_error_value(
tan_l, tan_r,
&pd->points[knot_l->index * dims], points_offset_len,
#ifdef USE_LENGTH_CACHE
&pd->points_length_cache[knot_l->index],
#else
NULL,
#endif
dims,
r_handle_factors, r_error_index);
/* Adjust the offset index to the global index & wrap if needed. */
*r_error_index += knot_l->index;
if (*r_error_index >= pd->points_len) {
*r_error_index -= pd->points_len;
}
return error_sq;
}
else {
/* No points between, use 1/3 handle length with no error as a fallback. */
assert(points_offset_len == 2);
#ifdef USE_LENGTH_CACHE
r_handle_factors[0] = r_handle_factors[1] = pd->points_length_cache[knot_l->index] / 3.0;
#else
r_handle_factors[0] = r_handle_factors[1] = len_vnvn(
&pd->points[(knot_l->index + 0) * dims],
&pd->points[(knot_l->index + 1) * dims], dims) / 3.0;
#endif
*r_error_index = 0;
return 0.0;
}
}
#endif /* USE_KNOT_REFIT_REMOVE */
struct KnotRemove_Params {
Heap *heap;
const struct PointData *pd;
@@ -607,18 +556,15 @@ static void knot_refit_error_recalculate(
assert(k->can_remove);
#ifdef USE_KNOT_REFIT_REMOVE
(void)knots_len;
uint refit_index = SPLIT_POINT_INVALID;
{
double handles[2];
/* First check if we can remove, this allows to refit and remove as we go. */
const double cost_sq = knot_calc_curve_error_value_and_index(
const double cost_sq = knot_calc_curve_error_value(
p->pd, k->prev, k->next,
k->prev->tan[1], k->next->tan[0],
dims,
handles, &refit_index);
handles);
if (cost_sq < error_sq_max) {
struct KnotRefitState *r;
@@ -652,14 +598,13 @@ static void knot_refit_error_recalculate(
}
#else
(void)error_sq_max;
#endif /* USE_KNOT_REFIT_REMOVE */
const uint refit_index = knot_find_split_point(
p->pd, k->prev, k->next,
knots_len,
dims);
#endif /* USE_KNOT_REFIT_REMOVE */
if ((refit_index == SPLIT_POINT_INVALID) ||
(refit_index == k->index))
{

111
extern/openhmd/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,111 @@
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENSE BLOCK *****
set(INC
.
src
include
)
set(INC_SYS
)
set(SRC
src/openhmd.c
src/platform-win32.c
src/drv_dummy/dummy.c
src/omath.c
src/platform-posix.c
src/fusion.c
src/queue.c
src/shaders.c
)
# TODO: Either remove this or move to main CMakeLists.txt
OPTION(OPENHMD_DRIVER_OCULUS_RIFT "Oculus Rift DK1, DK2 and CV1" ON)
OPTION(OPENHMD_DRIVER_DEEPOON "Deepoon E2" ON)
OPTION(OPENHMD_DRIVER_PSVR "Sony PSVR" ON)
OPTION(OPENHMD_DRIVER_HTC_VIVE "HTC Vive" ON)
OPTION(OPENHMD_DRIVER_EXTERNAL "External sensor driver" OFF)
OPTION(OPENHMD_DRIVER_ANDROID "General Android driver" OFF)
if(MSVC)
add_definitions(-DOHMD_STATIC)
endif(MSVC)
if(OPENHMD_DRIVER_OCULUS_RIFT)
list(APPEND SRC
src/drv_oculus_rift/rift.c
src/drv_oculus_rift/packet.c
)
add_definitions(-DDRIVER_OCULUS_RIFT)
find_package(HIDAPI REQUIRED)
list(APPEND INC_SYS ${HIDAPI_INCLUDE_DIRS})
endif()
if(OPENHMD_DRIVER_DEEPOON)
list(APPEND SRC
src/drv_deepoon/deepoon.c
src/drv_deepoon/packet.c
)
add_definitions(-DDRIVER_DEEPOON)
find_package(HIDAPI REQUIRED)
list(APPEND INC_SYS ${HIDAPI_INCLUDE_DIRS})
endif()
if(OPENHMD_DRIVER_PSVR)
list(APPEND SRC
src/drv_psvr/psvr.c
src/drv_psvr/packet.c
)
add_definitions(-DDRIVER_PSVR)
find_package(HIDAPI REQUIRED)
list(APPEND INC_SYS ${HIDAPI_INCLUDE_DIRS})
endif()
if(OPENHMD_DRIVER_HTC_VIVE)
list(APPEND SRC
src/drv_htc_vive/vive.c
src/drv_htc_vive/packet.c
)
add_definitions(-DDRIVER_HTC_VIVE)
find_package(HIDAPI REQUIRED)
list(APPEND INC_SYS ${HIDAPI_INCLUDE_DIRS})
endif()
if(OPENHMD_DRIVER_EXTERNAL)
list(APPEND SRC
src/drv_external/external.c
)
add_definitions(-DDRIVER_EXTERNAL)
endif()
if(OPENHMD_DRIVER_ANDROID)
list(APPEND SRC
src/drv_android/android.c
)
add_definitions(-DDRIVER_ANDROID)
endif()
blender_add_lib(extern_openhmd "${SRC}" "${INC}" "${INC_SYS}")

23
extern/openhmd/LICENSE vendored Normal file
View File

@@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

9
extern/openhmd/README.md vendored Normal file
View File

@@ -0,0 +1,9 @@
# OpenHMD
This project aims to provide a Free and Open Source API and drivers for immersive technology, such as head mounted displays with built in head tracking.
# License
OpenHMD is released under the permissive Boost Software License (see LICENSE for more information), to make sure it can be linked and distributed with both free and non-free software. While it doesn't require contribution from the users, it is still very appreciated.
# Implemented and maintained by TheOnlyJoey (Joey Ferwerda), contact info@thorwork.org if anything goes wrong

390
extern/openhmd/include/openhmd.h vendored Normal file
View File

@@ -0,0 +1,390 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/**
* \file openhmd.h
* Main header for OpenHMD public API.
**/
#ifndef OPENHMD_H
#define OPENHMD_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _WIN32
#ifdef DLL_EXPORT
#define OHMD_APIENTRY __cdecl
#define OHMD_APIENTRYDLL __declspec( dllexport )
#else
#ifdef OHMD_STATIC
#define OHMD_APIENTRY __cdecl
#define OHMD_APIENTRYDLL
#else
#define OHMD_APIENTRY __cdecl
#define OHMD_APIENTRYDLL __declspec( dllimport )
#endif
#endif
#else
#define OHMD_APIENTRY
#define OHMD_APIENTRYDLL
#endif
/** Maximum length of a string, including termination, in OpenHMD. */
#define OHMD_STR_SIZE 256
/** Return status codes, used for all functions that can return an error. */
typedef enum {
OHMD_S_OK = 0,
OHMD_S_UNKNOWN_ERROR = -1,
OHMD_S_INVALID_PARAMETER = -2,
OHMD_S_UNSUPPORTED = -3,
OHMD_S_INVALID_OPERATION = -4,
/** OHMD_S_USER_RESERVED and below can be used for user purposes, such as errors within ohmd wrappers, etc. */
OHMD_S_USER_RESERVED = -16384,
} ohmd_status;
/** A collection of string value information types, used for getting information with ohmd_list_gets(). */
typedef enum {
OHMD_VENDOR = 0,
OHMD_PRODUCT = 1,
OHMD_PATH = 2,
} ohmd_string_value;
/** A collection of string descriptions, used for getting strings with ohmd_gets(). */
typedef enum {
OHMD_GLSL_DISTORTION_VERT_SRC = 0,
OHMD_GLSL_DISTORTION_FRAG_SRC = 1,
} ohmd_string_description;
/** A collection of float value information types, used for getting and setting information with
ohmd_device_getf() and ohmd_device_setf(). */
typedef enum {
/** float[4] (get): Absolute rotation of the device, in space, as a quaternion (x, y, z, w). */
OHMD_ROTATION_QUAT = 1,
/** float[16] (get): A "ready to use" OpenGL style 4x4 matrix with a modelview matrix for the
left eye of the HMD. */
OHMD_LEFT_EYE_GL_MODELVIEW_MATRIX = 2,
/** float[16] (get): A "ready to use" OpenGL style 4x4 matrix with a modelview matrix for the
right eye of the HMD. */
OHMD_RIGHT_EYE_GL_MODELVIEW_MATRIX = 3,
/** float[16] (get): A "ready to use" OpenGL style 4x4 matrix with a projection matrix for the
left eye of the HMD. */
OHMD_LEFT_EYE_GL_PROJECTION_MATRIX = 4,
/** float[16] (get): A "ready to use" OpenGL style 4x4 matrix with a projection matrix for the
right eye of the HMD. */
OHMD_RIGHT_EYE_GL_PROJECTION_MATRIX = 5,
/** float[3] (get): A 3-D vector representing the absolute position of the device, in space. */
OHMD_POSITION_VECTOR = 6,
/** float[1] (get): Physical width of the device screen in metres. */
OHMD_SCREEN_HORIZONTAL_SIZE = 7,
/** float[1] (get): Physical height of the device screen in metres. */
OHMD_SCREEN_VERTICAL_SIZE = 8,
/** float[1] (get): Physical separation of the device lenses in metres. */
OHMD_LENS_HORIZONTAL_SEPARATION = 9,
/** float[1] (get): Physical vertical position of the lenses in metres. */
OHMD_LENS_VERTICAL_POSITION = 10,
/** float[1] (get): Physical field of view for the left eye in degrees. */
OHMD_LEFT_EYE_FOV = 11,
/** float[1] (get): Physical display aspect ratio for the left eye screen. */
OHMD_LEFT_EYE_ASPECT_RATIO = 12,
/** float[1] (get): Physical field of view for the left right in degrees. */
OHMD_RIGHT_EYE_FOV = 13,
/** float[1] (get): Physical display aspect ratio for the right eye screen. */
OHMD_RIGHT_EYE_ASPECT_RATIO = 14,
/** float[1] (get, set): Physical interpupillary distance of the user in metres. */
OHMD_EYE_IPD = 15,
/** float[1] (get, set): Z-far value for the projection matrix calculations (i.e. drawing distance). */
OHMD_PROJECTION_ZFAR = 16,
/** float[1] (get, set): Z-near value for the projection matrix calculations (i.e. close clipping distance). */
OHMD_PROJECTION_ZNEAR = 17,
/** float[6] (get): Device specific distortion value. */
OHMD_DISTORTION_K = 18,
/**
* float[10] (set): Perform sensor fusion on values from external sensors.
*
* Values are: dt (time since last update in seconds) X, Y, Z gyro, X, Y, Z accelerometer and X, Y, Z magnetometer.
**/
OHMD_EXTERNAL_SENSOR_FUSION = 19,
/** float[4] (get): Universal shader distortion coefficients (PanoTools model <a,b,c,d>. */
OHMD_UNIVERSAL_DISTORTION_K = 20,
/** float[3] (get): Universal shader aberration coefficients (post warp scaling <r,g,b>. */
OHMD_UNIVERSAL_ABERRATION_K = 21,
} ohmd_float_value;
/** A collection of int value information types used for getting information with ohmd_device_geti(). */
typedef enum {
/** int[1] (get): Physical horizontal resolution of the device screen. */
OHMD_SCREEN_HORIZONTAL_RESOLUTION = 0,
/** int[1] (get): Physical vertical resolution of the device screen. */
OHMD_SCREEN_VERTICAL_RESOLUTION = 1,
/** int[1] (get): Get number of events waiting in digital input event queue. */
OHMD_BUTTON_EVENT_COUNT = 2,
/** int[1] (get): Get if the there was an overflow in the event queue causing events to be dropped. */
OHMD_BUTTON_EVENT_OVERFLOW = 3,
/** int[1] (get): Get the number of physical digital input buttons on the device. */
OHMD_BUTTON_COUNT = 4,
/** int[2] (get): Performs an event pop action. Format: [button_index, button_state], where button_state is either OHMD_BUTTON_DOWN or OHMD_BUTTON_UP */
OHMD_BUTTON_POP_EVENT = 5,
} ohmd_int_value;
/** A collection of data information types used for setting information with ohmd_set_data(). */
typedef enum {
/** void* (set): Set void* data for use in the internal drivers. */
OHMD_DRIVER_DATA = 0,
/**
* ohmd_device_properties* (set):
* Set the device properties based on the ohmd_device_properties struct for use in the internal drivers.
*
* This can be used to fill in information about the device internally, such as Android, or for setting profiles.
**/
OHMD_DRIVER_PROPERTIES = 1,
} ohmd_data_value;
typedef enum {
/** int[1] (set, default: 1): Set this to 0 to prevent OpenHMD from creating background threads to do automatic device ticking.
Call ohmd_update(); must be called frequently, at least 10 times per second, if the background threads are disabled. */
OHMD_IDS_AUTOMATIC_UPDATE = 0,
} ohmd_int_settings;
/** Button states for digital input events. */
typedef enum {
/** Button was pressed. */
OHMD_BUTTON_DOWN = 0,
/** Button was released. */
OHMD_BUTTON_UP = 1
} ohmd_button_state;
/** An opaque pointer to a context structure. */
typedef struct ohmd_context ohmd_context;
/** An opaque pointer to a structure representing a device, such as an HMD. */
typedef struct ohmd_device ohmd_device;
/** An opaque pointer to a structure representing arguments for a device. */
typedef struct ohmd_device_settings ohmd_device_settings;
/**
* Create an OpenHMD context.
*
* @return a pointer to an allocated ohmd_context on success or NULL if it fails.
**/
OHMD_APIENTRYDLL ohmd_context* OHMD_APIENTRY ohmd_ctx_create(void);
/**
* Destroy an OpenHMD context.
*
* ohmd_ctx_destroy de-initializes and de-allocates an OpenHMD context allocated with ohmd_ctx_create.
* All devices associated with the context are automatically closed.
*
* @param ctx The context to destroy.
**/
OHMD_APIENTRYDLL void OHMD_APIENTRY ohmd_ctx_destroy(ohmd_context* ctx);
/**
* Get the last error as a human readable string.
*
* If a function taking a context as an argument (ohmd_context "methods") returns non-successfully,
* a human readable error message describing what went wrong can be retrieved with this function.
*
* @param ctx The context to retrieve the error message from.
* @return a pointer to the error message.
**/
OHMD_APIENTRYDLL const char* OHMD_APIENTRY ohmd_ctx_get_error(ohmd_context* ctx);
/**
* Update a context.
*
* Update the values for the devices handled by a context.
*
* If background threads are disabled, this performs tasks like pumping events from the device. The exact details
* are up to the driver but try to call it quite frequently.
* Once per frame in a "game loop" should be sufficient.
* If OpenHMD is handled in a background thread in your program, calling ohmd_ctx_update and then sleeping for 10-20 ms
* is recommended.
*
* @param ctx The context that needs updating.
**/
OHMD_APIENTRYDLL void OHMD_APIENTRY ohmd_ctx_update(ohmd_context* ctx);
/**
* Probe for devices.
*
* Probes for and enumerates supported devices attached to the system.
*
* @param ctx A context with no currently open devices.
* @return the number of devices found on the system.
**/
OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_ctx_probe(ohmd_context* ctx);
/**
* Get string from openhmd.
*
* Gets a string from OpenHMD. This is where non-device specific strings reside.
* This is where the distortion shader sources can be retrieved.
*
* @param type The name of the string to fetch. One of OHMD_GLSL_DISTORTION_FRAG_SRC, and OHMD_GLSL_DISTORTION_FRAG_SRC.
* @return a string with a human readable device name.
**/
OHMD_APIENTRYDLL const char* OHMD_APIENTRY ohmd_gets(ohmd_string_description type);
/**
* Get device description from enumeration list index.
*
* Gets a human readable device description string from a zero indexed enumeration index
* between 0 and (max - 1), where max is the number ohmd_ctx_probe returned
* (i.e. if ohmd_ctx_probe returns 3, valid indices are 0, 1 and 2).
* The function can return three types of data. The vendor name, the product name and
* a driver specific path where the device is attached.
*
* ohmd_ctx_probe must be called before calling ohmd_list_gets.
*
* @param ctx A (probed) context.
* @param index An index, between 0 and the value returned from ohmd_ctx_probe.
* @param type The type of data to fetch. One of OHMD_VENDOR, OHMD_PRODUCT and OHMD_PATH.
* @return a string with a human readable device name.
**/
OHMD_APIENTRYDLL const char* OHMD_APIENTRY ohmd_list_gets(ohmd_context* ctx, int index, ohmd_string_value type);
/**
* Open a device.
*
* Opens a device from a zero indexed enumeration index between 0 and (max - 1)
* where max is the number ohmd_ctx_probe returned (i.e. if ohmd_ctx_probe returns 3,
* valid indices are 0, 1 and 2).
*
* ohmd_ctx_probe must be called before calling ohmd_list_open_device.
*
* @param ctx A (probed) context.
* @param index An index, between 0 and the value returned from ohmd_ctx_probe.
* @return a pointer to an ohmd_device, which represents a hardware device, such as an HMD.
**/
OHMD_APIENTRYDLL ohmd_device* OHMD_APIENTRY ohmd_list_open_device(ohmd_context* ctx, int index);
/**
* Open a device with additional settings provided.
*
* Opens a device from a zero indexed enumeration index between 0 and (max - 1)
* where max is the number ohmd_ctx_probe returned (i.e. if ohmd_ctx_probe returns 3,
* valid indices are 0, 1 and 2).
*
* ohmd_ctx_probe must be called before calling ohmd_list_open_device.
*
* @param ctx A (probed) context.
* @param index An index, between 0 and the value returned from ohmd_ctx_probe.
* @param settings A pointer to a device settings struct.
* @return a pointer to an ohmd_device, which represents a hardware device, such as an HMD.
**/
OHMD_APIENTRYDLL ohmd_device* OHMD_APIENTRY ohmd_list_open_device_s(ohmd_context* ctx, int index, ohmd_device_settings* settings);
/**
* Specify int settings in a device settings struct.
*
* @param settings The device settings struct to set values to.
* @param key The specefic setting you wish to set.
* @param value A pointer to an int or int array (containing the expected number of elements) with the value(s) you wish to set.
**/
OHMD_APIENTRYDLL ohmd_status OHMD_APIENTRY ohmd_device_settings_seti(ohmd_device_settings* settings, ohmd_int_settings key, const int* val);
/**
* Create a device settings instance.
*
* @param ctx A pointer to a valid ohmd_context.
* @return a pointer to an allocated ohmd_context on success or NULL if it fails.
**/
OHMD_APIENTRYDLL ohmd_device_settings* OHMD_APIENTRY ohmd_device_settings_create(ohmd_context* ctx);
/**
* Destroy a device settings instance.
*
* @param ctx The device settings instance to destroy.
**/
OHMD_APIENTRYDLL void OHMD_APIENTRY ohmd_device_settings_destroy(ohmd_device_settings* settings);
/**
* Close a device.
*
* Closes a device opened by ohmd_list_open_device. Note that ohmd_ctx_destroy automatically closes any open devices
* associated with the context being destroyed.
*
* @param device The open device.
* @return 0 on success, <0 on failure.
**/
OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_close_device(ohmd_device* device);
/**
* Get a floating point value from a device.
*
*
* @param device An open device to retrieve the value from.
* @param type What type of value to retrieve, see ohmd_float_value section for more information.
* @param[out] out A pointer to a float, or float array where the retrieved value should be written.
* @return 0 on success, <0 on failure.
**/
OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_device_getf(ohmd_device* device, ohmd_float_value type, float* out);
/**
* Set a floating point value for a device.
*
* @param device An open device to set the value in.
* @param type What type of value to set, see ohmd_float_value section for more information.
* @param in A pointer to a float, or float array where the new value is stored.
* @return 0 on success, <0 on failure.
**/
OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_device_setf(ohmd_device* device, ohmd_float_value type, const float* in);
/**
* Get an integer value from a device.
*
* @param device An open device to retrieve the value from.
* @param type What type of value to retrieve, ohmd_int_value section for more information.
* @param[out] out A pointer to an integer, or integer array where the retrieved value should be written.
* @return 0 on success, <0 on failure.
**/
OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_device_geti(ohmd_device* device, ohmd_int_value type, int* out);
/**
* Set an integer value for a device.
*
* @param device An open device to set the value in.
* @param type What type of value to set, see ohmd_float_value section for more information.
* @param in A pointer to a int, or int array where the new value is stored.
* @return 0 on success, <0 on failure.
**/
OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_device_seti(ohmd_device* device, ohmd_int_value type, const int* in);
/**
* Set an void* data value for a device.
*
* @param device An open device to set the value in.
* @param type What type of value to set, see ohmd_float_value section for more information.
* @param in A pointer to the void* casted object.
* @return 0 on success, <0 on failure.
**/
OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_device_set_data(ohmd_device* device, ohmd_data_value type, const void* in);
#ifdef __cplusplus
}
#endif
#endif

335
extern/openhmd/src/drv_android/android.c vendored Normal file
View File

@@ -0,0 +1,335 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Copyright (C) 2015 Joey Ferwerda
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Android Driver */
#include "android.h"
#ifdef __ANDROID__
#include <android/sensor.h>
#endif // __ANDROID__
typedef struct {
ohmd_device base;
fusion sensor_fusion;
//Android specific
#ifdef __ANDROID__
android_app* state;
ASensorManager* sensorManager;
const ASensor* accelerometerSensor;
const ASensor* gyroscopeSensor;
ASensorEventQueue* sensorEventQueue;
AAssetManager* assetMgr;
short firstRun;
#endif
} android_priv;
//Forward decelerations
static void set_android_properties(ohmd_device* device, ohmd_device_properties* props);
static void nofusion_init(fusion* me);
static void nofusion_update(fusion* me, float dt, const vec3f* accel);
//Static variable for timeDelta;
static float timestamp;
//Android callback for the sensor event queue
static int android_sensor_callback(int fd, int events, void* data)
{
android_priv* priv = (android_priv*)data;
if (priv->accelerometerSensor != NULL)
{
ASensorEvent event;
vec3f gyro;
vec3f accel;
vec3f mag;
float lastevent_timestamp;
while (ASensorEventQueue_getEvents(priv->sensorEventQueue, &event, 1) > 0)
{
if (event.type == ASENSOR_TYPE_ACCELEROMETER)
{
accel.x = event.acceleration.y;
accel.y = -event.acceleration.x;
accel.z = event.acceleration.z;
}
if (event.type == ASENSOR_TYPE_GYROSCOPE)
{
gyro.x = -event.data[1];
gyro.y = event.data[0];
gyro.z = event.data[2];
}
///TODO: Implement mag when available
mag.x = 0.0f;
mag.y = 0.0f;
mag.z = 0.0f;
lastevent_timestamp = event.timestamp;
}
//apply data to the fusion
float dT = 0.0f;
if (timestamp != 0)
dT= (lastevent_timestamp - timestamp) * (1.0f / 1000000000.0f);
//Check if accelerometer only fallback is required
if (!priv->gyroscopeSensor)
nofusion_update(&priv->sensor_fusion, dT, &accel);
else
ofusion_update(&priv->sensor_fusion, dT, &gyro, &accel, &mag); //default
timestamp = lastevent_timestamp;
}
return 1;
}
static void update_device(ohmd_device* device)
{
android_priv* priv = (android_priv*)device;
if(!priv->state)
return;
//We need this since during init the android_app state is not set yet
if (priv->firstRun == 1)
{
priv->sensorEventQueue = ASensorManager_createEventQueue(priv->sensorManager,
priv->state->looper, LOOPER_ID_USER, android_sensor_callback, (void*)priv);
// Start sensors in case this was not done already.
if (priv->accelerometerSensor != NULL)
{
ASensorEventQueue_enableSensor(priv->sensorEventQueue, priv->accelerometerSensor);
// We'd like to get 60 events per second (in us).
ASensorEventQueue_setEventRate(priv->sensorEventQueue, priv->accelerometerSensor, (1000L/60)*1000);
}
if (priv->gyroscopeSensor != NULL)
{
ASensorEventQueue_enableSensor(priv->sensorEventQueue, priv->gyroscopeSensor);
// We'd like to get 60 events per second (in us).
ASensorEventQueue_setEventRate(priv->sensorEventQueue, priv->gyroscopeSensor, (1000L/60)*1000);
}
priv->firstRun = 0;
}
}
static int getf(ohmd_device* device, ohmd_float_value type, float* out)
{
android_priv* priv = (android_priv*)device;
switch(type){
case OHMD_ROTATION_QUAT: {
*(quatf*)out = priv->sensor_fusion.orient;
break;
}
case OHMD_POSITION_VECTOR:
out[0] = out[1] = out[2] = 0;
break;
case OHMD_DISTORTION_K:
// TODO this should be set to the equivalent of no distortion
memset(out, 0, sizeof(float) * 6);
break;
default:
ohmd_set_error(priv->base.ctx, "invalid type given to getf (%d)", type);
return -1;
break;
}
return 0;
}
static int set_data(ohmd_device* device, ohmd_data_value type, void* in)
{
android_priv* priv = (android_priv*)device;
switch(type){
case OHMD_DRIVER_DATA: {
priv->state = (android_app*)in;
break;
}
case OHMD_DRIVER_PROPERTIES: {
set_android_properties(device, (ohmd_device_properties*)in);
break;
}
default:
ohmd_set_error(priv->base.ctx, "invalid type given to set_data (%i)", type);
return -1;
break;
}
return 0;
}
static void close_device(ohmd_device* device)
{
LOGD("closing Android device");
free(device);
}
static ohmd_device* open_device(ohmd_driver* driver, ohmd_device_desc* desc)
{
android_priv* priv = ohmd_alloc(driver->ctx, sizeof(android_priv));
if(!priv)
return NULL;
// Set default device properties
ohmd_set_default_device_properties(&priv->base.properties);
// Set device properties
//TODO: Get information from android about device
//TODO: Use profile string to set default for a particular device (Durovis, VR One etc)
priv->base.properties.hsize = 0.149760f;
priv->base.properties.vsize = 0.093600f;
priv->base.properties.hres = 1280;
priv->base.properties.vres = 800;
priv->base.properties.lens_sep = 0.063500f;
priv->base.properties.lens_vpos = 0.046800f;
priv->base.properties.fov = DEG_TO_RAD(125.5144f);
priv->base.properties.ratio = (1280.0f / 800.0f) / 2.0f;
// calculate projection eye projection matrices from the device properties
ohmd_calc_default_proj_matrices(&priv->base.properties);
// set up device callbacks
priv->base.update = update_device;
priv->base.close = close_device;
priv->base.getf = getf;
priv->base.set_data = set_data;
//init Android sensors
priv->sensorManager = ASensorManager_getInstance();
priv->accelerometerSensor = ASensorManager_getDefaultSensor(priv->sensorManager,
ASENSOR_TYPE_ACCELEROMETER);
priv->gyroscopeSensor = ASensorManager_getDefaultSensor(priv->sensorManager,
ASENSOR_TYPE_GYROSCOPE);
priv->firstRun = 1; //need this since ASensorManager_createEventQueue requires a set android_app*
//Check if accelerometer only fallback is required
if (!priv->gyroscopeSensor)
nofusion_init(&priv->sensor_fusion);
else
ofusion_init(&priv->sensor_fusion); //Default when all sensors are available
return (ohmd_device*)priv;
}
static void get_device_list(ohmd_driver* driver, ohmd_device_list* list)
{
ohmd_device_desc* desc = &list->devices[list->num_devices++];
strcpy(desc->driver, "OpenHMD Generic Android Driver");
strcpy(desc->vendor, "OpenHMD");
strcpy(desc->product, "Android Device");
strcpy(desc->path, "(none)");
desc->driver_ptr = driver;
}
static void destroy_driver(ohmd_driver* drv)
{
LOGD("shutting down Android driver");
free(drv);
}
ohmd_driver* ohmd_create_android_drv(ohmd_context* ctx)
{
ohmd_driver* drv = ohmd_alloc(ctx, sizeof(ohmd_driver));
if(!drv)
return NULL;
drv->get_device_list = get_device_list;
drv->open_device = open_device;
drv->destroy = destroy_driver;
drv->ctx = ctx;
return drv;
}
/* Android specific functions */
static void nofusion_update(fusion* me, float dt, const vec3f* accel)
{
//avg raw accel data to smooth jitter, and normalise
ofq_add(&me->accel_fq, accel);
vec3f accel_mean;
ofq_get_mean(&me->accel_fq, &accel_mean);
vec3f acc_n = accel_mean;
ovec3f_normalize_me(&acc_n);
//reference vectors for axis-angle
vec3f xyzv[3] = {
{1,0,0},
{0,1,0},
{0,0,1}
};
quatf roll, pitch;
//pitch is rot around x, based on gravity in z and y axes
oquatf_init_axis(&pitch, xyzv+0, atan2f(-acc_n.z, -acc_n.y));
//roll is rot around z, based on gravity in x and y axes
//note we need to invert the values when the device is upside down (y < 0) for proper results
oquatf_init_axis(&roll, xyzv+2, acc_n.y < 0 ? atan2f(-acc_n.x, -acc_n.y) : atan2f(acc_n.x, acc_n.y));
quatf or = {0,0,0,1};
//order of applying is yaw-pitch-roll
//yaw is not possible using only accel
oquatf_mult_me(&or, &pitch);
oquatf_mult_me(&or, &roll);
me->orient = or;
}
//shorter buffers for frame smoothing
static void nofusion_init(fusion* me)
{
memset(me, 0, sizeof(fusion));
me->orient.w = 1.0f;
ofq_init(&me->mag_fq, 10);
ofq_init(&me->accel_fq, 10);
ofq_init(&me->ang_vel_fq, 10);
me->flags = FF_USE_GRAVITY;
me->grav_gain = 0.05f;
}
static void set_android_properties(ohmd_device* device, ohmd_device_properties* props)
{
android_priv* priv = (android_priv*)device;
priv->base.properties.hsize = props->hsize;
priv->base.properties.vsize = props->vsize;
priv->base.properties.hres = props->hres;
priv->base.properties.vres = props->vres;
priv->base.properties.lens_sep = props->lens_sep;
priv->base.properties.lens_vpos = props->lens_vpos;
priv->base.properties.fov = DEG_TO_RAD(props->fov);
priv->base.properties.ratio = props->ratio;
}
static void set_android_profile(ohmd_driver* driver, android_hmd_profile profile)
{
switch(profile){
case DROID_DUROVIS_OPEN_DIVE: break;
case DROID_DUROVIS_DIVE_5: break;
case DROID_DUROVIS_DIVE_7: break;
case DROID_CARL_ZEISS_VRONE: break;
case DROID_GOOGLE_CARDBOARD: break;
case DROID_NONE:
default: break;
}
}

View File

@@ -0,0 +1,91 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Copyright (C) 2015 Joey Ferwerda
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Android Driver */
#ifndef ANDROID_H
#define ANDROID_H
#include "../openhmdi.h"
typedef enum {
DROID_DUROVIS_OPEN_DIVE = 1,
DROID_DUROVIS_DIVE_5 = 2,
DROID_DUROVIS_DIVE_7 = 3,
DROID_CARL_ZEISS_VRONE = 4,
DROID_GOOGLE_CARDBOARD = 5,
DROID_NONE = 0,
} android_hmd_profile;
//Android copy-paste from android_native_app_glue to be able to cast data to something useful
#include <poll.h>
#include <pthread.h>
#include <sched.h>
#include <android/configuration.h>
#include <android/looper.h>
#include <android/native_activity.h>
struct android_app;
struct android_poll_source {
int32_t id;
struct android_app* app;
void (*process)(struct android_app* app, struct android_poll_source* source);
};
typedef struct android_app {
void* userData;
void (*onAppCmd)(struct android_app* app, int32_t cmd);
int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
ANativeActivity* activity;
AConfiguration* config;
void* savedState;
size_t savedStateSize;
ALooper* looper;
AInputQueue* inputQueue;
ANativeWindow* window;
ARect contentRect;
int activityState;
int destroyRequested;
pthread_mutex_t mutex;
pthread_cond_t cond;
int msgread;
int msgwrite;
pthread_t thread;
struct android_poll_source cmdPollSource;
struct android_poll_source inputPollSource;
int running;
int stateSaved;
int destroyed;
int redrawNeeded;
AInputQueue* pendingInputQueue;
ANativeWindow* pendingWindow;
ARect pendingContentRect;
} android_app;
enum {
LOOPER_ID_MAIN = 1,
LOOPER_ID_INPUT = 2,
LOOPER_ID_USER = 3
};
#endif // ANDROID_H

332
extern/openhmd/src/drv_deepoon/deepoon.c vendored Normal file
View File

@@ -0,0 +1,332 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Deepoon Driver - HID/USB Driver Implementation */
#include <stdlib.h>
#include <hidapi.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <assert.h>
#include "deepoon.h"
#define TICK_LEN (1.0f / 1000000.0f) // 1000 Hz ticks
#define KEEP_ALIVE_VALUE (10 * 1000)
#define SETFLAG(_s, _flag, _val) (_s) = ((_s) & ~(_flag)) | ((_val) ? (_flag) : 0)
#define DEEPOON_ID 0x0483
#define DEEPOON_HMD 0x5750
typedef struct {
ohmd_device base;
hid_device* handle;
pkt_sensor_range sensor_range;
pkt_sensor_display_info display_info;
rift_coordinate_frame coordinate_frame, hw_coordinate_frame;
pkt_sensor_config sensor_config;
pkt_tracker_sensor sensor;
double last_keep_alive;
fusion sensor_fusion;
vec3f raw_mag, raw_accel, raw_gyro;
} rift_priv;
static rift_priv* rift_priv_get(ohmd_device* device)
{
return (rift_priv*)device;
}
static int get_feature_report(rift_priv* priv, rift_sensor_feature_cmd cmd, unsigned char* buf)
{
memset(buf, 0, FEATURE_BUFFER_SIZE);
buf[0] = (unsigned char)cmd;
return hid_get_feature_report(priv->handle, buf, FEATURE_BUFFER_SIZE);
}
static int send_feature_report(rift_priv* priv, const unsigned char *data, size_t length)
{
return hid_send_feature_report(priv->handle, data, length);
}
static void set_coordinate_frame(rift_priv* priv, rift_coordinate_frame coordframe)
{
priv->coordinate_frame = coordframe;
// set the RIFT_SCF_SENSOR_COORDINATES in the sensor config to match whether coordframe is hmd or sensor
SETFLAG(priv->sensor_config.flags, RIFT_SCF_SENSOR_COORDINATES, coordframe == RIFT_CF_SENSOR);
// encode send the new config to the Rift
unsigned char buf[FEATURE_BUFFER_SIZE];
int size = dp_encode_sensor_config(buf, &priv->sensor_config);
if(send_feature_report(priv, buf, size) == -1){
ohmd_set_error(priv->base.ctx, "send_feature_report failed in set_coordinate frame");
return;
}
// read the state again, set the hw_coordinate_frame to match what
// the hardware actually is set to just incase it doesn't stick.
size = get_feature_report(priv, RIFT_CMD_SENSOR_CONFIG, buf);
if(size <= 0){
LOGW("could not set coordinate frame");
priv->hw_coordinate_frame = RIFT_CF_HMD;
return;
}
priv->hw_coordinate_frame = (priv->sensor_config.flags & RIFT_SCF_SENSOR_COORDINATES) ? RIFT_CF_SENSOR : RIFT_CF_HMD;
if(priv->hw_coordinate_frame != coordframe) {
LOGW("coordinate frame didn't stick");
}
}
static void handle_tracker_sensor_msg(rift_priv* priv, unsigned char* buffer, int size)
{
uint32_t last_sample_tick = priv->sensor.tick;
if(!dp_decode_tracker_sensor_msg(&priv->sensor, buffer, size)){
LOGE("couldn't decode tracker sensor message");
}
pkt_tracker_sensor* s = &priv->sensor;
dp_dump_packet_tracker_sensor(s);
uint32_t tick_delta = 1000;
if(last_sample_tick > 0) //startup correction
tick_delta = s->tick - last_sample_tick;
float dt = tick_delta * TICK_LEN;
vec3f mag = {{0.0f, 0.0f, 0.0f}};
for(int i = 0; i < 1; i++){ //just use 1 sample since we don't have sample order for this frame
vec3f_from_dp_vec(s->samples[i].accel, &priv->raw_accel);
vec3f_from_dp_vec(s->samples[i].gyro, &priv->raw_gyro);
ofusion_update(&priv->sensor_fusion, dt, &priv->raw_gyro, &priv->raw_accel, &mag);
// reset dt to tick_len for the last samples if there were more than one sample
dt = TICK_LEN;
}
}
static void update_device(ohmd_device* device)
{
rift_priv* priv = rift_priv_get(device);
unsigned char buffer[FEATURE_BUFFER_SIZE];
// Handle keep alive messages
double t = ohmd_get_tick();
if(t - priv->last_keep_alive >= (double)priv->sensor_config.keep_alive_interval / 1000.0 - .2){
// send keep alive message
pkt_keep_alive keep_alive = { 0, priv->sensor_config.keep_alive_interval };
int ka_size = dp_encode_keep_alive(buffer, &keep_alive);
send_feature_report(priv, buffer, ka_size);
// Update the time of the last keep alive we have sent.
priv->last_keep_alive = t;
}
// Read all the messages from the device.
while(true){
int size = hid_read(priv->handle, buffer, FEATURE_BUFFER_SIZE);
if(size < 0){
LOGE("error reading from device");
return;
} else if(size == 0) {
return; // No more messages, return.
}
// currently the only message type the hardware supports (I think)
if(buffer[0] == RIFT_IRQ_SENSORS || buffer[0] == 11){
handle_tracker_sensor_msg(priv, buffer, size);
}else{
LOGE("unknown message type: %u", buffer[0]);
}
}
}
static int getf(ohmd_device* device, ohmd_float_value type, float* out)
{
rift_priv* priv = rift_priv_get(device);
switch(type){
case OHMD_DISTORTION_K: {
for (int i = 0; i < 6; i++) {
out[i] = priv->display_info.distortion_k[i];
}
break;
}
case OHMD_ROTATION_QUAT: {
*(quatf*)out = priv->sensor_fusion.orient;
break;
}
case OHMD_POSITION_VECTOR:
out[0] = out[1] = out[2] = 0;
break;
default:
ohmd_set_error(priv->base.ctx, "invalid type given to getf (%ud)", type);
return -1;
break;
}
return 0;
}
static void close_device(ohmd_device* device)
{
LOGD("closing device");
rift_priv* priv = rift_priv_get(device);
hid_close(priv->handle);
free(priv);
}
static char* _hid_to_unix_path(char* path)
{
char bus [4];
char dev [4];
char *result = malloc( sizeof(char) * ( 20 + 1 ) );
sprintf (bus, "%.*s\n", 4, path);
sprintf (dev, "%.*s\n", 4, path + 5);
sprintf (result, "/dev/bus/usb/%03d/%03d",
(int)strtol(bus, NULL, 16),
(int)strtol(dev, NULL, 16));
return result;
}
static ohmd_device* open_device(ohmd_driver* driver, ohmd_device_desc* desc)
{
rift_priv* priv = ohmd_alloc(driver->ctx, sizeof(rift_priv));
if(!priv)
goto cleanup;
priv->base.ctx = driver->ctx;
// Open the HID device
priv->handle = hid_open_path(desc->path);
if(!priv->handle) {
char* path = _hid_to_unix_path(desc->path);
ohmd_set_error(driver->ctx, "Could not open %s. "
"Check your rights.", path);
free(path);
goto cleanup;
}
if(hid_set_nonblocking(priv->handle, 1) == -1){
ohmd_set_error(driver->ctx, "failed to set non-blocking on device");
goto cleanup;
}
unsigned char buf[FEATURE_BUFFER_SIZE];
int size;
// if the sensor has display info data, use HMD coordinate frame
priv->coordinate_frame = priv->display_info.distortion_type != RIFT_DT_NONE ? RIFT_CF_HMD : RIFT_CF_SENSOR;
// enable calibration
SETFLAG(priv->sensor_config.flags, RIFT_SCF_USE_CALIBRATION, 1);
SETFLAG(priv->sensor_config.flags, RIFT_SCF_AUTO_CALIBRATION, 1);
// apply sensor config
set_coordinate_frame(priv, priv->coordinate_frame);
// set keep alive interval to n seconds
pkt_keep_alive keep_alive = { 0, KEEP_ALIVE_VALUE };
size = dp_encode_keep_alive(buf, &keep_alive);
send_feature_report(priv, buf, size);
// Update the time of the last keep alive we have sent.
priv->last_keep_alive = ohmd_get_tick();
// Set default device properties
ohmd_set_default_device_properties(&priv->base.properties);
// Set device properties
//NOTE: These values are estimations, no one has taken one appart to check
priv->base.properties.hsize = 0.1698f;
priv->base.properties.vsize = 0.0936f;
priv->base.properties.hres = 1920;
priv->base.properties.vres = 1080;
priv->base.properties.lens_sep = 0.0849f;
priv->base.properties.lens_vpos = 0.0468f;;
priv->base.properties.fov = DEG_TO_RAD(110.0); // TODO calculate.
priv->base.properties.ratio = ((float)1920 / (float)1080) / 2.0f;
// calculate projection eye projection matrices from the device properties
ohmd_calc_default_proj_matrices(&priv->base.properties);
// set up device callbacks
priv->base.update = update_device;
priv->base.close = close_device;
priv->base.getf = getf;
// initialize sensor fusion
ofusion_init(&priv->sensor_fusion);
return &priv->base;
cleanup:
if(priv)
free(priv);
return NULL;
}
static void get_device_list(ohmd_driver* driver, ohmd_device_list* list)
{
struct hid_device_info* devs = hid_enumerate(DEEPOON_ID, DEEPOON_HMD);
struct hid_device_info* cur_dev = devs;
while (cur_dev) {
ohmd_device_desc* desc = &list->devices[list->num_devices++];
strcpy(desc->driver, "Deepoon Driver");
strcpy(desc->vendor, "Deepoon");
strcpy(desc->product, "Deepoon E2");
desc->revision = 0;
strcpy(desc->path, cur_dev->path);
desc->driver_ptr = driver;
cur_dev = cur_dev->next;
}
hid_free_enumeration(devs);
}
static void destroy_driver(ohmd_driver* drv)
{
LOGD("shutting down driver");
hid_exit();
free(drv);
}
ohmd_driver* ohmd_create_deepoon_drv(ohmd_context* ctx)
{
ohmd_driver* drv = ohmd_alloc(ctx, sizeof(ohmd_driver));
if(drv == NULL)
return NULL;
drv->get_device_list = get_device_list;
drv->open_device = open_device;
drv->ctx = ctx;
drv->get_device_list = get_device_list;
drv->open_device = open_device;
drv->destroy = destroy_driver;
return drv;
}

111
extern/openhmd/src/drv_deepoon/deepoon.h vendored Normal file
View File

@@ -0,0 +1,111 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Deepoon Driver Internal Interface */
#ifndef DEEPOON_H
#define DEEPOON_H
#include "../openhmdi.h"
#define FEATURE_BUFFER_SIZE 256
typedef enum {
RIFT_CMD_SENSOR_CONFIG = 2,
RIFT_CMD_RANGE = 4,
RIFT_CMD_KEEP_ALIVE = 8,
RIFT_CMD_DISPLAY_INFO = 9
} rift_sensor_feature_cmd;
typedef enum {
RIFT_CF_SENSOR,
RIFT_CF_HMD
} rift_coordinate_frame;
typedef enum {
RIFT_IRQ_SENSORS = 1
} rift_irq_cmd;
typedef enum {
RIFT_DT_NONE,
RIFT_DT_SCREEN_ONLY,
RIFT_DT_DISTORTION
} rift_distortion_type;
// Sensor config flags
#define RIFT_SCF_RAW_MODE 0x01
#define RIFT_SCF_CALIBRATION_TEST 0x02
#define RIFT_SCF_USE_CALIBRATION 0x04
#define RIFT_SCF_AUTO_CALIBRATION 0x08
#define RIFT_SCF_MOTION_KEEP_ALIVE 0x10
#define RIFT_SCF_COMMAND_KEEP_ALIVE 0x20
#define RIFT_SCF_SENSOR_COORDINATES 0x40
typedef struct {
uint16_t command_id;
uint16_t accel_scale;
uint16_t gyro_scale;
uint16_t mag_scale;
} pkt_sensor_range;
typedef struct {
int32_t accel[3];
int32_t gyro[3];
} pkt_tracker_sample;
typedef struct {
uint8_t report_id;
uint8_t sample_delta;
uint16_t sample_number;
uint32_t tick;
pkt_tracker_sample samples[2];
int16_t mag[3];
} pkt_tracker_sensor;
typedef struct {
uint16_t command_id;
uint8_t flags;
uint16_t packet_interval;
uint16_t keep_alive_interval; // in ms
} pkt_sensor_config;
typedef struct {
uint16_t command_id;
rift_distortion_type distortion_type;
uint8_t distortion_type_opts;
uint16_t h_resolution, v_resolution;
float h_screen_size, v_screen_size;
float v_center;
float lens_separation;
float eye_to_screen_distance[2];
float distortion_k[6];
} pkt_sensor_display_info;
typedef struct {
uint16_t command_id;
uint16_t keep_alive_interval;
} pkt_keep_alive;
bool dp_decode_sensor_range(pkt_sensor_range* range, const unsigned char* buffer, int size);
bool dp_decode_sensor_display_info(pkt_sensor_display_info* info, const unsigned char* buffer, int size);
bool dp_decode_sensor_config(pkt_sensor_config* config, const unsigned char* buffer, int size);
bool dp_decode_tracker_sensor_msg(pkt_tracker_sensor* msg, const unsigned char* buffer, int size);
void vec3f_from_dp_vec(const int32_t* smp, vec3f* out_vec);
int dp_encode_sensor_config(unsigned char* buffer, const pkt_sensor_config* config);
int dp_encode_keep_alive(unsigned char* buffer, const pkt_keep_alive* keep_alive);
void dp_dump_packet_sensor_range(const pkt_sensor_range* range);
void dp_dump_packet_sensor_config(const pkt_sensor_config* config);
void dp_dump_packet_sensor_display_info(const pkt_sensor_display_info* info);
void dp_dump_packet_tracker_sensor(const pkt_tracker_sensor* sensor);
#endif

182
extern/openhmd/src/drv_deepoon/packet.c vendored Normal file
View File

@@ -0,0 +1,182 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Deepoon Driver - Packet Decoding and Utilities */
#include <stdio.h>
#include "deepoon.h"
#define SKIP_CMD (buffer++)
#define READ8 *(buffer++);
#define READ16 *buffer | (*(buffer + 1) << 8); buffer += 2;
#define READ32 *buffer | (*(buffer + 1) << 8) | (*(buffer + 2) << 16) | (*(buffer + 3) << 24); buffer += 4;
#define READFLOAT ((float)(*buffer)); buffer += 4;
#define READFIXED (float)(*buffer | (*(buffer + 1) << 8) | (*(buffer + 2) << 16) | (*(buffer + 3) << 24)) / 1000000.0f; buffer += 4;
#define WRITE8(_val) *(buffer++) = (_val);
#define WRITE16(_val) WRITE8((_val) & 0xff); WRITE8(((_val) >> 8) & 0xff);
#define WRITE32(_val) WRITE16((_val) & 0xffff) *buffer; WRITE16(((_val) >> 16) & 0xffff);
bool dp_decodesensor_range(pkt_sensor_range* range, const unsigned char* buffer, int size)
{
if(!(size == 8 || size == 9)){
LOGE("invalid packet size (expected 8 or 9 but got %d)", size);
return false;
}
SKIP_CMD;
range->command_id = READ16;
range->accel_scale = READ8;
range->gyro_scale = READ16;
range->mag_scale = READ16;
return true;
}
bool dp_decodesensor_display_info(pkt_sensor_display_info* info, const unsigned char* buffer, int size)
{
if(!(size == 56 || size == 57)){
LOGE("invalid packet size (expected 56 or 57 but got %d)", size);
//return false;
}
SKIP_CMD;
info->command_id = READ16;
info->distortion_type = READ8;
info->h_resolution = READ16;
info->v_resolution = READ16;
info->h_screen_size = READFIXED;
info->v_screen_size = READFIXED;
info->v_center = READFIXED;
info->lens_separation = READFIXED;
info->eye_to_screen_distance[0] = READFIXED;
info->eye_to_screen_distance[1] = READFIXED;
info->distortion_type_opts = 0;
for(int i = 0; i < 6; i++){
info->distortion_k[i] = READFLOAT;
}
return true;
}
bool dp_decodesensor_config(pkt_sensor_config* config, const unsigned char* buffer, int size)
{
if(!(size == 7 || size == 8)){
LOGE("invalid packet size (expected 7 or 8 but got %d)", size);
return false;
}
SKIP_CMD;
config->command_id = READ16;
config->flags = READ8;
config->packet_interval = READ8;
config->keep_alive_interval = READ16;
return true;
}
static void dp_decodesample(const unsigned char* buffer, int32_t* smp)
{
/*
* Decode 3 tightly packed 21 bit values from 4 bytes.
* We unpack them in the higher 21 bit values first and then shift
* them down to the lower in order to get the sign bits correct.
*/
int x = (buffer[0] << 24) | (buffer[1] << 16) | ((buffer[2] & 0xF8) << 8);
int y = ((buffer[2] & 0x07) << 29) | (buffer[3] << 21) | (buffer[4] << 13) | ((buffer[5] & 0xC0) << 5);
int z = ((buffer[5] & 0x3F) << 26) | (buffer[6] << 18) | (buffer[7] << 10);
smp[0] = x >> 11;
smp[1] = y >> 11;
smp[2] = z >> 11;
}
bool dp_decode_tracker_sensor_msg(pkt_tracker_sensor* msg, const unsigned char* buffer, int size)
{
if(!(size == 62 || size == 64)){
LOGE("invalid packet size (expected 62 or 64 but got %d)", size);
return false;
}
msg->report_id = READ8;
buffer += 2;
msg->sample_delta = READ8;
msg->sample_number = READ16;
buffer += 2;
msg->tick = READ32;
for(int i = 0; i < 2; i++){
dp_decodesample(buffer, msg->samples[i].accel);
buffer += 8;
dp_decodesample(buffer, msg->samples[i].gyro);
buffer += 8;
}
return true;
}
// TODO do we need to consider HMD vs sensor "centric" values
void vec3f_from_dp_vec(const int32_t* smp, vec3f* out_vec)
{
out_vec->x = (float)smp[0] * 0.0001f;
out_vec->y = ((float)smp[2] * 0.0001f) * -1;
out_vec->z = (float)smp[1] * 0.0001f;
}
int dp_encode_sensor_config(unsigned char* buffer, const pkt_sensor_config* config)
{
WRITE8(RIFT_CMD_SENSOR_CONFIG);
WRITE16(config->command_id);
WRITE8(config->flags);
WRITE8(config->packet_interval);
WRITE16(config->keep_alive_interval);
return 7; // sensor config packet size
}
int dp_encode_keep_alive(unsigned char* buffer, const pkt_keep_alive* keep_alive)
{
WRITE8(RIFT_CMD_KEEP_ALIVE);
WRITE16(keep_alive->command_id);
WRITE16(keep_alive->keep_alive_interval);
return 5; // keep alive packet size
}
void dp_dump_packet_sensor_config(const pkt_sensor_config* config)
{
(void)config;
LOGD("sensor config");
LOGD(" command id: %u", config->command_id);
LOGD(" flags: %02x", config->flags);
LOGD(" raw mode: %d", !!(config->flags & RIFT_SCF_RAW_MODE));
LOGD(" calibration test: %d", !!(config->flags & RIFT_SCF_CALIBRATION_TEST));
LOGD(" use calibration: %d", !!(config->flags & RIFT_SCF_USE_CALIBRATION));
LOGD(" auto calibration: %d", !!(config->flags & RIFT_SCF_AUTO_CALIBRATION));
LOGD(" motion keep alive: %d", !!(config->flags & RIFT_SCF_MOTION_KEEP_ALIVE));
LOGD(" motion command keep alive: %d", !!(config->flags & RIFT_SCF_COMMAND_KEEP_ALIVE));
LOGD(" sensor coordinates: %d", !!(config->flags & RIFT_SCF_SENSOR_COORDINATES));
LOGD(" packet interval: %u", config->packet_interval);
LOGD(" keep alive interval: %u", config->keep_alive_interval);
}
void dp_dump_packet_tracker_sensor(const pkt_tracker_sensor* sensor)
{
(void)sensor;
LOGD("TEST: deepoon sensor data");
LOGD(" report id: %u", sensor->report_id);
LOGD(" sample delta: %u", sensor->sample_delta);
LOGD(" sample number: %d", sensor->sample_number);
LOGD(" tick: %u", sensor->tick);
for(int i = 0; i < 2; i++){
LOGD(" accel: %d %d %d", sensor->samples[i].accel[0], sensor->samples[i].accel[1], sensor->samples[i].accel[2]);
LOGD(" gyro: %d %d %d", sensor->samples[i].gyro[0], sensor->samples[i].gyro[1], sensor->samples[i].gyro[2]);
}
}

118
extern/openhmd/src/drv_dummy/dummy.c vendored Normal file
View File

@@ -0,0 +1,118 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Dummy Driver */
#include <string.h>
#include "../openhmdi.h"
typedef struct {
ohmd_device base;
} dummy_priv;
static void update_device(ohmd_device* device)
{
}
static int getf(ohmd_device* device, ohmd_float_value type, float* out)
{
dummy_priv* priv = (dummy_priv*)device;
switch(type){
case OHMD_ROTATION_QUAT:
out[0] = out[1] = out[2] = 0;
out[3] = 1.0f;
break;
case OHMD_POSITION_VECTOR:
out[0] = out[1] = out[2] = 0;
break;
case OHMD_DISTORTION_K:
// TODO this should be set to the equivalent of no distortion
memset(out, 0, sizeof(float) * 6);
break;
default:
ohmd_set_error(priv->base.ctx, "invalid type given to getf (%ud)", type);
return -1;
break;
}
return 0;
}
static void close_device(ohmd_device* device)
{
LOGD("closing dummy device");
free(device);
}
static ohmd_device* open_device(ohmd_driver* driver, ohmd_device_desc* desc)
{
dummy_priv* priv = ohmd_alloc(driver->ctx, sizeof(dummy_priv));
if(!priv)
return NULL;
// Set default device properties
ohmd_set_default_device_properties(&priv->base.properties);
// Set device properties (imitates the rift values)
priv->base.properties.hsize = 0.149760f;
priv->base.properties.vsize = 0.093600f;
priv->base.properties.hres = 1280;
priv->base.properties.vres = 800;
priv->base.properties.lens_sep = 0.063500f;
priv->base.properties.lens_vpos = 0.046800f;
priv->base.properties.fov = DEG_TO_RAD(125.5144f);
priv->base.properties.ratio = (1280.0f / 800.0f) / 2.0f;
priv->base.properties.digital_button_count = 4;
// calculate projection eye projection matrices from the device properties
ohmd_calc_default_proj_matrices(&priv->base.properties);
// set up device callbacks
priv->base.update = update_device;
priv->base.close = close_device;
priv->base.getf = getf;
return (ohmd_device*)priv;
}
static void get_device_list(ohmd_driver* driver, ohmd_device_list* list)
{
ohmd_device_desc* desc = &list->devices[list->num_devices++];
strcpy(desc->driver, "OpenHMD Dummy Driver");
strcpy(desc->vendor, "OpenHMD");
strcpy(desc->product, "Dummy Device");
strcpy(desc->path, "(none)");
desc->driver_ptr = driver;
}
static void destroy_driver(ohmd_driver* drv)
{
LOGD("shutting down dummy driver");
free(drv);
}
ohmd_driver* ohmd_create_dummy_drv(ohmd_context* ctx)
{
ohmd_driver* drv = ohmd_alloc(ctx, sizeof(ohmd_driver));
if(!drv)
return NULL;
drv->get_device_list = get_device_list;
drv->open_device = open_device;
drv->get_device_list = get_device_list;
drv->open_device = open_device;
drv->destroy = destroy_driver;
return drv;
}

View File

@@ -0,0 +1,152 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Copyright (C) 2015 Joey Ferwerda
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* External Driver */
#include "../openhmdi.h"
#include "string.h"
typedef struct {
ohmd_device base;
fusion sensor_fusion;
} external_priv;
static void update_device(ohmd_device* device)
{
}
static int getf(ohmd_device* device, ohmd_float_value type, float* out)
{
external_priv* priv = (external_priv*)device;
switch(type){
case OHMD_ROTATION_QUAT: {
*(quatf*)out = priv->sensor_fusion.orient;
break;
}
case OHMD_POSITION_VECTOR:
out[0] = out[1] = out[2] = 0;
break;
default:
ohmd_set_error(priv->base.ctx, "invalid type given to getf (%d)", type);
return -1;
break;
}
return 0;
}
static int setf(ohmd_device* device, ohmd_float_value type, const float* in)
{
external_priv* priv = (external_priv*)device;
switch(type){
case OHMD_EXTERNAL_SENSOR_FUSION: {
ofusion_update(&priv->sensor_fusion, *in, (vec3f*)(in + 1), (vec3f*)(in + 4), (vec3f*)(in + 7));
}
break;
default:
ohmd_set_error(priv->base.ctx, "invalid type given to setf (%d)", type);
return -1;
break;
}
return 0;
}
static void close_device(ohmd_device* device)
{
LOGD("closing external device");
free(device);
}
static ohmd_device* open_device(ohmd_driver* driver, ohmd_device_desc* desc)
{
external_priv* priv = ohmd_alloc(driver->ctx, sizeof(external_priv));
if(!priv)
return NULL;
// Set default device properties
ohmd_set_default_device_properties(&priv->base.properties);
// Set device properties
//TODO: Get information from external device using set_external_properties?
//Using 'dummy' settings for now
priv->base.properties.hsize = 0.149760f;
priv->base.properties.vsize = 0.093600f;
priv->base.properties.hres = 1280;
priv->base.properties.vres = 800;
priv->base.properties.lens_sep = 0.063500f;
priv->base.properties.lens_vpos = 0.046800f;
priv->base.properties.fov = DEG_TO_RAD(125.5144f);
priv->base.properties.ratio = (1280.0f / 800.0f) / 2.0f;
// calculate projection eye projection matrices from the device properties
ohmd_calc_default_proj_matrices(&priv->base.properties);
// set up device callbacks
priv->base.update = update_device;
priv->base.close = close_device;
priv->base.getf = getf;
priv->base.setf = setf;
ofusion_init(&priv->sensor_fusion);
return (ohmd_device*)priv;
}
static void get_device_list(ohmd_driver* driver, ohmd_device_list* list)
{
ohmd_device_desc* desc = &list->devices[list->num_devices++];
strcpy(desc->driver, "OpenHMD Generic External Driver");
strcpy(desc->vendor, "OpenHMD");
strcpy(desc->product, "External Device");
strcpy(desc->path, "(none)");
desc->driver_ptr = driver;
}
static void destroy_driver(ohmd_driver* drv)
{
LOGD("shutting down external driver");
free(drv);
}
ohmd_driver* ohmd_create_external_drv(ohmd_context* ctx)
{
ohmd_driver* drv = ohmd_alloc(ctx, sizeof(ohmd_driver));
if(!drv)
return NULL;
drv->get_device_list = get_device_list;
drv->open_device = open_device;
drv->destroy = destroy_driver;
drv->ctx = ctx;
return drv;
}
/* external specific functions */
/*static void set_external_properties(ohmd_device* device, ohmd_device_properties* props)
{
external_priv* priv = (external_priv*)device;
priv->base.properties.hsize = props->hsize;
priv->base.properties.vsize = props->vsize;
priv->base.properties.hres = props->hres;
priv->base.properties.vres = props->vres;
priv->base.properties.lens_sep = props->lens_sep;
priv->base.properties.lens_vpos = props->lens_vpos;
priv->base.properties.fov = DEG_TO_RAD(props->fov);
priv->base.properties.ratio = props->ratio;
}*/

View File

@@ -0,0 +1 @@
//Reserved

27
extern/openhmd/src/drv_htc_vive/magic.h vendored Normal file
View File

@@ -0,0 +1,27 @@
static const unsigned char vive_magic_power_on[64] = {
0x04, 0x78, 0x29, 0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01,
0xa8, 0x0d, 0x76, 0x00, 0x40, 0xfc, 0x01, 0x05, 0xfa, 0xec, 0xd1, 0x6d, 0x00,
0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x0d, 0x76, 0x00, 0x68, 0xfc,
0x01, 0x05, 0x2c, 0xb0, 0x2e, 0x65, 0x7a, 0x0d, 0x76, 0x00, 0x68, 0x54, 0x72,
0x00, 0x18, 0x54, 0x72, 0x00, 0x00, 0x6a, 0x72, 0x00, 0x00, 0x00, 0x00,
};
static const unsigned char vive_magic_power_off1[64] = {
0x04, 0x78, 0x29, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
0x30, 0x05, 0x77, 0x00, 0x30, 0x05, 0x77, 0x00, 0x6c, 0x4d, 0x37, 0x65, 0x40,
0xf9, 0x33, 0x00, 0x04, 0xf8, 0xa3, 0x04, 0x04, 0x00, 0x00, 0x00, 0x70, 0xb0,
0x72, 0x00, 0xf4, 0xf7, 0xa3, 0x04, 0x7c, 0xf8, 0x33, 0x00, 0x0c, 0xf8, 0xa3,
0x04, 0x0a, 0x6e, 0x29, 0x65, 0x24, 0xf9, 0x33, 0x00, 0x00, 0x00, 0x00,
};
static const unsigned char vive_magic_power_off2[64] = {
0x04, 0x78, 0x29, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
0x30, 0x05, 0x77, 0x00, 0xe4, 0xf7, 0x33, 0x00, 0xe4, 0xf7, 0x33, 0x00, 0x60,
0x6e, 0x72, 0x00, 0xb4, 0xf7, 0x33, 0x00, 0x04, 0x00, 0x00, 0x00, 0x70, 0xb0,
0x72, 0x00, 0x90, 0xf7, 0x33, 0x00, 0x7c, 0xf8, 0x33, 0x00, 0xd0, 0xf7, 0x33,
0x00, 0x3c, 0x68, 0x29, 0x65, 0x24, 0xf9, 0x33, 0x00, 0x00, 0x00, 0x00,
};
static const unsigned char vive_magic_enable_lighthouse[5] = {
0x04
};

View File

@@ -0,0 +1,63 @@
#include "vive.h"
#include "config.h"
#ifdef _MSC_VER
#define inline __inline
#endif
inline static uint8_t read8(const unsigned char** buffer)
{
uint8_t ret = **buffer;
*buffer += 1;
return ret;
}
inline static int16_t read16(const unsigned char** buffer)
{
int16_t ret = **buffer | (*(*buffer + 1) << 8);
*buffer += 2;
return ret;
}
inline static uint32_t read32(const unsigned char** buffer)
{
uint32_t ret = **buffer | (*(*buffer + 1) << 8) | (*(*buffer + 2) << 16) | (*(*buffer + 3) << 24);
*buffer += 4;
return ret;
}
bool vive_decode_sensor_packet(vive_sensor_packet* pkt, const unsigned char* buffer, int size)
{
if(size != 52){
LOGE("invalid vive sensor packet size (expected 52 but got %d)", size);
return false;
}
pkt->report_id = read8(&buffer);
for(int j = 0; j < 3; j++){
// acceleration
for(int i = 0; i < 3; i++){
pkt->samples[j].acc[i] = read16(&buffer);
}
// rotation
for(int i = 0; i < 3; i++){
pkt->samples[j].rot[i] = read16(&buffer);
}
pkt->samples[j].time_ticks = read32(&buffer);
pkt->samples[j].seq = read8(&buffer);
}
return true;
}
//TODO: Implement config packet decoding.
bool vive_decode_config_packet(vive_config_packet* pkt, const unsigned char* buffer, int size)
{
if(size != 64){
LOGE("invalid vive sensor packet size (expected 64 but got %d)", size);
return false;
}
return false;
}

441
extern/openhmd/src/drv_htc_vive/vive.c vendored Normal file
View File

@@ -0,0 +1,441 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* HTC Vive Driver */
#define FEATURE_BUFFER_SIZE 256
#define HTC_ID 0x0bb4
#define VIVE_HMD 0x2c87
#define VALVE_ID 0x28de
#define VIVE_WATCHMAN_DONGLE 0x2101
#define VIVE_LIGHTHOUSE_FPGA_RX 0x2000
#define VIVE_TIME_DIV 48000000.0f
#include <string.h>
#include <wchar.h>
#include <hidapi.h>
#include <assert.h>
#include <limits.h>
#include <stdint.h>
#include <stdbool.h>
#include "vive.h"
typedef struct {
ohmd_device base;
hid_device* hmd_handle;
hid_device* imu_handle;
fusion sensor_fusion;
vec3f raw_accel, raw_gyro;
uint32_t last_ticks;
uint8_t last_seq;
vec3f gyro_error;
filter_queue gyro_q;
} vive_priv;
void vec3f_from_vive_vec_accel(const int16_t* smp, vec3f* out_vec)
{
float gravity = 9.81f;
float scaler = 4.0f * gravity / 32768.0f;
out_vec->x = (float)smp[0] * scaler;
out_vec->y = (float)smp[1] * scaler * -1;
out_vec->z = (float)smp[2] * scaler * -1;
}
void vec3f_from_vive_vec_gyro(const int16_t* smp, vec3f* out_vec)
{
float scaler = 8.7f / 32768.0f;
out_vec->x = (float)smp[0] * scaler;
out_vec->y = (float)smp[1] * scaler * -1;
out_vec->z = (float)smp[2] * scaler * -1;
}
static bool process_error(vive_priv* priv)
{
if(priv->gyro_q.at >= priv->gyro_q.size - 1)
return true;
ofq_add(&priv->gyro_q, &priv->raw_gyro);
if(priv->gyro_q.at >= priv->gyro_q.size - 1){
ofq_get_mean(&priv->gyro_q, &priv->gyro_error);
printf("gyro error: %f, %f, %f\n", priv->gyro_error.x, priv->gyro_error.y, priv->gyro_error.z);
}
return false;
}
vive_sensor_sample* get_next_sample(vive_sensor_packet* pkt, int last_seq)
{
int diff[3];
for(int i = 0; i < 3; i++)
{
diff[i] = (int)pkt->samples[i].seq - last_seq;
if(diff[i] < -128){
diff[i] += 256;
}
}
int closest_diff = INT_MAX;
int closest_idx = -1;
for(int i = 0; i < 3; i++)
{
if(diff[i] < closest_diff && diff[i] > 0 && diff[i] < 128){
closest_diff = diff[i];
closest_idx = i;
}
}
if(closest_idx != -1)
return pkt->samples + closest_idx;
return NULL;
}
static void update_device(ohmd_device* device)
{
vive_priv* priv = (vive_priv*)device;
int size = 0;
unsigned char buffer[FEATURE_BUFFER_SIZE];
while((size = hid_read(priv->imu_handle, buffer, FEATURE_BUFFER_SIZE)) > 0){
if(buffer[0] == VIVE_IRQ_SENSORS){
vive_sensor_packet pkt;
vive_decode_sensor_packet(&pkt, buffer, size);
vive_sensor_sample* smp = NULL;
while((smp = get_next_sample(&pkt, priv->last_seq)) != NULL)
{
if(priv->last_ticks == 0)
priv->last_ticks = smp->time_ticks;
uint32_t t1, t2;
t1 = smp->time_ticks;
t2 = priv->last_ticks;
float dt = (t1 - t2) / VIVE_TIME_DIV;
priv->last_ticks = smp->time_ticks;
vec3f_from_vive_vec_accel(smp->acc, &priv->raw_accel);
vec3f_from_vive_vec_gyro(smp->rot, &priv->raw_gyro);
if(process_error(priv)){
vec3f mag = {{0.0f, 0.0f, 0.0f}};
vec3f gyro;
ovec3f_subtract(&priv->raw_gyro, &priv->gyro_error, &gyro);
ofusion_update(&priv->sensor_fusion, dt, &gyro, &priv->raw_accel, &mag);
}
priv->last_seq = smp->seq;
}
}else{
LOGE("unknown message type: %u", buffer[0]);
}
}
if(size < 0){
LOGE("error reading from device");
}
}
static int getf(ohmd_device* device, ohmd_float_value type, float* out)
{
vive_priv* priv = (vive_priv*)device;
switch(type){
case OHMD_ROTATION_QUAT:
*(quatf*)out = priv->sensor_fusion.orient;
break;
case OHMD_POSITION_VECTOR:
out[0] = out[1] = out[2] = 0;
break;
case OHMD_DISTORTION_K:
// TODO this should be set to the equivalent of no distortion
memset(out, 0, sizeof(float) * 6);
break;
default:
ohmd_set_error(priv->base.ctx, "invalid type given to getf (%ud)", type);
return -1;
break;
}
return 0;
}
static void close_device(ohmd_device* device)
{
int hret = 0;
vive_priv* priv = (vive_priv*)device;
LOGD("closing HTC Vive device");
// turn the display off
hret = hid_send_feature_report(priv->hmd_handle, vive_magic_power_off1, sizeof(vive_magic_power_off1));
//printf("power off magic 1: %d\n", hret);
hret = hid_send_feature_report(priv->hmd_handle, vive_magic_power_off2, sizeof(vive_magic_power_off2));
//printf("power off magic 2: %d\n", hret);
hid_close(priv->hmd_handle);
hid_close(priv->imu_handle);
free(device);
}
#if 0
static void dump_indexed_string(hid_device* device, int index)
{
wchar_t wbuffer[512] = {0};
char buffer[1024] = {0};
int hret = hid_get_indexed_string(device, index, wbuffer, 511);
if(hret == 0){
wcstombs(buffer, wbuffer, sizeof(buffer));
printf("indexed string 0x%02x: '%s'\n", index, buffer);
}
}
#endif
static void dump_info_string(int (*fun)(hid_device*, wchar_t*, size_t), const char* what, hid_device* device)
{
wchar_t wbuffer[512] = {0};
char buffer[1024] = {0};
int hret = fun(device, wbuffer, 511);
if(hret == 0){
wcstombs(buffer, wbuffer, sizeof(buffer));
printf("%s: '%s'\n", what, buffer);
}
}
#if 0
static void dumpbin(const char* label, const unsigned char* data, int length)
{
printf("%s:\n", label);
for(int i = 0; i < length; i++){
printf("%02x ", data[i]);
if((i % 16) == 15)
printf("\n");
}
printf("\n");
}
#endif
static hid_device* open_device_idx(int manufacturer, int product, int iface, int iface_tot, int device_index)
{
struct hid_device_info* devs = hid_enumerate(manufacturer, product);
struct hid_device_info* cur_dev = devs;
int idx = 0;
int iface_cur = 0;
hid_device* ret = NULL;
while (cur_dev) {
printf("%04x:%04x %s\n", manufacturer, product, cur_dev->path);
if(idx == device_index && iface == iface_cur){
ret = hid_open_path(cur_dev->path);
printf("opening\n");
}
cur_dev = cur_dev->next;
iface_cur++;
if(iface_cur >= iface_tot){
idx++;
iface_cur = 0;
}
}
hid_free_enumeration(devs);
return ret;
}
static ohmd_device* open_device(ohmd_driver* driver, ohmd_device_desc* desc)
{
vive_priv* priv = ohmd_alloc(driver->ctx, sizeof(vive_priv));
if(!priv)
return NULL;
int hret = 0;
priv->base.ctx = driver->ctx;
int idx = atoi(desc->path);
// Open the HMD device
priv->hmd_handle = open_device_idx(HTC_ID, VIVE_HMD, 0, 1, idx);
if(!priv->hmd_handle)
goto cleanup;
if(hid_set_nonblocking(priv->hmd_handle, 1) == -1){
ohmd_set_error(driver->ctx, "failed to set non-blocking on device");
goto cleanup;
}
// Open the lighthouse device
priv->imu_handle = open_device_idx(VALVE_ID, VIVE_LIGHTHOUSE_FPGA_RX, 0, 2, idx);
if(!priv->imu_handle)
goto cleanup;
if(hid_set_nonblocking(priv->imu_handle, 1) == -1){
ohmd_set_error(driver->ctx, "failed to set non-blocking on device");
goto cleanup;
}
dump_info_string(hid_get_manufacturer_string, "manufacturer", priv->hmd_handle);
dump_info_string(hid_get_product_string , "product", priv->hmd_handle);
dump_info_string(hid_get_serial_number_string, "serial number", priv->hmd_handle);
// turn the display on
hret = hid_send_feature_report(priv->hmd_handle, vive_magic_power_on, sizeof(vive_magic_power_on));
printf("power on magic: %d\n", hret);
// enable lighthouse
//hret = hid_send_feature_report(priv->hmd_handle, vive_magic_enable_lighthouse, sizeof(vive_magic_enable_lighthouse));
//printf("enable lighthouse magic: %d\n", hret);
// Set default device properties
ohmd_set_default_device_properties(&priv->base.properties);
// Set device properties TODO: Get from device
priv->base.properties.hsize = 0.122822f;
priv->base.properties.vsize = 0.068234f;
priv->base.properties.hres = 2160;
priv->base.properties.vres = 1200;
/*
// calculated from here: https://www.gamedev.net/topic/683698-projection-matrix-model-of-the-htc-vive/
priv->base.properties.lens_sep = 0.057863;
priv->base.properties.lens_vpos = 0.033896;
*/
// estimated 'by eye' on jsarret's vive
priv->base.properties.lens_sep = 0.056;
priv->base.properties.lens_vpos = 0.032;
float eye_to_screen_distance = 0.023226876441867737;
//priv->base.properties.fov = DEG_TO_RAD(111.435f); //TODO: Confirm exact mesurements
priv->base.properties.ratio = (2160.0f / 1200.0f) / 2.0f;
/*
ohmd_set_universal_distortion_k(&(priv->base.properties), 0.394119, -0.508383, 0.323322, 0.790942);
*/
ohmd_set_universal_distortion_k(&(priv->base.properties), 1.318397, -1.490242, 0.663824, 0.508021);
ohmd_set_universal_aberration_k(&(priv->base.properties), 1.00010147892f, 1.000f, 1.00019614479f);
// calculate projection eye projection matrices from the device properties
//ohmd_calc_default_proj_matrices(&priv->base.properties);
float l,r,t,b,n,f;
// left eye screen bounds
l = -1.0f * (priv->base.properties.hsize/2 - priv->base.properties.lens_sep/2);
r = priv->base.properties.lens_sep/2;
t = priv->base.properties.vsize - priv->base.properties.lens_vpos;
b = -1.0f * priv->base.properties.lens_vpos;
n = eye_to_screen_distance;
f = n*10e6;
//LOGD("l: %0.3f, r: %0.3f, b: %0.3f, t: %0.3f, n: %0.3f, f: %0.3f", l,r,b,t,n,f);
/* eye separation is handled by IPD in the Modelview matrix */
omat4x4f_init_frustum(&priv->base.properties.proj_left, l, r, b, t, n, f);
//right eye screen bounds
l = -1.0f * priv->base.properties.lens_sep/2;
r = priv->base.properties.hsize/2 - priv->base.properties.lens_sep/2;
n = eye_to_screen_distance;
f = n*10e6;
//LOGD("l: %0.3f, r: %0.3f, b: %0.3f, t: %0.3f, n: %0.3f, f: %0.3f", l,r,b,t,n,f);
/* eye separation is handled by IPD in the Modelview matrix */
omat4x4f_init_frustum(&priv->base.properties.proj_right, l, r, b, t, n, f);
priv->base.properties.fov = 2 * atan2f(
priv->base.properties.hsize/2 - priv->base.properties.lens_sep/2,
eye_to_screen_distance);
// set up device callbacks
priv->base.update = update_device;
priv->base.close = close_device;
priv->base.getf = getf;
ofusion_init(&priv->sensor_fusion);
ofq_init(&priv->gyro_q, 128);
return (ohmd_device*)priv;
cleanup:
if(priv)
free(priv);
return NULL;
}
static void get_device_list(ohmd_driver* driver, ohmd_device_list* list)
{
struct hid_device_info* devs = hid_enumerate(HTC_ID, VIVE_HMD);
struct hid_device_info* cur_dev = devs;
int idx = 0;
while (cur_dev) {
ohmd_device_desc* desc = &list->devices[list->num_devices++];
strcpy(desc->driver, "OpenHMD HTC Vive Driver");
strcpy(desc->vendor, "HTC/Valve");
strcpy(desc->product, "HTC Vive");
desc->revision = 0;
snprintf(desc->path, OHMD_STR_SIZE, "%d", idx);
desc->driver_ptr = driver;
cur_dev = cur_dev->next;
idx++;
}
hid_free_enumeration(devs);
}
static void destroy_driver(ohmd_driver* drv)
{
LOGD("shutting down HTC Vive driver");
free(drv);
}
ohmd_driver* ohmd_create_htc_vive_drv(ohmd_context* ctx)
{
ohmd_driver* drv = ohmd_alloc(ctx, sizeof(ohmd_driver));
if(!drv)
return NULL;
drv->get_device_list = get_device_list;
drv->open_device = open_device;
drv->destroy = destroy_driver;
drv->ctx = ctx;
return drv;
}

41
extern/openhmd/src/drv_htc_vive/vive.h vendored Normal file
View File

@@ -0,0 +1,41 @@
#ifndef VIVE_H
#define VIVE_H
#include <stdint.h>
#include <stdbool.h>
#include "../openhmdi.h"
#include "magic.h"
typedef enum
{
VIVE_CONFIG_DATA = 17,
VIVE_IRQ_SENSORS = 32,
} vive_irq_cmd;
typedef struct
{
int16_t acc[3];
int16_t rot[3];
uint32_t time_ticks;
uint8_t seq;
} vive_sensor_sample;
typedef struct
{
uint8_t report_id;
vive_sensor_sample samples[3];
} vive_sensor_packet;
typedef struct
{
uint8_t report_id;
uint16_t length;
unsigned char config_data[99999];
} vive_config_packet;
void vec3f_from_vive_vec(const int16_t* smp, vec3f* out_vec);
bool vive_decode_sensor_packet(vive_sensor_packet* pkt, const unsigned char* buffer, int size);
bool vive_decode_config_packet(vive_config_packet* pkt, const unsigned char* buffer, int size);
#endif

View File

@@ -0,0 +1,275 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Oculus Rift Driver - Packet Decoding and Utilities */
#include <stdio.h>
#include "rift.h"
#define SKIP_CMD (buffer++)
#define READ8 *(buffer++);
#define READ16 *buffer | (*(buffer + 1) << 8); buffer += 2;
#define READ32 *buffer | (*(buffer + 1) << 8) | (*(buffer + 2) << 16) | (*(buffer + 3) << 24); buffer += 4;
#define READFLOAT ((float)(*buffer)); buffer += 4;
#define READFIXED (float)(*buffer | (*(buffer + 1) << 8) | (*(buffer + 2) << 16) | (*(buffer + 3) << 24)) / 1000000.0f; buffer += 4;
#define WRITE8(_val) *(buffer++) = (_val);
#define WRITE16(_val) WRITE8((_val) & 0xff); WRITE8(((_val) >> 8) & 0xff);
#define WRITE32(_val) WRITE16((_val) & 0xffff) *buffer; WRITE16(((_val) >> 16) & 0xffff);
bool decode_sensor_range(pkt_sensor_range* range, const unsigned char* buffer, int size)
{
if(!(size == 8 || size == 9)){
LOGE("invalid packet size (expected 8 or 9 but got %d)", size);
return false;
}
SKIP_CMD;
range->command_id = READ16;
range->accel_scale = READ8;
range->gyro_scale = READ16;
range->mag_scale = READ16;
return true;
}
bool decode_sensor_display_info(pkt_sensor_display_info* info, const unsigned char* buffer, int size)
{
if(!(size == 56 || size == 57)){
LOGE("invalid packet size (expected 56 or 57 but got %d)", size);
return false;
}
SKIP_CMD;
info->command_id = READ16;
info->distortion_type = READ8;
info->h_resolution = READ16;
info->v_resolution = READ16;
info->h_screen_size = READFIXED;
info->v_screen_size = READFIXED;
info->v_center = READFIXED;
info->lens_separation = READFIXED;
info->eye_to_screen_distance[0] = READFIXED;
info->eye_to_screen_distance[1] = READFIXED;
info->distortion_type_opts = 0;
for(int i = 0; i < 6; i++){
info->distortion_k[i] = READFLOAT;
}
return true;
}
bool decode_sensor_config(pkt_sensor_config* config, const unsigned char* buffer, int size)
{
if(!(size == 7 || size == 8)){
LOGE("invalid packet size (expected 7 or 8 but got %d)", size);
return false;
}
SKIP_CMD;
config->command_id = READ16;
config->flags = READ8;
config->packet_interval = READ8;
config->keep_alive_interval = READ16;
return true;
}
static void decode_sample(const unsigned char* buffer, int32_t* smp)
{
/*
* Decode 3 tightly packed 21 bit values from 4 bytes.
* We unpack them in the higher 21 bit values first and then shift
* them down to the lower in order to get the sign bits correct.
*/
int x = (buffer[0] << 24) | (buffer[1] << 16) | ((buffer[2] & 0xF8) << 8);
int y = ((buffer[2] & 0x07) << 29) | (buffer[3] << 21) | (buffer[4] << 13) | ((buffer[5] & 0xC0) << 5);
int z = ((buffer[5] & 0x3F) << 26) | (buffer[6] << 18) | (buffer[7] << 10);
smp[0] = x >> 11;
smp[1] = y >> 11;
smp[2] = z >> 11;
}
bool decode_tracker_sensor_msg(pkt_tracker_sensor* msg, const unsigned char* buffer, int size)
{
if(!(size == 62 || size == 64)){
LOGE("invalid packet size (expected 62 or 64 but got %d)", size);
return false;
}
SKIP_CMD;
msg->num_samples = READ8;
msg->timestamp = READ16;
msg->timestamp *= 1000; // DK1 timestamps are in milliseconds
msg->last_command_id = READ16;
msg->temperature = READ16;
msg->num_samples = OHMD_MIN(msg->num_samples, 3);
for(int i = 0; i < msg->num_samples; i++){
decode_sample(buffer, msg->samples[i].accel);
buffer += 8;
decode_sample(buffer, msg->samples[i].gyro);
buffer += 8;
}
// Skip empty samples
buffer += (3 - msg->num_samples) * 16;
for(int i = 0; i < 3; i++){
msg->mag[i] = READ16;
}
return true;
}
bool decode_tracker_sensor_msg_dk2(pkt_tracker_sensor* msg, const unsigned char* buffer, int size)
{
if(!(size == 64)){
LOGE("invalid packet size (expected 62 or 64 but got %d)", size);
return false;
}
SKIP_CMD;
msg->last_command_id = READ16;
msg->num_samples = READ8;
/* Next is the number of samples since start, excluding the samples
contained in this packet */
buffer += 2; // unused: nb_samples_since_start
msg->temperature = READ16;
msg->timestamp = READ32;
/* Second sample value is junk (outdated/uninitialized) value if
num_samples < 2. */
msg->num_samples = OHMD_MIN(msg->num_samples, 2);
for(int i = 0; i < msg->num_samples; i++){
decode_sample(buffer, msg->samples[i].accel);
buffer += 8;
decode_sample(buffer, msg->samples[i].gyro);
buffer += 8;
}
// Skip empty samples
buffer += (2 - msg->num_samples) * 16;
for(int i = 0; i < 3; i++){
msg->mag[i] = READ16;
}
// TODO: positional tracking data and frame data
return true;
}
// TODO do we need to consider HMD vs sensor "centric" values
void vec3f_from_rift_vec(const int32_t* smp, vec3f* out_vec)
{
out_vec->x = (float)smp[0] * 0.0001f;
out_vec->y = (float)smp[1] * 0.0001f;
out_vec->z = (float)smp[2] * 0.0001f;
}
int encode_sensor_config(unsigned char* buffer, const pkt_sensor_config* config)
{
WRITE8(RIFT_CMD_SENSOR_CONFIG);
WRITE16(config->command_id);
WRITE8(config->flags);
WRITE8(config->packet_interval);
WRITE16(config->keep_alive_interval);
return 7; // sensor config packet size
}
int encode_keep_alive(unsigned char* buffer, const pkt_keep_alive* keep_alive)
{
WRITE8(RIFT_CMD_KEEP_ALIVE);
WRITE16(keep_alive->command_id);
WRITE16(keep_alive->keep_alive_interval);
return 5; // keep alive packet size
}
int encode_enable_components(unsigned char* buffer, bool display, bool audio)
{
uint8_t flags = 0;
WRITE8(RIFT_CMD_ENABLE_COMPONENTS);
WRITE16(0); // last command ID
if (display)
flags |= 1;
if (audio)
flags |= 2;
// flags |= 4; // I don't know what it is. Wireless?
WRITE8(flags);
return 4;
}
void dump_packet_sensor_range(const pkt_sensor_range* range)
{
(void)range;
LOGD("sensor range\n");
LOGD(" command id: %d", range->command_id);
LOGD(" accel scale: %d", range->accel_scale);
LOGD(" gyro scale: %d", range->gyro_scale);
LOGD(" mag scale: %d", range->mag_scale);
}
void dump_packet_sensor_display_info(const pkt_sensor_display_info* info)
{
(void)info;
LOGD("display info");
LOGD(" command id: %d", info->command_id);
LOGD(" distortion_type: %d", info->distortion_type);
LOGD(" resolution: %d x %d", info->h_resolution, info->v_resolution);
LOGD(" screen size: %f x %f", info->h_screen_size, info->v_screen_size);
LOGD(" vertical center: %f", info->v_center);
LOGD(" lens_separation: %f", info->lens_separation);
LOGD(" eye_to_screen_distance: %f, %f", info->eye_to_screen_distance[0], info->eye_to_screen_distance[1]);
LOGD(" distortion_k: %f, %f, %f, %f, %f, %f",
info->distortion_k[0], info->distortion_k[1], info->distortion_k[2],
info->distortion_k[3], info->distortion_k[4], info->distortion_k[5]);
}
void dump_packet_sensor_config(const pkt_sensor_config* config)
{
(void)config;
LOGD("sensor config");
LOGD(" command id: %u", config->command_id);
LOGD(" flags: %02x", config->flags);
LOGD(" raw mode: %d", !!(config->flags & RIFT_SCF_RAW_MODE));
LOGD(" calibration test: %d", !!(config->flags & RIFT_SCF_CALIBRATION_TEST));
LOGD(" use calibration: %d", !!(config->flags & RIFT_SCF_USE_CALIBRATION));
LOGD(" auto calibration: %d", !!(config->flags & RIFT_SCF_AUTO_CALIBRATION));
LOGD(" motion keep alive: %d", !!(config->flags & RIFT_SCF_MOTION_KEEP_ALIVE));
LOGD(" motion command keep alive: %d", !!(config->flags & RIFT_SCF_COMMAND_KEEP_ALIVE));
LOGD(" sensor coordinates: %d", !!(config->flags & RIFT_SCF_SENSOR_COORDINATES));
LOGD(" packet interval: %u", config->packet_interval);
LOGD(" keep alive interval: %u", config->keep_alive_interval);
}
void dump_packet_tracker_sensor(const pkt_tracker_sensor* sensor)
{
(void)sensor;
LOGD("tracker sensor:");
LOGD(" last command id: %u", sensor->last_command_id);
LOGD(" timestamp: %u", sensor->timestamp);
LOGD(" temperature: %d", sensor->temperature);
LOGD(" num samples: %u", sensor->num_samples);
LOGD(" magnetic field: %i %i %i", sensor->mag[0], sensor->mag[1], sensor->mag[2]);
for(int i = 0; i < sensor->num_samples; i++){
LOGD(" accel: %d %d %d", sensor->samples[i].accel[0], sensor->samples[i].accel[1], sensor->samples[i].accel[2]);
LOGD(" gyro: %d %d %d", sensor->samples[i].gyro[0], sensor->samples[i].gyro[1], sensor->samples[i].gyro[2]);
}
}

View File

@@ -0,0 +1,456 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Oculus Rift Driver - HID/USB Driver Implementation */
#include <stdlib.h>
#include <hidapi.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <assert.h>
#include "rift.h"
#define TICK_LEN (1.0f / 1000.0f) // 1000 Hz ticks
#define KEEP_ALIVE_VALUE (10 * 1000)
#define SETFLAG(_s, _flag, _val) (_s) = ((_s) & ~(_flag)) | ((_val) ? (_flag) : 0)
typedef struct {
ohmd_device base;
hid_device* handle;
pkt_sensor_range sensor_range;
pkt_sensor_display_info display_info;
rift_coordinate_frame coordinate_frame, hw_coordinate_frame;
pkt_sensor_config sensor_config;
pkt_tracker_sensor sensor;
uint32_t last_imu_timestamp;
double last_keep_alive;
fusion sensor_fusion;
vec3f raw_mag, raw_accel, raw_gyro;
} rift_priv;
typedef enum {
REV_DK1,
REV_DK2,
REV_CV1
} rift_revision;
typedef struct {
const char* name;
int id;
int iface;
rift_revision rev;
} rift_devices;
static rift_priv* rift_priv_get(ohmd_device* device)
{
return (rift_priv*)device;
}
static int get_feature_report(rift_priv* priv, rift_sensor_feature_cmd cmd, unsigned char* buf)
{
memset(buf, 0, FEATURE_BUFFER_SIZE);
buf[0] = (unsigned char)cmd;
return hid_get_feature_report(priv->handle, buf, FEATURE_BUFFER_SIZE);
}
static int send_feature_report(rift_priv* priv, const unsigned char *data, size_t length)
{
return hid_send_feature_report(priv->handle, data, length);
}
static void set_coordinate_frame(rift_priv* priv, rift_coordinate_frame coordframe)
{
priv->coordinate_frame = coordframe;
// set the RIFT_SCF_SENSOR_COORDINATES in the sensor config to match whether coordframe is hmd or sensor
SETFLAG(priv->sensor_config.flags, RIFT_SCF_SENSOR_COORDINATES, coordframe == RIFT_CF_SENSOR);
// encode send the new config to the Rift
unsigned char buf[FEATURE_BUFFER_SIZE];
int size = encode_sensor_config(buf, &priv->sensor_config);
if(send_feature_report(priv, buf, size) == -1){
ohmd_set_error(priv->base.ctx, "send_feature_report failed in set_coordinate frame");
return;
}
// read the state again, set the hw_coordinate_frame to match what
// the hardware actually is set to just incase it doesn't stick.
size = get_feature_report(priv, RIFT_CMD_SENSOR_CONFIG, buf);
if(size <= 0){
LOGW("could not set coordinate frame");
priv->hw_coordinate_frame = RIFT_CF_HMD;
return;
}
decode_sensor_config(&priv->sensor_config, buf, size);
priv->hw_coordinate_frame = (priv->sensor_config.flags & RIFT_SCF_SENSOR_COORDINATES) ? RIFT_CF_SENSOR : RIFT_CF_HMD;
if(priv->hw_coordinate_frame != coordframe) {
LOGW("coordinate frame didn't stick");
}
}
static void handle_tracker_sensor_msg(rift_priv* priv, unsigned char* buffer, int size)
{
if (buffer[0] == RIFT_IRQ_SENSORS
&& !decode_tracker_sensor_msg(&priv->sensor, buffer, size)){
LOGE("couldn't decode tracker sensor message");
}
if (buffer[0] == RIFT_IRQ_SENSORS_DK2
&& !decode_tracker_sensor_msg_dk2(&priv->sensor, buffer, size)){
LOGE("couldn't decode tracker sensor message");
}
pkt_tracker_sensor* s = &priv->sensor;
dump_packet_tracker_sensor(s);
int32_t mag32[] = { s->mag[0], s->mag[1], s->mag[2] };
vec3f_from_rift_vec(mag32, &priv->raw_mag);
// TODO: handle overflows in a nicer way
float dt = TICK_LEN; // TODO: query the Rift for the sample rate
if (s->timestamp > priv->last_imu_timestamp)
{
dt = (s->timestamp - priv->last_imu_timestamp) / 1000000.0f;
dt -= (s->num_samples - 1) * TICK_LEN; // TODO: query the Rift for the sample rate
}
for(int i = 0; i < s->num_samples; i++){
vec3f_from_rift_vec(s->samples[i].accel, &priv->raw_accel);
vec3f_from_rift_vec(s->samples[i].gyro, &priv->raw_gyro);
ofusion_update(&priv->sensor_fusion, dt, &priv->raw_gyro, &priv->raw_accel, &priv->raw_mag);
dt = TICK_LEN; // TODO: query the Rift for the sample rate
}
priv->last_imu_timestamp = s->timestamp;
}
static void update_device(ohmd_device* device)
{
rift_priv* priv = rift_priv_get(device);
unsigned char buffer[FEATURE_BUFFER_SIZE];
// Handle keep alive messages
double t = ohmd_get_tick();
if(t - priv->last_keep_alive >= (double)priv->sensor_config.keep_alive_interval / 1000.0 - .2){
// send keep alive message
pkt_keep_alive keep_alive = { 0, priv->sensor_config.keep_alive_interval };
int ka_size = encode_keep_alive(buffer, &keep_alive);
if (send_feature_report(priv, buffer, ka_size) == -1)
LOGE("error sending keepalive");
// Update the time of the last keep alive we have sent.
priv->last_keep_alive = t;
}
// Read all the messages from the device.
while(true){
int size = hid_read(priv->handle, buffer, FEATURE_BUFFER_SIZE);
if(size < 0){
LOGE("error reading from device");
return;
} else if(size == 0) {
return; // No more messages, return.
}
// currently the only message type the hardware supports (I think)
if(buffer[0] == RIFT_IRQ_SENSORS || buffer[0] == RIFT_IRQ_SENSORS_DK2) {
handle_tracker_sensor_msg(priv, buffer, size);
}else{
LOGE("unknown message type: %u", buffer[0]);
}
}
}
static int getf(ohmd_device* device, ohmd_float_value type, float* out)
{
rift_priv* priv = rift_priv_get(device);
switch(type){
case OHMD_DISTORTION_K: {
for (int i = 0; i < 6; i++) {
out[i] = priv->display_info.distortion_k[i];
}
break;
}
case OHMD_ROTATION_QUAT: {
*(quatf*)out = priv->sensor_fusion.orient;
break;
}
case OHMD_POSITION_VECTOR:
out[0] = out[1] = out[2] = 0;
break;
default:
ohmd_set_error(priv->base.ctx, "invalid type given to getf (%ud)", type);
return -1;
break;
}
return 0;
}
static void close_device(ohmd_device* device)
{
LOGD("closing device");
rift_priv* priv = rift_priv_get(device);
hid_close(priv->handle);
free(priv);
}
#ifndef _MSC_VER
static char* _hid_to_unix_path(char* path)
{
char bus [4];
char dev [4];
char *result = malloc( sizeof(char) * ( 20 + 1 ) );
sprintf (bus, "%.*s\n", 4, path);
sprintf (dev, "%.*s\n", 4, path + 5);
sprintf (result, "/dev/bus/usb/%03d/%03d",
(int)strtol(bus, NULL, 16),
(int)strtol(dev, NULL, 16));
return result;
}
#else
static char* _hid_to_unix_path(char* path)
{
return path;
}
#endif
static ohmd_device* open_device(ohmd_driver* driver, ohmd_device_desc* desc)
{
rift_priv* priv = ohmd_alloc(driver->ctx, sizeof(rift_priv));
if(!priv)
goto cleanup;
priv->last_imu_timestamp = -1;
priv->base.ctx = driver->ctx;
ohmd_toggle_ovr_service(0); //disable OVRService if running
// Open the HID device
priv->handle = hid_open_path(desc->path);
if(!priv->handle) {
char* path = _hid_to_unix_path(desc->path);
ohmd_set_error(driver->ctx, "Could not open %s. "
"Check your rights.", path);
#ifndef _MSC_VER
free(path);
#endif
goto cleanup;
}
if(hid_set_nonblocking(priv->handle, 1) == -1){
ohmd_set_error(driver->ctx, "failed to set non-blocking on device");
goto cleanup;
}
unsigned char buf[FEATURE_BUFFER_SIZE];
int size;
// Read and decode the sensor range
size = get_feature_report(priv, RIFT_CMD_RANGE, buf);
decode_sensor_range(&priv->sensor_range, buf, size);
dump_packet_sensor_range(&priv->sensor_range);
// Read and decode display information
size = get_feature_report(priv, RIFT_CMD_DISPLAY_INFO, buf);
decode_sensor_display_info(&priv->display_info, buf, size);
dump_packet_sensor_display_info(&priv->display_info);
// Read and decode the sensor config
size = get_feature_report(priv, RIFT_CMD_SENSOR_CONFIG, buf);
decode_sensor_config(&priv->sensor_config, buf, size);
dump_packet_sensor_config(&priv->sensor_config);
// if the sensor has display info data, use HMD coordinate frame
priv->coordinate_frame = priv->display_info.distortion_type != RIFT_DT_NONE ? RIFT_CF_HMD : RIFT_CF_SENSOR;
// enable calibration
SETFLAG(priv->sensor_config.flags, RIFT_SCF_USE_CALIBRATION, 1);
SETFLAG(priv->sensor_config.flags, RIFT_SCF_AUTO_CALIBRATION, 1);
// apply sensor config
set_coordinate_frame(priv, priv->coordinate_frame);
// Turn the screens on
if (desc->revision == REV_CV1)
{
size = encode_enable_components(buf, true, true);
if (send_feature_report(priv, buf, size) == -1)
LOGE("error turning the screens on");
}
// set keep alive interval to n seconds
pkt_keep_alive keep_alive = { 0, KEEP_ALIVE_VALUE };
size = encode_keep_alive(buf, &keep_alive);
if (send_feature_report(priv, buf, size) == -1)
LOGE("error setting up keepalive");
// Update the time of the last keep alive we have sent.
priv->last_keep_alive = ohmd_get_tick();
// update sensor settings with new keep alive value
// (which will have been ignored in favor of the default 1000 ms one)
size = get_feature_report(priv, RIFT_CMD_SENSOR_CONFIG, buf);
decode_sensor_config(&priv->sensor_config, buf, size);
dump_packet_sensor_config(&priv->sensor_config);
// Set default device properties
ohmd_set_default_device_properties(&priv->base.properties);
// Set device properties
priv->base.properties.hsize = priv->display_info.h_screen_size;
priv->base.properties.vsize = priv->display_info.v_screen_size;
priv->base.properties.hres = priv->display_info.h_resolution;
priv->base.properties.vres = priv->display_info.v_resolution;
priv->base.properties.lens_sep = priv->display_info.lens_separation;
priv->base.properties.lens_vpos = priv->display_info.v_center;
priv->base.properties.ratio = ((float)priv->display_info.h_resolution / (float)priv->display_info.v_resolution) / 2.0f;
//setup generic distortion coeffs, from hand-calibration
switch (desc->revision) {
case REV_DK2:
ohmd_set_universal_distortion_k(&(priv->base.properties), 0.247, -0.145, 0.103, 0.795);
ohmd_set_universal_aberration_k(&(priv->base.properties), 0.985, 1.000, 1.015);
break;
case REV_DK1:
ohmd_set_universal_distortion_k(&(priv->base.properties), 1.003, -1.005, 0.403, 0.599);
ohmd_set_universal_aberration_k(&(priv->base.properties), 0.985, 1.000, 1.015);
break;
case REV_CV1:
ohmd_set_universal_distortion_k(&(priv->base.properties), 0.098, .324, -0.241, 0.819);
ohmd_set_universal_aberration_k(&(priv->base.properties), 0.9952420, 1.0, 1.0008074);
/* CV1 reports IPD, but not lens center, at least not anywhere I could find, so use the manually measured value of 0.054 */
priv->display_info.lens_separation = 0.054;
priv->base.properties.lens_sep = priv->display_info.lens_separation;
default:
break;
}
// calculate projection eye projection matrices from the device properties
//ohmd_calc_default_proj_matrices(&priv->base.properties);
float l,r,t,b,n,f;
// left eye screen bounds
l = -1.0f * (priv->display_info.h_screen_size/2 - priv->display_info.lens_separation/2);
r = priv->display_info.lens_separation/2;
t = priv->display_info.v_screen_size - priv->display_info.v_center;
b = -1.0f * priv->display_info.v_center;
n = priv->display_info.eye_to_screen_distance[0];
f = n*10e6;
//LOGD("l: %0.3f, r: %0.3f, b: %0.3f, t: %0.3f, n: %0.3f, f: %0.3f", l,r,b,t,n,f);
/* eye separation is handled by IPD in the Modelview matrix */
omat4x4f_init_frustum(&priv->base.properties.proj_left, l, r, b, t, n, f);
//right eye screen bounds
l = -1.0f * priv->display_info.lens_separation/2;
r = priv->display_info.h_screen_size/2 - priv->display_info.lens_separation/2;
n = priv->display_info.eye_to_screen_distance[1];
f = n*10e6;
//LOGD("l: %0.3f, r: %0.3f, b: %0.3f, t: %0.3f, n: %0.3f, f: %0.3f", l,r,b,t,n,f);
/* eye separation is handled by IPD in the Modelview matrix */
omat4x4f_init_frustum(&priv->base.properties.proj_right, l, r, b, t, n, f);
priv->base.properties.fov = 2 * atan2f(
priv->display_info.h_screen_size/2 - priv->display_info.lens_separation/2,
priv->display_info.eye_to_screen_distance[0]);
// set up device callbacks
priv->base.update = update_device;
priv->base.close = close_device;
priv->base.getf = getf;
// initialize sensor fusion
ofusion_init(&priv->sensor_fusion);
return &priv->base;
cleanup:
if(priv)
free(priv);
return NULL;
}
#define OCULUS_VR_INC_ID 0x2833
#define RIFT_ID_COUNT 4
static void get_device_list(ohmd_driver* driver, ohmd_device_list* list)
{
// enumerate HID devices and add any Rifts found to the device list
rift_devices rd[RIFT_ID_COUNT] = {
{ "Rift (DK1)", 0x0001, -1, REV_DK1 },
{ "Rift (DK2)", 0x0021, -1, REV_DK2 },
{ "Rift (DK2)", 0x2021, -1, REV_DK2 },
{ "Rift (CV1)", 0x0031, 0, REV_CV1 },
};
for(int i = 0; i < RIFT_ID_COUNT; i++){
struct hid_device_info* devs = hid_enumerate(OCULUS_VR_INC_ID, rd[i].id);
struct hid_device_info* cur_dev = devs;
if(devs == NULL)
continue;
while (cur_dev) {
if(rd[i].iface == -1 || cur_dev->interface_number == rd[i].iface){
ohmd_device_desc* desc = &list->devices[list->num_devices++];
strcpy(desc->driver, "OpenHMD Rift Driver");
strcpy(desc->vendor, "Oculus VR, Inc.");
strcpy(desc->product, rd[i].name);
desc->revision = rd[i].rev;
strcpy(desc->path, cur_dev->path);
desc->driver_ptr = driver;
}
cur_dev = cur_dev->next;
}
hid_free_enumeration(devs);
}
}
static void destroy_driver(ohmd_driver* drv)
{
LOGD("shutting down driver");
hid_exit();
free(drv);
ohmd_toggle_ovr_service(1); //re-enable OVRService if previously running
}
ohmd_driver* ohmd_create_oculus_rift_drv(ohmd_context* ctx)
{
ohmd_driver* drv = ohmd_alloc(ctx, sizeof(ohmd_driver));
if(drv == NULL)
return NULL;
drv->get_device_list = get_device_list;
drv->open_device = open_device;
drv->destroy = destroy_driver;
drv->ctx = ctx;
return drv;
}

View File

@@ -0,0 +1,115 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Oculus Rift Driver Internal Interface */
#ifndef RIFT_H
#define RIFT_H
#include "../openhmdi.h"
#define FEATURE_BUFFER_SIZE 256
typedef enum {
RIFT_CMD_SENSOR_CONFIG = 2,
RIFT_CMD_RANGE = 4,
RIFT_CMD_KEEP_ALIVE = 8,
RIFT_CMD_DISPLAY_INFO = 9,
RIFT_CMD_ENABLE_COMPONENTS = 0x1d
} rift_sensor_feature_cmd;
typedef enum {
RIFT_CF_SENSOR,
RIFT_CF_HMD
} rift_coordinate_frame;
typedef enum {
RIFT_IRQ_SENSORS = 1,
RIFT_IRQ_SENSORS_DK2 = 11
} rift_irq_cmd;
typedef enum {
RIFT_DT_NONE,
RIFT_DT_SCREEN_ONLY,
RIFT_DT_DISTORTION
} rift_distortion_type;
// Sensor config flags
#define RIFT_SCF_RAW_MODE 0x01
#define RIFT_SCF_CALIBRATION_TEST 0x02
#define RIFT_SCF_USE_CALIBRATION 0x04
#define RIFT_SCF_AUTO_CALIBRATION 0x08
#define RIFT_SCF_MOTION_KEEP_ALIVE 0x10
#define RIFT_SCF_COMMAND_KEEP_ALIVE 0x20
#define RIFT_SCF_SENSOR_COORDINATES 0x40
typedef struct {
uint16_t command_id;
uint16_t accel_scale;
uint16_t gyro_scale;
uint16_t mag_scale;
} pkt_sensor_range;
typedef struct {
int32_t accel[3];
int32_t gyro[3];
} pkt_tracker_sample;
typedef struct {
uint8_t num_samples;
uint32_t timestamp;
uint16_t last_command_id;
int16_t temperature;
pkt_tracker_sample samples[3];
int16_t mag[3];
} pkt_tracker_sensor;
typedef struct {
uint16_t command_id;
uint8_t flags;
uint16_t packet_interval;
uint16_t keep_alive_interval; // in ms
} pkt_sensor_config;
typedef struct {
uint16_t command_id;
rift_distortion_type distortion_type;
uint8_t distortion_type_opts;
uint16_t h_resolution, v_resolution;
float h_screen_size, v_screen_size;
float v_center;
float lens_separation;
float eye_to_screen_distance[2];
float distortion_k[6];
} pkt_sensor_display_info;
typedef struct {
uint16_t command_id;
uint16_t keep_alive_interval;
} pkt_keep_alive;
bool decode_sensor_range(pkt_sensor_range* range, const unsigned char* buffer, int size);
bool decode_sensor_display_info(pkt_sensor_display_info* info, const unsigned char* buffer, int size);
bool decode_sensor_config(pkt_sensor_config* config, const unsigned char* buffer, int size);
bool decode_tracker_sensor_msg(pkt_tracker_sensor* msg, const unsigned char* buffer, int size);
bool decode_tracker_sensor_msg_dk2(pkt_tracker_sensor* msg, const unsigned char* buffer, int size);
void vec3f_from_rift_vec(const int32_t* smp, vec3f* out_vec);
int encode_sensor_config(unsigned char* buffer, const pkt_sensor_config* config);
int encode_keep_alive(unsigned char* buffer, const pkt_keep_alive* keep_alive);
int encode_enable_components(unsigned char* buffer, bool display, bool audio);
void dump_packet_sensor_range(const pkt_sensor_range* range);
void dump_packet_sensor_config(const pkt_sensor_config* config);
void dump_packet_sensor_display_info(const pkt_sensor_display_info* info);
void dump_packet_tracker_sensor(const pkt_tracker_sensor* sensor);
#endif

53
extern/openhmd/src/drv_psvr/packet.c vendored Normal file
View File

@@ -0,0 +1,53 @@
#include "psvr.h"
#ifdef _MSC_VER
#define inline __inline
#endif
inline static uint8_t read8(const unsigned char** buffer)
{
uint8_t ret = **buffer;
*buffer += 1;
return ret;
}
inline static int16_t read16(const unsigned char** buffer)
{
int16_t ret = **buffer | (*(*buffer + 1) << 8);
*buffer += 2;
return ret;
}
inline static uint32_t read32(const unsigned char** buffer)
{
uint32_t ret = **buffer | (*(*buffer + 1) << 8) | (*(*buffer + 2) << 16) | (*(*buffer + 3) << 24);
*buffer += 4;
return ret;
}
bool psvr_decode_sensor_packet(psvr_sensor_packet* pkt, const unsigned char* buffer, int size)
{
if(size != 64){
LOGE("invalid psvr sensor packet size (expected 64 but got %d)", size);
return false;
}
buffer += 2; //skip 2
pkt->samples[0].volume = read16(&buffer); //volume
buffer += 12; //unknown, skip 12
pkt->samples[0].tick = read32(&buffer); //TICK
// acceleration
for(int i = 0; i < 3; i++){
pkt->samples[0].gyro[i] = read16(&buffer);
}
// rotation
for(int i = 0; i < 3; i++){
pkt->samples[0].accel[i] = read16(&buffer);
}//34
buffer += 23; //probably other sample somewhere
pkt->samples[0].proximity = read8(&buffer); //255 for close
pkt->samples[0].proximity_state = read8(&buffer); // 0 (nothing) to 3 (headset is on)
return true;
}

296
extern/openhmd/src/drv_psvr/psvr.c vendored Normal file
View File

@@ -0,0 +1,296 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Sony PSVR Driver */
#define FEATURE_BUFFER_SIZE 256
#define TICK_LEN (1.0f / 1000000.0f) // 1000 Hz ticks
#define SONY_ID 0x054c
#define PSVR_HMD 0x09af
#include <string.h>
#include <wchar.h>
#include <hidapi.h>
#include <assert.h>
#include <limits.h>
#include <stdint.h>
#include <stdbool.h>
#include "psvr.h"
typedef struct {
ohmd_device base;
hid_device* hmd_handle;
hid_device* hmd_control;
fusion sensor_fusion;
vec3f raw_accel, raw_gyro;
uint32_t last_ticks;
uint8_t last_seq;
psvr_sensor_packet sensor;
} psvr_priv;
void vec3f_from_psvr_vec(const int16_t* smp, vec3f* out_vec)
{
out_vec->x = (float)smp[1] * 0.001f;
out_vec->y = (float)smp[0] * 0.001f;
out_vec->z = (float)smp[2] * 0.001f * -1.0f;
}
static void handle_tracker_sensor_msg(psvr_priv* priv, unsigned char* buffer, int size)
{
uint32_t last_sample_tick = priv->sensor.tick;
if(!psvr_decode_sensor_packet(&priv->sensor, buffer, size)){
LOGE("couldn't decode tracker sensor message");
}
psvr_sensor_packet* s = &priv->sensor;
uint32_t tick_delta = 1000;
if(last_sample_tick > 0) //startup correction
tick_delta = s->tick - last_sample_tick;
float dt = tick_delta * TICK_LEN;
vec3f mag = {{0.0f, 0.0f, 0.0f}};
for(int i = 0; i < 1; i++){ //just use 1 sample since we don't have sample order for frame
vec3f_from_psvr_vec(s->samples[i].accel, &priv->raw_accel);
vec3f_from_psvr_vec(s->samples[i].gyro, &priv->raw_gyro);
ofusion_update(&priv->sensor_fusion, dt, &priv->raw_gyro, &priv->raw_accel, &mag);
// reset dt to tick_len for the last samples if there were more than one sample
dt = TICK_LEN;
}
}
static void update_device(ohmd_device* device)
{
psvr_priv* priv = (psvr_priv*)device;
int size = 0;
unsigned char buffer[FEATURE_BUFFER_SIZE];
while(true){
int size = hid_read(priv->hmd_handle, buffer, FEATURE_BUFFER_SIZE);
if(size < 0){
LOGE("error reading from device");
return;
} else if(size == 0) {
return; // No more messages, return.
}
// currently the only message type the hardware supports (I think)
if(buffer[0] == PSVR_IRQ_SENSORS){
handle_tracker_sensor_msg(priv, buffer, size);
}else if (buffer[0] == PSVR_IRQ_VOLUME_PLUS){
//TODO implement
}else if (buffer[0] == PSVR_IRQ_VOLUME_MINUS){
//TODO implement
}else if (buffer[0] == PSVR_IRQ_MIC_MUTE){
//TODO implement
}else{
LOGE("unknown message type: %u", buffer[0]);
}
}
if(size < 0){
LOGE("error reading from device");
}
}
static int getf(ohmd_device* device, ohmd_float_value type, float* out)
{
psvr_priv* priv = (psvr_priv*)device;
switch(type){
case OHMD_ROTATION_QUAT:
*(quatf*)out = priv->sensor_fusion.orient;
break;
case OHMD_POSITION_VECTOR:
out[0] = out[1] = out[2] = 0;
break;
case OHMD_DISTORTION_K:
// TODO this should be set to the equivalent of no distortion
memset(out, 0, sizeof(float) * 6);
break;
default:
ohmd_set_error(priv->base.ctx, "invalid type given to getf (%ud)", type);
return -1;
break;
}
return 0;
}
static void close_device(ohmd_device* device)
{
psvr_priv* priv = (psvr_priv*)device;
LOGD("closing HTC PSVR device");
hid_close(priv->hmd_handle);
hid_close(priv->hmd_control);
free(device);
}
static hid_device* open_device_idx(int manufacturer, int product, int iface, int iface_tot, int device_index)
{
struct hid_device_info* devs = hid_enumerate(manufacturer, product);
struct hid_device_info* cur_dev = devs;
int idx = 0;
int iface_cur = 0;
hid_device* ret = NULL;
while (cur_dev) {
printf("%04x:%04x %s\n", (unsigned int)manufacturer, (unsigned int)product, cur_dev->path);
if(idx == device_index && iface == iface_cur){
ret = hid_open_path(cur_dev->path);
printf("opening\n");
}
cur_dev = cur_dev->next;
iface_cur++;
if(iface_cur >= iface_tot){
idx++;
iface_cur = 0;
}
}
hid_free_enumeration(devs);
return ret;
}
static ohmd_device* open_device(ohmd_driver* driver, ohmd_device_desc* desc)
{
psvr_priv* priv = ohmd_alloc(driver->ctx, sizeof(psvr_priv));
if(!priv)
return NULL;
priv->base.ctx = driver->ctx;
int idx = atoi(desc->path);
// Open the HMD device
priv->hmd_handle = open_device_idx(SONY_ID, PSVR_HMD, 0, 0, idx);
if(!priv->hmd_handle)
goto cleanup;
if(hid_set_nonblocking(priv->hmd_handle, 1) == -1){
ohmd_set_error(driver->ctx, "failed to set non-blocking on device");
goto cleanup;
}
// Open the HMD Control device
priv->hmd_control = open_device_idx(SONY_ID, PSVR_HMD, 0, 0, 1);
if(!priv->hmd_control)
goto cleanup;
if(hid_set_nonblocking(priv->hmd_control, 1) == -1){
ohmd_set_error(driver->ctx, "failed to set non-blocking on device");
goto cleanup;
}
// turn the display on
hid_write(priv->hmd_control, psvr_power_on, sizeof(psvr_power_on));
// set VR mode for the hmd
hid_write(priv->hmd_control, psvr_vrmode_on, sizeof(psvr_vrmode_on));
// Set default device properties
ohmd_set_default_device_properties(&priv->base.properties);
// Set device properties TODO: Get from device
priv->base.properties.hsize = 0.126; //from calculated specs
priv->base.properties.vsize = 0.071; //from calculated specs
priv->base.properties.hres = 1920;
priv->base.properties.vres = 1080;
priv->base.properties.lens_sep = 0.063500;
priv->base.properties.lens_vpos = 0.049694;
priv->base.properties.fov = DEG_TO_RAD(103.57f); //TODO: Confirm exact mesurements
priv->base.properties.ratio = (1920.0f / 1080.0f) / 2.0f;
// calculate projection eye projection matrices from the device properties
ohmd_calc_default_proj_matrices(&priv->base.properties);
// set up device callbacks
priv->base.update = update_device;
priv->base.close = close_device;
priv->base.getf = getf;
ofusion_init(&priv->sensor_fusion);
return (ohmd_device*)priv;
cleanup:
if(priv)
free(priv);
return NULL;
}
static void get_device_list(ohmd_driver* driver, ohmd_device_list* list)
{
struct hid_device_info* devs = hid_enumerate(SONY_ID, PSVR_HMD);
struct hid_device_info* cur_dev = devs;
int idx = 0;
while (cur_dev) {
ohmd_device_desc* desc = &list->devices[list->num_devices++];
strcpy(desc->driver, "OpenHMD Sony PSVR Driver");
strcpy(desc->vendor, "Sony");
strcpy(desc->product, "PSVR");
desc->revision = 0;
snprintf(desc->path, OHMD_STR_SIZE, "%d", idx);
desc->driver_ptr = driver;
cur_dev = cur_dev->next;
idx++;
}
hid_free_enumeration(devs);
}
static void destroy_driver(ohmd_driver* drv)
{
LOGD("shutting down Sony PSVR driver");
free(drv);
}
ohmd_driver* ohmd_create_psvr_drv(ohmd_context* ctx)
{
ohmd_driver* drv = ohmd_alloc(ctx, sizeof(ohmd_driver));
if(!drv)
return NULL;
drv->get_device_list = get_device_list;
drv->open_device = open_device;
drv->destroy = destroy_driver;
drv->ctx = ctx;
return drv;
}

48
extern/openhmd/src/drv_psvr/psvr.h vendored Normal file
View File

@@ -0,0 +1,48 @@
#ifndef PSVR_H
#define PSVR_H
#include <stdint.h>
#include <stdbool.h>
#include "../openhmdi.h"
typedef enum
{
PSVR_IRQ_SENSORS = 0,
PSVR_IRQ_VOLUME_PLUS = 2,
PSVR_IRQ_VOLUME_MINUS = 4,
PSVR_IRQ_MIC_MUTE = 8
} psvr_irq_cmd;
typedef struct
{
int16_t accel[3];
int16_t gyro[3];
uint32_t tick;
uint8_t seq;
uint8_t volume;
uint8_t proximity;
uint8_t proximity_state;
} psvr_sensor_sample;
typedef struct
{
uint8_t report_id;
uint32_t tick;
psvr_sensor_sample samples[1];
} psvr_sensor_packet;
static const unsigned char psvr_vrmode_on[12] = {
0x11, 0x00, 0xaa, 0x08, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00
};
static const unsigned char psvr_power_on[8] = {
0x17, 0x76, 0xaa, 0x04, 0x01, 0x00, 0x00, 0x00
};
void vec3f_from_psvr_vec(const int16_t* smp, vec3f* out_vec);
bool psvr_decode_sensor_packet(psvr_sensor_packet* pkt, const unsigned char* buffer, int size);
#endif

126
extern/openhmd/src/fusion.c vendored Normal file
View File

@@ -0,0 +1,126 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Sensor Fusion Implementation */
#include <string.h>
#include "openhmdi.h"
void ofusion_init(fusion* me)
{
memset(me, 0, sizeof(fusion));
me->orient.w = 1.0f;
ofq_init(&me->mag_fq, 20);
ofq_init(&me->accel_fq, 20);
ofq_init(&me->ang_vel_fq, 20);
me->flags = FF_USE_GRAVITY;
me->grav_gain = 0.05f;
}
void ofusion_update(fusion* me, float dt, const vec3f* ang_vel, const vec3f* accel, const vec3f* mag)
{
me->ang_vel = *ang_vel;
me->accel = *accel;
me->raw_mag = *mag;
me->mag = *mag;
vec3f world_accel;
oquatf_get_rotated(&me->orient, accel, &world_accel);
me->iterations += 1;
me->time += dt;
ofq_add(&me->mag_fq, mag);
ofq_add(&me->accel_fq, &world_accel);
ofq_add(&me->ang_vel_fq, ang_vel);
float ang_vel_length = ovec3f_get_length(ang_vel);
if(ang_vel_length > 0.0001f){
vec3f rot_axis =
{{ ang_vel->x / ang_vel_length, ang_vel->y / ang_vel_length, ang_vel->z / ang_vel_length }};
float rot_angle = ang_vel_length * dt;
quatf delta_orient;
oquatf_init_axis(&delta_orient, &rot_axis, rot_angle);
oquatf_mult_me(&me->orient, &delta_orient);
}
// gravity correction
if(me->flags & FF_USE_GRAVITY){
const float gravity_tolerance = .4f, ang_vel_tolerance = .1f;
const float min_tilt_error = 0.05f, max_tilt_error = 0.01f;
// if the device is within tolerance levels, count this as the device is level and add to the counter
// otherwise reset the counter and start over
me->device_level_count =
fabsf(ovec3f_get_length(accel) - 9.82f) < gravity_tolerance * 2.0f && ang_vel_length < ang_vel_tolerance
? me->device_level_count + 1 : 0;
// device has been level for long enough, grab mean from the accelerometer filter queue (last n values)
// and use for correction
if(me->device_level_count > 50){
me->device_level_count = 0;
vec3f accel_mean;
ofq_get_mean(&me->accel_fq, &accel_mean);
if (ovec3f_get_length(&accel_mean) - 9.82f < gravity_tolerance)
{
// Calculate a cross product between what the device
// thinks is up and what gravity indicates is down.
// The values are optimized of what we would get out
// from the cross product.
vec3f tilt = {{accel_mean.z, 0, -accel_mean.x}};
ovec3f_normalize_me(&tilt);
ovec3f_normalize_me(&accel_mean);
vec3f up = {{0, 1.0f, 0}};
float tilt_angle = ovec3f_get_angle(&up, &accel_mean);
if(tilt_angle > max_tilt_error){
me->grav_error_angle = tilt_angle;
me->grav_error_axis = tilt;
}
}
}
// preform gravity tilt correction
if(me->grav_error_angle > min_tilt_error){
float use_angle;
// if less than 2000 iterations have passed, set the up axis to the correction value outright
if(me->iterations < 2000){
use_angle = -me->grav_error_angle;
me->grav_error_angle = 0;
}
// otherwise try to correct
else {
use_angle = -me->grav_gain * me->grav_error_angle * 0.005f * (5.0f * ang_vel_length + 1.0f);
me->grav_error_angle += use_angle;
}
// perform the correction
quatf corr_quat, old_orient;
oquatf_init_axis(&corr_quat, &me->grav_error_axis, use_angle);
old_orient = me->orient;
oquatf_mult(&corr_quat, &old_orient, &me->orient);
}
}
// mitigate drift due to floating point
// inprecision with quat multiplication.
oquatf_normalize_me(&me->orient);
}

44
extern/openhmd/src/fusion.h vendored Normal file
View File

@@ -0,0 +1,44 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Sensor Fusion */
#ifndef FUSION_H
#define FUSION_H
#include "omath.h"
#define FF_USE_GRAVITY 1
typedef struct {
int state;
quatf orient; // orientation
vec3f accel; // acceleration
vec3f ang_vel; // angular velocity
vec3f mag; // magnetometer
vec3f raw_mag; // raw magnetometer values
int iterations;
float time;
int flags;
// filter queues for magnetometer, accelerometers and angular velocity
filter_queue mag_fq, accel_fq, ang_vel_fq;
// gravity correction
int device_level_count;
float grav_error_angle;
vec3f grav_error_axis;
float grav_gain; // amount of correction
} fusion;
void ofusion_init(fusion* me);
void ofusion_update(fusion* me, float dt, const vec3f* ang_vel, const vec3f* accel, const vec3f* mag_field);
#endif

39
extern/openhmd/src/log.h vendored Normal file
View File

@@ -0,0 +1,39 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Logging and Error Handling */
#ifndef LOG_H
#define LOG_H
void* ohmd_allocfn(ohmd_context* ctx, const char* e_msg, size_t size);
#define ohmd_alloc(_ctx, _size) ohmd_allocfn(_ctx, "could not allocate " #_size " bytes of RAM @ " __FILE__ ":" OHMD_STRINGIFY(__LINE__), _size)
#ifndef LOGLEVEL
#define LOGLEVEL 2
#endif
#define LOG(_level, _levelstr, ...) do{ if(_level >= LOGLEVEL){ printf("[%s] ", (_levelstr)); printf(__VA_ARGS__); puts(""); } } while(0)
#if LOGLEVEL == 0
#define LOGD(...) LOG(0, "DD", __VA_ARGS__)
#else
#define LOGD(...)
#endif
#define LOGV(...) LOG(1, "VV", __VA_ARGS__)
#define LOGI(...) LOG(2, "II", __VA_ARGS__)
#define LOGW(...) LOG(3, "WW", __VA_ARGS__)
#define LOGE(...) LOG(4, "EE", __VA_ARGS__)
#ifdef _MSC_VER
#define snprintf _snprintf
#endif
#define ohmd_set_error(_ctx, ...) { snprintf((_ctx)->error_msg, OHMD_STR_SIZE, __VA_ARGS__); LOGE(__VA_ARGS__); }
#endif

395
extern/openhmd/src/omath.c vendored Normal file
View File

@@ -0,0 +1,395 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Math Code Implementation */
#include <string.h>
#include "openhmdi.h"
// vector
float ovec3f_get_length(const vec3f* me)
{
return sqrtf(POW2(me->x) + POW2(me->y) + POW2(me->z));
}
void ovec3f_normalize_me(vec3f* me)
{
if(me->x == 0 && me->y == 0 && me->z == 0)
return;
float len = ovec3f_get_length(me);
me->x /= len;
me->y /= len;
me->z /= len;
}
void ovec3f_subtract(const vec3f* a, const vec3f* b, vec3f* out)
{
for(int i = 0; i < 3; i++)
out->arr[i] = a->arr[i] - b->arr[i];
}
float ovec3f_get_dot(const vec3f* me, const vec3f* vec)
{
return me->x * vec->x + me->y * vec->y + me->z * vec->z;
}
float ovec3f_get_angle(const vec3f* me, const vec3f* vec)
{
float dot = ovec3f_get_dot(me, vec);
float lengths = ovec3f_get_length(me) * ovec3f_get_length(vec);
if(lengths == 0)
return 0;
return acosf(dot / lengths);
}
// quaternion
void oquatf_init_axis(quatf* me, const vec3f* vec, float angle)
{
vec3f norm = *vec;
ovec3f_normalize_me(&norm);
me->x = norm.x * sinf(angle / 2.0f);
me->y = norm.y * sinf(angle / 2.0f);
me->z = norm.z * sinf(angle / 2.0f);
me->w = cosf(angle / 2.0f);
}
void oquatf_get_rotated(const quatf* me, const vec3f* vec, vec3f* out_vec)
{
quatf q = {{vec->x * me->w + vec->z * me->y - vec->y * me->z,
vec->y * me->w + vec->x * me->z - vec->z * me->x,
vec->z * me->w + vec->y * me->x - vec->x * me->y,
vec->x * me->x + vec->y * me->y + vec->z * me->z}};
out_vec->x = me->w * q.x + me->x * q.w + me->y * q.z - me->z * q.y;
out_vec->y = me->w * q.y + me->y * q.w + me->z * q.x - me->x * q.z;
out_vec->z = me->w * q.z + me->z * q.w + me->x * q.y - me->y * q.x;
}
void oquatf_mult(const quatf* me, const quatf* q, quatf* out_q)
{
out_q->x = me->w * q->x + me->x * q->w + me->y * q->z - me->z * q->y;
out_q->y = me->w * q->y - me->x * q->z + me->y * q->w + me->z * q->x;
out_q->z = me->w * q->z + me->x * q->y - me->y * q->x + me->z * q->w;
out_q->w = me->w * q->w - me->x * q->x - me->y * q->y - me->z * q->z;
}
void oquatf_mult_me(quatf* me, const quatf* q)
{
quatf tmp = *me;
oquatf_mult(&tmp, q, me);
}
void oquatf_normalize_me(quatf* me)
{
float len = oquatf_get_length(me);
me->x /= len;
me->y /= len;
me->z /= len;
me->w /= len;
}
float oquatf_get_length(const quatf* me)
{
return sqrtf(me->x * me->x + me->y * me->y + me->z * me->z + me->w * me->w);
}
float oquatf_get_dot(const quatf* me, const quatf* q)
{
return me->x * q->x + me->y * q->y + me->z * q->z + me->w * q->w;
}
void oquatf_inverse(quatf* me)
{
float dot = oquatf_get_dot(me, me);
// conjugate
for(int i = 0; i < 3; i++)
me->arr[i] = -me->arr[i];
for(int i = 0; i < 4; i++)
me->arr[i] /= dot;
}
void oquatf_diff(const quatf* me, const quatf* q, quatf* out_q)
{
quatf inv = *me;
oquatf_inverse(&inv);
oquatf_mult(&inv, q, out_q);
}
void oquatf_slerp (float fT, const quatf* rkP, const quatf* rkQ, bool shortestPath, quatf* out_q)
{
float fCos = oquatf_get_dot(rkP, rkQ);
quatf rkT;
// Do we need to invert rotation?
if (fCos < 0.0f && shortestPath)
{
fCos = -fCos;
rkT = *rkQ;
oquatf_inverse(&rkT);
}
else
{
rkT = *rkQ;
}
if (fabsf(fCos) < 1 - 0.001f)
{
// Standard case (slerp)
float fSin = sqrtf(1 - (fCos*fCos));
float fAngle = atan2f(fSin, fCos);
float fInvSin = 1.0f / fSin;
float fCoeff0 = sin((1.0f - fT) * fAngle) * fInvSin;
float fCoeff1 = sin(fT * fAngle) * fInvSin;
out_q->x = fCoeff0 * rkP->x + fCoeff1 * rkT.x;
out_q->y = fCoeff0 * rkP->y + fCoeff1 * rkT.y;
out_q->z = fCoeff0 * rkP->z + fCoeff1 * rkT.z;
out_q->w = fCoeff0 * rkP->w + fCoeff1 * rkT.w;
//return fCoeff0 * rkP + fCoeff1 * rkT;
}
else
{
// There are two situations:
// 1. "rkP" and "rkQ" are very close (fCos ~= +1), so we can do a linear
// interpolation safely.
// 2. "rkP" and "rkQ" are almost inverse of each other (fCos ~= -1), there
// are an infinite number of possibilities interpolation. but we haven't
// have method to fix this case, so just use linear interpolation here.
//Quaternion t = (1.0f - fT) * rkP + fT * rkT;
out_q->x = (1.0f - fT) * rkP->x + fT * rkT.x;
out_q->y = (1.0f - fT) * rkP->y + fT * rkT.y;
out_q->z = (1.0f - fT) * rkP->z + fT * rkT.z;
out_q->w = (1.0f - fT) * rkP->w + fT * rkT.w;
oquatf_normalize_me(out_q);
// taking the complement requires renormalisation
//t.normalise();
//return t;
}
}
void oquatf_get_mat4x4(const quatf* me, const vec3f* point, float mat[4][4])
{
mat[0][0] = 1 - 2 * me->y * me->y - 2 * me->z * me->z;
mat[0][1] = 2 * me->x * me->y - 2 * me->w * me->z;
mat[0][2] = 2 * me->x * me->z + 2 * me->w * me->y;
mat[0][3] = point->x;
mat[1][0] = 2 * me->x * me->y + 2 * me->w * me->z;
mat[1][1] = 1 - 2 * me->x * me->x - 2 * me->z * me->z;
mat[1][2] = 2 * me->y * me->z - 2 * me->w * me->x;
mat[1][3] = point->y;
mat[2][0] = 2 * me->x * me->z - 2 * me->w * me->y;
mat[2][1] = 2 * me->y * me->z + 2 * me->w * me->x;
mat[2][2] = 1 - 2 * me->x * me->x - 2 * me->y * me->y;
mat[2][3] = point->z;
mat[3][0] = 0;
mat[3][1] = 0;
mat[3][2] = 0;
mat[3][3] = 1;
}
// matrix
void omat4x4f_init_ident(mat4x4f* me)
{
memset(me, 0, sizeof(*me));
me->m[0][0] = 1.0f;
me->m[1][1] = 1.0f;
me->m[2][2] = 1.0f;
me->m[3][3] = 1.0f;
}
void omat4x4f_init_perspective(mat4x4f* me, float fovy_rad, float aspect, float znear, float zfar)
{
float sine, cotangent, delta, half_fov;
half_fov = fovy_rad / 2.0f;
delta = zfar - znear;
sine = sinf(half_fov);
if ((delta == 0.0f) || (sine == 0.0f) || (aspect == 0.0f)) {
omat4x4f_init_ident(me);
return;
}
cotangent = cosf(half_fov) / sine;
me->m[0][0] = cotangent / aspect;
me->m[0][1] = 0;
me->m[0][2] = 0;
me->m[0][3] = 0;
me->m[1][0] = 0;
me->m[1][1] = cotangent;
me->m[1][2] = 0;
me->m[1][3] = 0;
me->m[2][0] = 0;
me->m[2][1] = 0;
me->m[2][2] = -(zfar + znear) / delta;
me->m[2][3] = -2.0f * znear * zfar / delta;
me->m[3][0] = 0;
me->m[3][1] = 0;
me->m[3][2] = -1.0f;
me->m[3][3] = 0;
}
void omat4x4f_init_frustum(mat4x4f* me, float left, float right, float bottom, float top, float znear, float zfar)
{
omat4x4f_init_ident(me);
float delta_x = right - left;
float delta_y = top - bottom;
float delta_z = zfar - znear;
if ((delta_x == 0.0f) || (delta_y == 0.0f) || (delta_z == 0.0f)) {
/* can't divide by zero, so just give back identity */
return;
}
me->m[0][0] = 2.0f * znear / delta_x;
me->m[0][1] = 0;
me->m[0][2] = (right + left) / delta_x;
me->m[0][3] = 0;
me->m[1][0] = 0;
me->m[1][1] = 2.0f * znear / delta_y;
me->m[1][2] = (top + bottom) / delta_y;
me->m[1][3] = 0;
me->m[2][0] = 0;
me->m[2][1] = 0;
me->m[2][2] = -(zfar + znear) / delta_z;
me->m[2][3] = -2.0f * zfar * znear / delta_z;
me->m[3][0] = 0;
me->m[3][1] = 0;
me->m[3][2] = -1.0f;
me->m[3][3] = 0;
}
void omat4x4f_init_look_at(mat4x4f* me, const quatf* rot, const vec3f* eye)
{
quatf q;
vec3f p;
q.x = -rot->x;
q.y = -rot->y;
q.z = -rot->z;
q.w = rot->w;
p.x = -eye->x;
p.y = -eye->y;
p.z = -eye->z;
me->m[0][0] = 1 - 2 * q.y * q.y - 2 * q.z * q.z;
me->m[0][1] = 2 * q.x * q.y - 2 * q.w * q.z;
me->m[0][2] = 2 * q.x * q.z + 2 * q.w * q.y;
me->m[0][3] = p.x * me->m[0][0] + p.y * me->m[0][1] + p.z * me->m[0][2];
me->m[1][0] = 2 * q.x * q.y + 2 * q.w * q.z;
me->m[1][1] = 1 - 2 * q.x * q.x - 2 * q.z * q.z;
me->m[1][2] = 2 * q.y * q.z - 2 * q.w * q.x;
me->m[1][3] = p.x * me->m[1][0] + p.y * me->m[1][1] + p.z * me->m[1][2];
me->m[2][0] = 2 * q.x * q.z - 2 * q.w * q.y;
me->m[2][1] = 2 * q.y * q.z + 2 * q.w * q.x;
me->m[2][2] = 1 - 2 * q.x * q.x - 2 * q.y * q.y;
me->m[2][3] = p.x * me->m[2][0] + p.y * me->m[2][1] + p.z * me->m[2][2];
me->m[3][0] = 0;
me->m[3][1] = 0;
me->m[3][2] = 0;
me->m[3][3] = 1;
}
void omat4x4f_init_translate(mat4x4f* me, float x, float y, float z)
{
omat4x4f_init_ident(me);
me->m[0][3] = x;
me->m[1][3] = y;
me->m[2][3] = z;
}
void omat4x4f_transpose(const mat4x4f* m, mat4x4f* o)
{
o->m[0][0] = m->m[0][0];
o->m[1][0] = m->m[0][1];
o->m[2][0] = m->m[0][2];
o->m[3][0] = m->m[0][3];
o->m[0][1] = m->m[1][0];
o->m[1][1] = m->m[1][1];
o->m[2][1] = m->m[1][2];
o->m[3][1] = m->m[1][3];
o->m[0][2] = m->m[2][0];
o->m[1][2] = m->m[2][1];
o->m[2][2] = m->m[2][2];
o->m[3][2] = m->m[2][3];
o->m[0][3] = m->m[3][0];
o->m[1][3] = m->m[3][1];
o->m[2][3] = m->m[3][2];
o->m[3][3] = m->m[3][3];
}
void omat4x4f_mult(const mat4x4f* l, const mat4x4f* r, mat4x4f *o)
{
for(int i = 0; i < 4; i++){
float a0 = l->m[i][0], a1 = l->m[i][1], a2 = l->m[i][2], a3 = l->m[i][3];
o->m[i][0] = a0 * r->m[0][0] + a1 * r->m[1][0] + a2 * r->m[2][0] + a3 * r->m[3][0];
o->m[i][1] = a0 * r->m[0][1] + a1 * r->m[1][1] + a2 * r->m[2][1] + a3 * r->m[3][1];
o->m[i][2] = a0 * r->m[0][2] + a1 * r->m[1][2] + a2 * r->m[2][2] + a3 * r->m[3][2];
o->m[i][3] = a0 * r->m[0][3] + a1 * r->m[1][3] + a2 * r->m[2][3] + a3 * r->m[3][3];
}
}
// filter queue
void ofq_init(filter_queue* me, int size)
{
memset(me, 0, sizeof(filter_queue));
me->size = size;
}
void ofq_add(filter_queue* me, const vec3f* vec)
{
me->elems[me->at] = *vec;
me->at = ((me->at + 1) % me->size);
}
void ofq_get_mean(const filter_queue* me, vec3f* vec)
{
vec->x = vec->y = vec->z = 0;
for(int i = 0; i < me->size; i++){
vec->x += me->elems[i].x;
vec->y += me->elems[i].y;
vec->z += me->elems[i].z;
}
vec->x /= (float)me->size;
vec->y /= (float)me->size;
vec->z /= (float)me->size;
}

90
extern/openhmd/src/omath.h vendored Normal file
View File

@@ -0,0 +1,90 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Math */
#ifndef OMATH_H
#define OMATH_H
#include <math.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define POW2(_x) ((_x) * (_x))
#define RAD_TO_DEG(_r) ((_r) * 360.0f / (2.0f * (float)M_PI))
#define DEG_TO_RAD(_d) ((_d) * (2.0f * (float)M_PI) / 360.0f)
// vector
typedef union {
struct {
float x, y, z;
};
float arr[3];
} vec3f;
void ovec3f_normalize_me(vec3f* me);
float ovec3f_get_length(const vec3f* me);
float ovec3f_get_angle(const vec3f* me, const vec3f* vec);
float ovec3f_get_dot(const vec3f* me, const vec3f* vec);
void ovec3f_subtract(const vec3f* a, const vec3f* b, vec3f* out);
// quaternion
typedef union {
struct {
float x, y, z, w;
};
float arr[4];
} quatf;
void oquatf_init_axis(quatf* me, const vec3f* vec, float angle);
void oquatf_get_rotated(const quatf* me, const vec3f* vec, vec3f* out_vec);
void oquatf_mult_me(quatf* me, const quatf* q);
void oquatf_mult(const quatf* me, const quatf* q, quatf* out_q);
void oquatf_diff(const quatf* me, const quatf* q, quatf* out_q);
void oquatf_normalize_me(quatf* me);
float oquatf_get_length(const quatf* me);
float oquatf_get_dot(const quatf* me, const quatf* q);
void oquatf_inverse(quatf* me);
void oquatf_get_mat4x4(const quatf* me, const vec3f* point, float mat[4][4]);
// matrix
typedef union {
float m[4][4];
float arr[16];
} mat4x4f;
void omat4x4f_init_ident(mat4x4f* me);
void omat4x4f_init_perspective(mat4x4f* me, float fov_rad, float aspect, float znear, float zfar);
void omat4x4f_init_frustum(mat4x4f* me, float left, float right, float bottom, float top, float znear, float zfar);
void omat4x4f_init_look_at(mat4x4f* me, const quatf* ret, const vec3f* eye);
void omat4x4f_init_translate(mat4x4f* me, float x, float y, float z);
void omat4x4f_mult(const mat4x4f* left, const mat4x4f* right, mat4x4f* out_mat);
void omat4x4f_transpose(const mat4x4f* me, mat4x4f* out_mat);
// filter queue
#define FILTER_QUEUE_MAX_SIZE 256
typedef struct {
int at, size;
vec3f elems[FILTER_QUEUE_MAX_SIZE];
} filter_queue;
void ofq_init(filter_queue* me, int size);
void ofq_add(filter_queue* me, const vec3f* vec);
void ofq_get_mean(const filter_queue* me, vec3f* vec);
#endif

572
extern/openhmd/src/openhmd.c vendored Normal file
View File

@@ -0,0 +1,572 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Main Lib Implemenation */
#include "openhmdi.h"
#include "shaders.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define DIGITAL_INPUT_EVENT_QUEUE_SIZE 1024
// Running automatic updates at 1000 Hz
#define AUTOMATIC_UPDATE_SLEEP (1.0 / 1000.0)
ohmd_context* OHMD_APIENTRY ohmd_ctx_create(void)
{
ohmd_context* ctx = calloc(1, sizeof(ohmd_context));
if(!ctx){
LOGE("could not allocate RAM for context");
return NULL;
}
#if DRIVER_OCULUS_RIFT
ctx->drivers[ctx->num_drivers++] = ohmd_create_oculus_rift_drv(ctx);
#endif
#if DRIVER_DEEPOON
ctx->drivers[ctx->num_drivers++] = ohmd_create_deepoon_drv(ctx);
#endif
#if DRIVER_PSVR
ctx->drivers[ctx->num_drivers++] = ohmd_create_psvr_drv(ctx);
#endif
#if DRIVER_HTC_VIVE
ctx->drivers[ctx->num_drivers++] = ohmd_create_htc_vive_drv(ctx);
#endif
#if DRIVER_EXTERNAL
ctx->drivers[ctx->num_drivers++] = ohmd_create_external_drv(ctx);
#endif
#if DRIVER_ANDROID
ctx->drivers[ctx->num_drivers++] = ohmd_create_android_drv(ctx);
#endif
// add dummy driver last to make it the lowest priority
ctx->drivers[ctx->num_drivers++] = ohmd_create_dummy_drv(ctx);
ctx->update_request_quit = false;
return ctx;
}
void OHMD_APIENTRY ohmd_ctx_destroy(ohmd_context* ctx)
{
ctx->update_request_quit = true;
for(int i = 0; i < ctx->num_active_devices; i++){
ctx->active_devices[i]->close(ctx->active_devices[i]);
}
for(int i = 0; i < ctx->num_drivers; i++){
ctx->drivers[i]->destroy(ctx->drivers[i]);
}
if(ctx->update_thread){
ohmd_destroy_thread(ctx->update_thread);
ohmd_destroy_mutex(ctx->update_mutex);
}
free(ctx);
}
void OHMD_APIENTRY ohmd_ctx_update(ohmd_context* ctx)
{
for(int i = 0; i < ctx->num_active_devices; i++){
ohmd_device* dev = ctx->active_devices[i];
if(!dev->settings.automatic_update && dev->update)
dev->update(dev);
ohmd_lock_mutex(ctx->update_mutex);
dev->getf(dev, OHMD_POSITION_VECTOR, (float*)&dev->position);
dev->getf(dev, OHMD_ROTATION_QUAT, (float*)&dev->rotation);
ohmd_unlock_mutex(ctx->update_mutex);
}
}
const char* OHMD_APIENTRY ohmd_ctx_get_error(ohmd_context* ctx)
{
return ctx->error_msg;
}
int OHMD_APIENTRY ohmd_ctx_probe(ohmd_context* ctx)
{
memset(&ctx->list, 0, sizeof(ohmd_device_list));
for(int i = 0; i < ctx->num_drivers; i++){
ctx->drivers[i]->get_device_list(ctx->drivers[i], &ctx->list);
}
return ctx->list.num_devices;
}
const char* OHMD_APIENTRY ohmd_gets(ohmd_string_description type)
{
switch(type){
case OHMD_GLSL_DISTORTION_VERT_SRC:
return distortion_vert;
case OHMD_GLSL_DISTORTION_FRAG_SRC:
return distortion_frag;
default:
return NULL;
}
}
const char* OHMD_APIENTRY ohmd_list_gets(ohmd_context* ctx, int index, ohmd_string_value type)
{
if(index >= ctx->list.num_devices)
return NULL;
switch(type){
case OHMD_VENDOR:
return ctx->list.devices[index].vendor;
case OHMD_PRODUCT:
return ctx->list.devices[index].product;
case OHMD_PATH:
return ctx->list.devices[index].path;
default:
return NULL;
}
}
static unsigned int ohmd_update_thread(void* arg)
{
ohmd_context* ctx = (ohmd_context*)arg;
while(!ctx->update_request_quit)
{
ohmd_lock_mutex(ctx->update_mutex);
for(int i = 0; i < ctx->num_active_devices; i++){
if(ctx->active_devices[i]->settings.automatic_update && ctx->active_devices[i]->update)
ctx->active_devices[i]->update(ctx->active_devices[i]);
}
ohmd_unlock_mutex(ctx->update_mutex);
ohmd_sleep(AUTOMATIC_UPDATE_SLEEP);
}
return 0;
}
static void ohmd_set_up_update_thread(ohmd_context* ctx)
{
if(!ctx->update_thread){
ctx->update_mutex = ohmd_create_mutex(ctx);
ctx->update_thread = ohmd_create_thread(ctx, ohmd_update_thread, ctx);
}
}
ohmd_device* OHMD_APIENTRY ohmd_list_open_device_s(ohmd_context* ctx, int index, ohmd_device_settings* settings)
{
ohmd_lock_mutex(ctx->update_mutex);
if(index >= 0 && index < ctx->list.num_devices){
ohmd_device_desc* desc = &ctx->list.devices[index];
ohmd_driver* driver = (ohmd_driver*)desc->driver_ptr;
ohmd_device* device = driver->open_device(driver, desc);
if (device == NULL)
return NULL;
device->rotation_correction.w = 1;
device->settings = *settings;
device->ctx = ctx;
device->active_device_idx = ctx->num_active_devices;
ctx->active_devices[ctx->num_active_devices++] = device;
if(device->properties.digital_button_count > 0)
device->digital_input_event_queue = ohmdq_create(ctx, sizeof(ohmd_digital_input_event), DIGITAL_INPUT_EVENT_QUEUE_SIZE);
ohmd_unlock_mutex(ctx->update_mutex);
if(device->settings.automatic_update)
ohmd_set_up_update_thread(ctx);
return device;
}
ohmd_unlock_mutex(ctx->update_mutex);
ohmd_set_error(ctx, "no device with index: %d", index);
return NULL;
}
ohmd_device* OHMD_APIENTRY ohmd_list_open_device(ohmd_context* ctx, int index)
{
ohmd_device_settings settings;
settings.automatic_update = true;
return ohmd_list_open_device_s(ctx, index, &settings);
}
int OHMD_APIENTRY ohmd_close_device(ohmd_device* device)
{
ohmd_lock_mutex(device->ctx->update_mutex);
ohmd_context* ctx = device->ctx;
int idx = device->active_device_idx;
ohmdq* dinq = device->digital_input_event_queue;
memmove(ctx->active_devices + idx, ctx->active_devices + idx + 1,
sizeof(ohmd_device*) * (ctx->num_active_devices - idx - 1));
device->close(device);
if(dinq)
ohmdq_destroy(dinq);
ctx->num_active_devices--;
for(int i = idx; i < ctx->num_active_devices; i++)
ctx->active_devices[i]->active_device_idx--;
ohmd_unlock_mutex(ctx->update_mutex);
return OHMD_S_OK;
}
static int ohmd_device_getf_unp(ohmd_device* device, ohmd_float_value type, float* out)
{
switch(type){
case OHMD_LEFT_EYE_GL_MODELVIEW_MATRIX: {
vec3f point = {{0, 0, 0}};
quatf rot = device->rotation;
quatf tmp = device->rotation_correction;
oquatf_mult_me(&tmp, &rot);
rot = tmp;
mat4x4f orient, world_shift, result;
omat4x4f_init_look_at(&orient, &rot, &point);
omat4x4f_init_translate(&world_shift, +(device->properties.ipd / 2.0f), 0, 0);
omat4x4f_mult(&world_shift, &orient, &result);
omat4x4f_transpose(&result, (mat4x4f*)out);
return OHMD_S_OK;
}
case OHMD_RIGHT_EYE_GL_MODELVIEW_MATRIX: {
vec3f point = {{0, 0, 0}};
quatf rot = device->rotation;
oquatf_mult_me(&rot, &device->rotation_correction);
mat4x4f orient, world_shift, result;
omat4x4f_init_look_at(&orient, &rot, &point);
omat4x4f_init_translate(&world_shift, -(device->properties.ipd / 2.0f), 0, 0);
omat4x4f_mult(&world_shift, &orient, &result);
omat4x4f_transpose(&result, (mat4x4f*)out);
return OHMD_S_OK;
}
case OHMD_LEFT_EYE_GL_PROJECTION_MATRIX:
omat4x4f_transpose(&device->properties.proj_left, (mat4x4f*)out);
return OHMD_S_OK;
case OHMD_RIGHT_EYE_GL_PROJECTION_MATRIX:
omat4x4f_transpose(&device->properties.proj_right, (mat4x4f*)out);
return OHMD_S_OK;
case OHMD_SCREEN_HORIZONTAL_SIZE:
*out = device->properties.hsize;
return OHMD_S_OK;
case OHMD_SCREEN_VERTICAL_SIZE:
*out = device->properties.vsize;
return OHMD_S_OK;
case OHMD_LENS_HORIZONTAL_SEPARATION:
*out = device->properties.lens_sep;
return OHMD_S_OK;
case OHMD_LENS_VERTICAL_POSITION:
*out = device->properties.lens_vpos;
return OHMD_S_OK;
case OHMD_RIGHT_EYE_FOV:
case OHMD_LEFT_EYE_FOV:
*out = device->properties.fov;
return OHMD_S_OK;
case OHMD_RIGHT_EYE_ASPECT_RATIO:
case OHMD_LEFT_EYE_ASPECT_RATIO:
*out = device->properties.ratio;
return OHMD_S_OK;
case OHMD_EYE_IPD:
*out = device->properties.ipd;
return OHMD_S_OK;
case OHMD_PROJECTION_ZFAR:
*out = device->properties.zfar;
return OHMD_S_OK;
case OHMD_PROJECTION_ZNEAR:
*out = device->properties.znear;
return OHMD_S_OK;
case OHMD_ROTATION_QUAT:
{
*(quatf*)out = device->rotation;
oquatf_mult_me((quatf*)out, &device->rotation_correction);
quatf tmp = device->rotation_correction;
oquatf_mult_me(&tmp, (quatf*)out);
*(quatf*)out = tmp;
return OHMD_S_OK;
}
case OHMD_POSITION_VECTOR:
{
*(vec3f*)out = device->position;
for(int i = 0; i < 3; i++)
out[i] += device->position_correction.arr[i];
return OHMD_S_OK;
}
case OHMD_UNIVERSAL_DISTORTION_K: {
for (int i = 0; i < 4; i++) {
out[i] = device->properties.universal_distortion_k[i];
}
return OHMD_S_OK;
}
case OHMD_UNIVERSAL_ABERRATION_K: {
for (int i = 0; i < 3; i++) {
out[i] = device->properties.universal_aberration_k[i];
}
return OHMD_S_OK;
}
default:
return device->getf(device, type, out);
}
}
int OHMD_APIENTRY ohmd_device_getf(ohmd_device* device, ohmd_float_value type, float* out)
{
ohmd_lock_mutex(device->ctx->update_mutex);
int ret = ohmd_device_getf_unp(device, type, out);
ohmd_unlock_mutex(device->ctx->update_mutex);
return ret;
}
int ohmd_device_setf_unp(ohmd_device* device, ohmd_float_value type, const float* in)
{
switch(type){
case OHMD_EYE_IPD:
device->properties.ipd = *in;
return OHMD_S_OK;
case OHMD_PROJECTION_ZFAR:
device->properties.zfar = *in;
return OHMD_S_OK;
case OHMD_PROJECTION_ZNEAR:
device->properties.znear = *in;
return OHMD_S_OK;
case OHMD_ROTATION_QUAT:
{
// adjust rotation correction
quatf q;
int ret = device->getf(device, OHMD_ROTATION_QUAT, (float*)&q);
if(ret != 0){
return ret;
}
oquatf_diff(&q, (quatf*)in, &device->rotation_correction);
return OHMD_S_OK;
}
case OHMD_POSITION_VECTOR:
{
// adjust position correction
vec3f v;
int ret = device->getf(device, OHMD_POSITION_VECTOR, (float*)&v);
if(ret != 0){
return ret;
}
for(int i = 0; i < 3; i++)
device->position_correction.arr[i] = in[i] - v.arr[i];
return OHMD_S_OK;
}
case OHMD_EXTERNAL_SENSOR_FUSION:
{
if(device->setf == NULL)
return OHMD_S_UNSUPPORTED;
return device->setf(device, type, in);
}
default:
return OHMD_S_INVALID_PARAMETER;
}
}
int OHMD_APIENTRY ohmd_device_setf(ohmd_device* device, ohmd_float_value type, const float* in)
{
ohmd_lock_mutex(device->ctx->update_mutex);
int ret = ohmd_device_setf_unp(device, type, in);
ohmd_unlock_mutex(device->ctx->update_mutex);
return ret;
}
int OHMD_APIENTRY ohmd_device_geti(ohmd_device* device, ohmd_int_value type, int* out)
{
ohmdq* dinq = device->digital_input_event_queue;
switch(type){
case OHMD_SCREEN_HORIZONTAL_RESOLUTION:
*out = device->properties.hres;
return OHMD_S_OK;
case OHMD_SCREEN_VERTICAL_RESOLUTION:
*out = device->properties.vres;
return OHMD_S_OK;
case OHMD_BUTTON_EVENT_COUNT:
*out = dinq ? (int)ohmdq_get_size(dinq) : 0;
return OHMD_S_OK;
case OHMD_BUTTON_EVENT_OVERFLOW:
*out = dinq ? (ohmdq_get_size(dinq) == ohmdq_get_max(dinq)) : 0;
return OHMD_S_OK;
case OHMD_BUTTON_COUNT:
*out = device->properties.digital_button_count;
return OHMD_S_OK;
case OHMD_BUTTON_POP_EVENT: {
ohmd_digital_input_event event;
if(!ohmdq_pop(dinq, &event)){
return OHMD_S_INVALID_OPERATION;
}
out[0] = event.idx;
out[1] = event.state;
return OHMD_S_OK;
}
default:
return OHMD_S_INVALID_PARAMETER;
}
}
int OHMD_APIENTRY ohmd_device_seti(ohmd_device* device, ohmd_int_value type, const int* in)
{
switch(type){
default:
return OHMD_S_INVALID_PARAMETER;
}
}
int ohmd_device_set_data_unp(ohmd_device* device, ohmd_data_value type, const void* in)
{
switch(type){
case OHMD_DRIVER_DATA:
device->set_data(device, OHMD_DRIVER_DATA, in);
return OHMD_S_OK;
case OHMD_DRIVER_PROPERTIES:
device->set_data(device, OHMD_DRIVER_PROPERTIES, in);
return OHMD_S_OK;
default:
return OHMD_S_INVALID_PARAMETER;
}
}
int OHMD_APIENTRY ohmd_device_set_data(ohmd_device* device, ohmd_data_value type, const void* in)
{
ohmd_lock_mutex(device->ctx->update_mutex);
int ret = ohmd_device_set_data_unp(device, type, in);
ohmd_unlock_mutex(device->ctx->update_mutex);
return ret;
}
ohmd_status OHMD_APIENTRY ohmd_device_settings_seti(ohmd_device_settings* settings, ohmd_int_settings key, const int* val)
{
switch(key){
case OHMD_IDS_AUTOMATIC_UPDATE:
settings->automatic_update = val[0] == 0 ? false : true;
return OHMD_S_OK;
default:
return OHMD_S_INVALID_PARAMETER;
}
}
ohmd_device_settings* OHMD_APIENTRY ohmd_device_settings_create(ohmd_context* ctx)
{
return ohmd_alloc(ctx, sizeof(ohmd_device_settings));
}
void OHMD_APIENTRY ohmd_device_settings_destroy(ohmd_device_settings* settings)
{
free(settings);
}
void* ohmd_allocfn(ohmd_context* ctx, const char* e_msg, size_t size)
{
void* ret = calloc(1, size);
if(!ret)
ohmd_set_error(ctx, "%s", e_msg);
return ret;
}
void ohmd_set_default_device_properties(ohmd_device_properties* props)
{
props->ipd = 0.061f;
props->znear = 0.1f;
props->zfar = 1000.0f;
ohmd_set_universal_distortion_k(props, 0, 0, 0, 1);
ohmd_set_universal_aberration_k(props, 1.0, 1.0, 1.0);
}
void ohmd_calc_default_proj_matrices(ohmd_device_properties* props)
{
mat4x4f proj_base; // base projection matrix
// Calculate where the lens is on each screen,
// and with the given value offset the projection matrix.
float screen_center = props->hsize / 4.0f;
float lens_shift = screen_center - props->lens_sep / 2.0f;
// XXX: on CV1, props->hsize > props->lens_sep / 2.0,
// I am not sure about the implications, but just taking the absolute
// value of the offset seems to work.
float proj_offset = fabs(4.0f * lens_shift / props->hsize);
// Setup the base projection matrix. Each eye mostly have the
// same projection matrix with the exception of the offset.
omat4x4f_init_perspective(&proj_base, props->fov, props->ratio, props->znear, props->zfar);
// Setup the two adjusted projection matricies. Each is setup to deal
// with the fact that the lens is not in the center of the screen.
// These matrices only change of the hardware changes, so static.
mat4x4f translate;
omat4x4f_init_translate(&translate, proj_offset, 0, 0);
omat4x4f_mult(&translate, &proj_base, &props->proj_left);
omat4x4f_init_translate(&translate, -proj_offset, 0, 0);
omat4x4f_mult(&translate, &proj_base, &props->proj_right);
}
void ohmd_set_universal_distortion_k(ohmd_device_properties* props, float a, float b, float c, float d)
{
props->universal_distortion_k[0] = a;
props->universal_distortion_k[1] = b;
props->universal_distortion_k[2] = c;
props->universal_distortion_k[3] = d;
}
void ohmd_set_universal_aberration_k(ohmd_device_properties* props, float r, float g, float b)
{
props->universal_aberration_k[0] = r;
props->universal_aberration_k[1] = g;
props->universal_aberration_k[2] = b;
}

152
extern/openhmd/src/openhmdi.h vendored Normal file
View File

@@ -0,0 +1,152 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Internal interface */
#ifndef OPENHMDI_H
#define OPENHMDI_H
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "openhmd.h"
#include "omath.h"
#include "platform.h"
#include "queue.h"
#define OHMD_MAX_DEVICES 16
#define OHMD_MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
#define OHMD_MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#define OHMD_STRINGIFY(_what) #_what
typedef struct ohmd_driver ohmd_driver;
typedef struct {
char driver[OHMD_STR_SIZE];
char vendor[OHMD_STR_SIZE];
char product[OHMD_STR_SIZE];
char path[OHMD_STR_SIZE];
int revision;
ohmd_driver* driver_ptr;
} ohmd_device_desc;
typedef struct {
int num_devices;
ohmd_device_desc devices[OHMD_MAX_DEVICES];
} ohmd_device_list;
typedef struct {
int idx;
ohmd_button_state state;
} ohmd_digital_input_event;
struct ohmd_driver {
void (*get_device_list)(ohmd_driver* driver, ohmd_device_list* list);
ohmd_device* (*open_device)(ohmd_driver* driver, ohmd_device_desc* desc);
void (*destroy)(ohmd_driver* driver);
ohmd_context* ctx;
};
typedef struct {
int hres;
int vres;
int digital_button_count;
float hsize;
float vsize;
float lens_sep;
float lens_vpos;
float fov;
float ratio;
float ipd;
float zfar;
float znear;
int accel_only; //bool-like for setting acceleration only fallback (android driver)
mat4x4f proj_left; // adjusted projection matrix for left screen
mat4x4f proj_right; // adjusted projection matrix for right screen
float universal_distortion_k[4]; //PanoTools lens distiorion model [a,b,c,d]
float universal_aberration_k[3]; //post-warp per channel scaling [r,g,b]
} ohmd_device_properties;
struct ohmd_device_settings
{
bool automatic_update;
};
struct ohmd_device {
ohmd_device_properties properties;
quatf rotation_correction;
vec3f position_correction;
int (*getf)(ohmd_device* device, ohmd_float_value type, float* out);
int (*setf)(ohmd_device* device, ohmd_float_value type, const float* in);
int (*seti)(ohmd_device* device, ohmd_int_value type, const int* in);
int (*set_data)(ohmd_device* device, ohmd_data_value type, const void* in);
void (*update)(ohmd_device* device);
void (*close)(ohmd_device* device);
ohmd_context* ctx;
ohmd_device_settings settings;
int active_device_idx; // index into ohmd_device->active_devices[]
quatf rotation;
vec3f position;
ohmdq* digital_input_event_queue;
};
struct ohmd_context {
ohmd_driver* drivers[16];
int num_drivers;
ohmd_device_list list;
ohmd_device* active_devices[256];
int num_active_devices;
ohmd_thread* update_thread;
ohmd_mutex* update_mutex;
bool update_request_quit;
char error_msg[OHMD_STR_SIZE];
};
// helper functions
void ohmd_set_default_device_properties(ohmd_device_properties* props);
void ohmd_calc_default_proj_matrices(ohmd_device_properties* props);
void ohmd_set_universal_distortion_k(ohmd_device_properties* props, float a, float b, float c, float d);
void ohmd_set_universal_aberration_k(ohmd_device_properties* props, float r, float g, float b);
// drivers
ohmd_driver* ohmd_create_dummy_drv(ohmd_context* ctx);
ohmd_driver* ohmd_create_oculus_rift_drv(ohmd_context* ctx);
ohmd_driver* ohmd_create_deepoon_drv(ohmd_context* ctx);
ohmd_driver* ohmd_create_psvr_drv(ohmd_context* ctx);
ohmd_driver* ohmd_create_htc_vive_drv(ohmd_context* ctx);
ohmd_driver* ohmd_create_external_drv(ohmd_context* ctx);
ohmd_driver* ohmd_create_android_drv(ohmd_context* ctx);
#include "log.h"
#include "omath.h"
#include "fusion.h"
#endif

132
extern/openhmd/src/platform-posix.c vendored Normal file
View File

@@ -0,0 +1,132 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Platform Specific Functions, Unix/Posix Implementation */
#if defined(__unix__) || defined(__unix) || defined(__APPLE__) || defined(__MACH__)
#ifdef __CYGWIN__
#define CLOCK_MONOTONIC (clockid_t)4
#endif
#define _POSIX_C_SOURCE 199309L
#include <time.h>
#include <sys/time.h>
#include <stdio.h>
#include <pthread.h>
#include "platform.h"
#include "openhmdi.h"
// Use clock_gettime if the system implements posix realtime timers
#ifndef CLOCK_MONOTONIC
double ohmd_get_tick()
{
struct timeval now;
gettimeofday(&now, NULL);
return (double)now.tv_sec * 1.0 + (double)now.tv_usec / 1000000.0;
}
#else
double ohmd_get_tick()
{
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
return (double)now.tv_sec * 1.0 + (double)now.tv_nsec / 1000000000.0;
}
#endif
void ohmd_sleep(double seconds)
{
struct timespec sleepfor;
sleepfor.tv_sec = (time_t)seconds;
sleepfor.tv_nsec = (long)((seconds - sleepfor.tv_sec) * 1000000000.0);
nanosleep(&sleepfor, NULL);
}
// threads
struct ohmd_thread
{
pthread_t thread;
unsigned int (*routine)(void* arg);
void* arg;
};
static void* pthread_wrapper(void* arg)
{
ohmd_thread* my_thread = (ohmd_thread*)arg;
my_thread->routine(my_thread->arg);
return NULL;
}
ohmd_thread* ohmd_create_thread(ohmd_context* ctx, unsigned int (*routine)(void* arg), void* arg)
{
ohmd_thread* thread = ohmd_alloc(ctx, sizeof(ohmd_thread));
if(thread == NULL)
return NULL;
thread->arg = arg;
thread->routine = routine;
int ret = pthread_create(&thread->thread, NULL, pthread_wrapper, thread);
if(ret != 0){
free(thread);
thread = NULL;
}
return thread;
}
ohmd_mutex* ohmd_create_mutex(ohmd_context* ctx)
{
pthread_mutex_t* mutex = ohmd_alloc(ctx, sizeof(pthread_mutex_t));
if(mutex == NULL)
return NULL;
int ret = pthread_mutex_init(mutex, NULL);
if(ret != 0){
free(mutex);
mutex = NULL;
}
return (ohmd_mutex*)mutex;
}
void ohmd_destroy_thread(ohmd_thread* thread)
{
pthread_join(thread->thread, NULL);
free(thread);
}
void ohmd_destroy_mutex(ohmd_mutex* mutex)
{
pthread_mutex_destroy((pthread_mutex_t*)mutex);
free(mutex);
}
void ohmd_lock_mutex(ohmd_mutex* mutex)
{
if(mutex)
pthread_mutex_lock((pthread_mutex_t*)mutex);
}
void ohmd_unlock_mutex(ohmd_mutex* mutex)
{
if(mutex)
pthread_mutex_unlock((pthread_mutex_t*)mutex);
}
/// Handling ovr service
void ohmd_toggle_ovr_service(int state) //State is 0 for Disable, 1 for Enable
{
//Empty implementation
}
#endif

144
extern/openhmd/src/platform-win32.c vendored Normal file
View File

@@ -0,0 +1,144 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Platform Specific Functions, Win32 Implementation */
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN
#include <windows.h>
#include "platform.h"
#include "openhmdi.h"
double ohmd_get_tick()
{
double high, low;
FILETIME filetime;
GetSystemTimeAsFileTime(&filetime);
high = filetime.dwHighDateTime;
low = filetime.dwLowDateTime;
return (high * 4294967296.0 + low) / 10000000;
}
// TODO higher resolution
void ohmd_sleep(double seconds)
{
Sleep((DWORD)(seconds * 1000));
}
// threads
struct ohmd_thread {
HANDLE handle;
void* arg;
unsigned int (*routine)(void* arg);
};
struct ohmd_mutex {
HANDLE handle;
};
DWORD __stdcall ohmd_thread_wrapper(void* t)
{
ohmd_thread* thread = (ohmd_thread*)t;
return thread->routine(thread->arg);
}
ohmd_thread* ohmd_create_thread(ohmd_context* ctx, unsigned int (*routine)(void* arg), void* arg)
{
ohmd_thread* thread = ohmd_alloc(ctx, sizeof(ohmd_thread));
if(!thread)
return NULL;
thread->routine = routine;
thread->arg = arg;
thread->handle = CreateThread(NULL, 0, ohmd_thread_wrapper, thread, 0, NULL);
return thread;
}
void ohmd_destroy_thread(ohmd_thread* thread)
{
ohmd_sleep(3);
WaitForSingleObject(thread->handle, INFINITE);
CloseHandle(thread->handle);
free(thread);
}
ohmd_mutex* ohmd_create_mutex(ohmd_context* ctx)
{
ohmd_mutex* mutex = ohmd_alloc(ctx, sizeof(ohmd_mutex));
if(!mutex)
return NULL;
mutex->handle = CreateMutex(NULL, FALSE, NULL);
return mutex;
}
void ohmd_destroy_mutex(ohmd_mutex* mutex)
{
CloseHandle(mutex->handle);
free(mutex);
}
void ohmd_lock_mutex(ohmd_mutex* mutex)
{
if(mutex)
WaitForSingleObject(mutex->handle, INFINITE);
}
void ohmd_unlock_mutex(ohmd_mutex* mutex)
{
if(mutex)
ReleaseMutex(mutex->handle);
}
/// Handling ovr service
static int _enable_ovr_service = 0;
void ohmd_toggle_ovr_service(int state) //State is 0 for Disable, 1 for Enable
{
SC_HANDLE serviceDbHandle = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
SC_HANDLE serviceHandle = OpenService(serviceDbHandle, "OVRService", SC_MANAGER_ALL_ACCESS);
SERVICE_STATUS_PROCESS status;
DWORD bytesNeeded;
QueryServiceStatusEx(serviceHandle, SC_STATUS_PROCESS_INFO,(LPBYTE) &status,sizeof(SERVICE_STATUS_PROCESS), &bytesNeeded);
if (state == 0 || status.dwCurrentState == SERVICE_RUNNING)
{
// Stop it
BOOL b = ControlService(serviceHandle, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS) &status);
if (b)
{
printf("OVRService stopped\n");
_enable_ovr_service = 1;
}
else
printf("Error: OVRService failed to stop, please try running with Administrator rights\n");
}
else if (state == 1 && _enable_ovr_service)
{
// Start it
BOOL b = StartService(serviceHandle, NULL, NULL);
if (b)
printf("OVRService started\n");
else
printf("Error: OVRService failed to start, please try running with Administrator rights\n");
}
CloseServiceHandle(serviceHandle);
CloseServiceHandle(serviceDbHandle);
}
#endif

32
extern/openhmd/src/platform.h vendored Normal file
View File

@@ -0,0 +1,32 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2013 Fredrik Hultin.
* Copyright (C) 2013 Jakob Bornecrantz.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Internal Interface for Platform Specific Functions */
#ifndef PLATFORM_H
#define PLATFORM_H
#include "openhmd.h"
double ohmd_get_tick();
void ohmd_sleep(double seconds);
void ohmd_toggle_ovr_service(int state);
typedef struct ohmd_thread ohmd_thread;
typedef struct ohmd_mutex ohmd_mutex;
ohmd_mutex* ohmd_create_mutex(ohmd_context* ctx);
void ohmd_destroy_mutex(ohmd_mutex* mutex);
void ohmd_lock_mutex(ohmd_mutex* mutex);
void ohmd_unlock_mutex(ohmd_mutex* mutex);
ohmd_thread* ohmd_create_thread(ohmd_context* ctx, unsigned int (*routine)(void* arg), void* arg);
void ohmd_destroy_thread(ohmd_thread* thread);
#endif

97
extern/openhmd/src/queue.c vendored Normal file
View File

@@ -0,0 +1,97 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2016 Fredrik Hultin.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Naive Thread Safe Circular Queue Implementation */
#include <stdlib.h>
#include <string.h>
#include "queue.h"
#include "openhmdi.h"
struct ohmdq {
unsigned read_pos;
unsigned write_pos;
unsigned size;
unsigned max;
unsigned elem_size;
char* elems;
ohmd_mutex* mutex;
};
ohmdq* ohmdq_create(ohmd_context* ctx, unsigned elem_size, unsigned max)
{
ohmdq* me = ohmd_alloc(ctx, sizeof(ohmdq));
me->elems = ohmd_alloc(ctx, elem_size * max);
me->max = max;
me->elem_size = elem_size;
me->read_pos = 0;
me->write_pos = 0;
me->size = 0;
me->mutex = ohmd_create_mutex(ctx);
return me;
}
bool ohmdq_push(ohmdq* me, const void* elem)
{
bool ret = false;
ohmd_lock_mutex(me->mutex);
if(me->size < me->max){
memcpy(me->elems + me->write_pos, elem, me->elem_size);
me->write_pos = (me->write_pos + me->elem_size) % (me->max * me->elem_size);
me->size++;
ret = true;
}
ohmd_unlock_mutex(me->mutex);
return ret;
}
bool ohmdq_pop(ohmdq* me, void* out_elem)
{
bool ret = false;
ohmd_lock_mutex(me->mutex);
if(me->size > 0){
memcpy(out_elem, me->elems + me->read_pos, me->elem_size);
me->read_pos = (me->read_pos + me->elem_size) % (me->max * me->elem_size);
me->size--;
ret = true;
}
ohmd_unlock_mutex(me->mutex);
return ret;
}
unsigned ohmdq_get_size(ohmdq* me)
{
unsigned ret;
ohmd_lock_mutex(me->mutex);
ret = me->size;
ohmd_unlock_mutex(me->mutex);
return ret;
}
unsigned ohmdq_get_max(ohmdq* me)
{
return me->max;
}
void ohmdq_destroy(ohmdq* me)
{
free(me->elems);
ohmd_destroy_mutex(me->mutex);
free(me);
}

25
extern/openhmd/src/queue.h vendored Normal file
View File

@@ -0,0 +1,25 @@
/*
* OpenHMD - Free and Open Source API and drivers for immersive technology.
* Copyright (C) 2016 Fredrik Hultin.
* Distributed under the Boost 1.0 licence, see LICENSE for full text.
*/
/* Naive Thread Safe Circular Queue */
#ifndef OHMDQUEUE_H
#define OHMDQUEUE_H
#include <stdbool.h>
typedef struct ohmdq ohmdq;
typedef struct ohmd_context ohmd_context;
ohmdq* ohmdq_create(ohmd_context* ctx, unsigned elem_size, unsigned max);
void ohmdq_destroy(ohmdq* me);
bool ohmdq_push(ohmdq* me, const void* elem);
bool ohmdq_pop(ohmdq* me, void* out_elem);
unsigned ohmdq_get_size(ohmdq* me);
unsigned ohmdq_get_max(ohmdq* me);
#endif

55
extern/openhmd/src/shaders.c vendored Normal file
View File

@@ -0,0 +1,55 @@
const char * distortion_vert =
"#version 120\n"
"void main(void)\n"
"{\n"
"gl_TexCoord[0] = gl_MultiTexCoord0;\n"
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n"
"}";
const char * distortion_frag =
"#version 120\n"
"\n"
"//per eye texture to warp for lens distortion\n"
"uniform sampler2D warpTexture;\n"
"\n"
"//Position of lens center in m (usually eye_w/2, eye_h/2)\n"
"uniform vec2 LensCenter;\n"
"//Scale from texture co-ords to m (usually eye_w, eye_h)\n"
"uniform vec2 ViewportScale;\n"
"//Distortion overall scale in m (usually ~eye_w/2)\n"
"uniform float WarpScale;\n"
"//Distoriton coefficients (PanoTools model) [a,b,c,d]\n"
"uniform vec4 HmdWarpParam;\n"
"\n"
"//chromatic distortion post scaling\n"
"uniform vec3 aberr;\n"
"\n"
"void main()\n"
"{\n"
"//output_loc is the fragment location on screen from [0,1]x[0,1]\n"
"vec2 output_loc = vec2(gl_TexCoord[0].s, gl_TexCoord[0].t);\n"
"//Compute fragment location in lens-centered co-ordinates at world scale\n"
"vec2 r = output_loc * ViewportScale - LensCenter;\n"
"//scale for distortion model\n"
"//distortion model has r=1 being the largest circle inscribed (e.g. eye_w/2)\n"
"r /= WarpScale;\n"
"\n"
"//|r|**2\n"
"float r_mag = length(r);\n"
"//offset for which fragment is sourced\n"
"vec2 r_displaced = r * (HmdWarpParam.w + HmdWarpParam.z * r_mag +\n"
"HmdWarpParam.y * r_mag * r_mag +\n"
"HmdWarpParam.x * r_mag * r_mag * r_mag);\n"
"//back to world scale\n"
"r_displaced *= WarpScale;\n"
"//back to viewport co-ord\n"
"vec2 tc_r = (LensCenter + aberr.r * r_displaced) / ViewportScale;\n"
"vec2 tc_g = (LensCenter + aberr.g * r_displaced) / ViewportScale;\n"
"vec2 tc_b = (LensCenter + aberr.b * r_displaced) / ViewportScale;\n"
"\n"
"float red = texture2D(warpTexture, tc_r).r;\n"
"float green = texture2D(warpTexture, tc_g).g;\n"
"float blue = texture2D(warpTexture, tc_b).b;\n"
"//Black edges off the texture\n"
"gl_FragColor = ((tc_g.x < 0.0) || (tc_g.x > 1.0) || (tc_g.y < 0.0) || (tc_g.y > 1.0)) ? vec4(0.0, 0.0, 0.0, 1.0) : vec4(red, green, blue, 1.0);\n"
"}";

6
extern/openhmd/src/shaders.h vendored Normal file
View File

@@ -0,0 +1,6 @@
#ifndef SHADERS_H
#define SHADERS_H
const char * distortion_vert;
const char * distortion_frag;
#endif /* SHADERS_H */

View File

@@ -14,37 +14,25 @@
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# The Original Code is Copyright (C) 2017, Blender Foundation
# The Original Code is Copyright (C) 2016, Blender Foundation
# All rights reserved.
#
# The Original Code is: all of this file.
#
# Contributor(s): Bastien Montagne.
# Contributor(s): Sergey Sharybin.
#
# ***** END GPL LICENSE BLOCK *****
# -----------------------------------------------------------------------------
# Build msgfmt executable
set(INC
.
include
)
set(INC_SYS
blender_include_dirs(
../../../../intern/guardedalloc
../../blenlib
)
set(SRC
msgfmt.c
include/udew.h
src/udew.c
)
add_cc_flags_custom_test(msgfmt)
add_executable(msgfmt ${SRC})
target_link_libraries(msgfmt bf_blenlib)
target_link_libraries(msgfmt bf_intern_guardedalloc)
if(WIN32)
target_link_libraries(msgfmt bf_intern_utfconv)
endif()
target_link_libraries(msgfmt ${ZLIB_LIBRARIES})
target_link_libraries(msgfmt ${PLATFORM_LINKLIBS})
blender_add_lib(extern_udew "${SRC}" "${INC}" "${INC_SYS}")

174
extern/udew/LICENSE vendored Normal file
View File

@@ -0,0 +1,174 @@
Modified Apache 2.0 License
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
and its affiliates, except as required to comply with Section 4(c) of
the License and to reproduce 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.

14
extern/udew/README vendored Normal file
View File

@@ -0,0 +1,14 @@
The udev Extension Wrangler Library (UDEW) is a cross-platform open-source
C/C++ extension loading library. UDEW provides efficient run-time mechanisms
for determining which udev functions and extensions extensions are supported
on the target platform.
LICENSE
UDEW library is released under the Apache 2.0 license.
LIMITATIONS
- udev_device_get_parent_with_subsystem_devtype() need to be merged to a single
line in the geader before generating the wrangler with stubs support
- udev_set_log_fn() is not included into the stubs at all.

205
extern/udew/auto/libudev.h vendored Normal file
View File

@@ -0,0 +1,205 @@
/***
This file is part of systemd.
Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef _LIBUDEV_H_
#define _LIBUDEV_H_
#include <stdarg.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* udev - library context
*
* reads the udev config and system environment
* allows custom logging
*/
struct udev;
struct udev *udev_ref(struct udev *udev);
struct udev *udev_unref(struct udev *udev);
struct udev *udev_new(void);
void udev_set_log_fn(struct udev *udev,
void (*log_fn)(struct udev *udev,
int priority, const char *file, int line, const char *fn,
const char *format, va_list args)) __attribute__ ((deprecated));
int udev_get_log_priority(struct udev *udev) __attribute__ ((deprecated));
void udev_set_log_priority(struct udev *udev, int priority) __attribute__ ((deprecated));
void *udev_get_userdata(struct udev *udev);
void udev_set_userdata(struct udev *udev, void *userdata);
/*
* udev_list
*
* access to libudev generated lists
*/
struct udev_list_entry;
struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry);
struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name);
const char *udev_list_entry_get_name(struct udev_list_entry *list_entry);
const char *udev_list_entry_get_value(struct udev_list_entry *list_entry);
/**
* udev_list_entry_foreach:
* @list_entry: entry to store the current position
* @first_entry: first entry to start with
*
* Helper to iterate over all entries of a list.
*/
#define udev_list_entry_foreach(list_entry, first_entry) \
for (list_entry = first_entry; \
list_entry != NULL; \
list_entry = udev_list_entry_get_next(list_entry))
/*
* udev_device
*
* access to sysfs/kernel devices
*/
struct udev_device;
struct udev_device *udev_device_ref(struct udev_device *udev_device);
struct udev_device *udev_device_unref(struct udev_device *udev_device);
struct udev *udev_device_get_udev(struct udev_device *udev_device);
struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath);
struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum);
struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname);
struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id);
struct udev_device *udev_device_new_from_environment(struct udev *udev);
/* udev_device_get_parent_*() does not take a reference on the returned device, it is automatically unref'd with the parent */
struct udev_device *udev_device_get_parent(struct udev_device *udev_device);
struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype);
/* retrieve device properties */
const char *udev_device_get_devpath(struct udev_device *udev_device);
const char *udev_device_get_subsystem(struct udev_device *udev_device);
const char *udev_device_get_devtype(struct udev_device *udev_device);
const char *udev_device_get_syspath(struct udev_device *udev_device);
const char *udev_device_get_sysname(struct udev_device *udev_device);
const char *udev_device_get_sysnum(struct udev_device *udev_device);
const char *udev_device_get_devnode(struct udev_device *udev_device);
int udev_device_get_is_initialized(struct udev_device *udev_device);
struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device);
struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device);
struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device);
struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device);
const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key);
const char *udev_device_get_driver(struct udev_device *udev_device);
dev_t udev_device_get_devnum(struct udev_device *udev_device);
const char *udev_device_get_action(struct udev_device *udev_device);
unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device);
unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device);
const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr);
int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, char *value);
int udev_device_has_tag(struct udev_device *udev_device, const char *tag);
/*
* udev_monitor
*
* access to kernel uevents and udev events
*/
struct udev_monitor;
struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor);
struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor);
struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor);
/* kernel and udev generated events over netlink */
struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name);
/* bind socket */
int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor);
int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size);
int udev_monitor_get_fd(struct udev_monitor *udev_monitor);
struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor);
/* in-kernel socket filters to select messages that get delivered to a listener */
int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor,
const char *subsystem, const char *devtype);
int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag);
int udev_monitor_filter_update(struct udev_monitor *udev_monitor);
int udev_monitor_filter_remove(struct udev_monitor *udev_monitor);
/*
* udev_enumerate
*
* search sysfs for specific devices and provide a sorted list
*/
struct udev_enumerate;
struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate);
struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate);
struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate);
struct udev_enumerate *udev_enumerate_new(struct udev *udev);
/* device properties filter */
int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value);
int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value);
int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value);
int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname);
int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag);
int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent);
int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate);
int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath);
/* run enumeration with active filters */
int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate);
int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate);
/* return device list */
struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate);
/*
* udev_queue
*
* access to the currently running udev events
*/
struct udev_queue;
struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue);
struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue);
struct udev *udev_queue_get_udev(struct udev_queue *udev_queue);
struct udev_queue *udev_queue_new(struct udev *udev);
unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) __attribute__ ((deprecated));
unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) __attribute__ ((deprecated));
int udev_queue_get_udev_is_active(struct udev_queue *udev_queue);
int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue);
int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) __attribute__ ((deprecated));
int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue,
unsigned long long int start, unsigned long long int end) __attribute__ ((deprecated));
int udev_queue_get_fd(struct udev_queue *udev_queue);
int udev_queue_flush(struct udev_queue *udev_queue);
struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) __attribute__ ((deprecated));
/*
* udev_hwdb
*
* access to the static hardware properties database
*/
struct udev_hwdb;
struct udev_hwdb *udev_hwdb_new(struct udev *udev);
struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb);
struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb);
struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags);
/*
* udev_util
*
* udev specific utilities
*/
int udev_util_encode_string(const char *str, char *str_enc, size_t len);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

245
extern/udew/auto/udew_gen.sh vendored Executable file
View File

@@ -0,0 +1,245 @@
#!/bin/bash
#HEADER="/usr/include/libudev.h"
HEADER="libudev.h"
SCRIPT=`realpath -s $0`
DIR=`dirname $SCRIPT`
DIR=`dirname $DIR`
H="$DIR/include/udew.h"
C=$DIR/src/udew.c
STUBS=true
mkdir -p $DIR/include
mkdir -p $DIR/src
rm -rf $DIR/include/udew.h
rm -rf $DIR/src/udew.c
echo "Generating udew headers..."
append() {
f=`echo "$1" | sed ':a;N;$!ba;s/\n/\\\\n/g'`
line_num=`grep -n '#ifdef __cplusplus' $H | cut -d : -f 1 | tail -n 1`
gawk -i inplace "NR==$line_num {\$0=\"$f\n\n#ifdef __cplusplus\"} 1" $H
}
cat $HEADER \
| sed -r 's/^((const )?[a-z0-9_]+( [a-z0-9_]+)* \*?)([a-z0-9_]+)\(/typedef \1t\4(/i' \
> $H
if $STUBS; then
fp="_";
fi
f=`grep -E 'typedef ((const )?[a-z0-9_]+( [a-z0-9_]+)* \*?)t([a-z0-9_]+)\(' $H \
| sed -r "s/((const )?[a-z0-9_]+( [a-z0-9_]+)* \*?)t([a-z0-9_]+)\(.*/extern t\4 *$fp\4;/i"`
append "$f"
append "enum {\n\
UDEW_SUCCESS = 0,\n\
UDEW_ERROR_OPEN_FAILED = -1,\n\
UDEW_ERROR_ATEXIT_FAILED = -2,\n\
};\n\
\n\
int udewInit(void);"
if $STUBS; then
decl=`cat $HEADER \
| grep -E '^((const )?[a-z0-9_]+( [a-z0-9_]+)* \*?)([a-z0-9_]+)\(.*\);'`
append "$decl"
fi
sed -i 's/_LIBUDEV_H_/__UDEW_H__/g' $H
sed -i 's/ __attribute__ ((deprecated))//g' $H
line_num=`grep -n '\*\*\*/' $H | cut -d : -f 1`
for x in `seq $line_num`; do
sed -i '1d' $H
done
mv $H $H.tmp
cat << EOF > $H
/*
* Copyright 2016 Blender Foundation
*
* 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
*/
EOF
cat $H.tmp >> $H
rm $H.tmp
echo "Generating udew source..."
cat << EOF > $C
/*
* Copyright 2016 Blender Foundation
*
* 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
*/
#ifdef _MSC_VER
# define snprintf _snprintf
# define popen _popen
# define pclose _pclose
# define _CRT_SECURE_NO_WARNINGS
#endif
#include "udew.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
# define VC_EXTRALEAN
# include <windows.h>
/* Utility macros. */
typedef HMODULE DynamicLibrary;
# define dynamic_library_open(path) LoadLibrary(path)
# define dynamic_library_close(lib) FreeLibrary(lib)
# define dynamic_library_find(lib, symbol) GetProcAddress(lib, symbol)
#else
# include <dlfcn.h>
typedef void* DynamicLibrary;
# define dynamic_library_open(path) dlopen(path, RTLD_NOW)
# define dynamic_library_close(lib) dlclose(lib)
# define dynamic_library_find(lib, symbol) dlsym(lib, symbol)
#endif
#define GLUE(a, b) a ## b
#define UDEV_LIBRARY_FIND_CHECKED(name) \
GLUE(${fp}, name) = (t##name *)dynamic_library_find(lib, #name); \
assert(GLUE(${fp}, name));
#define UDEV_LIBRARY_FIND(name) \
GLUE(${fp}, name) = (t##name *)dynamic_library_find(lib, #name);
static DynamicLibrary lib;
EOF
content=`grep --no-filename -ER "extern t" $DIR/include/udew.h`
echo "$content" | sed -r "s/extern t([a-z0-9_]+).*/t\1 *$fp\1;/gi" >> $C
cat << EOF >> $C
static DynamicLibrary dynamic_library_open_find(const char **paths) {
int i = 0;
while (paths[i] != NULL) {
DynamicLibrary lib = dynamic_library_open(paths[i]);
if (lib != NULL) {
return lib;
}
++i;
}
return NULL;
}
static void udewExit(void) {
if(lib != NULL) {
/* Ignore errors. */
dynamic_library_close(lib);
lib = NULL;
}
}
/* Implementation function. */
int udewInit(void) {
/* Library paths. */
#ifdef _WIN32
/* Expected in c:/windows/system or similar, no path needed. */
const char *paths[] = {"udev.dll", NULL};
#elif defined(__APPLE__)
/* Default installation path. */
const char *paths[] = {"libudev.dylib", NULL};
#else
const char *paths[] = {"libudev.so",
"libudev.so.0",
"libudev.so.1",
"libudev.so.2",
NULL};
#endif
static int initialized = 0;
static int result = 0;
int error;
if (initialized) {
return result;
}
initialized = 1;
error = atexit(udewExit);
if (error) {
result = UDEW_ERROR_ATEXIT_FAILED;
return result;
}
/* Load library. */
lib = dynamic_library_open_find(paths);
if (lib == NULL) {
result = UDEW_ERROR_OPEN_FAILED;
return result;
}
EOF
echo "$content" | sed -r 's/extern t([a-z0-9_]+).*/ UDEV_LIBRARY_FIND(\1);/gi' >> $C
cat << EOF >> $C
result = UDEW_SUCCESS;
return result;
}
EOF
if $STUBS; then
echo "" >> $C
echo "$decl" | while read l; do
h=`echo "$l" | sed -r 's/;//' | sed 's/ __attribute__ ((deprecated))//'`
echo "$h {" >> $C
f=`echo $h | sed -r 's/^((const )?[a-z0-9_]+( [a-z0-9_]+)* \*?)([a-z0-9_]+)\(.*/\4/i'`
args=`echo $h | sed -r 's/^((const )?[a-z0-9_]+( [a-z0-9_]+)* \*?)([a-z0-9_]+)\((.*)\).*?/\5/i'`
args=`echo $args | python -c "import sys; l=sys.stdin.readline(); l=l.strip(); print(', '.join([x.split(' ')[-1].replace('*', '') for x in l.split(',')]))"`
if [ "$args" = "void" ]; then
args=""
fi
echo " return $fp$f($args);" >> $C
echo -e "}\n" >> $C
done
fi

389
extern/udew/include/udew.h vendored Normal file
View File

@@ -0,0 +1,389 @@
/*
* Copyright 2016 Blender Foundation
*
* 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 __UDEW_H__
#define __UDEW_H__
#include <stdarg.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* udev - library context
*
* reads the udev config and system environment
* allows custom logging
*/
struct udev;
typedef struct udev *tudev_ref(struct udev *udev);
typedef struct udev *tudev_unref(struct udev *udev);
typedef struct udev *tudev_new(void);
typedef void tudev_set_log_fn(struct udev *udev,
void (*log_fn)(struct udev *udev,
int priority, const char *file, int line, const char *fn,
const char *format, va_list args));
typedef int tudev_get_log_priority(struct udev *udev);
typedef void tudev_set_log_priority(struct udev *udev, int priority);
typedef void *tudev_get_userdata(struct udev *udev);
typedef void tudev_set_userdata(struct udev *udev, void *userdata);
/*
* udev_list
*
* access to libudev generated lists
*/
struct udev_list_entry;
typedef struct udev_list_entry *tudev_list_entry_get_next(struct udev_list_entry *list_entry);
typedef struct udev_list_entry *tudev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name);
typedef const char *tudev_list_entry_get_name(struct udev_list_entry *list_entry);
typedef const char *tudev_list_entry_get_value(struct udev_list_entry *list_entry);
/**
* udev_list_entry_foreach:
* @list_entry: entry to store the current position
* @first_entry: first entry to start with
*
* Helper to iterate over all entries of a list.
*/
#define udev_list_entry_foreach(list_entry, first_entry) \
for (list_entry = first_entry; \
list_entry != NULL; \
list_entry = udev_list_entry_get_next(list_entry))
/*
* udev_device
*
* access to sysfs/kernel devices
*/
struct udev_device;
typedef struct udev_device *tudev_device_ref(struct udev_device *udev_device);
typedef struct udev_device *tudev_device_unref(struct udev_device *udev_device);
typedef struct udev *tudev_device_get_udev(struct udev_device *udev_device);
typedef struct udev_device *tudev_device_new_from_syspath(struct udev *udev, const char *syspath);
typedef struct udev_device *tudev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum);
typedef struct udev_device *tudev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname);
typedef struct udev_device *tudev_device_new_from_device_id(struct udev *udev, const char *id);
typedef struct udev_device *tudev_device_new_from_environment(struct udev *udev);
/* udev_device_get_parent_*() does not take a reference on the returned device, it is automatically unref'd with the parent */
typedef struct udev_device *tudev_device_get_parent(struct udev_device *udev_device);
typedef struct udev_device *tudev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype);
/* retrieve device properties */
typedef const char *tudev_device_get_devpath(struct udev_device *udev_device);
typedef const char *tudev_device_get_subsystem(struct udev_device *udev_device);
typedef const char *tudev_device_get_devtype(struct udev_device *udev_device);
typedef const char *tudev_device_get_syspath(struct udev_device *udev_device);
typedef const char *tudev_device_get_sysname(struct udev_device *udev_device);
typedef const char *tudev_device_get_sysnum(struct udev_device *udev_device);
typedef const char *tudev_device_get_devnode(struct udev_device *udev_device);
typedef int tudev_device_get_is_initialized(struct udev_device *udev_device);
typedef struct udev_list_entry *tudev_device_get_devlinks_list_entry(struct udev_device *udev_device);
typedef struct udev_list_entry *tudev_device_get_properties_list_entry(struct udev_device *udev_device);
typedef struct udev_list_entry *tudev_device_get_tags_list_entry(struct udev_device *udev_device);
typedef struct udev_list_entry *tudev_device_get_sysattr_list_entry(struct udev_device *udev_device);
typedef const char *tudev_device_get_property_value(struct udev_device *udev_device, const char *key);
typedef const char *tudev_device_get_driver(struct udev_device *udev_device);
typedef dev_t tudev_device_get_devnum(struct udev_device *udev_device);
typedef const char *tudev_device_get_action(struct udev_device *udev_device);
typedef unsigned long long int tudev_device_get_seqnum(struct udev_device *udev_device);
typedef unsigned long long int tudev_device_get_usec_since_initialized(struct udev_device *udev_device);
typedef const char *tudev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr);
typedef int tudev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, char *value);
typedef int tudev_device_has_tag(struct udev_device *udev_device, const char *tag);
/*
* udev_monitor
*
* access to kernel uevents and udev events
*/
struct udev_monitor;
typedef struct udev_monitor *tudev_monitor_ref(struct udev_monitor *udev_monitor);
typedef struct udev_monitor *tudev_monitor_unref(struct udev_monitor *udev_monitor);
typedef struct udev *tudev_monitor_get_udev(struct udev_monitor *udev_monitor);
/* kernel and udev generated events over netlink */
typedef struct udev_monitor *tudev_monitor_new_from_netlink(struct udev *udev, const char *name);
/* bind socket */
typedef int tudev_monitor_enable_receiving(struct udev_monitor *udev_monitor);
typedef int tudev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size);
typedef int tudev_monitor_get_fd(struct udev_monitor *udev_monitor);
typedef struct udev_device *tudev_monitor_receive_device(struct udev_monitor *udev_monitor);
/* in-kernel socket filters to select messages that get delivered to a listener */
typedef int tudev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor,
const char *subsystem, const char *devtype);
typedef int tudev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag);
typedef int tudev_monitor_filter_update(struct udev_monitor *udev_monitor);
typedef int tudev_monitor_filter_remove(struct udev_monitor *udev_monitor);
/*
* udev_enumerate
*
* search sysfs for specific devices and provide a sorted list
*/
struct udev_enumerate;
typedef struct udev_enumerate *tudev_enumerate_ref(struct udev_enumerate *udev_enumerate);
typedef struct udev_enumerate *tudev_enumerate_unref(struct udev_enumerate *udev_enumerate);
typedef struct udev *tudev_enumerate_get_udev(struct udev_enumerate *udev_enumerate);
typedef struct udev_enumerate *tudev_enumerate_new(struct udev *udev);
/* device properties filter */
typedef int tudev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
typedef int tudev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
typedef int tudev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value);
typedef int tudev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value);
typedef int tudev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value);
typedef int tudev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname);
typedef int tudev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag);
typedef int tudev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent);
typedef int tudev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate);
typedef int tudev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath);
/* run enumeration with active filters */
typedef int tudev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate);
typedef int tudev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate);
/* return device list */
typedef struct udev_list_entry *tudev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate);
/*
* udev_queue
*
* access to the currently running udev events
*/
struct udev_queue;
typedef struct udev_queue *tudev_queue_ref(struct udev_queue *udev_queue);
typedef struct udev_queue *tudev_queue_unref(struct udev_queue *udev_queue);
typedef struct udev *tudev_queue_get_udev(struct udev_queue *udev_queue);
typedef struct udev_queue *tudev_queue_new(struct udev *udev);
typedef unsigned long long int tudev_queue_get_kernel_seqnum(struct udev_queue *udev_queue);
typedef unsigned long long int tudev_queue_get_udev_seqnum(struct udev_queue *udev_queue);
typedef int tudev_queue_get_udev_is_active(struct udev_queue *udev_queue);
typedef int tudev_queue_get_queue_is_empty(struct udev_queue *udev_queue);
typedef int tudev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum);
typedef int tudev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue,
unsigned long long int start, unsigned long long int end);
typedef int tudev_queue_get_fd(struct udev_queue *udev_queue);
typedef int tudev_queue_flush(struct udev_queue *udev_queue);
typedef struct udev_list_entry *tudev_queue_get_queued_list_entry(struct udev_queue *udev_queue);
/*
* udev_hwdb
*
* access to the static hardware properties database
*/
struct udev_hwdb;
typedef struct udev_hwdb *tudev_hwdb_new(struct udev *udev);
typedef struct udev_hwdb *tudev_hwdb_ref(struct udev_hwdb *hwdb);
typedef struct udev_hwdb *tudev_hwdb_unref(struct udev_hwdb *hwdb);
typedef struct udev_list_entry *tudev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags);
/*
* udev_util
*
* udev specific utilities
*/
typedef int tudev_util_encode_string(const char *str, char *str_enc, size_t len);
extern tudev_ref *_udev_ref;
extern tudev_unref *_udev_unref;
extern tudev_new *_udev_new;
extern tudev_set_log_fn *_udev_set_log_fn;
extern tudev_get_log_priority *_udev_get_log_priority;
extern tudev_set_log_priority *_udev_set_log_priority;
extern tudev_get_userdata *_udev_get_userdata;
extern tudev_set_userdata *_udev_set_userdata;
extern tudev_list_entry_get_next *_udev_list_entry_get_next;
extern tudev_list_entry_get_by_name *_udev_list_entry_get_by_name;
extern tudev_list_entry_get_name *_udev_list_entry_get_name;
extern tudev_list_entry_get_value *_udev_list_entry_get_value;
extern tudev_device_ref *_udev_device_ref;
extern tudev_device_unref *_udev_device_unref;
extern tudev_device_get_udev *_udev_device_get_udev;
extern tudev_device_new_from_syspath *_udev_device_new_from_syspath;
extern tudev_device_new_from_devnum *_udev_device_new_from_devnum;
extern tudev_device_new_from_subsystem_sysname *_udev_device_new_from_subsystem_sysname;
extern tudev_device_new_from_device_id *_udev_device_new_from_device_id;
extern tudev_device_new_from_environment *_udev_device_new_from_environment;
extern tudev_device_get_parent *_udev_device_get_parent;
extern tudev_device_get_parent_with_subsystem_devtype *_udev_device_get_parent_with_subsystem_devtype;
extern tudev_device_get_devpath *_udev_device_get_devpath;
extern tudev_device_get_subsystem *_udev_device_get_subsystem;
extern tudev_device_get_devtype *_udev_device_get_devtype;
extern tudev_device_get_syspath *_udev_device_get_syspath;
extern tudev_device_get_sysname *_udev_device_get_sysname;
extern tudev_device_get_sysnum *_udev_device_get_sysnum;
extern tudev_device_get_devnode *_udev_device_get_devnode;
extern tudev_device_get_is_initialized *_udev_device_get_is_initialized;
extern tudev_device_get_devlinks_list_entry *_udev_device_get_devlinks_list_entry;
extern tudev_device_get_properties_list_entry *_udev_device_get_properties_list_entry;
extern tudev_device_get_tags_list_entry *_udev_device_get_tags_list_entry;
extern tudev_device_get_sysattr_list_entry *_udev_device_get_sysattr_list_entry;
extern tudev_device_get_property_value *_udev_device_get_property_value;
extern tudev_device_get_driver *_udev_device_get_driver;
extern tudev_device_get_devnum *_udev_device_get_devnum;
extern tudev_device_get_action *_udev_device_get_action;
extern tudev_device_get_seqnum *_udev_device_get_seqnum;
extern tudev_device_get_usec_since_initialized *_udev_device_get_usec_since_initialized;
extern tudev_device_get_sysattr_value *_udev_device_get_sysattr_value;
extern tudev_device_set_sysattr_value *_udev_device_set_sysattr_value;
extern tudev_device_has_tag *_udev_device_has_tag;
extern tudev_monitor_ref *_udev_monitor_ref;
extern tudev_monitor_unref *_udev_monitor_unref;
extern tudev_monitor_get_udev *_udev_monitor_get_udev;
extern tudev_monitor_new_from_netlink *_udev_monitor_new_from_netlink;
extern tudev_monitor_enable_receiving *_udev_monitor_enable_receiving;
extern tudev_monitor_set_receive_buffer_size *_udev_monitor_set_receive_buffer_size;
extern tudev_monitor_get_fd *_udev_monitor_get_fd;
extern tudev_monitor_receive_device *_udev_monitor_receive_device;
extern tudev_monitor_filter_add_match_subsystem_devtype *_udev_monitor_filter_add_match_subsystem_devtype;
extern tudev_monitor_filter_add_match_tag *_udev_monitor_filter_add_match_tag;
extern tudev_monitor_filter_update *_udev_monitor_filter_update;
extern tudev_monitor_filter_remove *_udev_monitor_filter_remove;
extern tudev_enumerate_ref *_udev_enumerate_ref;
extern tudev_enumerate_unref *_udev_enumerate_unref;
extern tudev_enumerate_get_udev *_udev_enumerate_get_udev;
extern tudev_enumerate_new *_udev_enumerate_new;
extern tudev_enumerate_add_match_subsystem *_udev_enumerate_add_match_subsystem;
extern tudev_enumerate_add_nomatch_subsystem *_udev_enumerate_add_nomatch_subsystem;
extern tudev_enumerate_add_match_sysattr *_udev_enumerate_add_match_sysattr;
extern tudev_enumerate_add_nomatch_sysattr *_udev_enumerate_add_nomatch_sysattr;
extern tudev_enumerate_add_match_property *_udev_enumerate_add_match_property;
extern tudev_enumerate_add_match_sysname *_udev_enumerate_add_match_sysname;
extern tudev_enumerate_add_match_tag *_udev_enumerate_add_match_tag;
extern tudev_enumerate_add_match_parent *_udev_enumerate_add_match_parent;
extern tudev_enumerate_add_match_is_initialized *_udev_enumerate_add_match_is_initialized;
extern tudev_enumerate_add_syspath *_udev_enumerate_add_syspath;
extern tudev_enumerate_scan_devices *_udev_enumerate_scan_devices;
extern tudev_enumerate_scan_subsystems *_udev_enumerate_scan_subsystems;
extern tudev_enumerate_get_list_entry *_udev_enumerate_get_list_entry;
extern tudev_queue_ref *_udev_queue_ref;
extern tudev_queue_unref *_udev_queue_unref;
extern tudev_queue_get_udev *_udev_queue_get_udev;
extern tudev_queue_new *_udev_queue_new;
extern tudev_queue_get_kernel_seqnum *_udev_queue_get_kernel_seqnum;
extern tudev_queue_get_udev_seqnum *_udev_queue_get_udev_seqnum;
extern tudev_queue_get_udev_is_active *_udev_queue_get_udev_is_active;
extern tudev_queue_get_queue_is_empty *_udev_queue_get_queue_is_empty;
extern tudev_queue_get_seqnum_is_finished *_udev_queue_get_seqnum_is_finished;
extern tudev_queue_get_seqnum_sequence_is_finished *_udev_queue_get_seqnum_sequence_is_finished;
extern tudev_queue_get_fd *_udev_queue_get_fd;
extern tudev_queue_flush *_udev_queue_flush;
extern tudev_queue_get_queued_list_entry *_udev_queue_get_queued_list_entry;
extern tudev_hwdb_new *_udev_hwdb_new;
extern tudev_hwdb_ref *_udev_hwdb_ref;
extern tudev_hwdb_unref *_udev_hwdb_unref;
extern tudev_hwdb_get_properties_list_entry *_udev_hwdb_get_properties_list_entry;
extern tudev_util_encode_string *_udev_util_encode_string;
enum {
UDEW_SUCCESS = 0,
UDEW_ERROR_OPEN_FAILED = -1,
UDEW_ERROR_ATEXIT_FAILED = -2,
};
int udewInit(void);
struct udev *udev_ref(struct udev *udev);
struct udev *udev_unref(struct udev *udev);
struct udev *udev_new(void);
int udev_get_log_priority(struct udev *udev);
void udev_set_log_priority(struct udev *udev, int priority);
void *udev_get_userdata(struct udev *udev);
void udev_set_userdata(struct udev *udev, void *userdata);
struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry);
struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name);
const char *udev_list_entry_get_name(struct udev_list_entry *list_entry);
const char *udev_list_entry_get_value(struct udev_list_entry *list_entry);
struct udev_device *udev_device_ref(struct udev_device *udev_device);
struct udev_device *udev_device_unref(struct udev_device *udev_device);
struct udev *udev_device_get_udev(struct udev_device *udev_device);
struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath);
struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum);
struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname);
struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id);
struct udev_device *udev_device_new_from_environment(struct udev *udev);
struct udev_device *udev_device_get_parent(struct udev_device *udev_device);
struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype);
const char *udev_device_get_devpath(struct udev_device *udev_device);
const char *udev_device_get_subsystem(struct udev_device *udev_device);
const char *udev_device_get_devtype(struct udev_device *udev_device);
const char *udev_device_get_syspath(struct udev_device *udev_device);
const char *udev_device_get_sysname(struct udev_device *udev_device);
const char *udev_device_get_sysnum(struct udev_device *udev_device);
const char *udev_device_get_devnode(struct udev_device *udev_device);
int udev_device_get_is_initialized(struct udev_device *udev_device);
struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device);
struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device);
struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device);
struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device);
const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key);
const char *udev_device_get_driver(struct udev_device *udev_device);
dev_t udev_device_get_devnum(struct udev_device *udev_device);
const char *udev_device_get_action(struct udev_device *udev_device);
unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device);
unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device);
const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr);
int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, char *value);
int udev_device_has_tag(struct udev_device *udev_device, const char *tag);
struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor);
struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor);
struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor);
struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name);
int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor);
int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size);
int udev_monitor_get_fd(struct udev_monitor *udev_monitor);
struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor);
int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag);
int udev_monitor_filter_update(struct udev_monitor *udev_monitor);
int udev_monitor_filter_remove(struct udev_monitor *udev_monitor);
struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate);
struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate);
struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate);
struct udev_enumerate *udev_enumerate_new(struct udev *udev);
int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value);
int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value);
int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value);
int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname);
int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag);
int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent);
int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate);
int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath);
int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate);
int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate);
struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate);
struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue);
struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue);
struct udev *udev_queue_get_udev(struct udev_queue *udev_queue);
struct udev_queue *udev_queue_new(struct udev *udev);
unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue);
unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue);
int udev_queue_get_udev_is_active(struct udev_queue *udev_queue);
int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue);
int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum);
int udev_queue_get_fd(struct udev_queue *udev_queue);
int udev_queue_flush(struct udev_queue *udev_queue);
struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue);
struct udev_hwdb *udev_hwdb_new(struct udev *udev);
struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb);
struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb);
struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags);
int udev_util_encode_string(const char *str, char *str_enc, size_t len);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

656
extern/udew/src/udew.c vendored Normal file
View File

@@ -0,0 +1,656 @@
/*
* Copyright 2016 Blender Foundation
*
* 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
*/
#ifdef _MSC_VER
# define snprintf _snprintf
# define popen _popen
# define pclose _pclose
# define _CRT_SECURE_NO_WARNINGS
#endif
#include "udew.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
# define VC_EXTRALEAN
# include <windows.h>
/* Utility macros. */
typedef HMODULE DynamicLibrary;
# define dynamic_library_open(path) LoadLibrary(path)
# define dynamic_library_close(lib) FreeLibrary(lib)
# define dynamic_library_find(lib, symbol) GetProcAddress(lib, symbol)
#else
# include <dlfcn.h>
typedef void* DynamicLibrary;
# define dynamic_library_open(path) dlopen(path, RTLD_NOW)
# define dynamic_library_close(lib) dlclose(lib)
# define dynamic_library_find(lib, symbol) dlsym(lib, symbol)
#endif
#define GLUE(a, b) a ## b
#define UDEV_LIBRARY_FIND_CHECKED(name) GLUE(_, name) = (t##name *)dynamic_library_find(lib, #name); assert(GLUE(_, name));
#define UDEV_LIBRARY_FIND(name) GLUE(_, name) = (t##name *)dynamic_library_find(lib, #name);
static DynamicLibrary lib;
tudev_ref *_udev_ref;
tudev_unref *_udev_unref;
tudev_new *_udev_new;
tudev_set_log_fn *_udev_set_log_fn;
tudev_get_log_priority *_udev_get_log_priority;
tudev_set_log_priority *_udev_set_log_priority;
tudev_get_userdata *_udev_get_userdata;
tudev_set_userdata *_udev_set_userdata;
tudev_list_entry_get_next *_udev_list_entry_get_next;
tudev_list_entry_get_by_name *_udev_list_entry_get_by_name;
tudev_list_entry_get_name *_udev_list_entry_get_name;
tudev_list_entry_get_value *_udev_list_entry_get_value;
tudev_device_ref *_udev_device_ref;
tudev_device_unref *_udev_device_unref;
tudev_device_get_udev *_udev_device_get_udev;
tudev_device_new_from_syspath *_udev_device_new_from_syspath;
tudev_device_new_from_devnum *_udev_device_new_from_devnum;
tudev_device_new_from_subsystem_sysname *_udev_device_new_from_subsystem_sysname;
tudev_device_new_from_device_id *_udev_device_new_from_device_id;
tudev_device_new_from_environment *_udev_device_new_from_environment;
tudev_device_get_parent *_udev_device_get_parent;
tudev_device_get_parent_with_subsystem_devtype *_udev_device_get_parent_with_subsystem_devtype;
tudev_device_get_devpath *_udev_device_get_devpath;
tudev_device_get_subsystem *_udev_device_get_subsystem;
tudev_device_get_devtype *_udev_device_get_devtype;
tudev_device_get_syspath *_udev_device_get_syspath;
tudev_device_get_sysname *_udev_device_get_sysname;
tudev_device_get_sysnum *_udev_device_get_sysnum;
tudev_device_get_devnode *_udev_device_get_devnode;
tudev_device_get_is_initialized *_udev_device_get_is_initialized;
tudev_device_get_devlinks_list_entry *_udev_device_get_devlinks_list_entry;
tudev_device_get_properties_list_entry *_udev_device_get_properties_list_entry;
tudev_device_get_tags_list_entry *_udev_device_get_tags_list_entry;
tudev_device_get_sysattr_list_entry *_udev_device_get_sysattr_list_entry;
tudev_device_get_property_value *_udev_device_get_property_value;
tudev_device_get_driver *_udev_device_get_driver;
tudev_device_get_devnum *_udev_device_get_devnum;
tudev_device_get_action *_udev_device_get_action;
tudev_device_get_seqnum *_udev_device_get_seqnum;
tudev_device_get_usec_since_initialized *_udev_device_get_usec_since_initialized;
tudev_device_get_sysattr_value *_udev_device_get_sysattr_value;
tudev_device_set_sysattr_value *_udev_device_set_sysattr_value;
tudev_device_has_tag *_udev_device_has_tag;
tudev_monitor_ref *_udev_monitor_ref;
tudev_monitor_unref *_udev_monitor_unref;
tudev_monitor_get_udev *_udev_monitor_get_udev;
tudev_monitor_new_from_netlink *_udev_monitor_new_from_netlink;
tudev_monitor_enable_receiving *_udev_monitor_enable_receiving;
tudev_monitor_set_receive_buffer_size *_udev_monitor_set_receive_buffer_size;
tudev_monitor_get_fd *_udev_monitor_get_fd;
tudev_monitor_receive_device *_udev_monitor_receive_device;
tudev_monitor_filter_add_match_subsystem_devtype *_udev_monitor_filter_add_match_subsystem_devtype;
tudev_monitor_filter_add_match_tag *_udev_monitor_filter_add_match_tag;
tudev_monitor_filter_update *_udev_monitor_filter_update;
tudev_monitor_filter_remove *_udev_monitor_filter_remove;
tudev_enumerate_ref *_udev_enumerate_ref;
tudev_enumerate_unref *_udev_enumerate_unref;
tudev_enumerate_get_udev *_udev_enumerate_get_udev;
tudev_enumerate_new *_udev_enumerate_new;
tudev_enumerate_add_match_subsystem *_udev_enumerate_add_match_subsystem;
tudev_enumerate_add_nomatch_subsystem *_udev_enumerate_add_nomatch_subsystem;
tudev_enumerate_add_match_sysattr *_udev_enumerate_add_match_sysattr;
tudev_enumerate_add_nomatch_sysattr *_udev_enumerate_add_nomatch_sysattr;
tudev_enumerate_add_match_property *_udev_enumerate_add_match_property;
tudev_enumerate_add_match_sysname *_udev_enumerate_add_match_sysname;
tudev_enumerate_add_match_tag *_udev_enumerate_add_match_tag;
tudev_enumerate_add_match_parent *_udev_enumerate_add_match_parent;
tudev_enumerate_add_match_is_initialized *_udev_enumerate_add_match_is_initialized;
tudev_enumerate_add_syspath *_udev_enumerate_add_syspath;
tudev_enumerate_scan_devices *_udev_enumerate_scan_devices;
tudev_enumerate_scan_subsystems *_udev_enumerate_scan_subsystems;
tudev_enumerate_get_list_entry *_udev_enumerate_get_list_entry;
tudev_queue_ref *_udev_queue_ref;
tudev_queue_unref *_udev_queue_unref;
tudev_queue_get_udev *_udev_queue_get_udev;
tudev_queue_new *_udev_queue_new;
tudev_queue_get_kernel_seqnum *_udev_queue_get_kernel_seqnum;
tudev_queue_get_udev_seqnum *_udev_queue_get_udev_seqnum;
tudev_queue_get_udev_is_active *_udev_queue_get_udev_is_active;
tudev_queue_get_queue_is_empty *_udev_queue_get_queue_is_empty;
tudev_queue_get_seqnum_is_finished *_udev_queue_get_seqnum_is_finished;
tudev_queue_get_seqnum_sequence_is_finished *_udev_queue_get_seqnum_sequence_is_finished;
tudev_queue_get_fd *_udev_queue_get_fd;
tudev_queue_flush *_udev_queue_flush;
tudev_queue_get_queued_list_entry *_udev_queue_get_queued_list_entry;
tudev_hwdb_new *_udev_hwdb_new;
tudev_hwdb_ref *_udev_hwdb_ref;
tudev_hwdb_unref *_udev_hwdb_unref;
tudev_hwdb_get_properties_list_entry *_udev_hwdb_get_properties_list_entry;
tudev_util_encode_string *_udev_util_encode_string;
static DynamicLibrary dynamic_library_open_find(const char **paths) {
int i = 0;
while (paths[i] != NULL) {
DynamicLibrary lib = dynamic_library_open(paths[i]);
if (lib != NULL) {
return lib;
}
++i;
}
return NULL;
}
static void udewExit(void) {
if(lib != NULL) {
/* Ignore errors. */
dynamic_library_close(lib);
lib = NULL;
}
}
/* Implementation function. */
int udewInit(void) {
/* Library paths. */
#ifdef _WIN32
/* Expected in c:/windows/system or similar, no path needed. */
const char *paths[] = {"udev.dll", NULL};
#elif defined(__APPLE__)
/* Default installation path. */
const char *paths[] = {"libudev.dylib", NULL};
#else
const char *paths[] = {"libudev.so",
"libudev.so.0",
"libudev.so.1",
"libudev.so.2",
NULL};
#endif
static int initialized = 0;
static int result = 0;
int error;
if (initialized) {
return result;
}
initialized = 1;
error = atexit(udewExit);
if (error) {
result = UDEW_ERROR_ATEXIT_FAILED;
return result;
}
/* Load library. */
lib = dynamic_library_open_find(paths);
if (lib == NULL) {
result = UDEW_ERROR_OPEN_FAILED;
return result;
}
UDEV_LIBRARY_FIND(udev_ref);
UDEV_LIBRARY_FIND(udev_unref);
UDEV_LIBRARY_FIND(udev_new);
UDEV_LIBRARY_FIND(udev_set_log_fn);
UDEV_LIBRARY_FIND(udev_get_log_priority);
UDEV_LIBRARY_FIND(udev_set_log_priority);
UDEV_LIBRARY_FIND(udev_get_userdata);
UDEV_LIBRARY_FIND(udev_set_userdata);
UDEV_LIBRARY_FIND(udev_list_entry_get_next);
UDEV_LIBRARY_FIND(udev_list_entry_get_by_name);
UDEV_LIBRARY_FIND(udev_list_entry_get_name);
UDEV_LIBRARY_FIND(udev_list_entry_get_value);
UDEV_LIBRARY_FIND(udev_device_ref);
UDEV_LIBRARY_FIND(udev_device_unref);
UDEV_LIBRARY_FIND(udev_device_get_udev);
UDEV_LIBRARY_FIND(udev_device_new_from_syspath);
UDEV_LIBRARY_FIND(udev_device_new_from_devnum);
UDEV_LIBRARY_FIND(udev_device_new_from_subsystem_sysname);
UDEV_LIBRARY_FIND(udev_device_new_from_device_id);
UDEV_LIBRARY_FIND(udev_device_new_from_environment);
UDEV_LIBRARY_FIND(udev_device_get_parent);
UDEV_LIBRARY_FIND(udev_device_get_parent_with_subsystem_devtype);
UDEV_LIBRARY_FIND(udev_device_get_devpath);
UDEV_LIBRARY_FIND(udev_device_get_subsystem);
UDEV_LIBRARY_FIND(udev_device_get_devtype);
UDEV_LIBRARY_FIND(udev_device_get_syspath);
UDEV_LIBRARY_FIND(udev_device_get_sysname);
UDEV_LIBRARY_FIND(udev_device_get_sysnum);
UDEV_LIBRARY_FIND(udev_device_get_devnode);
UDEV_LIBRARY_FIND(udev_device_get_is_initialized);
UDEV_LIBRARY_FIND(udev_device_get_devlinks_list_entry);
UDEV_LIBRARY_FIND(udev_device_get_properties_list_entry);
UDEV_LIBRARY_FIND(udev_device_get_tags_list_entry);
UDEV_LIBRARY_FIND(udev_device_get_sysattr_list_entry);
UDEV_LIBRARY_FIND(udev_device_get_property_value);
UDEV_LIBRARY_FIND(udev_device_get_driver);
UDEV_LIBRARY_FIND(udev_device_get_devnum);
UDEV_LIBRARY_FIND(udev_device_get_action);
UDEV_LIBRARY_FIND(udev_device_get_seqnum);
UDEV_LIBRARY_FIND(udev_device_get_usec_since_initialized);
UDEV_LIBRARY_FIND(udev_device_get_sysattr_value);
UDEV_LIBRARY_FIND(udev_device_set_sysattr_value);
UDEV_LIBRARY_FIND(udev_device_has_tag);
UDEV_LIBRARY_FIND(udev_monitor_ref);
UDEV_LIBRARY_FIND(udev_monitor_unref);
UDEV_LIBRARY_FIND(udev_monitor_get_udev);
UDEV_LIBRARY_FIND(udev_monitor_new_from_netlink);
UDEV_LIBRARY_FIND(udev_monitor_enable_receiving);
UDEV_LIBRARY_FIND(udev_monitor_set_receive_buffer_size);
UDEV_LIBRARY_FIND(udev_monitor_get_fd);
UDEV_LIBRARY_FIND(udev_monitor_receive_device);
UDEV_LIBRARY_FIND(udev_monitor_filter_add_match_subsystem_devtype);
UDEV_LIBRARY_FIND(udev_monitor_filter_add_match_tag);
UDEV_LIBRARY_FIND(udev_monitor_filter_update);
UDEV_LIBRARY_FIND(udev_monitor_filter_remove);
UDEV_LIBRARY_FIND(udev_enumerate_ref);
UDEV_LIBRARY_FIND(udev_enumerate_unref);
UDEV_LIBRARY_FIND(udev_enumerate_get_udev);
UDEV_LIBRARY_FIND(udev_enumerate_new);
UDEV_LIBRARY_FIND(udev_enumerate_add_match_subsystem);
UDEV_LIBRARY_FIND(udev_enumerate_add_nomatch_subsystem);
UDEV_LIBRARY_FIND(udev_enumerate_add_match_sysattr);
UDEV_LIBRARY_FIND(udev_enumerate_add_nomatch_sysattr);
UDEV_LIBRARY_FIND(udev_enumerate_add_match_property);
UDEV_LIBRARY_FIND(udev_enumerate_add_match_sysname);
UDEV_LIBRARY_FIND(udev_enumerate_add_match_tag);
UDEV_LIBRARY_FIND(udev_enumerate_add_match_parent);
UDEV_LIBRARY_FIND(udev_enumerate_add_match_is_initialized);
UDEV_LIBRARY_FIND(udev_enumerate_add_syspath);
UDEV_LIBRARY_FIND(udev_enumerate_scan_devices);
UDEV_LIBRARY_FIND(udev_enumerate_scan_subsystems);
UDEV_LIBRARY_FIND(udev_enumerate_get_list_entry);
UDEV_LIBRARY_FIND(udev_queue_ref);
UDEV_LIBRARY_FIND(udev_queue_unref);
UDEV_LIBRARY_FIND(udev_queue_get_udev);
UDEV_LIBRARY_FIND(udev_queue_new);
UDEV_LIBRARY_FIND(udev_queue_get_kernel_seqnum);
UDEV_LIBRARY_FIND(udev_queue_get_udev_seqnum);
UDEV_LIBRARY_FIND(udev_queue_get_udev_is_active);
UDEV_LIBRARY_FIND(udev_queue_get_queue_is_empty);
UDEV_LIBRARY_FIND(udev_queue_get_seqnum_is_finished);
UDEV_LIBRARY_FIND(udev_queue_get_seqnum_sequence_is_finished);
UDEV_LIBRARY_FIND(udev_queue_get_fd);
UDEV_LIBRARY_FIND(udev_queue_flush);
UDEV_LIBRARY_FIND(udev_queue_get_queued_list_entry);
UDEV_LIBRARY_FIND(udev_hwdb_new);
UDEV_LIBRARY_FIND(udev_hwdb_ref);
UDEV_LIBRARY_FIND(udev_hwdb_unref);
UDEV_LIBRARY_FIND(udev_hwdb_get_properties_list_entry);
UDEV_LIBRARY_FIND(udev_util_encode_string);
result = UDEW_SUCCESS;
return result;
}
struct udev *udev_ref(struct udev *udev) {
return _udev_ref(udev);
}
struct udev *udev_unref(struct udev *udev) {
return _udev_unref(udev);
}
struct udev *udev_new(void) {
return _udev_new();
}
int udev_get_log_priority(struct udev *udev) {
return _udev_get_log_priority(udev);
}
void udev_set_log_priority(struct udev *udev, int priority) {
return _udev_set_log_priority(udev, priority);
}
void *udev_get_userdata(struct udev *udev) {
return _udev_get_userdata(udev);
}
void udev_set_userdata(struct udev *udev, void *userdata) {
return _udev_set_userdata(udev, userdata);
}
struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry) {
return _udev_list_entry_get_next(list_entry);
}
struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name) {
return _udev_list_entry_get_by_name(list_entry, name);
}
const char *udev_list_entry_get_name(struct udev_list_entry *list_entry) {
return _udev_list_entry_get_name(list_entry);
}
const char *udev_list_entry_get_value(struct udev_list_entry *list_entry) {
return _udev_list_entry_get_value(list_entry);
}
struct udev_device *udev_device_ref(struct udev_device *udev_device) {
return _udev_device_ref(udev_device);
}
struct udev_device *udev_device_unref(struct udev_device *udev_device) {
return _udev_device_unref(udev_device);
}
struct udev *udev_device_get_udev(struct udev_device *udev_device) {
return _udev_device_get_udev(udev_device);
}
struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) {
return _udev_device_new_from_syspath(udev, syspath);
}
struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum) {
return _udev_device_new_from_devnum(udev, type, devnum);
}
struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname) {
return _udev_device_new_from_subsystem_sysname(udev, subsystem, sysname);
}
struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id) {
return _udev_device_new_from_device_id(udev, id);
}
struct udev_device *udev_device_new_from_environment(struct udev *udev) {
return _udev_device_new_from_environment(udev);
}
struct udev_device *udev_device_get_parent(struct udev_device *udev_device) {
return _udev_device_get_parent(udev_device);
}
struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype) {
return _udev_device_get_parent_with_subsystem_devtype(udev_device, subsystem, devtype);
}
const char *udev_device_get_devpath(struct udev_device *udev_device) {
return _udev_device_get_devpath(udev_device);
}
const char *udev_device_get_subsystem(struct udev_device *udev_device) {
return _udev_device_get_subsystem(udev_device);
}
const char *udev_device_get_devtype(struct udev_device *udev_device) {
return _udev_device_get_devtype(udev_device);
}
const char *udev_device_get_syspath(struct udev_device *udev_device) {
return _udev_device_get_syspath(udev_device);
}
const char *udev_device_get_sysname(struct udev_device *udev_device) {
return _udev_device_get_sysname(udev_device);
}
const char *udev_device_get_sysnum(struct udev_device *udev_device) {
return _udev_device_get_sysnum(udev_device);
}
const char *udev_device_get_devnode(struct udev_device *udev_device) {
return _udev_device_get_devnode(udev_device);
}
int udev_device_get_is_initialized(struct udev_device *udev_device) {
return _udev_device_get_is_initialized(udev_device);
}
struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device) {
return _udev_device_get_devlinks_list_entry(udev_device);
}
struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device) {
return _udev_device_get_properties_list_entry(udev_device);
}
struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device) {
return _udev_device_get_tags_list_entry(udev_device);
}
struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device) {
return _udev_device_get_sysattr_list_entry(udev_device);
}
const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key) {
return _udev_device_get_property_value(udev_device, key);
}
const char *udev_device_get_driver(struct udev_device *udev_device) {
return _udev_device_get_driver(udev_device);
}
dev_t udev_device_get_devnum(struct udev_device *udev_device) {
return _udev_device_get_devnum(udev_device);
}
const char *udev_device_get_action(struct udev_device *udev_device) {
return _udev_device_get_action(udev_device);
}
unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device) {
return _udev_device_get_seqnum(udev_device);
}
unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device) {
return _udev_device_get_usec_since_initialized(udev_device);
}
const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) {
return _udev_device_get_sysattr_value(udev_device, sysattr);
}
int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, char *value) {
return _udev_device_set_sysattr_value(udev_device, sysattr, value);
}
int udev_device_has_tag(struct udev_device *udev_device, const char *tag) {
return _udev_device_has_tag(udev_device, tag);
}
struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor) {
return _udev_monitor_ref(udev_monitor);
}
struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor) {
return _udev_monitor_unref(udev_monitor);
}
struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor) {
return _udev_monitor_get_udev(udev_monitor);
}
struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) {
return _udev_monitor_new_from_netlink(udev, name);
}
int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) {
return _udev_monitor_enable_receiving(udev_monitor);
}
int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size) {
return _udev_monitor_set_receive_buffer_size(udev_monitor, size);
}
int udev_monitor_get_fd(struct udev_monitor *udev_monitor) {
return _udev_monitor_get_fd(udev_monitor);
}
struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor) {
return _udev_monitor_receive_device(udev_monitor);
}
int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag) {
return _udev_monitor_filter_add_match_tag(udev_monitor, tag);
}
int udev_monitor_filter_update(struct udev_monitor *udev_monitor) {
return _udev_monitor_filter_update(udev_monitor);
}
int udev_monitor_filter_remove(struct udev_monitor *udev_monitor) {
return _udev_monitor_filter_remove(udev_monitor);
}
struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate) {
return _udev_enumerate_ref(udev_enumerate);
}
struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate) {
return _udev_enumerate_unref(udev_enumerate);
}
struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate) {
return _udev_enumerate_get_udev(udev_enumerate);
}
struct udev_enumerate *udev_enumerate_new(struct udev *udev) {
return _udev_enumerate_new(udev);
}
int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) {
return _udev_enumerate_add_match_subsystem(udev_enumerate, subsystem);
}
int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) {
return _udev_enumerate_add_nomatch_subsystem(udev_enumerate, subsystem);
}
int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) {
return _udev_enumerate_add_match_sysattr(udev_enumerate, sysattr, value);
}
int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) {
return _udev_enumerate_add_nomatch_sysattr(udev_enumerate, sysattr, value);
}
int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value) {
return _udev_enumerate_add_match_property(udev_enumerate, property, value);
}
int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname) {
return _udev_enumerate_add_match_sysname(udev_enumerate, sysname);
}
int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) {
return _udev_enumerate_add_match_tag(udev_enumerate, tag);
}
int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent) {
return _udev_enumerate_add_match_parent(udev_enumerate, parent);
}
int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate) {
return _udev_enumerate_add_match_is_initialized(udev_enumerate);
}
int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath) {
return _udev_enumerate_add_syspath(udev_enumerate, syspath);
}
int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) {
return _udev_enumerate_scan_devices(udev_enumerate);
}
int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate) {
return _udev_enumerate_scan_subsystems(udev_enumerate);
}
struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) {
return _udev_enumerate_get_list_entry(udev_enumerate);
}
struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue) {
return _udev_queue_ref(udev_queue);
}
struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue) {
return _udev_queue_unref(udev_queue);
}
struct udev *udev_queue_get_udev(struct udev_queue *udev_queue) {
return _udev_queue_get_udev(udev_queue);
}
struct udev_queue *udev_queue_new(struct udev *udev) {
return _udev_queue_new(udev);
}
unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) {
return _udev_queue_get_kernel_seqnum(udev_queue);
}
unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) {
return _udev_queue_get_udev_seqnum(udev_queue);
}
int udev_queue_get_udev_is_active(struct udev_queue *udev_queue) {
return _udev_queue_get_udev_is_active(udev_queue);
}
int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue) {
return _udev_queue_get_queue_is_empty(udev_queue);
}
int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) {
return _udev_queue_get_seqnum_is_finished(udev_queue, seqnum);
}
int udev_queue_get_fd(struct udev_queue *udev_queue) {
return _udev_queue_get_fd(udev_queue);
}
int udev_queue_flush(struct udev_queue *udev_queue) {
return _udev_queue_flush(udev_queue);
}
struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) {
return _udev_queue_get_queued_list_entry(udev_queue);
}
struct udev_hwdb *udev_hwdb_new(struct udev *udev) {
return _udev_hwdb_new(udev);
}
struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb) {
return _udev_hwdb_ref(hwdb);
}
struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) {
return _udev_hwdb_unref(hwdb);
}
struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags) {
return _udev_hwdb_get_properties_list_entry(hwdb, modalias, flags);
}
int udev_util_encode_string(const char *str, char *str_enc, size_t len) {
return _udev_util_encode_string(str, str_enc, len);
}

View File

@@ -191,7 +191,7 @@ endif()
# Logging capabilities using GLog library.
if(WITH_CYCLES_LOGGING)
add_definitions(-DWITH_CYCLES_LOGGING)
add_definitions(${GLOG_DEFINES})
add_definitions(-DGOOGLE_GLOG_DLL_DECL=)
add_definitions(-DCYCLES_GFLAGS_NAMESPACE=${GFLAGS_NAMESPACE})
include_directories(
SYSTEM

View File

@@ -35,15 +35,18 @@ if(WITH_CYCLES_OSL)
list(APPEND LIBRARIES cycles_kernel_osl)
endif()
if(NOT CYCLES_STANDALONE_REPOSITORY)
if(CYCLES_STANDALONE_REPOSITORY)
if(WITH_CYCLES_LOGGING)
list(APPEND LIBRARIES
${GLOG_LIBRARIES}
${GFLAGS_LIBRARIES}
)
endif()
else()
list(APPEND LIBRARIES bf_intern_glew_mx bf_intern_guardedalloc)
endif()
if(WITH_CYCLES_LOGGING)
list(APPEND LIBRARIES
${GLOG_LIBRARIES}
${GFLAGS_LIBRARIES}
)
if(WITH_CYCLES_LOGGING)
list(APPEND LIBRARIES extern_glog extern_gflags)
endif()
endif()
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)

View File

@@ -102,9 +102,6 @@ class CyclesRender(bpy.types.RenderEngine):
else:
self.report({'ERROR'}, "OSL support disabled in this build.")
def update_render_passes(self, scene, srl):
engine.register_passes(self, scene, srl)
def engine_exit():
engine.exit()

View File

@@ -205,48 +205,3 @@ def with_network():
def system_info():
import _cycles
return _cycles.system_info()
def register_passes(engine, scene, srl):
engine.register_pass(scene, srl, "Combined", 4, "RGBA", 'COLOR')
if srl.use_pass_z: engine.register_pass(scene, srl, "Depth", 1, "Z", 'VALUE')
if srl.use_pass_mist: engine.register_pass(scene, srl, "Mist", 1, "Z", 'VALUE')
if srl.use_pass_normal: engine.register_pass(scene, srl, "Normal", 3, "XYZ", 'VECTOR')
if srl.use_pass_vector: engine.register_pass(scene, srl, "Vector", 4, "XYZW", 'VECTOR')
if srl.use_pass_uv: engine.register_pass(scene, srl, "UV", 3, "UVA", 'VECTOR')
if srl.use_pass_object_index: engine.register_pass(scene, srl, "IndexOB", 1, "X", 'VALUE')
if srl.use_pass_material_index: engine.register_pass(scene, srl, "IndexMA", 1, "X", 'VALUE')
if srl.use_pass_shadow: engine.register_pass(scene, srl, "Shadow", 3, "RGB", 'COLOR')
if srl.use_pass_ambient_occlusion: engine.register_pass(scene, srl, "AO", 3, "RGB", 'COLOR')
if srl.use_pass_diffuse_direct: engine.register_pass(scene, srl, "DiffDir", 3, "RGB", 'COLOR')
if srl.use_pass_diffuse_indirect: engine.register_pass(scene, srl, "DiffInd", 3, "RGB", 'COLOR')
if srl.use_pass_diffuse_color: engine.register_pass(scene, srl, "DiffCol", 3, "RGB", 'COLOR')
if srl.use_pass_glossy_direct: engine.register_pass(scene, srl, "GlossDir", 3, "RGB", 'COLOR')
if srl.use_pass_glossy_indirect: engine.register_pass(scene, srl, "GlossInd", 3, "RGB", 'COLOR')
if srl.use_pass_glossy_color: engine.register_pass(scene, srl, "GlossCol", 3, "RGB", 'COLOR')
if srl.use_pass_transmission_direct: engine.register_pass(scene, srl, "TransDir", 3, "RGB", 'COLOR')
if srl.use_pass_transmission_indirect: engine.register_pass(scene, srl, "TransInd", 3, "RGB", 'COLOR')
if srl.use_pass_transmission_color: engine.register_pass(scene, srl, "TransCol", 3, "RGB", 'COLOR')
if srl.use_pass_subsurface_direct: engine.register_pass(scene, srl, "SubsurfaceDir", 3, "RGB", 'COLOR')
if srl.use_pass_subsurface_indirect: engine.register_pass(scene, srl, "SubsurfaceInd", 3, "RGB", 'COLOR')
if srl.use_pass_subsurface_color: engine.register_pass(scene, srl, "SubsurfaceCol", 3, "RGB", 'COLOR')
if srl.use_pass_emit: engine.register_pass(scene, srl, "Emit", 3, "RGB", 'COLOR')
if srl.use_pass_environment: engine.register_pass(scene, srl, "Env", 3, "RGB", 'COLOR')
crl = srl.cycles
if crl.pass_debug_bvh_traversed_nodes: engine.register_pass(scene, srl, "Debug BVH Traversed Nodes", 1, "X", 'VALUE')
if crl.pass_debug_bvh_traversed_instances: engine.register_pass(scene, srl, "Debug BVH Traversed Instances", 1, "X", 'VALUE')
if crl.pass_debug_bvh_intersections: engine.register_pass(scene, srl, "Debug BVH Intersections", 1, "X", 'VALUE')
if crl.pass_debug_ray_bounces: engine.register_pass(scene, srl, "Debug Ray Bounces", 1, "X", 'VALUE')
if crl.use_denoising and crl.denoising_store_passes:
engine.register_pass(scene, srl, "Denoising Normal", 3, "XYZ", 'VECTOR');
engine.register_pass(scene, srl, "Denoising Normal Variance", 3, "XYZ", 'VECTOR');
engine.register_pass(scene, srl, "Denoising Albedo", 3, "RGB", 'COLOR');
engine.register_pass(scene, srl, "Denoising Albedo Variance", 3, "RGB", 'COLOR');
engine.register_pass(scene, srl, "Denoising Depth", 1, "Z", 'VALUE');
engine.register_pass(scene, srl, "Denoising Depth Variance", 1, "Z", 'VALUE');
engine.register_pass(scene, srl, "Denoising Shadow A", 3, "XYV", 'VECTOR');
engine.register_pass(scene, srl, "Denoising Shadow B", 3, "XYV", 'VECTOR');
engine.register_pass(scene, srl, "Denoising Image", 3, "RGB", 'COLOR');
engine.register_pass(scene, srl, "Denoising Image Variance", 3, "RGB", 'COLOR');

View File

@@ -695,7 +695,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
update=devices_update_callback
)
cls.debug_opencl_kernel_single_program = BoolProperty(name="Single Program", default=True, update=devices_update_callback);
cls.debug_opencl_kernel_single_program = BoolProperty(name="Single Program", default=False, update=devices_update_callback);
cls.debug_use_opencl_debug = BoolProperty(name="Debug OpenCL", default=False)
@@ -1166,113 +1166,6 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
def unregister(cls):
del bpy.types.Scene.cycles_curves
class CyclesRenderLayerSettings(bpy.types.PropertyGroup):
@classmethod
def register(cls):
bpy.types.SceneRenderLayer.cycles = PointerProperty(
name="Cycles SceneRenderLayer Settings",
description="Cycles SceneRenderLayer Settings",
type=cls,
)
cls.pass_debug_bvh_traversed_nodes = BoolProperty(
name="Debug BVH Traversed Nodes",
description="Store Debug BVH Traversed Nodes pass",
default=False,
)
cls.pass_debug_bvh_traversed_instances = BoolProperty(
name="Debug BVH Traversed Instances",
description="Store Debug BVH Traversed Instances pass",
default=False,
)
cls.pass_debug_bvh_intersections = BoolProperty(
name="Debug BVH Intersections",
description="Store Debug BVH Intersections",
default=False,
)
cls.pass_debug_ray_bounces = BoolProperty(
name="Debug Ray Bounces",
description="Store Debug Ray Bounces pass",
default=False,
)
cls.use_denoising = BoolProperty(
name="Use Denoising",
description="Denoise the rendered image",
default=False,
)
cls.denoising_diffuse_direct = BoolProperty(
name="Diffuse Direct",
description="Denoise the direct diffuse lighting",
default=True,
)
cls.denoising_diffuse_indirect = BoolProperty(
name="Diffuse Indirect",
description="Denoise the indirect diffuse lighting",
default=True,
)
cls.denoising_glossy_direct = BoolProperty(
name="Glossy Direct",
description="Denoise the direct glossy lighting",
default=True,
)
cls.denoising_glossy_indirect = BoolProperty(
name="Glossy Indirect",
description="Denoise the indirect glossy lighting",
default=True,
)
cls.denoising_transmission_direct = BoolProperty(
name="Transmission Direct",
description="Denoise the direct transmission lighting",
default=True,
)
cls.denoising_transmission_indirect = BoolProperty(
name="Transmission Indirect",
description="Denoise the indirect transmission lighting",
default=True,
)
cls.denoising_subsurface_direct = BoolProperty(
name="Subsurface Direct",
description="Denoise the direct subsurface lighting",
default=True,
)
cls.denoising_subsurface_indirect = BoolProperty(
name="Subsurface Indirect",
description="Denoise the indirect subsurface lighting",
default=True,
)
cls.denoising_strength = FloatProperty(
name="Denoising Strength",
description="Controls neighbor pixel weighting for the denoising filter (lower values preserve more detail, but aren't as smooth)",
min=0.0, max=1.0,
default=0.5,
)
cls.denoising_feature_strength = FloatProperty(
name="Denoising Feature Strength",
description="Controls removal of noisy image feature passes (lower values preserve more detail, but aren't as smooth)",
min=0.0, max=1.0,
default=0.5,
)
cls.denoising_radius = IntProperty(
name="Denoising Radius",
description="Size of the image area that's used to denoise a pixel (higher values are smoother, but might lose detail and are slower)",
min=1, max=50,
default=8,
)
cls.denoising_relative_pca = BoolProperty(
name="Relative filter",
description="When removing that don't carry information, use a relative threshold instead of an absolute one (can help to reduce artifacts, but might cause detail loss around edges)",
default=False,
)
cls.denoising_store_passes = BoolProperty(
name="Store denoising passes",
description="Store the denoising feature passes and the noisy image",
default=False,
)
@classmethod
def unregister(cls):
del bpy.types.SceneRenderLayer.cycles
class CyclesCurveSettings(bpy.types.PropertyGroup):
@classmethod
@@ -1404,14 +1297,14 @@ class CyclesPreferences(bpy.types.AddonPreferences):
row = layout.row()
if self.compute_device_type == 'CUDA' and cuda_devices:
box = row.box()
col = row.column(align=True)
for device in cuda_devices:
box.prop(device, "use", text=device.name)
col.prop(device, "use", text=device.name, toggle=True)
if self.compute_device_type == 'OPENCL' and opencl_devices:
box = row.box()
col = row.column(align=True)
for device in opencl_devices:
box.prop(device, "use", text=device.name)
col.prop(device, "use", text=device.name, toggle=True)
def draw(self, context):
@@ -1431,7 +1324,6 @@ def register():
bpy.utils.register_class(CyclesCurveSettings)
bpy.utils.register_class(CyclesDeviceSettings)
bpy.utils.register_class(CyclesPreferences)
bpy.utils.register_class(CyclesRenderLayerSettings)
def unregister():
@@ -1447,4 +1339,3 @@ def unregister():
bpy.utils.unregister_class(CyclesCurveSettings)
bpy.utils.unregister_class(CyclesDeviceSettings)
bpy.utils.unregister_class(CyclesPreferences)
bpy.utils.unregister_class(CyclesRenderLayerSettings)

View File

@@ -78,7 +78,7 @@ def use_cuda(context):
def use_branched_path(context):
cscene = context.scene.cycles
return (cscene.progressive == 'BRANCHED_PATH')
return (cscene.progressive == 'BRANCHED_PATH' and not use_opencl(context))
def use_sample_all_lights(context):
@@ -156,6 +156,7 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
row = layout.row()
sub = row.row()
sub.active = get_device_type(context) != 'OPENCL' or use_cpu(context)
sub.prop(cscene, "progressive", text="")
row.prop(cscene, "use_square_samples")
@@ -203,7 +204,8 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
col.prop(cscene, "sample_all_lights_direct")
col.prop(cscene, "sample_all_lights_indirect")
layout.row().prop(cscene, "sampling_pattern", text="Pattern")
if not (use_opencl(context) and cscene.feature_set != 'EXPERIMENTAL'):
layout.row().prop(cscene, "sampling_pattern", text="Pattern")
for rl in scene.render.layers:
if rl.samples > 0:
@@ -476,14 +478,11 @@ class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
import _cycles
layout = self.layout
scene = context.scene
rd = scene.render
rl = rd.layers.active
crl = rl.cycles
split = layout.split()
@@ -530,18 +529,8 @@ class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
col.prop(rl, "use_pass_emit", text="Emission")
col.prop(rl, "use_pass_environment")
if context.scene.cycles.feature_set == 'EXPERIMENTAL':
col.separator()
sub = col.column()
sub.active = crl.use_denoising
sub.prop(crl, "denoising_store_passes", text="Denoising")
if _cycles.with_cycles_debug:
col = layout.column()
col.prop(crl, "pass_debug_bvh_traversed_nodes")
col.prop(crl, "pass_debug_bvh_traversed_instances")
col.prop(crl, "pass_debug_bvh_intersections")
col.prop(crl, "pass_debug_ray_bounces")
if hasattr(rd, "debug_pass_type"):
layout.prop(rd, "debug_pass_type")
class CyclesRender_PT_views(CyclesButtonsPanel, Panel):
@@ -574,7 +563,7 @@ class CyclesRender_PT_views(CyclesButtonsPanel, Panel):
row.label(text="File Suffix:")
row.prop(rv, "file_suffix", text="")
else:
elif rd.views_format == 'MULTIVIEW':
row = layout.row()
row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "views", rd.views, "active_index", rows=2)
@@ -585,64 +574,23 @@ class CyclesRender_PT_views(CyclesButtonsPanel, Panel):
row = layout.row()
row.label(text="Camera Suffix:")
row.prop(rv, "camera_suffix", text="")
else:
wm = context.window_manager
running = scene.hmd_running
text_win = "Close HMD Window" if wm.has_hmd_window else "Open HMD Window"
text_run = "Stop Session" if running else "Start Session"
icon = 'PAUSE' if running else 'PLAY'
class CyclesRender_PT_denoising(CyclesButtonsPanel, Panel):
bl_label = "Denoising"
bl_context = "render_layer"
bl_options = {'DEFAULT_CLOSED'}
col = layout.column()
def draw_header(self, context):
rd = context.scene.render
rl = rd.layers.active
crl = rl.cycles
self.layout.prop(crl, "use_denoising", text="")
row = col.row(align=True)
row.operator("wm.hmd_view_toggle", text=text_win)
row.operator("wm.hmd_session_run", text=text_run, icon=icon)
def draw(self, context):
layout = self.layout
scene = context.scene
rd = scene.render
rl = rd.layers.active
crl = rl.cycles
split = layout.split()
col = split.column()
sub = col.column(align=True)
sub.prop(crl, "denoising_radius", text="Radius")
sub.prop(crl, "denoising_strength", slider=True, text="Strength")
col = split.column()
sub = col.column(align=True)
sub.prop(crl, "denoising_feature_strength", slider=True, text="Feature Strength")
sub.prop(crl, "denoising_relative_pca")
layout.separator()
row = layout.row()
row.label(text="Diffuse:")
sub = row.row(align=True)
sub.prop(crl, "denoising_diffuse_direct", text="Direct", toggle=True)
sub.prop(crl, "denoising_diffuse_indirect", text="Indirect", toggle=True)
row = layout.row()
row.label(text="Glossy:")
sub = row.row(align=True)
sub.prop(crl, "denoising_glossy_direct", text="Direct", toggle=True)
sub.prop(crl, "denoising_glossy_indirect", text="Indirect", toggle=True)
row = layout.row()
row.label(text="Transmission:")
sub = row.row(align=True)
sub.prop(crl, "denoising_transmission_direct", text="Direct", toggle=True)
sub.prop(crl, "denoising_transmission_indirect", text="Indirect", toggle=True)
row = layout.row()
row.label(text="Subsurface:")
sub = row.row(align=True)
sub.prop(crl, "denoising_subsurface_direct", text="Direct", toggle=True)
sub.prop(crl, "denoising_subsurface_indirect", text="Indirect", toggle=True)
col.prop(rd, "hmd_camlock")
col.prop(rd, "use_hmd_view_lensdist", text="Lens Distortion")
col.prop(rd, "hmd_view_shade", text="Shading")
class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
@@ -1798,7 +1746,6 @@ classes = (
CyclesRender_PT_layer_options,
CyclesRender_PT_layer_passes,
CyclesRender_PT_views,
CyclesRender_PT_denoising,
Cycles_PT_post_processing,
CyclesCamera_PT_dof,
Cycles_PT_context_material,

View File

@@ -411,7 +411,7 @@ static void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
}
}
mesh->resize_mesh(mesh->verts.size(), mesh->num_triangles());
mesh->resize_mesh(mesh->verts.size(), mesh->triangles.size());
mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
mesh->add_face_normals();
@@ -546,7 +546,7 @@ static void ExportCurveTriangleGeometry(Mesh *mesh,
}
}
mesh->resize_mesh(mesh->verts.size(), mesh->num_triangles());
mesh->resize_mesh(mesh->verts.size(), mesh->triangles.size());
mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
mesh->add_face_normals();
@@ -776,17 +776,17 @@ static void ExportCurveTriangleVcol(ParticleCurveData *CData,
for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
for(int section = 0; section < resol; section++) {
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve]));
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve]));
vertexindex++;
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve]));
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve]));
vertexindex++;
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve]));
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve]));
vertexindex++;
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve]));
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve]));
vertexindex++;
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve]));
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve]));
vertexindex++;
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve]));
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve]));
vertexindex++;
}
}
@@ -1004,7 +1004,7 @@ void BlenderSync::sync_curves(Mesh *mesh,
for(size_t curve = 0; curve < CData.curve_vcol.size(); curve++)
if(!(CData.curve_keynum[curve] <= 1 || CData.curve_length[curve] == 0.0f))
fdata[i++] = color_srgb_to_scene_linear_v3(CData.curve_vcol[curve]);
fdata[i++] = color_srgb_to_scene_linear(CData.curve_vcol[curve]);
}
}
}

View File

@@ -356,7 +356,7 @@ static void attr_create_vertex_color(Scene *scene,
int n = p->loop_total();
for(int i = 0; i < n; i++) {
float3 color = get_float3(l->data[p->loop_start() + i].color());
*(cdata++) = color_float_to_byte(color_srgb_to_scene_linear_v3(color));
*(cdata++) = color_float_to_byte(color_srgb_to_scene_linear(color));
}
}
}
@@ -380,11 +380,11 @@ static void attr_create_vertex_color(Scene *scene,
face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b);
uchar4 colors[4];
colors[0] = color_float_to_byte(color_srgb_to_scene_linear_v3(get_float3(c->color1())));
colors[1] = color_float_to_byte(color_srgb_to_scene_linear_v3(get_float3(c->color2())));
colors[2] = color_float_to_byte(color_srgb_to_scene_linear_v3(get_float3(c->color3())));
colors[0] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color1())));
colors[1] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color2())));
colors[2] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color3())));
if(nverts[i] == 4) {
colors[3] = color_float_to_byte(color_srgb_to_scene_linear_v3(get_float3(c->color4())));
colors[3] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color4())));
}
cdata[0] = colors[tri_a[0]];

View File

@@ -478,7 +478,7 @@ static bool object_render_hide_duplis(BL::Object& b_ob)
/* Object Loop */
void BlenderSync::sync_objects(float motion_time)
void BlenderSync::sync_objects(BL::SpaceView3D& b_v3d, float motion_time)
{
/* layer data */
uint scene_layer = render_layer.scene_layer;
@@ -506,7 +506,7 @@ void BlenderSync::sync_objects(float motion_time)
* 1 : DAG_EVAL_PREVIEW
* 2 : DAG_EVAL_RENDER
*/
int dupli_settings = (render_layer.use_viewport_visibility) ? 1 : 2;
int dupli_settings = preview ? 1 : 2;
bool cancel = false;
bool use_portal = false;
@@ -541,7 +541,7 @@ void BlenderSync::sync_objects(float motion_time)
for(b_ob.dupli_list.begin(b_dup); b_dup != b_ob.dupli_list.end(); ++b_dup) {
Transform tfm = get_transform(b_dup->matrix());
BL::Object b_dup_ob = b_dup->object();
bool dup_hide = (render_layer.use_viewport_visibility)? b_dup_ob.hide(): b_dup_ob.hide_render();
bool dup_hide = (b_v3d)? b_dup_ob.hide(): b_dup_ob.hide_render();
bool in_dupli_group = (b_dup->type() == BL::DupliObject::type_GROUP);
bool hide_tris;
@@ -617,6 +617,7 @@ void BlenderSync::sync_objects(float motion_time)
}
void BlenderSync::sync_motion(BL::RenderSettings& b_render,
BL::SpaceView3D& b_v3d,
BL::Object& b_override,
int width, int height,
void **python_thread_state)
@@ -653,7 +654,7 @@ void BlenderSync::sync_motion(BL::RenderSettings& b_render,
b_engine.frame_set(frame, subframe);
python_thread_state_save(python_thread_state);
sync_camera_motion(b_render, b_cam, width, height, 0.0f);
sync_objects(0.0f);
sync_objects(b_v3d, 0.0f);
}
/* always sample these times for camera motion */
@@ -687,7 +688,7 @@ void BlenderSync::sync_motion(BL::RenderSettings& b_render,
}
/* sync object */
sync_objects(relative_time);
sync_objects(b_v3d, relative_time);
}
/* we need to set the python thread state again because this

View File

@@ -811,14 +811,6 @@ void *CCL_python_module_init()
PyModule_AddStringConstant(mod, "osl_version_string", "unknown");
#endif
#ifdef WITH_CYCLES_DEBUG
PyModule_AddObject(mod, "with_cycles_debug", Py_True);
Py_INCREF(Py_True);
#else
PyModule_AddObject(mod, "with_cycles_debug", Py_False);
Py_INCREF(Py_False);
#endif
#ifdef WITH_NETWORK
PyModule_AddObject(mod, "with_network", Py_True);
Py_INCREF(Py_True);

View File

@@ -243,6 +243,90 @@ void BlenderSession::free_session()
delete session;
}
static PassType get_pass_type(BL::RenderPass& b_pass)
{
switch(b_pass.type()) {
case BL::RenderPass::type_COMBINED:
return PASS_COMBINED;
case BL::RenderPass::type_Z:
return PASS_DEPTH;
case BL::RenderPass::type_MIST:
return PASS_MIST;
case BL::RenderPass::type_NORMAL:
return PASS_NORMAL;
case BL::RenderPass::type_OBJECT_INDEX:
return PASS_OBJECT_ID;
case BL::RenderPass::type_UV:
return PASS_UV;
case BL::RenderPass::type_VECTOR:
return PASS_MOTION;
case BL::RenderPass::type_MATERIAL_INDEX:
return PASS_MATERIAL_ID;
case BL::RenderPass::type_DIFFUSE_DIRECT:
return PASS_DIFFUSE_DIRECT;
case BL::RenderPass::type_GLOSSY_DIRECT:
return PASS_GLOSSY_DIRECT;
case BL::RenderPass::type_TRANSMISSION_DIRECT:
return PASS_TRANSMISSION_DIRECT;
case BL::RenderPass::type_SUBSURFACE_DIRECT:
return PASS_SUBSURFACE_DIRECT;
case BL::RenderPass::type_DIFFUSE_INDIRECT:
return PASS_DIFFUSE_INDIRECT;
case BL::RenderPass::type_GLOSSY_INDIRECT:
return PASS_GLOSSY_INDIRECT;
case BL::RenderPass::type_TRANSMISSION_INDIRECT:
return PASS_TRANSMISSION_INDIRECT;
case BL::RenderPass::type_SUBSURFACE_INDIRECT:
return PASS_SUBSURFACE_INDIRECT;
case BL::RenderPass::type_DIFFUSE_COLOR:
return PASS_DIFFUSE_COLOR;
case BL::RenderPass::type_GLOSSY_COLOR:
return PASS_GLOSSY_COLOR;
case BL::RenderPass::type_TRANSMISSION_COLOR:
return PASS_TRANSMISSION_COLOR;
case BL::RenderPass::type_SUBSURFACE_COLOR:
return PASS_SUBSURFACE_COLOR;
case BL::RenderPass::type_EMIT:
return PASS_EMISSION;
case BL::RenderPass::type_ENVIRONMENT:
return PASS_BACKGROUND;
case BL::RenderPass::type_AO:
return PASS_AO;
case BL::RenderPass::type_SHADOW:
return PASS_SHADOW;
case BL::RenderPass::type_DIFFUSE:
case BL::RenderPass::type_COLOR:
case BL::RenderPass::type_REFRACTION:
case BL::RenderPass::type_SPECULAR:
case BL::RenderPass::type_REFLECTION:
return PASS_NONE;
#ifdef WITH_CYCLES_DEBUG
case BL::RenderPass::type_DEBUG:
{
switch(b_pass.debug_type()) {
case BL::RenderPass::debug_type_BVH_TRAVERSED_NODES:
return PASS_BVH_TRAVERSED_NODES;
case BL::RenderPass::debug_type_BVH_TRAVERSED_INSTANCES:
return PASS_BVH_TRAVERSED_INSTANCES;
case BL::RenderPass::debug_type_BVH_INTERSECTIONS:
return PASS_BVH_INTERSECTIONS;
case BL::RenderPass::debug_type_RAY_BOUNCES:
return PASS_RAY_BOUNCES;
}
break;
}
#endif
}
return PASS_NONE;
}
static ShaderEvalType get_shader_type(const string& pass_type)
{
const char *shader_type = pass_type.c_str();
@@ -299,13 +383,12 @@ static BL::RenderResult begin_render_result(BL::RenderEngine& b_engine,
static void end_render_result(BL::RenderEngine& b_engine,
BL::RenderResult& b_rr,
bool cancel,
bool highlight,
bool do_merge_results)
{
b_engine.end_result(b_rr, (int)cancel, (int) highlight, (int)do_merge_results);
b_engine.end_result(b_rr, (int)cancel, (int)do_merge_results);
}
void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_update_only, bool highlight)
void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_update_only)
{
BufferParams& params = rtile.buffers->params;
int x = params.full_x - session->tile_manager.params.full_x;
@@ -341,37 +424,37 @@ void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_upda
update_render_result(b_rr, b_rlay, rtile);
}
end_render_result(b_engine, b_rr, true, highlight, true);
end_render_result(b_engine, b_rr, true, true);
}
else {
/* write result */
write_render_result(b_rr, b_rlay, rtile);
end_render_result(b_engine, b_rr, false, false, true);
end_render_result(b_engine, b_rr, false, true);
}
}
void BlenderSession::write_render_tile(RenderTile& rtile)
{
do_write_update_render_tile(rtile, false, false);
do_write_update_render_tile(rtile, false);
}
void BlenderSession::update_render_tile(RenderTile& rtile, bool highlight)
void BlenderSession::update_render_tile(RenderTile& rtile)
{
/* use final write for preview renders, otherwise render result wouldn't be
* be updated in blender side
* would need to be investigated a bit further, but for now shall be fine
*/
if(!b_engine.is_preview())
do_write_update_render_tile(rtile, true, highlight);
do_write_update_render_tile(rtile, true);
else
do_write_update_render_tile(rtile, false, false);
do_write_update_render_tile(rtile, false);
}
void BlenderSession::render()
{
/* set callback to write out render results */
session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1);
session->update_render_tile_cb = function_bind(&BlenderSession::update_render_tile, this, _1, _2);
session->update_render_tile_cb = function_bind(&BlenderSession::update_render_tile, this, _1);
/* get buffer parameters */
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
@@ -392,7 +475,7 @@ void BlenderSession::render()
/* layer will be missing if it was disabled in the UI */
if(b_single_rlay == b_rr.layers.end()) {
end_render_result(b_engine, b_rr, true, true, false);
end_render_result(b_engine, b_rr, true, false);
continue;
}
@@ -400,36 +483,25 @@ void BlenderSession::render()
/* add passes */
array<Pass> passes;
Pass::add(PASS_COMBINED, passes);
if(session_params.device.advanced_shading) {
passes = sync->sync_render_passes(b_rlay, *b_layer_iter);
}
else {
Pass::add(PASS_COMBINED, passes);
/* loop over passes */
BL::RenderLayer::passes_iterator b_pass_iter;
for(b_rlay.passes.begin(b_pass_iter); b_pass_iter != b_rlay.passes.end(); ++b_pass_iter) {
BL::RenderPass b_pass(*b_pass_iter);
PassType pass_type = get_pass_type(b_pass);
if(pass_type == PASS_MOTION && scene->integrator->motion_blur)
continue;
if(pass_type != PASS_NONE)
Pass::add(pass_type, passes);
}
}
buffer_params.passes = passes;
PointerRNA crl = RNA_pointer_get(&b_layer_iter->ptr, "cycles");
buffer_params.denoising_data_pass = get_boolean(crl, "use_denoising");
session->tile_manager.schedule_denoising = get_boolean(crl, "use_denoising");
session->params.use_denoising = get_boolean(crl, "use_denoising");
scene->film->denoising_data_pass = buffer_params.denoising_data_pass;
scene->film->denoising_flags = 0;
if(!get_boolean(crl, "denoising_diffuse_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_DIFFUSE_DIR;
if(!get_boolean(crl, "denoising_diffuse_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_DIFFUSE_IND;
if(!get_boolean(crl, "denoising_glossy_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_GLOSSY_DIR;
if(!get_boolean(crl, "denoising_glossy_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_GLOSSY_IND;
if(!get_boolean(crl, "denoising_transmission_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_TRANSMISSION_DIR;
if(!get_boolean(crl, "denoising_transmission_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_TRANSMISSION_IND;
if(!get_boolean(crl, "denoising_subsurface_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_SUBSURFACE_DIR;
if(!get_boolean(crl, "denoising_subsurface_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_SUBSURFACE_IND;
scene->film->denoising_clean_pass = (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES);
buffer_params.denoising_clean_pass = scene->film->denoising_clean_pass;
session->params.denoising_radius = get_int(crl, "denoising_radius");
session->params.denoising_strength = get_float(crl, "denoising_strength");
session->params.denoising_feature_strength = get_float(crl, "denoising_feature_strength");
session->params.denoising_relative_pca = get_boolean(crl, "denoising_relative_pca");
scene->film->pass_alpha_threshold = b_layer_iter->pass_alpha_threshold();
scene->film->tag_passes_update(scene, passes);
scene->film->tag_update(scene);
@@ -483,7 +555,7 @@ void BlenderSession::render()
}
/* free result without merging */
end_render_result(b_engine, b_rr, true, true, false);
end_render_result(b_engine, b_rr, true, false);
if(session->progress.get_cancel())
break;
@@ -681,31 +753,19 @@ void BlenderSession::do_write_update_render_result(BL::RenderResult& b_rr,
BL::RenderPass b_pass(*b_iter);
/* find matching pass type */
PassType pass_type = BlenderSync::get_pass_type(b_pass);
PassType pass_type = get_pass_type(b_pass);
int components = b_pass.channels();
bool read = false;
if(pass_type != PASS_NONE) {
/* copy pixels */
read = buffers->get_pass_rect(pass_type, exposure, sample, components, &pixels[0]);
}
else {
int denoising_offset = BlenderSync::get_denoising_pass(b_pass);
if(denoising_offset >= 0) {
read = buffers->get_denoising_pass_rect(denoising_offset, exposure, sample, components, &pixels[0]);
}
}
if(!read) {
/* copy pixels */
if(!buffers->get_pass_rect(pass_type, exposure, sample, components, &pixels[0]))
memset(&pixels[0], 0, pixels.size()*sizeof(float));
}
b_pass.rect(&pixels[0]);
}
}
else {
/* copy combined pass */
BL::RenderPass b_combined_pass(b_rlay.passes.find_by_name("Combined", b_rview_name.c_str()));
BL::RenderPass b_combined_pass(b_rlay.passes.find_by_type(BL::RenderPass::type_COMBINED, b_rview_name.c_str()));
if(buffers->get_pass_rect(PASS_COMBINED, exposure, sample, 4, &pixels[0]))
b_combined_pass.rect(&pixels[0]);
}

View File

@@ -79,7 +79,7 @@ public:
void update_render_result(BL::RenderResult& b_rr,
BL::RenderLayer& b_rlay,
RenderTile& rtile);
void update_render_tile(RenderTile& rtile, bool highlight);
void update_render_tile(RenderTile& rtile);
/* interactive updates */
void synchronize();
@@ -147,7 +147,7 @@ protected:
BL::RenderLayer& b_rlay,
RenderTile& rtile,
bool do_update_only);
void do_write_update_render_tile(RenderTile& rtile, bool do_update_only, bool highlight);
void do_write_update_render_tile(RenderTile& rtile, bool do_update_only);
int builtin_image_frame(const string &builtin_name);
void builtin_image_info(const string &builtin_name,

View File

@@ -210,9 +210,10 @@ void BlenderSync::sync_data(BL::RenderSettings& b_render,
scene->need_motion() == Scene::MOTION_NONE ||
scene->camera->motion_position == Camera::MOTION_POSITION_CENTER)
{
sync_objects();
sync_objects(b_v3d);
}
sync_motion(b_render,
b_v3d,
b_override,
width, height,
python_thread_state);
@@ -479,132 +480,6 @@ void BlenderSync::sync_images()
}
}
/* Passes */
PassType BlenderSync::get_pass_type(BL::RenderPass& b_pass)
{
string name = b_pass.name();
#define MAP_PASS(passname, passtype) if(name == passname) return passtype;
/* NOTE: Keep in sync with defined names from DNA_scene_types.h */
MAP_PASS("Combined", PASS_COMBINED);
MAP_PASS("Depth", PASS_DEPTH);
MAP_PASS("Mist", PASS_MIST);
MAP_PASS("Normal", PASS_NORMAL);
MAP_PASS("IndexOB", PASS_OBJECT_ID);
MAP_PASS("UV", PASS_UV);
MAP_PASS("Vector", PASS_MOTION);
MAP_PASS("IndexMA", PASS_MATERIAL_ID);
MAP_PASS("DiffDir", PASS_DIFFUSE_DIRECT);
MAP_PASS("GlossDir", PASS_GLOSSY_DIRECT);
MAP_PASS("TransDir", PASS_TRANSMISSION_DIRECT);
MAP_PASS("SubsurfaceDir", PASS_SUBSURFACE_DIRECT);
MAP_PASS("DiffInd", PASS_DIFFUSE_INDIRECT);
MAP_PASS("GlossInd", PASS_GLOSSY_INDIRECT);
MAP_PASS("TransInd", PASS_TRANSMISSION_INDIRECT);
MAP_PASS("SubsurfaceInd", PASS_SUBSURFACE_INDIRECT);
MAP_PASS("DiffCol", PASS_DIFFUSE_COLOR);
MAP_PASS("GlossCol", PASS_GLOSSY_COLOR);
MAP_PASS("TransCol", PASS_TRANSMISSION_COLOR);
MAP_PASS("SubsurfaceCol", PASS_SUBSURFACE_COLOR);
MAP_PASS("Emit", PASS_EMISSION);
MAP_PASS("Env", PASS_BACKGROUND);
MAP_PASS("AO", PASS_AO);
MAP_PASS("Shadow", PASS_SHADOW);
#ifdef __KERNEL_DEBUG__
MAP_PASS("Debug BVH Traversed Nodes", PASS_BVH_TRAVERSED_NODES);
MAP_PASS("Debug BVH Traversed Instances", PASS_BVH_TRAVERSED_INSTANCES);
MAP_PASS("Debug BVH Intersections", PASS_BVH_INTERSECTIONS);
MAP_PASS("Debug Ray Bounces", PASS_RAY_BOUNCES);
#endif
#undef MAP_PASS
return PASS_NONE;
}
int BlenderSync::get_denoising_pass(BL::RenderPass& b_pass)
{
string name = b_pass.name();
if(name.substr(0, 10) != "Denoising ") {
return -1;
}
name = name.substr(10);
#define MAP_PASS(passname, offset) if(name == passname) return offset;
MAP_PASS("Normal", DENOISING_PASS_NORMAL);
MAP_PASS("Normal Variance", DENOISING_PASS_NORMAL_VAR);
MAP_PASS("Albedo", DENOISING_PASS_ALBEDO);
MAP_PASS("Albedo Variance", DENOISING_PASS_ALBEDO_VAR);
MAP_PASS("Depth", DENOISING_PASS_DEPTH);
MAP_PASS("Depth Variance", DENOISING_PASS_DEPTH_VAR);
MAP_PASS("Shadow A", DENOISING_PASS_SHADOW_A);
MAP_PASS("Shadow B", DENOISING_PASS_SHADOW_B);
MAP_PASS("Image", DENOISING_PASS_COLOR);
MAP_PASS("Image Variance", DENOISING_PASS_COLOR_VAR);
#undef MAP_PASS
return -1;
}
array<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
BL::SceneRenderLayer& b_srlay)
{
array<Pass> passes;
Pass::add(PASS_COMBINED, passes);
/* loop over passes */
BL::RenderLayer::passes_iterator b_pass_iter;
for(b_rlay.passes.begin(b_pass_iter); b_pass_iter != b_rlay.passes.end(); ++b_pass_iter) {
BL::RenderPass b_pass(*b_pass_iter);
PassType pass_type = get_pass_type(b_pass);
if(pass_type == PASS_MOTION && scene->integrator->motion_blur)
continue;
if(pass_type != PASS_NONE)
Pass::add(pass_type, passes);
}
PointerRNA crp = RNA_pointer_get(&b_srlay.ptr, "cycles");
if(get_boolean(crp, "denoising_store_passes")) {
b_engine.add_pass("Denoising Normal", 3, "XYZ", b_srlay.name().c_str());
b_engine.add_pass("Denoising Normal Variance", 3, "XYZ", b_srlay.name().c_str());
b_engine.add_pass("Denoising Albedo", 3, "RGB", b_srlay.name().c_str());
b_engine.add_pass("Denoising Albedo Variance", 3, "RGB", b_srlay.name().c_str());
b_engine.add_pass("Denoising Depth", 1, "Z", b_srlay.name().c_str());
b_engine.add_pass("Denoising Depth Variance", 1, "Z", b_srlay.name().c_str());
b_engine.add_pass("Denoising Shadow A", 3, "XYV", b_srlay.name().c_str());
b_engine.add_pass("Denoising Shadow B", 3, "XYV", b_srlay.name().c_str());
b_engine.add_pass("Denoising Image", 3, "RGB", b_srlay.name().c_str());
b_engine.add_pass("Denoising Image Variance", 3, "RGB", b_srlay.name().c_str());
}
#ifdef __KERNEL_DEBUG__
if(get_boolean(crp, "pass_debug_bvh_traversed_nodes")) {
b_engine.add_pass("Debug BVH Traversed Nodes", 1, "X", b_srlay.name().c_str());
Pass::add(PASS_BVH_TRAVERSED_NODES, passes);
}
if(get_boolean(crp, "pass_debug_bvh_traversed_instances")) {
b_engine.add_pass("Debug BVH Traversed Instances", 1, "X", b_srlay.name().c_str());
Pass::add(PASS_BVH_TRAVERSED_INSTANCES, passes);
}
if(get_boolean(crp, "pass_debug_bvh_intersections")) {
b_engine.add_pass("Debug BVH Intersections", 1, "X", b_srlay.name().c_str());
Pass::add(PASS_BVH_INTERSECTIONS, passes);
}
if(get_boolean(crp, "pass_debug_ray_bounces")) {
b_engine.add_pass("Debug Ray Bounces", 1, "X", b_srlay.name().c_str());
Pass::add(PASS_RAY_BOUNCES, passes);
}
#else
(void) b_srlay; /* Ignored. */
#endif
return passes;
}
/* Scene Parameters */
SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene,

View File

@@ -67,8 +67,6 @@ public:
void **python_thread_state,
const char *layer = 0);
void sync_render_layers(BL::SpaceView3D& b_v3d, const char *layer);
array<Pass> sync_render_passes(BL::RenderLayer& b_rlay,
BL::SceneRenderLayer& b_srlay);
void sync_integrator();
void sync_camera(BL::RenderSettings& b_render,
BL::Object& b_override,
@@ -95,15 +93,13 @@ public:
Camera *cam,
int width, int height);
static PassType get_pass_type(BL::RenderPass& b_pass);
static int get_denoising_pass(BL::RenderPass& b_pass);
private:
/* sync */
void sync_lamps(bool update_all);
void sync_materials(bool update_all);
void sync_objects(float motion_time = 0.0f);
void sync_objects(BL::SpaceView3D& b_v3d, float motion_time = 0.0f);
void sync_motion(BL::RenderSettings& b_render,
BL::SpaceView3D& b_v3d,
BL::Object& b_override,
int width, int height,
void **python_thread_state);

View File

@@ -135,5 +135,13 @@ if(CYCLES_STANDALONE_REPOSITORY)
unset(_lib_DIR)
else()
if(WIN32)
set(GLOG_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/glog/src/windows)
set(GFLAGS_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/gflags/src)
else()
set(GLOG_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/glog/src)
set(GFLAGS_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/gflags/src)
endif()
set(GFLAGS_NAMESPACE "gflags")
set(LLVM_LIBRARIES ${LLVM_LIBRARY})
endif()

View File

@@ -25,7 +25,6 @@ set(SRC
device.cpp
device_cpu.cpp
device_cuda.cpp
device_denoising.cpp
device_multi.cpp
device_opencl.cpp
device_split_kernel.cpp
@@ -49,7 +48,6 @@ endif()
set(SRC_HEADERS
device.h
device_denoising.h
device_memory.h
device_intern.h
device_network.h

View File

@@ -66,8 +66,6 @@ std::ostream& operator <<(std::ostream &os,
<< string_from_bool(requested_features.use_patch_evaluation) << std::endl;
os << "Use Transparent Shadows: "
<< string_from_bool(requested_features.use_transparent) << std::endl;
os << "Use Principled BSDF: "
<< string_from_bool(requested_features.use_principled) << std::endl;
return os;
}
@@ -402,16 +400,4 @@ void Device::free_memory()
devices.free_memory();
}
device_sub_ptr::device_sub_ptr(Device *device, device_memory& mem, int offset, int size, MemoryType type)
: device(device)
{
ptr = device->mem_alloc_sub_ptr(mem, offset, size, type);
}
device_sub_ptr::~device_sub_ptr()
{
device->mem_free_sub_ptr(ptr);
}
CCL_NAMESPACE_END

View File

@@ -124,9 +124,6 @@ public:
/* Use various shadow tricks, such as shadow catcher. */
bool use_shadow_tricks;
/* Per-uber shader usage flags. */
bool use_principled;
DeviceRequestedFeatures()
{
/* TODO(sergey): Find more meaningful defaults. */
@@ -144,7 +141,6 @@ public:
use_patch_evaluation = false;
use_transparent = false;
use_shadow_tricks = false;
use_principled = false;
}
bool modified(const DeviceRequestedFeatures& requested_features)
@@ -162,8 +158,7 @@ public:
use_integrator_branched == requested_features.use_integrator_branched &&
use_patch_evaluation == requested_features.use_patch_evaluation &&
use_transparent == requested_features.use_transparent &&
use_shadow_tricks == requested_features.use_shadow_tricks &&
use_principled == requested_features.use_principled);
use_shadow_tricks == requested_features.use_shadow_tricks);
}
/* Convert the requested features structure to a build options,
@@ -210,9 +205,6 @@ public:
if(!use_shadow_tricks) {
build_options += " -D__NO_SHADOW_TRICKS__";
}
if(!use_principled) {
build_options += " -D__NO_PRINCIPLED__";
}
return build_options;
}
};
@@ -228,7 +220,6 @@ struct DeviceDrawParams {
};
class Device {
friend class device_sub_ptr;
protected:
Device(DeviceInfo& info_, Stats &stats_, bool background) : background(background), vertex_buffer(0), info(info_), stats(stats_) {}
@@ -238,14 +229,6 @@ protected:
/* used for real time display */
unsigned int vertex_buffer;
virtual device_ptr mem_alloc_sub_ptr(device_memory& /*mem*/, int /*offset*/, int /*size*/, MemoryType /*type*/)
{
/* Only required for devices that implement denoising. */
assert(false);
return (device_ptr) 0;
}
virtual void mem_free_sub_ptr(device_ptr /*ptr*/) {};
public:
virtual ~Device();
@@ -274,8 +257,6 @@ public:
virtual void mem_zero(device_memory& mem) = 0;
virtual void mem_free(device_memory& mem) = 0;
virtual int mem_address_alignment() { return 16; }
/* constant memory */
virtual void const_copy_to(const char *name, void *host, size_t size) = 0;
@@ -323,8 +304,6 @@ public:
/* multi device */
virtual void map_tile(Device * /*sub_device*/, RenderTile& /*tile*/) {}
virtual int device_number(Device * /*sub_device*/) { return 0; }
virtual void map_neighbor_tiles(Device * /*sub_device*/, RenderTile * /*tiles*/) {}
virtual void unmap_neighbor_tiles(Device * /*sub_device*/, RenderTile * /*tiles*/) {}
/* static */
static Device *create(DeviceInfo& info, Stats &stats, bool background = true);

File diff suppressed because it is too large Load Diff

View File

@@ -21,14 +21,11 @@
#include <string.h>
#include "device/device.h"
#include "device/device_denoising.h"
#include "device/device_intern.h"
#include "device/device_split_kernel.h"
#include "render/buffers.h"
#include "kernel/filter/filter_defines.h"
#ifdef WITH_CUDA_DYNLOAD
# include "cuew.h"
#else
@@ -116,13 +113,12 @@ public:
DedicatedTaskPool task_pool;
CUdevice cuDevice;
CUcontext cuContext;
CUmodule cuModule, cuFilterModule;
CUmodule cuModule;
map<device_ptr, bool> tex_interp_map;
map<device_ptr, uint> tex_bindless_map;
int cuDevId;
int cuDevArchitecture;
bool first_error;
CUDASplitKernel *split_kernel;
struct PixelMem {
GLuint cuPBO;
@@ -173,7 +169,7 @@ public:
CUresult result = stmt; \
\
if(result != CUDA_SUCCESS) { \
string message = string_printf("CUDA error: %s in %s, line %d", cuewErrorString(result), #stmt, __LINE__); \
string message = string_printf("CUDA error: %s in %s", cuewErrorString(result), #stmt); \
if(error_msg == "") \
error_msg = message; \
fprintf(stderr, "%s\n", message.c_str()); \
@@ -225,8 +221,6 @@ public:
cuDevice = 0;
cuContext = 0;
split_kernel = NULL;
need_bindless_mapping = false;
/* intialize */
@@ -266,8 +260,6 @@ public:
{
task_pool.stop();
delete split_kernel;
if(info.has_bindless_textures) {
tex_free(bindless_mapping);
}
@@ -304,8 +296,7 @@ public:
* kernel sources md5 and only depends on compiler or compilation settings.
*/
string compile_kernel_get_common_cflags(
const DeviceRequestedFeatures& requested_features,
bool filter=false, bool split=false)
const DeviceRequestedFeatures& requested_features, bool split=false)
{
const int cuda_version = cuewCompilerVersion();
const int machine = system_cpu_bits();
@@ -320,7 +311,7 @@ public:
machine,
cuda_version,
include_path.c_str());
if(!filter && use_adaptive_compilation()) {
if(use_adaptive_compilation()) {
cflags += " " + requested_features.get_build_options();
}
const char *extra_cflags = getenv("CYCLES_CUDA_EXTRA_CFLAGS");
@@ -368,22 +359,8 @@ public:
return true;
}
string compile_kernel(const DeviceRequestedFeatures& requested_features,
bool filter=false, bool split=false)
string compile_kernel(const DeviceRequestedFeatures& requested_features, bool split=false)
{
const char *name, *source;
if(filter) {
name = "filter";
source = "filter.cu";
}
else if(split) {
name = "kernel_split";
source = "kernel_split.cu";
}
else {
name = "kernel";
source = "kernel.cu";
}
/* Compute cubin name. */
int major, minor;
cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, cuDevId);
@@ -391,8 +368,9 @@ public:
/* Attempt to use kernel provided with Blender. */
if(!use_adaptive_compilation()) {
const string cubin = path_get(string_printf("lib/%s_sm_%d%d.cubin",
name, major, minor));
const string cubin = path_get(string_printf(split ? "lib/kernel_split_sm_%d%d.cubin"
: "lib/kernel_sm_%d%d.cubin",
major, minor));
VLOG(1) << "Testing for pre-compiled kernel " << cubin << ".";
if(path_exists(cubin)) {
VLOG(1) << "Using precompiled kernel.";
@@ -401,7 +379,7 @@ public:
}
const string common_cflags =
compile_kernel_get_common_cflags(requested_features, filter, split);
compile_kernel_get_common_cflags(requested_features, split);
/* Try to use locally compiled kernel. */
const string source_path = path_get("source");
@@ -412,8 +390,9 @@ public:
*/
const string cubin_md5 = util_md5_string(kernel_md5 + common_cflags);
const string cubin_file = string_printf("cycles_%s_sm%d%d_%s.cubin",
name, major, minor,
const string cubin_file = string_printf(split ? "cycles_kernel_split_sm%d%d_%s.cubin"
: "cycles_kernel_sm%d%d_%s.cubin",
major, minor,
cubin_md5.c_str());
const string cubin = path_cache_get(path_join("kernels", cubin_file));
VLOG(1) << "Testing for locally compiled kernel " << cubin << ".";
@@ -448,7 +427,7 @@ public:
const string kernel = path_join(
path_join(source_path, "kernel"),
path_join("kernels",
path_join("cuda", source)));
path_join("cuda", split ? "kernel_split.cu" : "kernel.cu")));
double starttime = time_dt();
printf("Compiling CUDA kernel ...\n");
@@ -496,12 +475,9 @@ public:
return false;
/* get kernel */
string cubin = compile_kernel(requested_features, false, use_split_kernel());
if(cubin == "")
return false;
string cubin = compile_kernel(requested_features, use_split_kernel());
string filter_cubin = compile_kernel(requested_features, true, false);
if(filter_cubin == "")
if(cubin == "")
return false;
/* open module */
@@ -518,14 +494,6 @@ public:
if(cuda_error_(result, "cuModuleLoad"))
cuda_error_message(string_printf("Failed loading CUDA kernel %s.", cubin.c_str()));
if(path_read_text(filter_cubin, cubin_data))
result = cuModuleLoadData(&cuFilterModule, cubin_data.c_str());
else
result = CUDA_ERROR_FILE_NOT_FOUND;
if(cuda_error_(result, "cuModuleLoad"))
cuda_error_message(string_printf("Failed loading CUDA kernel %s.", filter_cubin.c_str()));
cuda_pop_context();
return (result == CUDA_SUCCESS);
@@ -608,11 +576,6 @@ public:
}
}
virtual device_ptr mem_alloc_sub_ptr(device_memory& mem, int offset, int /*size*/, MemoryType /*type*/)
{
return (device_ptr) (((char*) mem.device_pointer) + mem.memory_elements_size(offset));
}
void const_copy_to(const char *name, void *host, size_t size)
{
CUdeviceptr mem;
@@ -913,368 +876,6 @@ public:
}
}
bool denoising_set_tiles(device_ptr *buffers, DenoisingTask *task)
{
mem_alloc("Denoising Tile Info", task->tiles_mem, MEM_READ_ONLY);
TilesInfo *tiles = (TilesInfo*) task->tiles_mem.data_pointer;
for(int i = 0; i < 9; i++) {
tiles->buffers[i] = buffers[i];
}
mem_copy_to(task->tiles_mem);
return !have_error();
}
#define CUDA_GET_BLOCKSIZE(func, w, h) \
int threads_per_block; \
cuda_assert(cuFuncGetAttribute(&threads_per_block, CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK, func)); \
int threads = (int)sqrt((float)threads_per_block); \
int xblocks = ((w) + threads - 1)/threads; \
int yblocks = ((h) + threads - 1)/threads;
#define CUDA_LAUNCH_KERNEL(func, args) \
cuda_assert(cuLaunchKernel(func, \
xblocks, yblocks, 1, \
threads, threads, 1, \
0, 0, args, 0));
bool denoising_non_local_means(device_ptr image_ptr, device_ptr guide_ptr, device_ptr variance_ptr, device_ptr out_ptr,
DenoisingTask *task)
{
if(have_error())
return false;
cuda_push_context();
int4 rect = task->rect;
int w = rect.z-rect.x;
int h = rect.w-rect.y;
int r = task->nlm_state.r;
int f = task->nlm_state.f;
float a = task->nlm_state.a;
float k_2 = task->nlm_state.k_2;
CUdeviceptr difference = task->nlm_state.temporary_1_ptr;
CUdeviceptr blurDifference = task->nlm_state.temporary_2_ptr;
CUdeviceptr weightAccum = task->nlm_state.temporary_3_ptr;
cuda_assert(cuMemsetD8(weightAccum, 0, sizeof(float)*w*h));
cuda_assert(cuMemsetD8(out_ptr, 0, sizeof(float)*w*h));
CUfunction cuNLMCalcDifference, cuNLMBlur, cuNLMCalcWeight, cuNLMUpdateOutput, cuNLMNormalize;
cuda_assert(cuModuleGetFunction(&cuNLMCalcDifference, cuFilterModule, "kernel_cuda_filter_nlm_calc_difference"));
cuda_assert(cuModuleGetFunction(&cuNLMBlur, cuFilterModule, "kernel_cuda_filter_nlm_blur"));
cuda_assert(cuModuleGetFunction(&cuNLMCalcWeight, cuFilterModule, "kernel_cuda_filter_nlm_calc_weight"));
cuda_assert(cuModuleGetFunction(&cuNLMUpdateOutput, cuFilterModule, "kernel_cuda_filter_nlm_update_output"));
cuda_assert(cuModuleGetFunction(&cuNLMNormalize, cuFilterModule, "kernel_cuda_filter_nlm_normalize"));
cuda_assert(cuFuncSetCacheConfig(cuNLMCalcDifference, CU_FUNC_CACHE_PREFER_L1));
cuda_assert(cuFuncSetCacheConfig(cuNLMBlur, CU_FUNC_CACHE_PREFER_L1));
cuda_assert(cuFuncSetCacheConfig(cuNLMCalcWeight, CU_FUNC_CACHE_PREFER_L1));
cuda_assert(cuFuncSetCacheConfig(cuNLMUpdateOutput, CU_FUNC_CACHE_PREFER_L1));
cuda_assert(cuFuncSetCacheConfig(cuNLMNormalize, CU_FUNC_CACHE_PREFER_L1));
CUDA_GET_BLOCKSIZE(cuNLMCalcDifference, rect.z-rect.x, rect.w-rect.y);
int dx, dy;
int4 local_rect;
int channel_offset = 0;
void *calc_difference_args[] = {&dx, &dy, &guide_ptr, &variance_ptr, &difference, &local_rect, &w, &channel_offset, &a, &k_2};
void *blur_args[] = {&difference, &blurDifference, &local_rect, &w, &f};
void *calc_weight_args[] = {&blurDifference, &difference, &local_rect, &w, &f};
void *update_output_args[] = {&dx, &dy, &blurDifference, &image_ptr, &out_ptr, &weightAccum, &local_rect, &w, &f};
for(int i = 0; i < (2*r+1)*(2*r+1); i++) {
dy = i / (2*r+1) - r;
dx = i % (2*r+1) - r;
local_rect = make_int4(max(0, -dx), max(0, -dy), rect.z-rect.x - max(0, dx), rect.w-rect.y - max(0, dy));
CUDA_LAUNCH_KERNEL(cuNLMCalcDifference, calc_difference_args);
CUDA_LAUNCH_KERNEL(cuNLMBlur, blur_args);
CUDA_LAUNCH_KERNEL(cuNLMCalcWeight, calc_weight_args);
CUDA_LAUNCH_KERNEL(cuNLMBlur, blur_args);
CUDA_LAUNCH_KERNEL(cuNLMUpdateOutput, update_output_args);
}
local_rect = make_int4(0, 0, rect.z-rect.x, rect.w-rect.y);
void *normalize_args[] = {&out_ptr, &weightAccum, &local_rect, &w};
CUDA_LAUNCH_KERNEL(cuNLMNormalize, normalize_args);
cuda_assert(cuCtxSynchronize());
cuda_pop_context();
return !have_error();
}
bool denoising_construct_transform(DenoisingTask *task)
{
if(have_error())
return false;
cuda_push_context();
CUfunction cuFilterConstructTransform;
cuda_assert(cuModuleGetFunction(&cuFilterConstructTransform, cuFilterModule, "kernel_cuda_filter_construct_transform"));
cuda_assert(cuFuncSetCacheConfig(cuFilterConstructTransform, CU_FUNC_CACHE_PREFER_SHARED));
CUDA_GET_BLOCKSIZE(cuFilterConstructTransform,
task->storage.w,
task->storage.h);
void *args[] = {&task->buffer.mem.device_pointer,
&task->storage.transform.device_pointer,
&task->storage.rank.device_pointer,
&task->filter_area,
&task->rect,
&task->radius,
&task->pca_threshold,
&task->buffer.pass_stride};
CUDA_LAUNCH_KERNEL(cuFilterConstructTransform, args);
cuda_assert(cuCtxSynchronize());
cuda_pop_context();
return !have_error();
}
bool denoising_reconstruct(device_ptr color_ptr,
device_ptr color_variance_ptr,
device_ptr guide_ptr,
device_ptr guide_variance_ptr,
device_ptr output_ptr,
DenoisingTask *task)
{
if(have_error())
return false;
mem_zero(task->storage.XtWX);
mem_zero(task->storage.XtWY);
cuda_push_context();
CUfunction cuNLMCalcDifference, cuNLMBlur, cuNLMCalcWeight, cuNLMConstructGramian, cuFinalize;
cuda_assert(cuModuleGetFunction(&cuNLMCalcDifference, cuFilterModule, "kernel_cuda_filter_nlm_calc_difference"));
cuda_assert(cuModuleGetFunction(&cuNLMBlur, cuFilterModule, "kernel_cuda_filter_nlm_blur"));
cuda_assert(cuModuleGetFunction(&cuNLMCalcWeight, cuFilterModule, "kernel_cuda_filter_nlm_calc_weight"));
cuda_assert(cuModuleGetFunction(&cuNLMConstructGramian, cuFilterModule, "kernel_cuda_filter_nlm_construct_gramian"));
cuda_assert(cuModuleGetFunction(&cuFinalize, cuFilterModule, "kernel_cuda_filter_finalize"));
cuda_assert(cuFuncSetCacheConfig(cuNLMCalcDifference, CU_FUNC_CACHE_PREFER_L1));
cuda_assert(cuFuncSetCacheConfig(cuNLMBlur, CU_FUNC_CACHE_PREFER_L1));
cuda_assert(cuFuncSetCacheConfig(cuNLMCalcWeight, CU_FUNC_CACHE_PREFER_L1));
cuda_assert(cuFuncSetCacheConfig(cuNLMConstructGramian, CU_FUNC_CACHE_PREFER_SHARED));
cuda_assert(cuFuncSetCacheConfig(cuFinalize, CU_FUNC_CACHE_PREFER_L1));
CUDA_GET_BLOCKSIZE(cuNLMCalcDifference,
task->reconstruction_state.source_w,
task->reconstruction_state.source_h);
CUdeviceptr difference = task->reconstruction_state.temporary_1_ptr;
CUdeviceptr blurDifference = task->reconstruction_state.temporary_2_ptr;
int r = task->radius;
int f = 4;
float a = 1.0f;
for(int i = 0; i < (2*r+1)*(2*r+1); i++) {
int dy = i / (2*r+1) - r;
int dx = i % (2*r+1) - r;
int local_rect[4] = {max(0, -dx), max(0, -dy),
task->reconstruction_state.source_w - max(0, dx),
task->reconstruction_state.source_h - max(0, dy)};
void *calc_difference_args[] = {&dx, &dy,
&guide_ptr,
&guide_variance_ptr,
&difference,
&local_rect,
&task->buffer.w,
&task->buffer.pass_stride,
&a,
&task->nlm_k_2};
CUDA_LAUNCH_KERNEL(cuNLMCalcDifference, calc_difference_args);
void *blur_args[] = {&difference,
&blurDifference,
&local_rect,
&task->buffer.w,
&f};
CUDA_LAUNCH_KERNEL(cuNLMBlur, blur_args);
void *calc_weight_args[] = {&blurDifference,
&difference,
&local_rect,
&task->buffer.w,
&f};
CUDA_LAUNCH_KERNEL(cuNLMCalcWeight, calc_weight_args);
/* Reuse previous arguments. */
CUDA_LAUNCH_KERNEL(cuNLMBlur, blur_args);
void *construct_gramian_args[] = {&dx, &dy,
&blurDifference,
&task->buffer.mem.device_pointer,
&color_ptr,
&color_variance_ptr,
&task->storage.transform.device_pointer,
&task->storage.rank.device_pointer,
&task->storage.XtWX.device_pointer,
&task->storage.XtWY.device_pointer,
&local_rect,
&task->reconstruction_state.filter_rect,
&task->buffer.w,
&task->buffer.h,
&f,
&task->buffer.pass_stride};
CUDA_LAUNCH_KERNEL(cuNLMConstructGramian, construct_gramian_args);
}
void *finalize_args[] = {&task->buffer.w,
&task->buffer.h,
&output_ptr,
&task->storage.rank.device_pointer,
&task->storage.XtWX.device_pointer,
&task->storage.XtWY.device_pointer,
&task->filter_area,
&task->reconstruction_state.buffer_params.x,
&task->render_buffer.samples};
CUDA_LAUNCH_KERNEL(cuFinalize, finalize_args);
cuda_assert(cuCtxSynchronize());
cuda_pop_context();
return !have_error();
}
bool denoising_combine_halves(device_ptr a_ptr, device_ptr b_ptr,
device_ptr mean_ptr, device_ptr variance_ptr,
int r, int4 rect, DenoisingTask *task)
{
(void) task;
if(have_error())
return false;
cuda_push_context();
CUfunction cuFilterCombineHalves;
cuda_assert(cuModuleGetFunction(&cuFilterCombineHalves, cuFilterModule, "kernel_cuda_filter_combine_halves"));
cuda_assert(cuFuncSetCacheConfig(cuFilterCombineHalves, CU_FUNC_CACHE_PREFER_L1));
CUDA_GET_BLOCKSIZE(cuFilterCombineHalves,
task->rect.z-task->rect.x,
task->rect.w-task->rect.y);
void *args[] = {&mean_ptr,
&variance_ptr,
&a_ptr,
&b_ptr,
&rect,
&r};
CUDA_LAUNCH_KERNEL(cuFilterCombineHalves, args);
cuda_assert(cuCtxSynchronize());
cuda_pop_context();
return !have_error();
}
bool denoising_divide_shadow(device_ptr a_ptr, device_ptr b_ptr,
device_ptr sample_variance_ptr, device_ptr sv_variance_ptr,
device_ptr buffer_variance_ptr, DenoisingTask *task)
{
(void) task;
if(have_error())
return false;
cuda_push_context();
CUfunction cuFilterDivideShadow;
cuda_assert(cuModuleGetFunction(&cuFilterDivideShadow, cuFilterModule, "kernel_cuda_filter_divide_shadow"));
cuda_assert(cuFuncSetCacheConfig(cuFilterDivideShadow, CU_FUNC_CACHE_PREFER_L1));
CUDA_GET_BLOCKSIZE(cuFilterDivideShadow,
task->rect.z-task->rect.x,
task->rect.w-task->rect.y);
bool use_split_variance = use_split_kernel();
void *args[] = {&task->render_buffer.samples,
&task->tiles_mem.device_pointer,
&a_ptr,
&b_ptr,
&sample_variance_ptr,
&sv_variance_ptr,
&buffer_variance_ptr,
&task->rect,
&task->render_buffer.pass_stride,
&task->render_buffer.denoising_data_offset,
&use_split_variance};
CUDA_LAUNCH_KERNEL(cuFilterDivideShadow, args);
cuda_assert(cuCtxSynchronize());
cuda_pop_context();
return !have_error();
}
bool denoising_get_feature(int mean_offset,
int variance_offset,
device_ptr mean_ptr,
device_ptr variance_ptr,
DenoisingTask *task)
{
if(have_error())
return false;
cuda_push_context();
CUfunction cuFilterGetFeature;
cuda_assert(cuModuleGetFunction(&cuFilterGetFeature, cuFilterModule, "kernel_cuda_filter_get_feature"));
cuda_assert(cuFuncSetCacheConfig(cuFilterGetFeature, CU_FUNC_CACHE_PREFER_L1));
CUDA_GET_BLOCKSIZE(cuFilterGetFeature,
task->rect.z-task->rect.x,
task->rect.w-task->rect.y);
bool use_split_variance = use_split_kernel();
void *args[] = {&task->render_buffer.samples,
&task->tiles_mem.device_pointer,
&mean_offset,
&variance_offset,
&mean_ptr,
&variance_ptr,
&task->rect,
&task->render_buffer.pass_stride,
&task->render_buffer.denoising_data_offset,
&use_split_variance};
CUDA_LAUNCH_KERNEL(cuFilterGetFeature, args);
cuda_assert(cuCtxSynchronize());
cuda_pop_context();
return !have_error();
}
void denoise(RenderTile &rtile, const DeviceTask &task)
{
DenoisingTask denoising(this);
denoising.functions.construct_transform = function_bind(&CUDADevice::denoising_construct_transform, this, &denoising);
denoising.functions.reconstruct = function_bind(&CUDADevice::denoising_reconstruct, this, _1, _2, _3, _4, _5, &denoising);
denoising.functions.divide_shadow = function_bind(&CUDADevice::denoising_divide_shadow, this, _1, _2, _3, _4, _5, &denoising);
denoising.functions.non_local_means = function_bind(&CUDADevice::denoising_non_local_means, this, _1, _2, _3, _4, &denoising);
denoising.functions.combine_halves = function_bind(&CUDADevice::denoising_combine_halves, this, _1, _2, _3, _4, _5, _6, &denoising);
denoising.functions.get_feature = function_bind(&CUDADevice::denoising_get_feature, this, _1, _2, _3, _4, &denoising);
denoising.functions.set_tiles = function_bind(&CUDADevice::denoising_set_tiles, this, _1, &denoising);
denoising.filter_area = make_int4(rtile.x, rtile.y, rtile.w, rtile.h);
denoising.render_buffer.samples = rtile.sample;
RenderTile rtiles[9];
rtiles[4] = rtile;
task.map_neighbor_tiles(rtiles, this);
denoising.tiles_from_rendertiles(rtiles);
denoising.init_from_devicetask(task);
denoising.run_denoising();
task.unmap_neighbor_tiles(rtiles, this);
}
void path_trace(RenderTile& rtile, int sample, bool branched)
{
if(have_error())
@@ -1699,7 +1300,7 @@ public:
void thread_run(DeviceTask *task)
{
if(task->type == DeviceTask::RENDER) {
if(task->type == DeviceTask::PATH_TRACE) {
RenderTile tile;
bool branched = task->integrator_branched;
@@ -1707,56 +1308,47 @@ public:
/* Upload Bindless Mapping */
load_bindless_mapping();
DeviceRequestedFeatures requested_features;
if(use_split_kernel()) {
if(!use_split_kernel()) {
/* keep rendering tiles until done */
while(task->acquire_tile(this, tile)) {
int start_sample = tile.start_sample;
int end_sample = tile.start_sample + tile.num_samples;
for(int sample = start_sample; sample < end_sample; sample++) {
if(task->get_cancel()) {
if(task->need_finish_queue == false)
break;
}
path_trace(tile, sample, branched);
tile.sample = sample + 1;
task->update_progress(&tile, tile.w*tile.h);
}
task->release_tile(tile);
}
}
else {
DeviceRequestedFeatures requested_features;
if(!use_adaptive_compilation()) {
requested_features.max_closure = 64;
}
if(split_kernel == NULL) {
split_kernel = new CUDASplitKernel(this);
split_kernel->load_kernels(requested_features);
}
}
CUDASplitKernel split_kernel(this);
split_kernel.load_kernels(requested_features);
/* keep rendering tiles until done */
while(task->acquire_tile(this, tile)) {
if(tile.task == RenderTile::PATH_TRACE) {
if(use_split_kernel()) {
device_memory void_buffer;
split_kernel->path_trace(task, tile, void_buffer, void_buffer);
while(task->acquire_tile(this, tile)) {
device_memory void_buffer;
split_kernel.path_trace(task, tile, void_buffer, void_buffer);
task->release_tile(tile);
if(task->get_cancel()) {
if(task->need_finish_queue == false)
break;
}
else {
int start_sample = tile.start_sample;
int end_sample = tile.start_sample + tile.num_samples;
for(int sample = start_sample; sample < end_sample; sample++) {
if(task->get_cancel()) {
if(task->need_finish_queue == false)
break;
}
path_trace(tile, sample, branched);
tile.sample = sample + 1;
task->update_progress(&tile, tile.w*tile.h);
}
}
}
else if(tile.task == RenderTile::DENOISE) {
tile.sample = tile.start_sample + tile.num_samples;
denoise(tile, *task);
task->update_progress(&tile, tile.w*tile.h);
}
task->release_tile(tile);
if(task->get_cancel()) {
if(task->need_finish_queue == false)
break;
}
}
}
@@ -2035,8 +1627,7 @@ int2 CUDASplitKernel::split_kernel_global_size(device_memory& kg, device_memory&
<< string_human_readable_size(free) << ").";
size_t num_elements = max_elements_for_max_buffer_size(kg, data, free / 2);
size_t side = round_down((int)sqrt(num_elements), 32);
int2 global_size = make_int2(side, round_down(num_elements / side, 16));
int2 global_size = make_int2(round_down((int)sqrt(num_elements), 32), (int)sqrt(num_elements));
VLOG(1) << "Global size: " << global_size << ".";
return global_size;
}

View File

@@ -1,218 +0,0 @@
/*
* Copyright 2011-2017 Blender Foundation
*
* 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 "device/device_denoising.h"
#include "kernel/filter/filter_defines.h"
CCL_NAMESPACE_BEGIN
void DenoisingTask::init_from_devicetask(const DeviceTask &task)
{
radius = task.denoising_radius;
nlm_k_2 = powf(2.0f, lerp(-5.0f, 3.0f, task.denoising_strength));
if(task.denoising_relative_pca) {
pca_threshold = -powf(10.0f, lerp(-8.0f, 0.0f, task.denoising_feature_strength));
}
else {
pca_threshold = powf(10.0f, lerp(-5.0f, 3.0f, task.denoising_feature_strength));
}
render_buffer.pass_stride = task.pass_stride;
render_buffer.denoising_data_offset = task.pass_denoising_data;
render_buffer.denoising_clean_offset = task.pass_denoising_clean;
/* Expand filter_area by radius pixels and clamp the result to the extent of the neighboring tiles */
rect = make_int4(max(tiles->x[0], filter_area.x - radius),
max(tiles->y[0], filter_area.y - radius),
min(tiles->x[3], filter_area.x + filter_area.z + radius),
min(tiles->y[3], filter_area.y + filter_area.w + radius));
}
void DenoisingTask::tiles_from_rendertiles(RenderTile *rtiles)
{
tiles = (TilesInfo*) tiles_mem.resize(sizeof(TilesInfo)/sizeof(int));
device_ptr buffers[9];
for(int i = 0; i < 9; i++) {
buffers[i] = rtiles[i].buffer;
tiles->offsets[i] = rtiles[i].offset;
tiles->strides[i] = rtiles[i].stride;
}
tiles->x[0] = rtiles[3].x;
tiles->x[1] = rtiles[4].x;
tiles->x[2] = rtiles[5].x;
tiles->x[3] = rtiles[5].x + rtiles[5].w;
tiles->y[0] = rtiles[1].y;
tiles->y[1] = rtiles[4].y;
tiles->y[2] = rtiles[7].y;
tiles->y[3] = rtiles[7].y + rtiles[7].h;
render_buffer.offset = rtiles[4].offset;
render_buffer.stride = rtiles[4].stride;
render_buffer.ptr = rtiles[4].buffer;
functions.set_tiles(buffers);
}
bool DenoisingTask::run_denoising()
{
/* Allocate denoising buffer. */
buffer.passes = 14;
buffer.w = align_up(rect.z - rect.x, 4);
buffer.h = rect.w - rect.y;
buffer.pass_stride = align_up(buffer.w * buffer.h, divide_up(device->mem_address_alignment(), sizeof(float)));
buffer.mem.resize(buffer.pass_stride * buffer.passes);
device->mem_alloc("Denoising Pixel Buffer", buffer.mem, MEM_READ_WRITE);
device_ptr null_ptr = (device_ptr) 0;
/* Prefilter shadow feature. */
{
device_sub_ptr unfiltered_a (device, buffer.mem, 0, buffer.pass_stride, MEM_READ_WRITE);
device_sub_ptr unfiltered_b (device, buffer.mem, 1*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
device_sub_ptr sample_var (device, buffer.mem, 2*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
device_sub_ptr sample_var_var (device, buffer.mem, 3*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
device_sub_ptr buffer_var (device, buffer.mem, 5*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
device_sub_ptr filtered_var (device, buffer.mem, 6*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
device_sub_ptr nlm_temporary_1(device, buffer.mem, 7*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
device_sub_ptr nlm_temporary_2(device, buffer.mem, 8*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
device_sub_ptr nlm_temporary_3(device, buffer.mem, 9*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
nlm_state.temporary_1_ptr = *nlm_temporary_1;
nlm_state.temporary_2_ptr = *nlm_temporary_2;
nlm_state.temporary_3_ptr = *nlm_temporary_3;
/* Get the A/B unfiltered passes, the combined sample variance, the estimated variance of the sample variance and the buffer variance. */
functions.divide_shadow(*unfiltered_a, *unfiltered_b, *sample_var, *sample_var_var, *buffer_var);
/* Smooth the (generally pretty noisy) buffer variance using the spatial information from the sample variance. */
nlm_state.set_parameters(6, 3, 4.0f, 1.0f);
functions.non_local_means(*buffer_var, *sample_var, *sample_var_var, *filtered_var);
/* Reuse memory, the previous data isn't needed anymore. */
device_ptr filtered_a = *buffer_var,
filtered_b = *sample_var;
/* Use the smoothed variance to filter the two shadow half images using each other for weight calculation. */
nlm_state.set_parameters(5, 3, 1.0f, 0.25f);
functions.non_local_means(*unfiltered_a, *unfiltered_b, *filtered_var, filtered_a);
functions.non_local_means(*unfiltered_b, *unfiltered_a, *filtered_var, filtered_b);
device_ptr residual_var = *sample_var_var;
/* Estimate the residual variance between the two filtered halves. */
functions.combine_halves(filtered_a, filtered_b, null_ptr, residual_var, 2, rect);
device_ptr final_a = *unfiltered_a,
final_b = *unfiltered_b;
/* Use the residual variance for a second filter pass. */
nlm_state.set_parameters(4, 2, 1.0f, 0.5f);
functions.non_local_means(filtered_a, filtered_b, residual_var, final_a);
functions.non_local_means(filtered_b, filtered_a, residual_var, final_b);
/* Combine the two double-filtered halves to a final shadow feature. */
device_sub_ptr shadow_pass(device, buffer.mem, 4*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
functions.combine_halves(final_a, final_b, *shadow_pass, null_ptr, 0, rect);
}
/* Prefilter general features. */
{
device_sub_ptr unfiltered (device, buffer.mem, 8*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
device_sub_ptr variance (device, buffer.mem, 9*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
device_sub_ptr nlm_temporary_1(device, buffer.mem, 10*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
device_sub_ptr nlm_temporary_2(device, buffer.mem, 11*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
device_sub_ptr nlm_temporary_3(device, buffer.mem, 12*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
nlm_state.temporary_1_ptr = *nlm_temporary_1;
nlm_state.temporary_2_ptr = *nlm_temporary_2;
nlm_state.temporary_3_ptr = *nlm_temporary_3;
int mean_from[] = { 0, 1, 2, 6, 7, 8, 12 };
int variance_from[] = { 3, 4, 5, 9, 10, 11, 13 };
int pass_to[] = { 1, 2, 3, 0, 5, 6, 7 };
for(int pass = 0; pass < 7; pass++) {
device_sub_ptr feature_pass(device, buffer.mem, pass_to[pass]*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
/* Get the unfiltered pass and its variance from the RenderBuffers. */
functions.get_feature(mean_from[pass], variance_from[pass], *unfiltered, *variance);
/* Smooth the pass and store the result in the denoising buffers. */
nlm_state.set_parameters(2, 2, 1.0f, 0.25f);
functions.non_local_means(*unfiltered, *unfiltered, *variance, *feature_pass);
}
}
/* Copy color passes. */
{
int mean_from[] = {20, 21, 22};
int variance_from[] = {23, 24, 25};
int mean_to[] = { 8, 9, 10};
int variance_to[] = {11, 12, 13};
int num_color_passes = 3;
for(int pass = 0; pass < num_color_passes; pass++) {
device_sub_ptr color_pass (device, buffer.mem, mean_to[pass]*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
device_sub_ptr color_var_pass(device, buffer.mem, variance_to[pass]*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
functions.get_feature(mean_from[pass], variance_from[pass], *color_pass, *color_var_pass);
}
}
storage.w = filter_area.z;
storage.h = filter_area.w;
storage.transform.resize(storage.w*storage.h*TRANSFORM_SIZE);
storage.rank.resize(storage.w*storage.h);
device->mem_alloc("Denoising Transform", storage.transform, MEM_READ_WRITE);
device->mem_alloc("Denoising Rank", storage.rank, MEM_READ_WRITE);
functions.construct_transform();
device_only_memory<float> temporary_1;
device_only_memory<float> temporary_2;
temporary_1.resize(buffer.w*buffer.h);
temporary_2.resize(buffer.w*buffer.h);
device->mem_alloc("Denoising NLM temporary 1", temporary_1, MEM_READ_WRITE);
device->mem_alloc("Denoising NLM temporary 2", temporary_2, MEM_READ_WRITE);
reconstruction_state.temporary_1_ptr = temporary_1.device_pointer;
reconstruction_state.temporary_2_ptr = temporary_2.device_pointer;
storage.XtWX.resize(storage.w*storage.h*XTWX_SIZE);
storage.XtWY.resize(storage.w*storage.h*XTWY_SIZE);
device->mem_alloc("Denoising XtWX", storage.XtWX, MEM_READ_WRITE);
device->mem_alloc("Denoising XtWY", storage.XtWY, MEM_READ_WRITE);
reconstruction_state.filter_rect = make_int4(filter_area.x-rect.x, filter_area.y-rect.y, storage.w, storage.h);
int tile_coordinate_offset = filter_area.y*render_buffer.stride + filter_area.x;
reconstruction_state.buffer_params = make_int4(render_buffer.offset + tile_coordinate_offset,
render_buffer.stride,
render_buffer.pass_stride,
render_buffer.denoising_clean_offset);
reconstruction_state.source_w = rect.z-rect.x;
reconstruction_state.source_h = rect.w-rect.y;
{
device_sub_ptr color_ptr (device, buffer.mem, 8*buffer.pass_stride, 3*buffer.pass_stride, MEM_READ_WRITE);
device_sub_ptr color_var_ptr(device, buffer.mem, 11*buffer.pass_stride, 3*buffer.pass_stride, MEM_READ_WRITE);
functions.reconstruct(*color_ptr, *color_var_ptr, *color_ptr, *color_var_ptr, render_buffer.ptr);
}
device->mem_free(storage.XtWX);
device->mem_free(storage.XtWY);
device->mem_free(storage.transform);
device->mem_free(storage.rank);
device->mem_free(temporary_1);
device->mem_free(temporary_2);
device->mem_free(buffer.mem);
device->mem_free(tiles_mem);
return true;
}
CCL_NAMESPACE_END

View File

@@ -1,145 +0,0 @@
/*
* Copyright 2011-2017 Blender Foundation
*
* 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 __DEVICE_DENOISING_H__
#define __DEVICE_DENOISING_H__
#include "device/device.h"
#include "render/buffers.h"
#include "kernel/filter/filter_defines.h"
CCL_NAMESPACE_BEGIN
class DenoisingTask {
public:
/* Parameters of the denoising algorithm. */
int radius;
float nlm_k_2;
float pca_threshold;
/* Pointer and parameters of the RenderBuffers. */
struct RenderBuffers {
int denoising_data_offset;
int denoising_clean_offset;
int pass_stride;
int offset;
int stride;
device_ptr ptr;
int samples;
} render_buffer;
TilesInfo *tiles;
device_vector<int> tiles_mem;
void tiles_from_rendertiles(RenderTile *rtiles);
int4 rect;
int4 filter_area;
struct DeviceFunctions {
function<bool(device_ptr image_ptr, /* Contains the values that are smoothed. */
device_ptr guide_ptr, /* Contains the values that are used to calculate weights. */
device_ptr variance_ptr, /* Contains the variance of the guide image. */
device_ptr out_ptr /* The filtered output is written into this image. */
)> non_local_means;
function<bool(device_ptr color_ptr,
device_ptr color_variance_ptr,
device_ptr guide_ptr,
device_ptr guide_variance_ptr,
device_ptr output_ptr
)> reconstruct;
function<bool()> construct_transform;
function<bool(device_ptr a_ptr,
device_ptr b_ptr,
device_ptr mean_ptr,
device_ptr variance_ptr,
int r,
int4 rect
)> combine_halves;
function<bool(device_ptr a_ptr,
device_ptr b_ptr,
device_ptr sample_variance_ptr,
device_ptr sv_variance_ptr,
device_ptr buffer_variance_ptr
)> divide_shadow;
function<bool(int mean_offset,
int variance_offset,
device_ptr mean_ptr,
device_ptr variance_ptr
)> get_feature;
function<bool(device_ptr*)> set_tiles;
} functions;
/* Stores state of the current Reconstruction operation,
* which is accessed by the device in order to perform the operation. */
struct ReconstructionState {
device_ptr temporary_1_ptr; /* There two images are used as temporary storage. */
device_ptr temporary_2_ptr;
int4 filter_rect;
int4 buffer_params;
int source_w;
int source_h;
} reconstruction_state;
/* Stores state of the current NLM operation,
* which is accessed by the device in order to perform the operation. */
struct NLMState {
device_ptr temporary_1_ptr; /* There three images are used as temporary storage. */
device_ptr temporary_2_ptr;
device_ptr temporary_3_ptr;
int r; /* Search radius of the filter. */
int f; /* Patch size of the filter. */
float a; /* Variance compensation factor in the MSE estimation. */
float k_2; /* Squared value of the k parameter of the filter. */
void set_parameters(int r_, int f_, float a_, float k_2_) { r = r_; f = f_; a = a_, k_2 = k_2_; }
} nlm_state;
struct Storage {
device_only_memory<float> transform;
device_only_memory<int> rank;
device_only_memory<float> XtWX;
device_only_memory<float3> XtWY;
int w;
int h;
} storage;
DenoisingTask(Device *device) : device(device) {}
void init_from_devicetask(const DeviceTask &task);
bool run_denoising();
struct DenoiseBuffers {
int pass_stride;
int passes;
int w;
int h;
device_only_memory<float> mem;
} buffer;
protected:
Device *device;
};
CCL_NAMESPACE_END
#endif /* __DEVICE_DENOISING_H__ */

View File

@@ -35,8 +35,6 @@
CCL_NAMESPACE_BEGIN
class Device;
enum MemoryType {
MEM_READ_ONLY,
MEM_WRITE_ONLY,
@@ -146,7 +144,7 @@ template<> struct device_type_traits<float2> {
template<> struct device_type_traits<float3> {
static const DataType data_type = TYPE_FLOAT;
static const int num_elements = 4;
static const int num_elements = 3;
};
template<> struct device_type_traits<float4> {
@@ -175,9 +173,6 @@ class device_memory
{
public:
size_t memory_size() { return data_size*data_elements*datatype_size(data_type); }
size_t memory_elements_size(int elements) {
return elements*data_elements*datatype_size(data_type);
}
/* data information */
DataType data_type;
@@ -218,22 +213,6 @@ protected:
device_memory& operator = (const device_memory&);
};
template<typename T>
class device_only_memory : public device_memory
{
public:
device_only_memory()
{
data_type = device_type_traits<T>::data_type;
data_elements = max(device_type_traits<T>::num_elements, 1);
}
void resize(size_t num)
{
device_memory::resize(num*sizeof(T));
}
};
/* Device Vector */
template<typename T> class device_vector : public device_memory
@@ -320,27 +299,6 @@ private:
array<T> data;
};
/* A device_sub_ptr is a pointer into another existing memory.
* Therefore, it is not allocated separately, but just created from the already allocated base memory.
* It is freed automatically when it goes out of scope, which should happen before the base memory is freed.
* Note that some devices require the offset and size of the sub_ptr to be properly aligned. */
class device_sub_ptr
{
public:
device_sub_ptr(Device *device, device_memory& mem, int offset, int size, MemoryType type);
~device_sub_ptr();
/* No copying. */
device_sub_ptr& operator = (const device_sub_ptr&);
device_ptr operator*() const
{
return ptr;
}
protected:
Device *device;
device_ptr ptr;
};
CCL_NAMESPACE_END
#endif /* __DEVICE_MEMORY_H__ */

View File

@@ -299,60 +299,6 @@ public:
return -1;
}
void map_neighbor_tiles(Device *sub_device, RenderTile *tiles)
{
for(int i = 0; i < 9; i++) {
if(!tiles[i].buffers) {
continue;
}
/* If the tile was rendered on another device, copy its memory to
* to the current device now, for the duration of the denoising task.
* Note that this temporarily modifies the RenderBuffers and calls
* the device, so this function is not thread safe. */
if(tiles[i].buffers->device != sub_device) {
device_vector<float> &mem = tiles[i].buffers->buffer;
tiles[i].buffers->copy_from_device();
device_ptr original_ptr = mem.device_pointer;
mem.device_pointer = 0;
sub_device->mem_alloc("Temporary memory for neighboring tile", mem, MEM_READ_WRITE);
sub_device->mem_copy_to(mem);
tiles[i].buffer = mem.device_pointer;
mem.device_pointer = original_ptr;
}
}
}
void unmap_neighbor_tiles(Device * sub_device, RenderTile * tiles)
{
for(int i = 0; i < 9; i++) {
if(!tiles[i].buffers) {
continue;
}
if(tiles[i].buffers->device != sub_device) {
device_vector<float> &mem = tiles[i].buffers->buffer;
device_ptr original_ptr = mem.device_pointer;
mem.device_pointer = tiles[i].buffer;
/* Copy denoised tile to the host device. */
if(i == 4) {
tiles[i].buffers->copy_from_device(sub_device);
}
size_t mem_size = mem.device_size;
sub_device->mem_free(mem);
mem.device_pointer = original_ptr;
mem.device_size = mem_size;
/* Copy denoised tile to the original device. */
if(i == 4) {
tiles[i].buffers->device->mem_copy_to(mem);
}
}
}
}
int get_split_task_count(DeviceTask& task)
{
int total_tasks = 0;

View File

@@ -19,7 +19,6 @@
#include "kernel/kernel_types.h"
#include "kernel/split/kernel_split_data_types.h"
#include "util/util_logging.h"
#include "util/util_time.h"
CCL_NAMESPACE_BEGIN
@@ -39,8 +38,6 @@ DeviceSplitKernel::DeviceSplitKernel(Device *device) : device(device)
kernel_do_volume = NULL;
kernel_queue_enqueue = NULL;
kernel_indirect_background = NULL;
kernel_shader_setup = NULL;
kernel_shader_sort = NULL;
kernel_shader_eval = NULL;
kernel_holdout_emission_blurring_pathtermination_ao = NULL;
kernel_subsurface_scatter = NULL;
@@ -66,8 +63,6 @@ DeviceSplitKernel::~DeviceSplitKernel()
delete kernel_do_volume;
delete kernel_queue_enqueue;
delete kernel_indirect_background;
delete kernel_shader_setup;
delete kernel_shader_sort;
delete kernel_shader_eval;
delete kernel_holdout_emission_blurring_pathtermination_ao;
delete kernel_subsurface_scatter;
@@ -93,8 +88,6 @@ bool DeviceSplitKernel::load_kernels(const DeviceRequestedFeatures& requested_fe
LOAD_KERNEL(do_volume);
LOAD_KERNEL(queue_enqueue);
LOAD_KERNEL(indirect_background);
LOAD_KERNEL(shader_setup);
LOAD_KERNEL(shader_sort);
LOAD_KERNEL(shader_eval);
LOAD_KERNEL(holdout_emission_blurring_pathtermination_ao);
LOAD_KERNEL(subsurface_scatter);
@@ -115,9 +108,6 @@ bool DeviceSplitKernel::load_kernels(const DeviceRequestedFeatures& requested_fe
size_t DeviceSplitKernel::max_elements_for_max_buffer_size(device_memory& kg, device_memory& data, uint64_t max_buffer_size)
{
uint64_t size_per_element = state_buffer_size(kg, data, 1024) / 1024;
VLOG(1) << "Split state element size: "
<< string_human_readable_number(size_per_element) << " bytes. ("
<< string_human_readable_size(size_per_element) << ").";
return max_buffer_size / size_per_element;
}
@@ -166,13 +156,13 @@ bool DeviceSplitKernel::path_trace(DeviceTask *task,
unsigned int max_work_groups = num_global_elements / work_pool_size + 1;
/* Allocate work_pool_wgs memory. */
work_pool_wgs.resize(max_work_groups);
work_pool_wgs.resize(max_work_groups * sizeof(unsigned int));
device->mem_alloc("work_pool_wgs", work_pool_wgs, MEM_READ_WRITE);
queue_index.resize(NUM_QUEUES);
queue_index.resize(NUM_QUEUES * sizeof(int));
device->mem_alloc("queue_index", queue_index, MEM_READ_WRITE);
use_queues_flag.resize(1);
use_queues_flag.resize(sizeof(char));
device->mem_alloc("use_queues_flag", use_queues_flag, MEM_READ_WRITE);
ray_state.resize(num_global_elements);
@@ -237,7 +227,6 @@ bool DeviceSplitKernel::path_trace(DeviceTask *task,
ENQUEUE_SPLIT_KERNEL(path_init, global_size, local_size);
bool activeRaysAvailable = true;
double cancel_time = DBL_MAX;
while(activeRaysAvailable) {
/* Do path-iteration in host [Enqueue Path-iteration kernels. */
@@ -247,12 +236,9 @@ bool DeviceSplitKernel::path_trace(DeviceTask *task,
ENQUEUE_SPLIT_KERNEL(do_volume, global_size, local_size);
ENQUEUE_SPLIT_KERNEL(queue_enqueue, global_size, local_size);
ENQUEUE_SPLIT_KERNEL(indirect_background, global_size, local_size);
ENQUEUE_SPLIT_KERNEL(shader_setup, global_size, local_size);
ENQUEUE_SPLIT_KERNEL(shader_sort, global_size, local_size);
ENQUEUE_SPLIT_KERNEL(shader_eval, global_size, local_size);
ENQUEUE_SPLIT_KERNEL(holdout_emission_blurring_pathtermination_ao, global_size, local_size);
ENQUEUE_SPLIT_KERNEL(subsurface_scatter, global_size, local_size);
ENQUEUE_SPLIT_KERNEL(queue_enqueue, global_size, local_size);
ENQUEUE_SPLIT_KERNEL(direct_lighting, global_size, local_size);
ENQUEUE_SPLIT_KERNEL(shadow_blocked_ao, global_size, local_size);
ENQUEUE_SPLIT_KERNEL(shadow_blocked_dl, global_size, local_size);
@@ -261,14 +247,7 @@ bool DeviceSplitKernel::path_trace(DeviceTask *task,
ENQUEUE_SPLIT_KERNEL(queue_enqueue, global_size, local_size);
ENQUEUE_SPLIT_KERNEL(buffer_update, global_size, local_size);
if(task->get_cancel() && cancel_time == DBL_MAX) {
/* Wait up to twice as many seconds for current samples to finish
* to avoid artifacts in render result from ending too soon.
*/
cancel_time = time_dt() + 2.0 * time_multiplier;
}
if(time_dt() > cancel_time) {
if(task->get_cancel()) {
return true;
}
}
@@ -292,7 +271,7 @@ bool DeviceSplitKernel::path_trace(DeviceTask *task,
}
}
if(time_dt() > cancel_time) {
if(task->get_cancel()) {
return true;
}
}

View File

@@ -61,8 +61,6 @@ private:
SplitKernelFunction *kernel_do_volume;
SplitKernelFunction *kernel_queue_enqueue;
SplitKernelFunction *kernel_indirect_background;
SplitKernelFunction *kernel_shader_setup;
SplitKernelFunction *kernel_shader_sort;
SplitKernelFunction *kernel_shader_eval;
SplitKernelFunction *kernel_holdout_emission_blurring_pathtermination_ao;
SplitKernelFunction *kernel_subsurface_scatter;
@@ -80,16 +78,16 @@ private:
*/
device_memory split_data;
device_vector<uchar> ray_state;
device_only_memory<int> queue_index; /* Array of size num_queues that tracks the size of each queue. */
device_memory queue_index; /* Array of size num_queues * sizeof(int) that tracks the size of each queue. */
/* Flag to make sceneintersect and lampemission kernel use queues. */
device_only_memory<char> use_queues_flag;
device_memory use_queues_flag;
/* Approximate time it takes to complete one sample */
double avg_time_per_sample;
/* Work pool with respect to each work group. */
device_only_memory<unsigned int> work_pool_wgs;
device_memory work_pool_wgs;
/* clos_max value for which the kernels have been loaded currently. */
int current_max_closure;

View File

@@ -56,7 +56,7 @@ int DeviceTask::get_subtask_count(int num, int max_size)
if(type == SHADER) {
num = min(shader_w, num);
}
else if(type == RENDER) {
else if(type == PATH_TRACE) {
}
else {
num = min(h, num);
@@ -82,7 +82,7 @@ void DeviceTask::split(list<DeviceTask>& tasks, int num, int max_size)
tasks.push_back(task);
}
}
else if(type == RENDER) {
else if(type == PATH_TRACE) {
for(int i = 0; i < num; i++)
tasks.push_back(*this);
}
@@ -103,7 +103,7 @@ void DeviceTask::split(list<DeviceTask>& tasks, int num, int max_size)
void DeviceTask::update_progress(RenderTile *rtile, int pixel_samples)
{
if((type != RENDER) &&
if((type != PATH_TRACE) &&
(type != SHADER))
return;

View File

@@ -34,7 +34,7 @@ class Tile;
class DeviceTask : public Task {
public:
typedef enum { RENDER, FILM_CONVERT, SHADER } Type;
typedef enum { PATH_TRACE, FILM_CONVERT, SHADER } Type;
Type type;
int x, y, w, h;
@@ -53,7 +53,7 @@ public:
int passes_size;
explicit DeviceTask(Type type = RENDER);
explicit DeviceTask(Type type = PATH_TRACE);
int get_subtask_count(int num, int max_size = 0);
void split(list<DeviceTask>& tasks, int num, int max_size = 0);
@@ -65,16 +65,6 @@ public:
function<void(RenderTile&)> update_tile_sample;
function<void(RenderTile&)> release_tile;
function<bool(void)> get_cancel;
function<void(RenderTile*, Device*)> map_neighbor_tiles;
function<void(RenderTile*, Device*)> unmap_neighbor_tiles;
int denoising_radius;
float denoising_strength;
float denoising_feature_strength;
bool denoising_relative_pca;
int pass_stride;
int pass_denoising_data;
int pass_denoising_clean;
bool need_finish_queue;
bool integrator_branched;

View File

@@ -17,7 +17,6 @@
#ifdef WITH_OPENCL
#include "device/device.h"
#include "device/device_denoising.h"
#include "util/util_map.h"
#include "util/util_param.h"
@@ -32,16 +31,19 @@ CCL_NAMESPACE_BEGIN
/* Work around AMD driver hangs by ensuring each command is finished before doing anything else. */
# undef clEnqueueNDRangeKernel
# define clEnqueueNDRangeKernel(a, b, c, d, e, f, g, h, i) \
clFinish(a); \
CLEW_GET_FUN(__clewEnqueueNDRangeKernel)(a, b, c, d, e, f, g, h, i); \
clFinish(a);
# undef clEnqueueWriteBuffer
# define clEnqueueWriteBuffer(a, b, c, d, e, f, g, h, i) \
clFinish(a); \
CLEW_GET_FUN(__clewEnqueueWriteBuffer)(a, b, c, d, e, f, g, h, i); \
clFinish(a);
# undef clEnqueueReadBuffer
# define clEnqueueReadBuffer(a, b, c, d, e, f, g, h, i) \
clFinish(a); \
CLEW_GET_FUN(__clewEnqueueReadBuffer)(a, b, c, d, e, f, g, h, i); \
clFinish(a);
#endif /* CYCLES_DISABLE_DRIVER_WORKAROUNDS */
@@ -130,8 +132,6 @@ public:
cl_int* error = NULL);
static cl_device_type get_device_type(cl_device_id device_id);
static int mem_address_alignment(cl_device_id device_id);
/* Get somewhat more readable device name.
* Main difference is AMD OpenCL here which only gives code name
* for the regular device name. This will give more sane device
@@ -221,7 +221,7 @@ public:
cl_int err = stmt; \
\
if(err != CL_SUCCESS) { \
string message = string_printf("OpenCL error: %s in %s (%s:%d)", clewErrorString(err), #stmt, __FILE__, __LINE__); \
string message = string_printf("OpenCL error: %s in %s", clewErrorString(err), #stmt); \
if(error_msg == "") \
error_msg = message; \
fprintf(stderr, "%s\n", message.c_str()); \
@@ -285,7 +285,7 @@ public:
map<ustring, cl_kernel> kernels;
};
OpenCLProgram base_program, denoising_program;
OpenCLProgram base_program;
typedef map<string, device_vector<uchar>*> ConstMemMap;
typedef map<string, device_ptr> MemMap;
@@ -323,9 +323,6 @@ public:
void mem_copy_from(device_memory& mem, int y, int w, int h, int elem);
void mem_zero(device_memory& mem);
void mem_free(device_memory& mem);
int mem_address_alignment();
void const_copy_to(const char *name, void *host, size_t size);
void tex_alloc(const char *name,
device_memory& mem,
@@ -334,14 +331,12 @@ public:
void tex_free(device_memory& mem);
size_t global_size_round_up(int group_size, int global_size);
void enqueue_kernel(cl_kernel kernel, size_t w, size_t h, size_t max_workgroup_size = -1);
void enqueue_kernel(cl_kernel kernel, size_t w, size_t h);
void set_kernel_arg_mem(cl_kernel kernel, cl_uint *narg, const char *name);
void film_convert(DeviceTask& task, device_ptr buffer, device_ptr rgba_byte, device_ptr rgba_half);
void shader(DeviceTask& task);
void denoise(RenderTile& tile, const DeviceTask& task);
class OpenCLDeviceTask : public DeviceTask {
public:
OpenCLDeviceTask(OpenCLDeviceBase *device, DeviceTask& task)
@@ -375,48 +370,9 @@ public:
virtual void thread_run(DeviceTask * /*task*/) = 0;
virtual bool is_split_kernel() = 0;
protected:
string kernel_build_options(const string *debug_src = NULL);
void mem_zero_kernel(device_ptr ptr, size_t size);
bool denoising_non_local_means(device_ptr image_ptr,
device_ptr guide_ptr,
device_ptr variance_ptr,
device_ptr out_ptr,
DenoisingTask *task);
bool denoising_construct_transform(DenoisingTask *task);
bool denoising_reconstruct(device_ptr color_ptr,
device_ptr color_variance_ptr,
device_ptr guide_ptr,
device_ptr guide_variance_ptr,
device_ptr output_ptr,
DenoisingTask *task);
bool denoising_combine_halves(device_ptr a_ptr,
device_ptr b_ptr,
device_ptr mean_ptr,
device_ptr variance_ptr,
int r, int4 rect,
DenoisingTask *task);
bool denoising_divide_shadow(device_ptr a_ptr,
device_ptr b_ptr,
device_ptr sample_variance_ptr,
device_ptr sv_variance_ptr,
device_ptr buffer_variance_ptr,
DenoisingTask *task);
bool denoising_get_feature(int mean_offset,
int variance_offset,
device_ptr mean_ptr,
device_ptr variance_ptr,
DenoisingTask *task);
bool denoising_set_tiles(device_ptr *buffers,
DenoisingTask *task);
device_ptr mem_alloc_sub_ptr(device_memory& mem, int offset, int size, MemoryType type);
void mem_free_sub_ptr(device_ptr ptr);
class ArgumentWrapper {
public:
ArgumentWrapper() : size(0), pointer(NULL)

View File

@@ -213,23 +213,8 @@ bool OpenCLDeviceBase::load_kernels(const DeviceRequestedFeatures& requested_fea
base_program.add_kernel(ustring("bake"));
base_program.add_kernel(ustring("zero_buffer"));
denoising_program = OpenCLProgram(this, "denoising", "filter.cl", "");
denoising_program.add_kernel(ustring("filter_divide_shadow"));
denoising_program.add_kernel(ustring("filter_get_feature"));
denoising_program.add_kernel(ustring("filter_combine_halves"));
denoising_program.add_kernel(ustring("filter_construct_transform"));
denoising_program.add_kernel(ustring("filter_nlm_calc_difference"));
denoising_program.add_kernel(ustring("filter_nlm_blur"));
denoising_program.add_kernel(ustring("filter_nlm_calc_weight"));
denoising_program.add_kernel(ustring("filter_nlm_update_output"));
denoising_program.add_kernel(ustring("filter_nlm_normalize"));
denoising_program.add_kernel(ustring("filter_nlm_construct_gramian"));
denoising_program.add_kernel(ustring("filter_finalize"));
denoising_program.add_kernel(ustring("filter_set_tiles"));
vector<OpenCLProgram*> programs;
programs.push_back(&base_program);
programs.push_back(&denoising_program);
/* Call actual class to fill the vector with its programs. */
if(!load_kernels(requested_features, programs)) {
return false;
@@ -337,42 +322,37 @@ void OpenCLDeviceBase::mem_copy_from(device_memory& mem, int y, int w, int h, in
NULL, NULL));
}
void OpenCLDeviceBase::mem_zero_kernel(device_ptr mem, size_t size)
{
cl_kernel ckZeroBuffer = base_program(ustring("zero_buffer"));
size_t global_size[] = {1024, 1024};
size_t num_threads = global_size[0] * global_size[1];
cl_mem d_buffer = CL_MEM_PTR(mem);
cl_ulong d_offset = 0;
cl_ulong d_size = 0;
while(d_offset < size) {
d_size = std::min<cl_ulong>(num_threads*sizeof(float4), size - d_offset);
kernel_set_args(ckZeroBuffer, 0, d_buffer, d_size, d_offset);
ciErr = clEnqueueNDRangeKernel(cqCommandQueue,
ckZeroBuffer,
2,
NULL,
global_size,
NULL,
0,
NULL,
NULL);
opencl_assert_err(ciErr, "clEnqueueNDRangeKernel");
d_offset += d_size;
}
}
void OpenCLDeviceBase::mem_zero(device_memory& mem)
{
if(mem.device_pointer) {
if(base_program.is_loaded()) {
mem_zero_kernel(mem.device_pointer, mem.memory_size());
cl_kernel ckZeroBuffer = base_program(ustring("zero_buffer"));
size_t global_size[] = {1024, 1024};
size_t num_threads = global_size[0] * global_size[1];
cl_mem d_buffer = CL_MEM_PTR(mem.device_pointer);
cl_ulong d_offset = 0;
cl_ulong d_size = 0;
while(d_offset < mem.memory_size()) {
d_size = std::min<cl_ulong>(num_threads*sizeof(float4), mem.memory_size() - d_offset);
kernel_set_args(ckZeroBuffer, 0, d_buffer, d_size, d_offset);
ciErr = clEnqueueNDRangeKernel(cqCommandQueue,
ckZeroBuffer,
2,
NULL,
global_size,
NULL,
0,
NULL,
NULL);
opencl_assert_err(ciErr, "clEnqueueNDRangeKernel");
d_offset += d_size;
}
}
if(mem.data_pointer) {
@@ -416,41 +396,6 @@ void OpenCLDeviceBase::mem_free(device_memory& mem)
}
}
int OpenCLDeviceBase::mem_address_alignment()
{
return OpenCLInfo::mem_address_alignment(cdDevice);
}
device_ptr OpenCLDeviceBase::mem_alloc_sub_ptr(device_memory& mem, int offset, int size, MemoryType type)
{
cl_mem_flags mem_flag;
if(type == MEM_READ_ONLY)
mem_flag = CL_MEM_READ_ONLY;
else if(type == MEM_WRITE_ONLY)
mem_flag = CL_MEM_WRITE_ONLY;
else
mem_flag = CL_MEM_READ_WRITE;
cl_buffer_region info;
info.origin = mem.memory_elements_size(offset);
info.size = mem.memory_elements_size(size);
device_ptr sub_buf = (device_ptr) clCreateSubBuffer(CL_MEM_PTR(mem.device_pointer),
mem_flag,
CL_BUFFER_CREATE_TYPE_REGION,
&info,
&ciErr);
opencl_assert_err(ciErr, "clCreateSubBuffer");
return sub_buf;
}
void OpenCLDeviceBase::mem_free_sub_ptr(device_ptr device_pointer)
{
if(device_pointer && device_pointer != null_mem) {
opencl_assert(clReleaseMemObject(CL_MEM_PTR(device_pointer)));
}
}
void OpenCLDeviceBase::const_copy_to(const char *name, void *host, size_t size)
{
ConstMemMap::iterator i = const_mem_map.find(name);
@@ -504,7 +449,7 @@ size_t OpenCLDeviceBase::global_size_round_up(int group_size, int global_size)
return global_size + ((r == 0)? 0: group_size - r);
}
void OpenCLDeviceBase::enqueue_kernel(cl_kernel kernel, size_t w, size_t h, size_t max_workgroup_size)
void OpenCLDeviceBase::enqueue_kernel(cl_kernel kernel, size_t w, size_t h)
{
size_t workgroup_size, max_work_items[3];
@@ -513,10 +458,6 @@ void OpenCLDeviceBase::enqueue_kernel(cl_kernel kernel, size_t w, size_t h, size
clGetDeviceInfo(cdDevice,
CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(size_t)*3, max_work_items, NULL);
if(max_workgroup_size > 0 && workgroup_size > max_workgroup_size) {
workgroup_size = max_workgroup_size;
}
/* Try to divide evenly over 2 dimensions. */
size_t sqrt_workgroup_size = max((size_t)sqrt((double)workgroup_size), 1);
size_t local_size[2] = {sqrt_workgroup_size, sqrt_workgroup_size};
@@ -602,362 +543,6 @@ set_kernel_arg_mem(ckFilmConvertKernel, &start_arg_index, #name);
enqueue_kernel(ckFilmConvertKernel, d_w, d_h);
}
bool OpenCLDeviceBase::denoising_non_local_means(device_ptr image_ptr,
device_ptr guide_ptr,
device_ptr variance_ptr,
device_ptr out_ptr,
DenoisingTask *task)
{
int4 rect = task->rect;
int w = rect.z-rect.x;
int h = rect.w-rect.y;
int r = task->nlm_state.r;
int f = task->nlm_state.f;
float a = task->nlm_state.a;
float k_2 = task->nlm_state.k_2;
cl_mem difference = CL_MEM_PTR(task->nlm_state.temporary_1_ptr);
cl_mem blurDifference = CL_MEM_PTR(task->nlm_state.temporary_2_ptr);
cl_mem weightAccum = CL_MEM_PTR(task->nlm_state.temporary_3_ptr);
cl_mem image_mem = CL_MEM_PTR(image_ptr);
cl_mem guide_mem = CL_MEM_PTR(guide_ptr);
cl_mem variance_mem = CL_MEM_PTR(variance_ptr);
cl_mem out_mem = CL_MEM_PTR(out_ptr);
mem_zero_kernel(task->nlm_state.temporary_3_ptr, sizeof(float)*w*h);
mem_zero_kernel(out_ptr, sizeof(float)*w*h);
cl_kernel ckNLMCalcDifference = denoising_program(ustring("filter_nlm_calc_difference"));
cl_kernel ckNLMBlur = denoising_program(ustring("filter_nlm_blur"));
cl_kernel ckNLMCalcWeight = denoising_program(ustring("filter_nlm_calc_weight"));
cl_kernel ckNLMUpdateOutput = denoising_program(ustring("filter_nlm_update_output"));
cl_kernel ckNLMNormalize = denoising_program(ustring("filter_nlm_normalize"));
for(int i = 0; i < (2*r+1)*(2*r+1); i++) {
int dy = i / (2*r+1) - r;
int dx = i % (2*r+1) - r;
int4 local_rect = make_int4(max(0, -dx), max(0, -dy), rect.z-rect.x - max(0, dx), rect.w-rect.y - max(0, dy));
kernel_set_args(ckNLMCalcDifference, 0,
dx, dy, guide_mem, variance_mem,
difference, local_rect, w, 0, a, k_2);
kernel_set_args(ckNLMBlur, 0,
difference, blurDifference, local_rect, w, f);
kernel_set_args(ckNLMCalcWeight, 0,
blurDifference, difference, local_rect, w, f);
kernel_set_args(ckNLMUpdateOutput, 0,
dx, dy, blurDifference, image_mem,
out_mem, weightAccum, local_rect, w, f);
enqueue_kernel(ckNLMCalcDifference, w, h);
enqueue_kernel(ckNLMBlur, w, h);
enqueue_kernel(ckNLMCalcWeight, w, h);
enqueue_kernel(ckNLMBlur, w, h);
enqueue_kernel(ckNLMUpdateOutput, w, h);
}
int4 local_rect = make_int4(0, 0, w, h);
kernel_set_args(ckNLMNormalize, 0,
out_mem, weightAccum, local_rect, w);
enqueue_kernel(ckNLMNormalize, w, h);
return true;
}
bool OpenCLDeviceBase::denoising_construct_transform(DenoisingTask *task)
{
cl_mem buffer_mem = CL_MEM_PTR(task->buffer.mem.device_pointer);
cl_mem transform_mem = CL_MEM_PTR(task->storage.transform.device_pointer);
cl_mem rank_mem = CL_MEM_PTR(task->storage.rank.device_pointer);
cl_kernel ckFilterConstructTransform = denoising_program(ustring("filter_construct_transform"));
kernel_set_args(ckFilterConstructTransform, 0,
buffer_mem,
transform_mem,
rank_mem,
task->filter_area,
task->rect,
task->buffer.pass_stride,
task->radius,
task->pca_threshold);
enqueue_kernel(ckFilterConstructTransform,
task->storage.w,
task->storage.h,
256);
return true;
}
bool OpenCLDeviceBase::denoising_reconstruct(device_ptr color_ptr,
device_ptr color_variance_ptr,
device_ptr guide_ptr,
device_ptr guide_variance_ptr,
device_ptr output_ptr,
DenoisingTask *task)
{
mem_zero(task->storage.XtWX);
mem_zero(task->storage.XtWY);
cl_mem color_mem = CL_MEM_PTR(color_ptr);
cl_mem color_variance_mem = CL_MEM_PTR(color_variance_ptr);
cl_mem guide_mem = CL_MEM_PTR(guide_ptr);
cl_mem guide_variance_mem = CL_MEM_PTR(guide_variance_ptr);
cl_mem output_mem = CL_MEM_PTR(output_ptr);
cl_mem buffer_mem = CL_MEM_PTR(task->buffer.mem.device_pointer);
cl_mem transform_mem = CL_MEM_PTR(task->storage.transform.device_pointer);
cl_mem rank_mem = CL_MEM_PTR(task->storage.rank.device_pointer);
cl_mem XtWX_mem = CL_MEM_PTR(task->storage.XtWX.device_pointer);
cl_mem XtWY_mem = CL_MEM_PTR(task->storage.XtWY.device_pointer);
cl_kernel ckNLMCalcDifference = denoising_program(ustring("filter_nlm_calc_difference"));
cl_kernel ckNLMBlur = denoising_program(ustring("filter_nlm_blur"));
cl_kernel ckNLMCalcWeight = denoising_program(ustring("filter_nlm_calc_weight"));
cl_kernel ckNLMConstructGramian = denoising_program(ustring("filter_nlm_construct_gramian"));
cl_kernel ckFinalize = denoising_program(ustring("filter_finalize"));
cl_mem difference = CL_MEM_PTR(task->reconstruction_state.temporary_1_ptr);
cl_mem blurDifference = CL_MEM_PTR(task->reconstruction_state.temporary_2_ptr);
int r = task->radius;
int f = 4;
float a = 1.0f;
for(int i = 0; i < (2*r+1)*(2*r+1); i++) {
int dy = i / (2*r+1) - r;
int dx = i % (2*r+1) - r;
int local_rect[4] = {max(0, -dx), max(0, -dy),
task->reconstruction_state.source_w - max(0, dx),
task->reconstruction_state.source_h - max(0, dy)};
kernel_set_args(ckNLMCalcDifference, 0,
dx, dy,
guide_mem,
guide_variance_mem,
difference,
local_rect,
task->buffer.w,
task->buffer.pass_stride,
a, task->nlm_k_2);
enqueue_kernel(ckNLMCalcDifference,
task->reconstruction_state.source_w,
task->reconstruction_state.source_h);
kernel_set_args(ckNLMBlur, 0,
difference,
blurDifference,
local_rect,
task->buffer.w,
f);
enqueue_kernel(ckNLMBlur,
task->reconstruction_state.source_w,
task->reconstruction_state.source_h);
kernel_set_args(ckNLMCalcWeight, 0,
blurDifference,
difference,
local_rect,
task->buffer.w,
f);
enqueue_kernel(ckNLMCalcWeight,
task->reconstruction_state.source_w,
task->reconstruction_state.source_h);
/* Reuse previous arguments. */
enqueue_kernel(ckNLMBlur,
task->reconstruction_state.source_w,
task->reconstruction_state.source_h);
kernel_set_args(ckNLMConstructGramian, 0,
dx, dy,
blurDifference,
buffer_mem,
color_mem,
color_variance_mem,
transform_mem,
rank_mem,
XtWX_mem,
XtWY_mem,
local_rect,
task->reconstruction_state.filter_rect,
task->buffer.w,
task->buffer.h,
f,
task->buffer.pass_stride);
enqueue_kernel(ckNLMConstructGramian,
task->reconstruction_state.source_w,
task->reconstruction_state.source_h,
256);
}
kernel_set_args(ckFinalize, 0,
task->buffer.w,
task->buffer.h,
output_mem,
rank_mem,
XtWX_mem,
XtWY_mem,
task->filter_area,
task->reconstruction_state.buffer_params,
task->render_buffer.samples);
enqueue_kernel(ckFinalize,
task->reconstruction_state.source_w,
task->reconstruction_state.source_h);
return true;
}
bool OpenCLDeviceBase::denoising_combine_halves(device_ptr a_ptr,
device_ptr b_ptr,
device_ptr mean_ptr,
device_ptr variance_ptr,
int r, int4 rect,
DenoisingTask *task)
{
(void) task;
cl_mem a_mem = CL_MEM_PTR(a_ptr);
cl_mem b_mem = CL_MEM_PTR(b_ptr);
cl_mem mean_mem = CL_MEM_PTR(mean_ptr);
cl_mem variance_mem = CL_MEM_PTR(variance_ptr);
cl_kernel ckFilterCombineHalves = denoising_program(ustring("filter_combine_halves"));
kernel_set_args(ckFilterCombineHalves, 0,
mean_mem,
variance_mem,
a_mem,
b_mem,
rect,
r);
enqueue_kernel(ckFilterCombineHalves,
task->rect.z-task->rect.x,
task->rect.w-task->rect.y);
return true;
}
bool OpenCLDeviceBase::denoising_divide_shadow(device_ptr a_ptr,
device_ptr b_ptr,
device_ptr sample_variance_ptr,
device_ptr sv_variance_ptr,
device_ptr buffer_variance_ptr,
DenoisingTask *task)
{
(void) task;
cl_mem a_mem = CL_MEM_PTR(a_ptr);
cl_mem b_mem = CL_MEM_PTR(b_ptr);
cl_mem sample_variance_mem = CL_MEM_PTR(sample_variance_ptr);
cl_mem sv_variance_mem = CL_MEM_PTR(sv_variance_ptr);
cl_mem buffer_variance_mem = CL_MEM_PTR(buffer_variance_ptr);
cl_mem tiles_mem = CL_MEM_PTR(task->tiles_mem.device_pointer);
cl_kernel ckFilterDivideShadow = denoising_program(ustring("filter_divide_shadow"));
char split_kernel = is_split_kernel()? 1 : 0;
kernel_set_args(ckFilterDivideShadow, 0,
task->render_buffer.samples,
tiles_mem,
a_mem,
b_mem,
sample_variance_mem,
sv_variance_mem,
buffer_variance_mem,
task->rect,
task->render_buffer.pass_stride,
task->render_buffer.denoising_data_offset,
split_kernel);
enqueue_kernel(ckFilterDivideShadow,
task->rect.z-task->rect.x,
task->rect.w-task->rect.y);
return true;
}
bool OpenCLDeviceBase::denoising_get_feature(int mean_offset,
int variance_offset,
device_ptr mean_ptr,
device_ptr variance_ptr,
DenoisingTask *task)
{
cl_mem mean_mem = CL_MEM_PTR(mean_ptr);
cl_mem variance_mem = CL_MEM_PTR(variance_ptr);
cl_mem tiles_mem = CL_MEM_PTR(task->tiles_mem.device_pointer);
cl_kernel ckFilterGetFeature = denoising_program(ustring("filter_get_feature"));
char split_kernel = is_split_kernel()? 1 : 0;
kernel_set_args(ckFilterGetFeature, 0,
task->render_buffer.samples,
tiles_mem,
mean_offset,
variance_offset,
mean_mem,
variance_mem,
task->rect,
task->render_buffer.pass_stride,
task->render_buffer.denoising_data_offset,
split_kernel);
enqueue_kernel(ckFilterGetFeature,
task->rect.z-task->rect.x,
task->rect.w-task->rect.y);
return true;
}
bool OpenCLDeviceBase::denoising_set_tiles(device_ptr *buffers,
DenoisingTask *task)
{
mem_alloc("Denoising Tile Info", task->tiles_mem, MEM_READ_WRITE);
mem_copy_to(task->tiles_mem);
cl_mem tiles_mem = CL_MEM_PTR(task->tiles_mem.device_pointer);
cl_kernel ckFilterSetTiles = denoising_program(ustring("filter_set_tiles"));
kernel_set_args(ckFilterSetTiles, 0, tiles_mem);
for(int i = 0; i < 9; i++) {
cl_mem buffer_mem = CL_MEM_PTR(buffers[i]);
kernel_set_args(ckFilterSetTiles, i+1, buffer_mem);
}
enqueue_kernel(ckFilterSetTiles, 1, 1);
return true;
}
void OpenCLDeviceBase::denoise(RenderTile &rtile, const DeviceTask &task)
{
DenoisingTask denoising(this);
denoising.functions.set_tiles = function_bind(&OpenCLDeviceBase::denoising_set_tiles, this, _1, &denoising);
denoising.functions.construct_transform = function_bind(&OpenCLDeviceBase::denoising_construct_transform, this, &denoising);
denoising.functions.reconstruct = function_bind(&OpenCLDeviceBase::denoising_reconstruct, this, _1, _2, _3, _4, _5, &denoising);
denoising.functions.divide_shadow = function_bind(&OpenCLDeviceBase::denoising_divide_shadow, this, _1, _2, _3, _4, _5, &denoising);
denoising.functions.non_local_means = function_bind(&OpenCLDeviceBase::denoising_non_local_means, this, _1, _2, _3, _4, &denoising);
denoising.functions.combine_halves = function_bind(&OpenCLDeviceBase::denoising_combine_halves, this, _1, _2, _3, _4, _5, _6, &denoising);
denoising.functions.get_feature = function_bind(&OpenCLDeviceBase::denoising_get_feature, this, _1, _2, _3, _4, &denoising);
denoising.filter_area = make_int4(rtile.x, rtile.y, rtile.w, rtile.h);
denoising.render_buffer.samples = rtile.sample;
RenderTile rtiles[9];
rtiles[4] = rtile;
task.map_neighbor_tiles(rtiles, this);
denoising.tiles_from_rendertiles(rtiles);
denoising.init_from_devicetask(task);
denoising.run_denoising();
task.unmap_neighbor_tiles(rtiles, this);
}
void OpenCLDeviceBase::shader(DeviceTask& task)
{
/* cast arguments to cl types */
@@ -1027,7 +612,7 @@ void OpenCLDeviceBase::shader(DeviceTask& task)
string OpenCLDeviceBase::kernel_build_options(const string *debug_src)
{
string build_options = "-cl-no-signed-zeros -cl-mad-enable ";
string build_options = "-cl-fast-relaxed-math ";
if(platform_name == "NVIDIA CUDA") {
build_options += "-D__KERNEL_OPENCL_NVIDIA__ "

View File

@@ -108,53 +108,41 @@ public:
else if(task->type == DeviceTask::SHADER) {
shader(*task);
}
else if(task->type == DeviceTask::RENDER) {
else if(task->type == DeviceTask::PATH_TRACE) {
RenderTile tile;
/* Keep rendering tiles until done. */
while(task->acquire_tile(this, tile)) {
if(tile.task == RenderTile::PATH_TRACE) {
int start_sample = tile.start_sample;
int end_sample = tile.start_sample + tile.num_samples;
int start_sample = tile.start_sample;
int end_sample = tile.start_sample + tile.num_samples;
for(int sample = start_sample; sample < end_sample; sample++) {
if(task->get_cancel()) {
if(task->need_finish_queue == false)
break;
}
path_trace(tile, sample);
tile.sample = sample + 1;
task->update_progress(&tile, tile.w*tile.h);
for(int sample = start_sample; sample < end_sample; sample++) {
if(task->get_cancel()) {
if(task->need_finish_queue == false)
break;
}
/* Complete kernel execution before release tile */
/* This helps in multi-device render;
* The device that reaches the critical-section function
* release_tile waits (stalling other devices from entering
* release_tile) for all kernels to complete. If device1 (a
* slow-render device) reaches release_tile first then it would
* stall device2 (a fast-render device) from proceeding to render
* next tile.
*/
clFinish(cqCommandQueue);
}
else if(tile.task == RenderTile::DENOISE) {
tile.sample = tile.start_sample + tile.num_samples;
denoise(tile, *task);
path_trace(tile, sample);
tile.sample = sample + 1;
task->update_progress(&tile, tile.w*tile.h);
}
/* Complete kernel execution before release tile */
/* This helps in multi-device render;
* The device that reaches the critical-section function
* release_tile waits (stalling other devices from entering
* release_tile) for all kernels to complete. If device1 (a
* slow-render device) reaches release_tile first then it would
* stall device2 (a fast-render device) from proceeding to render
* next tile.
*/
clFinish(cqCommandQueue);
task->release_tile(tile);
}
}
}
bool is_split_kernel()
{
return false;
}
};
Device *opencl_create_mega_device(DeviceInfo& info, Stats& stats, bool background)

View File

@@ -100,7 +100,7 @@ public:
else if(task->type == DeviceTask::SHADER) {
shader(*task);
}
else if(task->type == DeviceTask::RENDER) {
else if(task->type == DeviceTask::PATH_TRACE) {
RenderTile tile;
/* Copy dummy KernelGlobals related to OpenCL from kernel_globals.h to
@@ -123,29 +123,21 @@ public:
/* Keep rendering tiles until done. */
while(task->acquire_tile(this, tile)) {
if(tile.task == RenderTile::PATH_TRACE) {
assert(tile.task == RenderTile::PATH_TRACE);
split_kernel->path_trace(task,
tile,
kgbuffer,
*const_mem_map["__data"]);
split_kernel->path_trace(task,
tile,
kgbuffer,
*const_mem_map["__data"]);
/* Complete kernel execution before release tile. */
/* This helps in multi-device render;
* The device that reaches the critical-section function
* release_tile waits (stalling other devices from entering
* release_tile) for all kernels to complete. If device1 (a
* slow-render device) reaches release_tile first then it would
* stall device2 (a fast-render device) from proceeding to render
* next tile.
*/
clFinish(cqCommandQueue);
}
else if(tile.task == RenderTile::DENOISE) {
tile.sample = tile.start_sample + tile.num_samples;
denoise(tile, *task);
task->update_progress(&tile, tile.w*tile.h);
}
/* Complete kernel execution before release tile. */
/* This helps in multi-device render;
* The device that reaches the critical-section function
* release_tile waits (stalling other devices from entering
* release_tile) for all kernels to complete. If device1 (a
* slow-render device) reaches release_tile first then it would
* stall device2 (a fast-render device) from proceeding to render
* next tile.
*/
clFinish(cqCommandQueue);
task->release_tile(tile);
}
@@ -154,11 +146,6 @@ public:
}
}
bool is_split_kernel()
{
return true;
}
protected:
/* ** Those guys are for workign around some compiler-specific bugs ** */

View File

@@ -1073,20 +1073,6 @@ string OpenCLInfo::get_readable_device_name(cl_device_id device_id)
return get_device_name(device_id);
}
int OpenCLInfo::mem_address_alignment(cl_device_id device_id)
{
int base_align_bits;
if(clGetDeviceInfo(device_id,
CL_DEVICE_MEM_BASE_ADDR_ALIGN,
sizeof(int),
&base_align_bits,
NULL) == CL_SUCCESS)
{
return base_align_bits/8;
}
return 1;
}
CCL_NAMESPACE_END
#endif

View File

@@ -10,23 +10,7 @@ set(INC_SYS
set(SRC
kernels/cpu/kernel.cpp
kernels/cpu/kernel_sse2.cpp
kernels/cpu/kernel_sse3.cpp
kernels/cpu/kernel_sse41.cpp
kernels/cpu/kernel_avx.cpp
kernels/cpu/kernel_avx2.cpp
kernels/cpu/kernel_split.cpp
kernels/cpu/kernel_split_sse2.cpp
kernels/cpu/kernel_split_sse3.cpp
kernels/cpu/kernel_split_sse41.cpp
kernels/cpu/kernel_split_avx.cpp
kernels/cpu/kernel_split_avx2.cpp
kernels/cpu/filter.cpp
kernels/cpu/filter_sse2.cpp
kernels/cpu/filter_sse3.cpp
kernels/cpu/filter_sse41.cpp
kernels/cpu/filter_avx.cpp
kernels/cpu/filter_avx2.cpp
kernels/opencl/kernel.cl
kernels/opencl/kernel_state_buffer_size.cl
kernels/opencl/kernel_split.cl
@@ -37,8 +21,6 @@ set(SRC
kernels/opencl/kernel_lamp_emission.cl
kernels/opencl/kernel_do_volume.cl
kernels/opencl/kernel_indirect_background.cl
kernels/opencl/kernel_shader_setup.cl
kernels/opencl/kernel_shader_sort.cl
kernels/opencl/kernel_shader_eval.cl
kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl
kernels/opencl/kernel_subsurface_scatter.cl
@@ -48,10 +30,8 @@ set(SRC
kernels/opencl/kernel_next_iteration_setup.cl
kernels/opencl/kernel_indirect_subsurface.cl
kernels/opencl/kernel_buffer_update.cl
kernels/opencl/filter.cl
kernels/cuda/kernel.cu
kernels/cuda/kernel_split.cu
kernels/cuda/filter.cu
)
set(SRC_BVH_HEADERS
@@ -113,8 +93,6 @@ set(SRC_KERNELS_CPU_HEADERS
kernels/cpu/kernel_cpu.h
kernels/cpu/kernel_cpu_impl.h
kernels/cpu/kernel_cpu_image.h
kernels/cpu/filter_cpu.h
kernels/cpu/filter_cpu_impl.h
)
set(SRC_KERNELS_CUDA_HEADERS
@@ -210,21 +188,6 @@ set(SRC_GEOM_HEADERS
geom/geom_volume.h
)
set(SRC_FILTER_HEADERS
filter/filter.h
filter/filter_defines.h
filter/filter_features.h
filter/filter_features_sse.h
filter/filter_kernel.h
filter/filter_nlm_cpu.h
filter/filter_nlm_gpu.h
filter/filter_prefilter.h
filter/filter_reconstruction.h
filter/filter_transform.h
filter/filter_transform_gpu.h
filter/filter_transform_sse.h
)
set(SRC_UTIL_HEADERS
../util/util_atomic.h
../util/util_color.h
@@ -233,47 +196,13 @@ set(SRC_UTIL_HEADERS
../util/util_math.h
../util/util_math_fast.h
../util/util_math_intersect.h
../util/util_math_float2.h
../util/util_math_float3.h
../util/util_math_float4.h
../util/util_math_int2.h
../util/util_math_int3.h
../util/util_math_int4.h
../util/util_math_matrix.h
../util/util_static_assert.h
../util/util_transform.h
../util/util_texture.h
../util/util_types.h
../util/util_types_float2.h
../util/util_types_float2_impl.h
../util/util_types_float3.h
../util/util_types_float3_impl.h
../util/util_types_float4.h
../util/util_types_float4_impl.h
../util/util_types_int2.h
../util/util_types_int2_impl.h
../util/util_types_int3.h
../util/util_types_int3_impl.h
../util/util_types_int4.h
../util/util_types_int4_impl.h
../util/util_types_uchar2.h
../util/util_types_uchar2_impl.h
../util/util_types_uchar3.h
../util/util_types_uchar3_impl.h
../util/util_types_uchar4.h
../util/util_types_uchar4_impl.h
../util/util_types_uint2.h
../util/util_types_uint2_impl.h
../util/util_types_uint3.h
../util/util_types_uint3_impl.h
../util/util_types_uint4.h
../util/util_types_uint4_impl.h
../util/util_types_vector3.h
../util/util_types_vector3_impl.h
)
set(SRC_SPLIT_HEADERS
split/kernel_branched.h
split/kernel_buffer_update.h
split/kernel_data_init.h
split/kernel_direct_lighting.h
@@ -286,8 +215,6 @@ set(SRC_SPLIT_HEADERS
split/kernel_path_init.h
split/kernel_queue_enqueue.h
split/kernel_scene_intersect.h
split/kernel_shader_setup.h
split/kernel_shader_sort.h
split/kernel_shader_eval.h
split/kernel_shadow_blocked_ao.h
split/kernel_shadow_blocked_dl.h
@@ -331,21 +258,23 @@ if(WITH_CYCLES_CUDA_BINARIES)
${SRC_CLOSURE_HEADERS}
${SRC_UTIL_HEADERS}
)
set(cuda_filter_sources kernels/cuda/filter.cu
${SRC_HEADERS}
${SRC_KERNELS_CUDA_HEADERS}
${SRC_FILTER_HEADERS}
${SRC_UTIL_HEADERS}
)
set(cuda_cubins)
macro(CYCLES_CUDA_KERNEL_ADD arch name flags sources experimental)
if(${experimental})
set(flags ${flags} -D__KERNEL_EXPERIMENTAL__)
set(name ${name}_experimental)
macro(CYCLES_CUDA_KERNEL_ADD arch split experimental)
if(${split})
set(cuda_extra_flags "-D__SPLIT__")
set(cuda_cubin kernel_split)
else()
set(cuda_extra_flags "")
set(cuda_cubin kernel)
endif()
set(cuda_cubin ${name}_${arch}.cubin)
if(${experimental})
set(cuda_extra_flags ${cuda_extra_flags} -D__KERNEL_EXPERIMENTAL__)
set(cuda_cubin ${cuda_cubin}_experimental)
endif()
set(cuda_cubin ${cuda_cubin}_${arch}.cubin)
if(WITH_CYCLES_DEBUG)
set(cuda_debug_flags "-D__KERNEL_DEBUG__")
@@ -359,7 +288,11 @@ if(WITH_CYCLES_CUDA_BINARIES)
set(cuda_version_flags "-D__KERNEL_CUDA_VERSION__=${cuda_nvcc_version}")
set(cuda_math_flags "--use_fast_math")
set(cuda_kernel_src "/kernels/cuda/${name}.cu")
if(split)
set(cuda_kernel_src "/kernels/cuda/kernel_split.cu")
else()
set(cuda_kernel_src "/kernels/cuda/kernel.cu")
endif()
add_custom_command(
OUTPUT ${cuda_cubin}
@@ -373,13 +306,13 @@ if(WITH_CYCLES_CUDA_BINARIES)
${cuda_arch_flags}
${cuda_version_flags}
${cuda_math_flags}
${flags}
${cuda_extra_flags}
${cuda_debug_flags}
-I${CMAKE_CURRENT_SOURCE_DIR}/..
-DCCL_NAMESPACE_BEGIN=
-DCCL_NAMESPACE_END=
-DNVCC
DEPENDS ${sources})
DEPENDS ${cuda_sources})
delayed_install("${CMAKE_CURRENT_BINARY_DIR}" "${cuda_cubin}" ${CYCLES_INSTALL_PATH}/lib)
list(APPEND cuda_cubins ${cuda_cubin})
@@ -393,12 +326,11 @@ if(WITH_CYCLES_CUDA_BINARIES)
foreach(arch ${CYCLES_CUDA_BINARIES_ARCH})
# Compile regular kernel
CYCLES_CUDA_KERNEL_ADD(${arch} kernel "" "${cuda_sources}" FALSE)
CYCLES_CUDA_KERNEL_ADD(${arch} filter "" "${cuda_filter_sources}" FALSE)
CYCLES_CUDA_KERNEL_ADD(${arch} FALSE FALSE)
if(WITH_CYCLES_CUDA_SPLIT_KERNEL_BINARIES)
# Compile split kernel
CYCLES_CUDA_KERNEL_ADD(${arch} kernel_split "-D__SPLIT__" ${cuda_sources} FALSE)
CYCLES_CUDA_KERNEL_ADD(${arch} TRUE FALSE)
endif()
endforeach()
@@ -419,30 +351,41 @@ include_directories(SYSTEM ${INC_SYS})
set_source_files_properties(kernels/cpu/kernel.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_KERNEL_FLAGS}")
set_source_files_properties(kernels/cpu/kernel_split.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_KERNEL_FLAGS}")
set_source_files_properties(kernels/cpu/filter.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_KERNEL_FLAGS}")
if(CXX_HAS_SSE)
list(APPEND SRC
kernels/cpu/kernel_sse2.cpp
kernels/cpu/kernel_sse3.cpp
kernels/cpu/kernel_sse41.cpp
kernels/cpu/kernel_split_sse2.cpp
kernels/cpu/kernel_split_sse3.cpp
kernels/cpu/kernel_split_sse41.cpp
)
set_source_files_properties(kernels/cpu/kernel_sse2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE2_KERNEL_FLAGS}")
set_source_files_properties(kernels/cpu/kernel_sse3.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE3_KERNEL_FLAGS}")
set_source_files_properties(kernels/cpu/kernel_sse41.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS}")
set_source_files_properties(kernels/cpu/kernel_split_sse2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE2_KERNEL_FLAGS}")
set_source_files_properties(kernels/cpu/kernel_split_sse3.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE3_KERNEL_FLAGS}")
set_source_files_properties(kernels/cpu/kernel_split_sse41.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS}")
set_source_files_properties(kernels/cpu/filter_sse2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE2_KERNEL_FLAGS}")
set_source_files_properties(kernels/cpu/filter_sse3.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE3_KERNEL_FLAGS}")
set_source_files_properties(kernels/cpu/filter_sse41.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS}")
endif()
if(CXX_HAS_AVX)
list(APPEND SRC
kernels/cpu/kernel_avx.cpp
kernels/cpu/kernel_split_avx.cpp
)
set_source_files_properties(kernels/cpu/kernel_avx.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX_KERNEL_FLAGS}")
set_source_files_properties(kernels/cpu/kernel_split_avx.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX_KERNEL_FLAGS}")
set_source_files_properties(kernels/cpu/filter_avx.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX_KERNEL_FLAGS}")
endif()
if(CXX_HAS_AVX2)
list(APPEND SRC
kernels/cpu/kernel_avx2.cpp
kernels/cpu/kernel_split_avx2.cpp
)
set_source_files_properties(kernels/cpu/kernel_avx2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
set_source_files_properties(kernels/cpu/kernel_split_avx2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
set_source_files_properties(kernels/cpu/filter_avx2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
endif()
add_library(cycles_kernel
@@ -452,7 +395,6 @@ add_library(cycles_kernel
${SRC_KERNELS_CUDA_HEADERS}
${SRC_BVH_HEADERS}
${SRC_CLOSURE_HEADERS}
${SRC_FILTER_HEADERS}
${SRC_SVM_HEADERS}
${SRC_GEOM_HEADERS}
${SRC_SPLIT_HEADERS}
@@ -482,8 +424,6 @@ delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_scene_interse
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_lamp_emission.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_do_volume.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_indirect_background.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shader_setup.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shader_sort.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shader_eval.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_subsurface_scatter.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
@@ -493,15 +433,12 @@ delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shadow_blocke
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_next_iteration_setup.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_indirect_subsurface.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_buffer_update.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/filter.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/cuda/kernel.cu" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/cuda)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/cuda/kernel_split.cu" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/cuda)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/cuda/filter.cu" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/cuda)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_KERNELS_CUDA_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/cuda)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_BVH_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel/bvh)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_CLOSURE_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel/closure)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_FILTER_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel/filter)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_SVM_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel/svm)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_GEOM_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel/geom)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_UTIL_HEADERS}" ${CYCLES_INSTALL_PATH}/source/util)

View File

@@ -137,7 +137,6 @@ ccl_device_forceinline int bsdf_sample(KernelGlobals *kg,
label = bsdf_hair_transmission_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
#ifdef __PRINCIPLED__
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
label = bsdf_principled_diffuse_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
@@ -147,7 +146,6 @@ ccl_device_forceinline int bsdf_sample(KernelGlobals *kg,
label = bsdf_principled_sheen_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
#endif /* __PRINCIPLED__ */
#endif
#ifdef __VOLUME__
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
@@ -245,7 +243,6 @@ float3 bsdf_eval(KernelGlobals *kg,
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
eval = bsdf_hair_transmission_eval_reflect(sc, sd->I, omega_in, pdf);
break;
#ifdef __PRINCIPLED__
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
eval = bsdf_principled_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
@@ -253,7 +250,6 @@ float3 bsdf_eval(KernelGlobals *kg,
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
eval = bsdf_principled_sheen_eval_reflect(sc, sd->I, omega_in, pdf);
break;
#endif /* __PRINCIPLED__ */
#endif
#ifdef __VOLUME__
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
@@ -327,7 +323,6 @@ float3 bsdf_eval(KernelGlobals *kg,
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
eval = bsdf_hair_transmission_eval_transmit(sc, sd->I, omega_in, pdf);
break;
#ifdef __PRINCIPLED__
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
eval = bsdf_principled_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
@@ -335,7 +330,6 @@ float3 bsdf_eval(KernelGlobals *kg,
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
eval = bsdf_principled_sheen_eval_transmit(sc, sd->I, omega_in, pdf);
break;
#endif /* __PRINCIPLED__ */
#endif
#ifdef __VOLUME__
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
@@ -435,23 +429,5 @@ ccl_device bool bsdf_merge(ShaderClosure *a, ShaderClosure *b)
#endif
}
/* Classifies a closure as diffuse-like or specular-like.
* This is needed for the denoising feature pass generation,
* which are written on the first bounce where more than 25%
* of the sampling weight belongs to diffuse-line closures. */
ccl_device_inline bool bsdf_is_specular_like(ShaderClosure *sc)
{
if(CLOSURE_IS_BSDF_TRANSPARENT(sc->type)) {
return true;
}
if(CLOSURE_IS_BSDF_MICROFACET(sc->type)) {
MicrofacetBsdf *bsdf = (MicrofacetBsdf*) sc;
return (bsdf->alpha_x*bsdf->alpha_y <= 0.075f*0.075f);
}
return false;
}
CCL_NAMESPACE_END

View File

@@ -40,6 +40,7 @@ typedef ccl_addr_space struct VelvetBsdf {
float sigma;
float invsigma2;
float3 N;
} VelvetBsdf;
ccl_device int bsdf_ashikhmin_velvet_setup(VelvetBsdf *bsdf)

View File

@@ -37,6 +37,7 @@ CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct DiffuseBsdf {
SHADER_CLOSURE_BASE;
float3 N;
} DiffuseBsdf;
/* DIFFUSE */

View File

@@ -40,6 +40,7 @@ CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct DiffuseRampBsdf {
SHADER_CLOSURE_BASE;
float3 N;
float3 *colors;
} DiffuseRampBsdf;

Some files were not shown because too many files have changed in this diff Show More