Compare commits

...

218 Commits

Author SHA1 Message Date
Leonard Hecker
e249b10977 Add support for Tracy 2023-07-11 21:44:29 +02:00
Mike Griese
8f83322322 Add support for setting the window frame color (#15441)
Add support for `$theme.window.frame`, `.unfocusedFrame`, and `.rainbowFrame`. The first two accept a `ThemeColor` to set the window frame, using [`DwmSetWindowAttribute`](https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/nf-dwmapi-dwmsetwindowattribute) with [`DWMWA_BORDER_COLOR`](https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute). `rainbowFrame` accepts a `bool`. When enabled, it'll cycle the color of the frame through all the hues, ala [this gif](https://user-images.githubusercontent.com/18356694/164307822-e4267965-2ce0-4294-8499-59c3ba7edbae.gif) (but, constantly, instead of just when the window moves). 

This only works on Windows 11.

## Validation Steps Performed
* Works on Windows 11
* Doesn't explode on Windows 10

## PR Checklist
- [x] Closes #12950
- See also #3327
- [x] Schema updated (if necessary)


### other details

There's probably some impact to perf with `rainbowFrame`. It's one `DispatcherTimer` per window. That could probably be optimized somehow to like, one per process, but meh?
2023-06-06 16:17:03 -07:00
ebarnabas
c627991522 Project build with space in filepath fix (#15447)
## Summary of the Pull Request
Fixing a problem where the repo build failed when the project location
path contained space character.

## References and Relevant Issues
Closes #15370 

## Detailed Description of the Pull Request / Additional comments
Placing missing quote, amp and apos symbols when calling commands with
filepath parameters.

## Validation Steps Performed
Built locally.

## PR Checklist
- [x] Closes #xxx
- [x] Tests added/passed
- [x] Documentation updated
- If checked, please file a pull request on [our docs
repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
- [x] Schema updated (if necessary)
2023-06-06 23:15:37 +00:00
Leonard Hecker
f0705fb7f7 AtlasEngine: Fix some Windows 10 <14393 bugs (#15485)
This fixes a couple spots where I wasn't properly checking
for the existence of some optional D2D interfaces.

## Validation Steps Performed
I haven't tested this and don't intend to do it just yet.
Windows Terminal requires build 19041 at least anyways.
2023-06-05 16:36:09 -07:00
Carlos Zamora
0425ab0c1d Expose 'Default' tag to Screen Readers in Color Schemes page (#15486)
## Summary of the Pull Request
This removes the "default" text box from the UI Automation tree, thus
preventing screen readers from navigating to it. This was a confusing
scenario for users because the "default" tag was unclear if it was a
part of the previous or next color scheme (i.e. consider hearing
"Campbell, default, Campbell PowerShell"; it's unclear which one is
default).

This also appends the "default" string to the `ToString` function of the
color scheme view model. This makes it so that the combo box and list
view visually appear the same, but can be quick searched or read out by
the screen reader with the 'default' tag.

## Validation Steps Performed
- [x] Verified this works on Windows 11
- [x] Verified this works on Windows 10
- Scenarios tested:
   - [x] saving settings after changing the default scheme
   - [x] saving settings.json to force a refresh in SUI

Closes #14401
2023-06-05 19:50:23 +00:00
James Holderness
e9de646e54 Remove the telemetry for VT sequences (#15494)
This removes the telemetry tracking which counted how many times each VT
sequence was executed, and how many times there were "failures". This
information isn't needed any more, and we were reaching the limit of how
many sequences we could track anyway.

Essentially what's been removed is the `TermTelemetry` class, but we are
still tracking some statemachine telemetry in the `ParserTracing` class.
And since that used the same trace logging provider as `TermTelemetry`,
I've now moved that definition into the `tracing.cpp` file. 

The code still compiles and runs without exploding.

Closes #15482
2023-06-05 16:41:32 +00:00
James Holderness
8aefc7a697 Make sure RIS re-enables win32 input and focus events (#15476)
When an `RIS` (hard reset) sequence is executed, ConHost will pass that
through to the connected conpty terminal, which results in all modes
being reset to their initial state. To work best, though, conpty needs
to have the win32 input mode enabled, as well as the focus event mode.
This PR addresses that by explicitly requesting the required modes after
an `RIS` is passed through.

Originally these modes were only set if the `--win32input` option was
given, but there is really no need for that, since terminals that don't
support them should simply ignore the request. To avoid that additional
complication, I've now removed the option (i.e. ConHost will now always
attempt to set the modes it needs).

I've manually confirmed that keypresses are still passed through with
win32 input sequences after a hard reset, and that focus events are
still being generated. I've also updated the existing conpty round-trip
test for `RIS` to confirm that it's now also passing through the mode
requests that it needs.

Closes #15461
2023-06-02 13:41:49 -05:00
Leonard Hecker
1bec08ec0a Modernize til::static_map with C++20 (#15484)
I wanted to show `til::static_map` to someone and noticed it hasn't been
updated since we updated to C++20. We can now make use of `constexpr`
`std::sort` and `constinit` to skip the initialization of the maps in
`KeyChordSerialization.cpp`. Also, I removed the comparator argument
to make the map a little more compact.
2023-05-31 12:59:03 -05:00
Mike Griese
c9e993a38e Exit the process after commandline-only invocations (#15445)
Yep it's that dumb

Closes #15443
2023-05-26 19:59:38 +00:00
Leonard Hecker
cd6b0832e2 Hotfix block selection linebreaks in conhost (#15423)
This regressed in a1f42e8 which only made changes to Windows Terminal
but forgot to make equivalent ones in OpenConsole/conhost.
Without this fix, line breaks in block selections are missing if the
line doesn't force a wrap via an explicit newline.

Closes #15153

## Validation Steps Performed
* Run Far or print long lines of text
* Trigger block selection via Ctrl+M or Edit > Mark
* Clipboard contains N-1 newlines lines for N selected rows 
2023-05-26 14:32:15 -05:00
Mike Griese
8611d901b6 Theoretical fix for some crashes (#15457)
RE: 
* #15454
* MSFT:44725712 "WindowsTerminal.exe!NonClientIslandWindow::OnSize"
* MSFT:44754014 "NonClientIslandWindow::GetTotalNonClientExclusiveSize"

I think this should fix all of those, but I want to ship and verify
live, since I can't repro this locally.
2023-05-26 14:31:21 -05:00
Leonard Hecker
a19d30a25a AtlasEngine: Improve scroll and swap chain invalidation (#15425)
`_p.MarkAllAsDirty()` sets `_p.scrollOffset` to 0, so we need to use
that instead of `_api.scrollOffset` when getting the offset.
Additionally, the previous code failed to release the swap chain
when recreating the backend, which is technically not correct.
I'm not sure to what issues this might have led, as it didn't had any
negative effects on my PC, but it's definitely not according to spec.

## Validation Steps Performed
Difficult to test but it seems alright.
2023-05-26 14:30:57 -05:00
Steve Otteson
709189d471 env: always expand PATH vars (#15444)
Make sure we always expand path env vars, even if they're REG_SZ in the
registry.

## Detailed Description of the Pull Request / Additional comments
On some systems path vars are REG_SZ instead of REG_EXPAND_SZ. We need
to make sure we always expand them. We looked at the system code, and it
also makes to sure to always expand them.

## Validation Steps Performed
Built locally and made sure the problem went away. Also stepped through
in the debugger to make sure things were working correctly.

Closes #15442
2023-05-26 18:45:10 +00:00
Mike Griese
aa8ed8c2d4 AGAIN, intentionally leak our App, so that we DON'T crash on exit (#15451)
This is a resurrection of #5629. As it so happens, this crash-on-exit
was _not_ specific to my laptop. It's a bug in the XAML platform
somewhere, only on Windows 10.

In #14843, we moved this leak into `becomeMonarch`. Turns out, we don't
just need this leak for the monarch process, but for all of them.

It's not a real "leak", because ultimately, our `App` lives for the
entire lifetime of our process, and then gets cleaned up when we do. But
`dtor`ing the `App` - that's apparently a no-no.

Was originally in #15424, but I'm pulling it out for a super-hotfix
release.


Closes #15410

MSFT:35761869 looks like it was closed as no repro many moons ago. This
should close out our hits there (firmly **40% of the crashes we've
gotten on 1.18**)
2023-05-26 13:09:00 -05:00
James Holderness
3c3b1aac02 Add support for horizontal scrolling sequences (#15368)
This PR introduces four new escapes sequences: `DECIC` (Insert Column),
`DECDC` (Delete Column), `DECBI` (Back Index), and `DECFI` (Forward
Index), which allow for horizontal scrolling within a margin area.

## References and Relevant Issues

This follows on from the horizontal margins PR #15084 to complete the
requirements for the horizontal scrolling extension.

## Detailed Description of the Pull Request / Additional comments

The implementation is fairly straightforward, since they're all built on
top of the existing `_ScrollRectHorizontally` method.

## Validation Steps Performed

Thanks to @al20878, these operations have been extensively tested on a
number of DEC terminals and I've manually confirmed our implementation
matches their behavior.

I've also added a unit tests that covers the basic execution of each of
the operations.

Closes #15109
2023-05-25 20:36:56 +00:00
Mike Griese
6775300f42 Fix focusFollowMouse (#15420)
Because this looks like it's entirely broken in `main`, and possibly in
1.17(?)

We didn't take a strong ref to the coroutine parameter. As to be
expected, that explodes.

Closes #15412
2023-05-25 22:25:10 +02:00
Jaswir
f5a703c711 Add support for a "Move Tab to New Window" tab context menu item (#15376)
## Summary of the Pull Request
Add the "Move Tab to New Window" item to the context menu of the tabs 

## References and Relevant Issues
https://github.com/microsoft/terminal/issues/15127

## Detailed Description of the Pull Request / Additional comments
Add the "Move Tab to New Window" item to the context menu of the tabs. 

![Detailed_description_of_commit_PR1](https://github.com/microsoft/terminal/assets/15957528/915ac07b-1fdd-456b-b180-2645dbc29e48)

## Validation Steps Performed
Checked Code Style
https://github.com/microsoft/terminal/blob/main/doc/STYLE.md

## PR Checklist
- [ V] Closes #15127
-  [?] Tests added/passed
- [ X] Documentation updated
- If checked, please file a pull request on [our docs
repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
- [ V] Schema updated (if necessary)

---------

Co-authored-by: Mike Griese <migrie@microsoft.com>
2023-05-25 18:22:58 +00:00
Leonard Hecker
7650ecf658 AtlasEngine: Fix cursor invalidation for BackendD2D (#15427)
TIL: `CreateCompatibleRenderTarget` does not initialize the bitmap
it returns. You got to do that yourself just like in D3D.

## Validation Steps Performed
* Set `ATLAS_DEBUG_FORCE_D2D_MODE` to 1
* Changing the cursor in the settings immediately updates it 
2023-05-25 18:22:07 +00:00
Leonard Hecker
0073e36d81 Fix VS profile command generation (#15439)
This regressed in f06cd17. It seems like the change went untested,
because it appends an extra " after -startdir=none.
This changeset also avoids calling `append()` twice.

Closes #15436

## Validation Steps Performed
* VS Developer Command Prompt works 
2023-05-25 18:21:57 +00:00
Leonard Hecker
245b13b94e AtlasEngine: Fix nullptr crash when using soft fonts (#15419)
Woops. Regressed in #15343. Fixes #15409.

## Validation Steps Performed
* Run `RenderingTests.exe`
* Soft fonts work 
2023-05-25 18:21:55 +00:00
Leonard Hecker
a9f34e3095 AtlasEngine: Fix Present() of out of bounds glyphs (#15403)
`til::rect`'s truthiness check (= rect is valid) returns `false` for
any rects that have negative coordinates. This makes sense for buffer
handling, but breaks AtlasEngine, where glyph coordinates can go out
of bounds and it's entirely valid for that to happen.

Closes #15416

## Validation Steps Performed
* Use MesloLGM NF and print NF glyphs in the first row
* Text rendering, selection, etc., still works 

---------

Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
2023-05-25 17:39:44 +00:00
Mike Griese
c589784b54 Leak the window when it closes on Windows 10 (#15397)
Re: #15384

Basically, when we close a `DesktopWindowXamlSource`, it calls to `Windows_UI_Xaml!DirectUI::MetadataAPI::Reset`, which resets the XAML metadata provider _for the process_. So, closing one DWXS on one thread will force an A/V next time another thread tries to do something like... display a tooltip. Not immediately, but surely soon enough.

This was fixed in Windows 11 by os.2020!5837001. That wasn't backported to Windows 10.

This will cause a ~15MB memory leak PER WINDOW. OBVIOUSLY, this is bad, but it's less bad than crashing. 

We're gonna keep using #15384 for other ideas here too.
2023-05-22 11:00:44 -05:00
Mike Griese
910c61b7e1 Manually close the ContentDialog in teardown (#15387)
As discussed. Closes #15364.

Prevents one crash on Windows 10. Opens the door to may more horrors.

Co-authored-by: James Holderness <j4_james@hotmail.com>
2023-05-22 06:07:59 -05:00
Dustin L. Howett
0ee2c74cd4 Switch the Preview text emoji to one that exists on Win10 (#15381) 2023-05-18 16:27:33 +00:00
Dustin L. Howett
125026dbb6 Remove the pending update version from the About dialog (#15378)
It turns out that the store API *doesn't* tell us what the new version
is. We were loading up our own package and checking its version instead.

The best we can do is tell users that an update--any update--is
available.
2023-05-18 10:22:29 -05:00
Dustin L. Howett
ce60bf290a Make the preview text 100% more accurate (#15366) 2023-05-16 17:59:36 -05:00
Dustin L. Howett
e269945a74 Reword the AdjustIndistinguishableColors subhead and perf. note (#15361)
I've changed the wording so that it flows better.
2023-05-16 15:01:31 -05:00
Dustin L. Howett
fbe45fafb5 Add a fun new preview text in the SUI, enable the cursor (#15363)
Our existing preview text was not very helpful in learning how different
settings impacted the display of text in Terminal.

This new preview text contains:
* Bold text, which is controlled by intenseTextStyle
* Colors
* Emoji
* A cursor, which overlaps a single character to show inversion behavior
2023-05-16 14:59:49 -05:00
Dustin L. Howett
62766db94d Reword or remove a bunch of subheadings in the SUI (#15362)
Some of these were reundant, and some didn't feel right when I read
them.

Oh, and I got rid of all of these particularly unhelpful or non-additive
resources:

```
Color Scheme        [                     v ]
Is a color scheme
```
2023-05-16 14:59:28 -05:00
James Holderness
b00b77a7ac Add support for horizontal margin sequences (#15084)
This PR introduces two new escapes sequences: `DECLRMM` (Left Right
Margin Mode), which enables the horizontal margin support, and `DECSLRM`
(Set Left and Right Margins), which does exactly what the name suggests.

A whole lot of existing operations have then been updated to take those
horizontal margins into account.

## Detailed Description of the Pull Request / Additional comments

The main complication was in figuring out in what way each operation is
affected, since there's a fair amount of variation.

* When writing text to the buffer, we need to wrap within the horizontal
margins, but only when the cursor is also within the vertical margins,
otherwise we just wrap within the boundaries of the screen.

* Not all cursor movement operations are constrained by the margins, but
for those that are, we clamp within both the vertical and horizontal
margins. But if the cursor is already outside the margins, it is just
clamped at the edges of the screen.

* The `ICH` and `DCH` operations are constrained by the horizontal
margins, but only when inside the vertical margins. And if the cursor is
outside the horizontal margins, these operations have no effect at all.

* The rectangular area operations are clamped within the horizontal
margins when in the origin mode, the same way they're clamped within the
vertical margins.

* The scrolling operations only scroll the area inside both horizontal
and vertical margins. This includes the `IL` and `DL` operations, but
they also won't have any effect at all unless the cursor is already
inside the margin area.

* `CR` returns to the left margin rather than the start of the line,
unless the cursor is already left of that margin, or outside the
vertical margins.

* `LF`, `VT`, `FF`, and `IND` only trigger a scroll at the bottom margin
if the cursor is already inside both vertical and horizontal margins.
The same rules apply to `RI` when triggering a scroll at the top margin.

Another thing worth noting is the change to the `ANSISYSSC` operation.
Since that shares the same escape sequence as `DECSLRM`, they can't both
be active at the same time. However, the latter is only meant to be
active when `DECLRMM` is set, so by default `ANSISYSC` will still work,
but it'll no longer apply once the `DECLRMM` mode is enabled.

## Validation Steps Performed

Thanks to @al20878, these operations have been extensively tested on a
number of DEC terminals and I've manually confirmed our implementation
matches their behavior.

I've also extended some of our existing unit tests to cover at least the
basic margin handling, although not all of the edge cases.

Closes #14876
2023-05-15 22:32:30 +00:00
Leonard Hecker
4628ceb295 AtlasEngine: Clip box glyphs to their cells (#15343)
Overhangs for box glyphs can produce unsightly effects, where the
antialiased edges of horizontal and vertical lines overlap between
neighboring glyphs and produce "boldened" intersections.
This avoids the issue in most cases by simply clipping the glyph to the
size of a single cell. The downside is that it fails to work well for
custom line heights, etc.

## Validation Steps Performed

* With Cascadia Code, printing ``"`u{2593}`n`u{2593}"`` in pwsh
  doesn't produce a brightened overlap anymore 
* ``"`e#3`u{2502}`n`e#4`u{2502}"`` produces a fat vertical line 
2023-05-16 00:05:16 +02:00
Mike Griese
9a4f4abaf2 Manually pre-evaluate the starting directory when calling elevate-shim (#15286)
_targets #15280_

When ctrl+clicking on a profile, pre-evaluate the starting directory of
that profile, and stash that in the commandline we pass to elevate shim.

So in the case of something like "use parent process directory", we'll
run `elevate-shim new-tab -p {guid} -d "C:\\the path\\of\\terminal\\."`


Closes #15173

---------

Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
2023-05-15 20:10:43 +00:00
Leonard Hecker
f6e9f91504 Fix AtlasEngine not being used in the appearance settings (#15355)
`TermControl` cannot change the text rendering engine after its
construction. Fix the issue by deferring the construction until
after we got the initial profile settings.

## Validation Steps Performed
* A line height of 0.5 shows up with overlapping rows 
2023-05-15 21:14:21 +02:00
Leonard Hecker
457bc65d7e AtlasEngine: Fix animated shaders (#15353)
We need to avoid calling `Present1()` with an empty dirty rect, but the
backends are what determines the resulting dirty rect, so we need to
first run the backend code and then decide if we `Present1()` or not.

## Validation Steps Performed
* `Animate_scan.hlsl` shows a smoothly animated line 
2023-05-15 13:46:39 -05:00
Leonard Hecker
4c3d3d83a5 AtlasEngine: Fix han unification issues (#15358)
This commit ensures that we pass the user's locale to `MapCharacters`.

## Validation Steps Performed
See: https://heistak.github.io/your-code-displays-japanese-wrong/
After modifying the `userLocaleName` to contain `ja-JP`, `zh-CN` and
`zh-TW`, printing "刃直海角骨入" produces the expected, localized result.
2023-05-15 20:40:41 +02:00
Leonard Hecker
af5a6ea640 AtlasEngine: Fix multiple minor issues (#15357)
This commit fixes 3 bugs that I found while working on another feature:
* `GetGlyphIndices` doesn't return an error when the codepoint couldn't
  be found, it simply returns a glyph index of 0.
* `_resetGlyphAtlas` failed to reset the `linear_flat_set` "load" to 0
  which would result in an unbounded memory growth over time.
* `linear_flat_set` was missing move constructors/operators, which
  would've led to crashes, etc., but thankfully we haven't made use
  of these operators yet. But better fix it now than never.
2023-05-15 20:40:13 +02:00
Leonard Hecker
ba39db52d7 Fix DesktopWindowXamlSource related crashes when closing a window (#15338)
XAML/WinUI may pump the event loop internally. One of the functions
that does this right now is `DesktopWindowXamlSource::Close()`.

This is problematic in the previous code, because we'd set `_window`
to `nullptr` before calling `Close()` and so any of the `IslandWindow`
callbacks may be invoked during shutdown, which then try to potentially
access `_window` and end up crashing. This commit fixes the issue by
simply not nulling out the `_window` and calling `Close()` directly.

Furthermore, `NonClientIslandWindow` may directly access WinUI
objects in its message handlers which also crashes.

I've had this happen roughly ~1% of my test exits in a debug build
and every single time on a (artificial) very slow CPU.

## Validation Steps Performed
* Closing a window destroys the rendering instance 
2023-05-15 14:11:22 +00:00
James Holderness
3d737214a4 Add support for LNM (Line Feed/New Line Mode) (#15261)
This PR adds support for the ANSI Line Feed/New Line mode (`LNM`), which
determines whether outputting a linefeed control should also trigger a
carriage return, and whether the `Return` key should generate an `LF` in
addition to `CR`.

## Detailed Description of the Pull Request / Additional comments

In ConHost, there was already a console mode which handled the output
side of things, but I've now also added a `TerminalInput` mode that
controls the behavior of the `Return` key. When `LNM` is set, both the
output and input modes are enabled, and when reset, they're disabled.

If they're not already matching, then `LNM` has no effect, and will be
reported as unknown when queried. This is the typical state for legacy
console applications, which expect a linefeed to trigger a carriage
return, but wouldn't want the `Return` key generating both `CR`+`LF`.

As part of this PR, I've also refactored the `ITerminalApi` interface to
consolidate what I'm now calling the "system" modes: bracketed paste,
auto wrap, and the new line feed mode. This closes another gap between
Terminal and ConHost, so both auto wrap, and line feed mode will now be
supported for conpty pass through.

## Validation Steps Performed

I've added an `LNM` test that checks the escape sequence is triggering
both of the expected mode changes, and added an additional `DECRQM` test
covering the currently implemented standard modes: the new `LNM`, and
the existing `IRM` (which wasn't previously tested). I've also extended
the `DECRQM` private mode test to cover `DECAWM` and Bracketed Paste
(which we also weren't previously testing).

I've manually tested `LNM` in Vttest to confirm the keyboard is working
as expected.

Closes #15167
2023-05-12 18:16:48 -05:00
Mike Griese
1324a0148a Don't even try to MoveContent to the same window you started in (#15325)
Don't go.
Tracked in #14957
2023-05-12 17:24:31 -05:00
Mike Griese
1bf2fcb6e0 Don't dismiss the command palette when the new tab menu closes (#15340)
Transient UIs are hard.

Regressed in #15077.

Closes #15305
2023-05-12 17:22:21 -05:00
Leonard Hecker
95944e5939 Make path-string conversions cheaper (#15332)
`native()` returns a `const std::wstring&`, whereas `wstring()`
returns a copy. Use the former to make path conversions cheaper.
2023-05-12 20:51:00 +00:00
Leonard Hecker
488de2d42c Fix WindowEmperor exiting too early (#15337)
`WindowEmperor` would exit as soon as the last window would enter
`RundownForExit()`, which is too early and triggers leak checks.
This commit splits up the shutdown up into deregistering the window from
the list of windows and into actually decrementing the window count.

Closes #15306

## Validation Steps Performed
* D2D leak warnings seem to disappear 
2023-05-12 20:15:50 +00:00
Leonard Hecker
bf8ef638b7 Avoid recreating the bell MediaPlayer every time (#15333)
We don't need to recreate the `MediaPlayer` to avoid the influence of
media keys if we simply opt out of media key controls.

## Validation Steps Performed
* Set a random .wav as the bell sound
* Bell is audible 
* Media keys have no effect while the sound plays 
2023-05-12 20:15:36 +00:00
Leonard Hecker
6a26fd68c4 Fix race conditions in ControlCore (#15334)
`ControlCore` contained two bugs:
* Race condition on access of the 3 throttled funcs which may now
  be `reset()` during tear out
* The `ScrollPositionChanged` event emitter was written incorrectly
  and would emit the event from the background thread without
  throttling during tear out
2023-05-12 20:11:22 +00:00
Dustin L. Howett
d6eb022975 Stage the fonts with the Helix payload (#15317)
I found that in all our Helix runs, we had a pesky dialog sitting on top
of the Terminal. Probably the entire time.

This will, as a side effect, PGO the nearby font loader.
2023-05-12 14:26:47 -05:00
Mike Griese
d0f66b9668 Restore the tab padding (#15339)
Honestly, I don't really know where it regressed. There isn't time for
me to go digging.

See also
* #15313
* #15164

Closes #15326
2023-05-12 13:26:05 -05:00
Mike Griese
5c08a86c49 Use a "virtual CWD" for each terminal window (#15280)
Before process model v3, each Terminal window was running in its own process, each with its own CWD. This allowed `startingDirectory: .` to work relative to the terminal's own CWD. However, now all windows share the same process, so there can only be one CWD. That's not great - folks who right-click "open in terminal", then "Use parent process directory" are only ever going to be able to use the CWD of the _first_ terminal opened. 

This PR remedies this issue, with a theory we had for another issue. Essentially, we'll give each Terminal window a "virtual" CWD. The Terminal isn't actually in that CWD, the terminal is in `system32`. This also will prevent the Terminal from locking the directory it was originally opened in. 

* Closes #5506
* There wasn't a 1.18 issue for "Use parent process directory is broken" yet, presumably selfhosters aren't using that feature
* Related to #14957

Many more notes on this topic in https://github.com/microsoft/terminal/issues/4637#issuecomment-1531979200


> **Warning** 
> ## Breaking change‼️

This will break a profile like 

```json
{
    "commandline": "media-test.exe",
    "name": "Use CWD for media-test",
    "startingDirectory": "."
},
```

if the user right-clicks "open in terminal", then attempts to open that profile. There's some theoretical work we could do in a follow up to fix this, but I'm inclined to say that relative paths for `commandline`s were already dangerous and should have been avoided.
2023-05-12 18:20:27 +00:00
Leonard Hecker
99abb2a6b5 Fix theoretical new-tab file drop crash (#15336)
After retrieving the items via `GetStorageItemsAsync()` inside a try
clause it fails to check if the pointer is actually non-null.
Apart from this this commit fixes the unsafe use of `this` by properly
using `get_weak()`. Finally it allows >1 paths to be dropped.

## Validation Steps Performed
* Dropping >1 file works 
* Dropping >1 directory works 
2023-05-12 13:14:07 -05:00
Dustin Howett
c6215c8b51 version: bump to 1.19 on main
Signed-off-by: Dustin Howett <duhowett@microsoft.com>
2023-05-11 16:33:49 -05:00
Mike Griese
63644507da Prevent flickering in nushell due to FTCS marks (#14677)
Tl;dr: Conpty would flush a frame whenever it encountered a FTCS mark.
Combine that with the whole-line redrawing that nushell does, and the
Terminal would get the prompt in two frames instead of one, causing a
slight flickering. This fixes that by rendering the frame, but not
flushing to the pipe when we encounter one of these sequences.

Closes #13710 

A complication here: there are some sequences that we passthrough
_immediately_ when we encounter them. For example, `\x1b[ 2q`. we need
to also not flush when we encounter one of these sequences. nushell
emits one of these as a part of the prompt, and that would force the
buffered frame to get written _anyways_, before writing that to the
pipe.
2023-05-11 16:11:30 -05:00
michalnpl
b2dd7fa600 Add support for CSI 18t (#15295)
Adds support for CSI 18t to report the buffer screen size in characters.

This pull request adds support for **CSI 18t**. When submitted to the
terminal, it will respond with **"\033[8;{A};{B}t"** where **A** is
equal to the **height** and **B** is equal to the **width** of the
screen buffer in the number of characters (not pixels).

## Validation Steps Performed
Manual tests against PowerShell 7 and ConHost.
Added adapterTest

Closes #13944
2023-05-11 12:06:39 -05:00
Mike Griese
c553b2123d Don't let a window be created with the literal name "new" (#15323)
As on the tin.

Blocking for 1.18.

Tracked in #14957
2023-05-11 12:03:47 +00:00
Mike Griese
076c36c6cb Add an action for manually invoking the control context menu (#15254)
Adds 

```
        { "command": "showContextMenu", "keys": "menu" },
```

as a default action. This will manually invoke the control context menu
(from #14775), even with the setting disabled.

As discussed with Dustin.
2023-05-10 22:32:27 -05:00
Mike Griese
0553f3ebf1 Fix an infinite loop when pressing alt (#15253)
As discussed in
https://github.com/microsoft/terminal/issues/14051#issuecomment-1517973776

regressed in #15189
2023-05-10 22:20:24 -05:00
Mike Griese
48eee4d75a Update MUX to 2.8.4 (#15313)
Reverts #15164, because that's fixed upstream now.

Closes #15139. 

Reverts #15178, but also closes #15121, because that's fixed upstream.

see also:
* https://github.com/microsoft/microsoft-ui-xaml/pull/8430
* https://github.com/microsoft/microsoft-ui-xaml/pull/8420
2023-05-10 13:04:41 -05:00
Mike Griese
6ad8cd0a63 Make conhost act in VtIo mode earlier in startup (#15298)
We need to act like a ConPTY just a little earlier in startup. My relevant notes start here: https://github.com/microsoft/terminal/issues/15245#issuecomment-1536150388. 

Basically, we'd create the first screen buffer with 9001 rows, because it would be created _before_ VtIo would be in a state to say "yes, we're a conpty". Then, if a CLI app emits an entire screenful of text _before_ the terminal has a chance to resize the conpty, then the conpty will explode during `_DoLineFeed`. That method is absolutely not expecting the buffer to get resized (and the old text buffer deallocated). 

Instead, this will treat the console as in ConPty mode as soon as `VtIo::Initialize` is called (this is during `ConsoleCreateIoThread`, which is right at the end of `ConsoleEstablishHandoff`, which is before the API server starts to process the client connect message).  THEORETICALLY, `VtIo` could `Initialize` then fail to create objects in `CreateIoHandlers` (which is what we used to treat as the moment that we were in conpty mode). However, if we do fail out of `CreateIoHandlers`, then the console itself will fail to start up, and just die. So I don't think that's needed.

This fixes #15245. I think this is PROBABLY also the solution to #14512, but I'm not gonna explicitly mark closed. We'll loop back on it.
2023-05-10 07:16:44 -05:00
Leonard Hecker
4dd9493135 Use Oklab for text and cursor contrast adjustments (#15283)
Oklab by Björn Ottosson is a color space that has less irregularities
than the CIELAB color space used for ΔE2000. The distance metric for
Oklab (ΔEOK) is defined by CSS4 as the simple euclidian distance.
This allows us to drastically simplify the code needed to determine
a color that has enough contrast. The new implementation still lacks
proper gamut mapping, but that's another and less important issue.
I also made it so that text with the dim attribute gets adjusted just
like regular text, since this is an accessibility feature after all.

The new code is so much faster than the old code (12-125x) that I
dropped any caching code we had. While this increases the CPU overhead
when printing lots of indexed colors, the code is way less complex now.
"Increases" in this case however means something in the order of 15-60ns
per color change (as measured on my CPU). It's possible to further
improve the performance using explicit SIMD instructions, but I've
left that as a future improvement, since that will make the code quite
a bit more verbose and I didn't want to hinder the initial review.

Finally, these new routines are also used for ensuring that the
AtlasEngine cursors remains visible at all times.

Closes #9610

## Validation Steps Performed
* When `adjustIndistinguishableColors` is enabled
  colors are distinguishable 
* An inverted cursor on top of a `#7f7f7f` foreground & background
  is still visible 
* A colored cursor on top of a background with identical color
  is still visible 
* Cursors on a transparent background are visible 
2023-05-08 19:16:26 +00:00
Leonard Hecker
cc89787c34 Fix Present1 params when scrolling the entire viewport (#15262)
This commit makes a few changes to avoid bugs, but they basically boil
down to: When we scroll by an entire viewport worth of content, we must
ensure that the scroll offset is 0, because otherwise the scroll rect
(that's basically the viewport, but excluding the scroll offset) will
end up being empty, which the `Present1` API chokes on. This commit
avoids this situation by shuffling around some code to first calculate
the dirty rows, _then_ check if it affects all of them and in that case
sets the scroll offset to 0, and only then finally actually does any
scrolling if there's still something to scroll.

## Validation Steps Performed
* Start pwsh
* Zoom in twice with Ctrl+Scrollwheel
* Print a few viewports worth of text
* Press Ctrl+L
* No errors 
2023-05-08 21:02:02 +02:00
Mike Griese
c18a4febe7 Remove the IsolatedMonarchMode velocity flag (#15300)
This was removed in #14843, but the velocity flag wasn't.

Related to #14957
2023-05-08 12:50:34 -05:00
Leonard Hecker
10c6206bfe AtlasEngine: Add support for locl variants (#15278)
Get the locale from `GetUserDefaultLocaleName` and pass it to
DirectWrite's `GetGlyphs` / `GetGlyphPlacements`.

This change is very important for some fonts, which heavily depend on
the locl table, like Source Han Sans for instance.

Closes #13685

## Validation Steps Performed
* Set font to Cascadia Code
* Set locale to "pl-PL"
* Type "Ć"
* The acute is less angled and almost vertical 
2023-05-04 19:08:09 +00:00
Mike Griese
ae7595b8e1 Add til::property and other winrt helpers (#15029)
## Summary of the Pull Request

This was a fever dream I had last July. What if, instead of `WINRT_PROPERTY` magic macros everywhere, we had actual templated versions you could debug into. 

So instead of 

```c++
WINRT_PROPERTY(bool, Deleted, false);
WINRT_PROPERTY(OriginTag, Origin, OriginTag::None);
WINRT_PROPERTY(guid, Updates);
```

you'd do 

```c++
til::property<bool> Deleted{ false };
til::property<OriginTag> Origin{ OriginTag::None };
til::property<guid> Updates;
```

.... and then I just kinda kept doing that. So I did that for `til::event`.

**AND THEN LAST WEEK**

Raymond Chen was like: ["this is a good idea"](https://devblogs.microsoft.com/oldnewthing/20230317-00/?p=107946)

So here it is. 

## Validation Steps Performed
Added some simple tests.

Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
2023-05-03 12:41:36 -05:00
Leonard Hecker
23d45a7e3a Avoid loading nearby fonts unless necessary (#15239)
`IDWriteFontSetBuilder` is super expensive (~40ms of CPU for building a
single font set on a high-end CPU from ~2021). Let's avoid the cost,
by only constructing it if Cascadia Code is actually missing.
To not overcomplicate the code and to support any additional fonts we
might ship in the future, I'm not checking for the font name, and
instead I just construct the font set whenever any font is missing.

Part of #5907

## Validation Steps Performed
* Breakpoints in FontCache aren't hit 
* App doesn't crash 
2023-05-03 11:30:54 +00:00
kovdu
18d4f1ace8 Add support to show close button for active tab only. (#15237)
This MR introduces `activeOnly ` for the `showCloseButton` theme option
causing the close button only to appear on the active tab.

This is more or less following the approach explained here
https://github.com/orgs/microsoft/projects/686/views/2?pane=issue&itemId=19775774
which indeed just works 😄 .

You notice when switching theme the close buttons is back on all tabs
again as well.

Closes #13672

I didn't check specific unit tests for this. I hope by making this MR
the pipeline will show if I broke something. Or just let me know if you
want me to add something specific for this.
2023-05-03 11:21:46 +00:00
Mike Griese
4feeef2155 Don't auto-dismiss the warning dialog on launch (#15273)
Apparently, `ShowWindow` also sends a `WM_MOVE`, which we then turn
around and use to dismiss open dialogs.

Closes #15170

Regressed in #13811
2023-05-02 20:22:12 +02:00
Mike Griese
e88e0be190 Move session restore into a helper in AppHost (#15263)
Just move session restoration into a helper function, as suggested by
Leonard.
2023-05-02 17:35:43 +00:00
Ben Constable
6abd72177b Make reset button accessible (#15257)
Make the reset button accessible by adding description in reset.

Closes #12044

---------

Co-authored-by: Dustin L. Howett <dustin@howett.net>
2023-05-02 17:33:50 +00:00
James Holderness
8c28e132b5 Preserve active attributes during VT resize operations (#15269)
## Summary of the Pull Request

When the screen is resized in ConHost via a VT escape sequence, the
active text attributes could end up being corrupted if they were set to
something that the legacy console APIs didn't support (e.g. RGB colors).
This PR fixes that issue.

## Detailed Description of the Pull Request / Additional comments

The way a resize is implemented is by retrieving the buffer information
with `GetConsoleScreenBufferInfoEx`, updating the size fields, and then
writing the data back out again with `SetConsoleScreenBufferInfoEx`.
However, this also results in the active attributes being updated via
the `wAttributes` field, and that's only capable of representing legacy
console attributes.

We address this by saving the full `TextAttribute` value before it gets
corrupted in the `SetConsoleScreenBufferInfoEx` call, and then restore
it again afterwards.

## Validation Steps Performed

I've added a unit test to verify the attributes are correctly preserved
for all VT resize operations, and I've also manually confirmed the test
case in #2540 is now working as expected.

## PR Checklist
- [x] Closes #2540
- [x] Tests added/passed
- [ ] Documentation updated
- [ ] Schema updated (if necessary)
2023-05-02 15:04:01 +02:00
Mike Griese
1da6131cb2 Add default bindings for "move tab/pane to a new window" (#15258)
This was in pursuit of #15156. I need an ack from OP to make sure this
is good enough.

Related to #14957
2023-05-01 15:20:23 +00:00
Mike Griese
20eabb35ba Another theoretical fix for another race condition (#15251)
Basically, just make sure that we register our `SettingsChanged` handler
in `TerminalWindow` _after_ `TerminalWindow` is actually ready to handle
it. _duh_.

Closes #15209
2023-05-01 14:43:38 +00:00
Mike Griese
97a617a909 Don't explode when we tear out the last tab of the window (#15259)
If you were really fast, and closed one window, and then tried to drag
the only tab out of the last remaining window, the Terminal could
explode. It'd attempt to restore the previous window state, and explode.

Easy way to stop this (also, be more robust): just don't attempt to
restore windows during tear-out. That's obvious.

This is a part of #14957
2023-04-28 18:10:19 -05:00
Mike Griese
c4944c3a23 Move the Close... actions to a nested menu on the tab (#15250)
A resurrection of the original nested "Close" menu from #7728. We
discovered that nested flyouts crash in #8238. Those are fixed now
though! So we can bring this back.

This also includes the "Close Pane" item from #15198.
2023-04-28 18:05:28 -05:00
Mike Griese
70e44c7915 Add an action for immediately restarting a connection (#15241)
Adds an action for immediately restarting the connection. I suspect
most folks that wanted #3726 will be happy just with the
<kbd>enter</kbd> solution from #14060, but this will work without having
to `exit` the client. Just, relaunch whatever the commandline is. Easy
peasy.

Closes #3726.

Obsoletes #14549
2023-04-28 22:50:12 +00:00
Mike Griese
0d6642ac6d (A better) Refactoring of how connection restarting is handled (#15240)
A different take on #14548.

> We didn't love that a connection could transition back in the state
diagram, from Closed -> Start. That felt wrong. To remedy this, we're
going to allow the ControlCore to...

ASK the app to restart its connection. This is a much more sensible
approach, than leaving the ConnectionInfo in the core and having the
core do the restart itself. That's mental.

Cleanup from #14060

Closes #14327

Obsoletes #14548
2023-04-28 20:01:12 +00:00
Mike Griese
bfcdc64ab1 Make the rclick menu pre-populate "Find" with the selected text (#15252)
As it says on the tin
2023-04-28 19:25:04 +00:00
Mike Griese
fc90045cc3 Don't just die if the user doesn't have the dx debugging tools (#15249)
This PR gives the atlas engine an attempt to retry a couple operations
where it asks for debug flags when we're in debug mode. If you don't
have the Graphics debugger and GPU profiler for DirectX installed, then
these calls will fail, and we end up blowing up the renderer. Instead,
just try again.

Originally, I actually thought I had hit #14082, but after sorting this
out, it was just #14316.

closes #14316
2023-04-27 12:08:31 -05:00
James Pack
4d5962e7b5 Add jump list support for indirect icon references (#15221)
Adds support to jump list generation for icon paths that include an
indirect reference e.g. `c:\windows\system32\shell32.dll,214`

If given a path that has an indirect icon reference parse the path into
component parts `filePath` and `iconIndex` and use
`IShellLinkW::SetIconLocation` to set the Icon for the entry. Otherwise
do what we always do.

This PR also introduces `til::to_int`, which is based on `til::to_ulong`
and supports signed integers.

## Validation Steps Performed
Icons were visible in the jump list and in terminal next to the
profiles.

Closes #15205
2023-04-26 22:34:15 +00:00
joadoumie
ca5834e922 Added Close Pane to Context Menu (#15198)
## Summary of the Pull Request
Adding a 'Close Pane' menu item in the context menu.

## References and Relevant Issues
#13580 

## Detailed Description of the Pull Request / Additional comments
If a user decides to split a tab to create multiple panes through the
context menu, they should be able to then close the pane via the context
menu too. This PR introduces a new context menu item, 'Close Pane', that
only appears when a user has 2 or more panes in a tab. When a user
clicks close pane, the _active_pane will be closed.

## Validation Steps Performed

![close_pane_terminal](https://user-images.githubusercontent.com/98557455/232649000-8b521070-4f1b-4da9-8092-6ff802e91e2c.gif)

As it's my first PR, I still need to understand how to go through the
testing suite.

## PR Checklist
- [x] Closes #13580 
- [ ] Tests added/passed
- [ ] Documentation updated
- If checked, please file a pull request on [our docs
repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
- [ ] Schema updated (if necessary)

---------

Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
2023-04-26 17:37:08 +00:00
James Holderness
a49b5a6045 Provide a more detailed Device Attributes report (#14906)
This is an update of our Primary Device Attributes report, which better
indicates the feature extensions that we now support.

## Detailed Description of the Pull Request / Additional comments

This first parameter of the response is 61, representing a conformance
level of 1. The subsequent parameters identify the supported feature
extensions.

1 = 132 column mode
6 = Selective erase
7 = Soft fonts
22 = Color text
23 = Greek character sets
24 = Turkish character sets
28 = Rectangular area operations
32 = Text macros
42 = ISO Latin-2 character set

Most of these features are handled entirely within `AdaptDispatch`, so
they apply to all clients. However, 132 column mode is only supported by
ConHost, so we don't report that for conpty clients.

And note that soft fonts won't necessarily work in all conpty clients,
but we don't have an easy way of determining that, so we just report
soft font support for everyone.

## Validation Steps Performed

I've manually verified that the `DA1` report is returning the expected
response in Vttest, both from ConHost and Windows Terminal.

I've also updated the `DeviceAttributesTests` in the adapter tests to
account for the new expected response.

Closes #14491
2023-04-26 11:56:22 -05:00
James Holderness
6030616d27 Add support for bracketed paste mode in ConHost (#15155)
This adds support for XTerm's "bracketed paste" mode in ConHost. When
enabled, any pasted text is bracketed with a pair of escape sequences,
which lets the receiving application know that the content was pasted
rather than typed.

## References and Relevant Issues

Bracketed paste mode was added to Windows Terminal in PR #9034.
Adding it to ConHost ticks one more item off the list in #13408. 

## Detailed Description of the Pull Request / Additional comments

This only applies when VT input mode is enabled, since that is the way
Windows Terminal currently works.

When it comes to filtering, though, the only change I've made is to
filter out the escape character, and only when bracketed mode is
enabled. That's necessary to prevent any attempts to bypass the
bracketing, but I didn't want to mess with the expected behavior for
legacy apps if bracketed mode is disabled.

## Validation Steps Performed

Manually tested in bash with `bind 'set enable-bracketed-paste on'` and
confirmed that pasted content is now buffered, instead of being executed
immediately.

Also tested in VIM, and confirmed that you can now paste preformatted
code without the autoindent breaking the formatting.

Closes #395
2023-04-26 11:37:21 -05:00
Leonard Hecker
2e3d5e658e Rewrite AtlasEngine to allow arbitrary overhangs (#14959)
This is practically a from scratch rewrite of AtlasEngine.

The initial approach used a very classic monospace text renderer, where
the viewport is subdivided into cells and each cell is assigned one
glyph texture, just like how real terminals used to work.
While we knew that it would have problems with overly large glyphs,
like those found in less often used languages, we didn't expect the
absolutely massive number of fonts that this approach would break.
For one, the assumption that monospace fonts are actually mostly
monospace has turned out to be a complete lie and we can't force users
to use better designed fonts. But more importantly, we can't just
design an entire Unicode fallback font collection from scratch where
every major glyph is monospace either. This is especially problematic
for vertical overhangs which are extremely difficult to handle in a
way that outperforms the much simpler alternative approach:
Just implementing a bog-standard, modern, quad-based text renderer.

Such an approach is both, less code and runs faster due to a less
complex CPU-side. The text shaping engine (in our case DirectWrite)
has to resolve text into glyph indices anyways, so using them directly
for text rendering allows reduces the effort of turning it back into
text ranges and hashing those. It's memory overhead is also reduced,
because we can now break up long ligatures into their individual glyphs.
Especially on AMD APUs I found this approach to run much faster.

A list of issues I think are either obsolete (and could be closed)
or resolved with this PR in combination with #14255:

Closes #6864
Closes #6974
Closes #8993
Closes #9940
Closes #10128
Closes #12537
Closes #13064
Closes #13527
Closes #13662
Closes #13700
Closes #13989
Closes #14022
Closes #14057
Closes #14094
Closes #14098
Closes #14117
Closes #14533
Closes #14877

## PR Checklist
* Enabling software rendering enables D2D mode 
* Both D2D and D3D:
  * Background appears correctly 
  * Text appears correctly
    * Cascadia Code Regular 
    * Cascadia Code Bold 
    * Cascadia Code Italic 
    * Cascadia Code block chars leave (almost) no gaps 
    * Terminus TTF at 13.5pt leaves no gaps between block chars 
    * ``"`u{e0b2}`u{e0b0}"`` in Fira Code Nerd Font forms a square 
  * Cursor appears correctly
    * Legacy small/medium/large 
    * Vertical bar 
    * Underscore 
    * Empty box 
    * Full box 
    * Double underscore 
  * Changing the cursor color works 
  * Selection appears correctly 
  * Scrolling in various manners always renders correctly 
  * Changing the text antialising mode works 
  * Semi-transparent backgrounds work 
  * Scroll-zooming the font size works 
  * Double-size characters work 
  * Resizing while text is printing works 
  * DWM `+Heatmap_ShowDirtyRegions` shows that only the cursor
    region is dirty when it's blinking 
* D2D
  * Margins are filled with background color 
    They're filled with the neighboring's cell background color for
    convenience, as D2D doesn't support `D3D11_TEXTURE_ADDRESS_BORDER`
* D3D
  * Margins are filled with background color 
  * Soft fonts work 
  * Custom shaders enable continous redraw if time constant is used 
  * Retro shader appears correctly 
  * Resizing while a custom shader is running works 
2023-04-26 12:02:51 +00:00
Leonard Hecker
405fb51201 Fix AppInitialized latency metric (#15206)
The AppInitialized latency metric logs how long the application needs
to initialize the UI. 5b434dc broke this metric, because it was now
executing the code outside of the `Initialized` callback.
It's the difference between a "latency" of ~50ms and ~350ms.

As an added bonus it moves the `_ApplyStartupTaskStateChange` task
into the `Initialized` callback as well, because why not.

## Validation Steps Performed
* Breakpoint into "AppInitialized" - latency is now correct 

Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
2023-04-25 22:28:07 +00:00
James Holderness
e413a4148e Prevent crash when VTParameters::subspan is out of range (#15235)
## Summary of the Pull Request

There are certain escape sequences that use the `VTParameters::subspan`
method to access a subsection of the provided parameter list. When the
parameter list is empty, that `subspan` call can end up using an offset
that is out of range, which causes the terminal to crash. This PR stops
that from happening by clamping the offset so it's in range.

## References and Relevant Issues

This bug effected the `DECCARA` and `DECRARA` operations introduced in
PR #14285, and the `DECPS` operation introduced in PR #13208.

## Validation Steps Performed

I've manually confirmed that the sequences mentioned above are no longer
crashing when executed with an empty parameter list, and I've added a
little unit test that checks `VTParameters::subspan` method is returning
the expected results when passed an offset that is out of range.

## PR Checklist
- [x] Closes #15234
- [x] Tests added/passed
- [ ] Documentation updated
- [ ] Schema updated (if necessary)
2023-04-25 16:52:33 -05:00
Mike Griese
4ebc383cb6 A hypothetical fix for hidden windows (#15213)
We had a report in a mail thread that someone's Terminal windows were
getting created hidden, and never showing themselves.

As a theory, I'm guessing that dwFlags didn't say that we should
actually use `wShowWindow`. So, to be more correct, let's actually obey
that.

I'm gonna send this package to them to see if it fixes them.

Related to #14957.

Likely regressed in #13838.
2023-04-25 16:42:09 -05:00
James Pack
fea6eeddfd Disable the context menu command inside a zipped folder (#15236)
Closes #15190
2023-04-25 21:36:20 +00:00
Leonard Hecker
adbe4a0d0c Fix missing call to UpdateViewport::UpdateViewport during tearout (#15175)
This bug causes AtlasEngine to render buffer contents with an incorrect
`cellCount`, which may either cause it to draw the contents only
partially, or potentially access the TextBuffer contents out of bounds.

`EnablePainting` sets the `_viewport` to the current viewport for some
unfortunate (and quite buggy/incorrect) caching purposes, which causes
`_CheckViewportAndScroll()` to think that the viewport hasn't changed
in the new window. We can ensure `_CheckViewportAndScroll()` works
by also setting `_forceUpdateViewport` to `true`.

Part of #14957

## PR Checklist
* Tear out a tab from a smaller window to a larger window
* Renderer contents adept to the larger window size 

---------

Co-authored-by: Mike Griese <migrie@microsoft.com>
Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
2023-04-25 16:32:44 -05:00
Mike Griese
7e9f09f495 A very sensible Pane refactoring (#15232)
It seemed dangerous to just have places all over Pane where we
manipulate the whole cadre of TermControl events. Seemed ripe for a
copypasta error. This moves that around, so there's only two methods for
messing with the TermControl callbacks: `_setupControlEvents` and
`_removeControlEvents`.

Closes: nothing. This was an off-the-cuff commit that seemed valuable.
2023-04-25 20:58:13 +00:00
Mike Griese
06dc975a0e Switch to function pointers (#15233)
Apparently, `std::function` is bad and we should feel bad. I friggen
hate the c++ function pointer syntax, but [I do what I'm
told](https://getyarn.io/yarn-clip/85c318d8-f4a7-4da6-ae20-23d7b737e71c)

I missed this comment in #15020. Sorry!
2023-04-25 20:25:30 +00:00
Kevin Kostrzewa
def3742a2e Fix focus issue when profile selected from nested menu entry (#15077)
Original bug report #15049
Relates to feature #1571 

MenuFlyoutSubItem, when collapsing from profile selection, move focus
back to the titlebar.
An extra Closing event handler is needed to keep focus on the command
shell.

Closes #15049
2023-04-25 15:24:06 -05:00
Dustin L. Howett
5ed3c76dcb Remove IsUwp, RunAsUwp, defaults-universal and all fallout (#15222)
The ability to build and run Terminal as a UWP application was removed
in #12119. We left some of its vestiges around, but now there is no need
for them.
2023-04-25 09:28:55 -07:00
Mike Griese
e491141bd9 Remove the window thread from the list of threads before nulling the AppHost (#15231)
See
https://github.com/microsoft/terminal/issues/14957#issuecomment-1520522722.

I think there's a race here that lets the WindowEmperor muck around with
the window after it's done, but before we remove it from our list of
threads.

This _should_ remove the thread from the list, _then_ null out the
AppHost, then flush the XAML queue, preventing the A/V.

Closes MSFT:43995981
2023-04-25 14:43:51 +00:00
Mike Griese
0d1540bbd2 Add buttons for selecting commands, output to context menu (#15020)
Adds a "Select command" and a "Select output" entry to the right-click
context menu when the user has shell integration enabled. This lets the
user quickly right-click on a command and select the entire commandline
or all of its output.

This was a "I'm waiting for reviews" sorta idea. Seemed like a
reasonable combination of features. Related to #13445, #11000.

Tested manually.

---------

Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
2023-04-25 14:43:49 +00:00
Dustin L. Howett
2cfd73d819 Enable WINRT_LEAN_AND_MEAN (#15215)
`WINRT_LEAN_AND_MEAN` removes a bunch of less often used parts of the
C++/WinRT headers:

- `std::hash` specializations for every object
- `operator <<(ostream)` overloads for any `IStringable`
- Interface producers for interfaces that are marked "exclusive"

There's only one place where we were using even one of these.

Enabling this saves us (optimistically) 30 seconds of build time on the
CI agents and shrinks our largest PCH (TerminalApp, x64, Debug) by about
150MiB.

It's not huge, but it's not nothing.
2023-04-25 00:14:17 +02:00
Mike Griese
ee05307379 Also do the VisualState dance on the tab item (#15217)
Just changing the Theme also doesn't seem to work by itself - there
seems to be a way for the tab to set the deselected foreground onto
itself as it becomes selected. If the mouse isn't over the tab, that can
result in mismatched fg/bg's

Regressed around #15078 

Closes #15184
2023-04-24 16:41:10 -05:00
Mike Griese
478834756e Make sure the command palette isn't null (#15220)
Fixes a crash when pressing a keybinding in the settings tab. 

Regressed in #15196.

Noted in #14051
2023-04-21 23:36:19 +02:00
James Pack
210414e5a8 Default to XamlRoot when unable to find focused object (#15189)
Default to XamlRoot when unable to find a focused object in
DirectKeyEvents

This may not be the most appropriate "fix" for this. Certainly open to
criticism and feedback. We are trapping the alt+space key chord on the
win32 side and forwarding it to the xaml side. There we try to find a
focused object by walking the xaml tree. If we are unable to find a
focused object we return false and do nothing. I suspect that the area
that has focus that prevents this from working normally is on the win32
side. Since we want to handle the system menu anyway and are explicitly
trapping that key combo and forwarding it on I thought this was the best
approach. If we cant find a focused object default to the xaml root.

## Validation Steps Performed
System menu opens as it should.

Closes #14397
2023-04-20 14:00:37 -05:00
Mike Griese
2aefb30355 Remove a 1px gap under the tabs only visible at >150% (#15164)
Set the padding to the default TabViewHeaderPadding (8,0,0,0), but with
-1 on the bottom. This prevents a small 1px gap that can appear on 150%
scale displays between the tab item and the content. The 1 on top helps
keep
the tab the correct relative height within the tab row.


Regressed in #15078 

See also MSFT:40692364
2023-04-20 12:13:40 -05:00
Ben Constable
ffda8c4a95 Add automation heading level 1 to fix about dialog (#15200)
Add automation heading level 1 to fix the about dialog by adding an
automation property.

Allows screen reader to pick up that this is a heading and read
properly.

Closes #11912

---------

Co-authored-by: Mike Griese <migrie@microsoft.com>
2023-04-20 13:18:13 +00:00
Dustin L. Howett
2fd33ba510 unpackaged: allow building an unpackaged distribution from layout (#15133)
This PR adds a convenience feature to New-UnpackagedTerminalDistribution
that produces an unpackaged layout from an already-unpacked AppX, like
the one Visual Studio registers.

```powershell
New-UnpackagedTerminalDistribution `
    -TerminalLayout path\to\bin\x64\Debug\AppX `
    -XamlAppX path\to\xaml\2.8.appx
```

The output item when you build an unpackaged layout is the temp folder
in which the distribution was built. It will not make a zip file for
you.
2023-04-20 07:47:05 -05:00
James Pack
2c165438ef Add a warning when a proportional font is selected (#15195)
## Summary of the Pull Request
Add an infobar warning when a non-monospaced font is selected.
## References and Relevant Issues
#13389 
## Detailed Description of the Pull Request / Additional comments
I initially had the `IsOpen` property of the infobar bound to the
`ShowAllFonts` checkbox property. However, I felt we could do better by
adding a property for it since there was already a method defined to
inspect whether the selected font was in the `MonoSpaceFontList`.
## Validation Steps Performed
Warning shows up when a non-monospaced font is selected either globally
or on individual profiles. All existing tests continue to pass.
<img width="868" alt="image"
src="https://user-images.githubusercontent.com/2086722/232594214-cd42397b-ce9d-499c-aa73-3feaa45e850e.png">

## PR Checklist
- [x] Closes #13389 
- [x] Tests added/passed
- [ ] Documentation updated
- If checked, please file a pull request on [our docs
repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
- [ ] Schema updated (if necessary)
2023-04-20 07:42:14 -05:00
Mike Griese
0e86ce559e Add the ability to select a whole command (or its output) (#14807)
Adds two new commands, `selectOutput` and `selectCommand`. These don't
do much without shell integration enabled, unfortunately. If you do
enable it, however, you can use these commands to quickly navigate the
history to select whole commands (or their output).

Some sample JSON:

```json
        { "keys": "ctrl+shift+<", "command": { "action": "selectCommand", "direction": "prev" } },
        { "keys": "ctrl+shift+>", "command": { "action": "selectCommand", "direction": "next" } },
        { "keys": "ctrl+shift+[", "command": { "action": "selectOutput", "direction": "prev" } },
        { "keys": "ctrl+shift+]", "command": { "action": "selectOutput", "direction": "next" } },
```

**Demo gifs** in
https://github.com/microsoft/terminal/issues/4588#issuecomment-1352042789

closes #4588

Tested manually. 

<details>
<summary>CMD.exe user? It's dangerous to go alone! Take this.</summary>

Surely, there's a simpler way to do it, this is adapted from my own
script.

```cmd
prompt $e]133;D$e\$e]133;A$e\$e\$e]9;9;$P$e\$e[30;107m[$T]$e[97;46m$g$P$e[36;49m$g$e[0m$e[K$_$e[0m$e[94m%username%$e[0m@$e[32m%computername%$e[0m$G$e]133;B$e\
```

</details>
2023-04-20 07:34:58 -05:00
Leonard Hecker
35b9e75574 Avoid animations during startup (#15204)
This fixes 3 sources for animations:
* `TabView`'s `EntranceThemeTransition` causes tabs to slowly slide in
  from the bottom. Removing the transition requires you to override the
  entire list of transitions obviously, which is a global change. Nice.
  Am I glad I don't need to deal with the complexity of CSS. /s
* `TabBase`, `SettingsTab` and `TerminalTab` were using a lot of
  coroutines with `resume_foreground` even though almost none of the
  functions are called from background tabs in the first place. This
  caused us to miss the initial XAML drawing pass, which resulted in
  animations when the tab icons would asynchronously pop into existence.
  It also appears as if `resume_foreground`, etc. have a very high CPU
  cost attached, which surprises me absolutely not at all given WinRT.

The improvement is difficult to quantify because the run to run
variation is very high. But it seems like this shaves about 10% off
of the ~500ms startup delay on my PC depending on how you measure it.

Part of #5907

## PR Checklist
* It starts when it should 
* It doesn't "exit" when it shouldn't 
  (Scrolling, Settings reload, Bell `\a`, Progress `\e]9;4;2;80\e\\`)
2023-04-20 07:31:44 -05:00
Leonard Hecker
da0a6d468a Lazy load CommandPalette and AboutDialog (#15203)
This sets `x:Load` to `false` for the two elements.
On my system, with Windows Defender disabled, this reduces CPU
usage by 15ms and the visual delay during launch by 40ms.

Part of #5907

## Validation Steps Performed
* Ctrl+Shift+P opens command palette 
* Context menu opens command palette 
* Context menu opens about dialog 
2023-04-19 19:18:36 +00:00
Leonard Hecker
c2dd6143ac Fix Peasant::ActivateWindow being called with an all 0 GUID (#15187)
`WM_ACTIVATE` is sent on window creation, whereas `WM_SHOWWINDOW` is
sent when the window is shown. Before we call `Peasant::ActivateWindow`
in the `WM_ACTIVATE` handler, we try to get the virtual desktop GUID of
our window, but since it's not shown yet during startup, there's also
no GUID that can be retrieved. This results in an error log message and
an all 0 GUID to be sent via `Peasant::ActivateWindow`.
The GUID of the window that actually spawned on the other hand is never
reported until the first time you reactivate it again, leading to a
number of subtle bugs around window activity.

Additionally, this commit fixes a race condition and pointer unsafety,
by pulling all relevant member variables onto the coroutine's stack,
before it yields itself to a background thread.

## Validation Steps Performed
- Set a trace breakpoint on `_peasantNotifyActivateWindow`
- GUID is non-zero 
2023-04-19 12:42:24 -05:00
James Pack
27bcf7e41c Add subtext to why Always show tabs is not toggleable in SUI. (#15154)
## Summary of the Pull Request
Add subtext that lets the user know why Always show tabs is not
toggleable in SUI. Also adds some additional information to the comment
for this value that points to the Globals_ShowTitlebar.Header setting.

## References and Relevant Issues
#13984 
## Detailed Description of the Pull Request / Additional comments
Simple updates to the resources that add some additional helpful
information for the user.
## Validation Steps Performed
Verified the updates show in the SUI and that they render correctly.
## PR Checklist
- [ ] Closes #13984 
- [ ] Tests added/passed
- [ ] Documentation updated
- If checked, please file a pull request on [our docs
repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
- [ ] Schema updated (if necessary)

---------

Co-authored-by: Mike Griese <migrie@microsoft.com>
2023-04-18 16:23:17 +00:00
Mike Griese
2c16e7c07b Respect the startup info state initially passed to wt via ShellExecute (#13838)
Original description, pre-process model v3:

> This is just the `SHOWDEFAULT` bit from #12979. This seems to also
work now, but I'm PR'ing it separately so it can be a separate revert
from #13811, if it is problematic.

More accurately: 
This PR enables terminal windows to use the `wShowCmd` from the
STARTUPINFO passed to `windowsterminal.exe` to set the initial
visibility of the window. We can't just use `SW_SHOWDEFAULT`, because
all the windows are running in the initial process! After the first
window, the subsequent ones would ignore any params passed to their
originating `windowsterminal.exe` processes. To mitigate, we pass that
`wShowCmd` info from the source process, to the actual running terminal
process. That accounts for most of the delta here.

Closes #9053


This doesn't do the same for defterm-initiated connections. This is
because we don't need to! Defterm very explicitly rejects handoff for
minimized console apps. This is probably for the best! I put an attempt
in 66f8b25ec before I forgot that it was filtered long before the
Terminal. NOT doing this for /min saves us all sorts of "what happens if
`start /min cmd` tries to glom?" or "what if someone does `start /min
cmd && start /max cmd` and they glom together?".

<hr>

Also closes #15193, which was introduced as a part of this.

---------

Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
2023-04-18 16:23:11 +00:00
Mike Griese
1825ca104e fix not updating the nav view when add/removing profiles (#15162)
* make the list of MenuItems observable, so the nav view can actually
listen for changes to it
* Use the MenuItemsSource to find the index to add at, rather than the
MenuItems (which isn't accurate anymore)
* Stash a single observable vector as the menuitemsource, and modify
that whenever we need to do modifications.
* I attempted to create a new vector, then copy into the new one, then
replace the MenuItemsSource with the new vector, but that _refused_ to
work. So let's just... not.

Regressed in #14630
Closes #15140

Manually validated that this and #13673 are still fixed
2023-04-17 09:53:59 -05:00
James Pack
e106c095a5 Enable ctrl+shift to run terminal elevated from context menu (#15137)
This pull request adds the requirement for the shift key to be pressed
in addition to the control key.

References #14810
Implemented in #14873

This is follow up work from my last pull request that was merged that
only required the control key to be pressed to launch the terminal as
admin from the shell context menu. After some discussion it was decided
that the shift key should be required as well as that is the norm on
Windows.

## Validation Steps Performed

Tested all combinations of shift+ctrl and verified that the terminal
only requests elevation when a shift and control key are pressed
together. The shell launches regularly if not.
2023-04-17 14:12:45 +00:00
Mike Griese
52171d2dab Update to MUX 2.8.3 (#15183)
This fixes the BreadcrumbBar issue that would crash into the debugger
anytime you open the SUI on a second thread.

See #14957.

Maybe also tracked in #15144 - let's have @j4james test when this
merges.
2023-04-17 15:28:29 +02:00
Mike Griese
9b960bc88c Fix reordering tabs mysteriously shuffling the actual backing tabs (#15178)
TL;DR: we stopped getting `TabView.TabItemsChanged`. This meant that the
tab view would change its apparent order, but we wouldn't change the
backing tab order.

I'm fixing this by grabbing the index of the tab that starts the drag,
and the index of the tab view item at the end of the drag, and using
that to reorder our backing list.

Closes #15121

Upstream https://github.com/microsoft/microsoft-ui-xaml/issues/8388

Regressed in #15078 - I'm pretty confident about this, since I've got a
1.18.931 build of the Terminal with tear-out, but not MUX 2.8.
2023-04-17 15:27:52 +02:00
Leonard Hecker
1d354d0f5c Fix a hang when writing wide glyphs into a 1 column terminal (#15171)
The code changes are mostly self-explanatory: Just skip glyphs
that can never be inserted. I implemented it slightly incorrectly
(a newline will be inserted every time you write such a wide glyph),
but it's a niche issue and I think the simplicity of the fix is
more important than its exact correctness.

It also contains a fix for some severe log spam due to
`_PrepareForDoubleByteSequence` complaining in this situation.
The spam is so bad that it freezes the app for a few seconds
during text buffer reflow.

Closes #7416

## Validation Steps Performed
* Open an extra pane and run `TerminalStress.exe` in there
* Resize to 1 column
* Doesn't hang 
2023-04-14 23:15:08 +02:00
Mitch Capper (they, them)
eb725e9993 fix: WpfTerminalControl allow Connection set to null (#15062)
Hides the cursor when null, shows it when not.
Clear the screen any time the connection is changed.

This prevents the WPF Control from crashing when set back to null, clears
the console and hides the mouse as well.

It sends 3 VT sequences as well now:
1) When the Connection is set to null the cursor is hidden (reflects
what the default state is)
2) When the Connection is set to a value and it was null before we show
the cursor (not a breaking change as requires it to have been null which
previously would cause a crash, except for for set)
3) When the Connection is changed the terminal is reset. A breaking
change officially although not sure if there are use cases where this
behavior is not desired. For added safety we could make sure we are not
being set to the same value we currently are.

None of the ansi commands are needed, users could do it all themselves
as well, the behavior largely seemed natural though. I didn't see any
ansi constants anywhere so they are just hard coded with comments, but
not sure if there is an established better practice.

Closes #15061
2023-04-14 20:25:07 +00:00
James Pack
19069e03be A more efficient copy assignment operator for Pane.LayoutSizeNode (#15169)
## Summary of the Pull Request
This pull request updates the implementation of the copy assignment
operator for Pane::LayoutSizeNode to a more efficient version and
eliminates the need for the _AssignChildNode code block.
## References and Relevant Issues
#11965 #11963 
## Detailed Description of the Pull Request / Additional comments
My understanding of the discussion and intent of the two linked issues
is that this is a more efficient way to implement the copy assignment
operator for Pane.LayoutSizeNode and eliminates the need for the code
block _AssignChildNode. Since both were relatively small changes, I
combined the two in one PR. If that is not desirable, I can separate
them. All existing tests continue to pass.

<img width="769" alt="image"
src="https://user-images.githubusercontent.com/2086722/231326683-8f685f58-5748-4d49-8a38-80ef5db3d5a2.png">

## Validation Steps Performed
All existing tests pass. No visible changes in behavior of the terminal.
## PR Checklist
- [x] Closes #11963  
- [x] Closes #11965 
- [x] Tests added/passed
- [ ] Documentation updated
- If checked, please file a pull request on [our docs
repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
- [ ] Schema updated (if necessary)
2023-04-14 18:52:39 +00:00
Mike Griese
21464fe41c Manually hide our DesktopWindowXamlSource (#15165)
As discussed in #6507

Newer builds of Windows do this automatically. However, this was spotted
in the wild on 1.18. It's possible the threading changes created a
situation where the OS-side fix no longer applied to us. So let's just
do it manually. It doesn't have any side effects.

I saw this once on Win11, but couldn't repro it this morning when I
tried to add this fix. I'm just gonna assume this worked, despite the
fact that I can't repro it on win11 anymore.

closes #6507

See also #14957

## detailed description

> `WindowsXamlManager::XamlCore::Initialize` calls
`ConfigureCoreWindow`, which creates a `CoreWindow` on the thread

> Problem is, we're calling that on the main thread (which doesn't have
_any_ windows), and then eventually creating a `DesktopWindowXamlSource`
on a second thread for the actual window

> It's not that it "manages a window", it's that it "manages xaml on
Windows OS". just use ICoreWindowInterop -- QI for ICoreWindowInterop
and call get_WindowHandle.

Also see:
*
[ICoreWindowInterop](https://learn.microsoft.com/en-us/windows/win32/api/corewindow/nn-corewindow-icorewindowinterop)
*
[WindowsXamlManager.InitializeForCurrentThread](https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.hosting.windowsxamlmanager.initializeforcurrentthread?view=winrt-22621#windows-ui-xaml-hosting-windowsxamlmanager-initializeforcurrentthread)
* The source code in
`onecoreuap\windows\dxaml\xcp\dxaml\lib\WindowsXamlManager_Partial.*`
* os.2020!6102020 which fixed MSFT:33498969, MSFT:27807465,
MSFT:21854264
2023-04-14 13:07:05 -05:00
Mike Griese
789b0b065f Actually use the persisted position with centerOnLaunch:true (#15179)
Fixes an issue when using both:

```json
    "centerOnLaunch": true,
    "firstWindowPreference": "persistedWindowLayout",
```

In this case, the Terminal would ignore the persisted location and still
just center on launch. This has been really annoying while testing
tear-out, as we keep re-opening all my debug windows as a stack on top
of each other.
2023-04-14 19:13:07 +02:00
Mike Griese
72d0566fa6 Back off between attempts to start the tests (#15106)
Looking through this test, I seriously don't understand how this doesn't
work. I mean, I don't really get how it _does_ work, but at this point
in the tests, we've actually established that both `Nihilist.exe` _and_
openconsole are running. From my read, there's no reason these should be
failing at this point.

We previously added a "retry 5 times" bit to this test, in #8534. That
did work back then. So uh, just do that... again?
2023-04-13 13:38:38 -05:00
Mike Griese
f671f065bf Register the GetWindowLayoutRequested handler only when ready (#15161)
Moves our `GetWindowLayoutRequested` handler AFTER the xaml island is
started. The `AppHost::_GetWindowLayoutAsync` handler requires us to be
able to work on our UI thread, which requires that we have a
`Dispatcher` ready for us to move to. If we set up this callback in the
ctor, then it is possible for there to be a time slice where
* the monarch creates the peasant for us,
* we get ctor'ed (registering the callback)
* then the monarch attempts to query all _peasants_ for their layout,
coming back to ask us even before XAML has been created.

I believe this was the source of the crash that was reported in a mail
thread. It actually happened to me once while debugging another branch.
Alas, this was realy hard to hit in the first place, so I'm not
_totally_ certain this fixes it.

Related to #14957
2023-04-12 11:57:25 -05:00
James Pack
10bdadffbd Skip generating a profile for rancher-desktop (#15166)
Don't generate a profile for rancher-desktop utility WSL distro.

Adds a check for rancher-desktop as well as docker. As mentioned in the
discussion of this issue. This becomes much more difficult to maintain
once other folks inevitably start to follow this pattern. But the easy
win was up for grabs so I took it :)

Closes #12757
2023-04-12 11:56:55 -05:00
Ian O'Neill
56d451ded7 Support environment variables in the settings (#15082)
Existing environment variables can be referenced by enclosing the name
in percent characters (e.g. `%PATH%`).

Resurrects #9287 by @christapley.

Tests added and manually tested.

Closes #2785
Closes #9233

Co-authored-by: Chris Tapley <chris.tapley.81@gmail.com>
2023-04-11 18:01:11 -05:00
James Holderness
508adbb1ec Send a KeyUp sequence only once a key has been released (#15130)
When win32-input-mode is enabled, we generate an input sequence for both
key down and key up events. However, in the initial implementation the
key up sequence for most keypresses would be faked - they were generated
at the same time as the key down sequence, regardless of when the key
was actually released. After this PR, we'll only generate the key up
sequence once a key has actually been released.

## References and Relevant Issues

The initial implementation of win32-input-mode was in PR #6309.
The spec for win32-input-mode was in PR #5887.

## Validation Steps Performed

I've manually tested this with an app that polls `ReadConsoleInput` in a
loop and logs the results. With this PR applied, I can now see the key
up events as a key is released, rather than when it was first pressed.

When compared with conhost, though, there are some differences. When
typing a shifted key, e.g. `Shift`+`A`, WT generates key down and key up
events for both the `Shift` and the `A`, while conhost only generates
both events for the `Shift` - the `A` won't generate a key up event
unless you release the `Shift` before the `A`. That seems more like a
conhost flaw though.

Another case I tested was the Japanese Microsoft IME, which in conhost
will generate a key down event for the Japanese character being inserted
followed by a key up event for for `Return`. WT generates key up events
for the ASCII characters being typed in the IME, then both a key down
and key up event for the inserted Japanese character, and finally a key
up event for `Return`. Both of those seem weird, but they still appear
to work OK. 

The current version of WT actually produces the most sensible behavior
for the IME - it just generates key up and key down events for the
inserted character. But that's only because it's dropping most of the
system generated key up events.

Closes #8440
2023-04-11 17:59:25 -05:00
Mike Griese
b4f65030e3 Fix re-persisting the new legacy themes (#15160)
Yep, I forgot to not write them back to the settings file here.

Regressed in #15108 

Closes #15152
2023-04-11 17:10:11 -05:00
Dustin L. Howett
90bbd2927d Helix: Decode HTML entities in the test comment field (#15141
I have observed the test comment coming back from Helix with `&quot;`
and friends in it.

It ends badly as you might imagine.

This unescape will be a no-op if the data is already well-formed.
2023-04-10 15:17:29 -05:00
Dustin L. Howett
ea44375f6d Check for updates automatically (but don't install) (#13437)
This PR adds support to the About Dialog for checking the store to see
if there's a new version of the Terminal package available. We'll only
do this once per day, per terminal window.

In dev mode, we'll always fake it and say there's an update to `x.y.z`
available.

This also involved pulling all of the About dialog code out into its own
class. All that is goodness.

We don't currently provide a button for _installing_ the update. We just
check. Incremental progress is better than none.

Co-authored-by: Mike Griese <migrie@microsoft.com>
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
2023-04-06 18:31:19 -05:00
Dustin L. Howett
7fbd3be8c3 Only try to hand off to ConhostV1 if building for Windows (#15131)
Some of our automated tooling detects this as being a private API that
we're accessing via LoadLibrary/GetProcAddress. It's not *wrong*, but
it's also not *right*.

It's easier for us to just not do it (and save all the code for it!) in
OpenConsole.
2023-04-06 16:32:40 -05:00
Dustin L. Howett
de09671d8a wpf: Bump the history length to 9001 instead of 1000 (#15129)
This was an oversight in the original implementation.
2023-04-06 15:03:12 -05:00
Dustin L. Howett
c7498a4269 PGO: Update the Helix payload to rely on the unpackaged distribution (#15123)
The unpackaged distribution was made for this exact use, so let's *do
it*!
2023-04-06 22:01:00 +02:00
Mike Griese
083fc647bb Revert the revert of "Hide the window until we're finished with initialization" (#13811)
This is a revert of the revert of #12979. We mainly reverted that PR
because of an issue where restored windows would grow/shrink slightly on
external displays. It was too close to the ship date for that release,
so we backed it out wholesale (in #13098). I think I've found the real
root of the problem, and fixed it here.

The money diff here from the original PR:
4c08b9a1bc2e90b8284e4d8117d0de400784520f...c34495dcfc19ea67a9f4f9673d422760200683ab.
Basically, I had put the part where we actually handle the creation of
the window into `_AppInitializedHandler`, when we should have left the
window to be created in `_HandleCreateWindow` We create it there,
_hidden_, and then should only _show_ it in `_AppInitializedHandler`.

I'm _NOT_ incorporating the change for #9053. I reverted that bit in
1fac40355. I am too worried about that messing with the phwnd that I
wanted to get that reviewed and committed atomically, separately.

* fixes  #11561
* tested manually
* I work here
2023-04-06 18:03:25 +00:00
Mike Griese
6f8ef58673 Add support for running the Terminal without _any_ windows (#14944)
This adds a setting (`compatibility.allowHeadless`) to let the Terminal
keep running even when all windows are closed. This lets hotkeys keep
working, because the Emperor thread is still running, just, without any
windows.

I'm really tempted to invoke the magic "closes" word on #9996, but
honestly, we should also add some sort of support for `wt --headless` or
`wt --hidden` or whatever, before we close that. There's also #13630
which seems imminently doable.

Tested manually. I'd post a gif of "close all terminal windows, then
invoke the quakeMode binding and \*presto\*, but that would be an
unnecessarily big gif.

Related to #9996 but not enough to close it if you ask me
2023-04-06 12:39:40 -05:00
Mike Griese
fe66ba5f58 Add "legacy" themes (#15108)
This is a minimal version of the requests for #14858. In that thread we
discussed FULL reverting the default themes to the old ones. In later
discussion, we decided _meh_, let's just ship the legacy themes too, so
it's easy to go back if you should choose. The default still remains the
sane `dark`, but the `legacy*` themes are all right there, and given the
same special treatment as the other inbox themes.

Closes #14858
Closes #14844
2023-04-06 16:50:30 +00:00
michalnpl
e73362d45b Respect the codepage stored in .LNK files in conhost (#15111)
Making Conhost pick up codepage from .lnk files.

Because of the wrong assignment order, the Conhost was not picking up
the codepage stored in .lnk shortcut files. This change fixes this issue
by changing the order of the assignment to the correct one.

This is a potential backward compatibility issue.

Since this issue has been present in the codebase for years, this change
runs a high risk of breaking backward compatibility with software that
depends on incorrect behavior.

## Validation Steps Performed
Tested fix manually (using chcp command, making sure each .lnk codepage
was picked up.) against Debug/Release x64 builds with 5 different .lnk
files:

1. Arabic codepage 1256
2. Greek 869
3. Latin2 852
4. Thai 874
5. Traditional Chinese 50229

Ran TAEF tests against Debug/Release x64/x86 with identical results as
main branch.

Tested against invalid codepage numbers by manually manipulating .lnk
file binary. In case of an invalid codepage number, Conhost defaults to
a valid default one, which I assume is expected behavior.

Closes #14942
2023-04-06 10:51:57 -05:00
Dustin L. Howett
a98a0cf2c6 Stop the beef when you hover off a hyperlink (#15120)
Big surprise, apparently W.F.Uri can parse the empty string into
garbage!
2023-04-05 16:10:54 -07:00
Leonard Hecker
5db8af6277 Return success if ReadCharacterInput read >0 characters (#15122)
This is a regression caused by 599b550. If I'm reading `stream.cpp`
in cf87590 right, it returns `STATUS_SUCCESS` if `ReadCharacterInput`
read at least 1 character. I think? this PR makes the code behave
exactly equivalent. The old code is a bit of an "acquired taste"
so it's a bit hard to tell.

Closes #15116

## PR Checklist
* Run `more long_text_file.txt` in cmd
* Press Spacebar
* Scrolls down 
* Press Q
* Exits 
2023-04-05 22:52:04 +00:00
Dustin L. Howett
5f70920491 When unpackaged, isolate the monarch by the install path (#15118)
Unpackaged installations don't have the luxury of magic package
isolation to stop them from accidentally touching each other's monarchs.
We need to enforce that ourselves by making their monarch CLSIDs unique
per install.

We'll use a v5 UUID based on the install folder to unique them.

Closes #15117
2023-04-05 17:04:58 -05:00
Leonard Hecker
62448969b3 Upgrade clang-format to 15.0.7 (#15110)
Upgrading clang-format lead to a few changes in the formatting
of code inside macros. Apart from the upgrade, I've also spent
some time removing all options from .clang-format that are
redundant with `BasedOnStyle: Microsoft`.
2023-04-05 10:03:20 -05:00
Leonard Hecker
ecb5e37a7d Use new row primitives for ResizeTraditional (#15105)
This will allow us to share the same fundamental text insertion
logic for both `ResizeTraditional` and `Reflow`, because both
can be implemented with `ROW::CopyRangeFrom`. It also replaces
the `BufferAllocator` struct with a `_allocateBuffer` function
which will help us allocate scratch buffer rows in the future.

Closes #14696

## PR Checklist
* Disable reflow resize in conhost
* Print "zhwik8.txt" - a enwik8.txt equivalent of Chinese Wikipedia
* Run `color 80` in cmd
* Resize windows from 120 to 119 columns
* Wide glyphs disappear and are replaced with whitespace 
* Resizing the window to >120 columns adds gray whitespace 
2023-04-05 09:59:20 -05:00
James Holderness
aea0477bda Filter out control characters that don't do anything (#15075)
On a real VT terminal, most of the control characters that don't do
anything are supposed to be filtered out, and not written to the buffer.
Up to to now, though, we've only been filtering out `NUL`. This PR
extends our control processing to filter the remaining characters that
aren't supposed to be displayed.

We introduced filtering for the `NUL` control in PR #3015.

The are two special cases worth mentioning.

1. The `SUB` control's main purpose is to the cancel a control sequence
that is in progress, but it also needs to output an error character (a
reverse question mark) to the display.

2. The `DEL` control is typically filtered out, but when a 96-character
set is designated, it can sometimes be mapped to a printable glyph that
needs to be displayed.

## Validation Steps Performed

I've manually tested that all the controls that are meant to be filtered
out are no longer being displayed.

I've also extended the existing `NUL` unit test to cover the full set of
controls characters that are supposed to be filtered.

Closes #10786
2023-04-05 09:58:52 -05:00
Dustin L. Howett
06526cac0c Remove our dependency on any CRT--AppX or forwarders (#15097)
The upgrade to Microsoft.UI.Xaml 2.8 was the last piece we needed to
break our dependency on the App CRT *and* any CRT whatsoever.
2023-04-04 16:11:12 -05:00
Leonard Hecker
9dfdf2afa3 Introduce til::linear_flat_set (#15089)
`til::linear_flat_set` is a primitive hash map with linear probing.
The implementation is slightly complicated due to the use of templates.
I've strongly considered just writing multiple copies of this class,
by hand since the code is indeed fairly trivial but ended up deciding
against it, because this templated approach makes testing easier.

This class is in the order of 10x faster than `std::unordered_map`.
2023-04-04 19:50:10 +02:00
Leonard Hecker
2a839d8c5a Fix accuracy bugs around float/double/int conversions (#15098)
I noticed this bug while resizing my window on my 150% scale display.
Every 3 "snaps" of the window size, it would fail to resize the text
buffer. I found that this occurs, because we convert the swap chain
size from a float into a double, which converts my 597.333313 height
into 597.33331298828125, which then multiplied by 1.5 results in
895.999969482421875. If you just cast this to an integer, it'll
result in a height of 895px instead of the expected 896px.

This PR addresses the issue in two ways:
* Replace casts to integers with `lrint` or `floor`, etc.
* Remove many of the redundant double <> float conversions.

## PR Checklist
* Resizing my window always resizes the text buffer 
2023-04-04 11:33:17 -05:00
James Pack
da995a014f Enable holding ctrl to open the Terminal elevated from File Explorer
## Summary of the Pull Request
This pull request adds support for holding the control key and clicking
the Open Terminal Here context menu item to elevate the request.
## References and Relevant Issues
#14810

## Detailed Description of the Pull Request / Additional comments

## Validation Steps Performed

## PR Checklist
- [x] Closes #14810
- [ ] Tests added/passed
- [ ] Documentation updated
- If checked, please file a pull request on [our docs
repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
- [ ] Schema updated (if necessary)

---------

Co-authored-by: Mike Griese <migrie@microsoft.com>
2023-04-04 16:24:33 +00:00
Leonard Hecker
47a17cf2d7 Replace statics in headers with inline constants (#15100)
C++ is a very well balanced and reasonable language, which is why
`static` inside classes means "shared between all instances", whereas
`static` outside of classes means "not shared between all .cpp files".

32 years after this problem was written onto parchment it was fixed with
the introduction of inline variables in C++17, which tell the compiler
to deduplicate variables the same way it deduplicates functions.
2023-04-04 10:19:20 -05:00
Mike Griese
c0f14567f3 Use DIPs for the window bounds when tearing out (#15094)
Fixes a bug where you'd drag across the boundary and the new window
would be at the wrong size

related to #14957
2023-04-04 14:21:43 +00:00
Leonard Hecker
5de1fd9a7b Introduce til::generational - a struct comparison helper (#15088)
It can be costly, difficult, or often impossible to compare two
instances of a struct. This little helper can simplify this.

The underlying idea is that changes in state occur much less often than
the amount of data that's being processed in between. As such, this
helper assumes that _any_ modification to the struct it wraps is a
state change. When you compare the modified instance with another
the comparison operator will then always return false. This makes
state changes potentially more costly, because more state might be
invalidated than was necessary, but on the other hand it makes both,
the code simpler and the fast-path (no state change) much faster.

For instance, let's look at the amount of data that represents a
user's chosen font: It encompasses the font family, size and weight,
font axes (a vector of tuples), dpi and cell height/width overrides.
Comparing all that data, every time the user changes anything, is
fairly complex to code and maintain and costly at runtime, even though
the user will change the only font very seldomly. Instead, we can
optimize for the common case of no font changes occuring and simply
assume that if any font related field changed, all fields changed.
This is exactly what `til::generational` does.
2023-04-04 15:47:36 +02:00
Mike Griese
17cf44fa71 Upgrade to MUX 2.8 (#15078)
Updates the Terminal to Microsoft.UI.Xaml v2.8. 

* MUX 2.8 adds a dependency on WebView2, so we need to include parts of it too.
* See https://github.com/microsoft/microsoft-ui-xaml/pull/7574 for why
we're adding the `.props`
* The TabView thing: 
> tl;dr: In >=MUX 2.7, we were updating our tab colors by doing a
"Visual State Dance", as I called it. We'd manually change the
`TabViewItem`'s VisualState to one that it wasn't in, then change it
back to the one it should be in. This seemingly re-applied the new
values of the brushes. However in 2.8, this seemingly didn't work
anymore!
  > 
  > So instead, we do a "Theme Dance", like so:
  > ```c++
  >   const auto& reqTheme = TabViewItem().RequestedTheme();
  >   TabViewItem().RequestedTheme(ElementTheme::Light);
  >   TabViewItem().RequestedTheme(ElementTheme::Dark);
  >   TabViewItem().RequestedTheme(reqTheme);
  >   ```
> This causes the `ThemeResource`s to be re-evaluated to the new values.
> We never got to the root cause of why this seems different in 2.8. It
literally makes no sense.
Closes #13495

Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
2023-04-03 22:40:46 +00:00
Dustin L. Howett
06174a9cb3 Format URLs for display when we show the tooltip (#15095)
This will reduce the incidence of confusables, RTL, and non-printables
messing with the display of the URL.
2023-04-03 21:22:25 +00:00
Leonard Hecker
0656afcf13 Expose hyperlink attributes in PaintBufferGridLines (#15090)
Rendering hyperlinks is unneccessarily complex at the moment, because
it requires you to implement `UpdateDrawingBrushes`, manually extract
the hyperlink flag from the given `TextAttribute` and save it until the
next call to `PaintBufferGridLines` which does not get that flag.
This isn't particularly clean as it assumes that `PaintBufferGridLines`
will be called after `UpdateDrawingBrushes` in the first place.

Instead, we can simply pass the hyperlink flag to `UpdateDrawingBrushes`
so that the renderers don't need to deal with this anymore.

## PR Checklist
* Hyperlinks show up with a dotted line 
* Hovering hyperlinks underline them 
2023-04-03 20:39:36 +02:00
Leonard Hecker
0d38d17299 Add a simple tool to test rendering functionality (#15091)
This tool augments `vttest` by adding some things that are specific to
us (like non-VT console attributes), and some things `vttest` is
seemingly too old for (like emojis). I'm planning to add more "pages"
of tests to the application in the future, whenever the need arises.
2023-04-03 13:21:22 -05:00
Leonard Hecker
7ddd98de0a Fix warnings in til for an upcoming version of MSVC (#15087)
A trivial change. :)
2023-04-03 13:14:01 -05:00
Sam Meyer
0105807be2 Add pre-build PowerShell version check (#14947)
Two PowerShell scripts were added so that developers new to the project
know if they have the wrong version of PowerShell installed.

When first building Terminal, it would continuously fail, and I didn't
really know why. I'm new to both this project and to open source, so
when I saw an error message about "pwsh.exe" not being found I was
confused and didn't know what went wrong. What I didn't know is that
Windows PowerShell and PowerShell Core had different names for
their .exe files, and since I had the latest version of Windows
PowerShell installed, I figured that I was completely set. So, once I
realized that Windows PowerShell (what I had installed) is
powershell.exe and PowerShell Core (what I needed to have installed) is
pwsh.exe, I downloaded PowerShell Core, and it built without issue. So,
in order to help other newbies, I made two scripts, `CheckPSVersion` and
`WindowsCheckPSVersion`, which make sure that PowerShell Core 7.0.0+ is
installed, outputting an error telling the developer to download Core
7.0.0+ if they have Windows PowerShell but not Core. These scripts are
run pre-build courtesy of `Microsoft.Terminal.Settings.ModelLib.vcxproj`

## Validation Steps Performed
Building with both Windows PowerShell and PowerShell core: builds
perfectly, no issues.
Building with Windows PowerShell but not PowerShell core: build fails,
but a nice error prints out that reminds the user to download the
correct version of PowerShell core.

Closes #14797
2023-03-31 18:02:29 -05:00
Dustin L. Howett
e6a3fa8d4e Add "portable mode", where settings load from the install path (#15051)
This pull request implements portable mode for Windows Terminal, which
will make side by side deployment of different versions generally more
feasible.

Portable mode was specified in #15032.

There are three broad categories of changes in this PR:

1. Changes to settings loading.
2. A new indicator in the settings UI plus a link to the portable mode
   docs.
3. A new application display name, `Terminal (Portable)`, which users
   will hopefully include in their bug reports.

It's surprisingly small for how big a deal it is!

Related to #15034
Closes #1386
2023-03-31 17:12:00 -05:00
Mike Griese
bbd4d1b1e4 Fix a crash in the rclick context menu (#15079)
Due to a bad merge a few commits back. This event should have had a
revoker.

Probably regressed in #14851
2023-03-31 13:49:12 -07:00
Dustin L. Howett
984b03ca33 [SPEC] Add a lightweight spec for Portable Mode (#15032) 2023-03-31 15:46:00 -05:00
Mike Griese
7b0aca444f Enable tearing out tabs to create new windows (#14935)
_This is the last one 🎉_

## Summary

_In the final chapter of our tale, we present a PR of great
significance. It grants the power to tear tabs from their windows and
create a new window where they may be dropped, one not necessarily of
the Terminal sort. The dimensions of the original window are transferred
to this new abode, and its placement on the screen is determined by the
user's placement of the tab._
_This is the last main chapter of the tear-out saga, and the dawning of
the new age._

Closes #5000
Related to #1256

## Detailed description

We're really leaning on the existing `RequestNewWindow` event that the
monarch already had - honestly, most of that was so simple that it could
have just been in the parent PRs. We just need to add new support for
passing in a content blob of json, and making sure the Terminal always
uses that over commandline args. Easy enough.

There's a bit of wackiness here in adjusting the positioning just right
so that the new window appears in the right place, but it feels...
pretty good all things considered.
2023-03-31 19:37:17 +00:00
Dustin L. Howett
dd63a0590b Add support for an unpackaged distribution of Terminal (#15034)
Since the removal of the Win10-specific variant of the Terminal MSIX in
#15031, there has been no officially-sanctioned (or even unofficially
tested!) way to get an unzippable double-click-runnable version of
Windows Terminal.

Due to a quirk in the resource loading system, an unpackaged
distribution of Terminal needs to ship all of XAML's resources and all
of is own resources in a single `resources.pri` file. The tooling to
support this is minimal, and we were previously just coasting by on
Visual Studio's generosity plus how the prerelease distribution of XAML
embedded itself into the consuming package.

This pull request introduces a build phase plus a supporting script (or
three) that produces a ZIP file distribution of Windows Terminal when
given a Terminal MSIX and an XAML AppX.

The three scripts are:

1. A script to merge any number of PRI files and/or PRI dump files (made
   with `makepri dump /dt detailed`)
2. A script that specifically merges XAML's resources with Terminal's.
   This is necessary because the XAML package emits a couple PRI
   resources into Terminal's resources _even when it is not
   co-packaged._ We need to remove the conflicting resources.
3. Finally, a script to take a WT and XAML distribution and combine them
   -- resources, files, everything -- and strip out the things that we
   don't need. This script is an all-in-one that calls the other two and
   produces a ZIP file at the end.

The final distribution is named after the PFN
(`Microsoft.WindowsTerminal`, or `...Preview` or `WindowsTerminalDev`),
the version number and the architecture. When expanded, it produces a
directory named `terminal-X.Y.Z.A` (version number.)

I've also added the build script to the release pipeline.

As a treat, this also produces an unpackaged distribution out of every
CI build... that way, contributors can download live deployable copies
of WT Unpackaged to test out their changes. Pretty cool.

Refs #1386
2023-03-30 16:38:10 -05:00
James Holderness
fc95802531 Merge the LineFeed functionality into AdaptDispatch (#14874)
The main purpose of this PR was to merge the `ITerminalApi::LineFeed`
implementations into a shared method in `AdaptDispatch`, and avoid the
VT code path depending on the `AdjustCursorPosition` function (which
could then be massively simplified). This refactoring also fixes some
bugs that existed in the original `LineFeed` implementations.

## References and Relevant Issues

This helps to close the gap between the Conhost and Terminal (#13408).
This improves some of the scrollbar mark bugs mentioned in #11000.

## Detailed Description of the Pull Request / Additional comments

I had initially hoped the line feed functionality could be implemented
entirely within `AdaptDispatch`, but there is still some Conhost and
Terminal-specific behavior that needs to be triggered when we reach the
bottom of the buffer, and the row coordinates are cycled.

In Conhost we need to trigger an accessibility scroll event, and in
Windows Terminal we need to update selection and marker offsets, reset
pattern intervals, and preserve the user's scroll offset. This is now
handled by a new `NotifyBufferRotation` method in `ITerminalApi`.

But this made me realise that the `_EraseAll` method should have been
doing the same thing when it reached the bottom of the buffer. So I've
added a call to the new `NotifyBufferRotation` API from there as well.

And in the case of Windows Terminal, the scroll offset preservation was
something that was also needed for a regular viewport pan. So I've put
that in a separate `_PreserveUserScrollOffset` method which is called
from the `SetViewportPosition` handler as well.

## Validation Steps Performed

Because of the API changes, there were a number of unit tests that
needed to be updated:

- Some of the `ScreenBufferTests` were accessing margin state in the
`SCREEN_INFORMATION` class which doesn't exist anymore, so I had to add
a little helper function which now manually detects the active margins.

- Some of the `AdapterTest` tests were dependent on APIs that no longer
exist, so they needed to be rewritten so they now check the resulting
state rather than expecting a mock API call.

- The `ScrollWithMargins` test in `ConptyRoundtripTests` was testing
functionality that didn't previously work correctly (issue #3673). Now
that it's been fixed, that test needed to be updated accordingly.

Other than getting the unit tests working, I've manually verified that
issue #3673 is now fixed. And I've also checked that the scroll markers,
selections, and user scroll offset are all being updated correctly, both
with a regular viewport pan, as well as when overrunning the buffer.

Closes #3673
2023-03-30 13:32:54 -05:00
Leonard Hecker
da3a33f3bc Minor cleanups after #14745 (#14748)
#14745 removed the only user of `GetAugmentedOutputBuffer`.
2023-03-30 10:27:04 -05:00
Mike Griese
9514c1191a Enable dragging tabs between windows (#14901)
_Behold, the penultimate chapter in the saga of tear-out! This
significant update bestows upon the user the power to transport tabs
betwixt Terminal windows. Alas, the drag and drop capabilities of
TabView are not yet refined, so this PR primarily concerns itself with
the intricacies of plumbing. When a tab is extracted and deposited
elsewhere, it is necessary to have the recipient make an inquiry to the
Monarch, who in turn will beseech the sender to transmit the tab
content, akin to the act of moving a tab. Curious it may seem, but the
method has proven effective._

The penultimate tear-out PR. This PR enables the user to move tabs from
one Terminal window to another. The TabView drag/drop APIs have some
rough edges, so this PR is mostly plumbing. When a tab is drag/dropped,
we need to get the recipient to ask the Monarch to ask the sender to
send the tab content, like a MoveTab action. Wacky, but it works.

There's a LONG tail of UX gaps. Those I'm going to track in #14900. It
is more valuable for us to merge this now than to figure out workarounds
immediately.

The next PR will be the last main PR in this saga - in which we enable
dragging a tab out of the window and dropping to create a new window.


* Closes #1256
* Related to #5000
* Follow-ups get to go in #14900 


## Detailed description

As I mentioned, it's mostly plumbing. The order that we get tab drag
events is... unfortunate... for our use case. So we do a lot of sending
`RequestReceiveContentArgs` up and down between windows, just to
communicate who the tab was dropped on to whomever the tab was dragged
from.

There's a diagram for this that I originally put in
https://github.com/microsoft/terminal/issues/5000#issuecomment-1435328038:

```mermaid  
sequenceDiagram
    participant Source
    participant Target
    participant Monarch

    Note Left of Source: _onTabDragStarting
    Source --> Source: stash dragged content
    Source --> Source: pack window ID into DataPackage

    Source ->> Target: Drag tab
    Note right of Target: _onTabStripDragOver
    Target ->> Target: AcceptedOperation(DataPackageOperation::Move)
    
    Source --> Target: Release mouse (to drop)
    
    Note right of Target: _onTabStripDrop
    Target --> Target: get WindowID from DataPackage
    Target -) Monarch: Request that WindowID sends content to us<br>RequestRecieveContent
    Monarch -) Source: Tell to send content to Target.Id<br>RequestSendContent, SendContent
    Source --> Source: detach our content
    Source -) Monarch: RequestMoveContent(stashed, target.id)
    Monarch -) Target: AttachContent(stashed)

    # Target -->> Source: 
    # Note Left of Source: TabViewTabDragStartingEventArgs<br>.OperationCompleted
    # Note Left of Source: _onTabDroppedCompleted
```

Really really though, let's try to avoid nits about the UX at this time.
This PR works with what we've got. Mail threads are percolating. I've
got 19 chapters worth of Hobbit branch names to use for those follow
ups.
2023-03-30 15:20:23 +00:00
Mike Griese
17a5b77335 Add support for moving panes and tabs between windows (#14866)
_Lo! Harken to me, for I shall divulge the heart of the tab tear-out
saga. Verily, this PR shall bestow upon thee the power to move tabs and
panes between windows by means of pre-defined actions. Though be warned,
it does not yet grant thee the power to drag and drop them as thou
mayest desire. Yet, the same plumbing that underpins this work shall
remain steadfast. Behold, the majority of this undertaking concerns the
elevation of the RequestMoveContent event from the TerminalPage to the
very summit of the Monarch. From thence, a great AttachContent method
shall descend back to the lowest depths. Furthermore, there are minor
revisions to TermControl that shall enable thee to better detach the
content and attach it to a new one._

This is the most important part of the tab tear-out saga. This PR
enables the user to move tabs and panes between windows using
pre-defined actions. It does _not_ enable the user to drag/drop them
yet, but the same fundamental plumbing will still apply. Most of the PR
is plumbing the `RequestMoveContent` event up from the `TerminalPage` up
to the `Monarch`, and then plumbing an `AttachContent` method back down.
There are also small changes to `TermControl` to better support
detaching the content and attaching to a new one.

For testing, I recommend:

```json
        { "keys": "f1", "command": { "action": "moveTab", "window": "1" } },
        { "keys": "f2", "command": { "action": "moveTab", "window": "2" } },

        { "keys": "f3", "command": { "action": "movePane", "window": "1" } },
        { "keys": "f4", "command": { "action": "movePane", "window": "2" } },

        { "keys": "shift+f3", "command": { "action": "movePane", "window": "1", "index": 3 } },
        { "keys": "shift+f4", "command": { "action": "movePane", "window": "2", "index": 3 } },
```

* Related to #1256
* Related to #5000

---------

Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
2023-03-30 14:37:53 +00:00
James Holderness
34aa6aa0d4 Update DECSC/DECRC to match the newer DEC terminals (#15054)
When saving and restoring the cursor position with origin mode enabled,
we originally matched the behavior of the early DEC terminals, which
stored the position as an absolute offset. But if the margin boundaries
were changed prior to restoring the position, that could result in the
cursor being outside the margins, potentially with negative coordinates.

Our implementation avoided that bug by clamping the coordinates back
into range, but that's not how DEC ultimately fixed the issue. Starting
with the VT420, they began using relative coordinates (i.e. relative to
the margin origin), so a restored position could never end up negative.
This PR updates our implementation to match that newer behavior.

## Validation Steps Performed

Thank to testing performed by @al20878, we know this was the algorithm
used on the VT420, VT520, and VT525, and I've manually confirmed that
our implementation now matches their behavior.

I've also updated the `CursorSaveRestore` unit test which previously
covered our clamping behavior - it's now being used to confirm that
we're correctly using relative offsets when restoring the cursor.

Closes #15048
2023-03-28 14:03:41 -05:00
Dustin L. Howett
c7816fdb05 Add flexible virtualization rules for HKCU\Console\Startup (#15050)
[Flexible Virtualization] is a little more restrictive than
`unvirtualizedResources`, but it's more descriptive and stands a chance
of working on Windows 10.

This makes `unvirtualizedResources` actually work for us - we can tell
the system exactly which registry keys we want to use. This is required
for our registry writes to work on Windows 10.

[Flexible Virtualization]:
https://learn.microsoft.com/en-us/windows/msix/desktop/flexible-virtualization
2023-03-28 10:23:57 -05:00
Leonard Hecker
d9efdae982 Fix font size of HTML clipboard contents (#15046)
This regression is caused by 0eff8c0. It previously said `.Y` here.
I went through the diff again and found no other width/height mistake.

Closes #14762
Closes #15043
2023-03-27 11:44:54 -05:00
Dustin L. Howett
c4d029829a Add a second way of detecting whether DefTerm is available (#15040)
This will become meaningful soon.
2023-03-24 17:21:50 -05:00
Leonard Hecker
f20cd3a9d3 Add an efficient text stream write function (#14821)
This adds PR adds a couple foundational functions and classes to make
our TextBuffer more performant and allow us to improve our Unicode
correctness in the future, by getting rid of our dependence on
`OutputCellIterator`. In the future we can then replace the simple
UTF-16 code point iterator with a proper grapheme cluster iterator.

While my focus is technically on Unicode correctness, the ~4x VT
throughput increase in OpenConsole is pretty nice too.

This PR adds:
* A new, simpler ROW iterator (unused in this PR)
* Cursor movement functions (`NavigateToPrevious`, `NavigateToNext`)
  They're based on functions that align the cursor to the start/end
  of the _current_ cell, so such functions can be added as well.
* `ReplaceText` to write a raw string of text with the possibility to
  specify a right margin.
* `CopyRangeFrom` will allow us to make reflow much faster, as it's able
  to bulk-copy already measured strings without re-measuring them.

Related to #8000

## Validation Steps Performed
* enwik8.txt, zhwik8.txt, emoji-test.txt, all work with proper
  wide glyph reflow at the end of a row 
* This produces "a 咪" where only "a" has a white background:
  ```sh
  printf '\e7こん\e8\x1b[107ma\x1b[m\n'
  ```
* This produces "abん":
  ```sh
  stdbuf -o0 printf '\x1b7こん\x1b8a'; printf 'b\n'
  ```
* This produces "xy" at the end of the line:
  ```sh
  stdbuf -o0 printf '\e[999C\bこ\bx'; printf 'y\n'
  ```
* This produces red whitespace followed by "こ " in the default
  background color at the end of the line, and "ん" on the next line:
  ```sh
  printf '\e[41m\e[K\e[m\e[999C\e[2Dこん\n'
  ```
2023-03-24 17:20:53 -05:00
Dustin L. Howett
f5e9e8ea77 Consolidate our MSIX distribution back down to one package (#15031)
We ship a separate package to Windows 10, which contains a copy of XAML
embedded in it, because of a bug in activating classes from framework
packages while we're elevated.

We did this to avoid wasting disk space on Windows 11 installs (which is
critical given that we're preinstalled in the Windows image.)

The fix for this issue was released in a servicing update in April 2022.
Thanks to KB5011831, we no longer need this workaround!

And finally, this means that we no longer need to depend on a copy of
"pre-release" XAML. We only did that because it would copy all of its
assets into our package.

Introduced in #12560
Closes #14106
Closes (discussion) #14981
Reverts #14660
2023-03-24 08:31:17 -05:00
Mike Griese
36c6b7748e Clean up more warnings (#15039)
* These `Icon` bindings were to `Profile`s which aren't Observable, but
it also doesn't matter
* More c# warnings

hopefully we'll just jump straight to real errors now.
2023-03-24 08:30:58 -05:00
Mike Griese
b34444f40a Fix wt -w _quake by not throwing when setting the window name (#15030)
If we get initialized with a window name, this will be called before
XAML is stood up, and constructing a PropertyChangedEventArgs will
throw. So don't.


Regressed in #14843 

Related to #5000, #14957
2023-03-24 08:30:37 -05:00
Dustin L. Howett
f06cd1759f VsDevCmdGenerator: respect the user's startingDirectory (#15035)
The PowerShell equivalent was added in the initial pull request, #7774.

Closes #13721
2023-03-23 18:14:48 -05:00
James Holderness
0f7d1f4568 Add support for the Presentation State reports (#14998)
This PR introduces two new sequences, `DECRQPSR` and `DECRSPS`, which
provide a way for applications to query and restore the presentation
state reports. This includes the tab stop report (`DECTABSR`) and the
cursor information report (`DECCIR`). 

One part of the cursor information report contains the character set
designations and mapped G-sets. But we weren't tracking that data in a
way that could easily be reported, so I needed to do some refactoring in
the `TerminalOutput` class to make that accessible.

Other than that, the rest was fairly straightforward. It was just a
matter of packaging up all the information into the correct format for
the returned `DCS` string, and in the case of the restore operations,
parsing the incoming data and applying the new state. 

## Validation Steps Performed

Thanks to @al20878, we were able to test these operations on a real
VT525, and I've manually verified that our implementation matches that
behavior. I've also added some unit tests covering both reports.

Closes #14984
2023-03-23 17:46:17 -05:00
James Holderness
7a2e4f8d9b Fix DECCRA when copying from a double-width line (#15026)
When a `DECCRA` operation is copying content that spans a double width
line, it's possible that some range of the bounding rectangle will be
off-screen, and that range is not supposed to be copied. However, the
code checking for off-screen positions was using incorrect coordinates,
so we would mistakenly copy content that shouldn't be copied, and drop
content that should have been copied. This PR fixes that.

## References and Relevant Issues

This was a regression introduced in PR #14650 when fixing an issue with
horizontal scrolling of DBCS characters.

## Validation Steps Performed

I manually verified this fixes the test case in #15019, and I've also
added a unit test that replicates that case.

Closes #15019
2023-03-22 12:37:08 -05:00
Alex Noble
2acdc9d7e2 Add options to enable and disable read only mode (#14995)
## Summary of the Pull Request
PR adds functionality to enable or disable readOnly mode within panes.
This functionality is different to toggling as if you call the same
functionality twice, it will not toggle between states.

## References and Relevant Issues
- Closes https://github.com/microsoft/terminal/issues/14415
- Documentation https://github.com/MicrosoftDocs/terminal/pull/645

## Validation Steps Performed
- Checked readOnly is enabled when command triggered
- Checked readOnly is enabled when command triggered while read only
already enabled
- Checked readOnly is disabled when command triggered while read only is
enabled
- Checked readOnly stays disabled when command triggered while read only
is disabled
- Checked above with multiple tabs and split panes

## PR Checklist
- [ ] Closes #14415 
- [X] Tests added/passed
- [x] Documentation updated
- If checked, please file a pull request on [our docs
repo](https://github.com/MicrosoftDocs/terminal) and link it here:
https://github.com/MicrosoftDocs/terminal/pull/645
- [X] Schema updated (if necessary)

---------

Co-authored-by: Mike Griese <migrie@microsoft.com>
2023-03-22 12:32:56 -05:00
Mike Griese
f3a722e0e9 Introduce a ContentManager helper (#14851)
## Summary

_Thus we come to the introduction of a new servant, the
`ContentManager`, a singular entity that serves at the behest of the
`emperor`. It is its charge to keep track of all `TermControl` instances
created by the windows, for each window must seek its blessing before
calling forth such an instance._
_With the aid of the `ContentManager`, the `TermControl` shall now be
traced by the hand of fate through the use of unique identifying marks,
known as `GUID`s. Yet, its purpose remains yet unknown, for it is merely
a waypoint upon the journey yet to come._
_This act of bridging also brings a change to the handling of events
within the `TermControl`. This change shall see the addition of a
revoker, similar to the manner in which the `AppHost` hath employed it,
to the `TermControl`. Additionally, there is a new layer of indirection
between the `ControlCore` and the `App` layer, making ready for the day
when the `TermControl` may be repositioned and re-parented with ease._
_Consider this but a trivial act, a mere shadow of things yet to come,
for its impact shall be felt but briefly, like the passing of a gentle
breeze._

Related to #5000
Related to #1256

# Detailed description

This PR is another small bridge PR between the big work in #14843, and
the PR that will enable panes to move between windows.

This introduces a new class, called `ContentManager`. This is a global
singleton object, owned by the emperor. Whenever a window wants to
instantiate a new `TermControl`, it must ask the ContentManager to give
it one. This allows the ContentManager to track each "content" by GUID.
That's it. We don't do anything with them in this PR by itself, we just
track them.

This also includes a small change to the way TermControl events are
handled. It adds an `AppHost`-like revoker struct, and weak_ref's all
the handlers. We also add a layer of indirection between the
ControlCore's raising of events and the App layer's handling. This will
make reparenting content easier in the future.

This is a pretty trivial change which shouldn't have any major side
effects. Consider it exposition of the things to come. It's
intentionally small to try and keep the reviews more managable.
2023-03-22 12:11:44 -05:00
Dustin L. Howett
e0046a4cca Remove useRegExe and add rescap:unvirtualizedResources (#15028)
Due to a limitation in the Windows App Installer UI, Terminal had to
shell out to `reg.exe` to write the Delegation registry keys. The team
in charge of AppInstaller lifted that (once by-policy) limitation.

Therefore, we can remove our BODGY workaround.
2023-03-21 15:18:21 -05:00
Dustin L. Howett
5a34d92cb5 winget.yml: switch to manually using wingetcreate (#15023)
It was brought to my attention that we should be more restrictive in
which tasks we ovver a GitHub token to. Sorry!

With thanks to sitiom for the version parsing and the magic GitHub
action syntax incantation for determining what is a prerelease.
2023-03-20 17:38:20 -05:00
Dustin Howett
e1079d8f55 winget: use the correct fork-user 2023-03-20 11:15:27 -05:00
Mike Griese
b9248fa903 One process to rule them all (#14843)
## Summary

_In the days of old, the windows were sundered, each with its own
process, like the scattered stars in the sky. But a new age hath dawned,
for all windows now reside within a single process, like the bright gems
of a single crown._
_And lo, there came the `WindowEmperor`, a new lord to rule over the
global state, wielding the power of hotkeys and the beacon of the
notification icon. The `WindowManager` was cast aside, no longer needed
to seek out other processes or determine the `Monarch`._
_Should the `WindowEmperor` determine that a new window shall be raised,
it shall set forth a new thread, born from the ether, to govern this new
realm. On the main thread shall reside a message loop, charged with the
weighty task of preserving the global state, guarded by hotkeys and the
beacon of the notification icon._
_Each window doth live on its own thread, each guarded by the new
`WindowThread`, a knightly champion to hold the `TerminalWindow`,
`AppHost`, and `IslandWindow` in its grasp. And so the windows shall run
free, no longer burdened by their former ways._


All windows are now in a single process, rather than in one process per
window. We'll add a new `WindowEmperor` class to manage global state
such as hotkeys and the notification icon. The `WindowManager` has been
streamlined and no longer needs to connect to other processes or
determine a new `Monarch`. Each window will run on its own thread, using
the new `WindowThread` class to encapsulate the thread and manage the
`TerminalWindow`, `AppHost`, and `IslandWindow`.


* Related to #5000
* Related to #1256

## Windows Terminal Process Model 3.0

Everything is now one process. All the windows for a single Terminal
instance live in a singular Terminal process. When a new terminal
process launches, it will still attempt to communicate with an existing
one. If it finds one, it'll pass the commandline to that process and
exit. Otherwise, it'll become the "monarch" and create a new window.

We'll introduce a new abstraction here, called the `WindowEmperor`.
`Monarch` & `Peasant` will still remain, for facilitating cross-window
communication. The Emperor will allow us to have a single dedicated
class for all global state, and will now always represent the "monarch"
(rather than our previously established non-deterministic monarchy to
elevate a random peasant to the role of monarch). We still need to do a
very minimal amount of x-proc calls. Namely, one right on startup, to
see if another `Terminal.exe` was already running. If we find one, then
we toss our commandline at it and bail. If we don't, then we need to
`CoRegister` the Monarch still, to prepare for subsequent launches to
send commands to us.

`WindowManager` takes the most changes here. It had a ton of logic to
redundantly attempt to connect to other monarchs of other processes, or
elect a new one. It doesn't need to do any of that anymore, which is a
pretty dramatic change to that class.

This creates the opportunity to move some lifetime management around.
We've played silly games in the past trying to have individual windows
determine if they're the singular monarch for global state.
`IslandWindow`s no longer need to track things like global hotkeys or
the notification icon. The emperor can do that - there's only ever one
emperor. It can also own a singular copy of the settings model, and hand
out references to each other thread.

Each window lives on separate threads. We'll need to separately
initialize XAML islands for each thread. This is totally fine, and
actually supported these days. We'll use a new class called
`WindowThread` to encapsulate one of these threads. It'll be responsible
for owning the `TerminalWindow`, `AppHost` and `IslandWindow` for a
single thread.

This introduces new classes of bugs we'll need to worry about. It's now
easier than ever to have "wrong thread" bugs when interacting with any
XAML object from another thread. A good case in point - we used to stash
a `static` `Brush` in `Pane`, for the color of the borders. We can't do
that anymore! The first window will end up stashing a brush from its
thread. So now when a second window starts, the app explodes, because
the panes of that window try to draw their borders using a brush from
the wrong thread.

_Another fun change_: The keybinding labels of the command palette.
`TerminalPage` is the thing that ends up expanding iterable `Command`s.
It does this largely with copies - it makes a new `map`, a new `vector`,
copies the `Command`s over, and does the work there before setting up
the cmdpal.
Except, it's not making a copy of the `Command`s, it's making a copy of
the `vector`, with winrt objects all pointing at the `Command` objects
that are ultimately owned by `CascadiaSettings`.
This doesn't matter if there's only one `TerminalPage` - we'll only ever
do that once. However, now there are many Pages, on different threads.
That causes one `TerminalPage` to end up expanding the subcommands of a
`Command` while another `TerminalPage` is ALSO iterating on those
subcommands.

_Emperor message window_: The Emperor will have its own HWND, that's
entirely unrelated to any terminal window. This window is a
`HWND_MESSAGE` window, which specifically cannot be visible, but is
useful for getting messages. We'll use that to handle the notification
icon and global hotkeys. This alleviates the need for the IslandWindow
to raise events for the tray icon up to the AppHost to handle them. Less
plumbing=more good.

### Class ownership diagram

_pretend that I know UML for a second_:

```mermaid
classDiagram
    direction LR
    class Monarch
    class Peasant
    class Emperor
    class WindowThread
    class AppHost

    Monarch "1" --o "*" Peasant: Tracks
    Emperor --* "1" AppLogic: 
    Monarch <..> "1" Emperor
    Peasant "1" .. "1" WindowThread
    Emperor "1" --o "*" WindowThread: Tracks
    WindowThread --* AppHost
    AppHost --* IslandWindow
    AppHost --* TerminalWindow
    TerminalWindow --* TerminalPage
```

* There's still only one `Monarch`. One for the Terminal process.
* There's still many `Peasant`s, one per window.
* The `Monarch` is no longer associated with a window. It's associated
with the `Emperor`, who maintains _all_ the Terminal windows (but is not
associated with any particular window)
* It may be relevant to note: As far as the `Remoting` dll is concerned,
it doesn't care if monarchs and peasants are associated with windows or
not. Prior to this PR, _yes_, the Monarch was in fact associated with a
specific window (which was also associated with a window). Now, the
monarch is associated with the Emperor, who isn't technically any of the
windows.
* The `Emperor` owns the `App` (and by extension, the single `AppLogic`
instance).
* Each Terminal window lives on its own thread, owed by a `WindowThread`
object.
* There's still one `AppHost`, one `IslandWindow`, one `TerminalWindow`
& `TerminalPage` per window.
* `AppLogic` hands out references to its settings to each
`TerminalWindow` as they're created.

### Isolated Mode

This was a bit of a tiny brainstorm Dustin and I discussed. This is a
new setting introduced as an escape watch from the "one process to rule
them all" model. Technically, the Terminal already did something like
this if it couldn't find a `Monarch`, though, we were never really sure
if that hit. This just adds a setting to manually enable this mode.

In isolated mode, we always instantiate a Monarch instance locally,
without attempting to use the `CoRegister`-ed one, and we _never_
register one. This prevents the Terminal from talking with other
windows.
* Global hotkeys won't work right
* Trying to run commandlines in other windows (`wt -w foo`) won't work
* Every window will be its own process again
* Tray icon behavior is left undefined for now.
* Tab tearout straight-up won't work.

### A diagram about settings

This helps explain how settings changes get propagated

```mermaid
sequenceDiagram
    participant Emperor
    participant AppLogic
    
    participant AppHost
    participant TerminalWindow
    participant TerminalPage

    Note Right of AppLogic: AL::ReloadSettings
    AppLogic ->> Emperor: raise SettingsChanged
    Note left of Emperor: E::...GlobalHotkeys
    Note left of Emperor: E::...NotificationIcon
    AppLogic ->> TerminalWindow: raise SettingsChanged<br>(to each window)
    AppLogic ->> TerminalWindow: 
    AppLogic ->> TerminalWindow: 
    Note right of TerminalWindow: TW::UpdateSettingsHandler
    Note right of TerminalWindow: TW::UpdateSettings
    TerminalWindow ->> TerminalPage: SetSettings
    TerminalWindow ->> AppHost: raise SettingsChanged
    Note right of AppHost: AH::_HandleSettingsChanged
```
2023-03-17 17:59:35 -05:00
sitiom
bee22f3ec8 Add a Winget Releaser workflow (#14965)
[The winget-releaser action] automatically generates manifests for the
[Winget Community Repository] and submits them.

I suggest adding Dependabot to keep the action up to date. There were
many cases where the action was failing due to an outdated version.

Closes #14795

[The winget-releaser action]:
https://github.com/vedantmgoyal2009/winget-releaser
[Winget Community Repository]: https://github.com/microsoft/winget-pkgs
2023-03-17 17:57:42 -05:00
Dustin L. Howett
b6bb3e0a80 Enable the Hybrid CRT for all C++ projects (#15010)
The less we need the C++ runtime, the better.

I measured this as growing our package by a fair amount...
but less than the size of XamlHost and all the forwarders combined.

Reducing our dependency surface makes us easier to deploy and more
reliable.

_as of 1.17 (2022-10)_

| **File**                | **Before** | **After** |        **Delta** |
| ----------------------- | ----------:| ---------:| ----------------:|
| `OpenConsole`           |  1,273,344 | 1,359,360 |   +86,016 (84kb) |
| `TerminalApp`           |  2,037,248 | 2,120,704 |   +83,456 (82kb) |
| `TerminalControl`       |  1,412,608 | 1,502,720 |   +90,112 (88kb) |
| `TerminalSettingsModel` |  1,510,912 | 1,621,504 | +110,592 (108kb) |
| `wt`                    |     97,280 |   122,368 |   +25,088 (25kb) |
| `WindowsTerminal`       |    508,928 |   575,488 |   +66,560 (65kb) |
| **MSIX Overall**        |  6,488,301 | 6,799,017 | +310,716 (303kb) |
2023-03-17 17:12:32 -05:00
Mike Griese
c5c15e86f3 Clearly differentiate running elevated vs. drag/drop breaking (#14946)
Credit where credit is due - @jboelter did literally all the hard work.

I just separated this out to two elements:
* Are we running elevated?
* Can we drag drop?

As we learned in #7754, the builtin administrator _can_ drag drop. But
critically, they are also running as admin! The way we had this logic
before, we're treat them as unelevated, because we had been overloading
the meaning here.

This splits these into two separate functions. Comes with the added
benefit of re-adding the elevation shield to the Terminal window for
users with UAC disabled (which was missing before) (and can _still_ be
disabled).

Closes #13928

Tested on a Win10 VM with `EnableLua=0`
2023-03-17 17:01:37 -05:00
Leonard Hecker
00af187a97 Fix console aliases not working (#14991)
#14745 contains two regressions related to console alias handling:
* When `ProcessAliases` expands the backup buffer into (an) aliased
  command(s) it changes the `_bytesRead` field of `COOKED_READ_DATA`,
  requiring us to re-read it and reconstruct the `input` string-view.
* Multiline aliases are read line-by-line whereas #14745 didn't treat
  them any different from regular single-line inputs.

## Validation Steps Performed
In `cmd.exe` run
```
doskey test=echo foo$Techo bar$Techo baz
test
```
The output should look exactly like this:
```
C:\>doskey test=echo foo$Techo bar$Techo baz

C:\>test
foo

C:\>bar

C:\>baz

C:\>
```
2023-03-17 13:43:44 -07:00
James Holderness
2810155046 Add support for querying the DECAC settings (#14990)
This PR adds support for querying the color indices set by the `DECAC`
control, using the existing `DECRQSS` implementation.

## References and Relevant Issues

The initial `DECRQSS` support was added in PR #11152.
The `DECAC` functionality was added in PR #13058, but at the time we
didn't know how to format the associated `DECRQSS` query.

## Detailed Description of the Pull Request / Additional comments

For most `DECRQSS` queries, the setting being requested is identified by
the final characters of its escape sequence. However, for the `DECAC`
settings, you also need to include a parameter value, to indicate which
color item you're querying.

This meant we needed to extend the `DECRQSS` parser, so I also took this
opportunity to ensure we correctly parsed any parameter prefix chars. We
don't yet support any setting requiring a prefix, but this makes sure we
don't respond incorrectly if an app does query such a setting.

## Validation Steps Performed

Thanks to @al20878, we've been able to test how these queries are parsed
on a real VT525 terminal, and I've manually verified our implementation
matches that behavior.

I've also extended the existing `DECRQSS` unit test to confirm that we
are responding to the `DECAC` queries as expected.

Closes #13091
2023-03-17 14:16:47 -05:00
Mike Griese
5c9f756891 Properly configure the project dependencies for TerminalAzBridge (#15008)
I don't think this is the resolution for #14581, but this can't hurt. These deps were using the wrong GUIDs
2023-03-17 13:59:35 -05:00
Mike Griese
7383b260e1 Add support for a right-click context menu (#14775)
Experimental for now. `experimental.rightClickContextMenu`, a
per-profile setting. Long term we want to enable full mouse bindings, at
which point this would be replaced.

Closes #3337

This adds **two** context menus to the `TermControl` - one for
right-clicking with a selection, and one without. The implementation is
designed to follows the API experience of the context menu on something
like a [`RichEditBox`](winui2gallery://item/RichEditBox). The hosting
application adds a handler for the menu's `Opening` event, and appends
whatever items it wants at that time.

So `TermControl` only implements a few "actions" by default - copy,
past, find. `TerminalApp` is then responsible for adding anything else
it needs. Right now, those actions are:
* Duplicate tab
* Duplicate pane
* Close Tab
* Close pane

Screenshots in
https://github.com/microsoft/terminal/pull/14775#issuecomment-1415737393
2023-03-17 13:54:10 -05:00
Mike Griese
4ca19623ca Fix some simple C# linter warnings (#15011)
Azure Devops jumps to these as the first "error" when you open a failing
build. But these are warnings, not errors. So you're left hunting for
the real error. _If only someone had scrollbar marks for indicating
lines with error messages..._

May as well clean them up.
2023-03-17 13:52:23 -05:00
Ian O'Neill
51661487c2 Reload environment variables by default; add setting to disable (#14999)
Adds a global setting `compatibility.reloadEnvironmentVariables` with a
default value of `true`. When set, during connection creation a new
environment block will be generated to ensure it has the latest
environment variables.

Closes #1125

Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
2023-03-17 13:50:18 -05:00
Mike Griese
65640f6fe3 Allow wsl$ in file URIs; generally allow all URI schemes (#14993)
Does two things related to URLs emitted via OSC8. 

* Allows `wsl$` and `wsl.localhost` as the hostname in `file://` URIs
* Generally allows _all_ URIs that parse as a URI. 

The relevant security comments: https://github.com/microsoft/terminal/pull/7526#issuecomment-764160208
> this doesn't let a would-be attacker specify command-line arguments (ala "cmd.exe /s /c do_a_bad_thing") (using somebody else's reputation to cause mayhem)
> 
> `ShellExecute` de-elevates because it bounces a launch request off the shell
> 
> "Works predictably for 15% of applications" (h/t to PhMajerus' AXSH, and other on-Windows requestors) is better in so many ways than "Works for 0% of applications", in my estimation. Incremental progress 😄 while we work on features that'll make it even more broadly applicable.

Closes #10188
Closes #7562
2023-03-17 11:29:42 -07:00
Mike Griese
5b434dcda4 Split AppLogic into "App logic" and "Window logic" (#14825)
_And so begins the first chapter in the epic tale of the Terminal's tab
tear-out. This commit, though humble in its nature, shall mark the
beginning of a grand journey._
_This initial offering, though small in its scope, doth serve to divide
the code that currently resides within TerminalPage and AppLogic, moving
it unto a new entity known as TerminalWindow. In the ages to come, these
classes shall take on separate responsibilities, each with their own
purpose._
_The AppLogic shall hold sway over the entire process, shared among all
Terminal windows, while the AppHost, TerminalWindow, and TerminalPage
shall rule over each individual window._
_This pull request prepares the way for the future, moving state that
pertains to the individual windows into the TerminalWindow. This is a
task of great labor, for it requires moving much code, but the end
result shall bring greater organization to the codebase._
_And so the stage is set, for in the next pull request, the Process
Model v3 shall be revealed, unifying all Terminal windows into a single
process, a grand accomplishment indeed._

_courtesy of G.P.T. Tolkien_

<details>
<summary>Or, as I wrote it originally. </summary>

This is the first of the commits in the long saga which will culminate
in tab tear-out for the Terminal.

This the most functionally trivial of the PRs. It mostly just splits up
code that's currently in TerminalPage & AppLogic, and moves it into a
new class `TerminalWindow`. In the future, these classes will separate
responsibility as such:
* There will be one `AppLogic` per process, shared across all Terminal
windows.
* There will be one `AppHost`, `TerminalWindow`, and `TerminalPage` for
each individual window in the process.

This PR prepares for that by moving some state that's applicable to
_individual windows_ into `TerminalWindow`. This is almost exclusively a
code moving PR. There should be minimal functional changes.

</details>


In the next PR, we'll introduce the actual "Process Model v3", merging
all Terminal windows into a single terminal process.

Related to #5000. See
https://github.com/Microsoft/terminal/issues/5000#issuecomment-1407110045
for my current todo list.
Related to #1256. 

These commits are all artificially broken down pieces. Honestly, I don't
want to really merge them till they're all ready, so we know that the
work e2e. This my feigned attempt to break it into digestable PRs.

Lightly manually tested, things seem to still all work? Most of this
code was actually written in deeper branches, it was only today I
realized it all needed to come back to this branch.

* [x] The window persistence fishy-ness of the subsequent PR isn't
present here. So that's something.
* [x] Localtests still pass

### Detailed description

> Q: Does `AppLogic` not keep track of its windows?

Sure doesn't! I didn't think that was something it needed to know.

>Q: Why does `TerminalWindow` (per-window) have access to the
commandline args (per-process)

It's because it's _not_ per process. Commandline args _are_ per-window.
Consider - you launch the Terminal, then run a `wt -w -1 -- foo`. That
makes its own window. In this process, yes. But that new window has its
own commandline args, separate from the ones that started the original
process.
2023-03-17 09:17:11 -05:00
Mike Griese
8c17475a9f Rebuild the profile nav via MenuItemsSource; mitigate a crash (#14630)
Directly manipulating the `NavigationView::MenuItems` vector is bad. If
you do that, you're gonna get crashes, in WinUI code for `Measure`.
However, a WinUI PR (below) gave me an idea: Changing
`NavigationView::MenuItemsSource` will wholly invalidate the entirety of
the nav view items, and that will avoid the crash.

This code does that. It's a wee bit janky, but it works. 

Closes #13673

_might_ affect #12333, need to try and repro. 

See also:
* #9273
* #10390
* https://github.com/microsoft/microsoft-ui-xaml/issues/6302
* https://github.com/microsoft/microsoft-ui-xaml/pull/3138, which was
the fix for https://github.com/microsoft/microsoft-ui-xaml/issues/2818
2023-03-16 15:41:46 -05:00
Leonard Hecker
6c80390de7 Fix offset calculation in the outlines shader (#14971)
The `Sample` method has an offset parameter which we can use here.
The result is not identical to the old shader, as the older shader
used the height of the terminal for drawing horizontal edges and so
the result looked way fatter than it was seemingly originally intended.
On my 150% scale display I found an offset of +/- 2px to produce an
acceptable result, although in the future it might be worthwhile to
make the offset dependent on the UI scale.

Closes #14953
2023-03-16 15:21:32 -05:00
James Holderness
7562c81066 Fix audit failures in TerminalCore (#15002)
## Summary of the Pull Request

This fixes a couple of audit failures in `TerminalCore` where the
compiler was complaining about functions that should have been declared
as `noexcept`.

These failures have actually existed for a while, but you'd only see
them if you ran the audit build locally. They only recently started
showing up on the CI build server - I'm guessing because the compiler
there has now been upgraded.

## Validation Steps Performed

Compiled the audit build locally and it no longer fails.
2023-03-16 17:51:53 +01:00
James Holderness
931aa8c87e Add support for the DECRQCRA checksum report (#14989)
This PR implements the `DECRQCRA` escape sequence, which lets you
request a checksum of a portion of the screen. This is most useful in
automated testing to verify that the generated screen content is what it
was expected to be. 

For now this functionality is gated behind a feature flag which is only
enabled for dev builds.

## Detailed Description of the Pull Request / Additional comments

I've done my best to match the DEC checksum algorithm as closely as
possible, which we've determined by testing on a real VT525 terminal
(many thanks to @al20878 for that).

The checksum is an unsigned 16-bit value that starts off at zero, and
from which you then subtract the ordinal value of every character in the
selected range. It's also affected by the rendition attributes in the
selected cells.

* Bold/Intense - subtract 0x80
* Blinking - subtract 0x40
* Reverse video - subtract 0x20
* Underlined - subtract 0x10
* Invisible - subtract 0x08
* Protected - subtract 0x04
* Background color - subtract the color index
* Foreground color - subtract the color index * 0x10

I should note that our ordinal calculation only matches DEC for the
characters in the ASCII and Latin-1 range, because the original
algorithm predates Unicode. If we want to support the other character
sets correctly we'll need custom mapping tables, but I didn't think that
was essential for now.

It's also worth mentioning that we don't handle "empty" cells correctly,
but that's not the fault of the checksum calculation - it's just that
our default fill character is a space rather than a `NUL`.

## Validation Steps Performed

I've manually compared our implementation against the tests results that
@al20878 got from the VT525, and confirmed that we match as well as was
expected (i.e. taking into account the limitations mentioned above).

I've also added a few basic unit tests that verify we're generating the
expected checksums for the various renditions and color attributes.

Closes #14974
2023-03-14 11:45:45 -05:00
Ian O'Neill
eb871bf8c0 Create til::env to help with refreshing environment variables (#14839)
Adds a helper that replicates how the `RegenerateUserEnvironment()`
method in `shell32.dll` behaves.

* Raises #12516 from the dead.
* Half of #1125

Co-authored-by: Michael Niksa <miniksa@microsoft.com>
2023-03-13 18:10:38 -05:00
James Holderness
fe2220e07b Ensure that delayed EOL wrap is reset when necessary (#14936)
When a character is written in the last column of a row, the cursor
doesn't move, but instead sets a "delayed EOL wrap" flag. If another
character is then output while that flag is still set, the cursor moves
to the start of the next line, before writing to the buffer.

That flag is supposed to be reset when certain control sequences are
executed, but prior to now we haven't always handled that correctly.
With this PR, we should be resetting the flag appropriately in all the
places that it's expected to be reset.

For the most part, I'm following the DEC STD 070 reference, which lists
a bunch of operations that are intended to reset the delayed wrap flag:

`DECSTBM`, `DECSWL`, `DECDWL`, `DECDHL`, setting `DECCOLM` and `DECOM`,
resetting `DECCOLM`, `DECOM`, and `DECAWM`, `CUU`, `CUD`, `CUF`, `CUB`,
`CUP`, `HVP`, `BS`, `LF`, `VT`, `FF`, `CR`, `IND`, `RI`, `NEL`, `ECH`,
`DCH`, `ICH`, `EL`, `DECSEL`, `DL`, `IL`, `ED`, and `DECSED`.

We were already resetting the flag for any of the operations that
performed cursor movement, since that always triggers a reset for us.
However, I've now also added manual resets in those ops that weren't
moving the cursor.

Horizontal tabs are a special case, though. Technically the standard
says they should reset the flag, but most DEC terminals never followed
that rule, and most modern terminals agree that it's best for a tab to
leave the flag as it is. Our implementation now does that too.

But as mentioned above, we automatically reset the flag on any cursor
movement, so the tab operation had to be handled as a special case,
saving and restoring the flag when the cursor is updated.

Another flaw in our implementation was that we should have been saving
and restoring the flag as part of the cursor state in the `DECSC` and
`DECRC` operations. That's now been fixed in this PR too.

I should also mention there was a change I had to make to the conpty
renderer, because it was sometimes using an `EL` sequence while the
terminal was in the delayed EOL wrap state. This would reset the flag,
and break subsequent output, so I've now added a check to prevent that
from happening.

## Validation Steps Performed

I've added some unit tests that confirm the operations listed above are
now resetting the delayed EOL wrap as expected, and I've expanded the
existing `CursorSaveRestore` test to make sure the flag is being saved
and restored correctly.

I've also manually confirmed that the test case in issue #3177 now
matches XTerm's output, and I've confirmed that the results of the
wraptest script[^1] now match XTerm's results.

[^1]: https://github.com/mattiase/wraptest/

Closes #3177
2023-03-03 18:57:51 -06:00
Dustin L. Howett
3e7e8d59f2 Switch to the new Helix queues (#14933)
The old ones are pushing up daisies.
2023-03-03 15:26:39 -06:00
Leonard Hecker
599b550817 Remove TranslateUnicodeToOem and all related code (#14745)
The overarching intention of this PR is to improve our Unicode support.
Most
of our APIs still don't support anything beyond UCS-2 and DBCS
sequences.
This commit doesn't fix the UTF-16 support (by supporting surrogate
pairs),
but it does improve support for UTF-8 by allowing longer `char`
sequences.

It does so by removing `TranslateUnicodeToOem` which seems to have had
an almost
viral effect on code quality wherever it was used. It made the
assumption that
_all_ narrow glyphs encode to 1 `char` and most wide glyphs to 2
`char`s.
It also didn't bother to check whether `WideCharToMultiByte` failed or
returned
a different amount of `char`s. So up until now it was easily possible to
read
uninitialized stack memory from conhost. Any code that used this
function was
forced to do the same "measurement" of narrow/wide glyphs, because _of
course_
it didn't had any way to indicate to the caller how much memory it needs
to
store the result. Instead all callers were forced to sorta replicate how
it
worked to calculate the required storage ahead of time.
Unsurprisingly, none of the callers used the same algorithm...

Without it the code is much leaner and easier to understand now. The
best
example is `COOKED_READ_DATA::_handlePostCharInputLoop` which used to
contain 3
blocks of _almost_ identical code, but with ever so subtle differences.
After
reading the old code for hours I still don't know if they were relevant
or not.
It used to be 200 lines of code lacking any documentation and it's now
50 lines
with descriptive function names. I hope this doesn't break anything, but
to
be honest I can't imagine anyone having relied on this mess in the first
place.

I needed some helpers to handle byte slices (`std::span<char>`), which
is why
a new `til/bytes.h` header was added. Initially I wrote a `buf_writer`
class
but felt like such a wrapper around a slice/span was annoying to use.
As such I've opted for freestanding functions which take slices as
mutable
references and "advance" them (offset the start) whenever they're read
from
or written to. I'm not particularly happy with the design but they do
the job.

Related to #8000
Fixes #4551
Fixes #7589
Fixes #8663

## Validation Steps Performed
* Unit and feature tests 
* Far Manager 
* Fixes test cases in #4551, #7589 and #8663 
2023-02-28 14:55:18 -06:00
Leonard Hecker
cf87590b31 Address remaining review feedback for #14255 (#14931)
This just removes some leftover code that I forgot to remove before the merge.
Additionally I forgot to add a newly added file to our `sources` build file.
2023-02-28 19:50:13 +01:00
Leonard Hecker
814e44bf45 AtlasEngine: Fix calculation of advanceScale (#14883)
Woops. Closes #14878

## Validation Steps Performed
* Font Family: Iosevka Term (v19.0.1)
* Font Size: 11pt (or 10px cell height in conhost)
* Display Scale: 100%
* "--------------" leaves no gap between the text and the cursor 
2023-02-21 15:23:38 -06:00
Dustin L. Howett
a5fc302716 Correctness: Remove JsonUtils and IconConverter's 2-phase lookup bugs (#14870)
Our templates were declared in the wrong order in JsonUtils, so all we
needed to do was reorder them. The tests bear this out.

This allows us to disable two-phase template name lookup. I also fixed a
minor issue that resulted in the inclusion of too many copies of
expandIconPath.
2023-02-17 16:26:30 -08:00
Dustin L. Howett
2cd280eeef Move to CppWinRT 2.0.230207.1 (#14869)
Interesting things we could do after this:
- remove all `InitializeComponent` calls - they do it automatically
- have some Clang support (!)
- use `std::optional`<->`IReference` automatic binding
- use `std::format` support (!) for json/uri/hostname/http stuff/all
`IStringable`s
- potentially move to `/await:strict` for C++20 coroutines

I've also fixed up a couple ambiguities introduced by this change.
2023-02-17 16:19:47 -08:00
Dustin L. Howett
c4c046595e Fix a number of minor correctness issues that Clang flagged (#14871)
* `lld-link` is more strict about the casing of keywords in `.def` files
* `[[nodiscard]]` must come before `virtual` and `static` qualifiers
* `precomp.h` is never to be included with `<>`
* We were calling the jsoncpp constructors directly (oops) as functions
(oops)
* ClipboardTests constructed `KeyEvent`s by copy instead of directly
* While we can `await` a `Dispatcher`, it's clearer to add `resume_foreground`
2023-02-17 16:13:13 -08:00
Dustin L. Howett
e1145c362f Add a proper reference from TermCore to MidiAudio (#14868)
It was just by luck that TerminalCore usually built after MidiAudio
2023-02-17 16:12:10 -08:00
Leonard Hecker
9dcdcac0bb Ignore CHAR_INFO trailers during WriteConsoleOutput (#14840)
#13626 contains a small "regression" compared to #13321:
It now began to store trailers in the buffer wherever possible to allow
a region
of the buffer to be backed up and restored via Read/WriteConsoleOutput.
But we're unfortunately still ill-equipped to handle anything but UCS-2
via
WriteConsoleOutput, so it's best to again ignore trailers just like in
#13321.

## Validation Steps Performed
* Added unit test 
2023-02-15 17:40:24 -06:00
Leonard Hecker
6a8bba96b2 Update ControlsV2 scrollbar template (#14846)
This commit updates our scrollbar template to microsoft-ui-xaml at ceeab5f.
This incorporates the bug fix for MSFT-39442675.
2023-02-15 17:36:40 -06:00
Dustin L. Howett
c08742ff18 Consolidate NTSTATUS and remove INLINE_NSTATUS_FROM_WIN32 (#14822)
This commit makes the following project-wide changes/replacements as a
first step in cleaning up our use of `NTSTATUS`.

* Rewriting any uses of `NTSTATUS_FROM_WIN32` that were vulnerable to multiple evaluation bugs
  * This is required because the macro version of `NTSTATUS_FROM_WIN32` evaluates its argument twice
* Removing all our local redefinitions of `NTSTATUS` in favor of that of `winternl.h`
  * Because of this, we got to (had to?) remove some old transclusions from `conddkrefs.h`
* `NT_SUCCESS` (ours) -> `SUCCEEDED_NTSTATUS` (wil)
* `VERIFY_IS_TRUE(NT_SUCCESS())` (overly elaborate) -> `VERIFY_NT_SUCCESS` (WEX)
* `VERIFY_SUCCESS_NTSTATUS` (ours) -> `VERIFY_NT_SUCCESS` (WEX)
* `!SUCCEEDED_NTSTATUS` -> `FAILED_NTSTATUS`
* One bad use of S_OK as an NTSTATUS -> `STATUS_SUCCESS`
* Removing `NTSTATUS` from any projects that do not use it
2023-02-14 15:48:24 -06:00
Leonard Hecker
b6e6dd861d Implement cell size customizations (#14255)
Does what it says in the title. After this commit you can customize the height
and width of the terminal's cells. This commit supports parts of CSS'
`<length-percentage>` data type: Font-size relative sizes as multiples (`1.2`),
percentage (`120%`), or advance-width relative (`1.2ch`), as well as absolute
sizes in CSS pixels (`px`) or points (`pt`).

This PR is neither bug free in DxEngine, nor in AtlasEngine.
The former fails to implement glyph advance corrections (for instance #9381),
as well as disallowing glyphs to overlap rows. The latter has the same
overlap issue, but more severely as it tries to shrink glyphs to fit in.

Closes #3498
Closes #14068

## Validation Steps Performed
* Setting `height` to `1` creates 12pt tall rows 
* Setting `height` to `1ch` creates square cells 
* Setting `width` to `1` creates square cells 
* Setting `width` or `height` to `Npx` or `Npt` works 
* Trailing zeroes are trimmed properly during serialization 
* Patching the PR to allow >100 line heights and entering "100.123456"
  displays 6 fractional digits 
2023-02-14 22:42:14 +01:00
PankajBhojwani
e4bba3cd9a Pass the window root to the profile page views, instead of the view model (#14816)
## Summary of the Pull Request
Let the profile pages' views have access to the window root, rather than the `ProfileViewModel`. The window root is passed along when the page is navigated to.

## Validation Steps Performed
Clicking `Browse` no longer crashes.

## PR Checklist
- [x] Closes #14808
2023-02-10 17:39:08 -06:00
Dustin L. Howett
9bab7d5d80 Reformat RegistrySerialization.cpp (#14824)
We had accidentally left clang-format turned off.
2023-02-10 16:52:07 -06:00
Marcel Wagner
143127d6c4 Update tab drop behavior to select dropped tab (#14787)
Dragging and dropping tabs now selects them

Closes #12473
2023-02-07 17:45:33 -06:00
Dustin L. Howett
4903cfd484 AzureConnection: remove our dependency on cpprestsdk (#14776)
This pull request removes, in full, our dependency on cpprestsdk. This
allows us to shed 500KiB-1.2MiB from our package off the top and enables
the following future investments:

- Removal of the App CRT forwarders to save an additional ~500KiB
- Switching over to the HybridCRT and removing our dependency on _any
  CRT_.

cpprest was built on my dev box two or so years ago, and is in _utter_
violation of our compliance guidelines on SBOM et al.

In addition, this change allows us to use the proxy server configured
in Windows Settings.

I did this in four steps (represented roughly by the individual commits):

1. Switch from cpprest's http_client/json to Windows.Web.Http and
   Windows.Data.Json
2. Switch from websocketpp to winhttp.dll's WebSocket implementation¹
3. Remove all remaining utility classes
4. Purge all dependencies from all projects and scripts on cpprest.

I also took this opportunity to add a feature flag that allows Dev
builds to run AzureConnection in-process.

¹ Windows.Networking.Sockets' API is so unergonomic that it was simply
infeasible (and also _horrible_) to use it.

## Validation Steps

I've run the Azure Connection quite a bit inproc.

Closes #4575.
Might be related to #5977, #11714, and with the user agent thing maybe #14403.
2023-02-07 15:13:10 -06:00
Leonard Hecker
42e8de3b52 Replace gsl::byte/span with std (#14763)
This is a rather trivial changeset. Now that these two are present in the
`std` namespace there's no reason for us to continue using the `gsl` ones.
Additionally this ensures future compatibility with other 3rd party libraries.
2023-02-02 13:24:13 -08:00
Leonard Hecker
8100d24bd0 Minor improvements for SplitToOem (#14746)
When working on #14745 I noticed that `SplitToOem` was in a bit of a poor state
as well. Instead of simply iterating over its `deque` argument and writing the
results into a new `deque` it used `pop` to advance the head of both queues.
This isn't quite exception safe and rather bloaty. Additionally there's no need
to call `WideCharToMultiByte` twice on each character if we know that the most
verbose encoding is UTF-8 which can't be any more than 4 chars anyways.

Related to #8000.

## PR Checklist
* 2 unit tests cover this 
2023-02-02 13:14:51 -08:00
Leonard Hecker
ddc349be81 Make KeyEvent char data a little less confusing (#14747)
When working on #14745 I found `KeyEvent`s a little hard to read in the
debugger. I noticed that this is because of sign extension when converting
`char`s to `wchar_t`s in `KeyEvent::SetCharData`.
2023-02-02 13:12:38 -08:00
James Holderness
282c583731 Make all console output modes more strictly buffer state (#14735)
The original console output modes were considered attributes of the
buffer, while later additions were treated as global state, and yet both
were accessed via the same buffer-based API. This could result in the
reported modes being out of sync with the way the system was actually
behaving, and a call to `SetConsoleMode` without updating anything could
still trigger unpredictable changes in behavior.

This PR attempts to address that problem by making all modes part of the
buffer state, and giving them predictable default values.

While this won't solve all the tmux layout-breaking issues in #6987, it
does at least fix one case which was the result of an unexpected change
in the `DISABLE_NEWLINE_AUTO_RETURN` mode.

All access to the output modes is now done via the `OutputMode` field in
`SCREEN_INFORMATION`. The fields that were tracking global state in the
`Settings` class (`_fAutoReturnOnNewline` and  `_fRenderGridWorldwide`)
have now been removed.

We still have a global `_dwVirtTermLevel` field, though, but that now
serves as a default value for the `ENABLE_VIRTUAL_TERMINAL_PROCESSING`
mode when creating a new buffer. It's enabled for conpty mode, and when
the VT level in the registry is not 0. That default doesn't change.

For the VT alternate buffer, things works slightly differently, since
there is an expectation that VT modes are global. So when creating an
alt buffer, we copy the current modes from the main buffer, and when
it's closed, we copy them back again.

## Validation Steps Performed

I've manually confirmed that this fixes the problem described in issue
#14690. I've also added a basic feature test that confirms the modes are
initialized as expected when creating new buffers, and changes to the
modes in one buffer do not impact any other buffers.

Closes #14690
2023-01-27 20:38:37 +00:00
Dustin L. Howett
fc960e3327 Generalize OpenConsoleProxy's HybridCRT logic (#14733)
This pull request moves the Hybrid CRT logic out of the Host.Proxy
project and makes it available for all other projects in our solution.
2023-01-27 19:17:30 +00:00
Dustin L. Howett
6a610334af When generating a stacked changelog, note which branch/es contain a commit (#14728)
New-TerminalStackedChangelog used to generate logs that looked like this:

```
* [3] A commit that was seen 3 times
* A commit that was only seen once
* [2] Some other commit
```

Now it will generate logs that look like this:

```
   / base..branch-1
   |/ base..branch-2
   ||/ base..branch-3
* [XXX] A commit that was seen 3 times
* [ X ] A commit that was only seen once
* [XX ] Some other commit
```

This format is more expressive, as it indicates _which branches_ contain which commits.

As a reminder, my release note writing style starts with a stacked changelog. It's how I tell (1) which commits are in the new preview release only, (2) which commits are in the new preview and the new stable release and (3) which commits were already released in a previous stable release.

Changes from 1 get included in the new changelog, changes from 2 get included in both and changes from 3 get deleted because they have already been released.
2023-01-25 10:52:11 -08:00
Dustin Howett
7d0baa7946 Revert "Manually set the automation name of the default color scheme for screen reader (#14704)"
This reverts commit 47f38e31a1.
2023-01-23 19:01:49 -06:00
Carlos Zamora
a0e830cc1a [UIA] Dispatch a TextChanged event on new output (#14723)
For some reason, Windows Terminal stops dispatching UIA TextChanged events sometimes. There isn't a reliable repro for this bug.

However, under NVDA's logger, it appears that when the bug does occur, we still dispatch UIA notifications (which may be ignored by NVDA in some configurations). A "quick fix" here is to dispatch a TextChanged event if we're going to dispatch a notification. Since we're just enabling a flag, we won't send two events at once.

Closes #10911
2023-01-23 21:53:09 +00:00
Mike Griese
a4cf4e2761 Resize our ContentDialog's when the window resizes (#14722)
Major thanks to @dongle-the-gadget in https://github.com/microsoft/microsoft-ui-xaml/issues/3577#issuecomment-1399250405 for coming up with this workaround.

This PR will manually forward a `WM_SIZE` message to our `CoreWindow`, to trigger the `ContentDialog` to resize itself. 

We always closed these issues as dupes of the upstream one, so this doesn't actually close anything.
HOWEVER, these are the following issues that reported this bug:
- #2380
- #4463
- #5252
- #5810
- #6181
- #7113
- #7225
- #8245
- #8496
- #8643
- #9336
- #9563
- #5808
- #10351
- #10634
- #10995
- #11770
- #13796
2023-01-23 12:42:27 -06:00
Carlos Zamora
3dd40791c9 Ensure TermControl is not closing when firing UIA events (#14714)
The `SignalTextChanged` crash seems to be occurring due to the `TermControlAutomationPeer` being destructed by the time the UIA event is actually dispatched. Even though we're already checking if TCAP and TermControl still exist, it could be that the TermControl is being closed as text is being output.

The proposed fix here is to record when the closing process starts and exposing that information directly to the TCAP. If TCAP sees that we're in the process of closing, don't bother sending a UIA event.


Closes #13978
2023-01-21 15:48:33 +00:00
Dustin Howett
8f1960d0b4 version: bump to 1.18 on main 2023-01-20 15:24:08 -06:00
622 changed files with 52366 additions and 15386 deletions

View File

@@ -1,57 +1,25 @@
---
Language: Cpp
BasedOnStyle: Microsoft
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AllowAllArgumentsOnNextLine: true
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AllowAllConstructorInitializersOnNextLine: true
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortFunctionsOnASingleLine: All
AllowShortCaseLabelsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: Never
#AllowShortLambdasOnASingleLine: Inline
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterCaseLabel: true
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: true
AfterExternBlock: false
BeforeCatch: true
BeforeElse: true
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: false
BreakConstructorInitializers: AfterColon
BreakInheritanceList: AfterColon
ColumnLimit: 0
CommentPragmas: "suppress"
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DeriveLineEnding: true
DerivePointerAlignment: false
FixNamespaceComments: false
IncludeBlocks: Regroup
IncludeCategories:
@@ -63,35 +31,13 @@ IncludeCategories:
Priority: 2
- Regex: '.*'
Priority: 3
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: "BEGIN_TEST_METHOD_PROPERTIES|BEGIN_MODULE|BEGIN_TEST_CLASS|BEGIN_TEST_METHOD"
MacroBlockEnd: "END_TEST_METHOD_PROPERTIES|END_MODULE|END_TEST_CLASS|END_TEST_METHOD"
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
PointerAlignment: Left
ReflowComments: false
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Latest
TabWidth: 4
UseTab: Never

View File

@@ -100,6 +100,7 @@ TLDR
tokenizes
tonos
toolset
truthiness
tshe
ubuntu
uiatextrange

View File

@@ -34,7 +34,6 @@ DNE
DONTADDTORECENT
DWMSBT
DWMWA
DWMWA
DWORDLONG
endfor
ENDSESSION
@@ -55,6 +54,8 @@ GETMOUSEHOVERTIME
Hashtable
HIGHCONTRASTON
HIGHCONTRASTW
hinternet
HINTERNET
hotkeys
href
hrgn
@@ -158,6 +159,7 @@ rcx
REGCLS
RETURNCMD
rfind
RLO
ROOTOWNER
roundf
RSHIFT
@@ -212,8 +214,11 @@ userenv
USEROBJECTFLAGS
Viewbox
virtualalloc
vsnwprintf
wcsstr
wcstoui
WDJ
winhttp
winmain
winsta
winstamin
@@ -221,6 +226,7 @@ wmemcmp
wpc
WSF
wsregex
WWH
wwinmain
xchg
XDocument
@@ -246,3 +252,4 @@ xtree
xutility
YIcon
YMax
zwstring

View File

@@ -9,9 +9,11 @@ appxbundle
appxerror
appxmanifest
ATL
autoexec
backplating
bitmaps
BOMs
COMPUTERNAME
CPLs
cpptools
cppvsdbg
@@ -26,6 +28,7 @@ dotnetfeed
DTDs
DWINRT
enablewttlogging
HOMESHARE
Intelli
IVisual
libucrt
@@ -33,6 +36,7 @@ libucrtd
LKG
LOCKFILE
Lxss
makepri
mfcribbon
microsoft
microsoftonline
@@ -50,15 +54,19 @@ pgo
pgosweep
powerrename
powershell
priconfig
PRIINFO
propkey
pscustomobject
QWORD
regedit
resfiles
robocopy
SACLs
segoe
sdkddkver
Shobjidl
sid
Skype
SRW
sxs
@@ -71,6 +79,7 @@ tdbuildteamid
ucrt
ucrtd
unvirtualized
USERDNSDOMAIN
VCRT
vcruntime
Virtualization

View File

@@ -1,6 +1,6 @@
Anup
austdi
arkthur
austdi
Ballmer
bhoj
Bhojwani
@@ -31,8 +31,8 @@ jerrysh
Kaiyu
kimwalisch
KMehrain
KODELIFE
Kodelife
KODELIFE
Kourosh
kowalczyk
leonardder
@@ -61,6 +61,7 @@ oising
oldnewthing
opengl
osgwiki
Ottosson
pabhojwa
panos
paulcam
@@ -88,8 +89,8 @@ Wirt
Wojciech
zadjii
Zamor
Zamora
zamora
Zamora
zljubisic
Zoey
zorio

View File

@@ -109,8 +109,10 @@
^src/tools/integrity/packageuwp/ConsoleUWP\.appxSources$
^src/tools/lnkd/lnkd\.bat$
^src/tools/pixels/pixels\.bat$
^src/tools/RenderingTests/main.cpp$
^src/tools/texttests/fira\.txt$
^src/tools/U8U16Test/(?:fr|ru|zh)\.txt$
^src/types/ColorFix.cpp
^src/types/ut_types/UtilsTests.cpp$
^tools/ReleaseEngineering/ServicingPipeline.ps1$
ignore$

View File

@@ -9,6 +9,7 @@ ABCDEFGHIJ
abcdefghijk
ABCDEFGHIJKLMNO
abcdefghijklmnop
ABCDEFGHIJKLMNOPQRS
ABCDEFGHIJKLMNOPQRST
ABCG
ABE
@@ -18,11 +19,15 @@ BBBBBBBB
BBBBBCCC
BBBBCCCCC
BBGGRR
efg
EFG
EFGh
KLMNOQQQQQQQQQQ
QQQQQQQQQQABCDEFGHIJ
QQQQQQQQQQABCDEFGHIJKLMNOPQRS
QQQQQQQQQQABCDEFGHIJKLMNOPQRSTQQQQQQQQQ
QQQQQQQQQQABCDEFGHIJKLMNOPQRSTQQQQQQQQQQ
QQQQQQQQQQABCDEFGHIJPQRST
QQQQQQQQQQABCDEFGHIJPQRSTQQQQQQQQQQ
qrstuvwxyz
qwerty

View File

@@ -2,6 +2,7 @@ aabbcc
ABANDONFONT
abbcc
ABCDEFGHIJKLMNOPQRSTUVWXY
ABCF
abgr
abi
ABORTIFHUNG
@@ -37,10 +38,12 @@ ansicpg
ANSISYS
ANSISYSRC
ANSISYSSC
answerback
antialiasing
ANull
anycpu
APARTMENTTHREADED
APCA
APCs
APIENTRY
apiset
@@ -175,7 +178,6 @@ CConsole
CConversion
CCRT
cdd
CDeclaration
CEdit
CELLSIZE
cfae
@@ -193,7 +195,8 @@ chh
chk
CHT
Cic
CLA
cielab
Cielab
Clcompile
CLE
cleartype
@@ -257,6 +260,7 @@ condrv
conechokey
conemu
configurability
confusables
conhost
conime
conimeinfo
@@ -311,7 +315,6 @@ CPLINFO
cplusplus
CPPCORECHECK
cppcorecheckrules
cpprest
cpprestsdk
cppwinrt
CProc
@@ -332,7 +335,7 @@ Cspace
csrmsg
CSRSS
csrutil
cstyle
CSTYLE
CSwitch
CTerminal
CText
@@ -407,20 +410,25 @@ DECANM
DECARM
DECAUPSS
DECAWM
DECBI
DECBKM
DECCARA
DECCIR
DECCKM
DECCKSR
DECCOLM
DECCRA
DECCTR
DECDC
DECDHL
decdld
DECDMAC
DECDWL
DECEKBD
DECERA
DECFI
DECFRA
DECIC
DECID
DECINVM
DECKPAM
@@ -438,9 +446,12 @@ DECRC
DECREQTPARM
DECRLM
DECRPM
DECRQCRA
DECRQM
DECRQPSR
DECRQSS
DECRQTSR
DECRSPS
decrst
DECSACE
DECSASD
@@ -461,6 +472,7 @@ DECSTBM
DECSTGLT
DECSTR
DECSWL
DECTABSR
DECTCEM
DECXCPR
DEFAPP
@@ -480,7 +492,6 @@ defterm
DELAYLOAD
DELETEONRELEASE
Delt
demoable
depersist
deprioritized
deserializers
@@ -537,7 +548,6 @@ DSSCL
DSwap
DTest
DTTERM
DUMMYUNIONNAME
dup'ed
dvi
dwl
@@ -565,6 +575,7 @@ EDITTEXT
EDITUPDATE
edputil
Efast
efghijklmn
EHsc
EINS
EJO
@@ -581,6 +592,7 @@ ENU
ENUMLOGFONT
ENUMLOGFONTEX
enumranges
EOK
eplace
EPres
EQU
@@ -590,7 +602,6 @@ ETW
EUDC
EVENTID
eventing
everytime
evflags
evt
execd
@@ -612,8 +623,12 @@ FACESIZE
FAILIFTHERE
fastlink
fcharset
FDEA
fdw
FECF
FEEF
fesb
FFAF
FFDE
FFrom
fgbg
@@ -810,6 +825,8 @@ hkl
HKLM
hlocal
hlsl
HMB
HMK
hmod
hmodule
hmon
@@ -899,7 +916,6 @@ INSERTMODE
INTERACTIVITYBASE
INTERCEPTCOPYPASTE
INTERNALNAME
inthread
intsafe
INVALIDARG
INVALIDATERECT
@@ -960,6 +976,8 @@ KLF
KLMNO
KLMNOPQRST
KLMNOPQRSTQQQQQ
KLMNOPQRSTUVWXY
KLMNOPQRSTY
KOK
KPRIORITY
KVM
@@ -1118,10 +1136,12 @@ Mip
MMBB
mmcc
MMCPL
MMIX
mmsystem
MNC
MNOPQ
MNOPQR
MNOPQRSTUVWXY
MODALFRAME
MODERNCORE
MONITORINFO
@@ -1256,14 +1276,12 @@ ntm
nto
ntrtl
ntstatus
ntsubauth
NTSYSCALLAPI
nttree
nturtl
ntuser
NTVDM
ntverp
NTWIN
nugetversions
nullability
nullness
@@ -1284,6 +1302,8 @@ OEMFONT
OEMFORMAT
OEMs
offboarded
oklab
Oklab
OLEAUT
OLECHAR
onecore
@@ -1302,8 +1322,6 @@ opencode
opencon
openconsole
openconsoleproxy
OPENIF
OPENLINK
openps
openvt
ORIGINALFILENAME
@@ -1356,9 +1374,7 @@ pcg
pch
PCIDLIST
PCIS
PCLIENT
PCLONG
PCOBJECT
pcon
PCONSOLE
PCONSOLEENDTASK
@@ -1370,7 +1386,6 @@ pcshell
PCSHORT
PCSR
PCSTR
PCUNICODE
PCWCH
PCWCHAR
PCWSTR
@@ -1419,7 +1434,6 @@ PLOGICAL
pnm
PNMLINK
pntm
PNTSTATUS
POBJECT
Podcast
POINTSLIST
@@ -1437,9 +1451,7 @@ PPEB
ppf
ppguid
ppidl
pplx
PPROC
PPROCESS
ppropvar
ppsi
ppsl
@@ -1503,7 +1515,6 @@ ptrs
ptsz
PTYIn
PUCHAR
PUNICODE
pwch
PWDDMCONSOLECONTEXT
pws
@@ -1565,7 +1576,6 @@ REGISTEROS
REGISTERVDM
regkey
REGSTR
reingest
RELBINPATH
remoting
renamer
@@ -1577,6 +1587,7 @@ replatformed
Replymessage
repositorypath
Requiresx
rerasterize
rescap
Resequence
RESETCONTENT
@@ -1773,10 +1784,13 @@ srcsrv
SRCSRVTRG
srctool
srect
srgb
Srgb
srv
srvinit
srvpipe
ssa
startdir
STARTF
STARTUPINFO
STARTUPINFOEX
@@ -1786,6 +1800,7 @@ STARTWPARMS
STARTWPARMSA
STARTWPARMSW
Statusline
stb
stdafx
STDAPI
stdc
@@ -1859,6 +1874,7 @@ TDP
TEAMPROJECT
tearoff
Teb
Techo
tellp
teraflop
terminalcore
@@ -1950,6 +1966,7 @@ trx
tsattrs
tsf
tsgr
tsm
TStr
TSTRFORMAT
TSub
@@ -2001,7 +2018,6 @@ unittesting
unittests
unk
unknwn
unmark
UNORM
unparseable
unregistering
@@ -2036,6 +2052,7 @@ USRDLL
utr
UVWX
UVWXY
UVWXYZ
uwa
uwp
uxtheme
@@ -2114,7 +2131,6 @@ WDDMCONSOLECONTEXT
wdm
webpage
websites
websockets
wekyb
wex
wextest
@@ -2297,7 +2313,9 @@ YOffset
YSubstantial
YVIRTUALSCREEN
YWalk
Zab
zabcd
Zabcdefghijklmn
Zabcdefghijklmnopqrstuvwxyz
ZCmd
ZCtrl

View File

@@ -10,4 +10,4 @@
\\tests(?![a-z])
\\thread(?![a-z])
\\tools(?![a-z])
\\types(?![a-z])
\\types?(?![a-z])

View File

@@ -35,7 +35,7 @@ ROY\sG\.\sBIV
# hit-count: 71 file-count: 35
# Compiler flags
(?:^|[\t ,"'`=(])-[D](?=[A-Z]{2,}|[A-Z][a-z])
(?:^|[\t ,"'`=(])-[X](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
(?:^|[\t ,"'`=(])-[X](?!aml)(?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
# hit-count: 41 file-count: 28
# version suffix <word>v#

24
.github/workflows/winget.yml vendored Normal file
View File

@@ -0,0 +1,24 @@
name: Publish to Winget
on:
release:
types: [published]
env:
REGEX: 'Microsoft\.WindowsTerminal(?:Preview)?_([\d.]+)_8wekyb3d8bbwe\.msixbundle$'
jobs:
publish:
runs-on: windows-latest # Action can only run on Windows
steps:
- name: Publish Windows Terminal ${{ github.event.release.prerelease && 'Preview' || 'Stable' }}
run: |
$assets = '${{ toJSON(github.event.release.assets) }}' | ConvertFrom-Json
$wingetRelevantAsset = $assets | Where-Object { $_.name -like '*.msixbundle' } | Select-Object -First 1
$regex = [Regex]::New($env:REGEX)
$version = $regex.Match($wingetRelevantAsset.name).Groups[1].Value
$wingetPackage = "Microsoft.WindowsTerminal${{ github.event.release.prerelease && '.Preview' || '' }}"
& curl.exe -JLO https://aka.ms/wingetcreate/latest
& .\wingetcreate.exe update $wingetPackage -s -v $version -u $wingetRelevantAsset.browser_download_url -t "${{ secrets.WINGET_TOKEN }}"

View File

@@ -6,7 +6,7 @@
"C_Cpp.loggingLevel": "None",
"files.associations": {
"xstring": "cpp",
"*.idl": "cpp",
"*.idl": "midl3",
"array": "cpp",
"future": "cpp",
"istream": "cpp",
@@ -106,4 +106,4 @@
"**/packages/**": true,
"**/Generated Files/**": true
}
}
}

View File

@@ -276,41 +276,53 @@ OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
```
## ConEmu
**Source**: [https://github.com/Maximus5/ConEmu](https://github.com/Maximus5/ConEmu)
## stb
**Source**: [https://github.com/nothings/stb](https://github.com/nothings/stb)
### License
```
BSD 3-Clause License
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
```
Copyright (c) 2009-2017, Maximus5 <ConEmu.Maximus5@gmail.com>
All rights reserved.
## Oklab
**Source**: [https://bottosson.github.io/posts/oklab/](https://bottosson.github.io/posts/oklab/)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
### License
* 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 the copyright holder 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 HOLDER 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.
```
Copyright (c) 2020 Björn Ottosson
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
# Microsoft Open Source

View File

@@ -326,6 +326,9 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winconpty.Tests.Feature", "src\winconpty\ft_pty\winconpty.FeatureTests.vcxproj", "{024052DE-83FB-4653-AEA4-90790D29D5BD}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalAzBridge", "src\cascadia\TerminalAzBridge\TerminalAzBridge.vcxproj", "{067F0A06-FCB7-472C-96E9-B03B54E8E18D}"
ProjectSection(ProjectDependencies) = postProject
{CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fmt", "src\dep\fmt\fmt.vcxproj", "{6BAE5851-50D5-4934-8D5E-30361A8A40F3}"
EndProject
@@ -415,6 +418,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MidiAudio", "src\audio\midi
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TerminalStress", "src\tools\TerminalStress\TerminalStress.csproj", "{613CCB57-5FA9-48EF-80D0-6B1E319E20C4}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RenderingTests", "src\tools\RenderingTests\RenderingTests.vcxproj", "{37C995E0-2349-4154-8E77-4A52C0C7F46D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tracy", "oss\tracy\tracy.vcxproj", "{93818413-1073-496A-A599-8450659BA190}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
AuditMode|Any CPU = AuditMode|Any CPU
@@ -2767,6 +2774,58 @@ Global
{613CCB57-5FA9-48EF-80D0-6B1E319E20C4}.Release|x64.ActiveCfg = Release|Any CPU
{613CCB57-5FA9-48EF-80D0-6B1E319E20C4}.Release|x64.Build.0 = Release|Any CPU
{613CCB57-5FA9-48EF-80D0-6B1E319E20C4}.Release|x86.ActiveCfg = Release|Any CPU
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.AuditMode|ARM64.ActiveCfg = Release|ARM64
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.AuditMode|x64.ActiveCfg = Release|x64
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.AuditMode|x86.ActiveCfg = Release|Win32
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Debug|Any CPU.ActiveCfg = Debug|Win32
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Debug|ARM.ActiveCfg = Debug|Win32
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Debug|ARM64.ActiveCfg = Debug|ARM64
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Debug|ARM64.Build.0 = Debug|ARM64
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Debug|x64.ActiveCfg = Debug|x64
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Debug|x64.Build.0 = Debug|x64
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Debug|x86.ActiveCfg = Debug|Win32
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Debug|x86.Build.0 = Debug|Win32
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Release|Any CPU.ActiveCfg = Release|Win32
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Release|ARM.ActiveCfg = Release|Win32
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Release|ARM64.ActiveCfg = Release|ARM64
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Release|ARM64.Build.0 = Release|ARM64
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Release|x64.ActiveCfg = Release|x64
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Release|x64.Build.0 = Release|x64
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Release|x86.ActiveCfg = Release|Win32
{37C995E0-2349-4154-8E77-4A52C0C7F46D}.Release|x86.Build.0 = Release|Win32
{93818413-1073-496A-A599-8450659BA190}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
{93818413-1073-496A-A599-8450659BA190}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
{93818413-1073-496A-A599-8450659BA190}.AuditMode|ARM64.ActiveCfg = Release|ARM64
{93818413-1073-496A-A599-8450659BA190}.AuditMode|x64.ActiveCfg = Release|x64
{93818413-1073-496A-A599-8450659BA190}.AuditMode|x86.ActiveCfg = Release|Win32
{93818413-1073-496A-A599-8450659BA190}.Debug|Any CPU.ActiveCfg = Debug|Win32
{93818413-1073-496A-A599-8450659BA190}.Debug|ARM.ActiveCfg = Debug|Win32
{93818413-1073-496A-A599-8450659BA190}.Debug|ARM64.ActiveCfg = Debug|ARM64
{93818413-1073-496A-A599-8450659BA190}.Debug|ARM64.Build.0 = Debug|ARM64
{93818413-1073-496A-A599-8450659BA190}.Debug|x64.ActiveCfg = Debug|x64
{93818413-1073-496A-A599-8450659BA190}.Debug|x64.Build.0 = Debug|x64
{93818413-1073-496A-A599-8450659BA190}.Debug|x86.ActiveCfg = Debug|Win32
{93818413-1073-496A-A599-8450659BA190}.Debug|x86.Build.0 = Debug|Win32
{93818413-1073-496A-A599-8450659BA190}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32
{93818413-1073-496A-A599-8450659BA190}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32
{93818413-1073-496A-A599-8450659BA190}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{93818413-1073-496A-A599-8450659BA190}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{93818413-1073-496A-A599-8450659BA190}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{93818413-1073-496A-A599-8450659BA190}.Release|Any CPU.ActiveCfg = Release|Win32
{93818413-1073-496A-A599-8450659BA190}.Release|ARM.ActiveCfg = Release|Win32
{93818413-1073-496A-A599-8450659BA190}.Release|ARM64.ActiveCfg = Release|ARM64
{93818413-1073-496A-A599-8450659BA190}.Release|ARM64.Build.0 = Release|ARM64
{93818413-1073-496A-A599-8450659BA190}.Release|x64.ActiveCfg = Release|x64
{93818413-1073-496A-A599-8450659BA190}.Release|x64.Build.0 = Release|x64
{93818413-1073-496A-A599-8450659BA190}.Release|x86.ActiveCfg = Release|Win32
{93818413-1073-496A-A599-8450659BA190}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2872,6 +2931,8 @@ Global
{40BD8415-DD93-4200-8D82-498DDDC08CC8} = {89CDCC5C-9F53-4054-97A4-639D99F169CD}
{3C67784E-1453-49C2-9660-483E2CC7F7AD} = {40BD8415-DD93-4200-8D82-498DDDC08CC8}
{613CCB57-5FA9-48EF-80D0-6B1E319E20C4} = {A10C4720-DCA4-4640-9749-67F4314F527C}
{37C995E0-2349-4154-8E77-4A52C0C7F46D} = {A10C4720-DCA4-4640-9749-67F4314F527C}
{93818413-1073-496A-A599-8450659BA190} = {A10C4720-DCA4-4640-9749-67F4314F527C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271}

View File

@@ -55,14 +55,8 @@ Copy-Item "build\helix\runtests.cmd" $payloadDir
Copy-Item "build\helix\InstallTestAppDependencies.ps1" "$payloadDir"
Copy-Item "build\Helix\EnsureMachineState.ps1" "$payloadDir"
# Copy the APPX package from the 'drop' artifact dir and Windows Kits
Copy-Item "$repoDirectory\Artifacts\$ArtifactName\appx\CascadiaPackage_0.0.1.0_$Platform.msix" $payloadDir\CascadiaPackage.zip
Copy-Item "C:\program files (x86)\Microsoft SDKs\Windows Kits\10\ExtensionSDKs\Microsoft.VCLibs.Desktop\14.0\Appx\Retail\x64\Microsoft.VCLibs.x64.14.00.Desktop.appx" $payloadDir\VCLibs.zip
# Rename it to extension of ZIP because Expand-Archive is real sassy on the build machines
# and refuses to unzip it because of its file extension while on a desktop, it just
# does the job without complaining.
# Extract the APPX package
Expand-Archive -LiteralPath $payloadDir\CascadiaPackage.zip -DestinationPath $payloadDir\appx
Expand-Archive -LiteralPath $payloadDir\VCLibs.zip -DestinationPath $payloadDir\appx -Force
# Extract the unpackaged distribution of Windows Terminal to the payload directory,
# where it will create a subdirectory named terminal-0.0.1.0
# This is referenced in TerminalApp.cs later as part of the test harness.
& tar -x -v -f "$repoDirectory\Artifacts\$ArtifactName\unpackaged\WindowsTerminalDev_0.0.1.0_x64.zip" -C "$payloadDir"
Copy-Item "res\fonts\*.ttf" "$payloadDir\terminal-0.0.1.0"

View File

@@ -70,7 +70,7 @@ foreach ($testRun in $testRuns.value)
foreach ($testResult in $testResults.value)
{
$info = ConvertFrom-Json $testResult.comment
$info = ConvertFrom-Json ([System.Web.HttpUtility]::HtmlDecode($testResult.comment))
$helixJobId = $info.HelixJobId
$helixWorkItemName = $info.HelixWorkItemName

View File

@@ -67,51 +67,6 @@
}
]
}
},
{
// THIRD PARTY SOFTWARE
"MatchedPath": [
"cpprest*.dll"
],
"SigningInfo": {
"Operations": [
{
"KeyCode": "CP-231522",
"OperationSetCode": "SigntoolSign",
"Parameters": [
{
"parameterName": "OpusName",
"parameterValue": "Microsoft"
},
{
"parameterName": "OpusInfo",
"parameterValue": "http://www.microsoft.com"
},
{
"parameterName": "FileDigest",
"parameterValue": "/fd \"SHA256\""
},
{
"parameterName": "PageHash",
"parameterValue": "/NPH"
},
{
"parameterName": "TimeStamp",
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
}
],
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "CP-231522",
"OperationSetCode": "SigntoolVerify",
"Parameters": [],
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
}
}
]
}

View File

@@ -3,8 +3,6 @@
<package id="MUXCustomBuildTasks" version="1.0.48" targetFramework="native" />
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
<package id="Microsoft.Internal.PGO-Helpers.Cpp" version="0.2.34" targetFramework="native" />
<!-- This cannot be included in another project that depends on XAML (as it would be a duplicate package ID) -->
<package id="Microsoft.UI.Xaml" version="2.7.3" targetFramework="native" />
<package id="Microsoft.Debugging.Tools.PdbStr" version="20220617.1556.0" targetFramework="native" />
<package id="Microsoft.Debugging.Tools.SrcTool" version="20220617.1556.0" targetFramework="native" />
</packages>

View File

@@ -56,15 +56,10 @@ parameters:
- x64
- x86
- arm64
- name: buildWindowsVersions
type: object
default:
- Win10
- Win11
variables:
MakeAppxPath: 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x86\MakeAppx.exe'
TerminalInternalPackageVersion: "0.0.7"
TerminalInternalPackageVersion: "0.0.8"
# If we are building a branch called "release-*", change the NuGet suffix
# to "preview". If we don't do that, XES will set the suffix to "release1"
# because it truncates the value after the first period.
@@ -87,13 +82,6 @@ variables:
NuGetPackBetaVersion: preview
${{ elseif eq(variables['Build.SourceBranchName'], 'main') }}:
NuGetPackBetaVersion: experimental
# The NuGet packages have to use *somebody's* DLLs. We used to force them to
# use the Win10 build outputs, but if there isn't a Win10 build we should use
# the Win11 one.
${{ if containsValue(parameters.buildWindowsVersions, 'Win10') }}:
TerminalBestVersionForNuGetPackages: Win10
${{ else }}:
TerminalBestVersionForNuGetPackages: Win11
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
resources:
@@ -107,11 +95,9 @@ jobs:
matrix:
${{ each config in parameters.buildConfigurations }}:
${{ each platform in parameters.buildPlatforms }}:
${{ each windowsVersion in parameters.buildWindowsVersions }}:
${{ config }}_${{ platform }}_${{ windowsVersion }}:
BuildConfiguration: ${{ config }}
BuildPlatform: ${{ platform }}
TerminalTargetWindowsVersion: ${{ windowsVersion }}
${{ config }}_${{ platform }}:
BuildConfiguration: ${{ config }}
BuildPlatform: ${{ platform }}
displayName: Build
timeoutInMinutes: 240
cancelTimeoutInMinutes: 1
@@ -185,10 +171,6 @@ jobs:
arguments: -MarkdownNoticePath .\NOTICE.md -OutputPath .\src\cascadia\CascadiaPackage\NOTICE.html
pwsh: true
- ${{ if eq(parameters.buildTerminal, true) }}:
- pwsh: |-
./build/scripts/Patch-ManifestsToWindowsVersion.ps1 -NewWindowsVersion "10.0.22000.0"
displayName: Update manifest target version to Win11 (if necessary)
condition: and(succeeded(), eq(variables['TerminalTargetWindowsVersion'], 'Win11'))
- task: VSBuild@1
displayName: Build solution **\OpenConsole.sln
condition: true
@@ -205,7 +187,7 @@ jobs:
continueOnError: True
inputs:
PathtoPublish: $(Build.SourcesDirectory)\msbuild.binlog
ArtifactName: binlog-$(BuildPlatform)-$(TerminalTargetWindowsVersion)
ArtifactName: binlog-$(BuildPlatform)
- task: PowerShell@2
displayName: Check MSIX for common regressions
inputs:
@@ -254,16 +236,12 @@ jobs:
arguments: -MatchPattern '*feature.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)'
- ${{ if eq(parameters.buildTerminal, true) }}:
- task: CopyFiles@2
displayName: Copy *.appx/*.msix to Artifacts
displayName: Copy *.msix and symbols to Artifacts
inputs:
Contents: >-
**/*.appx
**/*.msix
**/*.appxsym
!**/Microsoft.VCLibs*.appx
TargetFolder: $(Build.ArtifactStagingDirectory)/appx
OverWrite: true
flattenFolders: true
@@ -297,7 +275,17 @@ jobs:
displayName: Publish Artifact (appx)
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)/appx
ArtifactName: appx-$(BuildPlatform)-$(BuildConfiguration)-$(TerminalTargetWindowsVersion)
ArtifactName: appx-$(BuildPlatform)-$(BuildConfiguration)
- pwsh: |-
$XamlAppxPath = (Get-Item "src\cascadia\CascadiaPackage\AppPackages\*\Dependencies\$(BuildPlatform)\Microsoft.UI.Xaml*.appx").FullName
& .\build\scripts\New-UnpackagedTerminalDistribution.ps1 -TerminalAppX $(WindowsTerminalPackagePath) -XamlAppX $XamlAppxPath -Destination "$(Build.ArtifactStagingDirectory)/unpackaged"
displayName: Build Unpackaged Distribution
- publish: $(Build.ArtifactStagingDirectory)/unpackaged
artifact: unpackaged-$(BuildPlatform)-$(BuildConfiguration)
displayName: Publish Artifact (unpackaged)
- ${{ if eq(parameters.buildConPTY, true) }}:
- task: CopyFiles@2
displayName: Copy ConPTY to Artifacts
@@ -315,7 +303,7 @@ jobs:
displayName: Publish Artifact (ConPTY)
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)/conpty
ArtifactName: conpty-dll-$(BuildPlatform)-$(BuildConfiguration)-$(TerminalTargetWindowsVersion)
ArtifactName: conpty-dll-$(BuildPlatform)-$(BuildConfiguration)
- ${{ if eq(parameters.buildWPF, true) }}:
- task: CopyFiles@2
displayName: Copy PublicTerminalCore.dll to Artifacts
@@ -329,7 +317,7 @@ jobs:
displayName: Publish Artifact (PublicTerminalCore)
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)/wpf
ArtifactName: wpf-dll-$(BuildPlatform)-$(BuildConfiguration)-$(TerminalTargetWindowsVersion)
ArtifactName: wpf-dll-$(BuildPlatform)-$(BuildConfiguration)
- task: PublishSymbols@2
displayName: Publish symbols path
@@ -347,11 +335,6 @@ jobs:
- ${{ if eq(parameters.buildTerminal, true) }}:
- job: BundleAndSign
strategy:
matrix:
${{ each windowsVersion in parameters.buildWindowsVersions }}:
${{ windowsVersion }}:
TerminalTargetWindowsVersion: ${{ windowsVersion }}
displayName: Create and sign AppX/MSIX bundles
variables:
${{ if eq(parameters.branding, 'Release') }}:
@@ -373,9 +356,9 @@ jobs:
disableOutputRedirect: true
- ${{ each platform in parameters.buildPlatforms }}:
- task: DownloadBuildArtifacts@0
displayName: Download Artifacts ${{ platform }} $(TerminalTargetWindowsVersion)
displayName: Download Artifacts ${{ platform }}
inputs:
artifactName: appx-${{ platform }}-Release-$(TerminalTargetWindowsVersion)
artifactName: appx-${{ platform }}-Release
# Add 3000 to the major version component, but only for the bundle.
# This is to ensure that it is newer than "2022.xx.yy.zz" or whatever the original bundle versions were before
# we switched to uniform naming.
@@ -385,7 +368,7 @@ jobs:
$Components[0] = ([int]$Components[0] + $VersionEpoch)
$BundleVersion = $Components -Join "."
New-Item -Type Directory "$(System.ArtifactsDirectory)\bundle"
.\build\scripts\Create-AppxBundle.ps1 -InputPath "$(System.ArtifactsDirectory)" -ProjectName CascadiaPackage -BundleVersion $BundleVersion -OutputPath "$(System.ArtifactsDirectory)\bundle\$(BundleStemName)_$(TerminalTargetWindowsVersion)_$(XES_APPXMANIFESTVERSION)_8wekyb3d8bbwe.msixbundle"
.\build\scripts\Create-AppxBundle.ps1 -InputPath "$(System.ArtifactsDirectory)" -ProjectName CascadiaPackage -BundleVersion $BundleVersion -OutputPath "$(System.ArtifactsDirectory)\bundle\$(BundleStemName)_$(XES_APPXMANIFESTVERSION)_8wekyb3d8bbwe.msixbundle"
displayName: Create WindowsTerminal*.msixbundle
- task: EsrpCodeSigning@1
displayName: Submit *.msixbundle to ESRP for code signing
@@ -426,7 +409,7 @@ jobs:
displayName: 'Publish Artifact: appxbundle-signed'
inputs:
PathtoPublish: $(System.ArtifactsDirectory)\bundle
ArtifactName: appxbundle-signed-$(TerminalTargetWindowsVersion)
ArtifactName: appxbundle-signed
- ${{ if eq(parameters.buildConPTY, true) }}:
- job: PackageAndSignConPTY
@@ -451,7 +434,7 @@ jobs:
- task: DownloadBuildArtifacts@0
displayName: Download ${{ platform }} ConPTY binaries
inputs:
artifactName: conpty-dll-${{ platform }}-$(BuildConfiguration)-$(TerminalBestVersionForNuGetPackages)
artifactName: conpty-dll-${{ platform }}-$(BuildConfiguration)
downloadPath: bin\${{ platform }}\$(BuildConfiguration)\
extractTars: false
- task: PowerShell@2
@@ -542,7 +525,7 @@ jobs:
- task: DownloadBuildArtifacts@0
displayName: Download ${{ platform }} PublicTerminalCore
inputs:
artifactName: wpf-dll-${{ platform }}-$(BuildConfiguration)-$(TerminalBestVersionForNuGetPackages)
artifactName: wpf-dll-${{ platform }}-$(BuildConfiguration)
itemPattern: '**/*.dll'
downloadPath: bin\${{ platform }}\$(BuildConfiguration)\
extractTars: false
@@ -640,11 +623,10 @@ jobs:
# Download the appx-PLATFORM-CONFIG-VERSION artifact for every platform/version combo
- ${{ each platform in parameters.buildPlatforms }}:
- ${{ each windowsVersion in parameters.buildWindowsVersions }}:
- task: DownloadBuildArtifacts@0
displayName: Download Symbols ${{ platform }} ${{ windowsVersion }}
inputs:
artifactName: appx-${{ platform }}-Release-${{ windowsVersion }}
- task: DownloadBuildArtifacts@0
displayName: Download Symbols ${{ platform }}
inputs:
artifactName: appx-${{ platform }}-Release
# It seems easier to do this -- download every appxsym -- then enumerate all the PDBs in the build directory for the
# public symbol push. Otherwise, we would have to list all of the PDB files one by one.
@@ -704,7 +686,7 @@ jobs:
- task: DownloadBuildArtifacts@0
displayName: Download Build Artifacts
inputs:
artifactName: appxbundle-signed-Win11
artifactName: appxbundle-signed
extractTars: false
- task: PowerShell@2
displayName: Rename and stage packages for vpack
@@ -713,7 +695,7 @@ jobs:
script: >-
# Rename to known/fixed name for Windows build system
Get-ChildItem Microsoft.WindowsTerminal_Win11_*.msixbundle | Rename-Item -NewName { 'Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle' }
Get-ChildItem Microsoft.WindowsTerminal_*.msixbundle | Rename-Item -NewName { 'Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle' }
# Create vpack directory and place item inside
@@ -721,13 +703,13 @@ jobs:
mkdir WindowsTerminal.app
mv Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle .\WindowsTerminal.app\
workingDirectory: $(System.ArtifactsDirectory)\appxbundle-signed-Win11
workingDirectory: $(System.ArtifactsDirectory)\appxbundle-signed
- task: PkgESVPack@12
displayName: 'Package ES - VPack'
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
inputs:
sourceDirectory: $(System.ArtifactsDirectory)\appxbundle-signed-Win11\WindowsTerminal.app
sourceDirectory: $(System.ArtifactsDirectory)\appxbundle-signed\WindowsTerminal.app
description: VPack for the Windows Terminal Application
pushPkgName: WindowsTerminal.app
owner: conhost

View File

@@ -144,7 +144,7 @@ jobs:
inputs:
TargetPattern: guardianGlob
# See https://aka.ms/gdn-globs for how to do match patterns
AnalyzeTargetGlob: $(Build.SourcesDirectory)\bin\**\*.dll;$(Build.SourcesDirectory)\bin\**\*.exe;-:file|**\Microsoft.UI.Xaml.dll;-:file|**\Microsoft.Toolkit.Win32.UI.XamlHost.dll;-:file|**\vcruntime*.dll;-:file|**\vcomp*.dll;-:file|**\vccorlib*.dll;-:file|**\vcamp*.dll;-:file|**\msvcp*.dll;-:file|**\concrt*.dll;-:file|**\TerminalThemeHelpers*.dll;-:file|**\cpprest*.dll
AnalyzeTargetGlob: $(Build.SourcesDirectory)\bin\**\*.dll;$(Build.SourcesDirectory)\bin\**\*.exe;-:file|**\Microsoft.UI.Xaml.dll;-:file|**\Microsoft.Toolkit.Win32.UI.XamlHost.dll;-:file|**\vcruntime*.dll;-:file|**\vcomp*.dll;-:file|**\vccorlib*.dll;-:file|**\vcamp*.dll;-:file|**\msvcp*.dll;-:file|**\concrt*.dll;-:file|**\TerminalThemeHelpers*.dll
continueOnError: true
# Set XES_SERIALPOSTBUILDREADY to run Security and Compliance task once per build

View File

@@ -64,17 +64,24 @@ steps:
Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}"
- task: CopyFiles@2
displayName: 'Copy *.appx/*.msix to Artifacts (Non-PR builds only)'
displayName: 'Copy *.msix to Artifacts'
inputs:
Contents: |
**/*.appx
**/*.msix
**/*.appxsym
!**/Microsoft.VCLibs*.appx
TargetFolder: '$(Build.ArtifactStagingDirectory)/appx'
OverWrite: true
flattenFolders: true
condition: succeeded()
- pwsh: |-
$TerminalMsixPath = (Get-Item "$(Build.ArtifactStagingDirectory)\appx\Cascadia*.msix").FullName
$XamlAppxPath = (Get-Item "src\cascadia\CascadiaPackage\AppPackages\*\Dependencies\$(BuildPlatform)\Microsoft.UI.Xaml*.appx").FullName
& .\build\scripts\New-UnpackagedTerminalDistribution.ps1 -TerminalAppX $TerminalMsixPath -XamlAppX $XamlAppxPath -Destination "$(Build.ArtifactStagingDirectory)/unpackaged"
displayName: Build Unpackaged Distribution
- publish: $(Build.ArtifactStagingDirectory)/unpackaged
artifact: unpackaged-$(BuildPlatform)-$(BuildConfiguration)
displayName: Publish Artifact (unpackaged)
- task: CopyFiles@2
displayName: 'Copy outputs needed for test runs to Artifacts'

View File

@@ -14,8 +14,8 @@ parameters:
platform: ''
# if 'useBuildOutputFromBuildId' is set, we will default to using a build from this pipeline:
useBuildOutputFromPipeline: $(System.DefinitionId)
openHelixTargetQueues: 'windows.10.amd64.client21h1.open.xaml'
closedHelixTargetQueues: 'windows.10.amd64.client21h1.xaml'
openHelixTargetQueues: 'windows.11.amd64.client.open.reunion'
closedHelixTargetQueues: 'windows.11.amd64.client.reunion'
jobs:
- job: ${{ parameters.name }}

View File

@@ -30,7 +30,7 @@
DependsOnTargets="_ConsoleMapWinmdsToManifestFiles">
<!-- This target is batched and a new Exec is spawned for each entry in _ConsoleWinmdManifest. -->
<Exec Command="mt.exe -winmd:%(_ConsoleWinmdManifest.WinMDPath) -dll:%(_ConsoleWinmdManifest.Implementation) -out:%(_ConsoleWinmdManifest.Identity)" />
<Exec Command="mt.exe -winmd:&quot;%(_ConsoleWinmdManifest.WinMDPath)&quot; -dll:%(_ConsoleWinmdManifest.Implementation) -out:&quot;%(_ConsoleWinmdManifest.Identity)&quot;" />
<ItemGroup>
<!-- Emit the generated manifest into the Link inputs. -->

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--
This file contains targets that override behavior in Microsoft.UI.Xaml and
related packages.
For example: All XAML needs is a reference to WebView2; it does not need the
DLL and it does not need for us to copy the WinMD into the output folder. It
also doesn't require the WebView2 loader since we're not actually using
WebView2. Therefore, we can get away with *not including the WebView2
package* and only adding a reference to its winmd.
-->
<ItemGroup>
<Reference Include="$(WebView2PackageRoot)\lib\Microsoft.Web.WebView2.Core.winmd" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,78 @@
Param(
[Parameter(Mandatory,
HelpMessage="List of PRI files or XML dumps (detailed only) to merge")]
[string[]]
$Path,
[Parameter(Mandatory,
HelpMessage="Output Path")]
[string]
$OutputPath,
[Parameter(HelpMessage="Name of index in output file; defaults to 'Application'")]
[string]
$IndexName = "Application",
[Parameter(HelpMessage="Path to makepri.exe")]
[ValidateScript({Test-Path $_ -Type Leaf})]
[string]
$MakePriPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\MakePri.exe"
)
$ErrorActionPreference = 'Stop'
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) "tmp$([Convert]::ToString((Get-Random 65535),16).PadLeft(4,'0')).tmp"
New-Item -ItemType Directory -Path $tempDir | Out-Null
$priConfig = Join-Path $tempDir "priconfig.xml"
$priListFile = Join-Path $tempDir "pri.resfiles"
$dumpListFile = Join-Path $tempDir "dump.resfiles"
@"
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="dump.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRIINFO" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="pri.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
</resources>
"@ | Out-File -Encoding:utf8NoBOM $priConfig
$Path | Where { $_ -Like "*.pri" } | ForEach-Object {
Get-Item $_ | Select -Expand FullName
} | Out-File -Encoding:utf8NoBOM $priListFile
$Path | Where { $_ -Like "*.xml" } | ForEach-Object {
Get-Item $_ | Select -Expand FullName
} | Out-File -Encoding:utf8NoBOM $dumpListFile
& $MakePriPath new /pr $tempDir /cf $priConfig /o /in $IndexName /of $OutputPath
Remove-Item -Recurse -Force $tempDir

View File

@@ -0,0 +1,47 @@
Param(
[Parameter(Mandatory,
HelpMessage="Root directory of extracted Terminal AppX")]
[string[]]
$TerminalRoot,
[Parameter(Mandatory,
HelpMessage="Root directory of extracted Xaml AppX")]
[string[]]
$XamlRoot,
[Parameter(Mandatory,
HelpMessage="Output Path")]
[string]
$OutputPath,
[Parameter(HelpMessage="Path to makepri.exe")]
[ValidateScript({Test-Path $_ -Type Leaf})]
[string]
$MakePriPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\MakePri.exe"
)
$ErrorActionPreference = 'Stop'
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) "tmp$([Convert]::ToString((Get-Random 65535),16).PadLeft(4,'0')).tmp"
New-Item -ItemType Directory -Path $tempDir | Out-Null
$terminalDump = Join-Path $tempDir "terminal.pri.xml"
& $MakePriPath dump /if (Join-Path $TerminalRoot "resources.pri") /of $terminalDump /dt detailed
Write-Verbose "Removing Microsoft.UI.Xaml node from Terminal to prevent a collision with XAML"
$terminalXMLDocument = [xml](Get-Content $terminalDump)
$resourceMap = $terminalXMLDocument.PriInfo.ResourceMap
$fileSubtree = $resourceMap.ResourceMapSubtree | Where-Object { $_.Name -eq "Files" }
$subtrees = $fileSubtree.ResourceMapSubtree
$xamlSubtreeChild = ($subtrees | Where-Object { $_.Name -eq "Microsoft.UI.Xaml" })
if ($Null -Ne $xamlSubtreeChild) {
$null = $fileSubtree.RemoveChild($xamlSubtreeChild)
$terminalXMLDocument.Save($terminalDump)
}
$indexName = $terminalXMLDocument.PriInfo.ResourceMap.name
& (Join-Path $PSScriptRoot "Merge-PriFiles.ps1") -Path $terminalDump, (Join-Path $XamlRoot "resources.pri") -IndexName $indexName -OutputPath $OutputPath -MakePriPath $MakePriPath
Remove-Item -Recurse -Force $tempDir

View File

@@ -0,0 +1,140 @@
[CmdletBinding(DefaultParameterSetName = 'AppX')]
Param(
[Parameter(Mandatory, HelpMessage="Path to Terminal AppX", ParameterSetName = 'AppX')]
[ValidateScript({Test-Path $_ -Type Leaf})]
[string]
$TerminalAppX,
[Parameter(Mandatory, HelpMessage="Path to Terminal Layout Deployment", ParameterSetName='Layout')]
[ValidateScript({Test-Path $_ -Type Container})]
[string]
$TerminalLayout,
[Parameter(Mandatory, HelpMessage="Path to Xaml AppX", ParameterSetName='AppX')]
[Parameter(Mandatory, HelpMessage="Path to Xaml AppX", ParameterSetName='Layout')]
[ValidateScript({Test-Path $_ -Type Leaf})]
[string]
$XamlAppX,
[Parameter(HelpMessage="Output Directory", ParameterSetName='AppX')]
[Parameter(HelpMessage="Output Directory", ParameterSetName='Layout')]
[string]
$Destination = ".",
[Parameter(HelpMessage="Path to makeappx.exe", ParameterSetName='AppX')]
[Parameter(HelpMessage="Path to makeappx.exe", ParameterSetName='Layout')]
[ValidateScript({Test-Path $_ -Type Leaf})]
[string]
$MakeAppxPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\MakeAppx.exe"
)
$filesToRemove = @("*.xml", "*.winmd", "Appx*", "Images/*Tile*", "Images/*Logo*") # Remove from Terminal
$filesToKeep = @("Microsoft.Terminal.Remoting.winmd") # ... except for these
$filesToCopyFromXaml = @("Microsoft.UI.Xaml.dll", "Microsoft.UI.Xaml") # We don't need the .winmd
$ErrorActionPreference = 'Stop'
If ($null -Eq (Get-Item $MakeAppxPath -EA:SilentlyContinue)) {
Write-Error "Could not find MakeAppx.exe at `"$MakeAppxPath`".`nMake sure that -MakeAppxPath points to a valid SDK."
Exit 1
}
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) "tmp$([Convert]::ToString((Get-Random 65535),16).PadLeft(4,'0')).tmp"
New-Item -ItemType Directory -Path $tempDir | Out-Null
$XamlAppX = Get-Item $XamlAppX | Select-Object -Expand FullName
########
# Reading the AppX Manifest for preliminary info
########
If ($TerminalAppX) {
$appxManifestPath = Join-Path $tempDir AppxManifest.xml
& tar.exe -x -f "$TerminalAppX" -C $tempDir AppxManifest.xml
} ElseIf($TerminalLayout) {
$appxManifestPath = Join-Path $TerminalLayout AppxManifest.xml
}
$manifest = [xml](Get-Content $appxManifestPath)
$pfn = $manifest.Package.Identity.Name
$version = $manifest.Package.Identity.Version
$architecture = $manifest.Package.Identity.ProcessorArchitecture
$distributionName = "{0}_{1}_{2}" -f ($pfn, $version, $architecture)
$terminalDir = "terminal-{0}" -f ($version)
########
# Unpacking Terminal and XAML
########
$terminalAppPath = Join-Path $tempdir $terminalDir
If ($TerminalAppX) {
$TerminalAppX = Get-Item $TerminalAppX | Select-Object -Expand FullName
New-Item -ItemType Directory -Path $terminalAppPath | Out-Null
& $MakeAppxPath unpack /p $TerminalAppX /d $terminalAppPath /o | Out-Null
If ($LASTEXITCODE -Ne 0) {
Throw "Unpacking $TerminalAppX failed"
}
} ElseIf ($TerminalLayout) {
Copy-Item -Recurse -Path $TerminalLayout -Destination $terminalAppPath
}
$xamlAppPath = Join-Path $tempdir "xaml"
New-Item -ItemType Directory -Path $xamlAppPath | Out-Null
& $MakeAppxPath unpack /p $XamlAppX /d $xamlAppPath /o | Out-Null
If ($LASTEXITCODE -Ne 0) {
Throw "Unpacking $XamlAppX failed"
}
########
# Some sanity checking
########
$xamlManifest = [xml](Get-Content (Join-Path $xamlAppPath "AppxManifest.xml"))
If ($xamlManifest.Package.Identity.Name -NotLike "Microsoft.UI.Xaml*") {
Throw "$XamlAppX is not a XAML package (instead, it looks like $($xamlManifest.Package.Identity.Name))"
}
If ($xamlManifest.Package.Identity.ProcessorArchitecture -Ne $architecture) {
Throw "$XamlAppX is not built for $architecture (instead, it is built for $($xamlManifest.Package.Identity.ProcessorArchitecture))"
}
########
# Preparation of source files
########
$itemsToRemove = $filesToRemove | ForEach-Object {
Get-Item (Join-Path $terminalAppPath $_) -EA:SilentlyContinue | Where-Object {
$filesToKeep -NotContains $_.Name
}
} | Sort-Object FullName -Unique
$itemsToRemove | Remove-Item -Recurse
$filesToCopyFromXaml | ForEach-Object {
Get-Item (Join-Path $xamlAppPath $_)
} | Copy-Item -Recurse -Destination $terminalAppPath
########
# Resource Management
########
$finalTerminalPriFile = Join-Path $terminalAppPath "resources.pri"
& (Join-Path $PSScriptRoot "Merge-TerminalAndXamlResources.ps1") `
-TerminalRoot $terminalAppPath `
-XamlRoot $xamlAppPath `
-OutputPath $finalTerminalPriFile `
-Verbose:$Verbose | Out-Host
########
# Packaging
########
If ($PSCmdlet.ParameterSetName -Eq "AppX") {
# We only produce a ZIP when we're combining two AppX directories.
New-Item -ItemType Directory -Path $Destination -ErrorAction:SilentlyContinue | Out-Null
$outputZip = (Join-Path $Destination ("{0}.zip" -f ($distributionName)))
& tar -c --format=zip -f $outputZip -C $tempDir $terminalDir
Remove-Item -Recurse -Force $tempDir -EA:SilentlyContinue
Get-Item $outputZip
} ElseIf ($PSCmdlet.ParameterSetName -Eq "Layout") {
Get-Item $terminalAppPath
}

View File

@@ -1,14 +0,0 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
Param(
[string]$NewWindowsVersion = "10.0.22000.0"
)
Get-ChildItem src/cascadia/CascadiaPackage -Recurse -Filter *.appxmanifest | ForEach-Object {
$xml = [xml](Get-Content $_.FullName)
$xml.Package.Dependencies.TargetDeviceFamily | Where-Object Name -Like "Windows*" | ForEach-Object {
$_.MinVersion = $NewWindowsVersion
}
$xml.Save($_.FullName)
}

View File

@@ -70,23 +70,24 @@ Try {
$dependencies = $Manifest.Package.Dependencies.PackageDependency.Name
$depsHasVclibsDesktop = ("Microsoft.VCLibs.140.00.UWPDesktop" -in $dependencies) -or ("Microsoft.VCLibs.140.00.Debug.UWPDesktop" -in $dependencies)
$depsHasVcLibsAppX = ("Microsoft.VCLibs.140.00" -in $dependencies) -or ("Microsoft.VCLibs.140.00.Debug" -in $dependencies)
$depsHasVclibsAppX = ("Microsoft.VCLibs.140.00" -in $dependencies) -or ("Microsoft.VCLibs.140.00.Debug" -in $dependencies)
$filesHasVclibsDesktop = ($null -ne (Get-Item "$AppxPackageRootPath\vcruntime140.dll" -EA:Ignore)) -or ($null -ne (Get-Item "$AppxPackageRootPath\vcruntime140d.dll" -EA:Ignore))
$filesHasVclibsAppX = ($null -ne (Get-Item "$AppxPackageRootPath\vcruntime140_app.dll" -EA:Ignore)) -or ($null -ne (Get-Item "$AppxPackageRootPath\vcruntime140d_app.dll" -EA:Ignore))
If ($depsHasVclibsDesktop -Eq $filesHasVclibsDesktop) {
$eitherBoth = if ($depsHasVclibsDesktop) { "both" } else { "neither" }
$neitherNor = if ($depsHasVclibsDesktop) { "and" } else { "nor" }
Throw "Package has $eitherBoth Dependency $neitherNor Integrated Desktop VCLibs"
If ($filesHasVclibsDesktop) {
Throw "Package contains the desktop VCLibs"
}
If ($depsHasVclibsAppx -Eq $filesHasVclibsAppx) {
if ($depsHasVclibsAppx) {
# We've shipped like this forever, so downgrade to warning.
Write-Warning "Package has both Dependency and Integrated AppX VCLibs"
} else {
Throw "Package has neither Dependency nor Integrated AppX VCLibs"
}
If ($depsHasVclibsDesktop) {
Throw "Package has a dependency on the desktop VCLibs"
}
If ($filesHasVclibsAppX) {
Throw "Package contains the AppX VCLibs"
}
If ($depsHasVclibsAppX) {
Throw "Package has a dependency on the AppX VCLibs"
}
### Check that we have an App.xbf (which is a proxy for our resources having been merged)
@@ -96,11 +97,6 @@ Try {
Throw "Failed to find App.xbf (TerminalApp project) in resources.pri"
}
If (($null -eq (Get-Item "$AppxPackageRootPath\cpprest142_2_10.dll" -EA:Ignore)) -And
($null -eq (Get-Item "$AppxPackageRootPath\cpprest142_2_10d.dll" -EA:Ignore))) {
Throw "Failed to find cpprest142_2_10.dll -- check the WAP packaging project"
}
If (($null -eq (Get-Item "$AppxPackageRootPath\wtd.exe" -EA:Ignore)) -And
($null -eq (Get-Item "$AppxPackageRootPath\wt.exe" -EA:Ignore))) {
Throw "Failed to find wt.exe/wtd.exe -- check the WAP packaging project"

View File

@@ -10,22 +10,4 @@
<OpenConsoleDir>$(MSBuildThisFileDirectory)</OpenConsoleDir>
</PropertyGroup>
<PropertyGroup>
<!--
For the Windows 10 build, we're targeting the prerelease version of Microsoft.UI.Xaml.
This version emits every XAML DLL directly into our package.
This is a workaround for us not having deliverable MSFT-21242953 on this version of Windows.
This version should be tracked in all project packages.config files for projects that depend on Xaml.
-->
<TerminalMUXVersion>2.7.3-prerelease.220816001</TerminalMUXVersion>
<!--
For the Windows 11-specific build, we're targeting the public version of Microsoft.UI.Xaml.
This version emits a package dependency instead of embedding the dependency in our own package.
This version should be tracked in build/packages.config.
-->
<TerminalMUXVersion Condition="'$(TerminalTargetWindowsVersion)'=='Win11'">2.7.3</TerminalMUXVersion>
</PropertyGroup>
</Project>

View File

@@ -2,22 +2,10 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- This file is read by XES, which we use in our Release builds. -->
<PropertyGroup Label="Version">
<!--
The Windows 11 build is going to have the same package name, so it *must* have a different version.
The easiest way for us to do this is to add 1 to the revision field.
In short, for a given Terminal build 1.11, we will emit two different versions (assume this is build
4 on day 23 of the year):
- 1.11.234.0 for Windows 10
- 1.11.235.0 for Windows 11
This presents a potential for conflicts if we want to ship two builds produced back to back on the
same day... which is terribly unlikely.
-->
<VersionBuildRevision Condition="'$(TerminalTargetWindowsVersion)'=='Win11' and '$(VersionBuildRevision)'!=''">$([MSBuild]::Add($(VersionBuildRevision), 1))</VersionBuildRevision>
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
<XesBaseYearForStoreVersion>2022</XesBaseYearForStoreVersion>
<XesBaseYearForStoreVersion>2023</XesBaseYearForStoreVersion>
<VersionMajor>1</VersionMajor>
<VersionMinor>17</VersionMinor>
<VersionMinor>19</VersionMinor>
<VersionInfoProductName>Windows Terminal</VersionInfoProductName>
</PropertyGroup>
</Project>

View File

@@ -4,12 +4,11 @@
<!-- Native packages -->
<package id="Microsoft.Internal.PGO-Helpers.Cpp" version="0.2.34" targetFramework="native" />
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
<package id="vcpkg-cpprestsdk" version="2.10.14" targetFramework="native" />
<package id="Microsoft.VCRTForwarders.140" version="1.0.4" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.230207.1" targetFramework="native" />
<package id="Microsoft.Internal.Windows.Terminal.ThemeHelpers" version="0.6.220404001" targetFramework="native" />
<package id="Microsoft.VisualStudio.Setup.Configuration.Native" version="2.3.2262" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.UI.Xaml" version="2.7.3-prerelease.220816001" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.8.4" targetFramework="native" />
<package id="Microsoft.Web.WebView2" version="1.0.1661.34" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.220201.1" targetFramework="native" developmentDependency="true" />
<!-- Managed packages -->

View File

@@ -24,6 +24,13 @@
"pattern": "^(-?\\d+)?(,\\s?(-?\\d+)?)?$",
"type": "string"
},
"CSSLengthPercentage": {
"pattern": "^[+-]?\\d+(?:\\.\\d+)?(?:%|ch|pt|px)?$",
"type": [
"string",
"null"
]
},
"DynamicProfileSource": {
"enum": [
"Windows.Terminal.Wsl",
@@ -314,6 +321,14 @@
}
},
"additionalProperties": false
},
"cellWidth": {
"$ref": "#/$defs/CSSLengthPercentage",
"description": "Override the width of the terminal's cells. The override works similar to CSS' letter-spacing. It defaults to the natural glyph advance width of the primary font rounded to the nearest pixel."
},
"cellHeight": {
"$ref": "#/$defs/CSSLengthPercentage",
"description": "Override the height of the terminal's cells. The override works similar to CSS' line-height. Defaults to the sum of the natural glyph ascend, descend and line-gap of the primary font rounded to the nearest pixel. The default is usually quite close to setting this to 1.2."
}
},
"type": "object"
@@ -1726,7 +1741,8 @@
"enum": [
"always",
"hover",
"never"
"never",
"activeOnly"
],
"type": "string"
},
@@ -1797,6 +1813,19 @@
"description": "True if the Terminal should use a Mica backdrop for the window. This will apply underneath all controls (including the terminal panes and the titlebar)",
"type": "boolean",
"default": false
},
"experimental.rainbowFrame": {
"description": "When enabled, the frame of the window will cycle through all the colors. Enabling this will override the `frame` and `unfocusedFrame` settings.",
"type": "boolean",
"default": false
},
"frame": {
"description": "The color of the window frame when the window is inactive. This only works on Windows 11",
"$ref": "#/$defs/ThemeColor"
},
"unfocusedFrame": {
"description": "The color of the window frame when the window is inactive. This only works on Windows 11",
"$ref": "#/$defs/ThemeColor"
}
}
},
@@ -1807,7 +1836,7 @@
"name": {
"type": "string",
"description": "The name of the theme. This will be displayed in the settings UI.",
"not": {
"not": {
"enum": [ "light", "dark", "system" ]
}
},
@@ -2077,6 +2106,11 @@
"description": "When set to true, the terminal will focus the pane on mouse hover.",
"type": "boolean"
},
"compatibility.isolatedMode": {
"default": false,
"description": "When set to true, Terminal windows will not be able to interact with each other (including global hotkeys, tab drag/drop, running commandlines in existing windows, etc.). This is a compatibility escape hatch for users who are running into certain windowing issues.",
"type": "boolean"
},
"copyFormatting": {
"default": true,
"description": "When set to `true`, the color and font formatting of selected text is also copied to your clipboard. When set to `false`, only plain text is copied to your clipboard. An array of specific formats can also be used. Supported array values include `html` and `rtf`. Plain text is always copied.",
@@ -2149,6 +2183,11 @@
"description": "When set to true, the background image for the currently focused profile is expanded to encompass the entire window, beneath other panes.",
"type": "boolean"
},
"compatibility.reloadEnvironmentVariables": {
"default": true,
"description": "When set to true, when opening a new tab or pane it will get reloaded environment variables.",
"type": "boolean"
},
"initialCols": {
"default": 120,
"description": "The number of columns displayed in the window upon first load. If \"launchMode\" is set to \"maximized\" (or \"maximizedFocus\"), this property is ignored.",
@@ -2549,6 +2588,13 @@
"default": false,
"description": "When true, this profile should always open in an elevated context. If the window isn't running as an Administrator, then a new elevated window will be created."
},
"environment": {
"description": "Key-value pairs representing environment variables to set. Environment variable names are not case sensitive. You can reference existing environment variable names by enclosing them in literal percent characters (e.g. %PATH%).",
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"experimental.autoMarkPrompts": {
"default": false,
"description": "When set to true, prompts will automatically be marked.",

235
doc/color_nudging.html Normal file
View File

@@ -0,0 +1,235 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Perceptual Color Nudging</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
html {
background-color: #0c0c0c;
color: #cccccc;
font-family: "Cascadia Code", "Cascadia Mono", monospace;
}
body {
display: flex;
margin: 0;
white-space: nowrap;
min-height: 100vh;
}
body>div {
display: flex;
flex-direction: column;
align-items: center;
padding: 2rem;
}
form,
h2 {
margin: 1rem;
}
p,
pre {
margin: 0.5rem;
}
table {
border-collapse: collapse;
}
table td {
padding: 0.5rem;
}
</style>
</head>
<body>
<div style="flex: 2; align-items: flex-start; background-color: #0c0c0c">
<form>
<input id="background-color" name="background-color" type="color" value="#0c0c0c" />
<label for="background-color">background color</label>
</form>
<table>
<tr>
<td>Input</td>
<td>WCAG21:<br>APCA:</td>
<td id="stats-input"></td>
</tr>
<tr>
<td>&Delta;E2000<br>(ConEmu)</td>
<td>WCAG21:<br>APCA:</td>
<td id="stats-cielab"></td>
</tr>
<tr>
<td>&Delta;EOK</td>
<td>WCAG21:<br>APCA:</td>
<td id="stats-oklab"></td>
</tr>
</table>
</div>
<div id="input" style="flex: 1">
<h2>Input</h2>
<pre style="font-size: 8pt">&#29483;</pre>
<pre style="font-size: 10pt">&#29483;</pre>
<pre style="font-size: 12pt">&#29483;</pre>
<pre style="font-size: 14pt">&#29483;</pre>
<pre style="font-size: 16pt">&#29483;</pre>
<pre style="font-size: 32pt">&#29483;</pre>
<pre style="font-size: 64pt">&#29483;</pre>
</div>
<div id="cielab" style="flex: 1">
<h2>&Delta;E2000 (ConEmu)</h2>
<pre style="font-size: 8pt">&#29483;</pre>
<pre style="font-size: 10pt">&#29483;</pre>
<pre style="font-size: 12pt">&#29483;</pre>
<pre style="font-size: 14pt">&#29483;</pre>
<pre style="font-size: 16pt">&#29483;</pre>
<pre style="font-size: 32pt">&#29483;</pre>
<pre style="font-size: 64pt">&#29483;</pre>
</div>
<div id="oklab" style="flex: 1">
<h2>&Delta;EOK</h2>
<pre style="font-size: 8pt">&#29483;</pre>
<pre style="font-size: 10pt">&#29483;</pre>
<pre style="font-size: 12pt">&#29483;</pre>
<pre style="font-size: 14pt">&#29483;</pre>
<pre style="font-size: 16pt">&#29483;</pre>
<pre style="font-size: 32pt">&#29483;</pre>
<pre style="font-size: 64pt">&#29483;</pre>
</div>
<script type="module">
import Color from "https://cdn.jsdelivr.net/npm/colorjs.io@0.4.3/+esm";
window.Color = Color;
const input = document.getElementById("input");
const cielab = document.getElementById("cielab");
const oklab = document.getElementById("oklab");
const statsInput = document.getElementById("stats-input");
const statsCielab = document.getElementById("stats-cielab");
const statsOklab = document.getElementById("stats-oklab");
let backgroundColor = new Color("#0c0c0c");
let foregroundColor = new Color("#0c0c0c");
let foregroundColorRange = null;
let previousSecsIntegral = -1;
function saturate(val) {
return val < 0 ? 0 : val > 1 ? 1 : val;
}
function clipToSrgb(color) {
return color.to("srgb").toGamut({ method: "clip" });
}
function nudgeCielab(backgroundColor, foregroundColor) {
const backgroundCielab = backgroundColor.to("lab-d65");
const foregroundCielab = foregroundColor.to("lab-d65");
const de1 = Color.deltaE(foregroundColor, backgroundCielab, "2000");
if (de1 >= 12.0) {
return foregroundColor;
}
for (let i = 0; i <= 1; i++) {
const step = (i == 0) ? 5.0 : -5.0;
foregroundCielab.l += step;
while (((i == 0) && foregroundCielab.l <= 100) || (i == 1 && foregroundCielab.l >= 0)) {
const de2 = Color.deltaE(foregroundCielab, backgroundCielab, "2000");
if (de2 >= 20.0) {
return clipToSrgb(foregroundCielab);
}
foregroundCielab.l += step;
}
}
}
function nudgeOklab(backgroundColor, foregroundColor) {
const backgroundOklab = backgroundColor.to("oklab");
const foregroundOklab = foregroundColor.to("oklab");
const deltaSquared = {
l: (backgroundOklab.l - foregroundOklab.l) ** 2,
a: (backgroundOklab.a - foregroundOklab.a) ** 2,
b: (backgroundOklab.b - foregroundOklab.b) ** 2,
};
const distance = deltaSquared.l + deltaSquared.a + deltaSquared.b;
if (distance >= 0.25) {
return foregroundColor;
}
let deltaL = Math.sqrt(0.25 - deltaSquared.a - deltaSquared.b);
if (foregroundOklab.l < backgroundOklab.l)
{
deltaL = -deltaL;
}
foregroundOklab.l = backgroundOklab.l + deltaL;
if (foregroundOklab.l < 0 || foregroundOklab.l > 1)
{
foregroundOklab.l = backgroundOklab.l - deltaL;
}
return clipToSrgb(foregroundOklab);
}
function contrastStringLevels(num, level0, level1) {
const str = num.toFixed(1);
if (num < level0) {
return `<span style="color:crimson">${str}</span>`;
}
if (num < level1) {
return `<span style="color:coral">${str}</span>`;
}
return str;
}
function contrastString(foregroundColor) {
const contrastWCAG21 = contrastStringLevels(foregroundColor.contrast(backgroundColor, "WCAG21"), 3, 4.5);
const contrastAPCA = contrastStringLevels(Math.abs(foregroundColor.contrast(backgroundColor, "APCA")), 45, 60);
return `${contrastWCAG21}<br/>${contrastAPCA}`;
}
function animate(time) {
const timeScale = time / 1000;
const secsIntegral = Math.trunc(timeScale);
const secsFractional = timeScale % 1;
if (previousSecsIntegral != secsIntegral) {
const foregroundColorTarget = new Color("srgb", backgroundColor.coords.map(c => saturate(c + Math.random() - 0.5)));
foregroundColorRange = foregroundColor.range(foregroundColorTarget, { space: "srgb" });
previousSecsIntegral = secsIntegral;
}
foregroundColor = foregroundColorRange(secsFractional);
input.style.color = foregroundColor.toString({ inGamut: false });
const foregroundCielabNudged = nudgeCielab(backgroundColor, foregroundColor);
const foregroundOklabNudged = nudgeOklab(backgroundColor, foregroundColor);
cielab.style.color = foregroundCielabNudged;
oklab.style.color = foregroundOklabNudged;
statsInput.innerHTML = contrastString(foregroundColor);
statsCielab.innerHTML = contrastString(foregroundCielabNudged);
statsOklab.innerHTML = contrastString(foregroundOklabNudged);
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
document.getElementById("background-color").addEventListener("input", event => {
backgroundColor = new Color(event.target.value);
document.documentElement.style.backgroundColor = backgroundColor;
}, false);
document.documentElement.style.backgroundColor = backgroundColor;
</script>
</body>
</html>

View File

@@ -0,0 +1,90 @@
---
author: Dustin L. Howett @DHowett
created on: 2023-03-22
last updated: 2023-03-22
issue id: none
---
# Windows Terminal "Portable" Mode
## Abstract
Since we are planning on officially supporting unpackaged execution, I propose a special mode where Terminal stores its
settings in a `settings` folder next to `WindowsTerminal.exe`.
## Inspiration
- [PortableApps](https://portableapps.com)
- "Embeddable" Python, which relies on the deployment of a specific file to the Python root
## Solution Design
- _If running without package identity,_ `CascadiaSettings` will look for the presence of a file called `.portable` next
to `Microsoft.Terminal.Settings.Model.dll`.
- If that file is present, it will change the settings and state paths to be rooted in a subfolder named `settings` next
to `Microsoft.Terminal.Settings.Model.dll`.
Right now, _the only thing_ that makes Terminal not work in a "portable" manner is that it saves settings to
`%LOCALAPPDATA%`.
## UI/UX Design
_No UI/UX impact is expected._
## Capabilities
- Distributors could ship a self-contained and preconfigured Terminal installation.
- Users could archive fully-working preconfigured versions of Terminal.
- Developers (such as those on the team) could easily test multiple versions of Terminal without worrying about global
settings pollution.
### Accessibility
_No change is expected._
### Security
_No change is expected._
### Reliability
More code always bears a risk.
### Compatibility
This is a net new feature, and it does not break any existing features. A distributor (or a user) can opt in (or out) by
adding (or removing) the `.portable` file.
The following features may be impacted.
- **Dynamic Profiles** and **Fragment Extensions**
- _No impact expected._ Dynamic profiles will still be generated. If a portable installation is moved to a machine without the dynamic profile source, that profile will disappear.
- `firstWindowPreference` and `state.json`
- _No impact expected._
- State is stored next to settings, even for portable installations.
- If a dynamic profile was saved in `state` and has been removed, Terminal will proceed as in non-portable mode.
- Moving an install from Windows 10 to Windows 11 and back
- _No impact expected._
- "Machine-specific" settings, like those about rendering and repainting
- _No impact expected._
- Terminal does not distinguish settings that are specific to a machine. These settings will move along with the portable install.
- The shell extension
- _No impact expected._
- The shell extension will not be registered with Windows.
- If we choose to register the shell extension, it is already prepared for running a version of WT from the same directory. Registering the portable shell extension will make it launch portable Terminal.
### Performance, Power, and Efficiency
_No change is expected._
## Potential Issues
- User confusion around where settings are stored.
## Future considerations
- In the future, perhaps `.portable` could itself contain a directory path into which we would store settings.
- We could consider adding an indicator in the Settings UI.
- Because we are using the module path of the Settings Model DLL, a future unpackaged version of the shell extension
that supports profile loading would read the right settings file (assuming it used the settings model.)
- If we choose to store the shell extension cache in the registry, we would need to avoid doing so in portable mode.

37
oss/stb/LICENSE Normal file
View File

@@ -0,0 +1,37 @@
This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,4 @@
### Notes for Future Maintainers
Search for files prefixed with `stb_` in this project.
At the time of writing, the only file being used is `stb_rect_pack.h`.

15
oss/stb/cgmanifest.json Normal file
View File

@@ -0,0 +1,15 @@
{
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
"Registrations": [
{
"component": {
"type": "git",
"git": {
"repositoryUrl": "https://github.com/nothings/stb",
"commitHash": "5736b15f7ea0ffb08dd38af21067c314d6a3aae9"
}
}
}
],
"Version": 1
}

623
oss/stb/stb_rect_pack.h Normal file
View File

@@ -0,0 +1,623 @@
// stb_rect_pack.h - v1.01 - public domain - rectangle packing
// Sean Barrett 2014
//
// Useful for e.g. packing rectangular textures into an atlas.
// Does not do rotation.
//
// Before #including,
//
// #define STB_RECT_PACK_IMPLEMENTATION
//
// in the file that you want to have the implementation.
//
// Not necessarily the awesomest packing method, but better than
// the totally naive one in stb_truetype (which is primarily what
// this is meant to replace).
//
// Has only had a few tests run, may have issues.
//
// More docs to come.
//
// No memory allocations; uses qsort() and assert() from stdlib.
// Can override those by defining STBRP_SORT and STBRP_ASSERT.
//
// This library currently uses the Skyline Bottom-Left algorithm.
//
// Please note: better rectangle packers are welcome! Please
// implement them to the same API, but with a different init
// function.
//
// Credits
//
// Library
// Sean Barrett
// Minor features
// Martins Mozeiko
// github:IntellectualKitty
//
// Bugfixes / warning fixes
// Jeremy Jaussaud
// Fabian Giesen
//
// Version history:
//
// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
// 0.99 (2019-02-07) warning fixes
// 0.11 (2017-03-03) return packing success/fail result
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
// 0.09 (2016-08-27) fix compiler warnings
// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
// 0.05: added STBRP_ASSERT to allow replacing assert
// 0.04: fixed minor bug in STBRP_LARGE_RECTS support
// 0.01: initial release
//
// LICENSE
//
// See end of file for license information.
//////////////////////////////////////////////////////////////////////////////
//
// INCLUDE SECTION
//
#ifndef STB_INCLUDE_STB_RECT_PACK_H
#define STB_INCLUDE_STB_RECT_PACK_H
#define STB_RECT_PACK_VERSION 1
#ifdef STBRP_STATIC
#define STBRP_DEF static
#else
#define STBRP_DEF extern
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct stbrp_context stbrp_context;
typedef struct stbrp_node stbrp_node;
typedef struct stbrp_rect stbrp_rect;
typedef int stbrp_coord;
#define STBRP__MAXVAL 0x7fffffff
// Mostly for internal use, but this is the maximum supported coordinate value.
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
// Assign packed locations to rectangles. The rectangles are of type
// 'stbrp_rect' defined below, stored in the array 'rects', and there
// are 'num_rects' many of them.
//
// Rectangles which are successfully packed have the 'was_packed' flag
// set to a non-zero value and 'x' and 'y' store the minimum location
// on each axis (i.e. bottom-left in cartesian coordinates, top-left
// if you imagine y increasing downwards). Rectangles which do not fit
// have the 'was_packed' flag set to 0.
//
// You should not try to access the 'rects' array from another thread
// while this function is running, as the function temporarily reorders
// the array while it executes.
//
// To pack into another rectangle, you need to call stbrp_init_target
// again. To continue packing into the same rectangle, you can call
// this function again. Calling this multiple times with multiple rect
// arrays will probably produce worse packing results than calling it
// a single time with the full rectangle array, but the option is
// available.
//
// The function returns 1 if all of the rectangles were successfully
// packed and 0 otherwise.
struct stbrp_rect
{
// reserved for your use:
int id;
// input:
stbrp_coord w, h;
// output:
stbrp_coord x, y;
int was_packed; // non-zero if valid packing
}; // 16 bytes, nominally
STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
// Initialize a rectangle packer to:
// pack a rectangle that is 'width' by 'height' in dimensions
// using temporary storage provided by the array 'nodes', which is 'num_nodes' long
//
// You must call this function every time you start packing into a new target.
//
// There is no "shutdown" function. The 'nodes' memory must stay valid for
// the following stbrp_pack_rects() call (or calls), but can be freed after
// the call (or calls) finish.
//
// Note: to guarantee best results, either:
// 1. make sure 'num_nodes' >= 'width'
// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
//
// If you don't do either of the above things, widths will be quantized to multiples
// of small integers to guarantee the algorithm doesn't run out of temporary storage.
//
// If you do #2, then the non-quantized algorithm will be used, but the algorithm
// may run out of temporary storage and be unable to pack some rectangles.
STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
// Optionally call this function after init but before doing any packing to
// change the handling of the out-of-temp-memory scenario, described above.
// If you call init again, this will be reset to the default (false).
STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
// Optionally select which packing heuristic the library should use. Different
// heuristics will produce better/worse results for different data sets.
// If you call init again, this will be reset to the default.
enum
{
STBRP_HEURISTIC_Skyline_default=0,
STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
STBRP_HEURISTIC_Skyline_BF_sortHeight
};
//////////////////////////////////////////////////////////////////////////////
//
// the details of the following structures don't matter to you, but they must
// be visible so you can handle the memory allocations for them
struct stbrp_node
{
stbrp_coord x,y;
stbrp_node *next;
};
struct stbrp_context
{
int width;
int height;
int align;
int init_mode;
int heuristic;
int num_nodes;
stbrp_node *active_head;
stbrp_node *free_head;
stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
};
#ifdef __cplusplus
}
#endif
#endif
//////////////////////////////////////////////////////////////////////////////
//
// IMPLEMENTATION SECTION
//
#ifdef STB_RECT_PACK_IMPLEMENTATION
#ifndef STBRP_SORT
#include <stdlib.h>
#define STBRP_SORT qsort
#endif
#ifndef STBRP_ASSERT
#include <assert.h>
#define STBRP_ASSERT assert
#endif
#ifdef _MSC_VER
#define STBRP__NOTUSED(v) (void)(v)
#define STBRP__CDECL __cdecl
#else
#define STBRP__NOTUSED(v) (void)sizeof(v)
#define STBRP__CDECL
#endif
enum
{
STBRP__INIT_skyline = 1
};
STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
{
switch (context->init_mode) {
case STBRP__INIT_skyline:
STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
context->heuristic = heuristic;
break;
default:
STBRP_ASSERT(0);
}
}
STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
{
if (allow_out_of_mem)
// if it's ok to run out of memory, then don't bother aligning them;
// this gives better packing, but may fail due to OOM (even though
// the rectangles easily fit). @TODO a smarter approach would be to only
// quantize once we've hit OOM, then we could get rid of this parameter.
context->align = 1;
else {
// if it's not ok to run out of memory, then quantize the widths
// so that num_nodes is always enough nodes.
//
// I.e. num_nodes * align >= width
// align >= width / num_nodes
// align = ceil(width/num_nodes)
context->align = (context->width + context->num_nodes-1) / context->num_nodes;
}
}
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
{
int i;
for (i=0; i < num_nodes-1; ++i)
nodes[i].next = &nodes[i+1];
nodes[i].next = NULL;
context->init_mode = STBRP__INIT_skyline;
context->heuristic = STBRP_HEURISTIC_Skyline_default;
context->free_head = &nodes[0];
context->active_head = &context->extra[0];
context->width = width;
context->height = height;
context->num_nodes = num_nodes;
stbrp_setup_allow_out_of_mem(context, 0);
// node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
context->extra[0].x = 0;
context->extra[0].y = 0;
context->extra[0].next = &context->extra[1];
context->extra[1].x = (stbrp_coord) width;
context->extra[1].y = (1<<30);
context->extra[1].next = NULL;
}
// find minimum y position if it starts at x1
static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
{
stbrp_node *node = first;
int x1 = x0 + width;
int min_y, visited_width, waste_area;
STBRP__NOTUSED(c);
STBRP_ASSERT(first->x <= x0);
#if 0
// skip in case we're past the node
while (node->next->x <= x0)
++node;
#else
STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
#endif
STBRP_ASSERT(node->x <= x0);
min_y = 0;
waste_area = 0;
visited_width = 0;
while (node->x < x1) {
if (node->y > min_y) {
// raise min_y higher.
// we've accounted for all waste up to min_y,
// but we'll now add more waste for everything we've visted
waste_area += visited_width * (node->y - min_y);
min_y = node->y;
// the first time through, visited_width might be reduced
if (node->x < x0)
visited_width += node->next->x - x0;
else
visited_width += node->next->x - node->x;
} else {
// add waste area
int under_width = node->next->x - node->x;
if (under_width + visited_width > width)
under_width = width - visited_width;
waste_area += under_width * (min_y - node->y);
visited_width += under_width;
}
node = node->next;
}
*pwaste = waste_area;
return min_y;
}
typedef struct
{
int x,y;
stbrp_node **prev_link;
} stbrp__findresult;
static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
{
int best_waste = (1<<30), best_x, best_y = (1 << 30);
stbrp__findresult fr;
stbrp_node **prev, *node, *tail, **best = NULL;
// align to multiple of c->align
width = (width + c->align - 1);
width -= width % c->align;
STBRP_ASSERT(width % c->align == 0);
// if it can't possibly fit, bail immediately
if (width > c->width || height > c->height) {
fr.prev_link = NULL;
fr.x = fr.y = 0;
return fr;
}
node = c->active_head;
prev = &c->active_head;
while (node->x + width <= c->width) {
int y,waste;
y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
// bottom left
if (y < best_y) {
best_y = y;
best = prev;
}
} else {
// best-fit
if (y + height <= c->height) {
// can only use it if it first vertically
if (y < best_y || (y == best_y && waste < best_waste)) {
best_y = y;
best_waste = waste;
best = prev;
}
}
}
prev = &node->next;
node = node->next;
}
best_x = (best == NULL) ? 0 : (*best)->x;
// if doing best-fit (BF), we also have to try aligning right edge to each node position
//
// e.g, if fitting
//
// ____________________
// |____________________|
//
// into
//
// | |
// | ____________|
// |____________|
//
// then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
//
// This makes BF take about 2x the time
if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
tail = c->active_head;
node = c->active_head;
prev = &c->active_head;
// find first node that's admissible
while (tail->x < width)
tail = tail->next;
while (tail) {
int xpos = tail->x - width;
int y,waste;
STBRP_ASSERT(xpos >= 0);
// find the left position that matches this
while (node->next->x <= xpos) {
prev = &node->next;
node = node->next;
}
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
if (y + height <= c->height) {
if (y <= best_y) {
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
best_x = xpos;
STBRP_ASSERT(y <= best_y);
best_y = y;
best_waste = waste;
best = prev;
}
}
}
tail = tail->next;
}
}
fr.prev_link = best;
fr.x = best_x;
fr.y = best_y;
return fr;
}
static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
{
// find best position according to heuristic
stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
stbrp_node *node, *cur;
// bail if:
// 1. it failed
// 2. the best node doesn't fit (we don't always check this)
// 3. we're out of memory
if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
res.prev_link = NULL;
return res;
}
// on success, create new node
node = context->free_head;
node->x = (stbrp_coord) res.x;
node->y = (stbrp_coord) (res.y + height);
context->free_head = node->next;
// insert the new node into the right starting point, and
// let 'cur' point to the remaining nodes needing to be
// stiched back in
cur = *res.prev_link;
if (cur->x < res.x) {
// preserve the existing one, so start testing with the next one
stbrp_node *next = cur->next;
cur->next = node;
cur = next;
} else {
*res.prev_link = node;
}
// from here, traverse cur and free the nodes, until we get to one
// that shouldn't be freed
while (cur->next && cur->next->x <= res.x + width) {
stbrp_node *next = cur->next;
// move the current node to the free list
cur->next = context->free_head;
context->free_head = cur;
cur = next;
}
// stitch the list back in
node->next = cur;
if (cur->x < res.x + width)
cur->x = (stbrp_coord) (res.x + width);
#ifdef _DEBUG
cur = context->active_head;
while (cur->x < context->width) {
STBRP_ASSERT(cur->x < cur->next->x);
cur = cur->next;
}
STBRP_ASSERT(cur->next == NULL);
{
int count=0;
cur = context->active_head;
while (cur) {
cur = cur->next;
++count;
}
cur = context->free_head;
while (cur) {
cur = cur->next;
++count;
}
STBRP_ASSERT(count == context->num_nodes+2);
}
#endif
return res;
}
static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
if (p->h > q->h)
return -1;
if (p->h < q->h)
return 1;
return (p->w > q->w) ? -1 : (p->w < q->w);
}
static int STBRP__CDECL rect_original_order(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
}
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
{
int i, all_rects_packed = 1;
// we use the 'was_packed' field internally to allow sorting/unsorting
for (i=0; i < num_rects; ++i) {
rects[i].was_packed = i;
}
// sort according to heuristic
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
for (i=0; i < num_rects; ++i) {
if (rects[i].w == 0 || rects[i].h == 0) {
rects[i].x = rects[i].y = 0; // empty rect needs no space
} else {
stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
if (fr.prev_link) {
rects[i].x = (stbrp_coord) fr.x;
rects[i].y = (stbrp_coord) fr.y;
} else {
rects[i].x = rects[i].y = STBRP__MAXVAL;
}
}
}
// unsort
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
// set was_packed flags and all_rects_packed status
for (i=0; i < num_rects; ++i) {
rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
if (!rects[i].was_packed)
all_rects_packed = 0;
}
// return the all_rects_packed status
return all_rects_packed;
}
#endif
/*
------------------------------------------------------------------------------
This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------------
*/

57
oss/tracy/TracyClient.cpp Normal file
View File

@@ -0,0 +1,57 @@
//
// Tracy profiler
// ----------------
//
// For fast integration, compile and
// link with this source file (and none
// other) in your executable (or in the
// main DLL / shared object on multi-DLL
// projects).
//
// Define TRACY_ENABLE to enable profiler.
#include "common/TracySystem.cpp"
#ifdef TRACY_ENABLE
#ifdef _MSC_VER
# pragma warning(push, 0)
#endif
#include "common/tracy_lz4.cpp"
#include "client/TracyProfiler.cpp"
#include "client/TracyCallstack.cpp"
#include "client/TracySysTime.cpp"
#include "client/TracySysTrace.cpp"
#include "common/TracySocket.cpp"
#include "client/tracy_rpmalloc.cpp"
#include "client/TracyDxt1.cpp"
#include "client/TracyAlloc.cpp"
#include "client/TracyOverride.cpp"
#if TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 6
# include "libbacktrace/alloc.cpp"
# include "libbacktrace/dwarf.cpp"
# include "libbacktrace/fileline.cpp"
# include "libbacktrace/mmapio.cpp"
# include "libbacktrace/posix.cpp"
# include "libbacktrace/sort.cpp"
# include "libbacktrace/state.cpp"
# if TRACY_HAS_CALLSTACK == 4
# include "libbacktrace/macho.cpp"
# else
# include "libbacktrace/elf.cpp"
# endif
# include "common/TracyStackFrames.cpp"
#endif
#ifdef _MSC_VER
# pragma comment(lib, "ws2_32.lib")
# pragma comment(lib, "dbghelp.lib")
# pragma comment(lib, "advapi32.lib")
# pragma comment(lib, "user32.lib")
# pragma warning(pop)
#endif
#endif

View File

@@ -0,0 +1,43 @@
#include "../common/TracyAlloc.hpp"
#ifdef TRACY_USE_RPMALLOC
#include <atomic>
#include "../common/TracyForceInline.hpp"
#include "../common/TracyYield.hpp"
namespace tracy
{
extern thread_local bool RpThreadInitDone;
extern std::atomic<int> RpInitDone;
extern std::atomic<int> RpInitLock;
tracy_no_inline static void InitRpmallocPlumbing()
{
const auto done = RpInitDone.load( std::memory_order_acquire );
if( !done )
{
int expected = 0;
while( !RpInitLock.compare_exchange_weak( expected, 1, std::memory_order_release, std::memory_order_relaxed ) ) { expected = 0; YieldThread(); }
const auto done = RpInitDone.load( std::memory_order_acquire );
if( !done )
{
rpmalloc_initialize();
RpInitDone.store( 1, std::memory_order_release );
}
RpInitLock.store( 0, std::memory_order_release );
}
rpmalloc_thread_initialize();
RpThreadInitDone = true;
}
TRACY_API void InitRpmalloc()
{
if( !RpThreadInitDone ) InitRpmallocPlumbing();
}
}
#endif

View File

@@ -0,0 +1,401 @@
namespace tracy
{
#if defined __linux__ && defined __ARM_ARCH
static const char* DecodeArmImplementer( uint32_t v )
{
static char buf[16];
switch( v )
{
case 0x41: return "ARM";
case 0x42: return "Broadcom";
case 0x43: return "Cavium";
case 0x44: return "DEC";
case 0x46: return "Fujitsu";
case 0x48: return "HiSilicon";
case 0x49: return "Infineon";
case 0x4d: return "Motorola";
case 0x4e: return "Nvidia";
case 0x50: return "Applied Micro";
case 0x51: return "Qualcomm";
case 0x53: return "Samsung";
case 0x54: return "Texas Instruments";
case 0x56: return "Marvell";
case 0x61: return "Apple";
case 0x66: return "Faraday";
case 0x68: return "HXT";
case 0x69: return "Intel";
case 0xc0: return "Ampere Computing";
default: break;
}
sprintf( buf, "0x%x", v );
return buf;
}
static const char* DecodeArmPart( uint32_t impl, uint32_t part )
{
static char buf[16];
switch( impl )
{
case 0x41: // ARM
switch( part )
{
case 0x810: return "810";
case 0x920: return "920";
case 0x922: return "922";
case 0x926: return "926";
case 0x940: return "940";
case 0x946: return "946";
case 0x966: return "966";
case 0xa20: return "1020";
case 0xa22: return "1022";
case 0xa26: return "1026";
case 0xb02: return "11 MPCore";
case 0xb36: return "1136";
case 0xb56: return "1156";
case 0xb76: return "1176";
case 0xc05: return " Cortex-A5";
case 0xc07: return " Cortex-A7";
case 0xc08: return " Cortex-A8";
case 0xc09: return " Cortex-A9";
case 0xc0c: return " Cortex-A12";
case 0xc0d: return " Rockchip RK3288";
case 0xc0e: return " Cortex-A17";
case 0xc0f: return " Cortex-A15";
case 0xc14: return " Cortex-R4";
case 0xc15: return " Cortex-R5";
case 0xc17: return " Cortex-R7";
case 0xc18: return " Cortex-R8";
case 0xc20: return " Cortex-M0";
case 0xc21: return " Cortex-M1";
case 0xc23: return " Cortex-M3";
case 0xc24: return " Cortex-M4";
case 0xc27: return " Cortex-M7";
case 0xc60: return " Cortex-M0+";
case 0xd00: return " AArch64 simulator";
case 0xd01: return " Cortex-A32";
case 0xd02: return " Cortex-A34";
case 0xd03: return " Cortex-A53";
case 0xd04: return " Cortex-A35";
case 0xd05: return " Cortex-A55";
case 0xd06: return " Cortex-A65";
case 0xd07: return " Cortex-A57";
case 0xd08: return " Cortex-A72";
case 0xd09: return " Cortex-A73";
case 0xd0a: return " Cortex-A75";
case 0xd0b: return " Cortex-A76";
case 0xd0c: return " Neoverse N1";
case 0xd0d: return " Cortex-A77";
case 0xd0e: return " Cortex-A76AE";
case 0xd0f: return " AEMv8";
case 0xd13: return " Cortex-R52";
case 0xd20: return " Cortex-M23";
case 0xd21: return " Cortex-M33";
case 0xd22: return " Cortex-M55";
case 0xd40: return " Neoverse V1";
case 0xd41: return " Cortex-A78";
case 0xd42: return " Cortex-A78AE";
case 0xd43: return " Cortex-A65AE";
case 0xd44: return " Cortex-X1";
case 0xd47: return " Cortex-A710";
case 0xd48: return " Cortex-X2";
case 0xd49: return " Neoverse N2";
case 0xd4a: return " Neoverse E1";
case 0xd4b: return " Cortex-A78C";
case 0xd4c: return " Cortex-X1C";
default: break;
}
case 0x42: // Broadcom
switch( part )
{
case 0xf: return " Brahma B15";
case 0x100: return " Brahma B53";
case 0x516: return " ThunderX2";
default: break;
}
case 0x43: // Cavium
switch( part )
{
case 0xa0: return " ThunderX";
case 0xa1: return " ThunderX 88XX";
case 0xa2: return " ThunderX 81XX";
case 0xa3: return " ThunderX 83XX";
case 0xaf: return " ThunderX2 99xx";
case 0xb0: return " OcteonTX2";
case 0xb1: return " OcteonTX2 T98";
case 0xb2: return " OcteonTX2 T96";
case 0xb3: return " OcteonTX2 F95";
case 0xb4: return " OcteonTX2 F95N";
case 0xb5: return " OcteonTX2 F95MM";
case 0xb6: return " OcteonTX2 F95O";
case 0xb8: return " ThunderX3 T110";
default: break;
}
case 0x44: // DEC
switch( part )
{
case 0xa10: return " SA110";
case 0xa11: return " SA1100";
default: break;
}
case 0x46: // Fujitsu
switch( part )
{
case 0x1: return " A64FX";
default: break;
}
case 0x48: // HiSilicon
switch( part )
{
case 0xd01: return " TSV100";
case 0xd40: return " Kirin 980";
default: break;
}
case 0x4e: // Nvidia
switch( part )
{
case 0x0: return " Denver";
case 0x3: return " Denver 2";
case 0x4: return " Carmel";
default: break;
}
case 0x50: // Applied Micro
switch( part )
{
case 0x0: return " X-Gene";
default: break;
}
case 0x51: // Qualcomm
switch( part )
{
case 0xf: return " Scorpion";
case 0x2d: return " Scorpion";
case 0x4d: return " Krait";
case 0x6f: return " Krait";
case 0x200: return " Kryo";
case 0x201: return " Kryo Silver (Snapdragon 821)";
case 0x205: return " Kryo Gold";
case 0x211: return " Kryo Silver (Snapdragon 820)";
case 0x800: return " Kryo 260 / 280 Gold";
case 0x801: return " Kryo 260 / 280 Silver";
case 0x802: return " Kryo 385 Gold";
case 0x803: return " Kryo 385 Silver";
case 0x804: return " Kryo 485 Gold";
case 0x805: return " Kryo 4xx/5xx Silver";
case 0xc00: return " Falkor";
case 0xc01: return " Saphira";
default: break;
}
case 0x53: // Samsung
switch( part )
{
case 0x1: return " Exynos M1/M2";
case 0x2: return " Exynos M3";
case 0x3: return " Exynos M4";
case 0x4: return " Exynos M5";
default: break;
}
case 0x54: // Texas Instruments
switch( part )
{
case 0x925: return " TI925";
default: break;
}
case 0x56: // Marvell
switch( part )
{
case 0x131: return " Feroceon 88FR131";
case 0x581: return " PJ4 / PJ4B";
case 0x584: return " PJ4B-MP / PJ4C";
default: break;
}
case 0x61: // Apple
switch( part )
{
case 0x1: return " Cyclone";
case 0x2: return " Typhoon";
case 0x3: return " Typhoon/Capri";
case 0x4: return " Twister";
case 0x5: return " Twister/Elba/Malta";
case 0x6: return " Hurricane";
case 0x7: return " Hurricane/Myst";
case 0x22: return " M1 Icestorm";
case 0x23: return " M1 Firestorm";
case 0x24: return " M1 Icestorm Pro";
case 0x25: return " M1 Firestorm Pro";
case 0x28: return " M1 Icestorm Max";
case 0x29: return " M1 Firestorm Max";
default: break;
}
case 0x66: // Faraday
switch( part )
{
case 0x526: return " FA526";
case 0x626: return " FA626";
default: break;
}
case 0x68: // HXT
switch( part )
{
case 0x0: return " Phecda";
default: break;
}
case 0xc0: // Ampere Computing
switch( part )
{
case 0xac3: return " Ampere1";
default: break;
}
default: break;
}
sprintf( buf, " 0x%x", part );
return buf;
}
#elif defined __APPLE__ && TARGET_OS_IPHONE == 1
static const char* DecodeIosDevice( const char* id )
{
static const char* DeviceTable[] = {
"i386", "32-bit simulator",
"x86_64", "64-bit simulator",
"iPhone1,1", "iPhone",
"iPhone1,2", "iPhone 3G",
"iPhone2,1", "iPhone 3GS",
"iPhone3,1", "iPhone 4 (GSM)",
"iPhone3,2", "iPhone 4 (GSM)",
"iPhone3,3", "iPhone 4 (CDMA)",
"iPhone4,1", "iPhone 4S",
"iPhone5,1", "iPhone 5 (A1428)",
"iPhone5,2", "iPhone 5 (A1429)",
"iPhone5,3", "iPhone 5c (A1456/A1532)",
"iPhone5,4", "iPhone 5c (A1507/A1516/1526/A1529)",
"iPhone6,1", "iPhone 5s (A1433/A1533)",
"iPhone6,2", "iPhone 5s (A1457/A1518/A1528/A1530)",
"iPhone7,1", "iPhone 6 Plus",
"iPhone7,2", "iPhone 6",
"iPhone8,1", "iPhone 6S",
"iPhone8,2", "iPhone 6S Plus",
"iPhone8,4", "iPhone SE",
"iPhone9,1", "iPhone 7 (CDMA)",
"iPhone9,2", "iPhone 7 Plus (CDMA)",
"iPhone9,3", "iPhone 7 (GSM)",
"iPhone9,4", "iPhone 7 Plus (GSM)",
"iPhone10,1", "iPhone 8 (CDMA)",
"iPhone10,2", "iPhone 8 Plus (CDMA)",
"iPhone10,3", "iPhone X (CDMA)",
"iPhone10,4", "iPhone 8 (GSM)",
"iPhone10,5", "iPhone 8 Plus (GSM)",
"iPhone10,6", "iPhone X (GSM)",
"iPhone11,2", "iPhone XS",
"iPhone11,4", "iPhone XS Max",
"iPhone11,6", "iPhone XS Max China",
"iPhone11,8", "iPhone XR",
"iPhone12,1", "iPhone 11",
"iPhone12,3", "iPhone 11 Pro",
"iPhone12,5", "iPhone 11 Pro Max",
"iPhone12,8", "iPhone SE 2nd Gen",
"iPhone13,1", "iPhone 12 Mini",
"iPhone13,2", "iPhone 12",
"iPhone13,3", "iPhone 12 Pro",
"iPhone13,4", "iPhone 12 Pro Max",
"iPhone14,2", "iPhone 13 Pro",
"iPhone14,3", "iPhone 13 Pro Max",
"iPhone14,4", "iPhone 13 Mini",
"iPhone14,5", "iPhone 13",
"iPhone14,6", "iPhone SE 3rd Gen",
"iPad1,1", "iPad (A1219/A1337)",
"iPad2,1", "iPad 2 (A1395)",
"iPad2,2", "iPad 2 (A1396)",
"iPad2,3", "iPad 2 (A1397)",
"iPad2,4", "iPad 2 (A1395)",
"iPad2,5", "iPad Mini (A1432)",
"iPad2,6", "iPad Mini (A1454)",
"iPad2,7", "iPad Mini (A1455)",
"iPad3,1", "iPad 3 (A1416)",
"iPad3,2", "iPad 3 (A1403)",
"iPad3,3", "iPad 3 (A1430)",
"iPad3,4", "iPad 4 (A1458)",
"iPad3,5", "iPad 4 (A1459)",
"iPad3,6", "iPad 4 (A1460)",
"iPad4,1", "iPad Air (A1474)",
"iPad4,2", "iPad Air (A1475)",
"iPad4,3", "iPad Air (A1476)",
"iPad4,4", "iPad Mini 2 (A1489)",
"iPad4,5", "iPad Mini 2 (A1490)",
"iPad4,6", "iPad Mini 2 (A1491)",
"iPad4,7", "iPad Mini 3 (A1599)",
"iPad4,8", "iPad Mini 3 (A1600)",
"iPad4,9", "iPad Mini 3 (A1601)",
"iPad5,1", "iPad Mini 4 (A1538)",
"iPad5,2", "iPad Mini 4 (A1550)",
"iPad5,3", "iPad Air 2 (A1566)",
"iPad5,4", "iPad Air 2 (A1567)",
"iPad6,3", "iPad Pro 9.7\" (A1673)",
"iPad6,4", "iPad Pro 9.7\" (A1674)",
"iPad6,5", "iPad Pro 9.7\" (A1675)",
"iPad6,7", "iPad Pro 12.9\" (A1584)",
"iPad6,8", "iPad Pro 12.9\" (A1652)",
"iPad6,11", "iPad 5th gen (A1822)",
"iPad6,12", "iPad 5th gen (A1823)",
"iPad7,1", "iPad Pro 12.9\" 2nd gen (A1670)",
"iPad7,2", "iPad Pro 12.9\" 2nd gen (A1671/A1821)",
"iPad7,3", "iPad Pro 10.5\" (A1701)",
"iPad7,4", "iPad Pro 10.5\" (A1709)",
"iPad7,5", "iPad 6th gen (A1893)",
"iPad7,6", "iPad 6th gen (A1954)",
"iPad7,11", "iPad 7th gen 10.2\" (Wifi)",
"iPad7,12", "iPad 7th gen 10.2\" (Wifi+Cellular)",
"iPad8,1", "iPad Pro 11\" (A1980)",
"iPad8,2", "iPad Pro 11\" (A1980)",
"iPad8,3", "iPad Pro 11\" (A1934/A1979/A2013)",
"iPad8,4", "iPad Pro 11\" (A1934/A1979/A2013)",
"iPad8,5", "iPad Pro 12.9\" 3rd gen (A1876)",
"iPad8,6", "iPad Pro 12.9\" 3rd gen (A1876)",
"iPad8,7", "iPad Pro 12.9\" 3rd gen (A1895/A1983/A2014)",
"iPad8,8", "iPad Pro 12.9\" 3rd gen (A1895/A1983/A2014)",
"iPad8,9", "iPad Pro 11\" 2nd gen (Wifi)",
"iPad8,10", "iPad Pro 11\" 2nd gen (Wifi+Cellular)",
"iPad8,11", "iPad Pro 12.9\" 4th gen (Wifi)",
"iPad8,12", "iPad Pro 12.9\" 4th gen (Wifi+Cellular)",
"iPad11,1", "iPad Mini 5th gen (A2133)",
"iPad11,2", "iPad Mini 5th gen (A2124/A2125/A2126)",
"iPad11,3", "iPad Air 3rd gen (A2152)",
"iPad11,4", "iPad Air 3rd gen (A2123/A2153/A2154)",
"iPad11,6", "iPad 8th gen (WiFi)",
"iPad11,7", "iPad 8th gen (WiFi+Cellular)",
"iPad13,1", "iPad Air 4th gen (WiFi)",
"iPad13,2", "iPad Air 4th gen (WiFi+Cellular)",
"iPad13,4", "iPad Pro 11\" 3rd gen",
"iPad13,5", "iPad Pro 11\" 3rd gen",
"iPad13,6", "iPad Pro 11\" 3rd gen",
"iPad13,7", "iPad Pro 11\" 3rd gen",
"iPad13,8", "iPad Pro 12.9\" 5th gen",
"iPad13,9", "iPad Pro 12.9\" 5th gen",
"iPad13,10", "iPad Pro 12.9\" 5th gen",
"iPad13,11", "iPad Pro 12.9\" 5th gen",
"iPad13,16", "iPad Air 5th Gen (WiFi)",
"iPad13,17", "iPad Air 5th Gen (WiFi+Cellular)",
"iPod1,1", "iPod Touch",
"iPod2,1", "iPod Touch 2nd gen",
"iPod3,1", "iPod Touch 3rd gen",
"iPod4,1", "iPod Touch 4th gen",
"iPod5,1", "iPod Touch 5th gen",
"iPod7,1", "iPod Touch 6th gen",
"iPod9,1", "iPod Touch 7th gen",
nullptr
};
auto ptr = DeviceTable;
while( *ptr )
{
if( strcmp( ptr[0], id ) == 0 ) return ptr[1];
ptr += 2;
}
return id;
}
#endif
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
#ifndef __TRACYCALLSTACK_H__
#define __TRACYCALLSTACK_H__
#ifndef TRACY_NO_CALLSTACK
# if !defined _WIN32
# include <sys/param.h>
# endif
# if defined _WIN32
# include "../common/TracyUwp.hpp"
# ifndef TRACY_UWP
# define TRACY_HAS_CALLSTACK 1
# endif
# elif defined __ANDROID__
# if !defined __arm__ || __ANDROID_API__ >= 21
# define TRACY_HAS_CALLSTACK 2
# else
# define TRACY_HAS_CALLSTACK 5
# endif
# elif defined __linux
# if defined _GNU_SOURCE && defined __GLIBC__
# define TRACY_HAS_CALLSTACK 3
# else
# define TRACY_HAS_CALLSTACK 2
# endif
# elif defined __APPLE__
# define TRACY_HAS_CALLSTACK 4
# elif defined BSD
# define TRACY_HAS_CALLSTACK 6
# endif
#endif
#endif

View File

@@ -0,0 +1,142 @@
#ifndef __TRACYCALLSTACK_HPP__
#define __TRACYCALLSTACK_HPP__
#include "../common/TracyApi.h"
#include "../common/TracyForceInline.hpp"
#include "TracyCallstack.h"
#if TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 5
# include <unwind.h>
#elif TRACY_HAS_CALLSTACK >= 3
# include <execinfo.h>
#endif
#ifndef TRACY_HAS_CALLSTACK
namespace tracy
{
static tracy_force_inline void* Callstack( int depth ) { return nullptr; }
}
#else
#ifdef TRACY_DEBUGINFOD
# include <elfutils/debuginfod.h>
#endif
#include <assert.h>
#include <stdint.h>
#include "../common/TracyAlloc.hpp"
namespace tracy
{
struct CallstackSymbolData
{
const char* file;
uint32_t line;
bool needFree;
uint64_t symAddr;
};
struct CallstackEntry
{
const char* name;
const char* file;
uint32_t line;
uint32_t symLen;
uint64_t symAddr;
};
struct CallstackEntryData
{
const CallstackEntry* data;
uint8_t size;
const char* imageName;
};
CallstackSymbolData DecodeSymbolAddress( uint64_t ptr );
const char* DecodeCallstackPtrFast( uint64_t ptr );
CallstackEntryData DecodeCallstackPtr( uint64_t ptr );
void InitCallstack();
void InitCallstackCritical();
void EndCallstack();
const char* GetKernelModulePath( uint64_t addr );
#ifdef TRACY_DEBUGINFOD
const uint8_t* GetBuildIdForImage( const char* image, size_t& size );
debuginfod_client* GetDebuginfodClient();
#endif
#if TRACY_HAS_CALLSTACK == 1
extern "C"
{
typedef unsigned long (__stdcall *___tracy_t_RtlWalkFrameChain)( void**, unsigned long, unsigned long );
TRACY_API extern ___tracy_t_RtlWalkFrameChain ___tracy_RtlWalkFrameChain;
}
static tracy_force_inline void* Callstack( int depth )
{
assert( depth >= 1 && depth < 63 );
auto trace = (uintptr_t*)tracy_malloc( ( 1 + depth ) * sizeof( uintptr_t ) );
const auto num = ___tracy_RtlWalkFrameChain( (void**)( trace + 1 ), depth, 0 );
*trace = num;
return trace;
}
#elif TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 5
struct BacktraceState
{
void** current;
void** end;
};
static _Unwind_Reason_Code tracy_unwind_callback( struct _Unwind_Context* ctx, void* arg )
{
auto state = (BacktraceState*)arg;
uintptr_t pc = _Unwind_GetIP( ctx );
if( pc )
{
if( state->current == state->end ) return _URC_END_OF_STACK;
*state->current++ = (void*)pc;
}
return _URC_NO_REASON;
}
static tracy_force_inline void* Callstack( int depth )
{
assert( depth >= 1 && depth < 63 );
auto trace = (uintptr_t*)tracy_malloc( ( 1 + depth ) * sizeof( uintptr_t ) );
BacktraceState state = { (void**)(trace+1), (void**)(trace+1+depth) };
_Unwind_Backtrace( tracy_unwind_callback, &state );
*trace = (uintptr_t*)state.current - trace + 1;
return trace;
}
#elif TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 6
static tracy_force_inline void* Callstack( int depth )
{
assert( depth >= 1 );
auto trace = (uintptr_t*)tracy_malloc( ( 1 + (size_t)depth ) * sizeof( uintptr_t ) );
const auto num = (size_t)backtrace( (void**)(trace+1), depth );
*trace = num;
return trace;
}
#endif
}
#endif
#endif

View File

@@ -0,0 +1,12 @@
#ifndef __TRACYCPUID_HPP__
#define __TRACYCPUID_HPP__
// Prior to GCC 11 the cpuid.h header did not have any include guards and thus
// including it more than once would cause a compiler error due to symbol
// redefinitions. In order to support older GCC versions, we have to wrap this
// include between custom include guards to prevent this issue.
// See also https://github.com/wolfpld/tracy/issues/452
#include <cpuid.h>
#endif

View File

@@ -0,0 +1,11 @@
#ifndef __TRACYPRINT_HPP__
#define __TRACYPRINT_HPP__
#ifdef TRACY_VERBOSE
# include <stdio.h>
# define TracyDebug(...) fprintf( stderr, __VA_ARGS__ );
#else
# define TracyDebug(...)
#endif
#endif

View File

@@ -0,0 +1,644 @@
#include "TracyDxt1.hpp"
#include "../common/TracyForceInline.hpp"
#include <assert.h>
#include <stdint.h>
#include <string.h>
#ifdef __ARM_NEON
# include <arm_neon.h>
#endif
#if defined __AVX__ && !defined __SSE4_1__
# define __SSE4_1__
#endif
#if defined __SSE4_1__ || defined __AVX2__
# ifdef _MSC_VER
# include <intrin.h>
# else
# include <x86intrin.h>
# ifndef _mm256_cvtsi256_si32
# define _mm256_cvtsi256_si32( v ) ( _mm_cvtsi128_si32( _mm256_castsi256_si128( v ) ) )
# endif
# endif
#endif
namespace tracy
{
static inline uint16_t to565( uint8_t r, uint8_t g, uint8_t b )
{
return ( ( r & 0xF8 ) << 8 ) | ( ( g & 0xFC ) << 3 ) | ( b >> 3 );
}
static inline uint16_t to565( uint32_t c )
{
return
( ( c & 0xF80000 ) >> 19 ) |
( ( c & 0x00FC00 ) >> 5 ) |
( ( c & 0x0000F8 ) << 8 );
}
static const uint16_t DivTable[255*3+1] = {
0xffff, 0xffff, 0xffff, 0xffff, 0xcccc, 0xaaaa, 0x9249, 0x8000, 0x71c7, 0x6666, 0x5d17, 0x5555, 0x4ec4, 0x4924, 0x4444, 0x4000,
0x3c3c, 0x38e3, 0x35e5, 0x3333, 0x30c3, 0x2e8b, 0x2c85, 0x2aaa, 0x28f5, 0x2762, 0x25ed, 0x2492, 0x234f, 0x2222, 0x2108, 0x2000,
0x1f07, 0x1e1e, 0x1d41, 0x1c71, 0x1bac, 0x1af2, 0x1a41, 0x1999, 0x18f9, 0x1861, 0x17d0, 0x1745, 0x16c1, 0x1642, 0x15c9, 0x1555,
0x14e5, 0x147a, 0x1414, 0x13b1, 0x1352, 0x12f6, 0x129e, 0x1249, 0x11f7, 0x11a7, 0x115b, 0x1111, 0x10c9, 0x1084, 0x1041, 0x1000,
0x0fc0, 0x0f83, 0x0f48, 0x0f0f, 0x0ed7, 0x0ea0, 0x0e6c, 0x0e38, 0x0e07, 0x0dd6, 0x0da7, 0x0d79, 0x0d4c, 0x0d20, 0x0cf6, 0x0ccc,
0x0ca4, 0x0c7c, 0x0c56, 0x0c30, 0x0c0c, 0x0be8, 0x0bc5, 0x0ba2, 0x0b81, 0x0b60, 0x0b40, 0x0b21, 0x0b02, 0x0ae4, 0x0ac7, 0x0aaa,
0x0a8e, 0x0a72, 0x0a57, 0x0a3d, 0x0a23, 0x0a0a, 0x09f1, 0x09d8, 0x09c0, 0x09a9, 0x0991, 0x097b, 0x0964, 0x094f, 0x0939, 0x0924,
0x090f, 0x08fb, 0x08e7, 0x08d3, 0x08c0, 0x08ad, 0x089a, 0x0888, 0x0876, 0x0864, 0x0853, 0x0842, 0x0831, 0x0820, 0x0810, 0x0800,
0x07f0, 0x07e0, 0x07d1, 0x07c1, 0x07b3, 0x07a4, 0x0795, 0x0787, 0x0779, 0x076b, 0x075d, 0x0750, 0x0743, 0x0736, 0x0729, 0x071c,
0x070f, 0x0703, 0x06f7, 0x06eb, 0x06df, 0x06d3, 0x06c8, 0x06bc, 0x06b1, 0x06a6, 0x069b, 0x0690, 0x0685, 0x067b, 0x0670, 0x0666,
0x065c, 0x0652, 0x0648, 0x063e, 0x0634, 0x062b, 0x0621, 0x0618, 0x060f, 0x0606, 0x05fd, 0x05f4, 0x05eb, 0x05e2, 0x05d9, 0x05d1,
0x05c9, 0x05c0, 0x05b8, 0x05b0, 0x05a8, 0x05a0, 0x0598, 0x0590, 0x0588, 0x0581, 0x0579, 0x0572, 0x056b, 0x0563, 0x055c, 0x0555,
0x054e, 0x0547, 0x0540, 0x0539, 0x0532, 0x052b, 0x0525, 0x051e, 0x0518, 0x0511, 0x050b, 0x0505, 0x04fe, 0x04f8, 0x04f2, 0x04ec,
0x04e6, 0x04e0, 0x04da, 0x04d4, 0x04ce, 0x04c8, 0x04c3, 0x04bd, 0x04b8, 0x04b2, 0x04ad, 0x04a7, 0x04a2, 0x049c, 0x0497, 0x0492,
0x048d, 0x0487, 0x0482, 0x047d, 0x0478, 0x0473, 0x046e, 0x0469, 0x0465, 0x0460, 0x045b, 0x0456, 0x0452, 0x044d, 0x0448, 0x0444,
0x043f, 0x043b, 0x0436, 0x0432, 0x042d, 0x0429, 0x0425, 0x0421, 0x041c, 0x0418, 0x0414, 0x0410, 0x040c, 0x0408, 0x0404, 0x0400,
0x03fc, 0x03f8, 0x03f4, 0x03f0, 0x03ec, 0x03e8, 0x03e4, 0x03e0, 0x03dd, 0x03d9, 0x03d5, 0x03d2, 0x03ce, 0x03ca, 0x03c7, 0x03c3,
0x03c0, 0x03bc, 0x03b9, 0x03b5, 0x03b2, 0x03ae, 0x03ab, 0x03a8, 0x03a4, 0x03a1, 0x039e, 0x039b, 0x0397, 0x0394, 0x0391, 0x038e,
0x038b, 0x0387, 0x0384, 0x0381, 0x037e, 0x037b, 0x0378, 0x0375, 0x0372, 0x036f, 0x036c, 0x0369, 0x0366, 0x0364, 0x0361, 0x035e,
0x035b, 0x0358, 0x0355, 0x0353, 0x0350, 0x034d, 0x034a, 0x0348, 0x0345, 0x0342, 0x0340, 0x033d, 0x033a, 0x0338, 0x0335, 0x0333,
0x0330, 0x032e, 0x032b, 0x0329, 0x0326, 0x0324, 0x0321, 0x031f, 0x031c, 0x031a, 0x0317, 0x0315, 0x0313, 0x0310, 0x030e, 0x030c,
0x0309, 0x0307, 0x0305, 0x0303, 0x0300, 0x02fe, 0x02fc, 0x02fa, 0x02f7, 0x02f5, 0x02f3, 0x02f1, 0x02ef, 0x02ec, 0x02ea, 0x02e8,
0x02e6, 0x02e4, 0x02e2, 0x02e0, 0x02de, 0x02dc, 0x02da, 0x02d8, 0x02d6, 0x02d4, 0x02d2, 0x02d0, 0x02ce, 0x02cc, 0x02ca, 0x02c8,
0x02c6, 0x02c4, 0x02c2, 0x02c0, 0x02be, 0x02bc, 0x02bb, 0x02b9, 0x02b7, 0x02b5, 0x02b3, 0x02b1, 0x02b0, 0x02ae, 0x02ac, 0x02aa,
0x02a8, 0x02a7, 0x02a5, 0x02a3, 0x02a1, 0x02a0, 0x029e, 0x029c, 0x029b, 0x0299, 0x0297, 0x0295, 0x0294, 0x0292, 0x0291, 0x028f,
0x028d, 0x028c, 0x028a, 0x0288, 0x0287, 0x0285, 0x0284, 0x0282, 0x0280, 0x027f, 0x027d, 0x027c, 0x027a, 0x0279, 0x0277, 0x0276,
0x0274, 0x0273, 0x0271, 0x0270, 0x026e, 0x026d, 0x026b, 0x026a, 0x0268, 0x0267, 0x0265, 0x0264, 0x0263, 0x0261, 0x0260, 0x025e,
0x025d, 0x025c, 0x025a, 0x0259, 0x0257, 0x0256, 0x0255, 0x0253, 0x0252, 0x0251, 0x024f, 0x024e, 0x024d, 0x024b, 0x024a, 0x0249,
0x0247, 0x0246, 0x0245, 0x0243, 0x0242, 0x0241, 0x0240, 0x023e, 0x023d, 0x023c, 0x023b, 0x0239, 0x0238, 0x0237, 0x0236, 0x0234,
0x0233, 0x0232, 0x0231, 0x0230, 0x022e, 0x022d, 0x022c, 0x022b, 0x022a, 0x0229, 0x0227, 0x0226, 0x0225, 0x0224, 0x0223, 0x0222,
0x0220, 0x021f, 0x021e, 0x021d, 0x021c, 0x021b, 0x021a, 0x0219, 0x0218, 0x0216, 0x0215, 0x0214, 0x0213, 0x0212, 0x0211, 0x0210,
0x020f, 0x020e, 0x020d, 0x020c, 0x020b, 0x020a, 0x0209, 0x0208, 0x0207, 0x0206, 0x0205, 0x0204, 0x0203, 0x0202, 0x0201, 0x0200,
0x01ff, 0x01fe, 0x01fd, 0x01fc, 0x01fb, 0x01fa, 0x01f9, 0x01f8, 0x01f7, 0x01f6, 0x01f5, 0x01f4, 0x01f3, 0x01f2, 0x01f1, 0x01f0,
0x01ef, 0x01ee, 0x01ed, 0x01ec, 0x01eb, 0x01ea, 0x01e9, 0x01e9, 0x01e8, 0x01e7, 0x01e6, 0x01e5, 0x01e4, 0x01e3, 0x01e2, 0x01e1,
0x01e0, 0x01e0, 0x01df, 0x01de, 0x01dd, 0x01dc, 0x01db, 0x01da, 0x01da, 0x01d9, 0x01d8, 0x01d7, 0x01d6, 0x01d5, 0x01d4, 0x01d4,
0x01d3, 0x01d2, 0x01d1, 0x01d0, 0x01cf, 0x01cf, 0x01ce, 0x01cd, 0x01cc, 0x01cb, 0x01cb, 0x01ca, 0x01c9, 0x01c8, 0x01c7, 0x01c7,
0x01c6, 0x01c5, 0x01c4, 0x01c3, 0x01c3, 0x01c2, 0x01c1, 0x01c0, 0x01c0, 0x01bf, 0x01be, 0x01bd, 0x01bd, 0x01bc, 0x01bb, 0x01ba,
0x01ba, 0x01b9, 0x01b8, 0x01b7, 0x01b7, 0x01b6, 0x01b5, 0x01b4, 0x01b4, 0x01b3, 0x01b2, 0x01b2, 0x01b1, 0x01b0, 0x01af, 0x01af,
0x01ae, 0x01ad, 0x01ad, 0x01ac, 0x01ab, 0x01aa, 0x01aa, 0x01a9, 0x01a8, 0x01a8, 0x01a7, 0x01a6, 0x01a6, 0x01a5, 0x01a4, 0x01a4,
0x01a3, 0x01a2, 0x01a2, 0x01a1, 0x01a0, 0x01a0, 0x019f, 0x019e, 0x019e, 0x019d, 0x019c, 0x019c, 0x019b, 0x019a, 0x019a, 0x0199,
0x0198, 0x0198, 0x0197, 0x0197, 0x0196, 0x0195, 0x0195, 0x0194, 0x0193, 0x0193, 0x0192, 0x0192, 0x0191, 0x0190, 0x0190, 0x018f,
0x018f, 0x018e, 0x018d, 0x018d, 0x018c, 0x018b, 0x018b, 0x018a, 0x018a, 0x0189, 0x0189, 0x0188, 0x0187, 0x0187, 0x0186, 0x0186,
0x0185, 0x0184, 0x0184, 0x0183, 0x0183, 0x0182, 0x0182, 0x0181, 0x0180, 0x0180, 0x017f, 0x017f, 0x017e, 0x017e, 0x017d, 0x017d,
0x017c, 0x017b, 0x017b, 0x017a, 0x017a, 0x0179, 0x0179, 0x0178, 0x0178, 0x0177, 0x0177, 0x0176, 0x0175, 0x0175, 0x0174, 0x0174,
0x0173, 0x0173, 0x0172, 0x0172, 0x0171, 0x0171, 0x0170, 0x0170, 0x016f, 0x016f, 0x016e, 0x016e, 0x016d, 0x016d, 0x016c, 0x016c,
0x016b, 0x016b, 0x016a, 0x016a, 0x0169, 0x0169, 0x0168, 0x0168, 0x0167, 0x0167, 0x0166, 0x0166, 0x0165, 0x0165, 0x0164, 0x0164,
0x0163, 0x0163, 0x0162, 0x0162, 0x0161, 0x0161, 0x0160, 0x0160, 0x015f, 0x015f, 0x015e, 0x015e, 0x015d, 0x015d, 0x015d, 0x015c,
0x015c, 0x015b, 0x015b, 0x015a, 0x015a, 0x0159, 0x0159, 0x0158, 0x0158, 0x0158, 0x0157, 0x0157, 0x0156, 0x0156
};
#if defined __ARM_NEON && defined __aarch64__
static const uint16_t DivTableNEON[255*3+1] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x1c71, 0x1af2, 0x1999, 0x1861, 0x1745, 0x1642, 0x1555, 0x147a, 0x13b1, 0x12f6, 0x1249, 0x11a7, 0x1111, 0x1084, 0x1000,
0x0f83, 0x0f0f, 0x0ea0, 0x0e38, 0x0dd6, 0x0d79, 0x0d20, 0x0ccc, 0x0c7c, 0x0c30, 0x0be8, 0x0ba2, 0x0b60, 0x0b21, 0x0ae4, 0x0aaa,
0x0a72, 0x0a3d, 0x0a0a, 0x09d8, 0x09a9, 0x097b, 0x094f, 0x0924, 0x08fb, 0x08d3, 0x08ad, 0x0888, 0x0864, 0x0842, 0x0820, 0x0800,
0x07e0, 0x07c1, 0x07a4, 0x0787, 0x076b, 0x0750, 0x0736, 0x071c, 0x0703, 0x06eb, 0x06d3, 0x06bc, 0x06a6, 0x0690, 0x067b, 0x0666,
0x0652, 0x063e, 0x062b, 0x0618, 0x0606, 0x05f4, 0x05e2, 0x05d1, 0x05c0, 0x05b0, 0x05a0, 0x0590, 0x0581, 0x0572, 0x0563, 0x0555,
0x0547, 0x0539, 0x052b, 0x051e, 0x0511, 0x0505, 0x04f8, 0x04ec, 0x04e0, 0x04d4, 0x04c8, 0x04bd, 0x04b2, 0x04a7, 0x049c, 0x0492,
0x0487, 0x047d, 0x0473, 0x0469, 0x0460, 0x0456, 0x044d, 0x0444, 0x043b, 0x0432, 0x0429, 0x0421, 0x0418, 0x0410, 0x0408, 0x0400,
0x03f8, 0x03f0, 0x03e8, 0x03e0, 0x03d9, 0x03d2, 0x03ca, 0x03c3, 0x03bc, 0x03b5, 0x03ae, 0x03a8, 0x03a1, 0x039b, 0x0394, 0x038e,
0x0387, 0x0381, 0x037b, 0x0375, 0x036f, 0x0369, 0x0364, 0x035e, 0x0358, 0x0353, 0x034d, 0x0348, 0x0342, 0x033d, 0x0338, 0x0333,
0x032e, 0x0329, 0x0324, 0x031f, 0x031a, 0x0315, 0x0310, 0x030c, 0x0307, 0x0303, 0x02fe, 0x02fa, 0x02f5, 0x02f1, 0x02ec, 0x02e8,
0x02e4, 0x02e0, 0x02dc, 0x02d8, 0x02d4, 0x02d0, 0x02cc, 0x02c8, 0x02c4, 0x02c0, 0x02bc, 0x02b9, 0x02b5, 0x02b1, 0x02ae, 0x02aa,
0x02a7, 0x02a3, 0x02a0, 0x029c, 0x0299, 0x0295, 0x0292, 0x028f, 0x028c, 0x0288, 0x0285, 0x0282, 0x027f, 0x027c, 0x0279, 0x0276,
0x0273, 0x0270, 0x026d, 0x026a, 0x0267, 0x0264, 0x0261, 0x025e, 0x025c, 0x0259, 0x0256, 0x0253, 0x0251, 0x024e, 0x024b, 0x0249,
0x0246, 0x0243, 0x0241, 0x023e, 0x023c, 0x0239, 0x0237, 0x0234, 0x0232, 0x0230, 0x022d, 0x022b, 0x0229, 0x0226, 0x0224, 0x0222,
0x021f, 0x021d, 0x021b, 0x0219, 0x0216, 0x0214, 0x0212, 0x0210, 0x020e, 0x020c, 0x020a, 0x0208, 0x0206, 0x0204, 0x0202, 0x0200,
0x01fe, 0x01fc, 0x01fa, 0x01f8, 0x01f6, 0x01f4, 0x01f2, 0x01f0, 0x01ee, 0x01ec, 0x01ea, 0x01e9, 0x01e7, 0x01e5, 0x01e3, 0x01e1,
0x01e0, 0x01de, 0x01dc, 0x01da, 0x01d9, 0x01d7, 0x01d5, 0x01d4, 0x01d2, 0x01d0, 0x01cf, 0x01cd, 0x01cb, 0x01ca, 0x01c8, 0x01c7,
0x01c5, 0x01c3, 0x01c2, 0x01c0, 0x01bf, 0x01bd, 0x01bc, 0x01ba, 0x01b9, 0x01b7, 0x01b6, 0x01b4, 0x01b3, 0x01b2, 0x01b0, 0x01af,
0x01ad, 0x01ac, 0x01aa, 0x01a9, 0x01a8, 0x01a6, 0x01a5, 0x01a4, 0x01a2, 0x01a1, 0x01a0, 0x019e, 0x019d, 0x019c, 0x019a, 0x0199,
0x0198, 0x0197, 0x0195, 0x0194, 0x0193, 0x0192, 0x0190, 0x018f, 0x018e, 0x018d, 0x018b, 0x018a, 0x0189, 0x0188, 0x0187, 0x0186,
0x0184, 0x0183, 0x0182, 0x0181, 0x0180, 0x017f, 0x017e, 0x017d, 0x017b, 0x017a, 0x0179, 0x0178, 0x0177, 0x0176, 0x0175, 0x0174,
0x0173, 0x0172, 0x0171, 0x0170, 0x016f, 0x016e, 0x016d, 0x016c, 0x016b, 0x016a, 0x0169, 0x0168, 0x0167, 0x0166, 0x0165, 0x0164,
0x0163, 0x0162, 0x0161, 0x0160, 0x015f, 0x015e, 0x015d, 0x015c, 0x015b, 0x015a, 0x0159, 0x0158, 0x0158, 0x0157, 0x0156, 0x0155,
0x0154, 0x0153, 0x0152, 0x0151, 0x0150, 0x0150, 0x014f, 0x014e, 0x014d, 0x014c, 0x014b, 0x014a, 0x014a, 0x0149, 0x0148, 0x0147,
0x0146, 0x0146, 0x0145, 0x0144, 0x0143, 0x0142, 0x0142, 0x0141, 0x0140, 0x013f, 0x013e, 0x013e, 0x013d, 0x013c, 0x013b, 0x013b,
0x013a, 0x0139, 0x0138, 0x0138, 0x0137, 0x0136, 0x0135, 0x0135, 0x0134, 0x0133, 0x0132, 0x0132, 0x0131, 0x0130, 0x0130, 0x012f,
0x012e, 0x012e, 0x012d, 0x012c, 0x012b, 0x012b, 0x012a, 0x0129, 0x0129, 0x0128, 0x0127, 0x0127, 0x0126, 0x0125, 0x0125, 0x0124,
0x0123, 0x0123, 0x0122, 0x0121, 0x0121, 0x0120, 0x0120, 0x011f, 0x011e, 0x011e, 0x011d, 0x011c, 0x011c, 0x011b, 0x011b, 0x011a,
0x0119, 0x0119, 0x0118, 0x0118, 0x0117, 0x0116, 0x0116, 0x0115, 0x0115, 0x0114, 0x0113, 0x0113, 0x0112, 0x0112, 0x0111, 0x0111,
0x0110, 0x010f, 0x010f, 0x010e, 0x010e, 0x010d, 0x010d, 0x010c, 0x010c, 0x010b, 0x010a, 0x010a, 0x0109, 0x0109, 0x0108, 0x0108,
0x0107, 0x0107, 0x0106, 0x0106, 0x0105, 0x0105, 0x0104, 0x0104, 0x0103, 0x0103, 0x0102, 0x0102, 0x0101, 0x0101, 0x0100, 0x0100,
0x00ff, 0x00ff, 0x00fe, 0x00fe, 0x00fd, 0x00fd, 0x00fc, 0x00fc, 0x00fb, 0x00fb, 0x00fa, 0x00fa, 0x00f9, 0x00f9, 0x00f8, 0x00f8,
0x00f7, 0x00f7, 0x00f6, 0x00f6, 0x00f5, 0x00f5, 0x00f4, 0x00f4, 0x00f4, 0x00f3, 0x00f3, 0x00f2, 0x00f2, 0x00f1, 0x00f1, 0x00f0,
0x00f0, 0x00f0, 0x00ef, 0x00ef, 0x00ee, 0x00ee, 0x00ed, 0x00ed, 0x00ed, 0x00ec, 0x00ec, 0x00eb, 0x00eb, 0x00ea, 0x00ea, 0x00ea,
0x00e9, 0x00e9, 0x00e8, 0x00e8, 0x00e7, 0x00e7, 0x00e7, 0x00e6, 0x00e6, 0x00e5, 0x00e5, 0x00e5, 0x00e4, 0x00e4, 0x00e3, 0x00e3,
0x00e3, 0x00e2, 0x00e2, 0x00e1, 0x00e1, 0x00e1, 0x00e0, 0x00e0, 0x00e0, 0x00df, 0x00df, 0x00de, 0x00de, 0x00de, 0x00dd, 0x00dd,
0x00dd, 0x00dc, 0x00dc, 0x00db, 0x00db, 0x00db, 0x00da, 0x00da, 0x00da, 0x00d9, 0x00d9, 0x00d9, 0x00d8, 0x00d8, 0x00d7, 0x00d7,
0x00d7, 0x00d6, 0x00d6, 0x00d6, 0x00d5, 0x00d5, 0x00d5, 0x00d4, 0x00d4, 0x00d4, 0x00d3, 0x00d3, 0x00d3, 0x00d2, 0x00d2, 0x00d2,
0x00d1, 0x00d1, 0x00d1, 0x00d0, 0x00d0, 0x00d0, 0x00cf, 0x00cf, 0x00cf, 0x00ce, 0x00ce, 0x00ce, 0x00cd, 0x00cd, 0x00cd, 0x00cc,
0x00cc, 0x00cc, 0x00cb, 0x00cb, 0x00cb, 0x00ca, 0x00ca, 0x00ca, 0x00c9, 0x00c9, 0x00c9, 0x00c9, 0x00c8, 0x00c8, 0x00c8, 0x00c7,
0x00c7, 0x00c7, 0x00c6, 0x00c6, 0x00c6, 0x00c5, 0x00c5, 0x00c5, 0x00c5, 0x00c4, 0x00c4, 0x00c4, 0x00c3, 0x00c3, 0x00c3, 0x00c3,
0x00c2, 0x00c2, 0x00c2, 0x00c1, 0x00c1, 0x00c1, 0x00c1, 0x00c0, 0x00c0, 0x00c0, 0x00bf, 0x00bf, 0x00bf, 0x00bf, 0x00be, 0x00be,
0x00be, 0x00bd, 0x00bd, 0x00bd, 0x00bd, 0x00bc, 0x00bc, 0x00bc, 0x00bc, 0x00bb, 0x00bb, 0x00bb, 0x00ba, 0x00ba, 0x00ba, 0x00ba,
0x00b9, 0x00b9, 0x00b9, 0x00b9, 0x00b8, 0x00b8, 0x00b8, 0x00b8, 0x00b7, 0x00b7, 0x00b7, 0x00b7, 0x00b6, 0x00b6, 0x00b6, 0x00b6,
0x00b5, 0x00b5, 0x00b5, 0x00b5, 0x00b4, 0x00b4, 0x00b4, 0x00b4, 0x00b3, 0x00b3, 0x00b3, 0x00b3, 0x00b2, 0x00b2, 0x00b2, 0x00b2,
0x00b1, 0x00b1, 0x00b1, 0x00b1, 0x00b0, 0x00b0, 0x00b0, 0x00b0, 0x00af, 0x00af, 0x00af, 0x00af, 0x00ae, 0x00ae, 0x00ae, 0x00ae,
0x00ae, 0x00ad, 0x00ad, 0x00ad, 0x00ad, 0x00ac, 0x00ac, 0x00ac, 0x00ac, 0x00ac, 0x00ab, 0x00ab, 0x00ab, 0x00ab,
};
#endif
static tracy_force_inline uint64_t ProcessRGB( const uint8_t* src )
{
#ifdef __SSE4_1__
__m128i px0 = _mm_loadu_si128(((__m128i*)src) + 0);
__m128i px1 = _mm_loadu_si128(((__m128i*)src) + 1);
__m128i px2 = _mm_loadu_si128(((__m128i*)src) + 2);
__m128i px3 = _mm_loadu_si128(((__m128i*)src) + 3);
__m128i smask = _mm_set1_epi32( 0xF8FCF8 );
__m128i sd0 = _mm_and_si128( px0, smask );
__m128i sd1 = _mm_and_si128( px1, smask );
__m128i sd2 = _mm_and_si128( px2, smask );
__m128i sd3 = _mm_and_si128( px3, smask );
__m128i sc = _mm_shuffle_epi32(sd0, _MM_SHUFFLE(0, 0, 0, 0));
__m128i sc0 = _mm_cmpeq_epi8(sd0, sc);
__m128i sc1 = _mm_cmpeq_epi8(sd1, sc);
__m128i sc2 = _mm_cmpeq_epi8(sd2, sc);
__m128i sc3 = _mm_cmpeq_epi8(sd3, sc);
__m128i sm0 = _mm_and_si128(sc0, sc1);
__m128i sm1 = _mm_and_si128(sc2, sc3);
__m128i sm = _mm_and_si128(sm0, sm1);
if( _mm_testc_si128(sm, _mm_set1_epi32(-1)) )
{
return uint64_t( to565( src[0], src[1], src[2] ) ) << 16;
}
__m128i amask = _mm_set1_epi32( 0xFFFFFF );
px0 = _mm_and_si128( px0, amask );
px1 = _mm_and_si128( px1, amask );
px2 = _mm_and_si128( px2, amask );
px3 = _mm_and_si128( px3, amask );
__m128i min0 = _mm_min_epu8( px0, px1 );
__m128i min1 = _mm_min_epu8( px2, px3 );
__m128i min2 = _mm_min_epu8( min0, min1 );
__m128i max0 = _mm_max_epu8( px0, px1 );
__m128i max1 = _mm_max_epu8( px2, px3 );
__m128i max2 = _mm_max_epu8( max0, max1 );
__m128i min3 = _mm_shuffle_epi32( min2, _MM_SHUFFLE( 2, 3, 0, 1 ) );
__m128i max3 = _mm_shuffle_epi32( max2, _MM_SHUFFLE( 2, 3, 0, 1 ) );
__m128i min4 = _mm_min_epu8( min2, min3 );
__m128i max4 = _mm_max_epu8( max2, max3 );
__m128i min5 = _mm_shuffle_epi32( min4, _MM_SHUFFLE( 0, 0, 2, 2 ) );
__m128i max5 = _mm_shuffle_epi32( max4, _MM_SHUFFLE( 0, 0, 2, 2 ) );
__m128i rmin = _mm_min_epu8( min4, min5 );
__m128i rmax = _mm_max_epu8( max4, max5 );
__m128i range1 = _mm_subs_epu8( rmax, rmin );
__m128i range2 = _mm_sad_epu8( rmax, rmin );
uint32_t vrange = _mm_cvtsi128_si32( range2 ) >> 1;
__m128i range = _mm_set1_epi16( DivTable[vrange] );
__m128i inset1 = _mm_srli_epi16( range1, 4 );
__m128i inset = _mm_and_si128( inset1, _mm_set1_epi8( 0xF ) );
__m128i min = _mm_adds_epu8( rmin, inset );
__m128i max = _mm_subs_epu8( rmax, inset );
__m128i c0 = _mm_subs_epu8( px0, rmin );
__m128i c1 = _mm_subs_epu8( px1, rmin );
__m128i c2 = _mm_subs_epu8( px2, rmin );
__m128i c3 = _mm_subs_epu8( px3, rmin );
__m128i is0 = _mm_maddubs_epi16( c0, _mm_set1_epi8( 1 ) );
__m128i is1 = _mm_maddubs_epi16( c1, _mm_set1_epi8( 1 ) );
__m128i is2 = _mm_maddubs_epi16( c2, _mm_set1_epi8( 1 ) );
__m128i is3 = _mm_maddubs_epi16( c3, _mm_set1_epi8( 1 ) );
__m128i s0 = _mm_hadd_epi16( is0, is1 );
__m128i s1 = _mm_hadd_epi16( is2, is3 );
__m128i m0 = _mm_mulhi_epu16( s0, range );
__m128i m1 = _mm_mulhi_epu16( s1, range );
__m128i p0 = _mm_packus_epi16( m0, m1 );
__m128i p1 = _mm_or_si128( _mm_srai_epi32( p0, 6 ), _mm_srai_epi32( p0, 12 ) );
__m128i p2 = _mm_or_si128( _mm_srai_epi32( p0, 18 ), p0 );
__m128i p3 = _mm_or_si128( p1, p2 );
__m128i p =_mm_shuffle_epi8( p3, _mm_set1_epi32( 0x0C080400 ) );
uint32_t vmin = _mm_cvtsi128_si32( min );
uint32_t vmax = _mm_cvtsi128_si32( max );
uint32_t vp = _mm_cvtsi128_si32( p );
return uint64_t( ( uint64_t( to565( vmin ) ) << 16 ) | to565( vmax ) | ( uint64_t( vp ) << 32 ) );
#elif defined __ARM_NEON
# ifdef __aarch64__
uint8x16x4_t px = vld4q_u8( src );
uint8x16_t lr = px.val[0];
uint8x16_t lg = px.val[1];
uint8x16_t lb = px.val[2];
uint8_t rmaxr = vmaxvq_u8( lr );
uint8_t rmaxg = vmaxvq_u8( lg );
uint8_t rmaxb = vmaxvq_u8( lb );
uint8_t rminr = vminvq_u8( lr );
uint8_t rming = vminvq_u8( lg );
uint8_t rminb = vminvq_u8( lb );
int rr = rmaxr - rminr;
int rg = rmaxg - rming;
int rb = rmaxb - rminb;
int vrange1 = rr + rg + rb;
uint16_t vrange2 = DivTableNEON[vrange1];
uint8_t insetr = rr >> 4;
uint8_t insetg = rg >> 4;
uint8_t insetb = rb >> 4;
uint8_t minr = rminr + insetr;
uint8_t ming = rming + insetg;
uint8_t minb = rminb + insetb;
uint8_t maxr = rmaxr - insetr;
uint8_t maxg = rmaxg - insetg;
uint8_t maxb = rmaxb - insetb;
uint8x16_t cr = vsubq_u8( lr, vdupq_n_u8( rminr ) );
uint8x16_t cg = vsubq_u8( lg, vdupq_n_u8( rming ) );
uint8x16_t cb = vsubq_u8( lb, vdupq_n_u8( rminb ) );
uint16x8_t is0l = vaddl_u8( vget_low_u8( cr ), vget_low_u8( cg ) );
uint16x8_t is0h = vaddl_u8( vget_high_u8( cr ), vget_high_u8( cg ) );
uint16x8_t is1l = vaddw_u8( is0l, vget_low_u8( cb ) );
uint16x8_t is1h = vaddw_u8( is0h, vget_high_u8( cb ) );
int16x8_t range = vdupq_n_s16( vrange2 );
uint16x8_t m0 = vreinterpretq_u16_s16( vqdmulhq_s16( vreinterpretq_s16_u16( is1l ), range ) );
uint16x8_t m1 = vreinterpretq_u16_s16( vqdmulhq_s16( vreinterpretq_s16_u16( is1h ), range ) );
uint8x8_t p00 = vmovn_u16( m0 );
uint8x8_t p01 = vmovn_u16( m1 );
uint8x16_t p0 = vcombine_u8( p00, p01 );
uint32x4_t p1 = vaddq_u32( vshrq_n_u32( vreinterpretq_u32_u8( p0 ), 6 ), vshrq_n_u32( vreinterpretq_u32_u8( p0 ), 12 ) );
uint32x4_t p2 = vaddq_u32( vshrq_n_u32( vreinterpretq_u32_u8( p0 ), 18 ), vreinterpretq_u32_u8( p0 ) );
uint32x4_t p3 = vaddq_u32( p1, p2 );
uint16x4x2_t p4 = vuzp_u16( vget_low_u16( vreinterpretq_u16_u32( p3 ) ), vget_high_u16( vreinterpretq_u16_u32( p3 ) ) );
uint8x8x2_t p = vuzp_u8( vreinterpret_u8_u16( p4.val[0] ), vreinterpret_u8_u16( p4.val[0] ) );
uint32_t vp;
vst1_lane_u32( &vp, vreinterpret_u32_u8( p.val[0] ), 0 );
return uint64_t( ( uint64_t( to565( minr, ming, minb ) ) << 16 ) | to565( maxr, maxg, maxb ) | ( uint64_t( vp ) << 32 ) );
# else
uint32x4_t px0 = vld1q_u32( (uint32_t*)src );
uint32x4_t px1 = vld1q_u32( (uint32_t*)src + 4 );
uint32x4_t px2 = vld1q_u32( (uint32_t*)src + 8 );
uint32x4_t px3 = vld1q_u32( (uint32_t*)src + 12 );
uint32x4_t smask = vdupq_n_u32( 0xF8FCF8 );
uint32x4_t sd0 = vandq_u32( smask, px0 );
uint32x4_t sd1 = vandq_u32( smask, px1 );
uint32x4_t sd2 = vandq_u32( smask, px2 );
uint32x4_t sd3 = vandq_u32( smask, px3 );
uint32x4_t sc = vdupq_n_u32( sd0[0] );
uint32x4_t sc0 = vceqq_u32( sd0, sc );
uint32x4_t sc1 = vceqq_u32( sd1, sc );
uint32x4_t sc2 = vceqq_u32( sd2, sc );
uint32x4_t sc3 = vceqq_u32( sd3, sc );
uint32x4_t sm0 = vandq_u32( sc0, sc1 );
uint32x4_t sm1 = vandq_u32( sc2, sc3 );
int64x2_t sm = vreinterpretq_s64_u32( vandq_u32( sm0, sm1 ) );
if( sm[0] == -1 && sm[1] == -1 )
{
return uint64_t( to565( src[0], src[1], src[2] ) ) << 16;
}
uint32x4_t mask = vdupq_n_u32( 0xFFFFFF );
uint8x16_t l0 = vreinterpretq_u8_u32( vandq_u32( mask, px0 ) );
uint8x16_t l1 = vreinterpretq_u8_u32( vandq_u32( mask, px1 ) );
uint8x16_t l2 = vreinterpretq_u8_u32( vandq_u32( mask, px2 ) );
uint8x16_t l3 = vreinterpretq_u8_u32( vandq_u32( mask, px3 ) );
uint8x16_t min0 = vminq_u8( l0, l1 );
uint8x16_t min1 = vminq_u8( l2, l3 );
uint8x16_t min2 = vminq_u8( min0, min1 );
uint8x16_t max0 = vmaxq_u8( l0, l1 );
uint8x16_t max1 = vmaxq_u8( l2, l3 );
uint8x16_t max2 = vmaxq_u8( max0, max1 );
uint8x16_t min3 = vreinterpretq_u8_u32( vrev64q_u32( vreinterpretq_u32_u8( min2 ) ) );
uint8x16_t max3 = vreinterpretq_u8_u32( vrev64q_u32( vreinterpretq_u32_u8( max2 ) ) );
uint8x16_t min4 = vminq_u8( min2, min3 );
uint8x16_t max4 = vmaxq_u8( max2, max3 );
uint8x16_t min5 = vcombine_u8( vget_high_u8( min4 ), vget_low_u8( min4 ) );
uint8x16_t max5 = vcombine_u8( vget_high_u8( max4 ), vget_low_u8( max4 ) );
uint8x16_t rmin = vminq_u8( min4, min5 );
uint8x16_t rmax = vmaxq_u8( max4, max5 );
uint8x16_t range1 = vsubq_u8( rmax, rmin );
uint8x8_t range2 = vget_low_u8( range1 );
uint8x8x2_t range3 = vzip_u8( range2, vdup_n_u8( 0 ) );
uint16x4_t range4 = vreinterpret_u16_u8( range3.val[0] );
uint16_t vrange1;
uint16x4_t range5 = vpadd_u16( range4, range4 );
uint16x4_t range6 = vpadd_u16( range5, range5 );
vst1_lane_u16( &vrange1, range6, 0 );
uint32_t vrange2 = ( 2 << 16 ) / uint32_t( vrange1 + 1 );
uint16x8_t range = vdupq_n_u16( vrange2 );
uint8x16_t inset = vshrq_n_u8( range1, 4 );
uint8x16_t min = vaddq_u8( rmin, inset );
uint8x16_t max = vsubq_u8( rmax, inset );
uint8x16_t c0 = vsubq_u8( l0, rmin );
uint8x16_t c1 = vsubq_u8( l1, rmin );
uint8x16_t c2 = vsubq_u8( l2, rmin );
uint8x16_t c3 = vsubq_u8( l3, rmin );
uint16x8_t is0 = vpaddlq_u8( c0 );
uint16x8_t is1 = vpaddlq_u8( c1 );
uint16x8_t is2 = vpaddlq_u8( c2 );
uint16x8_t is3 = vpaddlq_u8( c3 );
uint16x4_t is4 = vpadd_u16( vget_low_u16( is0 ), vget_high_u16( is0 ) );
uint16x4_t is5 = vpadd_u16( vget_low_u16( is1 ), vget_high_u16( is1 ) );
uint16x4_t is6 = vpadd_u16( vget_low_u16( is2 ), vget_high_u16( is2 ) );
uint16x4_t is7 = vpadd_u16( vget_low_u16( is3 ), vget_high_u16( is3 ) );
uint16x8_t s0 = vcombine_u16( is4, is5 );
uint16x8_t s1 = vcombine_u16( is6, is7 );
uint16x8_t m0 = vreinterpretq_u16_s16( vqdmulhq_s16( vreinterpretq_s16_u16( s0 ), vreinterpretq_s16_u16( range ) ) );
uint16x8_t m1 = vreinterpretq_u16_s16( vqdmulhq_s16( vreinterpretq_s16_u16( s1 ), vreinterpretq_s16_u16( range ) ) );
uint8x8_t p00 = vmovn_u16( m0 );
uint8x8_t p01 = vmovn_u16( m1 );
uint8x16_t p0 = vcombine_u8( p00, p01 );
uint32x4_t p1 = vaddq_u32( vshrq_n_u32( vreinterpretq_u32_u8( p0 ), 6 ), vshrq_n_u32( vreinterpretq_u32_u8( p0 ), 12 ) );
uint32x4_t p2 = vaddq_u32( vshrq_n_u32( vreinterpretq_u32_u8( p0 ), 18 ), vreinterpretq_u32_u8( p0 ) );
uint32x4_t p3 = vaddq_u32( p1, p2 );
uint16x4x2_t p4 = vuzp_u16( vget_low_u16( vreinterpretq_u16_u32( p3 ) ), vget_high_u16( vreinterpretq_u16_u32( p3 ) ) );
uint8x8x2_t p = vuzp_u8( vreinterpret_u8_u16( p4.val[0] ), vreinterpret_u8_u16( p4.val[0] ) );
uint32_t vmin, vmax, vp;
vst1q_lane_u32( &vmin, vreinterpretq_u32_u8( min ), 0 );
vst1q_lane_u32( &vmax, vreinterpretq_u32_u8( max ), 0 );
vst1_lane_u32( &vp, vreinterpret_u32_u8( p.val[0] ), 0 );
return uint64_t( ( uint64_t( to565( vmin ) ) << 16 ) | to565( vmax ) | ( uint64_t( vp ) << 32 ) );
# endif
#else
uint32_t ref;
memcpy( &ref, src, 4 );
uint32_t refMask = ref & 0xF8FCF8;
auto stmp = src + 4;
for( int i=1; i<16; i++ )
{
uint32_t px;
memcpy( &px, stmp, 4 );
if( ( px & 0xF8FCF8 ) != refMask ) break;
stmp += 4;
}
if( stmp == src + 64 )
{
return uint64_t( to565( ref ) ) << 16;
}
uint8_t min[3] = { src[0], src[1], src[2] };
uint8_t max[3] = { src[0], src[1], src[2] };
auto tmp = src + 4;
for( int i=1; i<16; i++ )
{
for( int j=0; j<3; j++ )
{
if( tmp[j] < min[j] ) min[j] = tmp[j];
else if( tmp[j] > max[j] ) max[j] = tmp[j];
}
tmp += 4;
}
const uint32_t range = DivTable[max[0] - min[0] + max[1] - min[1] + max[2] - min[2]];
const uint32_t rmin = min[0] + min[1] + min[2];
for( int i=0; i<3; i++ )
{
const uint8_t inset = ( max[i] - min[i] ) >> 4;
min[i] += inset;
max[i] -= inset;
}
uint32_t data = 0;
for( int i=0; i<16; i++ )
{
const uint32_t c = src[0] + src[1] + src[2] - rmin;
const uint8_t idx = ( c * range ) >> 16;
data |= idx << (i*2);
src += 4;
}
return uint64_t( ( uint64_t( to565( min[0], min[1], min[2] ) ) << 16 ) | to565( max[0], max[1], max[2] ) | ( uint64_t( data ) << 32 ) );
#endif
}
#ifdef __AVX2__
static tracy_force_inline void ProcessRGB_AVX( const uint8_t* src, char*& dst )
{
__m256i px0 = _mm256_loadu_si256(((__m256i*)src) + 0);
__m256i px1 = _mm256_loadu_si256(((__m256i*)src) + 1);
__m256i px2 = _mm256_loadu_si256(((__m256i*)src) + 2);
__m256i px3 = _mm256_loadu_si256(((__m256i*)src) + 3);
__m256i smask = _mm256_set1_epi32( 0xF8FCF8 );
__m256i sd0 = _mm256_and_si256( px0, smask );
__m256i sd1 = _mm256_and_si256( px1, smask );
__m256i sd2 = _mm256_and_si256( px2, smask );
__m256i sd3 = _mm256_and_si256( px3, smask );
__m256i sc = _mm256_shuffle_epi32(sd0, _MM_SHUFFLE(0, 0, 0, 0));
__m256i sc0 = _mm256_cmpeq_epi8( sd0, sc );
__m256i sc1 = _mm256_cmpeq_epi8( sd1, sc );
__m256i sc2 = _mm256_cmpeq_epi8( sd2, sc );
__m256i sc3 = _mm256_cmpeq_epi8( sd3, sc );
__m256i sm0 = _mm256_and_si256( sc0, sc1 );
__m256i sm1 = _mm256_and_si256( sc2, sc3 );
__m256i sm = _mm256_and_si256( sm0, sm1 );
const int64_t solid0 = 1 - _mm_testc_si128( _mm256_castsi256_si128( sm ), _mm_set1_epi32( -1 ) );
const int64_t solid1 = 1 - _mm_testc_si128( _mm256_extracti128_si256( sm, 1 ), _mm_set1_epi32( -1 ) );
if( solid0 + solid1 == 0 )
{
const auto c0 = uint64_t( to565( src[0], src[1], src[2] ) ) << 16;
const auto c1 = uint64_t( to565( src[16], src[17], src[18] ) ) << 16;
memcpy( dst, &c0, 8 );
memcpy( dst+8, &c1, 8 );
dst += 16;
return;
}
__m256i amask = _mm256_set1_epi32( 0xFFFFFF );
px0 = _mm256_and_si256( px0, amask );
px1 = _mm256_and_si256( px1, amask );
px2 = _mm256_and_si256( px2, amask );
px3 = _mm256_and_si256( px3, amask );
__m256i min0 = _mm256_min_epu8( px0, px1 );
__m256i min1 = _mm256_min_epu8( px2, px3 );
__m256i min2 = _mm256_min_epu8( min0, min1 );
__m256i max0 = _mm256_max_epu8( px0, px1 );
__m256i max1 = _mm256_max_epu8( px2, px3 );
__m256i max2 = _mm256_max_epu8( max0, max1 );
__m256i min3 = _mm256_shuffle_epi32( min2, _MM_SHUFFLE( 2, 3, 0, 1 ) );
__m256i max3 = _mm256_shuffle_epi32( max2, _MM_SHUFFLE( 2, 3, 0, 1 ) );
__m256i min4 = _mm256_min_epu8( min2, min3 );
__m256i max4 = _mm256_max_epu8( max2, max3 );
__m256i min5 = _mm256_shuffle_epi32( min4, _MM_SHUFFLE( 0, 0, 2, 2 ) );
__m256i max5 = _mm256_shuffle_epi32( max4, _MM_SHUFFLE( 0, 0, 2, 2 ) );
__m256i rmin = _mm256_min_epu8( min4, min5 );
__m256i rmax = _mm256_max_epu8( max4, max5 );
__m256i range1 = _mm256_subs_epu8( rmax, rmin );
__m256i range2 = _mm256_sad_epu8( rmax, rmin );
uint16_t vrange0 = DivTable[_mm256_cvtsi256_si32( range2 ) >> 1];
uint16_t vrange1 = DivTable[_mm256_extract_epi16( range2, 8 ) >> 1];
__m256i range00 = _mm256_set1_epi16( vrange0 );
__m256i range = _mm256_inserti128_si256( range00, _mm_set1_epi16( vrange1 ), 1 );
__m256i inset1 = _mm256_srli_epi16( range1, 4 );
__m256i inset = _mm256_and_si256( inset1, _mm256_set1_epi8( 0xF ) );
__m256i min = _mm256_adds_epu8( rmin, inset );
__m256i max = _mm256_subs_epu8( rmax, inset );
__m256i c0 = _mm256_subs_epu8( px0, rmin );
__m256i c1 = _mm256_subs_epu8( px1, rmin );
__m256i c2 = _mm256_subs_epu8( px2, rmin );
__m256i c3 = _mm256_subs_epu8( px3, rmin );
__m256i is0 = _mm256_maddubs_epi16( c0, _mm256_set1_epi8( 1 ) );
__m256i is1 = _mm256_maddubs_epi16( c1, _mm256_set1_epi8( 1 ) );
__m256i is2 = _mm256_maddubs_epi16( c2, _mm256_set1_epi8( 1 ) );
__m256i is3 = _mm256_maddubs_epi16( c3, _mm256_set1_epi8( 1 ) );
__m256i s0 = _mm256_hadd_epi16( is0, is1 );
__m256i s1 = _mm256_hadd_epi16( is2, is3 );
__m256i m0 = _mm256_mulhi_epu16( s0, range );
__m256i m1 = _mm256_mulhi_epu16( s1, range );
__m256i p0 = _mm256_packus_epi16( m0, m1 );
__m256i p1 = _mm256_or_si256( _mm256_srai_epi32( p0, 6 ), _mm256_srai_epi32( p0, 12 ) );
__m256i p2 = _mm256_or_si256( _mm256_srai_epi32( p0, 18 ), p0 );
__m256i p3 = _mm256_or_si256( p1, p2 );
__m256i p =_mm256_shuffle_epi8( p3, _mm256_set1_epi32( 0x0C080400 ) );
__m256i mm0 = _mm256_unpacklo_epi8( _mm256_setzero_si256(), min );
__m256i mm1 = _mm256_unpacklo_epi8( _mm256_setzero_si256(), max );
__m256i mm2 = _mm256_unpacklo_epi64( mm1, mm0 );
__m256i mmr = _mm256_slli_epi64( _mm256_srli_epi64( mm2, 11 ), 11 );
__m256i mmg = _mm256_slli_epi64( _mm256_srli_epi64( mm2, 26 ), 5 );
__m256i mmb = _mm256_srli_epi64( _mm256_slli_epi64( mm2, 16 ), 59 );
__m256i mm3 = _mm256_or_si256( mmr, mmg );
__m256i mm4 = _mm256_or_si256( mm3, mmb );
__m256i mm5 = _mm256_shuffle_epi8( mm4, _mm256_set1_epi32( 0x09080100 ) );
__m256i d0 = _mm256_unpacklo_epi32( mm5, p );
__m256i d1 = _mm256_permute4x64_epi64( d0, _MM_SHUFFLE( 3, 2, 2, 0 ) );
__m128i d2 = _mm256_castsi256_si128( d1 );
__m128i mask = _mm_set_epi64x( 0xFFFF0000 | -solid1, 0xFFFF0000 | -solid0 );
__m128i d3 = _mm_and_si128( d2, mask );
_mm_storeu_si128( (__m128i*)dst, d3 );
dst += 16;
}
#endif
void CompressImageDxt1( const char* src, char* dst, int w, int h )
{
assert( (w % 4) == 0 && (h % 4) == 0 );
#ifdef __AVX2__
if( w%8 == 0 )
{
uint32_t buf[8*4];
int i = 0;
auto blocks = w * h / 32;
do
{
auto tmp = (char*)buf;
memcpy( tmp, src, 8*4 );
memcpy( tmp + 8*4, src + w * 4, 8*4 );
memcpy( tmp + 16*4, src + w * 8, 8*4 );
memcpy( tmp + 24*4, src + w * 12, 8*4 );
src += 8*4;
if( ++i == w/8 )
{
src += w * 3 * 4;
i = 0;
}
ProcessRGB_AVX( (uint8_t*)buf, dst );
}
while( --blocks );
}
else
#endif
{
uint32_t buf[4*4];
int i = 0;
auto ptr = dst;
auto blocks = w * h / 16;
do
{
auto tmp = (char*)buf;
memcpy( tmp, src, 4*4 );
memcpy( tmp + 4*4, src + w * 4, 4*4 );
memcpy( tmp + 8*4, src + w * 8, 4*4 );
memcpy( tmp + 12*4, src + w * 12, 4*4 );
src += 4*4;
if( ++i == w/4 )
{
src += w * 3 * 4;
i = 0;
}
const auto c = ProcessRGB( (uint8_t*)buf );
memcpy( ptr, &c, sizeof( uint64_t ) );
ptr += sizeof( uint64_t );
}
while( --blocks );
}
}
}

View File

@@ -0,0 +1,11 @@
#ifndef __TRACYDXT1_HPP__
#define __TRACYDXT1_HPP__
namespace tracy
{
void CompressImageDxt1( const char* src, char* dst, int w, int h );
}
#endif

View File

@@ -0,0 +1,118 @@
#ifndef __TRACYFASTVECTOR_HPP__
#define __TRACYFASTVECTOR_HPP__
#include <assert.h>
#include <stddef.h>
#include "../common/TracyAlloc.hpp"
#include "../common/TracyForceInline.hpp"
namespace tracy
{
template<typename T>
class FastVector
{
public:
using iterator = T*;
using const_iterator = const T*;
FastVector( size_t capacity )
: m_ptr( (T*)tracy_malloc( sizeof( T ) * capacity ) )
, m_write( m_ptr )
, m_end( m_ptr + capacity )
{
assert( capacity != 0 );
}
FastVector( const FastVector& ) = delete;
FastVector( FastVector&& ) = delete;
~FastVector()
{
tracy_free( m_ptr );
}
FastVector& operator=( const FastVector& ) = delete;
FastVector& operator=( FastVector&& ) = delete;
bool empty() const { return m_ptr == m_write; }
size_t size() const { return m_write - m_ptr; }
T* data() { return m_ptr; }
const T* data() const { return m_ptr; };
T* begin() { return m_ptr; }
const T* begin() const { return m_ptr; }
T* end() { return m_write; }
const T* end() const { return m_write; }
T& front() { assert( !empty() ); return m_ptr[0]; }
const T& front() const { assert( !empty() ); return m_ptr[0]; }
T& back() { assert( !empty() ); return m_write[-1]; }
const T& back() const { assert( !empty() ); return m_write[-1]; }
T& operator[]( size_t idx ) { return m_ptr[idx]; }
const T& operator[]( size_t idx ) const { return m_ptr[idx]; }
T* push_next()
{
if( m_write == m_end ) AllocMore();
return m_write++;
}
T* prepare_next()
{
if( m_write == m_end ) AllocMore();
return m_write;
}
void commit_next()
{
m_write++;
}
void clear()
{
m_write = m_ptr;
}
void swap( FastVector& vec )
{
const auto ptr1 = m_ptr;
const auto ptr2 = vec.m_ptr;
const auto write1 = m_write;
const auto write2 = vec.m_write;
const auto end1 = m_end;
const auto end2 = vec.m_end;
m_ptr = ptr2;
vec.m_ptr = ptr1;
m_write = write2;
vec.m_write = write1;
m_end = end2;
vec.m_end = end1;
}
private:
tracy_no_inline void AllocMore()
{
const auto cap = size_t( m_end - m_ptr ) * 2;
const auto size = size_t( m_write - m_ptr );
T* ptr = (T*)tracy_malloc( sizeof( T ) * cap );
memcpy( ptr, m_ptr, size * sizeof( T ) );
tracy_free_fast( m_ptr );
m_ptr = ptr;
m_write = m_ptr + size;
m_end = m_ptr + cap;
}
T* m_ptr;
T* m_write;
T* m_end;
};
}
#endif

View File

@@ -0,0 +1,546 @@
#ifndef __TRACYLOCK_HPP__
#define __TRACYLOCK_HPP__
#include <atomic>
#include <limits>
#include "../common/TracySystem.hpp"
#include "../common/TracyAlign.hpp"
#include "TracyProfiler.hpp"
namespace tracy
{
class LockableCtx
{
public:
tracy_force_inline LockableCtx( const SourceLocationData* srcloc )
: m_id( GetLockCounter().fetch_add( 1, std::memory_order_relaxed ) )
#ifdef TRACY_ON_DEMAND
, m_lockCount( 0 )
, m_active( false )
#endif
{
assert( m_id != std::numeric_limits<uint32_t>::max() );
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockAnnounce );
MemWrite( &item->lockAnnounce.id, m_id );
MemWrite( &item->lockAnnounce.time, Profiler::GetTime() );
MemWrite( &item->lockAnnounce.lckloc, (uint64_t)srcloc );
MemWrite( &item->lockAnnounce.type, LockType::Lockable );
#ifdef TRACY_ON_DEMAND
GetProfiler().DeferItem( *item );
#endif
Profiler::QueueSerialFinish();
}
LockableCtx( const LockableCtx& ) = delete;
LockableCtx& operator=( const LockableCtx& ) = delete;
tracy_force_inline ~LockableCtx()
{
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockTerminate );
MemWrite( &item->lockTerminate.id, m_id );
MemWrite( &item->lockTerminate.time, Profiler::GetTime() );
#ifdef TRACY_ON_DEMAND
GetProfiler().DeferItem( *item );
#endif
Profiler::QueueSerialFinish();
}
tracy_force_inline bool BeforeLock()
{
#ifdef TRACY_ON_DEMAND
bool queue = false;
const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed );
const auto active = m_active.load( std::memory_order_relaxed );
if( locks == 0 || active )
{
const bool connected = GetProfiler().IsConnected();
if( active != connected ) m_active.store( connected, std::memory_order_relaxed );
if( connected ) queue = true;
}
if( !queue ) return false;
#endif
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockWait );
MemWrite( &item->lockWait.thread, GetThreadHandle() );
MemWrite( &item->lockWait.id, m_id );
MemWrite( &item->lockWait.time, Profiler::GetTime() );
Profiler::QueueSerialFinish();
return true;
}
tracy_force_inline void AfterLock()
{
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockObtain );
MemWrite( &item->lockObtain.thread, GetThreadHandle() );
MemWrite( &item->lockObtain.id, m_id );
MemWrite( &item->lockObtain.time, Profiler::GetTime() );
Profiler::QueueSerialFinish();
}
tracy_force_inline void AfterUnlock()
{
#ifdef TRACY_ON_DEMAND
m_lockCount.fetch_sub( 1, std::memory_order_relaxed );
if( !m_active.load( std::memory_order_relaxed ) ) return;
if( !GetProfiler().IsConnected() )
{
m_active.store( false, std::memory_order_relaxed );
return;
}
#endif
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockRelease );
MemWrite( &item->lockRelease.id, m_id );
MemWrite( &item->lockRelease.time, Profiler::GetTime() );
Profiler::QueueSerialFinish();
}
tracy_force_inline void AfterTryLock( bool acquired )
{
#ifdef TRACY_ON_DEMAND
if( !acquired ) return;
bool queue = false;
const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed );
const auto active = m_active.load( std::memory_order_relaxed );
if( locks == 0 || active )
{
const bool connected = GetProfiler().IsConnected();
if( active != connected ) m_active.store( connected, std::memory_order_relaxed );
if( connected ) queue = true;
}
if( !queue ) return;
#endif
if( acquired )
{
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockObtain );
MemWrite( &item->lockObtain.thread, GetThreadHandle() );
MemWrite( &item->lockObtain.id, m_id );
MemWrite( &item->lockObtain.time, Profiler::GetTime() );
Profiler::QueueSerialFinish();
}
}
tracy_force_inline void Mark( const SourceLocationData* srcloc )
{
#ifdef TRACY_ON_DEMAND
const auto active = m_active.load( std::memory_order_relaxed );
if( !active ) return;
const auto connected = GetProfiler().IsConnected();
if( !connected )
{
if( active ) m_active.store( false, std::memory_order_relaxed );
return;
}
#endif
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockMark );
MemWrite( &item->lockMark.thread, GetThreadHandle() );
MemWrite( &item->lockMark.id, m_id );
MemWrite( &item->lockMark.srcloc, (uint64_t)srcloc );
Profiler::QueueSerialFinish();
}
tracy_force_inline void CustomName( const char* name, size_t size )
{
assert( size < std::numeric_limits<uint16_t>::max() );
auto ptr = (char*)tracy_malloc( size );
memcpy( ptr, name, size );
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockName );
MemWrite( &item->lockNameFat.id, m_id );
MemWrite( &item->lockNameFat.name, (uint64_t)ptr );
MemWrite( &item->lockNameFat.size, (uint16_t)size );
#ifdef TRACY_ON_DEMAND
GetProfiler().DeferItem( *item );
#endif
Profiler::QueueSerialFinish();
}
private:
uint32_t m_id;
#ifdef TRACY_ON_DEMAND
std::atomic<uint32_t> m_lockCount;
std::atomic<bool> m_active;
#endif
};
template<class T>
class Lockable
{
public:
tracy_force_inline Lockable( const SourceLocationData* srcloc )
: m_ctx( srcloc )
{
}
Lockable( const Lockable& ) = delete;
Lockable& operator=( const Lockable& ) = delete;
tracy_force_inline void lock()
{
const auto runAfter = m_ctx.BeforeLock();
m_lockable.lock();
if( runAfter ) m_ctx.AfterLock();
}
tracy_force_inline void unlock()
{
m_lockable.unlock();
m_ctx.AfterUnlock();
}
tracy_force_inline bool try_lock()
{
const auto acquired = m_lockable.try_lock();
m_ctx.AfterTryLock( acquired );
return acquired;
}
tracy_force_inline void Mark( const SourceLocationData* srcloc )
{
m_ctx.Mark( srcloc );
}
tracy_force_inline void CustomName( const char* name, size_t size )
{
m_ctx.CustomName( name, size );
}
private:
T m_lockable;
LockableCtx m_ctx;
};
class SharedLockableCtx
{
public:
tracy_force_inline SharedLockableCtx( const SourceLocationData* srcloc )
: m_id( GetLockCounter().fetch_add( 1, std::memory_order_relaxed ) )
#ifdef TRACY_ON_DEMAND
, m_lockCount( 0 )
, m_active( false )
#endif
{
assert( m_id != std::numeric_limits<uint32_t>::max() );
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockAnnounce );
MemWrite( &item->lockAnnounce.id, m_id );
MemWrite( &item->lockAnnounce.time, Profiler::GetTime() );
MemWrite( &item->lockAnnounce.lckloc, (uint64_t)srcloc );
MemWrite( &item->lockAnnounce.type, LockType::SharedLockable );
#ifdef TRACY_ON_DEMAND
GetProfiler().DeferItem( *item );
#endif
Profiler::QueueSerialFinish();
}
SharedLockableCtx( const SharedLockableCtx& ) = delete;
SharedLockableCtx& operator=( const SharedLockableCtx& ) = delete;
tracy_force_inline ~SharedLockableCtx()
{
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockTerminate );
MemWrite( &item->lockTerminate.id, m_id );
MemWrite( &item->lockTerminate.time, Profiler::GetTime() );
#ifdef TRACY_ON_DEMAND
GetProfiler().DeferItem( *item );
#endif
Profiler::QueueSerialFinish();
}
tracy_force_inline bool BeforeLock()
{
#ifdef TRACY_ON_DEMAND
bool queue = false;
const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed );
const auto active = m_active.load( std::memory_order_relaxed );
if( locks == 0 || active )
{
const bool connected = GetProfiler().IsConnected();
if( active != connected ) m_active.store( connected, std::memory_order_relaxed );
if( connected ) queue = true;
}
if( !queue ) return false;
#endif
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockWait );
MemWrite( &item->lockWait.thread, GetThreadHandle() );
MemWrite( &item->lockWait.id, m_id );
MemWrite( &item->lockWait.time, Profiler::GetTime() );
Profiler::QueueSerialFinish();
return true;
}
tracy_force_inline void AfterLock()
{
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockObtain );
MemWrite( &item->lockObtain.thread, GetThreadHandle() );
MemWrite( &item->lockObtain.id, m_id );
MemWrite( &item->lockObtain.time, Profiler::GetTime() );
Profiler::QueueSerialFinish();
}
tracy_force_inline void AfterUnlock()
{
#ifdef TRACY_ON_DEMAND
m_lockCount.fetch_sub( 1, std::memory_order_relaxed );
if( !m_active.load( std::memory_order_relaxed ) ) return;
if( !GetProfiler().IsConnected() )
{
m_active.store( false, std::memory_order_relaxed );
return;
}
#endif
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockRelease );
MemWrite( &item->lockRelease.id, m_id );
MemWrite( &item->lockRelease.time, Profiler::GetTime() );
Profiler::QueueSerialFinish();
}
tracy_force_inline void AfterTryLock( bool acquired )
{
#ifdef TRACY_ON_DEMAND
if( !acquired ) return;
bool queue = false;
const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed );
const auto active = m_active.load( std::memory_order_relaxed );
if( locks == 0 || active )
{
const bool connected = GetProfiler().IsConnected();
if( active != connected ) m_active.store( connected, std::memory_order_relaxed );
if( connected ) queue = true;
}
if( !queue ) return;
#endif
if( acquired )
{
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockObtain );
MemWrite( &item->lockObtain.thread, GetThreadHandle() );
MemWrite( &item->lockObtain.id, m_id );
MemWrite( &item->lockObtain.time, Profiler::GetTime() );
Profiler::QueueSerialFinish();
}
}
tracy_force_inline bool BeforeLockShared()
{
#ifdef TRACY_ON_DEMAND
bool queue = false;
const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed );
const auto active = m_active.load( std::memory_order_relaxed );
if( locks == 0 || active )
{
const bool connected = GetProfiler().IsConnected();
if( active != connected ) m_active.store( connected, std::memory_order_relaxed );
if( connected ) queue = true;
}
if( !queue ) return false;
#endif
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockSharedWait );
MemWrite( &item->lockWait.thread, GetThreadHandle() );
MemWrite( &item->lockWait.id, m_id );
MemWrite( &item->lockWait.time, Profiler::GetTime() );
Profiler::QueueSerialFinish();
return true;
}
tracy_force_inline void AfterLockShared()
{
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockSharedObtain );
MemWrite( &item->lockObtain.thread, GetThreadHandle() );
MemWrite( &item->lockObtain.id, m_id );
MemWrite( &item->lockObtain.time, Profiler::GetTime() );
Profiler::QueueSerialFinish();
}
tracy_force_inline void AfterUnlockShared()
{
#ifdef TRACY_ON_DEMAND
m_lockCount.fetch_sub( 1, std::memory_order_relaxed );
if( !m_active.load( std::memory_order_relaxed ) ) return;
if( !GetProfiler().IsConnected() )
{
m_active.store( false, std::memory_order_relaxed );
return;
}
#endif
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockSharedRelease );
MemWrite( &item->lockReleaseShared.thread, GetThreadHandle() );
MemWrite( &item->lockReleaseShared.id, m_id );
MemWrite( &item->lockReleaseShared.time, Profiler::GetTime() );
Profiler::QueueSerialFinish();
}
tracy_force_inline void AfterTryLockShared( bool acquired )
{
#ifdef TRACY_ON_DEMAND
if( !acquired ) return;
bool queue = false;
const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed );
const auto active = m_active.load( std::memory_order_relaxed );
if( locks == 0 || active )
{
const bool connected = GetProfiler().IsConnected();
if( active != connected ) m_active.store( connected, std::memory_order_relaxed );
if( connected ) queue = true;
}
if( !queue ) return;
#endif
if( acquired )
{
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockSharedObtain );
MemWrite( &item->lockObtain.thread, GetThreadHandle() );
MemWrite( &item->lockObtain.id, m_id );
MemWrite( &item->lockObtain.time, Profiler::GetTime() );
Profiler::QueueSerialFinish();
}
}
tracy_force_inline void Mark( const SourceLocationData* srcloc )
{
#ifdef TRACY_ON_DEMAND
const auto active = m_active.load( std::memory_order_relaxed );
if( !active ) return;
const auto connected = GetProfiler().IsConnected();
if( !connected )
{
if( active ) m_active.store( false, std::memory_order_relaxed );
return;
}
#endif
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockMark );
MemWrite( &item->lockMark.thread, GetThreadHandle() );
MemWrite( &item->lockMark.id, m_id );
MemWrite( &item->lockMark.srcloc, (uint64_t)srcloc );
Profiler::QueueSerialFinish();
}
tracy_force_inline void CustomName( const char* name, size_t size )
{
assert( size < std::numeric_limits<uint16_t>::max() );
auto ptr = (char*)tracy_malloc( size );
memcpy( ptr, name, size );
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::LockName );
MemWrite( &item->lockNameFat.id, m_id );
MemWrite( &item->lockNameFat.name, (uint64_t)ptr );
MemWrite( &item->lockNameFat.size, (uint16_t)size );
#ifdef TRACY_ON_DEMAND
GetProfiler().DeferItem( *item );
#endif
Profiler::QueueSerialFinish();
}
private:
uint32_t m_id;
#ifdef TRACY_ON_DEMAND
std::atomic<uint32_t> m_lockCount;
std::atomic<bool> m_active;
#endif
};
template<class T>
class SharedLockable
{
public:
tracy_force_inline SharedLockable( const SourceLocationData* srcloc )
: m_ctx( srcloc )
{
}
SharedLockable( const SharedLockable& ) = delete;
SharedLockable& operator=( const SharedLockable& ) = delete;
tracy_force_inline void lock()
{
const auto runAfter = m_ctx.BeforeLock();
m_lockable.lock();
if( runAfter ) m_ctx.AfterLock();
}
tracy_force_inline void unlock()
{
m_lockable.unlock();
m_ctx.AfterUnlock();
}
tracy_force_inline bool try_lock()
{
const auto acquired = m_lockable.try_lock();
m_ctx.AfterTryLock( acquired );
return acquired;
}
tracy_force_inline void lock_shared()
{
const auto runAfter = m_ctx.BeforeLockShared();
m_lockable.lock_shared();
if( runAfter ) m_ctx.AfterLockShared();
}
tracy_force_inline void unlock_shared()
{
m_lockable.unlock_shared();
m_ctx.AfterUnlockShared();
}
tracy_force_inline bool try_lock_shared()
{
const auto acquired = m_lockable.try_lock_shared();
m_ctx.AfterTryLockShared( acquired );
return acquired;
}
tracy_force_inline void Mark( const SourceLocationData* srcloc )
{
m_ctx.Mark( srcloc );
}
tracy_force_inline void CustomName( const char* name, size_t size )
{
m_ctx.CustomName( name, size );
}
private:
T m_lockable;
SharedLockableCtx m_ctx;
};
}
#endif

View File

@@ -0,0 +1,26 @@
#ifdef TRACY_ENABLE
# ifdef __linux__
# include "TracyDebug.hpp"
# ifdef TRACY_VERBOSE
# include <dlfcn.h>
# include <link.h>
# endif
extern "C" int dlclose( void* hnd )
{
#ifdef TRACY_VERBOSE
struct link_map* lm;
if( dlinfo( hnd, RTLD_DI_LINKMAP, &lm ) == 0 )
{
TracyDebug( "Overriding dlclose for %s\n", lm->l_name );
}
else
{
TracyDebug( "Overriding dlclose for unknown object (%s)\n", dlerror() );
}
#endif
return 0;
}
# endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,966 @@
#ifndef __TRACYPROFILER_HPP__
#define __TRACYPROFILER_HPP__
#include <assert.h>
#include <atomic>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include "tracy_concurrentqueue.h"
#include "tracy_SPSCQueue.h"
#include "TracyCallstack.hpp"
#include "TracySysTime.hpp"
#include "TracyFastVector.hpp"
#include "../common/TracyQueue.hpp"
#include "../common/TracyAlign.hpp"
#include "../common/TracyAlloc.hpp"
#include "../common/TracyMutex.hpp"
#include "../common/TracyProtocol.hpp"
#if defined _WIN32
# include <intrin.h>
#endif
#ifdef __APPLE__
# include <TargetConditionals.h>
# include <mach/mach_time.h>
#endif
#if ( defined _WIN32 || ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 ) || ( defined TARGET_OS_IOS && TARGET_OS_IOS == 1 ) )
# define TRACY_HW_TIMER
#endif
#ifdef __linux__
# include <signal.h>
#endif
#if defined TRACY_TIMER_FALLBACK || !defined TRACY_HW_TIMER
# include <chrono>
#endif
#ifndef TracyConcat
# define TracyConcat(x,y) TracyConcatIndirect(x,y)
#endif
#ifndef TracyConcatIndirect
# define TracyConcatIndirect(x,y) x##y
#endif
namespace tracy
{
#if defined(TRACY_DELAYED_INIT) && defined(TRACY_MANUAL_LIFETIME)
TRACY_API void StartupProfiler();
TRACY_API void ShutdownProfiler();
#endif
class GpuCtx;
class Profiler;
class Socket;
class UdpBroadcast;
struct GpuCtxWrapper
{
GpuCtx* ptr;
};
TRACY_API moodycamel::ConcurrentQueue<QueueItem>::ExplicitProducer* GetToken();
TRACY_API Profiler& GetProfiler();
TRACY_API std::atomic<uint32_t>& GetLockCounter();
TRACY_API std::atomic<uint8_t>& GetGpuCtxCounter();
TRACY_API GpuCtxWrapper& GetGpuCtx();
TRACY_API uint32_t GetThreadHandle();
TRACY_API bool ProfilerAvailable();
TRACY_API bool ProfilerAllocatorAvailable();
TRACY_API int64_t GetFrequencyQpc();
#if defined TRACY_TIMER_FALLBACK && defined TRACY_HW_TIMER && ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 )
TRACY_API bool HardwareSupportsInvariantTSC(); // check, if we need fallback scenario
#else
# if defined TRACY_HW_TIMER
tracy_force_inline bool HardwareSupportsInvariantTSC()
{
return true; // this is checked at startup
}
# else
tracy_force_inline bool HardwareSupportsInvariantTSC()
{
return false;
}
# endif
#endif
struct SourceLocationData
{
const char* name;
const char* function;
const char* file;
uint32_t line;
uint32_t color;
};
#ifdef TRACY_ON_DEMAND
struct LuaZoneState
{
uint32_t counter;
bool active;
};
#endif
#define TracyLfqPrepare( _type ) \
moodycamel::ConcurrentQueueDefaultTraits::index_t __magic; \
auto __token = GetToken(); \
auto& __tail = __token->get_tail_index(); \
auto item = __token->enqueue_begin( __magic ); \
MemWrite( &item->hdr.type, _type );
#define TracyLfqCommit \
__tail.store( __magic + 1, std::memory_order_release );
#define TracyLfqPrepareC( _type ) \
tracy::moodycamel::ConcurrentQueueDefaultTraits::index_t __magic; \
auto __token = tracy::GetToken(); \
auto& __tail = __token->get_tail_index(); \
auto item = __token->enqueue_begin( __magic ); \
tracy::MemWrite( &item->hdr.type, _type );
#define TracyLfqCommitC \
__tail.store( __magic + 1, std::memory_order_release );
#ifdef TRACY_FIBERS
# define TracyQueuePrepare( _type ) \
auto item = Profiler::QueueSerial(); \
MemWrite( &item->hdr.type, _type );
# define TracyQueueCommit( _name ) \
MemWrite( &item->_name.thread, GetThreadHandle() ); \
Profiler::QueueSerialFinish();
# define TracyQueuePrepareC( _type ) \
auto item = tracy::Profiler::QueueSerial(); \
tracy::MemWrite( &item->hdr.type, _type );
# define TracyQueueCommitC( _name ) \
tracy::MemWrite( &item->_name.thread, tracy::GetThreadHandle() ); \
tracy::Profiler::QueueSerialFinish();
#else
# define TracyQueuePrepare( _type ) TracyLfqPrepare( _type )
# define TracyQueueCommit( _name ) TracyLfqCommit
# define TracyQueuePrepareC( _type ) TracyLfqPrepareC( _type )
# define TracyQueueCommitC( _name ) TracyLfqCommitC
#endif
typedef void(*ParameterCallback)( void* data, uint32_t idx, int32_t val );
typedef char*(*SourceContentsCallback)( void* data, const char* filename, size_t& size );
class Profiler
{
struct FrameImageQueueItem
{
void* image;
uint32_t frame;
uint16_t w;
uint16_t h;
bool flip;
};
enum class SymbolQueueItemType
{
CallstackFrame,
SymbolQuery,
ExternalName,
KernelCode,
SourceCode
};
struct SymbolQueueItem
{
SymbolQueueItemType type;
uint64_t ptr;
uint64_t extra;
uint32_t id;
};
public:
Profiler();
~Profiler();
void SpawnWorkerThreads();
static tracy_force_inline int64_t GetTime()
{
#ifdef TRACY_HW_TIMER
# if defined TARGET_OS_IOS && TARGET_OS_IOS == 1
if( HardwareSupportsInvariantTSC() ) return mach_absolute_time();
# elif defined _WIN32
# ifdef TRACY_TIMER_QPC
return GetTimeQpc();
# else
if( HardwareSupportsInvariantTSC() ) return int64_t( __rdtsc() );
# endif
# elif defined __i386 || defined _M_IX86
if( HardwareSupportsInvariantTSC() )
{
uint32_t eax, edx;
asm volatile ( "rdtsc" : "=a" (eax), "=d" (edx) );
return ( uint64_t( edx ) << 32 ) + uint64_t( eax );
}
# elif defined __x86_64__ || defined _M_X64
if( HardwareSupportsInvariantTSC() )
{
uint64_t rax, rdx;
asm volatile ( "rdtsc" : "=a" (rax), "=d" (rdx) );
return (int64_t)(( rdx << 32 ) + rax);
}
# else
# error "TRACY_HW_TIMER detection logic needs fixing"
# endif
#endif
#if !defined TRACY_HW_TIMER || defined TRACY_TIMER_FALLBACK
# if defined __linux__ && defined CLOCK_MONOTONIC_RAW
struct timespec ts;
clock_gettime( CLOCK_MONOTONIC_RAW, &ts );
return int64_t( ts.tv_sec ) * 1000000000ll + int64_t( ts.tv_nsec );
# else
return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();
# endif
#endif
#if !defined TRACY_TIMER_FALLBACK
return 0; // unreachable branch
#endif
}
tracy_force_inline uint32_t GetNextZoneId()
{
return m_zoneId.fetch_add( 1, std::memory_order_relaxed );
}
static tracy_force_inline QueueItem* QueueSerial()
{
auto& p = GetProfiler();
p.m_serialLock.lock();
return p.m_serialQueue.prepare_next();
}
static tracy_force_inline QueueItem* QueueSerialCallstack( void* ptr )
{
auto& p = GetProfiler();
p.m_serialLock.lock();
p.SendCallstackSerial( ptr );
return p.m_serialQueue.prepare_next();
}
static tracy_force_inline void QueueSerialFinish()
{
auto& p = GetProfiler();
p.m_serialQueue.commit_next();
p.m_serialLock.unlock();
}
static tracy_force_inline void SendFrameMark( const char* name )
{
if( !name ) GetProfiler().m_frameCount.fetch_add( 1, std::memory_order_relaxed );
#ifdef TRACY_ON_DEMAND
if( !GetProfiler().IsConnected() ) return;
#endif
auto item = QueueSerial();
MemWrite( &item->hdr.type, QueueType::FrameMarkMsg );
MemWrite( &item->frameMark.time, GetTime() );
MemWrite( &item->frameMark.name, uint64_t( name ) );
QueueSerialFinish();
}
static tracy_force_inline void SendFrameMark( const char* name, QueueType type )
{
assert( type == QueueType::FrameMarkMsgStart || type == QueueType::FrameMarkMsgEnd );
#ifdef TRACY_ON_DEMAND
if( !GetProfiler().IsConnected() ) return;
#endif
auto item = QueueSerial();
MemWrite( &item->hdr.type, type );
MemWrite( &item->frameMark.time, GetTime() );
MemWrite( &item->frameMark.name, uint64_t( name ) );
QueueSerialFinish();
}
static tracy_force_inline void SendFrameImage( const void* image, uint16_t w, uint16_t h, uint8_t offset, bool flip )
{
#ifndef TRACY_NO_FRAME_IMAGE
auto& profiler = GetProfiler();
assert( profiler.m_frameCount.load( std::memory_order_relaxed ) < std::numeric_limits<uint32_t>::max() );
# ifdef TRACY_ON_DEMAND
if( !profiler.IsConnected() ) return;
# endif
const auto sz = size_t( w ) * size_t( h ) * 4;
auto ptr = (char*)tracy_malloc( sz );
memcpy( ptr, image, sz );
profiler.m_fiLock.lock();
auto fi = profiler.m_fiQueue.prepare_next();
fi->image = ptr;
fi->frame = uint32_t( profiler.m_frameCount.load( std::memory_order_relaxed ) - offset );
fi->w = w;
fi->h = h;
fi->flip = flip;
profiler.m_fiQueue.commit_next();
profiler.m_fiLock.unlock();
#endif
}
static tracy_force_inline void PlotData( const char* name, int64_t val )
{
#ifdef TRACY_ON_DEMAND
if( !GetProfiler().IsConnected() ) return;
#endif
TracyLfqPrepare( QueueType::PlotDataInt );
MemWrite( &item->plotDataInt.name, (uint64_t)name );
MemWrite( &item->plotDataInt.time, GetTime() );
MemWrite( &item->plotDataInt.val, val );
TracyLfqCommit;
}
static tracy_force_inline void PlotData( const char* name, float val )
{
#ifdef TRACY_ON_DEMAND
if( !GetProfiler().IsConnected() ) return;
#endif
TracyLfqPrepare( QueueType::PlotDataFloat );
MemWrite( &item->plotDataFloat.name, (uint64_t)name );
MemWrite( &item->plotDataFloat.time, GetTime() );
MemWrite( &item->plotDataFloat.val, val );
TracyLfqCommit;
}
static tracy_force_inline void PlotData( const char* name, double val )
{
#ifdef TRACY_ON_DEMAND
if( !GetProfiler().IsConnected() ) return;
#endif
TracyLfqPrepare( QueueType::PlotDataDouble );
MemWrite( &item->plotDataDouble.name, (uint64_t)name );
MemWrite( &item->plotDataDouble.time, GetTime() );
MemWrite( &item->plotDataDouble.val, val );
TracyLfqCommit;
}
static tracy_force_inline void ConfigurePlot( const char* name, PlotFormatType type, bool step, bool fill, uint32_t color )
{
TracyLfqPrepare( QueueType::PlotConfig );
MemWrite( &item->plotConfig.name, (uint64_t)name );
MemWrite( &item->plotConfig.type, (uint8_t)type );
MemWrite( &item->plotConfig.step, (uint8_t)step );
MemWrite( &item->plotConfig.fill, (uint8_t)fill );
MemWrite( &item->plotConfig.color, color );
#ifdef TRACY_ON_DEMAND
GetProfiler().DeferItem( *item );
#endif
TracyLfqCommit;
}
static tracy_force_inline void Message( const char* txt, size_t size, int callstack )
{
assert( size < std::numeric_limits<uint16_t>::max() );
#ifdef TRACY_ON_DEMAND
if( !GetProfiler().IsConnected() ) return;
#endif
if( callstack != 0 )
{
tracy::GetProfiler().SendCallstack( callstack );
}
auto ptr = (char*)tracy_malloc( size );
memcpy( ptr, txt, size );
TracyQueuePrepare( callstack == 0 ? QueueType::Message : QueueType::MessageCallstack );
MemWrite( &item->messageFat.time, GetTime() );
MemWrite( &item->messageFat.text, (uint64_t)ptr );
MemWrite( &item->messageFat.size, (uint16_t)size );
TracyQueueCommit( messageFatThread );
}
static tracy_force_inline void Message( const char* txt, int callstack )
{
#ifdef TRACY_ON_DEMAND
if( !GetProfiler().IsConnected() ) return;
#endif
if( callstack != 0 )
{
tracy::GetProfiler().SendCallstack( callstack );
}
TracyQueuePrepare( callstack == 0 ? QueueType::MessageLiteral : QueueType::MessageLiteralCallstack );
MemWrite( &item->messageLiteral.time, GetTime() );
MemWrite( &item->messageLiteral.text, (uint64_t)txt );
TracyQueueCommit( messageLiteralThread );
}
static tracy_force_inline void MessageColor( const char* txt, size_t size, uint32_t color, int callstack )
{
assert( size < std::numeric_limits<uint16_t>::max() );
#ifdef TRACY_ON_DEMAND
if( !GetProfiler().IsConnected() ) return;
#endif
if( callstack != 0 )
{
tracy::GetProfiler().SendCallstack( callstack );
}
auto ptr = (char*)tracy_malloc( size );
memcpy( ptr, txt, size );
TracyQueuePrepare( callstack == 0 ? QueueType::MessageColor : QueueType::MessageColorCallstack );
MemWrite( &item->messageColorFat.time, GetTime() );
MemWrite( &item->messageColorFat.text, (uint64_t)ptr );
MemWrite( &item->messageColorFat.b, uint8_t( ( color ) & 0xFF ) );
MemWrite( &item->messageColorFat.g, uint8_t( ( color >> 8 ) & 0xFF ) );
MemWrite( &item->messageColorFat.r, uint8_t( ( color >> 16 ) & 0xFF ) );
MemWrite( &item->messageColorFat.size, (uint16_t)size );
TracyQueueCommit( messageColorFatThread );
}
static tracy_force_inline void MessageColor( const char* txt, uint32_t color, int callstack )
{
#ifdef TRACY_ON_DEMAND
if( !GetProfiler().IsConnected() ) return;
#endif
if( callstack != 0 )
{
tracy::GetProfiler().SendCallstack( callstack );
}
TracyQueuePrepare( callstack == 0 ? QueueType::MessageLiteralColor : QueueType::MessageLiteralColorCallstack );
MemWrite( &item->messageColorLiteral.time, GetTime() );
MemWrite( &item->messageColorLiteral.text, (uint64_t)txt );
MemWrite( &item->messageColorLiteral.b, uint8_t( ( color ) & 0xFF ) );
MemWrite( &item->messageColorLiteral.g, uint8_t( ( color >> 8 ) & 0xFF ) );
MemWrite( &item->messageColorLiteral.r, uint8_t( ( color >> 16 ) & 0xFF ) );
TracyQueueCommit( messageColorLiteralThread );
}
static tracy_force_inline void MessageAppInfo( const char* txt, size_t size )
{
assert( size < std::numeric_limits<uint16_t>::max() );
auto ptr = (char*)tracy_malloc( size );
memcpy( ptr, txt, size );
TracyLfqPrepare( QueueType::MessageAppInfo );
MemWrite( &item->messageFat.time, GetTime() );
MemWrite( &item->messageFat.text, (uint64_t)ptr );
MemWrite( &item->messageFat.size, (uint16_t)size );
#ifdef TRACY_ON_DEMAND
GetProfiler().DeferItem( *item );
#endif
TracyLfqCommit;
}
static tracy_force_inline void MemAlloc( const void* ptr, size_t size, bool secure )
{
if( secure && !ProfilerAvailable() ) return;
#ifdef TRACY_ON_DEMAND
if( !GetProfiler().IsConnected() ) return;
#endif
const auto thread = GetThreadHandle();
GetProfiler().m_serialLock.lock();
SendMemAlloc( QueueType::MemAlloc, thread, ptr, size );
GetProfiler().m_serialLock.unlock();
}
static tracy_force_inline void MemFree( const void* ptr, bool secure )
{
if( secure && !ProfilerAvailable() ) return;
#ifdef TRACY_ON_DEMAND
if( !GetProfiler().IsConnected() ) return;
#endif
const auto thread = GetThreadHandle();
GetProfiler().m_serialLock.lock();
SendMemFree( QueueType::MemFree, thread, ptr );
GetProfiler().m_serialLock.unlock();
}
static tracy_force_inline void MemAllocCallstack( const void* ptr, size_t size, int depth, bool secure )
{
if( secure && !ProfilerAvailable() ) return;
#ifdef TRACY_HAS_CALLSTACK
auto& profiler = GetProfiler();
# ifdef TRACY_ON_DEMAND
if( !profiler.IsConnected() ) return;
# endif
const auto thread = GetThreadHandle();
auto callstack = Callstack( depth );
profiler.m_serialLock.lock();
SendCallstackSerial( callstack );
SendMemAlloc( QueueType::MemAllocCallstack, thread, ptr, size );
profiler.m_serialLock.unlock();
#else
static_cast<void>(depth); // unused
MemAlloc( ptr, size, secure );
#endif
}
static tracy_force_inline void MemFreeCallstack( const void* ptr, int depth, bool secure )
{
if( secure && !ProfilerAvailable() ) return;
if( !ProfilerAllocatorAvailable() )
{
MemFree( ptr, secure );
return;
}
#ifdef TRACY_HAS_CALLSTACK
auto& profiler = GetProfiler();
# ifdef TRACY_ON_DEMAND
if( !profiler.IsConnected() ) return;
# endif
const auto thread = GetThreadHandle();
auto callstack = Callstack( depth );
profiler.m_serialLock.lock();
SendCallstackSerial( callstack );
SendMemFree( QueueType::MemFreeCallstack, thread, ptr );
profiler.m_serialLock.unlock();
#else
static_cast<void>(depth); // unused
MemFree( ptr, secure );
#endif
}
static tracy_force_inline void MemAllocNamed( const void* ptr, size_t size, bool secure, const char* name )
{
if( secure && !ProfilerAvailable() ) return;
#ifdef TRACY_ON_DEMAND
if( !GetProfiler().IsConnected() ) return;
#endif
const auto thread = GetThreadHandle();
GetProfiler().m_serialLock.lock();
SendMemName( name );
SendMemAlloc( QueueType::MemAllocNamed, thread, ptr, size );
GetProfiler().m_serialLock.unlock();
}
static tracy_force_inline void MemFreeNamed( const void* ptr, bool secure, const char* name )
{
if( secure && !ProfilerAvailable() ) return;
#ifdef TRACY_ON_DEMAND
if( !GetProfiler().IsConnected() ) return;
#endif
const auto thread = GetThreadHandle();
GetProfiler().m_serialLock.lock();
SendMemName( name );
SendMemFree( QueueType::MemFreeNamed, thread, ptr );
GetProfiler().m_serialLock.unlock();
}
static tracy_force_inline void MemAllocCallstackNamed( const void* ptr, size_t size, int depth, bool secure, const char* name )
{
if( secure && !ProfilerAvailable() ) return;
#ifdef TRACY_HAS_CALLSTACK
auto& profiler = GetProfiler();
# ifdef TRACY_ON_DEMAND
if( !profiler.IsConnected() ) return;
# endif
const auto thread = GetThreadHandle();
auto callstack = Callstack( depth );
profiler.m_serialLock.lock();
SendCallstackSerial( callstack );
SendMemName( name );
SendMemAlloc( QueueType::MemAllocCallstackNamed, thread, ptr, size );
profiler.m_serialLock.unlock();
#else
static_cast<void>(depth); // unused
static_cast<void>(name); // unused
MemAlloc( ptr, size, secure );
#endif
}
static tracy_force_inline void MemFreeCallstackNamed( const void* ptr, int depth, bool secure, const char* name )
{
if( secure && !ProfilerAvailable() ) return;
#ifdef TRACY_HAS_CALLSTACK
auto& profiler = GetProfiler();
# ifdef TRACY_ON_DEMAND
if( !profiler.IsConnected() ) return;
# endif
const auto thread = GetThreadHandle();
auto callstack = Callstack( depth );
profiler.m_serialLock.lock();
SendCallstackSerial( callstack );
SendMemName( name );
SendMemFree( QueueType::MemFreeCallstackNamed, thread, ptr );
profiler.m_serialLock.unlock();
#else
static_cast<void>(depth); // unused
static_cast<void>(name); // unused
MemFree( ptr, secure );
#endif
}
static tracy_force_inline void SendCallstack( int depth )
{
#ifdef TRACY_HAS_CALLSTACK
auto ptr = Callstack( depth );
TracyQueuePrepare( QueueType::Callstack );
MemWrite( &item->callstackFat.ptr, (uint64_t)ptr );
TracyQueueCommit( callstackFatThread );
#else
static_cast<void>(depth); // unused
#endif
}
static tracy_force_inline void ParameterRegister( ParameterCallback cb, void* data )
{
auto& profiler = GetProfiler();
profiler.m_paramCallback = cb;
profiler.m_paramCallbackData = data;
}
static tracy_force_inline void ParameterSetup( uint32_t idx, const char* name, bool isBool, int32_t val )
{
TracyLfqPrepare( QueueType::ParamSetup );
tracy::MemWrite( &item->paramSetup.idx, idx );
tracy::MemWrite( &item->paramSetup.name, (uint64_t)name );
tracy::MemWrite( &item->paramSetup.isBool, (uint8_t)isBool );
tracy::MemWrite( &item->paramSetup.val, val );
#ifdef TRACY_ON_DEMAND
GetProfiler().DeferItem( *item );
#endif
TracyLfqCommit;
}
static tracy_force_inline void SourceCallbackRegister( SourceContentsCallback cb, void* data )
{
auto& profiler = GetProfiler();
profiler.m_sourceCallback = cb;
profiler.m_sourceCallbackData = data;
}
#ifdef TRACY_FIBERS
static tracy_force_inline void EnterFiber( const char* fiber )
{
TracyQueuePrepare( QueueType::FiberEnter );
MemWrite( &item->fiberEnter.time, GetTime() );
MemWrite( &item->fiberEnter.fiber, (uint64_t)fiber );
TracyQueueCommit( fiberEnter );
}
static tracy_force_inline void LeaveFiber()
{
TracyQueuePrepare( QueueType::FiberLeave );
MemWrite( &item->fiberLeave.time, GetTime() );
TracyQueueCommit( fiberLeave );
}
#endif
void SendCallstack( int depth, const char* skipBefore );
static void CutCallstack( void* callstack, const char* skipBefore );
static bool ShouldExit();
tracy_force_inline bool IsConnected() const
{
return m_isConnected.load( std::memory_order_acquire );
}
#ifdef TRACY_ON_DEMAND
tracy_force_inline uint64_t ConnectionId() const
{
return m_connectionId.load( std::memory_order_acquire );
}
tracy_force_inline void DeferItem( const QueueItem& item )
{
m_deferredLock.lock();
auto dst = m_deferredQueue.push_next();
memcpy( dst, &item, sizeof( item ) );
m_deferredLock.unlock();
}
#endif
void RequestShutdown() { m_shutdown.store( true, std::memory_order_relaxed ); m_shutdownManual.store( true, std::memory_order_relaxed ); }
bool HasShutdownFinished() const { return m_shutdownFinished.load( std::memory_order_relaxed ); }
void SendString( uint64_t str, const char* ptr, QueueType type ) { SendString( str, ptr, strlen( ptr ), type ); }
void SendString( uint64_t str, const char* ptr, size_t len, QueueType type );
void SendSingleString( const char* ptr ) { SendSingleString( ptr, strlen( ptr ) ); }
void SendSingleString( const char* ptr, size_t len );
void SendSecondString( const char* ptr ) { SendSecondString( ptr, strlen( ptr ) ); }
void SendSecondString( const char* ptr, size_t len );
// Allocated source location data layout:
// 2b payload size
// 4b color
// 4b source line
// fsz function name
// 1b null terminator
// ssz source file name
// 1b null terminator
// nsz zone name (optional)
static tracy_force_inline uint64_t AllocSourceLocation( uint32_t line, const char* source, const char* function )
{
return AllocSourceLocation( line, source, function, nullptr, 0 );
}
static tracy_force_inline uint64_t AllocSourceLocation( uint32_t line, const char* source, const char* function, const char* name, size_t nameSz )
{
return AllocSourceLocation( line, source, strlen(source), function, strlen(function), name, nameSz );
}
static tracy_force_inline uint64_t AllocSourceLocation( uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz )
{
return AllocSourceLocation( line, source, sourceSz, function, functionSz, nullptr, 0 );
}
static tracy_force_inline uint64_t AllocSourceLocation( uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz )
{
const auto sz32 = uint32_t( 2 + 4 + 4 + functionSz + 1 + sourceSz + 1 + nameSz );
assert( sz32 <= std::numeric_limits<uint16_t>::max() );
const auto sz = uint16_t( sz32 );
auto ptr = (char*)tracy_malloc( sz );
memcpy( ptr, &sz, 2 );
memset( ptr + 2, 0, 4 );
memcpy( ptr + 6, &line, 4 );
memcpy( ptr + 10, function, functionSz );
ptr[10 + functionSz] = '\0';
memcpy( ptr + 10 + functionSz + 1, source, sourceSz );
ptr[10 + functionSz + 1 + sourceSz] = '\0';
if( nameSz != 0 )
{
memcpy( ptr + 10 + functionSz + 1 + sourceSz + 1, name, nameSz );
}
return uint64_t( ptr );
}
private:
enum class DequeueStatus { DataDequeued, ConnectionLost, QueueEmpty };
enum class ThreadCtxStatus { Same, Changed, ConnectionLost };
static void LaunchWorker( void* ptr ) { ((Profiler*)ptr)->Worker(); }
void Worker();
#ifndef TRACY_NO_FRAME_IMAGE
static void LaunchCompressWorker( void* ptr ) { ((Profiler*)ptr)->CompressWorker(); }
void CompressWorker();
#endif
#ifdef TRACY_HAS_CALLSTACK
static void LaunchSymbolWorker( void* ptr ) { ((Profiler*)ptr)->SymbolWorker(); }
void SymbolWorker();
void HandleSymbolQueueItem( const SymbolQueueItem& si );
#endif
void ClearQueues( tracy::moodycamel::ConsumerToken& token );
void ClearSerial();
DequeueStatus Dequeue( tracy::moodycamel::ConsumerToken& token );
DequeueStatus DequeueContextSwitches( tracy::moodycamel::ConsumerToken& token, int64_t& timeStop );
DequeueStatus DequeueSerial();
ThreadCtxStatus ThreadCtxCheck( uint32_t threadId );
bool CommitData();
tracy_force_inline bool AppendData( const void* data, size_t len )
{
const auto ret = NeedDataSize( len );
AppendDataUnsafe( data, len );
return ret;
}
tracy_force_inline bool NeedDataSize( size_t len )
{
assert( len <= TargetFrameSize );
bool ret = true;
if( m_bufferOffset - m_bufferStart + (int)len > TargetFrameSize )
{
ret = CommitData();
}
return ret;
}
tracy_force_inline void AppendDataUnsafe( const void* data, size_t len )
{
memcpy( m_buffer + m_bufferOffset, data, len );
m_bufferOffset += int( len );
}
bool SendData( const char* data, size_t len );
void SendLongString( uint64_t ptr, const char* str, size_t len, QueueType type );
void SendSourceLocation( uint64_t ptr );
void SendSourceLocationPayload( uint64_t ptr );
void SendCallstackPayload( uint64_t ptr );
void SendCallstackPayload64( uint64_t ptr );
void SendCallstackAlloc( uint64_t ptr );
void QueueCallstackFrame( uint64_t ptr );
void QueueSymbolQuery( uint64_t symbol );
void QueueExternalName( uint64_t ptr );
void QueueKernelCode( uint64_t symbol, uint32_t size );
void QueueSourceCodeQuery( uint32_t id );
bool HandleServerQuery();
void HandleDisconnect();
void HandleParameter( uint64_t payload );
void HandleSymbolCodeQuery( uint64_t symbol, uint32_t size );
void HandleSourceCodeQuery( char* data, char* image, uint32_t id );
void AckServerQuery();
void AckSymbolCodeNotAvailable();
void CalibrateTimer();
void CalibrateDelay();
void ReportTopology();
static tracy_force_inline void SendCallstackSerial( void* ptr )
{
#ifdef TRACY_HAS_CALLSTACK
auto item = GetProfiler().m_serialQueue.prepare_next();
MemWrite( &item->hdr.type, QueueType::CallstackSerial );
MemWrite( &item->callstackFat.ptr, (uint64_t)ptr );
GetProfiler().m_serialQueue.commit_next();
#else
static_cast<void>(ptr); // unused
#endif
}
static tracy_force_inline void SendMemAlloc( QueueType type, const uint32_t thread, const void* ptr, size_t size )
{
assert( type == QueueType::MemAlloc || type == QueueType::MemAllocCallstack || type == QueueType::MemAllocNamed || type == QueueType::MemAllocCallstackNamed );
auto item = GetProfiler().m_serialQueue.prepare_next();
MemWrite( &item->hdr.type, type );
MemWrite( &item->memAlloc.time, GetTime() );
MemWrite( &item->memAlloc.thread, thread );
MemWrite( &item->memAlloc.ptr, (uint64_t)ptr );
if( compile_time_condition<sizeof( size ) == 4>::value )
{
memcpy( &item->memAlloc.size, &size, 4 );
memset( &item->memAlloc.size + 4, 0, 2 );
}
else
{
assert( sizeof( size ) == 8 );
memcpy( &item->memAlloc.size, &size, 4 );
memcpy( ((char*)&item->memAlloc.size)+4, ((char*)&size)+4, 2 );
}
GetProfiler().m_serialQueue.commit_next();
}
static tracy_force_inline void SendMemFree( QueueType type, const uint32_t thread, const void* ptr )
{
assert( type == QueueType::MemFree || type == QueueType::MemFreeCallstack || type == QueueType::MemFreeNamed || type == QueueType::MemFreeCallstackNamed );
auto item = GetProfiler().m_serialQueue.prepare_next();
MemWrite( &item->hdr.type, type );
MemWrite( &item->memFree.time, GetTime() );
MemWrite( &item->memFree.thread, thread );
MemWrite( &item->memFree.ptr, (uint64_t)ptr );
GetProfiler().m_serialQueue.commit_next();
}
static tracy_force_inline void SendMemName( const char* name )
{
assert( name );
auto item = GetProfiler().m_serialQueue.prepare_next();
MemWrite( &item->hdr.type, QueueType::MemNamePayload );
MemWrite( &item->memName.name, (uint64_t)name );
GetProfiler().m_serialQueue.commit_next();
}
#if defined _WIN32 && defined TRACY_TIMER_QPC
static int64_t GetTimeQpc();
#endif
double m_timerMul;
uint64_t m_resolution;
uint64_t m_delay;
std::atomic<int64_t> m_timeBegin;
uint32_t m_mainThread;
uint64_t m_epoch, m_exectime;
std::atomic<bool> m_shutdown;
std::atomic<bool> m_shutdownManual;
std::atomic<bool> m_shutdownFinished;
Socket* m_sock;
UdpBroadcast* m_broadcast;
bool m_noExit;
uint32_t m_userPort;
std::atomic<uint32_t> m_zoneId;
int64_t m_samplingPeriod;
uint32_t m_threadCtx;
int64_t m_refTimeThread;
int64_t m_refTimeSerial;
int64_t m_refTimeCtx;
int64_t m_refTimeGpu;
void* m_stream; // LZ4_stream_t*
char* m_buffer;
int m_bufferOffset;
int m_bufferStart;
char* m_lz4Buf;
FastVector<QueueItem> m_serialQueue, m_serialDequeue;
TracyMutex m_serialLock;
#ifndef TRACY_NO_FRAME_IMAGE
FastVector<FrameImageQueueItem> m_fiQueue, m_fiDequeue;
TracyMutex m_fiLock;
#endif
SPSCQueue<SymbolQueueItem> m_symbolQueue;
std::atomic<uint64_t> m_frameCount;
std::atomic<bool> m_isConnected;
#ifdef TRACY_ON_DEMAND
std::atomic<uint64_t> m_connectionId;
TracyMutex m_deferredLock;
FastVector<QueueItem> m_deferredQueue;
#endif
#ifdef TRACY_HAS_SYSTIME
void ProcessSysTime();
SysTime m_sysTime;
uint64_t m_sysTimeLast = 0;
#else
void ProcessSysTime() {}
#endif
ParameterCallback m_paramCallback;
void* m_paramCallbackData;
SourceContentsCallback m_sourceCallback;
void* m_sourceCallbackData;
char* m_queryImage;
char* m_queryData;
char* m_queryDataPtr;
#if defined _WIN32
void* m_exceptionHandler;
#endif
#ifdef __linux__
struct {
struct sigaction pwr, ill, fpe, segv, pipe, bus, abrt;
} m_prevSignal;
#endif
bool m_crashHandlerInstalled;
};
}
#endif

View File

@@ -0,0 +1,141 @@
#include <atomic>
#include <assert.h>
#include <errno.h>
#include <linux/perf_event.h>
#include <stdint.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
#include "TracyDebug.hpp"
namespace tracy
{
class RingBuffer
{
public:
RingBuffer( unsigned int size, int fd, int id, int cpu = -1 )
: m_size( size )
, m_id( id )
, m_cpu( cpu )
, m_fd( fd )
{
const auto pageSize = uint32_t( getpagesize() );
assert( size >= pageSize );
assert( __builtin_popcount( size ) == 1 );
m_mapSize = size + pageSize;
auto mapAddr = mmap( nullptr, m_mapSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
if( mapAddr == MAP_FAILED )
{
TracyDebug( "mmap failed: errno %i (%s)\n", errno, strerror( errno ) );
m_fd = 0;
m_metadata = nullptr;
close( fd );
return;
}
m_metadata = (perf_event_mmap_page*)mapAddr;
assert( m_metadata->data_offset == pageSize );
m_buffer = ((char*)mapAddr) + pageSize;
m_tail = m_metadata->data_tail;
}
~RingBuffer()
{
if( m_metadata ) munmap( m_metadata, m_mapSize );
if( m_fd ) close( m_fd );
}
RingBuffer( const RingBuffer& ) = delete;
RingBuffer& operator=( const RingBuffer& ) = delete;
RingBuffer( RingBuffer&& other )
{
memcpy( (char*)&other, (char*)this, sizeof( RingBuffer ) );
m_metadata = nullptr;
m_fd = 0;
}
RingBuffer& operator=( RingBuffer&& other )
{
memcpy( (char*)&other, (char*)this, sizeof( RingBuffer ) );
m_metadata = nullptr;
m_fd = 0;
return *this;
}
bool IsValid() const { return m_metadata != nullptr; }
int GetId() const { return m_id; }
int GetCpu() const { return m_cpu; }
void Enable()
{
ioctl( m_fd, PERF_EVENT_IOC_ENABLE, 0 );
}
void Read( void* dst, uint64_t offset, uint64_t cnt )
{
const auto size = m_size;
auto src = ( m_tail + offset ) % size;
if( src + cnt <= size )
{
memcpy( dst, m_buffer + src, cnt );
}
else
{
const auto s0 = size - src;
const auto buf = m_buffer;
memcpy( dst, buf + src, s0 );
memcpy( (char*)dst + s0, buf, cnt - s0 );
}
}
void Advance( uint64_t cnt )
{
m_tail += cnt;
StoreTail();
}
bool CheckTscCaps() const
{
return m_metadata->cap_user_time_zero;
}
int64_t ConvertTimeToTsc( int64_t timestamp ) const
{
if( !m_metadata->cap_user_time_zero ) return 0;
const auto time = timestamp - m_metadata->time_zero;
const auto quot = time / m_metadata->time_mult;
const auto rem = time % m_metadata->time_mult;
return ( quot << m_metadata->time_shift ) + ( rem << m_metadata->time_shift ) / m_metadata->time_mult;
}
uint64_t LoadHead() const
{
return std::atomic_load_explicit( (const volatile std::atomic<uint64_t>*)&m_metadata->data_head, std::memory_order_acquire );
}
uint64_t GetTail() const
{
return m_tail;
}
private:
void StoreTail()
{
std::atomic_store_explicit( (volatile std::atomic<uint64_t>*)&m_metadata->data_tail, m_tail, std::memory_order_release );
}
unsigned int m_size;
uint64_t m_tail;
char* m_buffer;
int m_id;
int m_cpu;
perf_event_mmap_page* m_metadata;
size_t m_mapSize;
int m_fd;
};
}

View File

@@ -0,0 +1,175 @@
#ifndef __TRACYSCOPED_HPP__
#define __TRACYSCOPED_HPP__
#include <limits>
#include <stdint.h>
#include <string.h>
#include "../common/TracySystem.hpp"
#include "../common/TracyAlign.hpp"
#include "../common/TracyAlloc.hpp"
#include "TracyProfiler.hpp"
namespace tracy
{
class ScopedZone
{
public:
ScopedZone( const ScopedZone& ) = delete;
ScopedZone( ScopedZone&& ) = delete;
ScopedZone& operator=( const ScopedZone& ) = delete;
ScopedZone& operator=( ScopedZone&& ) = delete;
tracy_force_inline ScopedZone( const SourceLocationData* srcloc, bool is_active = true )
#ifdef TRACY_ON_DEMAND
: m_active( is_active && GetProfiler().IsConnected() )
#else
: m_active( is_active )
#endif
{
if( !m_active ) return;
#ifdef TRACY_ON_DEMAND
m_connectionId = GetProfiler().ConnectionId();
#endif
TracyQueuePrepare( QueueType::ZoneBegin );
MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
MemWrite( &item->zoneBegin.srcloc, (uint64_t)srcloc );
TracyQueueCommit( zoneBeginThread );
}
tracy_force_inline ScopedZone( const SourceLocationData* srcloc, int depth, bool is_active = true )
#ifdef TRACY_ON_DEMAND
: m_active( is_active && GetProfiler().IsConnected() )
#else
: m_active( is_active )
#endif
{
if( !m_active ) return;
#ifdef TRACY_ON_DEMAND
m_connectionId = GetProfiler().ConnectionId();
#endif
GetProfiler().SendCallstack( depth );
TracyQueuePrepare( QueueType::ZoneBeginCallstack );
MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
MemWrite( &item->zoneBegin.srcloc, (uint64_t)srcloc );
TracyQueueCommit( zoneBeginThread );
}
tracy_force_inline ScopedZone( uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, bool is_active = true )
#ifdef TRACY_ON_DEMAND
: m_active( is_active && GetProfiler().IsConnected() )
#else
: m_active( is_active )
#endif
{
if( !m_active ) return;
#ifdef TRACY_ON_DEMAND
m_connectionId = GetProfiler().ConnectionId();
#endif
TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLoc );
const auto srcloc = Profiler::AllocSourceLocation( line, source, sourceSz, function, functionSz, name, nameSz );
MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
MemWrite( &item->zoneBegin.srcloc, srcloc );
TracyQueueCommit( zoneBeginThread );
}
tracy_force_inline ScopedZone( uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, int depth, bool is_active = true )
#ifdef TRACY_ON_DEMAND
: m_active( is_active && GetProfiler().IsConnected() )
#else
: m_active( is_active )
#endif
{
if( !m_active ) return;
#ifdef TRACY_ON_DEMAND
m_connectionId = GetProfiler().ConnectionId();
#endif
GetProfiler().SendCallstack( depth );
TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLocCallstack );
const auto srcloc = Profiler::AllocSourceLocation( line, source, sourceSz, function, functionSz, name, nameSz );
MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
MemWrite( &item->zoneBegin.srcloc, srcloc );
TracyQueueCommit( zoneBeginThread );
}
tracy_force_inline ~ScopedZone()
{
if( !m_active ) return;
#ifdef TRACY_ON_DEMAND
if( GetProfiler().ConnectionId() != m_connectionId ) return;
#endif
TracyQueuePrepare( QueueType::ZoneEnd );
MemWrite( &item->zoneEnd.time, Profiler::GetTime() );
TracyQueueCommit( zoneEndThread );
}
tracy_force_inline void Text( const char* txt, size_t size )
{
assert( size < std::numeric_limits<uint16_t>::max() );
if( !m_active ) return;
#ifdef TRACY_ON_DEMAND
if( GetProfiler().ConnectionId() != m_connectionId ) return;
#endif
auto ptr = (char*)tracy_malloc( size );
memcpy( ptr, txt, size );
TracyQueuePrepare( QueueType::ZoneText );
MemWrite( &item->zoneTextFat.text, (uint64_t)ptr );
MemWrite( &item->zoneTextFat.size, (uint16_t)size );
TracyQueueCommit( zoneTextFatThread );
}
tracy_force_inline void Name( const char* txt, size_t size )
{
assert( size < std::numeric_limits<uint16_t>::max() );
if( !m_active ) return;
#ifdef TRACY_ON_DEMAND
if( GetProfiler().ConnectionId() != m_connectionId ) return;
#endif
auto ptr = (char*)tracy_malloc( size );
memcpy( ptr, txt, size );
TracyQueuePrepare( QueueType::ZoneName );
MemWrite( &item->zoneTextFat.text, (uint64_t)ptr );
MemWrite( &item->zoneTextFat.size, (uint16_t)size );
TracyQueueCommit( zoneTextFatThread );
}
tracy_force_inline void Color( uint32_t color )
{
if( !m_active ) return;
#ifdef TRACY_ON_DEMAND
if( GetProfiler().ConnectionId() != m_connectionId ) return;
#endif
TracyQueuePrepare( QueueType::ZoneColor );
MemWrite( &item->zoneColor.b, uint8_t( ( color ) & 0xFF ) );
MemWrite( &item->zoneColor.g, uint8_t( ( color >> 8 ) & 0xFF ) );
MemWrite( &item->zoneColor.r, uint8_t( ( color >> 16 ) & 0xFF ) );
TracyQueueCommit( zoneColorThread );
}
tracy_force_inline void Value( uint64_t value )
{
if( !m_active ) return;
#ifdef TRACY_ON_DEMAND
if( GetProfiler().ConnectionId() != m_connectionId ) return;
#endif
TracyQueuePrepare( QueueType::ZoneValue );
MemWrite( &item->zoneValue.value, value );
TracyQueueCommit( zoneValueThread );
}
tracy_force_inline bool IsActive() const { return m_active; }
private:
const bool m_active;
#ifdef TRACY_ON_DEMAND
uint64_t m_connectionId = 0;
#endif
};
}
#endif

View File

@@ -0,0 +1,41 @@
#ifndef __TRACYSTRINGHELPERS_HPP__
#define __TRACYSTRINGHELPERS_HPP__
#include <assert.h>
#include <string.h>
#include "../common/TracyAlloc.hpp"
#include "../common/TracyForceInline.hpp"
namespace tracy
{
static tracy_force_inline char* CopyString( const char* src, size_t sz )
{
auto dst = (char*)tracy_malloc( sz + 1 );
memcpy( dst, src, sz );
dst[sz] = '\0';
return dst;
}
static tracy_force_inline char* CopyString( const char* src )
{
return CopyString( src, strlen( src ) );
}
static tracy_force_inline char* CopyStringFast( const char* src, size_t sz )
{
auto dst = (char*)tracy_malloc_fast( sz + 1 );
memcpy( dst, src, sz );
dst[sz] = '\0';
return dst;
}
static tracy_force_inline char* CopyStringFast( const char* src )
{
return CopyStringFast( src, strlen( src ) );
}
}
#endif

View File

@@ -0,0 +1,108 @@
#include "TracySysTime.hpp"
#ifdef TRACY_HAS_SYSTIME
# if defined _WIN32
# include <windows.h>
# elif defined __linux__
# include <stdio.h>
# include <inttypes.h>
# elif defined __APPLE__
# include <mach/mach_host.h>
# include <mach/host_info.h>
# elif defined BSD
# include <sys/types.h>
# include <sys/sysctl.h>
# endif
namespace tracy
{
# if defined _WIN32
static inline uint64_t ConvertTime( const FILETIME& t )
{
return ( uint64_t( t.dwHighDateTime ) << 32 ) | uint64_t( t.dwLowDateTime );
}
void SysTime::ReadTimes()
{
FILETIME idleTime;
FILETIME kernelTime;
FILETIME userTime;
GetSystemTimes( &idleTime, &kernelTime, &userTime );
idle = ConvertTime( idleTime );
const auto kernel = ConvertTime( kernelTime );
const auto user = ConvertTime( userTime );
used = kernel + user;
}
# elif defined __linux__
void SysTime::ReadTimes()
{
uint64_t user, nice, system;
FILE* f = fopen( "/proc/stat", "r" );
if( f )
{
int read = fscanf( f, "cpu %" PRIu64 " %" PRIu64 " %" PRIu64" %" PRIu64, &user, &nice, &system, &idle );
fclose( f );
if (read == 4)
{
used = user + nice + system;
}
}
}
# elif defined __APPLE__
void SysTime::ReadTimes()
{
host_cpu_load_info_data_t info;
mach_msg_type_number_t cnt = HOST_CPU_LOAD_INFO_COUNT;
host_statistics( mach_host_self(), HOST_CPU_LOAD_INFO, reinterpret_cast<host_info_t>( &info ), &cnt );
used = info.cpu_ticks[CPU_STATE_USER] + info.cpu_ticks[CPU_STATE_NICE] + info.cpu_ticks[CPU_STATE_SYSTEM];
idle = info.cpu_ticks[CPU_STATE_IDLE];
}
# elif defined BSD
void SysTime::ReadTimes()
{
u_long data[5];
size_t sz = sizeof( data );
sysctlbyname( "kern.cp_time", &data, &sz, nullptr, 0 );
used = data[0] + data[1] + data[2] + data[3];
idle = data[4];
}
#endif
SysTime::SysTime()
{
ReadTimes();
}
float SysTime::Get()
{
const auto oldUsed = used;
const auto oldIdle = idle;
ReadTimes();
const auto diffIdle = idle - oldIdle;
const auto diffUsed = used - oldUsed;
#if defined _WIN32
return diffUsed == 0 ? -1 : ( diffUsed - diffIdle ) * 100.f / diffUsed;
#elif defined __linux__ || defined __APPLE__ || defined BSD
const auto total = diffUsed + diffIdle;
return total == 0 ? -1 : diffUsed * 100.f / total;
#endif
}
}
#endif

View File

@@ -0,0 +1,36 @@
#ifndef __TRACYSYSTIME_HPP__
#define __TRACYSYSTIME_HPP__
#if defined _WIN32 || defined __linux__ || defined __APPLE__
# define TRACY_HAS_SYSTIME
#else
# include <sys/param.h>
#endif
#ifdef BSD
# define TRACY_HAS_SYSTIME
#endif
#ifdef TRACY_HAS_SYSTIME
#include <stdint.h>
namespace tracy
{
class SysTime
{
public:
SysTime();
float Get();
void ReadTimes();
private:
uint64_t idle, used;
};
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,28 @@
#ifndef __TRACYSYSTRACE_HPP__
#define __TRACYSYSTRACE_HPP__
#if !defined TRACY_NO_SYSTEM_TRACING && ( defined _WIN32 || defined __linux__ )
# include "../common/TracyUwp.hpp"
# ifndef TRACY_UWP
# define TRACY_HAS_SYSTEM_TRACING
# endif
#endif
#ifdef TRACY_HAS_SYSTEM_TRACING
#include <stdint.h>
namespace tracy
{
bool SysTraceStart( int64_t& samplingPeriod );
void SysTraceStop();
void SysTraceWorker( void* ptr );
void SysTraceGetExternalName( uint64_t thread, const char*& threadName, const char*& name );
}
#endif
#endif

View File

@@ -0,0 +1,90 @@
#ifndef __TRACYTHREAD_HPP__
#define __TRACYTHREAD_HPP__
#if defined _WIN32
# include <windows.h>
#else
# include <pthread.h>
#endif
#ifdef TRACY_MANUAL_LIFETIME
# include "tracy_rpmalloc.hpp"
#endif
namespace tracy
{
#ifdef TRACY_MANUAL_LIFETIME
extern thread_local bool RpThreadInitDone;
#endif
class ThreadExitHandler
{
public:
~ThreadExitHandler()
{
#ifdef TRACY_MANUAL_LIFETIME
rpmalloc_thread_finalize( 1 );
RpThreadInitDone = false;
#endif
}
};
#if defined _WIN32
class Thread
{
public:
Thread( void(*func)( void* ptr ), void* ptr )
: m_func( func )
, m_ptr( ptr )
, m_hnd( CreateThread( nullptr, 0, Launch, this, 0, nullptr ) )
{}
~Thread()
{
WaitForSingleObject( m_hnd, INFINITE );
CloseHandle( m_hnd );
}
HANDLE Handle() const { return m_hnd; }
private:
static DWORD WINAPI Launch( void* ptr ) { ((Thread*)ptr)->m_func( ((Thread*)ptr)->m_ptr ); return 0; }
void(*m_func)( void* ptr );
void* m_ptr;
HANDLE m_hnd;
};
#else
class Thread
{
public:
Thread( void(*func)( void* ptr ), void* ptr )
: m_func( func )
, m_ptr( ptr )
{
pthread_create( &m_thread, nullptr, Launch, this );
}
~Thread()
{
pthread_join( m_thread, nullptr );
}
pthread_t Handle() const { return m_thread; }
private:
static void* Launch( void* ptr ) { ((Thread*)ptr)->m_func( ((Thread*)ptr)->m_ptr ); return nullptr; }
void(*m_func)( void* ptr );
void* m_ptr;
pthread_t m_thread;
};
#endif
}
#endif

View File

@@ -0,0 +1,148 @@
/*
Copyright (c) 2020 Erik Rigtorp <erik@rigtorp.se>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <atomic>
#include <cassert>
#include <cstddef>
#include <stdexcept>
#include <type_traits> // std::enable_if, std::is_*_constructible
#include "../common/TracyAlloc.hpp"
#if defined (_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4324)
#endif
namespace tracy {
template <typename T> class SPSCQueue {
public:
explicit SPSCQueue(const size_t capacity)
: capacity_(capacity) {
capacity_++; // Needs one slack element
slots_ = (T*)tracy_malloc(sizeof(T) * (capacity_ + 2 * kPadding));
static_assert(alignof(SPSCQueue<T>) == kCacheLineSize, "");
static_assert(sizeof(SPSCQueue<T>) >= 3 * kCacheLineSize, "");
assert(reinterpret_cast<char *>(&readIdx_) -
reinterpret_cast<char *>(&writeIdx_) >=
static_cast<std::ptrdiff_t>(kCacheLineSize));
}
~SPSCQueue() {
while (front()) {
pop();
}
tracy_free(slots_);
}
// non-copyable and non-movable
SPSCQueue(const SPSCQueue &) = delete;
SPSCQueue &operator=(const SPSCQueue &) = delete;
template <typename... Args>
void emplace(Args &&...args) noexcept(
std::is_nothrow_constructible<T, Args &&...>::value) {
static_assert(std::is_constructible<T, Args &&...>::value,
"T must be constructible with Args&&...");
auto const writeIdx = writeIdx_.load(std::memory_order_relaxed);
auto nextWriteIdx = writeIdx + 1;
if (nextWriteIdx == capacity_) {
nextWriteIdx = 0;
}
while (nextWriteIdx == readIdxCache_) {
readIdxCache_ = readIdx_.load(std::memory_order_acquire);
}
new (&slots_[writeIdx + kPadding]) T(std::forward<Args>(args)...);
writeIdx_.store(nextWriteIdx, std::memory_order_release);
}
T *front() noexcept {
auto const readIdx = readIdx_.load(std::memory_order_relaxed);
if (readIdx == writeIdxCache_) {
writeIdxCache_ = writeIdx_.load(std::memory_order_acquire);
if (writeIdxCache_ == readIdx) {
return nullptr;
}
}
return &slots_[readIdx + kPadding];
}
void pop() noexcept {
static_assert(std::is_nothrow_destructible<T>::value,
"T must be nothrow destructible");
auto const readIdx = readIdx_.load(std::memory_order_relaxed);
assert(writeIdx_.load(std::memory_order_acquire) != readIdx);
slots_[readIdx + kPadding].~T();
auto nextReadIdx = readIdx + 1;
if (nextReadIdx == capacity_) {
nextReadIdx = 0;
}
readIdx_.store(nextReadIdx, std::memory_order_release);
}
size_t size() const noexcept {
std::ptrdiff_t diff = writeIdx_.load(std::memory_order_acquire) -
readIdx_.load(std::memory_order_acquire);
if (diff < 0) {
diff += capacity_;
}
return static_cast<size_t>(diff);
}
bool empty() const noexcept {
return writeIdx_.load(std::memory_order_acquire) ==
readIdx_.load(std::memory_order_acquire);
}
size_t capacity() const noexcept { return capacity_ - 1; }
private:
static constexpr size_t kCacheLineSize = 64;
// Padding to avoid false sharing between slots_ and adjacent allocations
static constexpr size_t kPadding = (kCacheLineSize - 1) / sizeof(T) + 1;
private:
size_t capacity_;
T *slots_;
// Align to cache line size in order to avoid false sharing
// readIdxCache_ and writeIdxCache_ is used to reduce the amount of cache
// coherency traffic
alignas(kCacheLineSize) std::atomic<size_t> writeIdx_ = {0};
alignas(kCacheLineSize) size_t readIdxCache_ = 0;
alignas(kCacheLineSize) std::atomic<size_t> readIdx_ = {0};
alignas(kCacheLineSize) size_t writeIdxCache_ = 0;
// Padding to avoid adjacent allocations to share cache line with
// writeIdxCache_
char padding_[kCacheLineSize - sizeof(SPSCQueue<T>::writeIdxCache_)];
};
} // namespace rigtorp
#if defined (_MSC_VER)
#pragma warning(pop)
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,363 @@
/* rpmalloc.h - Memory allocator - Public Domain - 2016 Mattias Jansson
*
* This library provides a cross-platform lock free thread caching malloc implementation in C11.
* The latest source code is always available at
*
* https://github.com/mjansson/rpmalloc
*
* This library is put in the public domain; you can redistribute it and/or modify it without any restrictions.
*
*/
#pragma once
#include <stddef.h>
#include "../common/TracyApi.h"
namespace tracy
{
#if defined(__clang__) || defined(__GNUC__)
# define RPMALLOC_EXPORT __attribute__((visibility("default")))
# define RPMALLOC_ALLOCATOR
# if (defined(__clang_major__) && (__clang_major__ < 4)) || (defined(__GNUC__) && defined(ENABLE_PRELOAD) && ENABLE_PRELOAD)
# define RPMALLOC_ATTRIB_MALLOC
# define RPMALLOC_ATTRIB_ALLOC_SIZE(size)
# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size)
# else
# define RPMALLOC_ATTRIB_MALLOC __attribute__((__malloc__))
# define RPMALLOC_ATTRIB_ALLOC_SIZE(size) __attribute__((alloc_size(size)))
# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size) __attribute__((alloc_size(count, size)))
# endif
# define RPMALLOC_CDECL
#elif defined(_MSC_VER)
# define RPMALLOC_EXPORT
# define RPMALLOC_ALLOCATOR __declspec(allocator) __declspec(restrict)
# define RPMALLOC_ATTRIB_MALLOC
# define RPMALLOC_ATTRIB_ALLOC_SIZE(size)
# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count,size)
# define RPMALLOC_CDECL __cdecl
#else
# define RPMALLOC_EXPORT
# define RPMALLOC_ALLOCATOR
# define RPMALLOC_ATTRIB_MALLOC
# define RPMALLOC_ATTRIB_ALLOC_SIZE(size)
# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count,size)
# define RPMALLOC_CDECL
#endif
//! Define RPMALLOC_CONFIGURABLE to enable configuring sizes. Will introduce
// a very small overhead due to some size calculations not being compile time constants
#ifndef RPMALLOC_CONFIGURABLE
#define RPMALLOC_CONFIGURABLE 0
#endif
//! Define RPMALLOC_FIRST_CLASS_HEAPS to enable heap based API (rpmalloc_heap_* functions).
// Will introduce a very small overhead to track fully allocated spans in heaps
#ifndef RPMALLOC_FIRST_CLASS_HEAPS
#define RPMALLOC_FIRST_CLASS_HEAPS 0
#endif
//! Flag to rpaligned_realloc to not preserve content in reallocation
#define RPMALLOC_NO_PRESERVE 1
//! Flag to rpaligned_realloc to fail and return null pointer if grow cannot be done in-place,
// in which case the original pointer is still valid (just like a call to realloc which failes to allocate
// a new block).
#define RPMALLOC_GROW_OR_FAIL 2
typedef struct rpmalloc_global_statistics_t {
//! Current amount of virtual memory mapped, all of which might not have been committed (only if ENABLE_STATISTICS=1)
size_t mapped;
//! Peak amount of virtual memory mapped, all of which might not have been committed (only if ENABLE_STATISTICS=1)
size_t mapped_peak;
//! Current amount of memory in global caches for small and medium sizes (<32KiB)
size_t cached;
//! Current amount of memory allocated in huge allocations, i.e larger than LARGE_SIZE_LIMIT which is 2MiB by default (only if ENABLE_STATISTICS=1)
size_t huge_alloc;
//! Peak amount of memory allocated in huge allocations, i.e larger than LARGE_SIZE_LIMIT which is 2MiB by default (only if ENABLE_STATISTICS=1)
size_t huge_alloc_peak;
//! Total amount of memory mapped since initialization (only if ENABLE_STATISTICS=1)
size_t mapped_total;
//! Total amount of memory unmapped since initialization (only if ENABLE_STATISTICS=1)
size_t unmapped_total;
} rpmalloc_global_statistics_t;
typedef struct rpmalloc_thread_statistics_t {
//! Current number of bytes available in thread size class caches for small and medium sizes (<32KiB)
size_t sizecache;
//! Current number of bytes available in thread span caches for small and medium sizes (<32KiB)
size_t spancache;
//! Total number of bytes transitioned from thread cache to global cache (only if ENABLE_STATISTICS=1)
size_t thread_to_global;
//! Total number of bytes transitioned from global cache to thread cache (only if ENABLE_STATISTICS=1)
size_t global_to_thread;
//! Per span count statistics (only if ENABLE_STATISTICS=1)
struct {
//! Currently used number of spans
size_t current;
//! High water mark of spans used
size_t peak;
//! Number of spans transitioned to global cache
size_t to_global;
//! Number of spans transitioned from global cache
size_t from_global;
//! Number of spans transitioned to thread cache
size_t to_cache;
//! Number of spans transitioned from thread cache
size_t from_cache;
//! Number of spans transitioned to reserved state
size_t to_reserved;
//! Number of spans transitioned from reserved state
size_t from_reserved;
//! Number of raw memory map calls (not hitting the reserve spans but resulting in actual OS mmap calls)
size_t map_calls;
} span_use[64];
//! Per size class statistics (only if ENABLE_STATISTICS=1)
struct {
//! Current number of allocations
size_t alloc_current;
//! Peak number of allocations
size_t alloc_peak;
//! Total number of allocations
size_t alloc_total;
//! Total number of frees
size_t free_total;
//! Number of spans transitioned to cache
size_t spans_to_cache;
//! Number of spans transitioned from cache
size_t spans_from_cache;
//! Number of spans transitioned from reserved state
size_t spans_from_reserved;
//! Number of raw memory map calls (not hitting the reserve spans but resulting in actual OS mmap calls)
size_t map_calls;
} size_use[128];
} rpmalloc_thread_statistics_t;
typedef struct rpmalloc_config_t {
//! Map memory pages for the given number of bytes. The returned address MUST be
// aligned to the rpmalloc span size, which will always be a power of two.
// Optionally the function can store an alignment offset in the offset variable
// in case it performs alignment and the returned pointer is offset from the
// actual start of the memory region due to this alignment. The alignment offset
// will be passed to the memory unmap function. The alignment offset MUST NOT be
// larger than 65535 (storable in an uint16_t), if it is you must use natural
// alignment to shift it into 16 bits. If you set a memory_map function, you
// must also set a memory_unmap function or else the default implementation will
// be used for both. This function must be thread safe, it can be called by
// multiple threads simultaneously.
void* (*memory_map)(size_t size, size_t* offset);
//! Unmap the memory pages starting at address and spanning the given number of bytes.
// If release is set to non-zero, the unmap is for an entire span range as returned by
// a previous call to memory_map and that the entire range should be released. The
// release argument holds the size of the entire span range. If release is set to 0,
// the unmap is a partial decommit of a subset of the mapped memory range.
// If you set a memory_unmap function, you must also set a memory_map function or
// else the default implementation will be used for both. This function must be thread
// safe, it can be called by multiple threads simultaneously.
void (*memory_unmap)(void* address, size_t size, size_t offset, size_t release);
//! Called when an assert fails, if asserts are enabled. Will use the standard assert()
// if this is not set.
void (*error_callback)(const char* message);
//! Called when a call to map memory pages fails (out of memory). If this callback is
// not set or returns zero the library will return a null pointer in the allocation
// call. If this callback returns non-zero the map call will be retried. The argument
// passed is the number of bytes that was requested in the map call. Only used if
// the default system memory map function is used (memory_map callback is not set).
int (*map_fail_callback)(size_t size);
//! Size of memory pages. The page size MUST be a power of two. All memory mapping
// requests to memory_map will be made with size set to a multiple of the page size.
// Used if RPMALLOC_CONFIGURABLE is defined to 1, otherwise system page size is used.
size_t page_size;
//! Size of a span of memory blocks. MUST be a power of two, and in [4096,262144]
// range (unless 0 - set to 0 to use the default span size). Used if RPMALLOC_CONFIGURABLE
// is defined to 1.
size_t span_size;
//! Number of spans to map at each request to map new virtual memory blocks. This can
// be used to minimize the system call overhead at the cost of virtual memory address
// space. The extra mapped pages will not be written until actually used, so physical
// committed memory should not be affected in the default implementation. Will be
// aligned to a multiple of spans that match memory page size in case of huge pages.
size_t span_map_count;
//! Enable use of large/huge pages. If this flag is set to non-zero and page size is
// zero, the allocator will try to enable huge pages and auto detect the configuration.
// If this is set to non-zero and page_size is also non-zero, the allocator will
// assume huge pages have been configured and enabled prior to initializing the
// allocator.
// For Windows, see https://docs.microsoft.com/en-us/windows/desktop/memory/large-page-support
// For Linux, see https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt
int enable_huge_pages;
//! Respectively allocated pages and huge allocated pages names for systems
// supporting it to be able to distinguish among anonymous regions.
const char *page_name;
const char *huge_page_name;
} rpmalloc_config_t;
//! Initialize allocator with default configuration
TRACY_API int
rpmalloc_initialize(void);
//! Initialize allocator with given configuration
RPMALLOC_EXPORT int
rpmalloc_initialize_config(const rpmalloc_config_t* config);
//! Get allocator configuration
RPMALLOC_EXPORT const rpmalloc_config_t*
rpmalloc_config(void);
//! Finalize allocator
TRACY_API void
rpmalloc_finalize(void);
//! Initialize allocator for calling thread
TRACY_API void
rpmalloc_thread_initialize(void);
//! Finalize allocator for calling thread
TRACY_API void
rpmalloc_thread_finalize(int release_caches);
//! Perform deferred deallocations pending for the calling thread heap
RPMALLOC_EXPORT void
rpmalloc_thread_collect(void);
//! Query if allocator is initialized for calling thread
RPMALLOC_EXPORT int
rpmalloc_is_thread_initialized(void);
//! Get per-thread statistics
RPMALLOC_EXPORT void
rpmalloc_thread_statistics(rpmalloc_thread_statistics_t* stats);
//! Get global statistics
RPMALLOC_EXPORT void
rpmalloc_global_statistics(rpmalloc_global_statistics_t* stats);
//! Dump all statistics in human readable format to file (should be a FILE*)
RPMALLOC_EXPORT void
rpmalloc_dump_statistics(void* file);
//! Allocate a memory block of at least the given size
TRACY_API RPMALLOC_ALLOCATOR void*
rpmalloc(size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1);
//! Free the given memory block
TRACY_API void
rpfree(void* ptr);
//! Allocate a memory block of at least the given size and zero initialize it
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpcalloc(size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(1, 2);
//! Reallocate the given block to at least the given size
TRACY_API RPMALLOC_ALLOCATOR void*
rprealloc(void* ptr, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);
//! Reallocate the given block to at least the given size and alignment,
// with optional control flags (see RPMALLOC_NO_PRESERVE).
// Alignment must be a power of two and a multiple of sizeof(void*),
// and should ideally be less than memory page size. A caveat of rpmalloc
// internals is that this must also be strictly less than the span size (default 64KiB)
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpaligned_realloc(void* ptr, size_t alignment, size_t size, size_t oldsize, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3);
//! Allocate a memory block of at least the given size and alignment.
// Alignment must be a power of two and a multiple of sizeof(void*),
// and should ideally be less than memory page size. A caveat of rpmalloc
// internals is that this must also be strictly less than the span size (default 64KiB)
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpaligned_alloc(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);
//! Allocate a memory block of at least the given size and alignment, and zero initialize it.
// Alignment must be a power of two and a multiple of sizeof(void*),
// and should ideally be less than memory page size. A caveat of rpmalloc
// internals is that this must also be strictly less than the span size (default 64KiB)
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpaligned_calloc(size_t alignment, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);
//! Allocate a memory block of at least the given size and alignment.
// Alignment must be a power of two and a multiple of sizeof(void*),
// and should ideally be less than memory page size. A caveat of rpmalloc
// internals is that this must also be strictly less than the span size (default 64KiB)
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpmemalign(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);
//! Allocate a memory block of at least the given size and alignment.
// Alignment must be a power of two and a multiple of sizeof(void*),
// and should ideally be less than memory page size. A caveat of rpmalloc
// internals is that this must also be strictly less than the span size (default 64KiB)
RPMALLOC_EXPORT int
rpposix_memalign(void** memptr, size_t alignment, size_t size);
//! Query the usable size of the given memory block (from given pointer to the end of block)
RPMALLOC_EXPORT size_t
rpmalloc_usable_size(void* ptr);
#if RPMALLOC_FIRST_CLASS_HEAPS
//! Heap type
typedef struct heap_t rpmalloc_heap_t;
//! Acquire a new heap. Will reuse existing released heaps or allocate memory for a new heap
// if none available. Heap API is implemented with the strict assumption that only one single
// thread will call heap functions for a given heap at any given time, no functions are thread safe.
RPMALLOC_EXPORT rpmalloc_heap_t*
rpmalloc_heap_acquire(void);
//! Release a heap (does NOT free the memory allocated by the heap, use rpmalloc_heap_free_all before destroying the heap).
// Releasing a heap will enable it to be reused by other threads. Safe to pass a null pointer.
RPMALLOC_EXPORT void
rpmalloc_heap_release(rpmalloc_heap_t* heap);
//! Allocate a memory block of at least the given size using the given heap.
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpmalloc_heap_alloc(rpmalloc_heap_t* heap, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);
//! Allocate a memory block of at least the given size using the given heap. The returned
// block will have the requested alignment. Alignment must be a power of two and a multiple of sizeof(void*),
// and should ideally be less than memory page size. A caveat of rpmalloc
// internals is that this must also be strictly less than the span size (default 64KiB).
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpmalloc_heap_aligned_alloc(rpmalloc_heap_t* heap, size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3);
//! Allocate a memory block of at least the given size using the given heap and zero initialize it.
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpmalloc_heap_calloc(rpmalloc_heap_t* heap, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);
//! Allocate a memory block of at least the given size using the given heap and zero initialize it. The returned
// block will have the requested alignment. Alignment must either be zero, or a power of two and a multiple of sizeof(void*),
// and should ideally be less than memory page size. A caveat of rpmalloc
// internals is that this must also be strictly less than the span size (default 64KiB).
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpmalloc_heap_aligned_calloc(rpmalloc_heap_t* heap, size_t alignment, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);
//! Reallocate the given block to at least the given size. The memory block MUST be allocated
// by the same heap given to this function.
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpmalloc_heap_realloc(rpmalloc_heap_t* heap, void* ptr, size_t size, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3);
//! Reallocate the given block to at least the given size. The memory block MUST be allocated
// by the same heap given to this function. The returned block will have the requested alignment.
// Alignment must be either zero, or a power of two and a multiple of sizeof(void*), and should ideally be
// less than memory page size. A caveat of rpmalloc internals is that this must also be strictly less than
// the span size (default 64KiB).
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpmalloc_heap_aligned_realloc(rpmalloc_heap_t* heap, void* ptr, size_t alignment, size_t size, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(4);
//! Free the given memory block from the given heap. The memory block MUST be allocated
// by the same heap given to this function.
RPMALLOC_EXPORT void
rpmalloc_heap_free(rpmalloc_heap_t* heap, void* ptr);
//! Free all memory allocated by the heap
RPMALLOC_EXPORT void
rpmalloc_heap_free_all(rpmalloc_heap_t* heap);
//! Set the given heap as the current heap for the calling thread. A heap MUST only be current heap
// for a single thread, a heap can never be shared between multiple threads. The previous
// current heap for the calling thread is released to be reused by other threads.
RPMALLOC_EXPORT void
rpmalloc_heap_thread_set_current(rpmalloc_heap_t* heap);
#endif
}

View File

@@ -0,0 +1,27 @@
#ifndef __TRACYALIGN_HPP__
#define __TRACYALIGN_HPP__
#include <string.h>
#include "TracyForceInline.hpp"
namespace tracy
{
template<typename T>
tracy_force_inline T MemRead( const void* ptr )
{
T val;
memcpy( &val, ptr, sizeof( T ) );
return val;
}
template<typename T>
tracy_force_inline void MemWrite( void* ptr, T val )
{
memcpy( ptr, &val, sizeof( T ) );
}
}
#endif

View File

@@ -0,0 +1,72 @@
#ifndef __TRACYALLOC_HPP__
#define __TRACYALLOC_HPP__
#include <stdlib.h>
#if defined TRACY_ENABLE && !defined __EMSCRIPTEN__
# include "TracyApi.h"
# include "TracyForceInline.hpp"
# include "../client/tracy_rpmalloc.hpp"
# define TRACY_USE_RPMALLOC
#endif
namespace tracy
{
#ifdef TRACY_USE_RPMALLOC
TRACY_API void InitRpmalloc();
#else
static inline void InitRpmalloc() {}
#endif
static inline void* tracy_malloc( size_t size )
{
#ifdef TRACY_USE_RPMALLOC
InitRpmalloc();
return rpmalloc( size );
#else
return malloc( size );
#endif
}
static inline void* tracy_malloc_fast( size_t size )
{
#ifdef TRACY_USE_RPMALLOC
return rpmalloc( size );
#else
return malloc( size );
#endif
}
static inline void tracy_free( void* ptr )
{
#ifdef TRACY_USE_RPMALLOC
InitRpmalloc();
rpfree( ptr );
#else
free( ptr );
#endif
}
static inline void tracy_free_fast( void* ptr )
{
#ifdef TRACY_USE_RPMALLOC
rpfree( ptr );
#else
free( ptr );
#endif
}
static inline void* tracy_realloc( void* ptr, size_t size )
{
#ifdef TRACY_USE_RPMALLOC
InitRpmalloc();
return rprealloc( ptr, size );
#else
return realloc( ptr, size );
#endif
}
}
#endif

View File

@@ -0,0 +1,16 @@
#ifndef __TRACYAPI_H__
#define __TRACYAPI_H__
#if defined _WIN32
# if defined TRACY_EXPORTS
# define TRACY_API __declspec(dllexport)
# elif defined TRACY_IMPORTS
# define TRACY_API __declspec(dllimport)
# else
# define TRACY_API
# endif
#else
# define TRACY_API __attribute__((visibility("default")))
#endif
#endif // __TRACYAPI_H__

View File

@@ -0,0 +1,690 @@
#ifndef __TRACYCOLOR_HPP__
#define __TRACYCOLOR_HPP__
namespace tracy
{
struct Color
{
enum ColorType
{
Snow = 0xfffafa,
GhostWhite = 0xf8f8ff,
WhiteSmoke = 0xf5f5f5,
Gainsboro = 0xdcdcdc,
FloralWhite = 0xfffaf0,
OldLace = 0xfdf5e6,
Linen = 0xfaf0e6,
AntiqueWhite = 0xfaebd7,
PapayaWhip = 0xffefd5,
BlanchedAlmond = 0xffebcd,
Bisque = 0xffe4c4,
PeachPuff = 0xffdab9,
NavajoWhite = 0xffdead,
Moccasin = 0xffe4b5,
Cornsilk = 0xfff8dc,
Ivory = 0xfffff0,
LemonChiffon = 0xfffacd,
Seashell = 0xfff5ee,
Honeydew = 0xf0fff0,
MintCream = 0xf5fffa,
Azure = 0xf0ffff,
AliceBlue = 0xf0f8ff,
Lavender = 0xe6e6fa,
LavenderBlush = 0xfff0f5,
MistyRose = 0xffe4e1,
White = 0xffffff,
Black = 0x000000,
DarkSlateGray = 0x2f4f4f,
DarkSlateGrey = 0x2f4f4f,
DimGray = 0x696969,
DimGrey = 0x696969,
SlateGray = 0x708090,
SlateGrey = 0x708090,
LightSlateGray = 0x778899,
LightSlateGrey = 0x778899,
Gray = 0xbebebe,
Grey = 0xbebebe,
X11Gray = 0xbebebe,
X11Grey = 0xbebebe,
WebGray = 0x808080,
WebGrey = 0x808080,
LightGrey = 0xd3d3d3,
LightGray = 0xd3d3d3,
MidnightBlue = 0x191970,
Navy = 0x000080,
NavyBlue = 0x000080,
CornflowerBlue = 0x6495ed,
DarkSlateBlue = 0x483d8b,
SlateBlue = 0x6a5acd,
MediumSlateBlue = 0x7b68ee,
LightSlateBlue = 0x8470ff,
MediumBlue = 0x0000cd,
RoyalBlue = 0x4169e1,
Blue = 0x0000ff,
DodgerBlue = 0x1e90ff,
DeepSkyBlue = 0x00bfff,
SkyBlue = 0x87ceeb,
LightSkyBlue = 0x87cefa,
SteelBlue = 0x4682b4,
LightSteelBlue = 0xb0c4de,
LightBlue = 0xadd8e6,
PowderBlue = 0xb0e0e6,
PaleTurquoise = 0xafeeee,
DarkTurquoise = 0x00ced1,
MediumTurquoise = 0x48d1cc,
Turquoise = 0x40e0d0,
Cyan = 0x00ffff,
Aqua = 0x00ffff,
LightCyan = 0xe0ffff,
CadetBlue = 0x5f9ea0,
MediumAquamarine = 0x66cdaa,
Aquamarine = 0x7fffd4,
DarkGreen = 0x006400,
DarkOliveGreen = 0x556b2f,
DarkSeaGreen = 0x8fbc8f,
SeaGreen = 0x2e8b57,
MediumSeaGreen = 0x3cb371,
LightSeaGreen = 0x20b2aa,
PaleGreen = 0x98fb98,
SpringGreen = 0x00ff7f,
LawnGreen = 0x7cfc00,
Green = 0x00ff00,
Lime = 0x00ff00,
X11Green = 0x00ff00,
WebGreen = 0x008000,
Chartreuse = 0x7fff00,
MediumSpringGreen = 0x00fa9a,
GreenYellow = 0xadff2f,
LimeGreen = 0x32cd32,
YellowGreen = 0x9acd32,
ForestGreen = 0x228b22,
OliveDrab = 0x6b8e23,
DarkKhaki = 0xbdb76b,
Khaki = 0xf0e68c,
PaleGoldenrod = 0xeee8aa,
LightGoldenrodYellow = 0xfafad2,
LightYellow = 0xffffe0,
Yellow = 0xffff00,
Gold = 0xffd700,
LightGoldenrod = 0xeedd82,
Goldenrod = 0xdaa520,
DarkGoldenrod = 0xb8860b,
RosyBrown = 0xbc8f8f,
IndianRed = 0xcd5c5c,
SaddleBrown = 0x8b4513,
Sienna = 0xa0522d,
Peru = 0xcd853f,
Burlywood = 0xdeb887,
Beige = 0xf5f5dc,
Wheat = 0xf5deb3,
SandyBrown = 0xf4a460,
Tan = 0xd2b48c,
Chocolate = 0xd2691e,
Firebrick = 0xb22222,
Brown = 0xa52a2a,
DarkSalmon = 0xe9967a,
Salmon = 0xfa8072,
LightSalmon = 0xffa07a,
Orange = 0xffa500,
DarkOrange = 0xff8c00,
Coral = 0xff7f50,
LightCoral = 0xf08080,
Tomato = 0xff6347,
OrangeRed = 0xff4500,
Red = 0xff0000,
HotPink = 0xff69b4,
DeepPink = 0xff1493,
Pink = 0xffc0cb,
LightPink = 0xffb6c1,
PaleVioletRed = 0xdb7093,
Maroon = 0xb03060,
X11Maroon = 0xb03060,
WebMaroon = 0x800000,
MediumVioletRed = 0xc71585,
VioletRed = 0xd02090,
Magenta = 0xff00ff,
Fuchsia = 0xff00ff,
Violet = 0xee82ee,
Plum = 0xdda0dd,
Orchid = 0xda70d6,
MediumOrchid = 0xba55d3,
DarkOrchid = 0x9932cc,
DarkViolet = 0x9400d3,
BlueViolet = 0x8a2be2,
Purple = 0xa020f0,
X11Purple = 0xa020f0,
WebPurple = 0x800080,
MediumPurple = 0x9370db,
Thistle = 0xd8bfd8,
Snow1 = 0xfffafa,
Snow2 = 0xeee9e9,
Snow3 = 0xcdc9c9,
Snow4 = 0x8b8989,
Seashell1 = 0xfff5ee,
Seashell2 = 0xeee5de,
Seashell3 = 0xcdc5bf,
Seashell4 = 0x8b8682,
AntiqueWhite1 = 0xffefdb,
AntiqueWhite2 = 0xeedfcc,
AntiqueWhite3 = 0xcdc0b0,
AntiqueWhite4 = 0x8b8378,
Bisque1 = 0xffe4c4,
Bisque2 = 0xeed5b7,
Bisque3 = 0xcdb79e,
Bisque4 = 0x8b7d6b,
PeachPuff1 = 0xffdab9,
PeachPuff2 = 0xeecbad,
PeachPuff3 = 0xcdaf95,
PeachPuff4 = 0x8b7765,
NavajoWhite1 = 0xffdead,
NavajoWhite2 = 0xeecfa1,
NavajoWhite3 = 0xcdb38b,
NavajoWhite4 = 0x8b795e,
LemonChiffon1 = 0xfffacd,
LemonChiffon2 = 0xeee9bf,
LemonChiffon3 = 0xcdc9a5,
LemonChiffon4 = 0x8b8970,
Cornsilk1 = 0xfff8dc,
Cornsilk2 = 0xeee8cd,
Cornsilk3 = 0xcdc8b1,
Cornsilk4 = 0x8b8878,
Ivory1 = 0xfffff0,
Ivory2 = 0xeeeee0,
Ivory3 = 0xcdcdc1,
Ivory4 = 0x8b8b83,
Honeydew1 = 0xf0fff0,
Honeydew2 = 0xe0eee0,
Honeydew3 = 0xc1cdc1,
Honeydew4 = 0x838b83,
LavenderBlush1 = 0xfff0f5,
LavenderBlush2 = 0xeee0e5,
LavenderBlush3 = 0xcdc1c5,
LavenderBlush4 = 0x8b8386,
MistyRose1 = 0xffe4e1,
MistyRose2 = 0xeed5d2,
MistyRose3 = 0xcdb7b5,
MistyRose4 = 0x8b7d7b,
Azure1 = 0xf0ffff,
Azure2 = 0xe0eeee,
Azure3 = 0xc1cdcd,
Azure4 = 0x838b8b,
SlateBlue1 = 0x836fff,
SlateBlue2 = 0x7a67ee,
SlateBlue3 = 0x6959cd,
SlateBlue4 = 0x473c8b,
RoyalBlue1 = 0x4876ff,
RoyalBlue2 = 0x436eee,
RoyalBlue3 = 0x3a5fcd,
RoyalBlue4 = 0x27408b,
Blue1 = 0x0000ff,
Blue2 = 0x0000ee,
Blue3 = 0x0000cd,
Blue4 = 0x00008b,
DodgerBlue1 = 0x1e90ff,
DodgerBlue2 = 0x1c86ee,
DodgerBlue3 = 0x1874cd,
DodgerBlue4 = 0x104e8b,
SteelBlue1 = 0x63b8ff,
SteelBlue2 = 0x5cacee,
SteelBlue3 = 0x4f94cd,
SteelBlue4 = 0x36648b,
DeepSkyBlue1 = 0x00bfff,
DeepSkyBlue2 = 0x00b2ee,
DeepSkyBlue3 = 0x009acd,
DeepSkyBlue4 = 0x00688b,
SkyBlue1 = 0x87ceff,
SkyBlue2 = 0x7ec0ee,
SkyBlue3 = 0x6ca6cd,
SkyBlue4 = 0x4a708b,
LightSkyBlue1 = 0xb0e2ff,
LightSkyBlue2 = 0xa4d3ee,
LightSkyBlue3 = 0x8db6cd,
LightSkyBlue4 = 0x607b8b,
SlateGray1 = 0xc6e2ff,
SlateGray2 = 0xb9d3ee,
SlateGray3 = 0x9fb6cd,
SlateGray4 = 0x6c7b8b,
LightSteelBlue1 = 0xcae1ff,
LightSteelBlue2 = 0xbcd2ee,
LightSteelBlue3 = 0xa2b5cd,
LightSteelBlue4 = 0x6e7b8b,
LightBlue1 = 0xbfefff,
LightBlue2 = 0xb2dfee,
LightBlue3 = 0x9ac0cd,
LightBlue4 = 0x68838b,
LightCyan1 = 0xe0ffff,
LightCyan2 = 0xd1eeee,
LightCyan3 = 0xb4cdcd,
LightCyan4 = 0x7a8b8b,
PaleTurquoise1 = 0xbbffff,
PaleTurquoise2 = 0xaeeeee,
PaleTurquoise3 = 0x96cdcd,
PaleTurquoise4 = 0x668b8b,
CadetBlue1 = 0x98f5ff,
CadetBlue2 = 0x8ee5ee,
CadetBlue3 = 0x7ac5cd,
CadetBlue4 = 0x53868b,
Turquoise1 = 0x00f5ff,
Turquoise2 = 0x00e5ee,
Turquoise3 = 0x00c5cd,
Turquoise4 = 0x00868b,
Cyan1 = 0x00ffff,
Cyan2 = 0x00eeee,
Cyan3 = 0x00cdcd,
Cyan4 = 0x008b8b,
DarkSlateGray1 = 0x97ffff,
DarkSlateGray2 = 0x8deeee,
DarkSlateGray3 = 0x79cdcd,
DarkSlateGray4 = 0x528b8b,
Aquamarine1 = 0x7fffd4,
Aquamarine2 = 0x76eec6,
Aquamarine3 = 0x66cdaa,
Aquamarine4 = 0x458b74,
DarkSeaGreen1 = 0xc1ffc1,
DarkSeaGreen2 = 0xb4eeb4,
DarkSeaGreen3 = 0x9bcd9b,
DarkSeaGreen4 = 0x698b69,
SeaGreen1 = 0x54ff9f,
SeaGreen2 = 0x4eee94,
SeaGreen3 = 0x43cd80,
SeaGreen4 = 0x2e8b57,
PaleGreen1 = 0x9aff9a,
PaleGreen2 = 0x90ee90,
PaleGreen3 = 0x7ccd7c,
PaleGreen4 = 0x548b54,
SpringGreen1 = 0x00ff7f,
SpringGreen2 = 0x00ee76,
SpringGreen3 = 0x00cd66,
SpringGreen4 = 0x008b45,
Green1 = 0x00ff00,
Green2 = 0x00ee00,
Green3 = 0x00cd00,
Green4 = 0x008b00,
Chartreuse1 = 0x7fff00,
Chartreuse2 = 0x76ee00,
Chartreuse3 = 0x66cd00,
Chartreuse4 = 0x458b00,
OliveDrab1 = 0xc0ff3e,
OliveDrab2 = 0xb3ee3a,
OliveDrab3 = 0x9acd32,
OliveDrab4 = 0x698b22,
DarkOliveGreen1 = 0xcaff70,
DarkOliveGreen2 = 0xbcee68,
DarkOliveGreen3 = 0xa2cd5a,
DarkOliveGreen4 = 0x6e8b3d,
Khaki1 = 0xfff68f,
Khaki2 = 0xeee685,
Khaki3 = 0xcdc673,
Khaki4 = 0x8b864e,
LightGoldenrod1 = 0xffec8b,
LightGoldenrod2 = 0xeedc82,
LightGoldenrod3 = 0xcdbe70,
LightGoldenrod4 = 0x8b814c,
LightYellow1 = 0xffffe0,
LightYellow2 = 0xeeeed1,
LightYellow3 = 0xcdcdb4,
LightYellow4 = 0x8b8b7a,
Yellow1 = 0xffff00,
Yellow2 = 0xeeee00,
Yellow3 = 0xcdcd00,
Yellow4 = 0x8b8b00,
Gold1 = 0xffd700,
Gold2 = 0xeec900,
Gold3 = 0xcdad00,
Gold4 = 0x8b7500,
Goldenrod1 = 0xffc125,
Goldenrod2 = 0xeeb422,
Goldenrod3 = 0xcd9b1d,
Goldenrod4 = 0x8b6914,
DarkGoldenrod1 = 0xffb90f,
DarkGoldenrod2 = 0xeead0e,
DarkGoldenrod3 = 0xcd950c,
DarkGoldenrod4 = 0x8b6508,
RosyBrown1 = 0xffc1c1,
RosyBrown2 = 0xeeb4b4,
RosyBrown3 = 0xcd9b9b,
RosyBrown4 = 0x8b6969,
IndianRed1 = 0xff6a6a,
IndianRed2 = 0xee6363,
IndianRed3 = 0xcd5555,
IndianRed4 = 0x8b3a3a,
Sienna1 = 0xff8247,
Sienna2 = 0xee7942,
Sienna3 = 0xcd6839,
Sienna4 = 0x8b4726,
Burlywood1 = 0xffd39b,
Burlywood2 = 0xeec591,
Burlywood3 = 0xcdaa7d,
Burlywood4 = 0x8b7355,
Wheat1 = 0xffe7ba,
Wheat2 = 0xeed8ae,
Wheat3 = 0xcdba96,
Wheat4 = 0x8b7e66,
Tan1 = 0xffa54f,
Tan2 = 0xee9a49,
Tan3 = 0xcd853f,
Tan4 = 0x8b5a2b,
Chocolate1 = 0xff7f24,
Chocolate2 = 0xee7621,
Chocolate3 = 0xcd661d,
Chocolate4 = 0x8b4513,
Firebrick1 = 0xff3030,
Firebrick2 = 0xee2c2c,
Firebrick3 = 0xcd2626,
Firebrick4 = 0x8b1a1a,
Brown1 = 0xff4040,
Brown2 = 0xee3b3b,
Brown3 = 0xcd3333,
Brown4 = 0x8b2323,
Salmon1 = 0xff8c69,
Salmon2 = 0xee8262,
Salmon3 = 0xcd7054,
Salmon4 = 0x8b4c39,
LightSalmon1 = 0xffa07a,
LightSalmon2 = 0xee9572,
LightSalmon3 = 0xcd8162,
LightSalmon4 = 0x8b5742,
Orange1 = 0xffa500,
Orange2 = 0xee9a00,
Orange3 = 0xcd8500,
Orange4 = 0x8b5a00,
DarkOrange1 = 0xff7f00,
DarkOrange2 = 0xee7600,
DarkOrange3 = 0xcd6600,
DarkOrange4 = 0x8b4500,
Coral1 = 0xff7256,
Coral2 = 0xee6a50,
Coral3 = 0xcd5b45,
Coral4 = 0x8b3e2f,
Tomato1 = 0xff6347,
Tomato2 = 0xee5c42,
Tomato3 = 0xcd4f39,
Tomato4 = 0x8b3626,
OrangeRed1 = 0xff4500,
OrangeRed2 = 0xee4000,
OrangeRed3 = 0xcd3700,
OrangeRed4 = 0x8b2500,
Red1 = 0xff0000,
Red2 = 0xee0000,
Red3 = 0xcd0000,
Red4 = 0x8b0000,
DeepPink1 = 0xff1493,
DeepPink2 = 0xee1289,
DeepPink3 = 0xcd1076,
DeepPink4 = 0x8b0a50,
HotPink1 = 0xff6eb4,
HotPink2 = 0xee6aa7,
HotPink3 = 0xcd6090,
HotPink4 = 0x8b3a62,
Pink1 = 0xffb5c5,
Pink2 = 0xeea9b8,
Pink3 = 0xcd919e,
Pink4 = 0x8b636c,
LightPink1 = 0xffaeb9,
LightPink2 = 0xeea2ad,
LightPink3 = 0xcd8c95,
LightPink4 = 0x8b5f65,
PaleVioletRed1 = 0xff82ab,
PaleVioletRed2 = 0xee799f,
PaleVioletRed3 = 0xcd6889,
PaleVioletRed4 = 0x8b475d,
Maroon1 = 0xff34b3,
Maroon2 = 0xee30a7,
Maroon3 = 0xcd2990,
Maroon4 = 0x8b1c62,
VioletRed1 = 0xff3e96,
VioletRed2 = 0xee3a8c,
VioletRed3 = 0xcd3278,
VioletRed4 = 0x8b2252,
Magenta1 = 0xff00ff,
Magenta2 = 0xee00ee,
Magenta3 = 0xcd00cd,
Magenta4 = 0x8b008b,
Orchid1 = 0xff83fa,
Orchid2 = 0xee7ae9,
Orchid3 = 0xcd69c9,
Orchid4 = 0x8b4789,
Plum1 = 0xffbbff,
Plum2 = 0xeeaeee,
Plum3 = 0xcd96cd,
Plum4 = 0x8b668b,
MediumOrchid1 = 0xe066ff,
MediumOrchid2 = 0xd15fee,
MediumOrchid3 = 0xb452cd,
MediumOrchid4 = 0x7a378b,
DarkOrchid1 = 0xbf3eff,
DarkOrchid2 = 0xb23aee,
DarkOrchid3 = 0x9a32cd,
DarkOrchid4 = 0x68228b,
Purple1 = 0x9b30ff,
Purple2 = 0x912cee,
Purple3 = 0x7d26cd,
Purple4 = 0x551a8b,
MediumPurple1 = 0xab82ff,
MediumPurple2 = 0x9f79ee,
MediumPurple3 = 0x8968cd,
MediumPurple4 = 0x5d478b,
Thistle1 = 0xffe1ff,
Thistle2 = 0xeed2ee,
Thistle3 = 0xcdb5cd,
Thistle4 = 0x8b7b8b,
Gray0 = 0x000000,
Grey0 = 0x000000,
Gray1 = 0x030303,
Grey1 = 0x030303,
Gray2 = 0x050505,
Grey2 = 0x050505,
Gray3 = 0x080808,
Grey3 = 0x080808,
Gray4 = 0x0a0a0a,
Grey4 = 0x0a0a0a,
Gray5 = 0x0d0d0d,
Grey5 = 0x0d0d0d,
Gray6 = 0x0f0f0f,
Grey6 = 0x0f0f0f,
Gray7 = 0x121212,
Grey7 = 0x121212,
Gray8 = 0x141414,
Grey8 = 0x141414,
Gray9 = 0x171717,
Grey9 = 0x171717,
Gray10 = 0x1a1a1a,
Grey10 = 0x1a1a1a,
Gray11 = 0x1c1c1c,
Grey11 = 0x1c1c1c,
Gray12 = 0x1f1f1f,
Grey12 = 0x1f1f1f,
Gray13 = 0x212121,
Grey13 = 0x212121,
Gray14 = 0x242424,
Grey14 = 0x242424,
Gray15 = 0x262626,
Grey15 = 0x262626,
Gray16 = 0x292929,
Grey16 = 0x292929,
Gray17 = 0x2b2b2b,
Grey17 = 0x2b2b2b,
Gray18 = 0x2e2e2e,
Grey18 = 0x2e2e2e,
Gray19 = 0x303030,
Grey19 = 0x303030,
Gray20 = 0x333333,
Grey20 = 0x333333,
Gray21 = 0x363636,
Grey21 = 0x363636,
Gray22 = 0x383838,
Grey22 = 0x383838,
Gray23 = 0x3b3b3b,
Grey23 = 0x3b3b3b,
Gray24 = 0x3d3d3d,
Grey24 = 0x3d3d3d,
Gray25 = 0x404040,
Grey25 = 0x404040,
Gray26 = 0x424242,
Grey26 = 0x424242,
Gray27 = 0x454545,
Grey27 = 0x454545,
Gray28 = 0x474747,
Grey28 = 0x474747,
Gray29 = 0x4a4a4a,
Grey29 = 0x4a4a4a,
Gray30 = 0x4d4d4d,
Grey30 = 0x4d4d4d,
Gray31 = 0x4f4f4f,
Grey31 = 0x4f4f4f,
Gray32 = 0x525252,
Grey32 = 0x525252,
Gray33 = 0x545454,
Grey33 = 0x545454,
Gray34 = 0x575757,
Grey34 = 0x575757,
Gray35 = 0x595959,
Grey35 = 0x595959,
Gray36 = 0x5c5c5c,
Grey36 = 0x5c5c5c,
Gray37 = 0x5e5e5e,
Grey37 = 0x5e5e5e,
Gray38 = 0x616161,
Grey38 = 0x616161,
Gray39 = 0x636363,
Grey39 = 0x636363,
Gray40 = 0x666666,
Grey40 = 0x666666,
Gray41 = 0x696969,
Grey41 = 0x696969,
Gray42 = 0x6b6b6b,
Grey42 = 0x6b6b6b,
Gray43 = 0x6e6e6e,
Grey43 = 0x6e6e6e,
Gray44 = 0x707070,
Grey44 = 0x707070,
Gray45 = 0x737373,
Grey45 = 0x737373,
Gray46 = 0x757575,
Grey46 = 0x757575,
Gray47 = 0x787878,
Grey47 = 0x787878,
Gray48 = 0x7a7a7a,
Grey48 = 0x7a7a7a,
Gray49 = 0x7d7d7d,
Grey49 = 0x7d7d7d,
Gray50 = 0x7f7f7f,
Grey50 = 0x7f7f7f,
Gray51 = 0x828282,
Grey51 = 0x828282,
Gray52 = 0x858585,
Grey52 = 0x858585,
Gray53 = 0x878787,
Grey53 = 0x878787,
Gray54 = 0x8a8a8a,
Grey54 = 0x8a8a8a,
Gray55 = 0x8c8c8c,
Grey55 = 0x8c8c8c,
Gray56 = 0x8f8f8f,
Grey56 = 0x8f8f8f,
Gray57 = 0x919191,
Grey57 = 0x919191,
Gray58 = 0x949494,
Grey58 = 0x949494,
Gray59 = 0x969696,
Grey59 = 0x969696,
Gray60 = 0x999999,
Grey60 = 0x999999,
Gray61 = 0x9c9c9c,
Grey61 = 0x9c9c9c,
Gray62 = 0x9e9e9e,
Grey62 = 0x9e9e9e,
Gray63 = 0xa1a1a1,
Grey63 = 0xa1a1a1,
Gray64 = 0xa3a3a3,
Grey64 = 0xa3a3a3,
Gray65 = 0xa6a6a6,
Grey65 = 0xa6a6a6,
Gray66 = 0xa8a8a8,
Grey66 = 0xa8a8a8,
Gray67 = 0xababab,
Grey67 = 0xababab,
Gray68 = 0xadadad,
Grey68 = 0xadadad,
Gray69 = 0xb0b0b0,
Grey69 = 0xb0b0b0,
Gray70 = 0xb3b3b3,
Grey70 = 0xb3b3b3,
Gray71 = 0xb5b5b5,
Grey71 = 0xb5b5b5,
Gray72 = 0xb8b8b8,
Grey72 = 0xb8b8b8,
Gray73 = 0xbababa,
Grey73 = 0xbababa,
Gray74 = 0xbdbdbd,
Grey74 = 0xbdbdbd,
Gray75 = 0xbfbfbf,
Grey75 = 0xbfbfbf,
Gray76 = 0xc2c2c2,
Grey76 = 0xc2c2c2,
Gray77 = 0xc4c4c4,
Grey77 = 0xc4c4c4,
Gray78 = 0xc7c7c7,
Grey78 = 0xc7c7c7,
Gray79 = 0xc9c9c9,
Grey79 = 0xc9c9c9,
Gray80 = 0xcccccc,
Grey80 = 0xcccccc,
Gray81 = 0xcfcfcf,
Grey81 = 0xcfcfcf,
Gray82 = 0xd1d1d1,
Grey82 = 0xd1d1d1,
Gray83 = 0xd4d4d4,
Grey83 = 0xd4d4d4,
Gray84 = 0xd6d6d6,
Grey84 = 0xd6d6d6,
Gray85 = 0xd9d9d9,
Grey85 = 0xd9d9d9,
Gray86 = 0xdbdbdb,
Grey86 = 0xdbdbdb,
Gray87 = 0xdedede,
Grey87 = 0xdedede,
Gray88 = 0xe0e0e0,
Grey88 = 0xe0e0e0,
Gray89 = 0xe3e3e3,
Grey89 = 0xe3e3e3,
Gray90 = 0xe5e5e5,
Grey90 = 0xe5e5e5,
Gray91 = 0xe8e8e8,
Grey91 = 0xe8e8e8,
Gray92 = 0xebebeb,
Grey92 = 0xebebeb,
Gray93 = 0xededed,
Grey93 = 0xededed,
Gray94 = 0xf0f0f0,
Grey94 = 0xf0f0f0,
Gray95 = 0xf2f2f2,
Grey95 = 0xf2f2f2,
Gray96 = 0xf5f5f5,
Grey96 = 0xf5f5f5,
Gray97 = 0xf7f7f7,
Grey97 = 0xf7f7f7,
Gray98 = 0xfafafa,
Grey98 = 0xfafafa,
Gray99 = 0xfcfcfc,
Grey99 = 0xfcfcfc,
Gray100 = 0xffffff,
Grey100 = 0xffffff,
DarkGrey = 0xa9a9a9,
DarkGray = 0xa9a9a9,
DarkBlue = 0x00008b,
DarkCyan = 0x008b8b,
DarkMagenta = 0x8b008b,
DarkRed = 0x8b0000,
LightGreen = 0x90ee90,
Crimson = 0xdc143c,
Indigo = 0x4b0082,
Olive = 0x808000,
RebeccaPurple = 0x663399,
Silver = 0xc0c0c0,
Teal = 0x008080,
};
};
}
#endif

View File

@@ -0,0 +1,20 @@
#ifndef __TRACYFORCEINLINE_HPP__
#define __TRACYFORCEINLINE_HPP__
#if defined(__GNUC__)
# define tracy_force_inline __attribute__((always_inline)) inline
#elif defined(_MSC_VER)
# define tracy_force_inline __forceinline
#else
# define tracy_force_inline inline
#endif
#if defined(__GNUC__)
# define tracy_no_inline __attribute__((noinline))
#elif defined(_MSC_VER)
# define tracy_no_inline __declspec(noinline)
#else
# define tracy_no_inline
#endif
#endif

View File

@@ -0,0 +1,24 @@
#ifndef __TRACYMUTEX_HPP__
#define __TRACYMUTEX_HPP__
#if defined _MSC_VER
# include <shared_mutex>
namespace tracy
{
using TracyMutex = std::shared_mutex;
}
#else
#include <mutex>
namespace tracy
{
using TracyMutex = std::mutex;
}
#endif
#endif

View File

@@ -0,0 +1,169 @@
#ifndef __TRACYPROTOCOL_HPP__
#define __TRACYPROTOCOL_HPP__
#include <limits>
#include <stdint.h>
namespace tracy
{
constexpr unsigned Lz4CompressBound( unsigned isize ) { return isize + ( isize / 255 ) + 16; }
enum : uint32_t { ProtocolVersion = 63 };
enum : uint16_t { BroadcastVersion = 3 };
using lz4sz_t = uint32_t;
enum { TargetFrameSize = 256 * 1024 };
enum { LZ4Size = Lz4CompressBound( TargetFrameSize ) };
static_assert( LZ4Size <= std::numeric_limits<lz4sz_t>::max(), "LZ4Size greater than lz4sz_t" );
static_assert( TargetFrameSize * 2 >= 64 * 1024, "Not enough space for LZ4 stream buffer" );
enum { HandshakeShibbolethSize = 8 };
static const char HandshakeShibboleth[HandshakeShibbolethSize] = { 'T', 'r', 'a', 'c', 'y', 'P', 'r', 'f' };
enum HandshakeStatus : uint8_t
{
HandshakePending,
HandshakeWelcome,
HandshakeProtocolMismatch,
HandshakeNotAvailable,
HandshakeDropped
};
enum { WelcomeMessageProgramNameSize = 64 };
enum { WelcomeMessageHostInfoSize = 1024 };
#pragma pack( push, 1 )
// Must increase left query space after handling!
enum ServerQuery : uint8_t
{
ServerQueryTerminate,
ServerQueryString,
ServerQueryThreadString,
ServerQuerySourceLocation,
ServerQueryPlotName,
ServerQueryFrameName,
ServerQueryParameter,
ServerQueryFiberName,
// Items above are high priority. Split order must be preserved. See IsQueryPrio().
ServerQueryDisconnect,
ServerQueryCallstackFrame,
ServerQueryExternalName,
ServerQuerySymbol,
ServerQuerySymbolCode,
ServerQuerySourceCode,
ServerQueryDataTransfer,
ServerQueryDataTransferPart
};
struct ServerQueryPacket
{
ServerQuery type;
uint64_t ptr;
uint32_t extra;
};
enum { ServerQueryPacketSize = sizeof( ServerQueryPacket ) };
enum CpuArchitecture : uint8_t
{
CpuArchUnknown,
CpuArchX86,
CpuArchX64,
CpuArchArm32,
CpuArchArm64
};
struct WelcomeFlag
{
enum _t : uint8_t
{
OnDemand = 1 << 0,
IsApple = 1 << 1,
CodeTransfer = 1 << 2,
CombineSamples = 1 << 3,
IdentifySamples = 1 << 4,
};
};
struct WelcomeMessage
{
double timerMul;
int64_t initBegin;
int64_t initEnd;
uint64_t delay;
uint64_t resolution;
uint64_t epoch;
uint64_t exectime;
uint64_t pid;
int64_t samplingPeriod;
uint8_t flags;
uint8_t cpuArch;
char cpuManufacturer[12];
uint32_t cpuId;
char programName[WelcomeMessageProgramNameSize];
char hostInfo[WelcomeMessageHostInfoSize];
};
enum { WelcomeMessageSize = sizeof( WelcomeMessage ) };
struct OnDemandPayloadMessage
{
uint64_t frames;
uint64_t currentTime;
};
enum { OnDemandPayloadMessageSize = sizeof( OnDemandPayloadMessage ) };
struct BroadcastMessage
{
uint16_t broadcastVersion;
uint16_t listenPort;
uint32_t protocolVersion;
uint64_t pid;
int32_t activeTime; // in seconds
char programName[WelcomeMessageProgramNameSize];
};
struct BroadcastMessage_v2
{
uint16_t broadcastVersion;
uint16_t listenPort;
uint32_t protocolVersion;
int32_t activeTime;
char programName[WelcomeMessageProgramNameSize];
};
struct BroadcastMessage_v1
{
uint32_t broadcastVersion;
uint32_t protocolVersion;
uint32_t listenPort;
uint32_t activeTime;
char programName[WelcomeMessageProgramNameSize];
};
struct BroadcastMessage_v0
{
uint32_t broadcastVersion;
uint32_t protocolVersion;
uint32_t activeTime;
char programName[WelcomeMessageProgramNameSize];
};
enum { BroadcastMessageSize = sizeof( BroadcastMessage ) };
enum { BroadcastMessageSize_v2 = sizeof( BroadcastMessage_v2 ) };
enum { BroadcastMessageSize_v1 = sizeof( BroadcastMessage_v1 ) };
enum { BroadcastMessageSize_v0 = sizeof( BroadcastMessage_v0 ) };
#pragma pack( pop )
}
#endif

View File

@@ -0,0 +1,874 @@
#ifndef __TRACYQUEUE_HPP__
#define __TRACYQUEUE_HPP__
#include <stddef.h>
#include <stdint.h>
namespace tracy
{
enum class QueueType : uint8_t
{
ZoneText,
ZoneName,
Message,
MessageColor,
MessageCallstack,
MessageColorCallstack,
MessageAppInfo,
ZoneBeginAllocSrcLoc,
ZoneBeginAllocSrcLocCallstack,
CallstackSerial,
Callstack,
CallstackAlloc,
CallstackSample,
CallstackSampleContextSwitch,
FrameImage,
ZoneBegin,
ZoneBeginCallstack,
ZoneEnd,
LockWait,
LockObtain,
LockRelease,
LockSharedWait,
LockSharedObtain,
LockSharedRelease,
LockName,
MemAlloc,
MemAllocNamed,
MemFree,
MemFreeNamed,
MemAllocCallstack,
MemAllocCallstackNamed,
MemFreeCallstack,
MemFreeCallstackNamed,
GpuZoneBegin,
GpuZoneBeginCallstack,
GpuZoneBeginAllocSrcLoc,
GpuZoneBeginAllocSrcLocCallstack,
GpuZoneEnd,
GpuZoneBeginSerial,
GpuZoneBeginCallstackSerial,
GpuZoneBeginAllocSrcLocSerial,
GpuZoneBeginAllocSrcLocCallstackSerial,
GpuZoneEndSerial,
PlotDataInt,
PlotDataFloat,
PlotDataDouble,
ContextSwitch,
ThreadWakeup,
GpuTime,
GpuContextName,
CallstackFrameSize,
SymbolInformation,
ExternalNameMetadata,
SymbolCodeMetadata,
SourceCodeMetadata,
FiberEnter,
FiberLeave,
Terminate,
KeepAlive,
ThreadContext,
GpuCalibration,
Crash,
CrashReport,
ZoneValidation,
ZoneColor,
ZoneValue,
FrameMarkMsg,
FrameMarkMsgStart,
FrameMarkMsgEnd,
FrameVsync,
SourceLocation,
LockAnnounce,
LockTerminate,
LockMark,
MessageLiteral,
MessageLiteralColor,
MessageLiteralCallstack,
MessageLiteralColorCallstack,
GpuNewContext,
CallstackFrame,
SysTimeReport,
TidToPid,
HwSampleCpuCycle,
HwSampleInstructionRetired,
HwSampleCacheReference,
HwSampleCacheMiss,
HwSampleBranchRetired,
HwSampleBranchMiss,
PlotConfig,
ParamSetup,
AckServerQueryNoop,
AckSourceCodeNotAvailable,
AckSymbolCodeNotAvailable,
CpuTopology,
SingleStringData,
SecondStringData,
MemNamePayload,
StringData,
ThreadName,
PlotName,
SourceLocationPayload,
CallstackPayload,
CallstackAllocPayload,
FrameName,
FrameImageData,
ExternalName,
ExternalThreadName,
SymbolCode,
SourceCode,
FiberName,
NUM_TYPES
};
#pragma pack( push, 1 )
struct QueueThreadContext
{
uint32_t thread;
};
struct QueueZoneBeginLean
{
int64_t time;
};
struct QueueZoneBegin : public QueueZoneBeginLean
{
uint64_t srcloc; // ptr
};
struct QueueZoneBeginThread : public QueueZoneBegin
{
uint32_t thread;
};
struct QueueZoneEnd
{
int64_t time;
};
struct QueueZoneEndThread : public QueueZoneEnd
{
uint32_t thread;
};
struct QueueZoneValidation
{
uint32_t id;
};
struct QueueZoneValidationThread : public QueueZoneValidation
{
uint32_t thread;
};
struct QueueZoneColor
{
uint8_t b;
uint8_t g;
uint8_t r;
};
struct QueueZoneColorThread : public QueueZoneColor
{
uint32_t thread;
};
struct QueueZoneValue
{
uint64_t value;
};
struct QueueZoneValueThread : public QueueZoneValue
{
uint32_t thread;
};
struct QueueStringTransfer
{
uint64_t ptr;
};
struct QueueFrameMark
{
int64_t time;
uint64_t name; // ptr
};
struct QueueFrameVsync
{
int64_t time;
uint32_t id;
};
struct QueueFrameImage
{
uint32_t frame;
uint16_t w;
uint16_t h;
uint8_t flip;
};
struct QueueFrameImageFat : public QueueFrameImage
{
uint64_t image; // ptr
};
struct QueueSourceLocation
{
uint64_t name;
uint64_t function; // ptr
uint64_t file; // ptr
uint32_t line;
uint8_t b;
uint8_t g;
uint8_t r;
};
struct QueueZoneTextFat
{
uint64_t text; // ptr
uint16_t size;
};
struct QueueZoneTextFatThread : public QueueZoneTextFat
{
uint32_t thread;
};
enum class LockType : uint8_t
{
Lockable,
SharedLockable
};
struct QueueLockAnnounce
{
uint32_t id;
int64_t time;
uint64_t lckloc; // ptr
LockType type;
};
struct QueueFiberEnter
{
int64_t time;
uint64_t fiber; // ptr
uint32_t thread;
};
struct QueueFiberLeave
{
int64_t time;
uint32_t thread;
};
struct QueueLockTerminate
{
uint32_t id;
int64_t time;
};
struct QueueLockWait
{
uint32_t thread;
uint32_t id;
int64_t time;
};
struct QueueLockObtain
{
uint32_t thread;
uint32_t id;
int64_t time;
};
struct QueueLockRelease
{
uint32_t id;
int64_t time;
};
struct QueueLockReleaseShared : public QueueLockRelease
{
uint32_t thread;
};
struct QueueLockMark
{
uint32_t thread;
uint32_t id;
uint64_t srcloc; // ptr
};
struct QueueLockName
{
uint32_t id;
};
struct QueueLockNameFat : public QueueLockName
{
uint64_t name; // ptr
uint16_t size;
};
struct QueuePlotDataBase
{
uint64_t name; // ptr
int64_t time;
};
struct QueuePlotDataInt : public QueuePlotDataBase
{
int64_t val;
};
struct QueuePlotDataFloat : public QueuePlotDataBase
{
float val;
};
struct QueuePlotDataDouble : public QueuePlotDataBase
{
double val;
};
struct QueueMessage
{
int64_t time;
};
struct QueueMessageColor : public QueueMessage
{
uint8_t b;
uint8_t g;
uint8_t r;
};
struct QueueMessageLiteral : public QueueMessage
{
uint64_t text; // ptr
};
struct QueueMessageLiteralThread : public QueueMessageLiteral
{
uint32_t thread;
};
struct QueueMessageColorLiteral : public QueueMessageColor
{
uint64_t text; // ptr
};
struct QueueMessageColorLiteralThread : public QueueMessageColorLiteral
{
uint32_t thread;
};
struct QueueMessageFat : public QueueMessage
{
uint64_t text; // ptr
uint16_t size;
};
struct QueueMessageFatThread : public QueueMessageFat
{
uint32_t thread;
};
struct QueueMessageColorFat : public QueueMessageColor
{
uint64_t text; // ptr
uint16_t size;
};
struct QueueMessageColorFatThread : public QueueMessageColorFat
{
uint32_t thread;
};
// Don't change order, only add new entries at the end, this is also used on trace dumps!
enum class GpuContextType : uint8_t
{
Invalid,
OpenGl,
Vulkan,
OpenCL,
Direct3D12,
Direct3D11
};
enum GpuContextFlags : uint8_t
{
GpuContextCalibration = 1 << 0
};
struct QueueGpuNewContext
{
int64_t cpuTime;
int64_t gpuTime;
uint32_t thread;
float period;
uint8_t context;
GpuContextFlags flags;
GpuContextType type;
};
struct QueueGpuZoneBeginLean
{
int64_t cpuTime;
uint32_t thread;
uint16_t queryId;
uint8_t context;
};
struct QueueGpuZoneBegin : public QueueGpuZoneBeginLean
{
uint64_t srcloc;
};
struct QueueGpuZoneEnd
{
int64_t cpuTime;
uint32_t thread;
uint16_t queryId;
uint8_t context;
};
struct QueueGpuTime
{
int64_t gpuTime;
uint16_t queryId;
uint8_t context;
};
struct QueueGpuCalibration
{
int64_t gpuTime;
int64_t cpuTime;
int64_t cpuDelta;
uint8_t context;
};
struct QueueGpuContextName
{
uint8_t context;
};
struct QueueGpuContextNameFat : public QueueGpuContextName
{
uint64_t ptr;
uint16_t size;
};
struct QueueMemNamePayload
{
uint64_t name;
};
struct QueueMemAlloc
{
int64_t time;
uint32_t thread;
uint64_t ptr;
char size[6];
};
struct QueueMemFree
{
int64_t time;
uint32_t thread;
uint64_t ptr;
};
struct QueueCallstackFat
{
uint64_t ptr;
};
struct QueueCallstackFatThread : public QueueCallstackFat
{
uint32_t thread;
};
struct QueueCallstackAllocFat
{
uint64_t ptr;
uint64_t nativePtr;
};
struct QueueCallstackAllocFatThread : public QueueCallstackAllocFat
{
uint32_t thread;
};
struct QueueCallstackSample
{
int64_t time;
uint32_t thread;
};
struct QueueCallstackSampleFat : public QueueCallstackSample
{
uint64_t ptr;
};
struct QueueCallstackFrameSize
{
uint64_t ptr;
uint8_t size;
};
struct QueueCallstackFrameSizeFat : public QueueCallstackFrameSize
{
uint64_t data;
uint64_t imageName;
};
struct QueueCallstackFrame
{
uint32_t line;
uint64_t symAddr;
uint32_t symLen;
};
struct QueueSymbolInformation
{
uint32_t line;
uint64_t symAddr;
};
struct QueueSymbolInformationFat : public QueueSymbolInformation
{
uint64_t fileString;
uint8_t needFree;
};
struct QueueCrashReport
{
int64_t time;
uint64_t text; // ptr
};
struct QueueCrashReportThread
{
uint32_t thread;
};
struct QueueSysTime
{
int64_t time;
float sysTime;
};
struct QueueContextSwitch
{
int64_t time;
uint32_t oldThread;
uint32_t newThread;
uint8_t cpu;
uint8_t reason;
uint8_t state;
};
struct QueueThreadWakeup
{
int64_t time;
uint32_t thread;
};
struct QueueTidToPid
{
uint64_t tid;
uint64_t pid;
};
struct QueueHwSample
{
uint64_t ip;
int64_t time;
};
enum class PlotFormatType : uint8_t
{
Number,
Memory,
Percentage
};
struct QueuePlotConfig
{
uint64_t name; // ptr
uint8_t type;
uint8_t step;
uint8_t fill;
uint32_t color;
};
struct QueueParamSetup
{
uint32_t idx;
uint64_t name; // ptr
uint8_t isBool;
int32_t val;
};
struct QueueSourceCodeNotAvailable
{
uint32_t id;
};
struct QueueCpuTopology
{
uint32_t package;
uint32_t core;
uint32_t thread;
};
struct QueueExternalNameMetadata
{
uint64_t thread;
uint64_t name;
uint64_t threadName;
};
struct QueueSymbolCodeMetadata
{
uint64_t symbol;
uint64_t ptr;
uint32_t size;
};
struct QueueSourceCodeMetadata
{
uint64_t ptr;
uint32_t size;
uint32_t id;
};
struct QueueHeader
{
union
{
QueueType type;
uint8_t idx;
};
};
struct QueueItem
{
QueueHeader hdr;
union
{
QueueThreadContext threadCtx;
QueueZoneBegin zoneBegin;
QueueZoneBeginLean zoneBeginLean;
QueueZoneBeginThread zoneBeginThread;
QueueZoneEnd zoneEnd;
QueueZoneEndThread zoneEndThread;
QueueZoneValidation zoneValidation;
QueueZoneValidationThread zoneValidationThread;
QueueZoneColor zoneColor;
QueueZoneColorThread zoneColorThread;
QueueZoneValue zoneValue;
QueueZoneValueThread zoneValueThread;
QueueStringTransfer stringTransfer;
QueueFrameMark frameMark;
QueueFrameVsync frameVsync;
QueueFrameImage frameImage;
QueueFrameImageFat frameImageFat;
QueueSourceLocation srcloc;
QueueZoneTextFat zoneTextFat;
QueueZoneTextFatThread zoneTextFatThread;
QueueLockAnnounce lockAnnounce;
QueueLockTerminate lockTerminate;
QueueLockWait lockWait;
QueueLockObtain lockObtain;
QueueLockRelease lockRelease;
QueueLockReleaseShared lockReleaseShared;
QueueLockMark lockMark;
QueueLockName lockName;
QueueLockNameFat lockNameFat;
QueuePlotDataInt plotDataInt;
QueuePlotDataFloat plotDataFloat;
QueuePlotDataDouble plotDataDouble;
QueueMessage message;
QueueMessageColor messageColor;
QueueMessageLiteral messageLiteral;
QueueMessageLiteralThread messageLiteralThread;
QueueMessageColorLiteral messageColorLiteral;
QueueMessageColorLiteralThread messageColorLiteralThread;
QueueMessageFat messageFat;
QueueMessageFatThread messageFatThread;
QueueMessageColorFat messageColorFat;
QueueMessageColorFatThread messageColorFatThread;
QueueGpuNewContext gpuNewContext;
QueueGpuZoneBegin gpuZoneBegin;
QueueGpuZoneBeginLean gpuZoneBeginLean;
QueueGpuZoneEnd gpuZoneEnd;
QueueGpuTime gpuTime;
QueueGpuCalibration gpuCalibration;
QueueGpuContextName gpuContextName;
QueueGpuContextNameFat gpuContextNameFat;
QueueMemAlloc memAlloc;
QueueMemFree memFree;
QueueMemNamePayload memName;
QueueCallstackFat callstackFat;
QueueCallstackFatThread callstackFatThread;
QueueCallstackAllocFat callstackAllocFat;
QueueCallstackAllocFatThread callstackAllocFatThread;
QueueCallstackSample callstackSample;
QueueCallstackSampleFat callstackSampleFat;
QueueCallstackFrameSize callstackFrameSize;
QueueCallstackFrameSizeFat callstackFrameSizeFat;
QueueCallstackFrame callstackFrame;
QueueSymbolInformation symbolInformation;
QueueSymbolInformationFat symbolInformationFat;
QueueCrashReport crashReport;
QueueCrashReportThread crashReportThread;
QueueSysTime sysTime;
QueueContextSwitch contextSwitch;
QueueThreadWakeup threadWakeup;
QueueTidToPid tidToPid;
QueueHwSample hwSample;
QueuePlotConfig plotConfig;
QueueParamSetup paramSetup;
QueueCpuTopology cpuTopology;
QueueExternalNameMetadata externalNameMetadata;
QueueSymbolCodeMetadata symbolCodeMetadata;
QueueSourceCodeMetadata sourceCodeMetadata;
QueueSourceCodeNotAvailable sourceCodeNotAvailable;
QueueFiberEnter fiberEnter;
QueueFiberLeave fiberLeave;
};
};
#pragma pack( pop )
enum { QueueItemSize = sizeof( QueueItem ) };
static constexpr size_t QueueDataSize[] = {
sizeof( QueueHeader ), // zone text
sizeof( QueueHeader ), // zone name
sizeof( QueueHeader ) + sizeof( QueueMessage ),
sizeof( QueueHeader ) + sizeof( QueueMessageColor ),
sizeof( QueueHeader ) + sizeof( QueueMessage ), // callstack
sizeof( QueueHeader ) + sizeof( QueueMessageColor ), // callstack
sizeof( QueueHeader ) + sizeof( QueueMessage ), // app info
sizeof( QueueHeader ) + sizeof( QueueZoneBeginLean ), // allocated source location
sizeof( QueueHeader ) + sizeof( QueueZoneBeginLean ), // allocated source location, callstack
sizeof( QueueHeader ), // callstack memory
sizeof( QueueHeader ), // callstack
sizeof( QueueHeader ), // callstack alloc
sizeof( QueueHeader ) + sizeof( QueueCallstackSample ),
sizeof( QueueHeader ) + sizeof( QueueCallstackSample ), // context switch
sizeof( QueueHeader ) + sizeof( QueueFrameImage ),
sizeof( QueueHeader ) + sizeof( QueueZoneBegin ),
sizeof( QueueHeader ) + sizeof( QueueZoneBegin ), // callstack
sizeof( QueueHeader ) + sizeof( QueueZoneEnd ),
sizeof( QueueHeader ) + sizeof( QueueLockWait ),
sizeof( QueueHeader ) + sizeof( QueueLockObtain ),
sizeof( QueueHeader ) + sizeof( QueueLockRelease ),
sizeof( QueueHeader ) + sizeof( QueueLockWait ), // shared
sizeof( QueueHeader ) + sizeof( QueueLockObtain ), // shared
sizeof( QueueHeader ) + sizeof( QueueLockReleaseShared ),
sizeof( QueueHeader ) + sizeof( QueueLockName ),
sizeof( QueueHeader ) + sizeof( QueueMemAlloc ),
sizeof( QueueHeader ) + sizeof( QueueMemAlloc ), // named
sizeof( QueueHeader ) + sizeof( QueueMemFree ),
sizeof( QueueHeader ) + sizeof( QueueMemFree ), // named
sizeof( QueueHeader ) + sizeof( QueueMemAlloc ), // callstack
sizeof( QueueHeader ) + sizeof( QueueMemAlloc ), // callstack, named
sizeof( QueueHeader ) + sizeof( QueueMemFree ), // callstack
sizeof( QueueHeader ) + sizeof( QueueMemFree ), // callstack, named
sizeof( QueueHeader ) + sizeof( QueueGpuZoneBegin ),
sizeof( QueueHeader ) + sizeof( QueueGpuZoneBegin ), // callstack
sizeof( QueueHeader ) + sizeof( QueueGpuZoneBeginLean ),// allocated source location
sizeof( QueueHeader ) + sizeof( QueueGpuZoneBeginLean ),// allocated source location, callstack
sizeof( QueueHeader ) + sizeof( QueueGpuZoneEnd ),
sizeof( QueueHeader ) + sizeof( QueueGpuZoneBegin ), // serial
sizeof( QueueHeader ) + sizeof( QueueGpuZoneBegin ), // serial, callstack
sizeof( QueueHeader ) + sizeof( QueueGpuZoneBeginLean ),// serial, allocated source location
sizeof( QueueHeader ) + sizeof( QueueGpuZoneBeginLean ),// serial, allocated source location, callstack
sizeof( QueueHeader ) + sizeof( QueueGpuZoneEnd ), // serial
sizeof( QueueHeader ) + sizeof( QueuePlotDataInt ),
sizeof( QueueHeader ) + sizeof( QueuePlotDataFloat ),
sizeof( QueueHeader ) + sizeof( QueuePlotDataDouble ),
sizeof( QueueHeader ) + sizeof( QueueContextSwitch ),
sizeof( QueueHeader ) + sizeof( QueueThreadWakeup ),
sizeof( QueueHeader ) + sizeof( QueueGpuTime ),
sizeof( QueueHeader ) + sizeof( QueueGpuContextName ),
sizeof( QueueHeader ) + sizeof( QueueCallstackFrameSize ),
sizeof( QueueHeader ) + sizeof( QueueSymbolInformation ),
sizeof( QueueHeader ), // ExternalNameMetadata - not for wire transfer
sizeof( QueueHeader ), // SymbolCodeMetadata - not for wire transfer
sizeof( QueueHeader ), // SourceCodeMetadata - not for wire transfer
sizeof( QueueHeader ) + sizeof( QueueFiberEnter ),
sizeof( QueueHeader ) + sizeof( QueueFiberLeave ),
// above items must be first
sizeof( QueueHeader ), // terminate
sizeof( QueueHeader ), // keep alive
sizeof( QueueHeader ) + sizeof( QueueThreadContext ),
sizeof( QueueHeader ) + sizeof( QueueGpuCalibration ),
sizeof( QueueHeader ), // crash
sizeof( QueueHeader ) + sizeof( QueueCrashReport ),
sizeof( QueueHeader ) + sizeof( QueueZoneValidation ),
sizeof( QueueHeader ) + sizeof( QueueZoneColor ),
sizeof( QueueHeader ) + sizeof( QueueZoneValue ),
sizeof( QueueHeader ) + sizeof( QueueFrameMark ), // continuous frames
sizeof( QueueHeader ) + sizeof( QueueFrameMark ), // start
sizeof( QueueHeader ) + sizeof( QueueFrameMark ), // end
sizeof( QueueHeader ) + sizeof( QueueFrameVsync ),
sizeof( QueueHeader ) + sizeof( QueueSourceLocation ),
sizeof( QueueHeader ) + sizeof( QueueLockAnnounce ),
sizeof( QueueHeader ) + sizeof( QueueLockTerminate ),
sizeof( QueueHeader ) + sizeof( QueueLockMark ),
sizeof( QueueHeader ) + sizeof( QueueMessageLiteral ),
sizeof( QueueHeader ) + sizeof( QueueMessageColorLiteral ),
sizeof( QueueHeader ) + sizeof( QueueMessageLiteral ), // callstack
sizeof( QueueHeader ) + sizeof( QueueMessageColorLiteral ), // callstack
sizeof( QueueHeader ) + sizeof( QueueGpuNewContext ),
sizeof( QueueHeader ) + sizeof( QueueCallstackFrame ),
sizeof( QueueHeader ) + sizeof( QueueSysTime ),
sizeof( QueueHeader ) + sizeof( QueueTidToPid ),
sizeof( QueueHeader ) + sizeof( QueueHwSample ), // cpu cycle
sizeof( QueueHeader ) + sizeof( QueueHwSample ), // instruction retired
sizeof( QueueHeader ) + sizeof( QueueHwSample ), // cache reference
sizeof( QueueHeader ) + sizeof( QueueHwSample ), // cache miss
sizeof( QueueHeader ) + sizeof( QueueHwSample ), // branch retired
sizeof( QueueHeader ) + sizeof( QueueHwSample ), // branch miss
sizeof( QueueHeader ) + sizeof( QueuePlotConfig ),
sizeof( QueueHeader ) + sizeof( QueueParamSetup ),
sizeof( QueueHeader ), // server query acknowledgement
sizeof( QueueHeader ) + sizeof( QueueSourceCodeNotAvailable ),
sizeof( QueueHeader ), // symbol code not available
sizeof( QueueHeader ) + sizeof( QueueCpuTopology ),
sizeof( QueueHeader ), // single string data
sizeof( QueueHeader ), // second string data
sizeof( QueueHeader ) + sizeof( QueueMemNamePayload ),
// keep all QueueStringTransfer below
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // string data
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // thread name
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // plot name
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // allocated source location payload
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // callstack payload
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // callstack alloc payload
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // frame name
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // frame image data
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // external name
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // external thread name
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // symbol code
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // source code
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // fiber name
};
static_assert( QueueItemSize == 32, "Queue item size not 32 bytes" );
static_assert( sizeof( QueueDataSize ) / sizeof( size_t ) == (uint8_t)QueueType::NUM_TYPES, "QueueDataSize mismatch" );
static_assert( sizeof( void* ) <= sizeof( uint64_t ), "Pointer size > 8 bytes" );
static_assert( sizeof( void* ) == sizeof( uintptr_t ), "Pointer size != uintptr_t" );
}
#endif

View File

@@ -0,0 +1,749 @@
#include <assert.h>
#include <inttypes.h>
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include "TracyAlloc.hpp"
#include "TracySocket.hpp"
#include "TracySystem.hpp"
#ifdef _WIN32
# ifndef NOMINMAX
# define NOMINMAX
# endif
# include <winsock2.h>
# include <ws2tcpip.h>
# ifdef _MSC_VER
# pragma warning(disable:4244)
# pragma warning(disable:4267)
# endif
# define poll WSAPoll
#else
# include <arpa/inet.h>
# include <sys/socket.h>
# include <sys/param.h>
# include <errno.h>
# include <fcntl.h>
# include <netinet/in.h>
# include <netdb.h>
# include <unistd.h>
# include <poll.h>
#endif
#ifndef MSG_NOSIGNAL
# define MSG_NOSIGNAL 0
#endif
namespace tracy
{
#ifdef _WIN32
typedef SOCKET socket_t;
#else
typedef int socket_t;
#endif
#ifdef _WIN32
struct __wsinit
{
__wsinit()
{
WSADATA wsaData;
if( WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) != 0 )
{
fprintf( stderr, "Cannot init winsock.\n" );
exit( 1 );
}
}
};
void InitWinSock()
{
static __wsinit init;
}
#endif
enum { BufSize = 128 * 1024 };
Socket::Socket()
: m_buf( (char*)tracy_malloc( BufSize ) )
, m_bufPtr( nullptr )
, m_sock( -1 )
, m_bufLeft( 0 )
, m_ptr( nullptr )
{
#ifdef _WIN32
InitWinSock();
#endif
}
Socket::Socket( int sock )
: m_buf( (char*)tracy_malloc( BufSize ) )
, m_bufPtr( nullptr )
, m_sock( sock )
, m_bufLeft( 0 )
, m_ptr( nullptr )
{
}
Socket::~Socket()
{
tracy_free( m_buf );
if( m_sock.load( std::memory_order_relaxed ) != -1 )
{
Close();
}
if( m_ptr )
{
freeaddrinfo( m_res );
#ifdef _WIN32
closesocket( m_connSock );
#else
close( m_connSock );
#endif
}
}
bool Socket::Connect( const char* addr, uint16_t port )
{
assert( !IsValid() );
if( m_ptr )
{
const auto c = connect( m_connSock, m_ptr->ai_addr, m_ptr->ai_addrlen );
if( c == -1 )
{
#if defined _WIN32
const auto err = WSAGetLastError();
if( err == WSAEALREADY || err == WSAEINPROGRESS ) return false;
if( err != WSAEISCONN )
{
freeaddrinfo( m_res );
closesocket( m_connSock );
m_ptr = nullptr;
return false;
}
#else
const auto err = errno;
if( err == EALREADY || err == EINPROGRESS ) return false;
if( err != EISCONN )
{
freeaddrinfo( m_res );
close( m_connSock );
m_ptr = nullptr;
return false;
}
#endif
}
#if defined _WIN32
u_long nonblocking = 0;
ioctlsocket( m_connSock, FIONBIO, &nonblocking );
#else
int flags = fcntl( m_connSock, F_GETFL, 0 );
fcntl( m_connSock, F_SETFL, flags & ~O_NONBLOCK );
#endif
m_sock.store( m_connSock, std::memory_order_relaxed );
freeaddrinfo( m_res );
m_ptr = nullptr;
return true;
}
struct addrinfo hints;
struct addrinfo *res, *ptr;
memset( &hints, 0, sizeof( hints ) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
char portbuf[32];
sprintf( portbuf, "%" PRIu16, port );
if( getaddrinfo( addr, portbuf, &hints, &res ) != 0 ) return false;
int sock = 0;
for( ptr = res; ptr; ptr = ptr->ai_next )
{
if( ( sock = socket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol ) ) == -1 ) continue;
#if defined __APPLE__
int val = 1;
setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
#endif
#if defined _WIN32
u_long nonblocking = 1;
ioctlsocket( sock, FIONBIO, &nonblocking );
#else
int flags = fcntl( sock, F_GETFL, 0 );
fcntl( sock, F_SETFL, flags | O_NONBLOCK );
#endif
if( connect( sock, ptr->ai_addr, ptr->ai_addrlen ) == 0 )
{
break;
}
else
{
#if defined _WIN32
const auto err = WSAGetLastError();
if( err != WSAEWOULDBLOCK )
{
closesocket( sock );
continue;
}
#else
if( errno != EINPROGRESS )
{
close( sock );
continue;
}
#endif
}
m_res = res;
m_ptr = ptr;
m_connSock = sock;
return false;
}
freeaddrinfo( res );
if( !ptr ) return false;
#if defined _WIN32
u_long nonblocking = 0;
ioctlsocket( sock, FIONBIO, &nonblocking );
#else
int flags = fcntl( sock, F_GETFL, 0 );
fcntl( sock, F_SETFL, flags & ~O_NONBLOCK );
#endif
m_sock.store( sock, std::memory_order_relaxed );
return true;
}
bool Socket::ConnectBlocking( const char* addr, uint16_t port )
{
assert( !IsValid() );
assert( !m_ptr );
struct addrinfo hints;
struct addrinfo *res, *ptr;
memset( &hints, 0, sizeof( hints ) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
char portbuf[32];
sprintf( portbuf, "%" PRIu16, port );
if( getaddrinfo( addr, portbuf, &hints, &res ) != 0 ) return false;
int sock = 0;
for( ptr = res; ptr; ptr = ptr->ai_next )
{
if( ( sock = socket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol ) ) == -1 ) continue;
#if defined __APPLE__
int val = 1;
setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
#endif
if( connect( sock, ptr->ai_addr, ptr->ai_addrlen ) == -1 )
{
#ifdef _WIN32
closesocket( sock );
#else
close( sock );
#endif
continue;
}
break;
}
freeaddrinfo( res );
if( !ptr ) return false;
m_sock.store( sock, std::memory_order_relaxed );
return true;
}
void Socket::Close()
{
const auto sock = m_sock.load( std::memory_order_relaxed );
assert( sock != -1 );
#ifdef _WIN32
closesocket( sock );
#else
close( sock );
#endif
m_sock.store( -1, std::memory_order_relaxed );
}
int Socket::Send( const void* _buf, int len )
{
const auto sock = m_sock.load( std::memory_order_relaxed );
auto buf = (const char*)_buf;
assert( sock != -1 );
auto start = buf;
while( len > 0 )
{
auto ret = send( sock, buf, len, MSG_NOSIGNAL );
if( ret == -1 ) return -1;
len -= ret;
buf += ret;
}
return int( buf - start );
}
int Socket::GetSendBufSize()
{
const auto sock = m_sock.load( std::memory_order_relaxed );
int bufSize;
#if defined _WIN32
int sz = sizeof( bufSize );
getsockopt( sock, SOL_SOCKET, SO_SNDBUF, (char*)&bufSize, &sz );
#else
socklen_t sz = sizeof( bufSize );
getsockopt( sock, SOL_SOCKET, SO_SNDBUF, &bufSize, &sz );
#endif
return bufSize;
}
int Socket::RecvBuffered( void* buf, int len, int timeout )
{
if( len <= m_bufLeft )
{
memcpy( buf, m_bufPtr, len );
m_bufPtr += len;
m_bufLeft -= len;
return len;
}
if( m_bufLeft > 0 )
{
memcpy( buf, m_bufPtr, m_bufLeft );
const auto ret = m_bufLeft;
m_bufLeft = 0;
return ret;
}
if( len >= BufSize ) return Recv( buf, len, timeout );
m_bufLeft = Recv( m_buf, BufSize, timeout );
if( m_bufLeft <= 0 ) return m_bufLeft;
const auto sz = len < m_bufLeft ? len : m_bufLeft;
memcpy( buf, m_buf, sz );
m_bufPtr = m_buf + sz;
m_bufLeft -= sz;
return sz;
}
int Socket::Recv( void* _buf, int len, int timeout )
{
const auto sock = m_sock.load( std::memory_order_relaxed );
auto buf = (char*)_buf;
struct pollfd fd;
fd.fd = (socket_t)sock;
fd.events = POLLIN;
if( poll( &fd, 1, timeout ) > 0 )
{
return recv( sock, buf, len, 0 );
}
else
{
return -1;
}
}
int Socket::ReadUpTo( void* _buf, int len, int timeout )
{
const auto sock = m_sock.load( std::memory_order_relaxed );
auto buf = (char*)_buf;
int rd = 0;
while( len > 0 )
{
const auto res = recv( sock, buf, len, 0 );
if( res == 0 ) break;
if( res == -1 ) return -1;
len -= res;
rd += res;
buf += res;
}
return rd;
}
bool Socket::Read( void* buf, int len, int timeout )
{
auto cbuf = (char*)buf;
while( len > 0 )
{
if( !ReadImpl( cbuf, len, timeout ) ) return false;
}
return true;
}
bool Socket::ReadImpl( char*& buf, int& len, int timeout )
{
const auto sz = RecvBuffered( buf, len, timeout );
switch( sz )
{
case 0:
return false;
case -1:
#ifdef _WIN32
{
auto err = WSAGetLastError();
if( err == WSAECONNABORTED || err == WSAECONNRESET ) return false;
}
#endif
break;
default:
len -= sz;
buf += sz;
break;
}
return true;
}
bool Socket::ReadRaw( void* _buf, int len, int timeout )
{
auto buf = (char*)_buf;
while( len > 0 )
{
const auto sz = Recv( buf, len, timeout );
if( sz <= 0 ) return false;
len -= sz;
buf += sz;
}
return true;
}
bool Socket::HasData()
{
const auto sock = m_sock.load( std::memory_order_relaxed );
if( m_bufLeft > 0 ) return true;
struct pollfd fd;
fd.fd = (socket_t)sock;
fd.events = POLLIN;
return poll( &fd, 1, 0 ) > 0;
}
bool Socket::IsValid() const
{
return m_sock.load( std::memory_order_relaxed ) >= 0;
}
ListenSocket::ListenSocket()
: m_sock( -1 )
{
#ifdef _WIN32
InitWinSock();
#endif
}
ListenSocket::~ListenSocket()
{
if( m_sock != -1 ) Close();
}
static int addrinfo_and_socket_for_family( uint16_t port, int ai_family, struct addrinfo** res )
{
struct addrinfo hints;
memset( &hints, 0, sizeof( hints ) );
hints.ai_family = ai_family;
hints.ai_socktype = SOCK_STREAM;
#ifndef TRACY_ONLY_LOCALHOST
const char* onlyLocalhost = GetEnvVar( "TRACY_ONLY_LOCALHOST" );
if( !onlyLocalhost || onlyLocalhost[0] != '1' )
{
hints.ai_flags = AI_PASSIVE;
}
#endif
char portbuf[32];
sprintf( portbuf, "%" PRIu16, port );
if( getaddrinfo( nullptr, portbuf, &hints, res ) != 0 ) return -1;
int sock = socket( (*res)->ai_family, (*res)->ai_socktype, (*res)->ai_protocol );
if (sock == -1) freeaddrinfo( *res );
return sock;
}
bool ListenSocket::Listen( uint16_t port, int backlog )
{
assert( m_sock == -1 );
struct addrinfo* res = nullptr;
#if !defined TRACY_ONLY_IPV4 && !defined TRACY_ONLY_LOCALHOST
const char* onlyIPv4 = GetEnvVar( "TRACY_ONLY_IPV4" );
if( !onlyIPv4 || onlyIPv4[0] != '1' )
{
m_sock = addrinfo_and_socket_for_family( port, AF_INET6, &res );
}
#endif
if (m_sock == -1)
{
// IPV6 protocol may not be available/is disabled. Try to create a socket
// with the IPV4 protocol
m_sock = addrinfo_and_socket_for_family( port, AF_INET, &res );
if( m_sock == -1 ) return false;
}
#if defined _WIN32
unsigned long val = 0;
setsockopt( m_sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&val, sizeof( val ) );
#elif defined BSD
int val = 0;
setsockopt( m_sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&val, sizeof( val ) );
val = 1;
setsockopt( m_sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof( val ) );
#else
int val = 1;
setsockopt( m_sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof( val ) );
#endif
if( bind( m_sock, res->ai_addr, res->ai_addrlen ) == -1 ) { freeaddrinfo( res ); Close(); return false; }
if( listen( m_sock, backlog ) == -1 ) { freeaddrinfo( res ); Close(); return false; }
freeaddrinfo( res );
return true;
}
Socket* ListenSocket::Accept()
{
struct sockaddr_storage remote;
socklen_t sz = sizeof( remote );
struct pollfd fd;
fd.fd = (socket_t)m_sock;
fd.events = POLLIN;
if( poll( &fd, 1, 10 ) > 0 )
{
int sock = accept( m_sock, (sockaddr*)&remote, &sz);
if( sock == -1 ) return nullptr;
#if defined __APPLE__
int val = 1;
setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
#endif
auto ptr = (Socket*)tracy_malloc( sizeof( Socket ) );
new(ptr) Socket( sock );
return ptr;
}
else
{
return nullptr;
}
}
void ListenSocket::Close()
{
assert( m_sock != -1 );
#ifdef _WIN32
closesocket( m_sock );
#else
close( m_sock );
#endif
m_sock = -1;
}
UdpBroadcast::UdpBroadcast()
: m_sock( -1 )
{
#ifdef _WIN32
InitWinSock();
#endif
}
UdpBroadcast::~UdpBroadcast()
{
if( m_sock != -1 ) Close();
}
bool UdpBroadcast::Open( const char* addr, uint16_t port )
{
assert( m_sock == -1 );
struct addrinfo hints;
struct addrinfo *res, *ptr;
memset( &hints, 0, sizeof( hints ) );
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
char portbuf[32];
sprintf( portbuf, "%" PRIu16, port );
if( getaddrinfo( addr, portbuf, &hints, &res ) != 0 ) return false;
int sock = 0;
for( ptr = res; ptr; ptr = ptr->ai_next )
{
if( ( sock = socket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol ) ) == -1 ) continue;
#if defined __APPLE__
int val = 1;
setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
#endif
#if defined _WIN32
unsigned long broadcast = 1;
if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof( broadcast ) ) == -1 )
#else
int broadcast = 1;
if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof( broadcast ) ) == -1 )
#endif
{
#ifdef _WIN32
closesocket( sock );
#else
close( sock );
#endif
continue;
}
break;
}
freeaddrinfo( res );
if( !ptr ) return false;
m_sock = sock;
inet_pton( AF_INET, addr, &m_addr );
return true;
}
void UdpBroadcast::Close()
{
assert( m_sock != -1 );
#ifdef _WIN32
closesocket( m_sock );
#else
close( m_sock );
#endif
m_sock = -1;
}
int UdpBroadcast::Send( uint16_t port, const void* data, int len )
{
assert( m_sock != -1 );
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons( port );
addr.sin_addr.s_addr = m_addr;
return sendto( m_sock, (const char*)data, len, MSG_NOSIGNAL, (sockaddr*)&addr, sizeof( addr ) );
}
IpAddress::IpAddress()
: m_number( 0 )
{
*m_text = '\0';
}
IpAddress::~IpAddress()
{
}
void IpAddress::Set( const struct sockaddr& addr )
{
#if defined _WIN32 && ( !defined NTDDI_WIN10 || NTDDI_VERSION < NTDDI_WIN10 )
struct sockaddr_in tmp;
memcpy( &tmp, &addr, sizeof( tmp ) );
auto ai = &tmp;
#else
auto ai = (const struct sockaddr_in*)&addr;
#endif
inet_ntop( AF_INET, &ai->sin_addr, m_text, 17 );
m_number = ai->sin_addr.s_addr;
}
UdpListen::UdpListen()
: m_sock( -1 )
{
#ifdef _WIN32
InitWinSock();
#endif
}
UdpListen::~UdpListen()
{
if( m_sock != -1 ) Close();
}
bool UdpListen::Listen( uint16_t port )
{
assert( m_sock == -1 );
int sock;
if( ( sock = socket( AF_INET, SOCK_DGRAM, 0 ) ) == -1 ) return false;
#if defined __APPLE__
int val = 1;
setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
#endif
#if defined _WIN32
unsigned long reuse = 1;
setsockopt( m_sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof( reuse ) );
#else
int reuse = 1;
setsockopt( m_sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof( reuse ) );
#endif
#if defined _WIN32
unsigned long broadcast = 1;
if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof( broadcast ) ) == -1 )
#else
int broadcast = 1;
if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof( broadcast ) ) == -1 )
#endif
{
#ifdef _WIN32
closesocket( sock );
#else
close( sock );
#endif
return false;
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons( port );
addr.sin_addr.s_addr = INADDR_ANY;
if( bind( sock, (sockaddr*)&addr, sizeof( addr ) ) == -1 )
{
#ifdef _WIN32
closesocket( sock );
#else
close( sock );
#endif
return false;
}
m_sock = sock;
return true;
}
void UdpListen::Close()
{
assert( m_sock != -1 );
#ifdef _WIN32
closesocket( m_sock );
#else
close( m_sock );
#endif
m_sock = -1;
}
const char* UdpListen::Read( size_t& len, IpAddress& addr, int timeout )
{
static char buf[2048];
struct pollfd fd;
fd.fd = (socket_t)m_sock;
fd.events = POLLIN;
if( poll( &fd, 1, timeout ) <= 0 ) return nullptr;
sockaddr sa;
socklen_t salen = sizeof( struct sockaddr );
len = (size_t)recvfrom( m_sock, buf, 2048, 0, &sa, &salen );
addr.Set( sa );
return buf;
}
}

View File

@@ -0,0 +1,155 @@
#ifndef __TRACYSOCKET_HPP__
#define __TRACYSOCKET_HPP__
#include <atomic>
#include <stddef.h>
#include <stdint.h>
struct addrinfo;
struct sockaddr;
namespace tracy
{
#ifdef _WIN32
void InitWinSock();
#endif
class Socket
{
public:
Socket();
Socket( int sock );
~Socket();
bool Connect( const char* addr, uint16_t port );
bool ConnectBlocking( const char* addr, uint16_t port );
void Close();
int Send( const void* buf, int len );
int GetSendBufSize();
int ReadUpTo( void* buf, int len, int timeout );
bool Read( void* buf, int len, int timeout );
template<typename ShouldExit>
bool Read( void* buf, int len, int timeout, ShouldExit exitCb )
{
auto cbuf = (char*)buf;
while( len > 0 )
{
if( exitCb() ) return false;
if( !ReadImpl( cbuf, len, timeout ) ) return false;
}
return true;
}
bool ReadRaw( void* buf, int len, int timeout );
bool HasData();
bool IsValid() const;
Socket( const Socket& ) = delete;
Socket( Socket&& ) = delete;
Socket& operator=( const Socket& ) = delete;
Socket& operator=( Socket&& ) = delete;
private:
int RecvBuffered( void* buf, int len, int timeout );
int Recv( void* buf, int len, int timeout );
bool ReadImpl( char*& buf, int& len, int timeout );
char* m_buf;
char* m_bufPtr;
std::atomic<int> m_sock;
int m_bufLeft;
struct addrinfo *m_res;
struct addrinfo *m_ptr;
int m_connSock;
};
class ListenSocket
{
public:
ListenSocket();
~ListenSocket();
bool Listen( uint16_t port, int backlog );
Socket* Accept();
void Close();
ListenSocket( const ListenSocket& ) = delete;
ListenSocket( ListenSocket&& ) = delete;
ListenSocket& operator=( const ListenSocket& ) = delete;
ListenSocket& operator=( ListenSocket&& ) = delete;
private:
int m_sock;
};
class UdpBroadcast
{
public:
UdpBroadcast();
~UdpBroadcast();
bool Open( const char* addr, uint16_t port );
void Close();
int Send( uint16_t port, const void* data, int len );
UdpBroadcast( const UdpBroadcast& ) = delete;
UdpBroadcast( UdpBroadcast&& ) = delete;
UdpBroadcast& operator=( const UdpBroadcast& ) = delete;
UdpBroadcast& operator=( UdpBroadcast&& ) = delete;
private:
int m_sock;
uint32_t m_addr;
};
class IpAddress
{
public:
IpAddress();
~IpAddress();
void Set( const struct sockaddr& addr );
uint32_t GetNumber() const { return m_number; }
const char* GetText() const { return m_text; }
IpAddress( const IpAddress& ) = delete;
IpAddress( IpAddress&& ) = delete;
IpAddress& operator=( const IpAddress& ) = delete;
IpAddress& operator=( IpAddress&& ) = delete;
private:
uint32_t m_number;
char m_text[17];
};
class UdpListen
{
public:
UdpListen();
~UdpListen();
bool Listen( uint16_t port );
void Close();
const char* Read( size_t& len, IpAddress& addr, int timeout );
UdpListen( const UdpListen& ) = delete;
UdpListen( UdpListen&& ) = delete;
UdpListen& operator=( const UdpListen& ) = delete;
UdpListen& operator=( UdpListen&& ) = delete;
private:
int m_sock;
};
}
#endif

View File

@@ -0,0 +1,122 @@
#include "TracyStackFrames.hpp"
namespace tracy
{
const char* s_tracyStackFrames_[] = {
"tracy::Callstack",
"tracy::Callstack(int)",
"tracy::GpuCtxScope::{ctor}",
"tracy::Profiler::SendCallstack",
"tracy::Profiler::SendCallstack(int)",
"tracy::Profiler::SendCallstack(int, unsigned long)",
"tracy::Profiler::MemAllocCallstack",
"tracy::Profiler::MemAllocCallstack(void const*, unsigned long, int)",
"tracy::Profiler::MemFreeCallstack",
"tracy::Profiler::MemFreeCallstack(void const*, int)",
"tracy::ScopedZone::{ctor}",
"tracy::ScopedZone::ScopedZone(tracy::SourceLocationData const*, int, bool)",
"tracy::Profiler::Message",
nullptr
};
const char** s_tracyStackFrames = s_tracyStackFrames_;
const StringMatch s_tracySkipSubframes_[] = {
{ "/include/arm_neon.h", 19 },
{ "/include/adxintrin.h", 20 },
{ "/include/ammintrin.h", 20 },
{ "/include/amxbf16intrin.h", 24 },
{ "/include/amxint8intrin.h", 24 },
{ "/include/amxtileintrin.h", 24 },
{ "/include/avx2intrin.h", 21 },
{ "/include/avx5124fmapsintrin.h", 29 },
{ "/include/avx5124vnniwintrin.h", 29 },
{ "/include/avx512bf16intrin.h", 27 },
{ "/include/avx512bf16vlintrin.h", 29 },
{ "/include/avx512bitalgintrin.h", 29 },
{ "/include/avx512bwintrin.h", 25 },
{ "/include/avx512cdintrin.h", 25 },
{ "/include/avx512dqintrin.h", 25 },
{ "/include/avx512erintrin.h", 25 },
{ "/include/avx512fintrin.h", 24 },
{ "/include/avx512ifmaintrin.h", 27 },
{ "/include/avx512ifmavlintrin.h", 29 },
{ "/include/avx512pfintrin.h", 25 },
{ "/include/avx512vbmi2intrin.h", 28 },
{ "/include/avx512vbmi2vlintrin.h", 30 },
{ "/include/avx512vbmiintrin.h", 27 },
{ "/include/avx512vbmivlintrin.h", 29 },
{ "/include/avx512vlbwintrin.h", 27 },
{ "/include/avx512vldqintrin.h", 27 },
{ "/include/avx512vlintrin.h", 25 },
{ "/include/avx512vnniintrin.h", 27 },
{ "/include/avx512vnnivlintrin.h", 29 },
{ "/include/avx512vp2intersectintrin.h", 35 },
{ "/include/avx512vp2intersectvlintrin.h", 37 },
{ "/include/avx512vpopcntdqintrin.h", 32 },
{ "/include/avx512vpopcntdqvlintrin.h", 34 },
{ "/include/avxintrin.h", 20 },
{ "/include/avxvnniintrin.h", 24 },
{ "/include/bmi2intrin.h", 21 },
{ "/include/bmiintrin.h", 20 },
{ "/include/bmmintrin.h", 20 },
{ "/include/cetintrin.h", 20 },
{ "/include/cldemoteintrin.h", 25 },
{ "/include/clflushoptintrin.h", 27 },
{ "/include/clwbintrin.h", 21 },
{ "/include/clzerointrin.h", 23 },
{ "/include/emmintrin.h", 20 },
{ "/include/enqcmdintrin.h", 23 },
{ "/include/f16cintrin.h", 21 },
{ "/include/fma4intrin.h", 21 },
{ "/include/fmaintrin.h", 20 },
{ "/include/fxsrintrin.h", 21 },
{ "/include/gfniintrin.h", 21 },
{ "/include/hresetintrin.h", 23 },
{ "/include/ia32intrin.h", 21 },
{ "/include/immintrin.h", 20 },
{ "/include/keylockerintrin.h", 26 },
{ "/include/lwpintrin.h", 20 },
{ "/include/lzcntintrin.h", 22 },
{ "/include/mmintrin.h", 19 },
{ "/include/movdirintrin.h", 23 },
{ "/include/mwaitxintrin.h", 23 },
{ "/include/nmmintrin.h", 20 },
{ "/include/pconfigintrin.h", 24 },
{ "/include/pkuintrin.h", 20 },
{ "/include/pmmintrin.h", 20 },
{ "/include/popcntintrin.h", 23 },
{ "/include/prfchwintrin.h", 23 },
{ "/include/rdseedintrin.h", 23 },
{ "/include/rtmintrin.h", 20 },
{ "/include/serializeintrin.h", 26 },
{ "/include/sgxintrin.h", 20 },
{ "/include/shaintrin.h", 20 },
{ "/include/smmintrin.h", 20 },
{ "/include/tbmintrin.h", 20 },
{ "/include/tmmintrin.h", 20 },
{ "/include/tsxldtrkintrin.h", 25 },
{ "/include/uintrintrin.h", 22 },
{ "/include/vaesintrin.h", 21 },
{ "/include/vpclmulqdqintrin.h", 27 },
{ "/include/waitpkgintrin.h", 24 },
{ "/include/wbnoinvdintrin.h", 25 },
{ "/include/wmmintrin.h", 20 },
{ "/include/x86gprintrin.h", 23 },
{ "/include/x86intrin.h", 20 },
{ "/include/xmmintrin.h", 20 },
{ "/include/xopintrin.h", 20 },
{ "/include/xsavecintrin.h", 23 },
{ "/include/xsaveintrin.h", 22 },
{ "/include/xsaveoptintrin.h", 25 },
{ "/include/xsavesintrin.h", 23 },
{ "/include/xtestintrin.h", 22 },
{ "/bits/atomic_base.h", 19 },
{ "/atomic", 7 },
{}
};
const StringMatch* s_tracySkipSubframes = s_tracySkipSubframes_;
}

View File

@@ -0,0 +1,22 @@
#ifndef __TRACYSTACKFRAMES_HPP__
#define __TRACYSTACKFRAMES_HPP__
#include <stddef.h>
namespace tracy
{
struct StringMatch
{
const char* str;
size_t len;
};
extern const char** s_tracyStackFrames;
extern const StringMatch* s_tracySkipSubframes;
static constexpr int s_tracySkipSubframesMinLen = 7;
}
#endif

View File

@@ -0,0 +1,303 @@
#ifdef _MSC_VER
# pragma warning(disable:4996)
#endif
#if defined _WIN32
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# ifndef NOMINMAX
# define NOMINMAX
# endif
# include <windows.h>
# include <malloc.h>
# include "TracyUwp.hpp"
#else
# include <pthread.h>
# include <string.h>
# include <unistd.h>
#endif
#ifdef __linux__
# ifdef __ANDROID__
# include <sys/types.h>
# else
# include <sys/syscall.h>
# endif
# include <fcntl.h>
#elif defined __FreeBSD__
# include <sys/thr.h>
#elif defined __NetBSD__ || defined __DragonFly__
# include <sys/lwp.h>
#endif
#ifdef __MINGW32__
# define __STDC_FORMAT_MACROS
#endif
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include "TracySystem.hpp"
#if defined _WIN32
extern "C" typedef HRESULT (WINAPI *t_SetThreadDescription)( HANDLE, PCWSTR );
extern "C" typedef HRESULT (WINAPI *t_GetThreadDescription)( HANDLE, PWSTR* );
#endif
#ifdef TRACY_ENABLE
# include <atomic>
# include "TracyAlloc.hpp"
#endif
namespace tracy
{
namespace detail
{
TRACY_API uint32_t GetThreadHandleImpl()
{
#if defined _WIN32
static_assert( sizeof( decltype( GetCurrentThreadId() ) ) <= sizeof( uint32_t ), "Thread handle too big to fit in protocol" );
return uint32_t( GetCurrentThreadId() );
#elif defined __APPLE__
uint64_t id;
pthread_threadid_np( pthread_self(), &id );
return uint32_t( id );
#elif defined __ANDROID__
return (uint32_t)gettid();
#elif defined __linux__
return (uint32_t)syscall( SYS_gettid );
#elif defined __FreeBSD__
long id;
thr_self( &id );
return id;
#elif defined __NetBSD__
return _lwp_self();
#elif defined __DragonFly__
return lwp_gettid();
#elif defined __OpenBSD__
return getthrid();
#elif defined __EMSCRIPTEN__
// Not supported, but let it compile.
return 0;
#else
// To add support for a platform, retrieve and return the kernel thread identifier here.
//
// Note that pthread_t (as for example returned by pthread_self()) is *not* a kernel
// thread identifier. It is a pointer to a library-allocated data structure instead.
// Such pointers will be reused heavily, making the pthread_t non-unique. Additionally
// a 64-bit pointer cannot be reliably truncated to 32 bits.
#error "Unsupported platform!"
#endif
}
}
#ifdef TRACY_ENABLE
struct ThreadNameData
{
uint32_t id;
const char* name;
ThreadNameData* next;
};
std::atomic<ThreadNameData*>& GetThreadNameData();
#endif
#ifdef _MSC_VER
# pragma pack( push, 8 )
struct THREADNAME_INFO
{
DWORD dwType;
LPCSTR szName;
DWORD dwThreadID;
DWORD dwFlags;
};
# pragma pack( pop )
void ThreadNameMsvcMagic( const THREADNAME_INFO& info )
{
__try
{
RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
#endif
TRACY_API void SetThreadName( const char* name )
{
#if defined _WIN32
# ifdef TRACY_UWP
static auto _SetThreadDescription = &::SetThreadDescription;
# else
static auto _SetThreadDescription = (t_SetThreadDescription)GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "SetThreadDescription" );
# endif
if( _SetThreadDescription )
{
wchar_t buf[256];
mbstowcs( buf, name, 256 );
_SetThreadDescription( GetCurrentThread(), buf );
}
else
{
# if defined _MSC_VER
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = name;
info.dwThreadID = GetCurrentThreadId();
info.dwFlags = 0;
ThreadNameMsvcMagic( info );
# endif
}
#elif defined _GNU_SOURCE && !defined __EMSCRIPTEN__
{
const auto sz = strlen( name );
if( sz <= 15 )
{
#if defined __APPLE__
pthread_setname_np( name );
#else
pthread_setname_np( pthread_self(), name );
#endif
}
else
{
char buf[16];
memcpy( buf, name, 15 );
buf[15] = '\0';
#if defined __APPLE__
pthread_setname_np( buf );
#else
pthread_setname_np( pthread_self(), buf );
#endif
}
}
#endif
#ifdef TRACY_ENABLE
{
const auto sz = strlen( name );
char* buf = (char*)tracy_malloc( sz+1 );
memcpy( buf, name, sz );
buf[sz] = '\0';
auto data = (ThreadNameData*)tracy_malloc_fast( sizeof( ThreadNameData ) );
data->id = detail::GetThreadHandleImpl();
data->name = buf;
data->next = GetThreadNameData().load( std::memory_order_relaxed );
while( !GetThreadNameData().compare_exchange_weak( data->next, data, std::memory_order_release, std::memory_order_relaxed ) ) {}
}
#endif
}
TRACY_API const char* GetThreadName( uint32_t id )
{
static char buf[256];
#ifdef TRACY_ENABLE
auto ptr = GetThreadNameData().load( std::memory_order_relaxed );
while( ptr )
{
if( ptr->id == id )
{
return ptr->name;
}
ptr = ptr->next;
}
#endif
#if defined _WIN32
# ifdef TRACY_UWP
static auto _GetThreadDescription = &::GetThreadDescription;
# else
static auto _GetThreadDescription = (t_GetThreadDescription)GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "GetThreadDescription" );
# endif
if( _GetThreadDescription )
{
auto hnd = OpenThread( THREAD_QUERY_LIMITED_INFORMATION, FALSE, (DWORD)id );
if( hnd != 0 )
{
PWSTR tmp;
_GetThreadDescription( hnd, &tmp );
auto ret = wcstombs( buf, tmp, 256 );
CloseHandle( hnd );
if( ret != 0 )
{
return buf;
}
}
}
#elif defined __linux__
int cs, fd;
char path[32];
snprintf( path, sizeof( path ), "/proc/self/task/%d/comm", id );
sprintf( buf, "%" PRIu32, id );
# ifndef __ANDROID__
pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &cs );
# endif
if ( ( fd = open( path, O_RDONLY ) ) > 0) {
int len = read( fd, buf, 255 );
if( len > 0 )
{
buf[len] = 0;
if( len > 1 && buf[len-1] == '\n' )
{
buf[len-1] = 0;
}
}
close( fd );
}
# ifndef __ANDROID__
pthread_setcancelstate( cs, 0 );
# endif
return buf;
#endif
sprintf( buf, "%" PRIu32, id );
return buf;
}
TRACY_API const char* GetEnvVar( const char* name )
{
#if defined _WIN32
// unfortunately getenv() on Windows is just fundamentally broken. It caches the entire
// environment block once on startup, then never refreshes it again. If any environment
// strings are added or modified after startup of the CRT, those changes will not be
// seen by getenv(). This removes the possibility of an app using this SDK from
// programmatically setting any of the behaviour controlling envvars here.
//
// To work around this, we'll instead go directly to the Win32 environment strings APIs
// to get the current value.
static char buffer[1024];
DWORD const kBufferSize = DWORD(sizeof(buffer) / sizeof(buffer[0]));
DWORD count = GetEnvironmentVariableA(name, buffer, kBufferSize);
if( count == 0 )
return nullptr;
if( count >= kBufferSize )
{
char* buf = reinterpret_cast<char*>(_alloca(count + 1));
count = GetEnvironmentVariableA(name, buf, count + 1);
memcpy(buffer, buf, kBufferSize);
buffer[kBufferSize - 1] = 0;
}
return buffer;
#else
return getenv(name);
#endif
}
}
#ifdef __cplusplus
extern "C" {
#endif
TRACY_API void ___tracy_set_thread_name( const char* name ) { tracy::SetThreadName( name ); }
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,32 @@
#ifndef __TRACYSYSTEM_HPP__
#define __TRACYSYSTEM_HPP__
#include <stdint.h>
#include "TracyApi.h"
namespace tracy
{
namespace detail
{
TRACY_API uint32_t GetThreadHandleImpl();
}
#ifdef TRACY_ENABLE
TRACY_API uint32_t GetThreadHandle();
#else
static inline uint32_t GetThreadHandle()
{
return detail::GetThreadHandleImpl();
}
#endif
TRACY_API void SetThreadName( const char* name );
TRACY_API const char* GetThreadName( uint32_t id );
TRACY_API const char* GetEnvVar(const char* name);
}
#endif

View File

@@ -0,0 +1,11 @@
#ifndef __TRACYUWP_HPP__
#define __TRACYUWP_HPP__
#ifdef _WIN32
# include <winapifamily.h>
# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
# define TRACY_UWP
# endif
#endif
#endif

View File

@@ -0,0 +1,14 @@
#ifndef __TRACYVERSION_HPP__
#define __TRACYVERSION_HPP__
namespace tracy
{
namespace Version
{
enum { Major = 0 };
enum { Minor = 9 };
enum { Patch = 1 };
}
}
#endif

View File

@@ -0,0 +1,28 @@
#ifndef __TRACYYIELD_HPP__
#define __TRACYYIELD_HPP__
#if defined __SSE2__ || defined _M_AMD64 || (defined _M_IX86_FP && _M_IX86_FP == 2)
# include <emmintrin.h>
#else
# include <thread>
#endif
#include "TracyForceInline.hpp"
namespace tracy
{
static tracy_force_inline void YieldThread()
{
#if defined __SSE2__ || defined _M_AMD64 || (defined _M_IX86_FP && _M_IX86_FP == 2)
_mm_pause();
#elif defined __aarch64__
asm volatile( "isb" : : );
#else
std::this_thread::yield();
#endif
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,847 @@
/*
* LZ4 - Fast LZ compression algorithm
* Header File
* Copyright (C) 2011-2020, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
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.
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.
You can contact the author at :
- LZ4 homepage : http://www.lz4.org
- LZ4 source repository : https://github.com/lz4/lz4
*/
#ifndef TRACY_LZ4_H_2983827168210
#define TRACY_LZ4_H_2983827168210
/* --- Dependency --- */
#include <stddef.h> /* size_t */
#include <stdint.h>
/**
Introduction
LZ4 is lossless compression algorithm, providing compression speed >500 MB/s per core,
scalable with multi-cores CPU. It features an extremely fast decoder, with speed in
multiple GB/s per core, typically reaching RAM speed limits on multi-core systems.
The LZ4 compression library provides in-memory compression and decompression functions.
It gives full buffer control to user.
Compression can be done in:
- a single step (described as Simple Functions)
- a single step, reusing a context (described in Advanced Functions)
- unbounded multiple steps (described as Streaming compression)
lz4.h generates and decodes LZ4-compressed blocks (doc/lz4_Block_format.md).
Decompressing such a compressed block requires additional metadata.
Exact metadata depends on exact decompression function.
For the typical case of LZ4_decompress_safe(),
metadata includes block's compressed size, and maximum bound of decompressed size.
Each application is free to encode and pass such metadata in whichever way it wants.
lz4.h only handle blocks, it can not generate Frames.
Blocks are different from Frames (doc/lz4_Frame_format.md).
Frames bundle both blocks and metadata in a specified manner.
Embedding metadata is required for compressed data to be self-contained and portable.
Frame format is delivered through a companion API, declared in lz4frame.h.
The `lz4` CLI can only manage frames.
*/
/*^***************************************************************
* Export parameters
*****************************************************************/
/*
* LZ4_DLL_EXPORT :
* Enable exporting of functions when building a Windows DLL
* LZ4LIB_VISIBILITY :
* Control library symbols visibility.
*/
#ifndef LZ4LIB_VISIBILITY
# if defined(__GNUC__) && (__GNUC__ >= 4)
# define LZ4LIB_VISIBILITY __attribute__ ((visibility ("default")))
# else
# define LZ4LIB_VISIBILITY
# endif
#endif
#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1)
# define LZ4LIB_API __declspec(dllexport) LZ4LIB_VISIBILITY
#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1)
# define LZ4LIB_API __declspec(dllimport) LZ4LIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
#else
# define LZ4LIB_API LZ4LIB_VISIBILITY
#endif
/*! LZ4_FREESTANDING :
* When this macro is set to 1, it enables "freestanding mode" that is
* suitable for typical freestanding environment which doesn't support
* standard C library.
*
* - LZ4_FREESTANDING is a compile-time switch.
* - It requires the following macros to be defined:
* LZ4_memcpy, LZ4_memmove, LZ4_memset.
* - It only enables LZ4/HC functions which don't use heap.
* All LZ4F_* functions are not supported.
* - See tests/freestanding.c to check its basic setup.
*/
#if defined(LZ4_FREESTANDING) && (LZ4_FREESTANDING == 1)
# define LZ4_HEAPMODE 0
# define LZ4HC_HEAPMODE 0
# define LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION 1
# if !defined(LZ4_memcpy)
# error "LZ4_FREESTANDING requires macro 'LZ4_memcpy'."
# endif
# if !defined(LZ4_memset)
# error "LZ4_FREESTANDING requires macro 'LZ4_memset'."
# endif
# if !defined(LZ4_memmove)
# error "LZ4_FREESTANDING requires macro 'LZ4_memmove'."
# endif
#elif ! defined(LZ4_FREESTANDING)
# define LZ4_FREESTANDING 0
#endif
/*------ Version ------*/
#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
#define LZ4_VERSION_MINOR 9 /* for new (non-breaking) interface capabilities */
#define LZ4_VERSION_RELEASE 4 /* for tweaks, bug-fixes, or development */
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE
#define LZ4_QUOTE(str) #str
#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str)
#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION) /* requires v1.7.3+ */
namespace tracy
{
LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; useful to check dll version; requires v1.3.0+ */
LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; useful to check dll version; requires v1.7.5+ */
/*-************************************
* Tuning parameter
**************************************/
#define LZ4_MEMORY_USAGE_MIN 10
#define LZ4_MEMORY_USAGE_DEFAULT 14
#define LZ4_MEMORY_USAGE_MAX 20
/*!
* LZ4_MEMORY_USAGE :
* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; )
* Increasing memory usage improves compression ratio, at the cost of speed.
* Reduced memory usage may improve speed at the cost of ratio, thanks to better cache locality.
* Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
*/
#ifndef LZ4_MEMORY_USAGE
# define LZ4_MEMORY_USAGE LZ4_MEMORY_USAGE_DEFAULT
#endif
#if (LZ4_MEMORY_USAGE < LZ4_MEMORY_USAGE_MIN)
# error "LZ4_MEMORY_USAGE is too small !"
#endif
#if (LZ4_MEMORY_USAGE > LZ4_MEMORY_USAGE_MAX)
# error "LZ4_MEMORY_USAGE is too large !"
#endif
/*-************************************
* Simple Functions
**************************************/
/*! LZ4_compress_default() :
* Compresses 'srcSize' bytes from buffer 'src'
* into already allocated 'dst' buffer of size 'dstCapacity'.
* Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize).
* It also runs faster, so it's a recommended setting.
* If the function cannot compress 'src' into a more limited 'dst' budget,
* compression stops *immediately*, and the function result is zero.
* In which case, 'dst' content is undefined (invalid).
* srcSize : max supported value is LZ4_MAX_INPUT_SIZE.
* dstCapacity : size of buffer 'dst' (which must be already allocated)
* @return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity)
* or 0 if compression fails
* Note : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer).
*/
LZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity);
/*! LZ4_decompress_safe() :
* compressedSize : is the exact complete size of the compressed block.
* dstCapacity : is the size of destination buffer (which must be already allocated), presumed an upper bound of decompressed size.
* @return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity)
* If destination buffer is not large enough, decoding will stop and output an error code (negative value).
* If the source stream is detected malformed, the function will stop decoding and return a negative result.
* Note 1 : This function is protected against malicious data packets :
* it will never writes outside 'dst' buffer, nor read outside 'source' buffer,
* even if the compressed block is maliciously modified to order the decoder to do these actions.
* In such case, the decoder stops immediately, and considers the compressed block malformed.
* Note 2 : compressedSize and dstCapacity must be provided to the function, the compressed block does not contain them.
* The implementation is free to send / store / derive this information in whichever way is most beneficial.
* If there is a need for a different format which bundles together both compressed data and its metadata, consider looking at lz4frame.h instead.
*/
LZ4LIB_API int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity);
/*-************************************
* Advanced Functions
**************************************/
#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
/*! LZ4_compressBound() :
Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)
This function is primarily useful for memory allocation purposes (destination buffer size).
Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
Note that LZ4_compress_default() compresses faster when dstCapacity is >= LZ4_compressBound(srcSize)
inputSize : max supported value is LZ4_MAX_INPUT_SIZE
return : maximum output size in a "worst case" scenario
or 0, if input size is incorrect (too large or negative)
*/
LZ4LIB_API int LZ4_compressBound(int inputSize);
/*! LZ4_compress_fast() :
Same as LZ4_compress_default(), but allows selection of "acceleration" factor.
The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
An acceleration value of "1" is the same as regular LZ4_compress_default()
Values <= 0 will be replaced by LZ4_ACCELERATION_DEFAULT (currently == 1, see lz4.c).
Values > LZ4_ACCELERATION_MAX will be replaced by LZ4_ACCELERATION_MAX (currently == 65537, see lz4.c).
*/
LZ4LIB_API int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
/*! LZ4_compress_fast_extState() :
* Same as LZ4_compress_fast(), using an externally allocated memory space for its state.
* Use LZ4_sizeofState() to know how much memory must be allocated,
* and allocate it on 8-bytes boundaries (using `malloc()` typically).
* Then, provide this buffer as `void* state` to compression function.
*/
LZ4LIB_API int LZ4_sizeofState(void);
LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
/*! LZ4_compress_destSize() :
* Reverse the logic : compresses as much data as possible from 'src' buffer
* into already allocated buffer 'dst', of size >= 'targetDestSize'.
* This function either compresses the entire 'src' content into 'dst' if it's large enough,
* or fill 'dst' buffer completely with as much data as possible from 'src'.
* note: acceleration parameter is fixed to "default".
*
* *srcSizePtr : will be modified to indicate how many bytes where read from 'src' to fill 'dst'.
* New value is necessarily <= input value.
* @return : Nb bytes written into 'dst' (necessarily <= targetDestSize)
* or 0 if compression fails.
*
* Note : from v1.8.2 to v1.9.1, this function had a bug (fixed un v1.9.2+):
* the produced compressed content could, in specific circumstances,
* require to be decompressed into a destination buffer larger
* by at least 1 byte than the content to decompress.
* If an application uses `LZ4_compress_destSize()`,
* it's highly recommended to update liblz4 to v1.9.2 or better.
* If this can't be done or ensured,
* the receiving decompression function should provide
* a dstCapacity which is > decompressedSize, by at least 1 byte.
* See https://github.com/lz4/lz4/issues/859 for details
*/
LZ4LIB_API int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePtr, int targetDstSize);
/*! LZ4_decompress_safe_partial() :
* Decompress an LZ4 compressed block, of size 'srcSize' at position 'src',
* into destination buffer 'dst' of size 'dstCapacity'.
* Up to 'targetOutputSize' bytes will be decoded.
* The function stops decoding on reaching this objective.
* This can be useful to boost performance
* whenever only the beginning of a block is required.
*
* @return : the number of bytes decoded in `dst` (necessarily <= targetOutputSize)
* If source stream is detected malformed, function returns a negative result.
*
* Note 1 : @return can be < targetOutputSize, if compressed block contains less data.
*
* Note 2 : targetOutputSize must be <= dstCapacity
*
* Note 3 : this function effectively stops decoding on reaching targetOutputSize,
* so dstCapacity is kind of redundant.
* This is because in older versions of this function,
* decoding operation would still write complete sequences.
* Therefore, there was no guarantee that it would stop writing at exactly targetOutputSize,
* it could write more bytes, though only up to dstCapacity.
* Some "margin" used to be required for this operation to work properly.
* Thankfully, this is no longer necessary.
* The function nonetheless keeps the same signature, in an effort to preserve API compatibility.
*
* Note 4 : If srcSize is the exact size of the block,
* then targetOutputSize can be any value,
* including larger than the block's decompressed size.
* The function will, at most, generate block's decompressed size.
*
* Note 5 : If srcSize is _larger_ than block's compressed size,
* then targetOutputSize **MUST** be <= block's decompressed size.
* Otherwise, *silent corruption will occur*.
*/
LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcSize, int targetOutputSize, int dstCapacity);
/*-*********************************************
* Streaming Compression Functions
***********************************************/
typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */
/**
Note about RC_INVOKED
- RC_INVOKED is predefined symbol of rc.exe (the resource compiler which is part of MSVC/Visual Studio).
https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros
- Since rc.exe is a legacy compiler, it truncates long symbol (> 30 chars)
and reports warning "RC4011: identifier truncated".
- To eliminate the warning, we surround long preprocessor symbol with
"#if !defined(RC_INVOKED) ... #endif" block that means
"skip this block when rc.exe is trying to read it".
*/
#if !defined(RC_INVOKED) /* https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros */
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
LZ4LIB_API LZ4_stream_t* LZ4_createStream(void);
LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr);
#endif /* !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) */
#endif
/*! LZ4_resetStream_fast() : v1.9.0+
* Use this to prepare an LZ4_stream_t for a new chain of dependent blocks
* (e.g., LZ4_compress_fast_continue()).
*
* An LZ4_stream_t must be initialized once before usage.
* This is automatically done when created by LZ4_createStream().
* However, should the LZ4_stream_t be simply declared on stack (for example),
* it's necessary to initialize it first, using LZ4_initStream().
*
* After init, start any new stream with LZ4_resetStream_fast().
* A same LZ4_stream_t can be re-used multiple times consecutively
* and compress multiple streams,
* provided that it starts each new stream with LZ4_resetStream_fast().
*
* LZ4_resetStream_fast() is much faster than LZ4_initStream(),
* but is not compatible with memory regions containing garbage data.
*
* Note: it's only useful to call LZ4_resetStream_fast()
* in the context of streaming compression.
* The *extState* functions perform their own resets.
* Invoking LZ4_resetStream_fast() before is redundant, and even counterproductive.
*/
LZ4LIB_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr);
/*! LZ4_loadDict() :
* Use this function to reference a static dictionary into LZ4_stream_t.
* The dictionary must remain available during compression.
* LZ4_loadDict() triggers a reset, so any previous data will be forgotten.
* The same dictionary will have to be loaded on decompression side for successful decoding.
* Dictionary are useful for better compression of small data (KB range).
* While LZ4 accept any input as dictionary,
* results are generally better when using Zstandard's Dictionary Builder.
* Loading a size of 0 is allowed, and is the same as reset.
* @return : loaded dictionary size, in bytes (necessarily <= 64 KB)
*/
LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
/*! LZ4_compress_fast_continue() :
* Compress 'src' content using data from previously compressed blocks, for better compression ratio.
* 'dst' buffer must be already allocated.
* If dstCapacity >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.
*
* @return : size of compressed block
* or 0 if there is an error (typically, cannot fit into 'dst').
*
* Note 1 : Each invocation to LZ4_compress_fast_continue() generates a new block.
* Each block has precise boundaries.
* Each block must be decompressed separately, calling LZ4_decompress_*() with relevant metadata.
* It's not possible to append blocks together and expect a single invocation of LZ4_decompress_*() to decompress them together.
*
* Note 2 : The previous 64KB of source data is __assumed__ to remain present, unmodified, at same address in memory !
*
* Note 3 : When input is structured as a double-buffer, each buffer can have any size, including < 64 KB.
* Make sure that buffers are separated, by at least one byte.
* This construction ensures that each block only depends on previous block.
*
* Note 4 : If input buffer is a ring-buffer, it can have any size, including < 64 KB.
*
* Note 5 : After an error, the stream status is undefined (invalid), it can only be reset or freed.
*/
LZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
/*! LZ4_saveDict() :
* If last 64KB data cannot be guaranteed to remain available at its current memory location,
* save it into a safer place (char* safeBuffer).
* This is schematically equivalent to a memcpy() followed by LZ4_loadDict(),
* but is much faster, because LZ4_saveDict() doesn't need to rebuild tables.
* @return : saved dictionary size in bytes (necessarily <= maxDictSize), or 0 if error.
*/
LZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int maxDictSize);
/*-**********************************************
* Streaming Decompression Functions
* Bufferless synchronous API
************************************************/
typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* tracking context */
/*! LZ4_createStreamDecode() and LZ4_freeStreamDecode() :
* creation / destruction of streaming decompression tracking context.
* A tracking context can be re-used multiple times.
*/
#if !defined(RC_INVOKED) /* https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros */
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void);
LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
#endif /* !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) */
#endif
/*! LZ4_setStreamDecode() :
* An LZ4_streamDecode_t context can be allocated once and re-used multiple times.
* Use this function to start decompression of a new stream of blocks.
* A dictionary can optionally be set. Use NULL or size 0 for a reset order.
* Dictionary is presumed stable : it must remain accessible and unmodified during next decompression.
* @return : 1 if OK, 0 if error
*/
LZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize);
/*! LZ4_decoderRingBufferSize() : v1.8.2+
* Note : in a ring buffer scenario (optional),
* blocks are presumed decompressed next to each other
* up to the moment there is not enough remaining space for next block (remainingSize < maxBlockSize),
* at which stage it resumes from beginning of ring buffer.
* When setting such a ring buffer for streaming decompression,
* provides the minimum size of this ring buffer
* to be compatible with any source respecting maxBlockSize condition.
* @return : minimum ring buffer size,
* or 0 if there is an error (invalid maxBlockSize).
*/
LZ4LIB_API int LZ4_decoderRingBufferSize(int maxBlockSize);
#define LZ4_DECODER_RING_BUFFER_SIZE(maxBlockSize) (65536 + 14 + (maxBlockSize)) /* for static allocation; maxBlockSize presumed valid */
/*! LZ4_decompress_*_continue() :
* These decoding functions allow decompression of consecutive blocks in "streaming" mode.
* A block is an unsplittable entity, it must be presented entirely to a decompression function.
* Decompression functions only accepts one block at a time.
* The last 64KB of previously decoded data *must* remain available and unmodified at the memory position where they were decoded.
* If less than 64KB of data has been decoded, all the data must be present.
*
* Special : if decompression side sets a ring buffer, it must respect one of the following conditions :
* - Decompression buffer size is _at least_ LZ4_decoderRingBufferSize(maxBlockSize).
* maxBlockSize is the maximum size of any single block. It can have any value > 16 bytes.
* In which case, encoding and decoding buffers do not need to be synchronized.
* Actually, data can be produced by any source compliant with LZ4 format specification, and respecting maxBlockSize.
* - Synchronized mode :
* Decompression buffer size is _exactly_ the same as compression buffer size,
* and follows exactly same update rule (block boundaries at same positions),
* and decoding function is provided with exact decompressed size of each block (exception for last block of the stream),
* _then_ decoding & encoding ring buffer can have any size, including small ones ( < 64 KB).
* - Decompression buffer is larger than encoding buffer, by a minimum of maxBlockSize more bytes.
* In which case, encoding and decoding buffers do not need to be synchronized,
* and encoding ring buffer can have any size, including small ones ( < 64 KB).
*
* Whenever these conditions are not possible,
* save the last 64KB of decoded data into a safe buffer where it can't be modified during decompression,
* then indicate where this data is saved using LZ4_setStreamDecode(), before decompressing next block.
*/
LZ4LIB_API int
LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode,
const char* src, char* dst,
int srcSize, int dstCapacity);
/*! LZ4_decompress_*_usingDict() :
* These decoding functions work the same as
* a combination of LZ4_setStreamDecode() followed by LZ4_decompress_*_continue()
* They are stand-alone, and don't need an LZ4_streamDecode_t structure.
* Dictionary is presumed stable : it must remain accessible and unmodified during decompression.
* Performance tip : Decompression speed can be substantially increased
* when dst == dictStart + dictSize.
*/
LZ4LIB_API int
LZ4_decompress_safe_usingDict(const char* src, char* dst,
int srcSize, int dstCapacity,
const char* dictStart, int dictSize);
LZ4LIB_API int
LZ4_decompress_safe_partial_usingDict(const char* src, char* dst,
int compressedSize,
int targetOutputSize, int maxOutputSize,
const char* dictStart, int dictSize);
}
#endif /* LZ4_H_2983827168210 */
/*^*************************************
* !!!!!! STATIC LINKING ONLY !!!!!!
***************************************/
/*-****************************************************************************
* Experimental section
*
* Symbols declared in this section must be considered unstable. Their
* signatures or semantics may change, or they may be removed altogether in the
* future. They are therefore only safe to depend on when the caller is
* statically linked against the library.
*
* To protect against unsafe usage, not only are the declarations guarded,
* the definitions are hidden by default
* when building LZ4 as a shared/dynamic library.
*
* In order to access these declarations,
* define LZ4_STATIC_LINKING_ONLY in your application
* before including LZ4's headers.
*
* In order to make their implementations accessible dynamically, you must
* define LZ4_PUBLISH_STATIC_FUNCTIONS when building the LZ4 library.
******************************************************************************/
#ifdef LZ4_STATIC_LINKING_ONLY
#ifndef TRACY_LZ4_STATIC_3504398509
#define TRACY_LZ4_STATIC_3504398509
#ifdef LZ4_PUBLISH_STATIC_FUNCTIONS
#define LZ4LIB_STATIC_API LZ4LIB_API
#else
#define LZ4LIB_STATIC_API
#endif
namespace tracy
{
/*! LZ4_compress_fast_extState_fastReset() :
* A variant of LZ4_compress_fast_extState().
*
* Using this variant avoids an expensive initialization step.
* It is only safe to call if the state buffer is known to be correctly initialized already
* (see above comment on LZ4_resetStream_fast() for a definition of "correctly initialized").
* From a high level, the difference is that
* this function initializes the provided state with a call to something like LZ4_resetStream_fast()
* while LZ4_compress_fast_extState() starts with a call to LZ4_resetStream().
*/
LZ4LIB_STATIC_API int LZ4_compress_fast_extState_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
/*! LZ4_attach_dictionary() :
* This is an experimental API that allows
* efficient use of a static dictionary many times.
*
* Rather than re-loading the dictionary buffer into a working context before
* each compression, or copying a pre-loaded dictionary's LZ4_stream_t into a
* working LZ4_stream_t, this function introduces a no-copy setup mechanism,
* in which the working stream references the dictionary stream in-place.
*
* Several assumptions are made about the state of the dictionary stream.
* Currently, only streams which have been prepared by LZ4_loadDict() should
* be expected to work.
*
* Alternatively, the provided dictionaryStream may be NULL,
* in which case any existing dictionary stream is unset.
*
* If a dictionary is provided, it replaces any pre-existing stream history.
* The dictionary contents are the only history that can be referenced and
* logically immediately precede the data compressed in the first subsequent
* compression call.
*
* The dictionary will only remain attached to the working stream through the
* first compression call, at the end of which it is cleared. The dictionary
* stream (and source buffer) must remain in-place / accessible / unchanged
* through the completion of the first compression call on the stream.
*/
LZ4LIB_STATIC_API void
LZ4_attach_dictionary(LZ4_stream_t* workingStream,
const LZ4_stream_t* dictionaryStream);
/*! In-place compression and decompression
*
* It's possible to have input and output sharing the same buffer,
* for highly constrained memory environments.
* In both cases, it requires input to lay at the end of the buffer,
* and decompression to start at beginning of the buffer.
* Buffer size must feature some margin, hence be larger than final size.
*
* |<------------------------buffer--------------------------------->|
* |<-----------compressed data--------->|
* |<-----------decompressed size------------------>|
* |<----margin---->|
*
* This technique is more useful for decompression,
* since decompressed size is typically larger,
* and margin is short.
*
* In-place decompression will work inside any buffer
* which size is >= LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize).
* This presumes that decompressedSize > compressedSize.
* Otherwise, it means compression actually expanded data,
* and it would be more efficient to store such data with a flag indicating it's not compressed.
* This can happen when data is not compressible (already compressed, or encrypted).
*
* For in-place compression, margin is larger, as it must be able to cope with both
* history preservation, requiring input data to remain unmodified up to LZ4_DISTANCE_MAX,
* and data expansion, which can happen when input is not compressible.
* As a consequence, buffer size requirements are much higher,
* and memory savings offered by in-place compression are more limited.
*
* There are ways to limit this cost for compression :
* - Reduce history size, by modifying LZ4_DISTANCE_MAX.
* Note that it is a compile-time constant, so all compressions will apply this limit.
* Lower values will reduce compression ratio, except when input_size < LZ4_DISTANCE_MAX,
* so it's a reasonable trick when inputs are known to be small.
* - Require the compressor to deliver a "maximum compressed size".
* This is the `dstCapacity` parameter in `LZ4_compress*()`.
* When this size is < LZ4_COMPRESSBOUND(inputSize), then compression can fail,
* in which case, the return code will be 0 (zero).
* The caller must be ready for these cases to happen,
* and typically design a backup scheme to send data uncompressed.
* The combination of both techniques can significantly reduce
* the amount of margin required for in-place compression.
*
* In-place compression can work in any buffer
* which size is >= (maxCompressedSize)
* with maxCompressedSize == LZ4_COMPRESSBOUND(srcSize) for guaranteed compression success.
* LZ4_COMPRESS_INPLACE_BUFFER_SIZE() depends on both maxCompressedSize and LZ4_DISTANCE_MAX,
* so it's possible to reduce memory requirements by playing with them.
*/
#define LZ4_DECOMPRESS_INPLACE_MARGIN(compressedSize) (((compressedSize) >> 8) + 32)
#define LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize) ((decompressedSize) + LZ4_DECOMPRESS_INPLACE_MARGIN(decompressedSize)) /**< note: presumes that compressedSize < decompressedSize. note2: margin is overestimated a bit, since it could use compressedSize instead */
#ifndef LZ4_DISTANCE_MAX /* history window size; can be user-defined at compile time */
# define LZ4_DISTANCE_MAX 65535 /* set to maximum value by default */
#endif
#define LZ4_COMPRESS_INPLACE_MARGIN (LZ4_DISTANCE_MAX + 32) /* LZ4_DISTANCE_MAX can be safely replaced by srcSize when it's smaller */
#define LZ4_COMPRESS_INPLACE_BUFFER_SIZE(maxCompressedSize) ((maxCompressedSize) + LZ4_COMPRESS_INPLACE_MARGIN) /**< maxCompressedSize is generally LZ4_COMPRESSBOUND(inputSize), but can be set to any lower value, with the risk that compression can fail (return code 0(zero)) */
}
#endif /* LZ4_STATIC_3504398509 */
#endif /* LZ4_STATIC_LINKING_ONLY */
#ifndef TRACY_LZ4_H_98237428734687
#define TRACY_LZ4_H_98237428734687
namespace tracy
{
/*-************************************************************
* Private Definitions
**************************************************************
* Do not use these definitions directly.
* They are only exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`.
* Accessing members will expose user code to API and/or ABI break in future versions of the library.
**************************************************************/
#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2)
#define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)
#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */
#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
typedef int8_t LZ4_i8;
typedef uint8_t LZ4_byte;
typedef uint16_t LZ4_u16;
typedef uint32_t LZ4_u32;
#else
typedef signed char LZ4_i8;
typedef unsigned char LZ4_byte;
typedef unsigned short LZ4_u16;
typedef unsigned int LZ4_u32;
#endif
/*! LZ4_stream_t :
* Never ever use below internal definitions directly !
* These definitions are not API/ABI safe, and may change in future versions.
* If you need static allocation, declare or allocate an LZ4_stream_t object.
**/
typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
struct LZ4_stream_t_internal {
LZ4_u32 hashTable[LZ4_HASH_SIZE_U32];
const LZ4_byte* dictionary;
const LZ4_stream_t_internal* dictCtx;
LZ4_u32 currentOffset;
LZ4_u32 tableType;
LZ4_u32 dictSize;
/* Implicit padding to ensure structure is aligned */
};
#define LZ4_STREAM_MINSIZE ((1UL << LZ4_MEMORY_USAGE) + 32) /* static size, for inter-version compatibility */
union LZ4_stream_u {
char minStateSize[LZ4_STREAM_MINSIZE];
LZ4_stream_t_internal internal_donotuse;
}; /* previously typedef'd to LZ4_stream_t */
/*! LZ4_initStream() : v1.9.0+
* An LZ4_stream_t structure must be initialized at least once.
* This is automatically done when invoking LZ4_createStream(),
* but it's not when the structure is simply declared on stack (for example).
*
* Use LZ4_initStream() to properly initialize a newly declared LZ4_stream_t.
* It can also initialize any arbitrary buffer of sufficient size,
* and will @return a pointer of proper type upon initialization.
*
* Note : initialization fails if size and alignment conditions are not respected.
* In which case, the function will @return NULL.
* Note2: An LZ4_stream_t structure guarantees correct alignment and size.
* Note3: Before v1.9.0, use LZ4_resetStream() instead
**/
LZ4LIB_API LZ4_stream_t* LZ4_initStream (void* buffer, size_t size);
/*! LZ4_streamDecode_t :
* Never ever use below internal definitions directly !
* These definitions are not API/ABI safe, and may change in future versions.
* If you need static allocation, declare or allocate an LZ4_streamDecode_t object.
**/
typedef struct {
const LZ4_byte* externalDict;
const LZ4_byte* prefixEnd;
size_t extDictSize;
size_t prefixSize;
} LZ4_streamDecode_t_internal;
#define LZ4_STREAMDECODE_MINSIZE 32
union LZ4_streamDecode_u {
char minStateSize[LZ4_STREAMDECODE_MINSIZE];
LZ4_streamDecode_t_internal internal_donotuse;
} ; /* previously typedef'd to LZ4_streamDecode_t */
/*-************************************
* Obsolete Functions
**************************************/
/*! Deprecation warnings
*
* Deprecated functions make the compiler generate a warning when invoked.
* This is meant to invite users to update their source code.
* Should deprecation warnings be a problem, it is generally possible to disable them,
* typically with -Wno-deprecated-declarations for gcc
* or _CRT_SECURE_NO_WARNINGS in Visual.
*
* Another method is to define LZ4_DISABLE_DEPRECATE_WARNINGS
* before including the header file.
*/
#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS
# define LZ4_DEPRECATED(message) /* disable deprecation warnings */
#else
# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
# define LZ4_DEPRECATED(message) [[deprecated(message)]]
# elif defined(_MSC_VER)
# define LZ4_DEPRECATED(message) __declspec(deprecated(message))
# elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 45))
# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
# elif defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 31)
# define LZ4_DEPRECATED(message) __attribute__((deprecated))
# else
# pragma message("WARNING: LZ4_DEPRECATED needs custom implementation for this compiler")
# define LZ4_DEPRECATED(message) /* disabled */
# endif
#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */
/*! Obsolete compression functions (since v1.7.3) */
LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress (const char* src, char* dest, int srcSize);
LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress_limitedOutput (const char* src, char* dest, int srcSize, int maxOutputSize);
LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
/*! Obsolete decompression functions (since v1.8.0) */
LZ4_DEPRECATED("use LZ4_decompress_fast() instead") LZ4LIB_API int LZ4_uncompress (const char* source, char* dest, int outputSize);
LZ4_DEPRECATED("use LZ4_decompress_safe() instead") LZ4LIB_API int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize);
/* Obsolete streaming functions (since v1.7.0)
* degraded functionality; do not use!
*
* In order to perform streaming compression, these functions depended on data
* that is no longer tracked in the state. They have been preserved as well as
* possible: using them will still produce a correct output. However, they don't
* actually retain any history between compression calls. The compression ratio
* achieved will therefore be no better than compressing each chunk
* independently.
*/
LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API void* LZ4_create (char* inputBuffer);
LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API int LZ4_sizeofStreamState(void);
LZ4_DEPRECATED("Use LZ4_resetStream() instead") LZ4LIB_API int LZ4_resetStreamState(void* state, char* inputBuffer);
LZ4_DEPRECATED("Use LZ4_saveDict() instead") LZ4LIB_API char* LZ4_slideInputBuffer (void* state);
/*! Obsolete streaming decoding functions (since v1.7.0) */
LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
/*! Obsolete LZ4_decompress_fast variants (since v1.9.0) :
* These functions used to be faster than LZ4_decompress_safe(),
* but this is no longer the case. They are now slower.
* This is because LZ4_decompress_fast() doesn't know the input size,
* and therefore must progress more cautiously into the input buffer to not read beyond the end of block.
* On top of that `LZ4_decompress_fast()` is not protected vs malformed or malicious inputs, making it a security liability.
* As a consequence, LZ4_decompress_fast() is strongly discouraged, and deprecated.
*
* The last remaining LZ4_decompress_fast() specificity is that
* it can decompress a block without knowing its compressed size.
* Such functionality can be achieved in a more secure manner
* by employing LZ4_decompress_safe_partial().
*
* Parameters:
* originalSize : is the uncompressed size to regenerate.
* `dst` must be already allocated, its size must be >= 'originalSize' bytes.
* @return : number of bytes read from source buffer (== compressed size).
* The function expects to finish at block's end exactly.
* If the source stream is detected malformed, the function stops decoding and returns a negative result.
* note : LZ4_decompress_fast*() requires originalSize. Thanks to this information, it never writes past the output buffer.
* However, since it doesn't know its 'src' size, it may read an unknown amount of input, past input buffer bounds.
* Also, since match offsets are not validated, match reads from 'src' may underflow too.
* These issues never happen if input (compressed) data is correct.
* But they may happen if input data is invalid (error or intentional tampering).
* As a consequence, use these functions in trusted environments with trusted data **only**.
*/
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe() instead")
LZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize);
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_continue() instead")
LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int originalSize);
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_usingDict() instead")
LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize, const char* dictStart, int dictSize);
/*! LZ4_resetStream() :
* An LZ4_stream_t structure must be initialized at least once.
* This is done with LZ4_initStream(), or LZ4_resetStream().
* Consider switching to LZ4_initStream(),
* invoking LZ4_resetStream() will trigger deprecation warnings in the future.
*/
LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr);
}
#endif /* LZ4_H_98237428734687 */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,405 @@
/*
LZ4 HC - High Compression Mode of LZ4
Header File
Copyright (C) 2011-2020, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
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.
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.
You can contact the author at :
- LZ4 source repository : https://github.com/lz4/lz4
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
*/
#ifndef TRACY_LZ4_HC_H_19834876238432
#define TRACY_LZ4_HC_H_19834876238432
/* --- Dependency --- */
/* note : lz4hc requires lz4.h/lz4.c for compilation */
#include "tracy_lz4.hpp" /* stddef, LZ4LIB_API, LZ4_DEPRECATED */
/* --- Useful constants --- */
#define LZ4HC_CLEVEL_MIN 3
#define LZ4HC_CLEVEL_DEFAULT 9
#define LZ4HC_CLEVEL_OPT_MIN 10
#define LZ4HC_CLEVEL_MAX 12
namespace tracy
{
/*-************************************
* Block Compression
**************************************/
/*! LZ4_compress_HC() :
* Compress data from `src` into `dst`, using the powerful but slower "HC" algorithm.
* `dst` must be already allocated.
* Compression is guaranteed to succeed if `dstCapacity >= LZ4_compressBound(srcSize)` (see "lz4.h")
* Max supported `srcSize` value is LZ4_MAX_INPUT_SIZE (see "lz4.h")
* `compressionLevel` : any value between 1 and LZ4HC_CLEVEL_MAX will work.
* Values > LZ4HC_CLEVEL_MAX behave the same as LZ4HC_CLEVEL_MAX.
* @return : the number of bytes written into 'dst'
* or 0 if compression fails.
*/
LZ4LIB_API int LZ4_compress_HC (const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel);
/* Note :
* Decompression functions are provided within "lz4.h" (BSD license)
*/
/*! LZ4_compress_HC_extStateHC() :
* Same as LZ4_compress_HC(), but using an externally allocated memory segment for `state`.
* `state` size is provided by LZ4_sizeofStateHC().
* Memory segment must be aligned on 8-bytes boundaries (which a normal malloc() should do properly).
*/
LZ4LIB_API int LZ4_sizeofStateHC(void);
LZ4LIB_API int LZ4_compress_HC_extStateHC(void* stateHC, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel);
/*! LZ4_compress_HC_destSize() : v1.9.0+
* Will compress as much data as possible from `src`
* to fit into `targetDstSize` budget.
* Result is provided in 2 parts :
* @return : the number of bytes written into 'dst' (necessarily <= targetDstSize)
* or 0 if compression fails.
* `srcSizePtr` : on success, *srcSizePtr is updated to indicate how much bytes were read from `src`
*/
LZ4LIB_API int LZ4_compress_HC_destSize(void* stateHC,
const char* src, char* dst,
int* srcSizePtr, int targetDstSize,
int compressionLevel);
/*-************************************
* Streaming Compression
* Bufferless synchronous API
**************************************/
typedef union LZ4_streamHC_u LZ4_streamHC_t; /* incomplete type (defined later) */
/*! LZ4_createStreamHC() and LZ4_freeStreamHC() :
* These functions create and release memory for LZ4 HC streaming state.
* Newly created states are automatically initialized.
* A same state can be used multiple times consecutively,
* starting with LZ4_resetStreamHC_fast() to start a new stream of blocks.
*/
LZ4LIB_API LZ4_streamHC_t* LZ4_createStreamHC(void);
LZ4LIB_API int LZ4_freeStreamHC (LZ4_streamHC_t* streamHCPtr);
/*
These functions compress data in successive blocks of any size,
using previous blocks as dictionary, to improve compression ratio.
One key assumption is that previous blocks (up to 64 KB) remain read-accessible while compressing next blocks.
There is an exception for ring buffers, which can be smaller than 64 KB.
Ring-buffer scenario is automatically detected and handled within LZ4_compress_HC_continue().
Before starting compression, state must be allocated and properly initialized.
LZ4_createStreamHC() does both, though compression level is set to LZ4HC_CLEVEL_DEFAULT.
Selecting the compression level can be done with LZ4_resetStreamHC_fast() (starts a new stream)
or LZ4_setCompressionLevel() (anytime, between blocks in the same stream) (experimental).
LZ4_resetStreamHC_fast() only works on states which have been properly initialized at least once,
which is automatically the case when state is created using LZ4_createStreamHC().
After reset, a first "fictional block" can be designated as initial dictionary,
using LZ4_loadDictHC() (Optional).
Invoke LZ4_compress_HC_continue() to compress each successive block.
The number of blocks is unlimited.
Previous input blocks, including initial dictionary when present,
must remain accessible and unmodified during compression.
It's allowed to update compression level anytime between blocks,
using LZ4_setCompressionLevel() (experimental).
'dst' buffer should be sized to handle worst case scenarios
(see LZ4_compressBound(), it ensures compression success).
In case of failure, the API does not guarantee recovery,
so the state _must_ be reset.
To ensure compression success
whenever `dst` buffer size cannot be made >= LZ4_compressBound(),
consider using LZ4_compress_HC_continue_destSize().
Whenever previous input blocks can't be preserved unmodified in-place during compression of next blocks,
it's possible to copy the last blocks into a more stable memory space, using LZ4_saveDictHC().
Return value of LZ4_saveDictHC() is the size of dictionary effectively saved into 'safeBuffer' (<= 64 KB)
After completing a streaming compression,
it's possible to start a new stream of blocks, using the same LZ4_streamHC_t state,
just by resetting it, using LZ4_resetStreamHC_fast().
*/
LZ4LIB_API void LZ4_resetStreamHC_fast(LZ4_streamHC_t* streamHCPtr, int compressionLevel); /* v1.9.0+ */
LZ4LIB_API int LZ4_loadDictHC (LZ4_streamHC_t* streamHCPtr, const char* dictionary, int dictSize);
LZ4LIB_API int LZ4_compress_HC_continue (LZ4_streamHC_t* streamHCPtr,
const char* src, char* dst,
int srcSize, int maxDstSize);
/*! LZ4_compress_HC_continue_destSize() : v1.9.0+
* Similar to LZ4_compress_HC_continue(),
* but will read as much data as possible from `src`
* to fit into `targetDstSize` budget.
* Result is provided into 2 parts :
* @return : the number of bytes written into 'dst' (necessarily <= targetDstSize)
* or 0 if compression fails.
* `srcSizePtr` : on success, *srcSizePtr will be updated to indicate how much bytes were read from `src`.
* Note that this function may not consume the entire input.
*/
LZ4LIB_API int LZ4_compress_HC_continue_destSize(LZ4_streamHC_t* LZ4_streamHCPtr,
const char* src, char* dst,
int* srcSizePtr, int targetDstSize);
LZ4LIB_API int LZ4_saveDictHC (LZ4_streamHC_t* streamHCPtr, char* safeBuffer, int maxDictSize);
/*^**********************************************
* !!!!!! STATIC LINKING ONLY !!!!!!
***********************************************/
/*-******************************************************************
* PRIVATE DEFINITIONS :
* Do not use these definitions directly.
* They are merely exposed to allow static allocation of `LZ4_streamHC_t`.
* Declare an `LZ4_streamHC_t` directly, rather than any type below.
* Even then, only do so in the context of static linking, as definitions may change between versions.
********************************************************************/
#define LZ4HC_DICTIONARY_LOGSIZE 16
#define LZ4HC_MAXD (1<<LZ4HC_DICTIONARY_LOGSIZE)
#define LZ4HC_MAXD_MASK (LZ4HC_MAXD - 1)
#define LZ4HC_HASH_LOG 15
#define LZ4HC_HASHTABLESIZE (1 << LZ4HC_HASH_LOG)
#define LZ4HC_HASH_MASK (LZ4HC_HASHTABLESIZE - 1)
/* Never ever use these definitions directly !
* Declare or allocate an LZ4_streamHC_t instead.
**/
typedef struct LZ4HC_CCtx_internal LZ4HC_CCtx_internal;
struct LZ4HC_CCtx_internal
{
LZ4_u32 hashTable[LZ4HC_HASHTABLESIZE];
LZ4_u16 chainTable[LZ4HC_MAXD];
const LZ4_byte* end; /* next block here to continue on current prefix */
const LZ4_byte* prefixStart; /* Indexes relative to this position */
const LZ4_byte* dictStart; /* alternate reference for extDict */
LZ4_u32 dictLimit; /* below that point, need extDict */
LZ4_u32 lowLimit; /* below that point, no more dict */
LZ4_u32 nextToUpdate; /* index from which to continue dictionary update */
short compressionLevel;
LZ4_i8 favorDecSpeed; /* favor decompression speed if this flag set,
otherwise, favor compression ratio */
LZ4_i8 dirty; /* stream has to be fully reset if this flag is set */
const LZ4HC_CCtx_internal* dictCtx;
};
#define LZ4_STREAMHC_MINSIZE 262200 /* static size, for inter-version compatibility */
union LZ4_streamHC_u {
char minStateSize[LZ4_STREAMHC_MINSIZE];
LZ4HC_CCtx_internal internal_donotuse;
}; /* previously typedef'd to LZ4_streamHC_t */
/* LZ4_streamHC_t :
* This structure allows static allocation of LZ4 HC streaming state.
* This can be used to allocate statically on stack, or as part of a larger structure.
*
* Such state **must** be initialized using LZ4_initStreamHC() before first use.
*
* Note that invoking LZ4_initStreamHC() is not required when
* the state was created using LZ4_createStreamHC() (which is recommended).
* Using the normal builder, a newly created state is automatically initialized.
*
* Static allocation shall only be used in combination with static linking.
*/
/* LZ4_initStreamHC() : v1.9.0+
* Required before first use of a statically allocated LZ4_streamHC_t.
* Before v1.9.0 : use LZ4_resetStreamHC() instead
*/
LZ4LIB_API LZ4_streamHC_t* LZ4_initStreamHC(void* buffer, size_t size);
/*-************************************
* Deprecated Functions
**************************************/
/* see lz4.h LZ4_DISABLE_DEPRECATE_WARNINGS to turn off deprecation warnings */
/* deprecated compression functions */
LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC (const char* source, char* dest, int inputSize);
LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize);
LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC2 (const char* source, char* dest, int inputSize, int compressionLevel);
LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC_withStateHC (void* state, const char* source, char* dest, int inputSize);
LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC2_withStateHC (void* state, const char* source, char* dest, int inputSize, int compressionLevel);
LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput_withStateHC(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize);
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
/* Obsolete streaming functions; degraded functionality; do not use!
*
* In order to perform streaming compression, these functions depended on data
* that is no longer tracked in the state. They have been preserved as well as
* possible: using them will still produce a correct output. However, use of
* LZ4_slideInputBufferHC() will truncate the history of the stream, rather
* than preserve a window-sized chunk of history.
*/
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API void* LZ4_createHC (const char* inputBuffer);
LZ4_DEPRECATED("use LZ4_freeStreamHC() instead") LZ4LIB_API int LZ4_freeHC (void* LZ4HC_Data);
#endif
LZ4_DEPRECATED("use LZ4_saveDictHC() instead") LZ4LIB_API char* LZ4_slideInputBufferHC (void* LZ4HC_Data);
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel);
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API int LZ4_sizeofStreamStateHC(void);
LZ4_DEPRECATED("use LZ4_initStreamHC() instead") LZ4LIB_API int LZ4_resetStreamStateHC(void* state, char* inputBuffer);
/* LZ4_resetStreamHC() is now replaced by LZ4_initStreamHC().
* The intention is to emphasize the difference with LZ4_resetStreamHC_fast(),
* which is now the recommended function to start a new stream of blocks,
* but cannot be used to initialize a memory segment containing arbitrary garbage data.
*
* It is recommended to switch to LZ4_initStreamHC().
* LZ4_resetStreamHC() will generate deprecation warnings in a future version.
*/
LZ4LIB_API void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionLevel);
}
#endif /* LZ4_HC_H_19834876238432 */
/*-**************************************************
* !!!!! STATIC LINKING ONLY !!!!!
* Following definitions are considered experimental.
* They should not be linked from DLL,
* as there is no guarantee of API stability yet.
* Prototypes will be promoted to "stable" status
* after successful usage in real-life scenarios.
***************************************************/
#ifdef LZ4_HC_STATIC_LINKING_ONLY /* protection macro */
#ifndef TRACY_LZ4_HC_SLO_098092834
#define TRACY_LZ4_HC_SLO_098092834
#define LZ4_STATIC_LINKING_ONLY /* LZ4LIB_STATIC_API */
#include "tracy_lz4.hpp"
namespace tracy
{
/*! LZ4_setCompressionLevel() : v1.8.0+ (experimental)
* It's possible to change compression level
* between successive invocations of LZ4_compress_HC_continue*()
* for dynamic adaptation.
*/
LZ4LIB_STATIC_API void LZ4_setCompressionLevel(
LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel);
/*! LZ4_favorDecompressionSpeed() : v1.8.2+ (experimental)
* Opt. Parser will favor decompression speed over compression ratio.
* Only applicable to levels >= LZ4HC_CLEVEL_OPT_MIN.
*/
LZ4LIB_STATIC_API void LZ4_favorDecompressionSpeed(
LZ4_streamHC_t* LZ4_streamHCPtr, int favor);
/*! LZ4_resetStreamHC_fast() : v1.9.0+
* When an LZ4_streamHC_t is known to be in a internally coherent state,
* it can often be prepared for a new compression with almost no work, only
* sometimes falling back to the full, expensive reset that is always required
* when the stream is in an indeterminate state (i.e., the reset performed by
* LZ4_resetStreamHC()).
*
* LZ4_streamHCs are guaranteed to be in a valid state when:
* - returned from LZ4_createStreamHC()
* - reset by LZ4_resetStreamHC()
* - memset(stream, 0, sizeof(LZ4_streamHC_t))
* - the stream was in a valid state and was reset by LZ4_resetStreamHC_fast()
* - the stream was in a valid state and was then used in any compression call
* that returned success
* - the stream was in an indeterminate state and was used in a compression
* call that fully reset the state (LZ4_compress_HC_extStateHC()) and that
* returned success
*
* Note:
* A stream that was last used in a compression call that returned an error
* may be passed to this function. However, it will be fully reset, which will
* clear any existing history and settings from the context.
*/
LZ4LIB_STATIC_API void LZ4_resetStreamHC_fast(
LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel);
/*! LZ4_compress_HC_extStateHC_fastReset() :
* A variant of LZ4_compress_HC_extStateHC().
*
* Using this variant avoids an expensive initialization step. It is only safe
* to call if the state buffer is known to be correctly initialized already
* (see above comment on LZ4_resetStreamHC_fast() for a definition of
* "correctly initialized"). From a high level, the difference is that this
* function initializes the provided state with a call to
* LZ4_resetStreamHC_fast() while LZ4_compress_HC_extStateHC() starts with a
* call to LZ4_resetStreamHC().
*/
LZ4LIB_STATIC_API int LZ4_compress_HC_extStateHC_fastReset (
void* state,
const char* src, char* dst,
int srcSize, int dstCapacity,
int compressionLevel);
/*! LZ4_attach_HC_dictionary() :
* This is an experimental API that allows for the efficient use of a
* static dictionary many times.
*
* Rather than re-loading the dictionary buffer into a working context before
* each compression, or copying a pre-loaded dictionary's LZ4_streamHC_t into a
* working LZ4_streamHC_t, this function introduces a no-copy setup mechanism,
* in which the working stream references the dictionary stream in-place.
*
* Several assumptions are made about the state of the dictionary stream.
* Currently, only streams which have been prepared by LZ4_loadDictHC() should
* be expected to work.
*
* Alternatively, the provided dictionary stream pointer may be NULL, in which
* case any existing dictionary stream is unset.
*
* A dictionary should only be attached to a stream without any history (i.e.,
* a stream that has just been reset).
*
* The dictionary will remain attached to the working stream only for the
* current stream session. Calls to LZ4_resetStreamHC(_fast) will remove the
* dictionary context association from the working stream. The dictionary
* stream (and source buffer) must remain in-place / accessible / unchanged
* through the lifetime of the stream session.
*/
LZ4LIB_STATIC_API void LZ4_attach_HC_dictionary(
LZ4_streamHC_t *working_stream,
const LZ4_streamHC_t *dictionary_stream);
}
#endif /* LZ4_HC_SLO_098092834 */
#endif /* LZ4_HC_STATIC_LINKING_ONLY */

26
oss/tracy/tracy.vcxproj Normal file
View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{93818413-1073-496a-a599-8450659ba190}</ProjectGuid>
<RootNamespace>tracy</RootNamespace>
<ProjectName>tracy</ProjectName>
<TargetName>tracy</TargetName>
<ConfigurationType>StaticLibrary</ConfigurationType>
</PropertyGroup>
<ItemGroup>
<ClCompile Include="TracyClient.cpp" />
</ItemGroup>
<Import Project="$(SolutionDir)src\common.build.pre.props" />
<Import Project="$(SolutionDir)src\common.nugetversions.props" />
<Import Project="$(SolutionDir)src\common.build.post.props" />
<Import Project="$(SolutionDir)src\common.nugetversions.targets" />
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<TreatSpecificWarningsAsErrors></TreatSpecificWarningsAsErrors>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
</ItemDefinitionGroup>
</Project>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="TracyClient.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

281
oss/tracy/tracy/Tracy.hpp Normal file
View File

@@ -0,0 +1,281 @@
#ifndef __TRACY_HPP__
#define __TRACY_HPP__
#include "../common/TracyColor.hpp"
#include "../common/TracySystem.hpp"
#ifndef TracyFunction
# define TracyFunction __FUNCTION__
#endif
#ifndef TracyFile
# define TracyFile __FILE__
#endif
#ifndef TracyLine
# define TracyLine __LINE__
#endif
#ifndef TRACY_ENABLE
#define ZoneNamed(x,y)
#define ZoneNamedN(x,y,z)
#define ZoneNamedC(x,y,z)
#define ZoneNamedNC(x,y,z,w)
#define ZoneTransient(x,y)
#define ZoneTransientN(x,y,z)
#define ZoneScoped
#define ZoneScopedN(x)
#define ZoneScopedC(x)
#define ZoneScopedNC(x,y)
#define ZoneText(x,y)
#define ZoneTextV(x,y,z)
#define ZoneName(x,y)
#define ZoneNameV(x,y,z)
#define ZoneColor(x)
#define ZoneColorV(x,y)
#define ZoneValue(x)
#define ZoneValueV(x,y)
#define ZoneIsActive false
#define ZoneIsActiveV(x) false
#define FrameMark
#define FrameMarkNamed(x)
#define FrameMarkStart(x)
#define FrameMarkEnd(x)
#define FrameImage(x,y,z,w,a)
#define TracyLockable( type, varname ) type varname
#define TracyLockableN( type, varname, desc ) type varname
#define TracySharedLockable( type, varname ) type varname
#define TracySharedLockableN( type, varname, desc ) type varname
#define LockableBase( type ) type
#define SharedLockableBase( type ) type
#define LockMark(x) (void)x
#define LockableName(x,y,z)
#define TracyPlot(x,y)
#define TracyPlotConfig(x,y,z,w,a)
#define TracyMessage(x,y)
#define TracyMessageL(x)
#define TracyMessageC(x,y,z)
#define TracyMessageLC(x,y)
#define TracyAppInfo(x,y)
#define TracyAlloc(x,y)
#define TracyFree(x)
#define TracySecureAlloc(x,y)
#define TracySecureFree(x)
#define TracyAllocN(x,y,z)
#define TracyFreeN(x,y)
#define TracySecureAllocN(x,y,z)
#define TracySecureFreeN(x,y)
#define ZoneNamedS(x,y,z)
#define ZoneNamedNS(x,y,z,w)
#define ZoneNamedCS(x,y,z,w)
#define ZoneNamedNCS(x,y,z,w,a)
#define ZoneTransientS(x,y,z)
#define ZoneTransientNS(x,y,z,w)
#define ZoneScopedS(x)
#define ZoneScopedNS(x,y)
#define ZoneScopedCS(x,y)
#define ZoneScopedNCS(x,y,z)
#define TracyAllocS(x,y,z)
#define TracyFreeS(x,y)
#define TracySecureAllocS(x,y,z)
#define TracySecureFreeS(x,y)
#define TracyAllocNS(x,y,z,w)
#define TracyFreeNS(x,y,z)
#define TracySecureAllocNS(x,y,z,w)
#define TracySecureFreeNS(x,y,z)
#define TracyMessageS(x,y,z)
#define TracyMessageLS(x,y)
#define TracyMessageCS(x,y,z,w)
#define TracyMessageLCS(x,y,z)
#define TracySourceCallbackRegister(x,y)
#define TracyParameterRegister(x,y)
#define TracyParameterSetup(x,y,z,w)
#define TracyIsConnected false
#define TracyFiberEnter(x)
#define TracyFiberLeave
#else
#include <string.h>
#include "../client/TracyLock.hpp"
#include "../client/TracyProfiler.hpp"
#include "../client/TracyScoped.hpp"
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
# define ZoneNamed( varname, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { nullptr, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), TRACY_CALLSTACK, active )
# define ZoneNamedN( varname, name, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), TRACY_CALLSTACK, active )
# define ZoneNamedC( varname, color, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { nullptr, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), TRACY_CALLSTACK, active )
# define ZoneNamedNC( varname, name, color, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), TRACY_CALLSTACK, active )
# define ZoneTransient( varname, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), nullptr, 0, TRACY_CALLSTACK, active )
# define ZoneTransientN( varname, name, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), TRACY_CALLSTACK, active )
#else
# define ZoneNamed( varname, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { nullptr, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), active )
# define ZoneNamedN( varname, name, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), active )
# define ZoneNamedC( varname, color, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { nullptr, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), active )
# define ZoneNamedNC( varname, name, color, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), active )
# define ZoneTransient( varname, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), nullptr, 0, active )
# define ZoneTransientN( varname, name, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), active )
#endif
#define ZoneScoped ZoneNamed( ___tracy_scoped_zone, true )
#define ZoneScopedN( name ) ZoneNamedN( ___tracy_scoped_zone, name, true )
#define ZoneScopedC( color ) ZoneNamedC( ___tracy_scoped_zone, color, true )
#define ZoneScopedNC( name, color ) ZoneNamedNC( ___tracy_scoped_zone, name, color, true )
#define ZoneText( txt, size ) ___tracy_scoped_zone.Text( txt, size )
#define ZoneTextV( varname, txt, size ) varname.Text( txt, size )
#define ZoneName( txt, size ) ___tracy_scoped_zone.Name( txt, size )
#define ZoneNameV( varname, txt, size ) varname.Name( txt, size )
#define ZoneColor( color ) ___tracy_scoped_zone.Color( color )
#define ZoneColorV( varname, color ) varname.Color( color )
#define ZoneValue( value ) ___tracy_scoped_zone.Value( value )
#define ZoneValueV( varname, value ) varname.Value( value )
#define ZoneIsActive ___tracy_scoped_zone.IsActive()
#define ZoneIsActiveV( varname ) varname.IsActive()
#define FrameMark tracy::Profiler::SendFrameMark( nullptr )
#define FrameMarkNamed( name ) tracy::Profiler::SendFrameMark( name )
#define FrameMarkStart( name ) tracy::Profiler::SendFrameMark( name, tracy::QueueType::FrameMarkMsgStart )
#define FrameMarkEnd( name ) tracy::Profiler::SendFrameMark( name, tracy::QueueType::FrameMarkMsgEnd )
#define FrameImage( image, width, height, offset, flip ) tracy::Profiler::SendFrameImage( image, width, height, offset, flip )
#define TracyLockable( type, varname ) tracy::Lockable<type> varname { [] () -> const tracy::SourceLocationData* { static constexpr tracy::SourceLocationData srcloc { nullptr, #type " " #varname, TracyFile, TracyLine, 0 }; return &srcloc; }() }
#define TracyLockableN( type, varname, desc ) tracy::Lockable<type> varname { [] () -> const tracy::SourceLocationData* { static constexpr tracy::SourceLocationData srcloc { nullptr, desc, TracyFile, TracyLine, 0 }; return &srcloc; }() }
#define TracySharedLockable( type, varname ) tracy::SharedLockable<type> varname { [] () -> const tracy::SourceLocationData* { static constexpr tracy::SourceLocationData srcloc { nullptr, #type " " #varname, TracyFile, TracyLine, 0 }; return &srcloc; }() }
#define TracySharedLockableN( type, varname, desc ) tracy::SharedLockable<type> varname { [] () -> const tracy::SourceLocationData* { static constexpr tracy::SourceLocationData srcloc { nullptr, desc, TracyFile, TracyLine, 0 }; return &srcloc; }() }
#define LockableBase( type ) tracy::Lockable<type>
#define SharedLockableBase( type ) tracy::SharedLockable<type>
#define LockMark( varname ) static constexpr tracy::SourceLocationData __tracy_lock_location_##varname { nullptr, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; varname.Mark( &__tracy_lock_location_##varname )
#define LockableName( varname, txt, size ) varname.CustomName( txt, size )
#define TracyPlot( name, val ) tracy::Profiler::PlotData( name, val )
#define TracyPlotConfig( name, type, step, fill, color ) tracy::Profiler::ConfigurePlot( name, type, step, fill, color )
#define TracyAppInfo( txt, size ) tracy::Profiler::MessageAppInfo( txt, size )
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
# define TracyMessage( txt, size ) tracy::Profiler::Message( txt, size, TRACY_CALLSTACK )
# define TracyMessageL( txt ) tracy::Profiler::Message( txt, TRACY_CALLSTACK )
# define TracyMessageC( txt, size, color ) tracy::Profiler::MessageColor( txt, size, color, TRACY_CALLSTACK )
# define TracyMessageLC( txt, color ) tracy::Profiler::MessageColor( txt, color, TRACY_CALLSTACK )
# define TracyAlloc( ptr, size ) tracy::Profiler::MemAllocCallstack( ptr, size, TRACY_CALLSTACK, false )
# define TracyFree( ptr ) tracy::Profiler::MemFreeCallstack( ptr, TRACY_CALLSTACK, false )
# define TracySecureAlloc( ptr, size ) tracy::Profiler::MemAllocCallstack( ptr, size, TRACY_CALLSTACK, true )
# define TracySecureFree( ptr ) tracy::Profiler::MemFreeCallstack( ptr, TRACY_CALLSTACK, true )
# define TracyAllocN( ptr, size, name ) tracy::Profiler::MemAllocCallstackNamed( ptr, size, TRACY_CALLSTACK, false, name )
# define TracyFreeN( ptr, name ) tracy::Profiler::MemFreeCallstackNamed( ptr, TRACY_CALLSTACK, false, name )
# define TracySecureAllocN( ptr, size, name ) tracy::Profiler::MemAllocCallstackNamed( ptr, size, TRACY_CALLSTACK, true, name )
# define TracySecureFreeN( ptr, name ) tracy::Profiler::MemFreeCallstackNamed( ptr, TRACY_CALLSTACK, true, name )
#else
# define TracyMessage( txt, size ) tracy::Profiler::Message( txt, size, 0 )
# define TracyMessageL( txt ) tracy::Profiler::Message( txt, 0 )
# define TracyMessageC( txt, size, color ) tracy::Profiler::MessageColor( txt, size, color, 0 )
# define TracyMessageLC( txt, color ) tracy::Profiler::MessageColor( txt, color, 0 )
# define TracyAlloc( ptr, size ) tracy::Profiler::MemAlloc( ptr, size, false )
# define TracyFree( ptr ) tracy::Profiler::MemFree( ptr, false )
# define TracySecureAlloc( ptr, size ) tracy::Profiler::MemAlloc( ptr, size, true )
# define TracySecureFree( ptr ) tracy::Profiler::MemFree( ptr, true )
# define TracyAllocN( ptr, size, name ) tracy::Profiler::MemAllocNamed( ptr, size, false, name )
# define TracyFreeN( ptr, name ) tracy::Profiler::MemFreeNamed( ptr, false, name )
# define TracySecureAllocN( ptr, size, name ) tracy::Profiler::MemAllocNamed( ptr, size, true, name )
# define TracySecureFreeN( ptr, name ) tracy::Profiler::MemFreeNamed( ptr, true, name )
#endif
#ifdef TRACY_HAS_CALLSTACK
# define ZoneNamedS( varname, depth, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { nullptr, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), depth, active )
# define ZoneNamedNS( varname, name, depth, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), depth, active )
# define ZoneNamedCS( varname, color, depth, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { nullptr, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), depth, active )
# define ZoneNamedNCS( varname, name, color, depth, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), depth, active )
# define ZoneTransientS( varname, depth, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), nullptr, 0, depth, active )
# define ZoneTransientNS( varname, name, depth, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), depth, active )
# define ZoneScopedS( depth ) ZoneNamedS( ___tracy_scoped_zone, depth, true )
# define ZoneScopedNS( name, depth ) ZoneNamedNS( ___tracy_scoped_zone, name, depth, true )
# define ZoneScopedCS( color, depth ) ZoneNamedCS( ___tracy_scoped_zone, color, depth, true )
# define ZoneScopedNCS( name, color, depth ) ZoneNamedNCS( ___tracy_scoped_zone, name, color, depth, true )
# define TracyAllocS( ptr, size, depth ) tracy::Profiler::MemAllocCallstack( ptr, size, depth, false )
# define TracyFreeS( ptr, depth ) tracy::Profiler::MemFreeCallstack( ptr, depth, false )
# define TracySecureAllocS( ptr, size, depth ) tracy::Profiler::MemAllocCallstack( ptr, size, depth, true )
# define TracySecureFreeS( ptr, depth ) tracy::Profiler::MemFreeCallstack( ptr, depth, true )
# define TracyAllocNS( ptr, size, depth, name ) tracy::Profiler::MemAllocCallstackNamed( ptr, size, depth, false, name )
# define TracyFreeNS( ptr, depth, name ) tracy::Profiler::MemFreeCallstackNamed( ptr, depth, false, name )
# define TracySecureAllocNS( ptr, size, depth, name ) tracy::Profiler::MemAllocCallstackNamed( ptr, size, depth, true, name )
# define TracySecureFreeNS( ptr, depth, name ) tracy::Profiler::MemFreeCallstackNamed( ptr, depth, true, name )
# define TracyMessageS( txt, size, depth ) tracy::Profiler::Message( txt, size, depth )
# define TracyMessageLS( txt, depth ) tracy::Profiler::Message( txt, depth )
# define TracyMessageCS( txt, size, color, depth ) tracy::Profiler::MessageColor( txt, size, color, depth )
# define TracyMessageLCS( txt, color, depth ) tracy::Profiler::MessageColor( txt, color, depth )
#else
# define ZoneNamedS( varname, depth, active ) ZoneNamed( varname, active )
# define ZoneNamedNS( varname, name, depth, active ) ZoneNamedN( varname, name, active )
# define ZoneNamedCS( varname, color, depth, active ) ZoneNamedC( varname, color, active )
# define ZoneNamedNCS( varname, name, color, depth, active ) ZoneNamedNC( varname, name, color, active )
# define ZoneTransientS( varname, depth, active ) ZoneTransient( varname, active )
# define ZoneTransientNS( varname, name, depth, active ) ZoneTransientN( varname, name, active )
# define ZoneScopedS( depth ) ZoneScoped
# define ZoneScopedNS( name, depth ) ZoneScopedN( name )
# define ZoneScopedCS( color, depth ) ZoneScopedC( color )
# define ZoneScopedNCS( name, color, depth ) ZoneScopedNC( name, color )
# define TracyAllocS( ptr, size, depth ) TracyAlloc( ptr, size )
# define TracyFreeS( ptr, depth ) TracyFree( ptr )
# define TracySecureAllocS( ptr, size, depth ) TracySecureAlloc( ptr, size )
# define TracySecureFreeS( ptr, depth ) TracySecureFree( ptr )
# define TracyAllocNS( ptr, size, depth, name ) TracyAllocN( ptr, size, name )
# define TracyFreeNS( ptr, depth, name ) TracyFreeN( ptr, name )
# define TracySecureAllocNS( ptr, size, depth, name ) TracySecureAllocN( ptr, size, name )
# define TracySecureFreeNS( ptr, depth, name ) TracySecureFreeN( ptr, name )
# define TracyMessageS( txt, size, depth ) TracyMessage( txt, size )
# define TracyMessageLS( txt, depth ) TracyMessageL( txt )
# define TracyMessageCS( txt, size, color, depth ) TracyMessageC( txt, size, color )
# define TracyMessageLCS( txt, color, depth ) TracyMessageLC( txt, color )
#endif
#define TracySourceCallbackRegister( cb, data ) tracy::Profiler::SourceCallbackRegister( cb, data )
#define TracyParameterRegister( cb, data ) tracy::Profiler::ParameterRegister( cb, data )
#define TracyParameterSetup( idx, name, isBool, val ) tracy::Profiler::ParameterSetup( idx, name, isBool, val )
#define TracyIsConnected tracy::GetProfiler().IsConnected()
#ifdef TRACY_FIBERS
# define TracyFiberEnter( fiber ) tracy::Profiler::EnterFiber( fiber )
# define TracyFiberLeave tracy::Profiler::LeaveFiber()
#endif
#endif
#endif

358
oss/tracy/tracy/TracyC.h Normal file
View File

@@ -0,0 +1,358 @@
#ifndef __TRACYC_HPP__
#define __TRACYC_HPP__
#include <stddef.h>
#include <stdint.h>
#include "../client/TracyCallstack.h"
#include "../common/TracyApi.h"
#ifdef __cplusplus
extern "C" {
#endif
TRACY_API void ___tracy_set_thread_name( const char* name );
#define TracyCSetThreadName( name ) ___tracy_set_thread_name( name );
#ifndef TracyFunction
# define TracyFunction __FUNCTION__
#endif
#ifndef TracyFile
# define TracyFile __FILE__
#endif
#ifndef TracyLine
# define TracyLine __LINE__
#endif
#ifndef TRACY_ENABLE
typedef const void* TracyCZoneCtx;
#define TracyCZone(c,x)
#define TracyCZoneN(c,x,y)
#define TracyCZoneC(c,x,y)
#define TracyCZoneNC(c,x,y,z)
#define TracyCZoneEnd(c)
#define TracyCZoneText(c,x,y)
#define TracyCZoneName(c,x,y)
#define TracyCZoneColor(c,x)
#define TracyCZoneValue(c,x)
#define TracyCAlloc(x,y)
#define TracyCFree(x)
#define TracyCSecureAlloc(x,y)
#define TracyCSecureFree(x)
#define TracyCAllocN(x,y,z)
#define TracyCFreeN(x,y)
#define TracyCSecureAllocN(x,y,z)
#define TracyCSecureFreeN(x,y)
#define TracyCFrameMark
#define TracyCFrameMarkNamed(x)
#define TracyCFrameMarkStart(x)
#define TracyCFrameMarkEnd(x)
#define TracyCFrameImage(x,y,z,w,a)
#define TracyCPlot(x,y)
#define TracyCPlotF(x,y)
#define TracyCPlotI(x,y)
#define TracyCMessage(x,y)
#define TracyCMessageL(x)
#define TracyCMessageC(x,y,z)
#define TracyCMessageLC(x,y)
#define TracyCAppInfo(x,y)
#define TracyCZoneS(x,y,z)
#define TracyCZoneNS(x,y,z,w)
#define TracyCZoneCS(x,y,z,w)
#define TracyCZoneNCS(x,y,z,w,a)
#define TracyCAllocS(x,y,z)
#define TracyCFreeS(x,y)
#define TracyCSecureAllocS(x,y,z)
#define TracyCSecureFreeS(x,y)
#define TracyCAllocNS(x,y,z,w)
#define TracyCFreeNS(x,y,z)
#define TracyCSecureAllocNS(x,y,z,w)
#define TracyCSecureFreeNS(x,y,z)
#define TracyCMessageS(x,y,z)
#define TracyCMessageLS(x,y)
#define TracyCMessageCS(x,y,z,w)
#define TracyCMessageLCS(x,y,z)
#define TracyCIsConnected 0
#ifdef TRACY_FIBERS
# define TracyCFiberEnter(fiber)
# define TracyCFiberLeave
#endif
#else
#ifndef TracyConcat
# define TracyConcat(x,y) TracyConcatIndirect(x,y)
#endif
#ifndef TracyConcatIndirect
# define TracyConcatIndirect(x,y) x##y
#endif
struct ___tracy_source_location_data
{
const char* name;
const char* function;
const char* file;
uint32_t line;
uint32_t color;
};
struct ___tracy_c_zone_context
{
uint32_t id;
int active;
};
struct ___tracy_gpu_time_data
{
int64_t gpuTime;
uint16_t queryId;
uint8_t context;
};
struct ___tracy_gpu_zone_begin_data {
uint64_t srcloc;
uint16_t queryId;
uint8_t context;
};
struct ___tracy_gpu_zone_begin_callstack_data {
uint64_t srcloc;
int depth;
uint16_t queryId;
uint8_t context;
};
struct ___tracy_gpu_zone_end_data {
uint16_t queryId;
uint8_t context;
};
struct ___tracy_gpu_new_context_data {
int64_t gpuTime;
float period;
uint8_t context;
uint8_t flags;
uint8_t type;
};
struct ___tracy_gpu_context_name_data {
uint8_t context;
const char* name;
uint16_t len;
};
struct ___tracy_gpu_calibration_data {
int64_t gpuTime;
int64_t cpuDelta;
uint8_t context;
};
// Some containers don't support storing const types.
// This struct, as visible to user, is immutable, so treat it as if const was declared here.
typedef /*const*/ struct ___tracy_c_zone_context TracyCZoneCtx;
#ifdef TRACY_MANUAL_LIFETIME
TRACY_API void ___tracy_startup_profiler(void);
TRACY_API void ___tracy_shutdown_profiler(void);
#endif
TRACY_API uint64_t ___tracy_alloc_srcloc( uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz );
TRACY_API uint64_t ___tracy_alloc_srcloc_name( uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz );
TRACY_API TracyCZoneCtx ___tracy_emit_zone_begin( const struct ___tracy_source_location_data* srcloc, int active );
TRACY_API TracyCZoneCtx ___tracy_emit_zone_begin_callstack( const struct ___tracy_source_location_data* srcloc, int depth, int active );
TRACY_API TracyCZoneCtx ___tracy_emit_zone_begin_alloc( uint64_t srcloc, int active );
TRACY_API TracyCZoneCtx ___tracy_emit_zone_begin_alloc_callstack( uint64_t srcloc, int depth, int active );
TRACY_API void ___tracy_emit_zone_end( TracyCZoneCtx ctx );
TRACY_API void ___tracy_emit_zone_text( TracyCZoneCtx ctx, const char* txt, size_t size );
TRACY_API void ___tracy_emit_zone_name( TracyCZoneCtx ctx, const char* txt, size_t size );
TRACY_API void ___tracy_emit_zone_color( TracyCZoneCtx ctx, uint32_t color );
TRACY_API void ___tracy_emit_zone_value( TracyCZoneCtx ctx, uint64_t value );
TRACY_API void ___tracy_emit_gpu_zone_begin( const struct ___tracy_gpu_zone_begin_data );
TRACY_API void ___tracy_emit_gpu_zone_begin_callstack( const struct ___tracy_gpu_zone_begin_callstack_data );
TRACY_API void ___tracy_emit_gpu_zone_begin_alloc( const struct ___tracy_gpu_zone_begin_data );
TRACY_API void ___tracy_emit_gpu_zone_begin_alloc_callstack( const struct ___tracy_gpu_zone_begin_callstack_data );
TRACY_API void ___tracy_emit_gpu_zone_end( const struct ___tracy_gpu_zone_end_data data );
TRACY_API void ___tracy_emit_gpu_time( const struct ___tracy_gpu_time_data );
TRACY_API void ___tracy_emit_gpu_new_context( const struct ___tracy_gpu_new_context_data );
TRACY_API void ___tracy_emit_gpu_context_name( const struct ___tracy_gpu_context_name_data );
TRACY_API void ___tracy_emit_gpu_calibration( const struct ___tracy_gpu_calibration_data );
TRACY_API void ___tracy_emit_gpu_zone_begin_serial( const struct ___tracy_gpu_zone_begin_data );
TRACY_API void ___tracy_emit_gpu_zone_begin_callstack_serial( const struct ___tracy_gpu_zone_begin_callstack_data );
TRACY_API void ___tracy_emit_gpu_zone_begin_alloc_serial( const struct ___tracy_gpu_zone_begin_data );
TRACY_API void ___tracy_emit_gpu_zone_begin_alloc_callstack_serial( const struct ___tracy_gpu_zone_begin_callstack_data );
TRACY_API void ___tracy_emit_gpu_zone_end_serial( const struct ___tracy_gpu_zone_end_data data );
TRACY_API void ___tracy_emit_gpu_time_serial( const struct ___tracy_gpu_time_data );
TRACY_API void ___tracy_emit_gpu_new_context_serial( const struct ___tracy_gpu_new_context_data );
TRACY_API void ___tracy_emit_gpu_context_name_serial( const struct ___tracy_gpu_context_name_data );
TRACY_API void ___tracy_emit_gpu_calibration_serial( const struct ___tracy_gpu_calibration_data );
TRACY_API int ___tracy_connected(void);
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
# define TracyCZone( ctx, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { NULL, __func__, TracyFile, (uint32_t)TracyLine, 0 }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,TracyLine), TRACY_CALLSTACK, active );
# define TracyCZoneN( ctx, name, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { name, __func__, TracyFile, (uint32_t)TracyLine, 0 }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,TracyLine), TRACY_CALLSTACK, active );
# define TracyCZoneC( ctx, color, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { NULL, __func__, TracyFile, (uint32_t)TracyLine, color }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,TracyLine), TRACY_CALLSTACK, active );
# define TracyCZoneNC( ctx, name, color, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { name, __func__, TracyFile, (uint32_t)TracyLine, color }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,TracyLine), TRACY_CALLSTACK, active );
#else
# define TracyCZone( ctx, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { NULL, __func__, TracyFile, (uint32_t)TracyLine, 0 }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin( &TracyConcat(__tracy_source_location,TracyLine), active );
# define TracyCZoneN( ctx, name, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { name, __func__, TracyFile, (uint32_t)TracyLine, 0 }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin( &TracyConcat(__tracy_source_location,TracyLine), active );
# define TracyCZoneC( ctx, color, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { NULL, __func__, TracyFile, (uint32_t)TracyLine, color }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin( &TracyConcat(__tracy_source_location,TracyLine), active );
# define TracyCZoneNC( ctx, name, color, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { name, __func__, TracyFile, (uint32_t)TracyLine, color }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin( &TracyConcat(__tracy_source_location,TracyLine), active );
#endif
#define TracyCZoneEnd( ctx ) ___tracy_emit_zone_end( ctx );
#define TracyCZoneText( ctx, txt, size ) ___tracy_emit_zone_text( ctx, txt, size );
#define TracyCZoneName( ctx, txt, size ) ___tracy_emit_zone_name( ctx, txt, size );
#define TracyCZoneColor( ctx, color ) ___tracy_emit_zone_color( ctx, color );
#define TracyCZoneValue( ctx, value ) ___tracy_emit_zone_value( ctx, value );
TRACY_API void ___tracy_emit_memory_alloc( const void* ptr, size_t size, int secure );
TRACY_API void ___tracy_emit_memory_alloc_callstack( const void* ptr, size_t size, int depth, int secure );
TRACY_API void ___tracy_emit_memory_free( const void* ptr, int secure );
TRACY_API void ___tracy_emit_memory_free_callstack( const void* ptr, int depth, int secure );
TRACY_API void ___tracy_emit_memory_alloc_named( const void* ptr, size_t size, int secure, const char* name );
TRACY_API void ___tracy_emit_memory_alloc_callstack_named( const void* ptr, size_t size, int depth, int secure, const char* name );
TRACY_API void ___tracy_emit_memory_free_named( const void* ptr, int secure, const char* name );
TRACY_API void ___tracy_emit_memory_free_callstack_named( const void* ptr, int depth, int secure, const char* name );
TRACY_API void ___tracy_emit_message( const char* txt, size_t size, int callstack );
TRACY_API void ___tracy_emit_messageL( const char* txt, int callstack );
TRACY_API void ___tracy_emit_messageC( const char* txt, size_t size, uint32_t color, int callstack );
TRACY_API void ___tracy_emit_messageLC( const char* txt, uint32_t color, int callstack );
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
# define TracyCAlloc( ptr, size ) ___tracy_emit_memory_alloc_callstack( ptr, size, TRACY_CALLSTACK, 0 )
# define TracyCFree( ptr ) ___tracy_emit_memory_free_callstack( ptr, TRACY_CALLSTACK, 0 )
# define TracyCSecureAlloc( ptr, size ) ___tracy_emit_memory_alloc_callstack( ptr, size, TRACY_CALLSTACK, 1 )
# define TracyCSecureFree( ptr ) ___tracy_emit_memory_free_callstack( ptr, TRACY_CALLSTACK, 1 )
# define TracyCAllocN( ptr, size, name ) ___tracy_emit_memory_alloc_callstack_named( ptr, size, TRACY_CALLSTACK, 0, name )
# define TracyCFreeN( ptr, name ) ___tracy_emit_memory_free_callstack_named( ptr, TRACY_CALLSTACK, 0, name )
# define TracyCSecureAllocN( ptr, size, name ) ___tracy_emit_memory_alloc_callstack_named( ptr, size, TRACY_CALLSTACK, 1, name )
# define TracyCSecureFreeN( ptr, name ) ___tracy_emit_memory_free_callstack_named( ptr, TRACY_CALLSTACK, 1, name )
# define TracyCMessage( txt, size ) ___tracy_emit_message( txt, size, TRACY_CALLSTACK );
# define TracyCMessageL( txt ) ___tracy_emit_messageL( txt, TRACY_CALLSTACK );
# define TracyCMessageC( txt, size, color ) ___tracy_emit_messageC( txt, size, color, TRACY_CALLSTACK );
# define TracyCMessageLC( txt, color ) ___tracy_emit_messageLC( txt, color, TRACY_CALLSTACK );
#else
# define TracyCAlloc( ptr, size ) ___tracy_emit_memory_alloc( ptr, size, 0 );
# define TracyCFree( ptr ) ___tracy_emit_memory_free( ptr, 0 );
# define TracyCSecureAlloc( ptr, size ) ___tracy_emit_memory_alloc( ptr, size, 1 );
# define TracyCSecureFree( ptr ) ___tracy_emit_memory_free( ptr, 1 );
# define TracyCAllocN( ptr, size, name ) ___tracy_emit_memory_alloc_named( ptr, size, 0, name );
# define TracyCFreeN( ptr, name ) ___tracy_emit_memory_free_named( ptr, 0, name );
# define TracyCSecureAllocN( ptr, size, name ) ___tracy_emit_memory_alloc_named( ptr, size, 1, name );
# define TracyCSecureFreeN( ptr, name ) ___tracy_emit_memory_free_named( ptr, 1, name );
# define TracyCMessage( txt, size ) ___tracy_emit_message( txt, size, 0 );
# define TracyCMessageL( txt ) ___tracy_emit_messageL( txt, 0 );
# define TracyCMessageC( txt, size, color ) ___tracy_emit_messageC( txt, size, color, 0 );
# define TracyCMessageLC( txt, color ) ___tracy_emit_messageLC( txt, color, 0 );
#endif
TRACY_API void ___tracy_emit_frame_mark( const char* name );
TRACY_API void ___tracy_emit_frame_mark_start( const char* name );
TRACY_API void ___tracy_emit_frame_mark_end( const char* name );
TRACY_API void ___tracy_emit_frame_image( const void* image, uint16_t w, uint16_t h, uint8_t offset, int flip );
#define TracyCFrameMark ___tracy_emit_frame_mark( 0 );
#define TracyCFrameMarkNamed( name ) ___tracy_emit_frame_mark( name );
#define TracyCFrameMarkStart( name ) ___tracy_emit_frame_mark_start( name );
#define TracyCFrameMarkEnd( name ) ___tracy_emit_frame_mark_end( name );
#define TracyCFrameImage( image, width, height, offset, flip ) ___tracy_emit_frame_image( image, width, height, offset, flip );
TRACY_API void ___tracy_emit_plot( const char* name, double val );
TRACY_API void ___tracy_emit_plot_float( const char* name, float val );
TRACY_API void ___tracy_emit_plot_int( const char* name, int64_t val );
TRACY_API void ___tracy_emit_message_appinfo( const char* txt, size_t size );
#define TracyCPlot( name, val ) ___tracy_emit_plot( name, val );
#define TracyCPlotF( name, val ) ___tracy_emit_plot_float( name, val );
#define TracyCPlotI( name, val ) ___tracy_emit_plot_int( name, val );
#define TracyCAppInfo( txt, size ) ___tracy_emit_message_appinfo( txt, size );
#ifdef TRACY_HAS_CALLSTACK
# define TracyCZoneS( ctx, depth, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { NULL, __func__, TracyFile, (uint32_t)TracyLine, 0 }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,TracyLine), depth, active );
# define TracyCZoneNS( ctx, name, depth, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { name, __func__, TracyFile, (uint32_t)TracyLine, 0 }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,TracyLine), depth, active );
# define TracyCZoneCS( ctx, color, depth, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { NULL, __func__, TracyFile, (uint32_t)TracyLine, color }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,TracyLine), depth, active );
# define TracyCZoneNCS( ctx, name, color, depth, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { name, __func__, TracyFile, (uint32_t)TracyLine, color }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,TracyLine), depth, active );
# define TracyCAllocS( ptr, size, depth ) ___tracy_emit_memory_alloc_callstack( ptr, size, depth, 0 )
# define TracyCFreeS( ptr, depth ) ___tracy_emit_memory_free_callstack( ptr, depth, 0 )
# define TracyCSecureAllocS( ptr, size, depth ) ___tracy_emit_memory_alloc_callstack( ptr, size, depth, 1 )
# define TracyCSecureFreeS( ptr, depth ) ___tracy_emit_memory_free_callstack( ptr, depth, 1 )
# define TracyCAllocNS( ptr, size, depth, name ) ___tracy_emit_memory_alloc_callstack_named( ptr, size, depth, 0, name )
# define TracyCFreeNS( ptr, depth, name ) ___tracy_emit_memory_free_callstack_named( ptr, depth, 0, name )
# define TracyCSecureAllocNS( ptr, size, depth, name ) ___tracy_emit_memory_alloc_callstack_named( ptr, size, depth, 1, name )
# define TracyCSecureFreeNS( ptr, depth, name ) ___tracy_emit_memory_free_callstack_named( ptr, depth, 1, name )
# define TracyCMessageS( txt, size, depth ) ___tracy_emit_message( txt, size, depth );
# define TracyCMessageLS( txt, depth ) ___tracy_emit_messageL( txt, depth );
# define TracyCMessageCS( txt, size, color, depth ) ___tracy_emit_messageC( txt, size, color, depth );
# define TracyCMessageLCS( txt, color, depth ) ___tracy_emit_messageLC( txt, color, depth );
#else
# define TracyCZoneS( ctx, depth, active ) TracyCZone( ctx, active )
# define TracyCZoneNS( ctx, name, depth, active ) TracyCZoneN( ctx, name, active )
# define TracyCZoneCS( ctx, color, depth, active ) TracyCZoneC( ctx, color, active )
# define TracyCZoneNCS( ctx, name, color, depth, active ) TracyCZoneNC( ctx, name, color, active )
# define TracyCAllocS( ptr, size, depth ) TracyCAlloc( ptr, size )
# define TracyCFreeS( ptr, depth ) TracyCFree( ptr )
# define TracyCSecureAllocS( ptr, size, depth ) TracyCSecureAlloc( ptr, size )
# define TracyCSecureFreeS( ptr, depth ) TracyCSecureFree( ptr )
# define TracyCAllocNS( ptr, size, depth, name ) TracyCAllocN( ptr, size, name )
# define TracyCFreeNS( ptr, depth, name ) TracyCFreeN( ptr, name )
# define TracyCSecureAllocNS( ptr, size, depth, name ) TracyCSecureAllocN( ptr, size, name )
# define TracyCSecureFreeNS( ptr, depth, name ) TracyCSecureFreeN( ptr, name )
# define TracyCMessageS( txt, size, depth ) TracyCMessage( txt, size )
# define TracyCMessageLS( txt, depth ) TracyCMessageL( txt )
# define TracyCMessageCS( txt, size, color, depth ) TracyCMessageC( txt, size, color )
# define TracyCMessageLCS( txt, color, depth ) TracyCMessageLC( txt, color )
#endif
#define TracyCIsConnected ___tracy_connected()
#ifdef TRACY_FIBERS
TRACY_API void ___tracy_fiber_enter( const char* fiber );
TRACY_API void ___tracy_fiber_leave( void );
# define TracyCFiberEnter( fiber ) ___tracy_fiber_enter( fiber );
# define TracyCFiberLeave ___tracy_fiber_leave();
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,444 @@
#ifndef __TRACYD3D11_HPP__
#define __TRACYD3D11_HPP__
#ifndef TRACY_ENABLE
#define TracyD3D11Context(device,queue) nullptr
#define TracyD3D11Destroy(ctx)
#define TracyD3D11ContextName(ctx, name, size)
#define TracyD3D11NewFrame(ctx)
#define TracyD3D11Zone(ctx, name)
#define TracyD3D11ZoneC(ctx, name, color)
#define TracyD3D11NamedZone(ctx, varname, name, active)
#define TracyD3D11NamedZoneC(ctx, varname, name, color, active)
#define TracyD3D12ZoneTransient(ctx, varname, name, active)
#define TracyD3D11ZoneS(ctx, name, depth)
#define TracyD3D11ZoneCS(ctx, name, color, depth)
#define TracyD3D11NamedZoneS(ctx, varname, name, depth, active)
#define TracyD3D11NamedZoneCS(ctx, varname, name, color, depth, active)
#define TracyD3D12ZoneTransientS(ctx, varname, name, depth, active)
#define TracyD3D11Collect(ctx)
namespace tracy
{
class D3D11ZoneScope {};
}
using TracyD3D11Ctx = void*;
#else
#include <atomic>
#include <assert.h>
#include <stdlib.h>
#include "Tracy.hpp"
#include "../client/TracyProfiler.hpp"
#include "../client/TracyCallstack.hpp"
#include "../common/TracyAlign.hpp"
#include "../common/TracyAlloc.hpp"
#include <d3d11.h>
namespace tracy
{
class D3D11Ctx
{
friend class D3D11ZoneScope;
enum { QueryCount = 64 * 1024 };
public:
D3D11Ctx( ID3D11Device* device, ID3D11DeviceContext* devicectx )
: m_device( device )
, m_devicectx( devicectx )
, m_context( GetGpuCtxCounter().fetch_add( 1, std::memory_order_relaxed ) )
, m_head( 0 )
, m_tail( 0 )
{
assert( m_context != 255 );
for (int i = 0; i < QueryCount; i++)
{
HRESULT hr = S_OK;
D3D11_QUERY_DESC desc;
desc.MiscFlags = 0;
desc.Query = D3D11_QUERY_TIMESTAMP;
hr |= device->CreateQuery(&desc, &m_queries[i]);
desc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
hr |= device->CreateQuery(&desc, &m_disjoints[i]);
m_disjointMap[i] = nullptr;
assert(SUCCEEDED(hr));
}
// Force query the initial GPU timestamp (pipeline stall)
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjoint;
UINT64 timestamp;
for (int attempts = 0; attempts < 50; attempts++)
{
devicectx->Begin(m_disjoints[0]);
devicectx->End(m_queries[0]);
devicectx->End(m_disjoints[0]);
devicectx->Flush();
while (devicectx->GetData(m_disjoints[0], &disjoint, sizeof(disjoint), 0) == S_FALSE)
/* Nothing */;
if (disjoint.Disjoint)
continue;
while (devicectx->GetData(m_queries[0], &timestamp, sizeof(timestamp), 0) == S_FALSE)
/* Nothing */;
break;
}
int64_t tgpu = timestamp * (1000000000ull / disjoint.Frequency);
int64_t tcpu = Profiler::GetTime();
uint8_t flags = 0;
const float period = 1.f;
auto* item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::GpuNewContext );
MemWrite( &item->gpuNewContext.cpuTime, tcpu );
MemWrite( &item->gpuNewContext.gpuTime, tgpu );
memset(&item->gpuNewContext.thread, 0, sizeof(item->gpuNewContext.thread));
MemWrite( &item->gpuNewContext.period, period );
MemWrite( &item->gpuNewContext.context, m_context );
MemWrite( &item->gpuNewContext.flags, flags );
MemWrite( &item->gpuNewContext.type, GpuContextType::Direct3D11 );
#ifdef TRACY_ON_DEMAND
GetProfiler().DeferItem( *item );
#endif
Profiler::QueueSerialFinish();
}
~D3D11Ctx()
{
for (int i = 0; i < QueryCount; i++)
{
m_queries[i]->Release();
m_disjoints[i]->Release();
m_disjointMap[i] = nullptr;
}
}
void Name( const char* name, uint16_t len )
{
auto ptr = (char*)tracy_malloc( len );
memcpy( ptr, name, len );
auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::GpuContextName );
MemWrite( &item->gpuContextNameFat.context, m_context );
MemWrite( &item->gpuContextNameFat.ptr, (uint64_t)ptr );
MemWrite( &item->gpuContextNameFat.size, len );
#ifdef TRACY_ON_DEMAND
GetProfiler().DeferItem( *item );
#endif
Profiler::QueueSerialFinish();
}
void Collect()
{
ZoneScopedC( Color::Red4 );
if( m_tail == m_head ) return;
#ifdef TRACY_ON_DEMAND
if( !GetProfiler().IsConnected() )
{
m_head = m_tail = 0;
return;
}
#endif
auto start = m_tail;
auto end = m_head + QueryCount;
auto cnt = (end - start) % QueryCount;
while (cnt > 1)
{
auto mid = start + cnt / 2;
bool available =
m_devicectx->GetData(m_disjointMap[mid % QueryCount], nullptr, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK &&
m_devicectx->GetData(m_queries[mid % QueryCount], nullptr, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
if (available)
{
start = mid;
}
else
{
end = mid;
}
cnt = (end - start) % QueryCount;
}
start %= QueryCount;
while (m_tail != start)
{
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjoint;
UINT64 time;
m_devicectx->GetData(m_disjointMap[m_tail], &disjoint, sizeof(disjoint), 0);
m_devicectx->GetData(m_queries[m_tail], &time, sizeof(time), 0);
time *= (1000000000ull / disjoint.Frequency);
auto* item = Profiler::QueueSerial();
MemWrite(&item->hdr.type, QueueType::GpuTime);
MemWrite(&item->gpuTime.gpuTime, (int64_t)time);
MemWrite(&item->gpuTime.queryId, (uint16_t)m_tail);
MemWrite(&item->gpuTime.context, m_context);
Profiler::QueueSerialFinish();
m_tail = (m_tail + 1) % QueryCount;
}
}
private:
tracy_force_inline unsigned int NextQueryId()
{
const auto id = m_head;
m_head = ( m_head + 1 ) % QueryCount;
assert( m_head != m_tail );
return id;
}
tracy_force_inline ID3D11Query* TranslateQueryId( unsigned int id )
{
return m_queries[id];
}
tracy_force_inline ID3D11Query* MapDisjointQueryId( unsigned int id, unsigned int disjointId )
{
m_disjointMap[id] = m_disjoints[disjointId];
return m_disjoints[disjointId];
}
tracy_force_inline uint8_t GetId() const
{
return m_context;
}
ID3D11Device* m_device;
ID3D11DeviceContext* m_devicectx;
ID3D11Query* m_queries[QueryCount];
ID3D11Query* m_disjoints[QueryCount];
ID3D11Query* m_disjointMap[QueryCount]; // Multiple time queries can have one disjoint query
uint8_t m_context;
unsigned int m_head;
unsigned int m_tail;
};
class D3D11ZoneScope
{
public:
tracy_force_inline D3D11ZoneScope( D3D11Ctx* ctx, const SourceLocationData* srcloc, bool is_active )
#ifdef TRACY_ON_DEMAND
: m_active( is_active && GetProfiler().IsConnected() )
#else
: m_active( is_active )
#endif
{
if( !m_active ) return;
m_ctx = ctx;
const auto queryId = ctx->NextQueryId();
ctx->m_devicectx->Begin(ctx->MapDisjointQueryId(queryId, queryId));
ctx->m_devicectx->End(ctx->TranslateQueryId(queryId));
m_disjointId = queryId;
auto* item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::GpuZoneBeginSerial );
MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );
MemWrite( &item->gpuZoneBegin.srcloc, (uint64_t)srcloc );
MemWrite( &item->gpuZoneBegin.thread, GetThreadHandle() );
MemWrite( &item->gpuZoneBegin.queryId, uint16_t( queryId ) );
MemWrite( &item->gpuZoneBegin.context, ctx->GetId() );
Profiler::QueueSerialFinish();
}
tracy_force_inline D3D11ZoneScope( D3D11Ctx* ctx, const SourceLocationData* srcloc, int depth, bool is_active )
#ifdef TRACY_ON_DEMAND
: m_active( is_active && GetProfiler().IsConnected() )
#else
: m_active( is_active )
#endif
{
if( !m_active ) return;
m_ctx = ctx;
const auto queryId = ctx->NextQueryId();
ctx->m_devicectx->Begin(ctx->MapDisjointQueryId(queryId, queryId));
ctx->m_devicectx->End(ctx->TranslateQueryId(queryId));
m_disjointId = queryId;
auto* item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::GpuZoneBeginCallstackSerial );
MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );
MemWrite( &item->gpuZoneBegin.srcloc, (uint64_t)srcloc );
MemWrite( &item->gpuZoneBegin.thread, GetThreadHandle() );
MemWrite( &item->gpuZoneBegin.queryId, uint16_t( queryId ) );
MemWrite( &item->gpuZoneBegin.context, ctx->GetId() );
Profiler::QueueSerialFinish();
GetProfiler().SendCallstack( depth );
}
tracy_force_inline D3D11ZoneScope(D3D11Ctx* ctx, uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, bool active)
#ifdef TRACY_ON_DEMAND
: m_active(active&& GetProfiler().IsConnected())
#else
: m_active(active)
#endif
{
if( !m_active ) return;
m_ctx = ctx;
const auto queryId = ctx->NextQueryId();
ctx->m_devicectx->Begin(ctx->MapDisjointQueryId(queryId, queryId));
ctx->m_devicectx->End(ctx->TranslateQueryId(queryId));
m_disjointId = queryId;
const auto sourceLocation = Profiler::AllocSourceLocation(line, source, sourceSz, function, functionSz, name, nameSz);
auto* item = Profiler::QueueSerial();
MemWrite(&item->hdr.type, QueueType::GpuZoneBeginAllocSrcLocSerial);
MemWrite(&item->gpuZoneBegin.cpuTime, Profiler::GetTime());
MemWrite(&item->gpuZoneBegin.srcloc, sourceLocation);
MemWrite(&item->gpuZoneBegin.thread, GetThreadHandle());
MemWrite(&item->gpuZoneBegin.queryId, static_cast<uint16_t>(queryId));
MemWrite(&item->gpuZoneBegin.context, ctx->GetId());
Profiler::QueueSerialFinish();
}
tracy_force_inline D3D11ZoneScope(D3D11Ctx* ctx, uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, int depth, bool active)
#ifdef TRACY_ON_DEMAND
: m_active(active&& GetProfiler().IsConnected())
#else
: m_active(active)
#endif
{
if( !m_active ) return;
m_ctx = ctx;
const auto queryId = ctx->NextQueryId();
ctx->m_devicectx->Begin(ctx->MapDisjointQueryId(queryId, queryId));
ctx->m_devicectx->End(ctx->TranslateQueryId(queryId));
m_disjointId = queryId;
const auto sourceLocation = Profiler::AllocSourceLocation(line, source, sourceSz, function, functionSz, name, nameSz);
auto* item = Profiler::QueueSerialCallstack(Callstack(depth));
MemWrite(&item->hdr.type, QueueType::GpuZoneBeginAllocSrcLocCallstackSerial);
MemWrite(&item->gpuZoneBegin.cpuTime, Profiler::GetTime());
MemWrite(&item->gpuZoneBegin.srcloc, sourceLocation);
MemWrite(&item->gpuZoneBegin.thread, GetThreadHandle());
MemWrite(&item->gpuZoneBegin.queryId, static_cast<uint16_t>(queryId));
MemWrite(&item->gpuZoneBegin.context, ctx->GetId());
Profiler::QueueSerialFinish();
}
tracy_force_inline ~D3D11ZoneScope()
{
if( !m_active ) return;
const auto queryId = m_ctx->NextQueryId();
m_ctx->m_devicectx->End(m_ctx->TranslateQueryId(queryId));
m_ctx->m_devicectx->End(m_ctx->MapDisjointQueryId(queryId, m_disjointId));
auto* item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::GpuZoneEndSerial );
MemWrite( &item->gpuZoneEnd.cpuTime, Profiler::GetTime() );
MemWrite( &item->gpuZoneEnd.thread, GetThreadHandle() );
MemWrite( &item->gpuZoneEnd.queryId, uint16_t( queryId ) );
MemWrite( &item->gpuZoneEnd.context, m_ctx->GetId() );
Profiler::QueueSerialFinish();
}
private:
const bool m_active;
D3D11Ctx* m_ctx;
unsigned int m_disjointId;
};
static inline D3D11Ctx* CreateD3D11Context( ID3D11Device* device, ID3D11DeviceContext* devicectx )
{
auto ctx = (D3D11Ctx*)tracy_malloc( sizeof( D3D11Ctx ) );
new(ctx) D3D11Ctx( device, devicectx );
return ctx;
}
static inline void DestroyD3D11Context( D3D11Ctx* ctx )
{
ctx->~D3D11Ctx();
tracy_free( ctx );
}
}
using TracyD3D11Ctx = tracy::D3D11Ctx*;
#define TracyD3D11Context( device, devicectx ) tracy::CreateD3D11Context( device, devicectx );
#define TracyD3D11Destroy(ctx) tracy::DestroyD3D11Context(ctx);
#define TracyD3D11ContextName(ctx, name, size) ctx->Name(name, size);
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
# define TracyD3D11Zone( ctx, name ) TracyD3D11NamedZoneS( ctx, ___tracy_gpu_zone, name, TRACY_CALLSTACK, true )
# define TracyD3D11ZoneC( ctx, name, color ) TracyD3D11NamedZoneCS( ctx, ___tracy_gpu_zone, name, color, TRACY_CALLSTACK, true )
# define TracyD3D11NamedZone( ctx, varname, name, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::D3D11ZoneScope varname( ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), TRACY_CALLSTACK, active );
# define TracyD3D11NamedZoneC( ctx, varname, name, color, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::D3D11ZoneScope varname( ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), TRACY_CALLSTACK, active );
# define TracyD3D11ZoneTransient(ctx, varname, name, active) TracyD3D11ZoneTransientS(ctx, varname, cmdList, name, TRACY_CALLSTACK, active)
#else
# define TracyD3D11Zone( ctx, name ) TracyD3D11NamedZone( ctx, ___tracy_gpu_zone, name, true )
# define TracyD3D11ZoneC( ctx, name, color ) TracyD3D11NamedZoneC( ctx, ___tracy_gpu_zone, name, color, true )
# define TracyD3D11NamedZone( ctx, varname, name, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::D3D11ZoneScope varname( ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), active );
# define TracyD3D11NamedZoneC( ctx, varname, name, color, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::D3D11ZoneScope varname( ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), active );
# define TracyD3D11ZoneTransient(ctx, varname, name, active) tracy::D3D11ZoneScope varname{ ctx, TracyLine, TracyFile, strlen(TracyFile), TracyFunction, strlen(TracyFunction), name, strlen(name), active };
#endif
#ifdef TRACY_HAS_CALLSTACK
# define TracyD3D11ZoneS( ctx, name, depth ) TracyD3D11NamedZoneS( ctx, ___tracy_gpu_zone, name, depth, true )
# define TracyD3D11ZoneCS( ctx, name, color, depth ) TracyD3D11NamedZoneCS( ctx, ___tracy_gpu_zone, name, color, depth, true )
# define TracyD3D11NamedZoneS( ctx, varname, name, depth, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::D3D11ZoneScope varname( ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), depth, active );
# define TracyD3D11NamedZoneCS( ctx, varname, name, color, depth, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::D3D11ZoneScope varname( ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), depth, active );
# define TracyD3D11ZoneTransientS(ctx, varname, name, depth, active) tracy::D3D11ZoneScope varname{ ctx, TracyLine, TracyFile, strlen(TracyFile), TracyFunction, strlen(TracyFunction), name, strlen(name), depth, active };
#else
# define TracyD3D11ZoneS( ctx, name, depth, active ) TracyD3D11Zone( ctx, name )
# define TracyD3D11ZoneCS( ctx, name, color, depth, active ) TracyD3D11ZoneC( name, color )
# define TracyD3D11NamedZoneS( ctx, varname, name, depth, active ) TracyD3D11NamedZone( ctx, varname, name, active )
# define TracyD3D11NamedZoneCS( ctx, varname, name, color, depth, active ) TracyD3D11NamedZoneC( ctx, varname, name, color, active )
# define TracyD3D11ZoneTransientS(ctx, varname, name, depth, active) TracyD3D12ZoneTransient(ctx, varname, name, active)
#endif
#define TracyD3D11Collect( ctx ) ctx->Collect();
#endif
#endif

View File

@@ -6,14 +6,14 @@ SamplerState samplerState;
// Terminal settings such as the resolution of the texture
cbuffer PixelShaderSettings {
// The number of seconds since the pixel shader was enabled
float Time;
// UI Scale
float Scale;
// Resolution of the shaderTexture
float2 Resolution;
// Background color as rgba
float4 Background;
// The number of seconds since the pixel shader was enabled
float Time;
// UI Scale
float Scale;
// Resolution of the shaderTexture
float2 Resolution;
// Background color as rgba
float4 Background;
};
// A pixel shader is a program that given a texture coordinate (tex) produces a color.
@@ -29,38 +29,19 @@ float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET
// effect, read the colors offset on the left, right, top, bottom of this
// fragment, as well as on the corners of this fragment.
//
// You could get away with fewer samples, but the resulting outlines will be
// blurrier.
//left, right, top, bottom:
float4 leftColor = shaderTexture.Sample(samplerState, tex+1.0*Scale*float2( 1.0, 0.0)/Resolution.y);
float4 rightColor = shaderTexture.Sample(samplerState, tex+1.0*Scale*float2(-1.0, 0.0)/Resolution.y);
float4 topColor = shaderTexture.Sample(samplerState, tex+1.0*Scale*float2( 0.0, 1.0)/Resolution.y);
float4 bottomColor = shaderTexture.Sample(samplerState, tex+1.0*Scale*float2( 0.0, -1.0)/Resolution.y);
// Corners
float4 topLeftColor = shaderTexture.Sample(samplerState, tex+1.0*Scale*float2( 1.0, 1.0)/Resolution.y);
float4 topRightColor = shaderTexture.Sample(samplerState, tex+1.0*Scale*float2(-1.0, 1.0)/Resolution.y);
float4 bottomLeftColor = shaderTexture.Sample(samplerState, tex+1.0*Scale*float2( 1.0, -1.0)/Resolution.y);
float4 bottomRightColor = shaderTexture.Sample(samplerState, tex+1.0*Scale*float2(-1.0, -1.0)/Resolution.y);
// Now, if any of those adjacent cells has text in it, then the *color vec4
// will have a non-zero .w (which is used for alpha). Use that alpha value
// to add some black to the current fragment.
//
// This will result in only coloring fragments adjacent to text, but leaving
// background images (for example) untouched.
float3 outlineColor = float3(0, 0, 0);
float4 result = color;
result = result + float4(outlineColor, leftColor.w);
result = result + float4(outlineColor, rightColor.w);
result = result + float4(outlineColor, topColor.w);
result = result + float4(outlineColor, bottomColor.w);
result = result + float4(outlineColor, topLeftColor.w);
result = result + float4(outlineColor, topRightColor.w);
result = result + float4(outlineColor, bottomLeftColor.w);
result = result + float4(outlineColor, bottomRightColor.w);
return result;
for (int dy = -2; dy <= 2; dy += 2) {
for (int dx = -2; dx <= 2; dx += 2) {
float4 neighbor = shaderTexture.Sample(samplerState, tex, int2(dx, dy));
color.a += neighbor.a;
}
}
return color;
}

View File

@@ -2,5 +2,5 @@
<packages>
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.7.3" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.230207.1" targetFramework="native" />
</packages>

View File

@@ -17,8 +17,6 @@
<PropertyGroup Label="NuGet Dependencies">
<TerminalCppWinrt>true</TerminalCppWinrt>
<TerminalXamlApplicationToolkit>true</TerminalXamlApplicationToolkit>
<TerminalVCRTForwarders>true</TerminalVCRTForwarders>
<TerminalThemeHelpers>true</TerminalThemeHelpers>
</PropertyGroup>
@@ -197,26 +195,6 @@
<!-- **END VC LIBS HACK** -->
<!-- **BEGIN TERMINAL CONNECTION HACK** -->
<!-- This is the same as the above VC libs hack, but for TerminalConnection.
TerminalConnection depends on cpprest*.dll, and if we don't include it in
the packaging output, we'll crash as soon as we try to load
TerminalConnection.dll.
The Sample sln needs to do this manually - the real exe has a
ProjectReference to TerminalConnection.vcxproj and can figure this out on
its own. -->
<ItemGroup>
<_TerminalConnectionDlls Include="$(OpenConsoleCommonOutDir)\TerminalConnection\*.dll" />
<PackagingOutputs Include="@(_TerminalConnectionDlls)">
<ProjectName>$(ProjectName)</ProjectName>
<OutputGroup>BuiltProjectOutputGroup</OutputGroup>
<TargetPath>%(Filename)%(Extension)</TargetPath>
</PackagingOutputs>
</ItemGroup>
<!-- **END TERMINAL CONNECTION HACK** -->
<!-- Same thing again here, with WindowsTerminal.exe -->
<ItemGroup>
<_WindowsTerminalExe Include="$(OpenConsoleCommonOutDir)\WindowsTerminal\*.exe" />

View File

@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.230207.1" targetFramework="native" />
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.7.3" targetFramework="native" />
<package id="Microsoft.VCRTForwarders.140" version="1.0.4" targetFramework="native" />
</packages>

View File

@@ -113,7 +113,7 @@ OutputCellIterator::OutputCellIterator(const std::wstring_view utf16Text, const
// - This is an iterator over legacy colors only. The text is not modified.
// Arguments:
// - legacyAttrs - One legacy color item per cell
OutputCellIterator::OutputCellIterator(const gsl::span<const WORD> legacyAttrs) noexcept :
OutputCellIterator::OutputCellIterator(const std::span<const WORD> legacyAttrs) noexcept :
_mode(Mode::LegacyAttr),
_currentView(s_GenerateViewLegacyAttr(til::at(legacyAttrs, 0))),
_run(legacyAttrs),
@@ -128,7 +128,7 @@ OutputCellIterator::OutputCellIterator(const gsl::span<const WORD> legacyAttrs)
// - This is an iterator over legacy cell data. We will use the unicode text and the legacy color attribute.
// Arguments:
// - charInfos - Multiple cell with unicode text and legacy color data.
OutputCellIterator::OutputCellIterator(const gsl::span<const CHAR_INFO> charInfos) noexcept :
OutputCellIterator::OutputCellIterator(const std::span<const CHAR_INFO> charInfos) noexcept :
_mode(Mode::CharInfo),
_currentView(s_GenerateView(til::at(charInfos, 0))),
_run(charInfos),
@@ -143,7 +143,7 @@ OutputCellIterator::OutputCellIterator(const gsl::span<const CHAR_INFO> charInfo
// - This is an iterator over existing OutputCells with full text and color data.
// Arguments:
// - cells - Multiple cells in a run
OutputCellIterator::OutputCellIterator(const gsl::span<const OutputCell> cells) :
OutputCellIterator::OutputCellIterator(const std::span<const OutputCell> cells) :
_mode(Mode::Cell),
_currentView(s_GenerateView(til::at(cells, 0))),
_run(cells),
@@ -181,15 +181,15 @@ OutputCellIterator::operator bool() const noexcept
}
case Mode::Cell:
{
return _pos < std::get<gsl::span<const OutputCell>>(_run).size();
return _pos < std::get<std::span<const OutputCell>>(_run).size();
}
case Mode::CharInfo:
{
return _pos < std::get<gsl::span<const CHAR_INFO>>(_run).size();
return _pos < std::get<std::span<const CHAR_INFO>>(_run).size();
}
case Mode::LegacyAttr:
{
return _pos < std::get<gsl::span<const WORD>>(_run).size();
return _pos < std::get<std::span<const WORD>>(_run).size();
}
default:
FAIL_FAST_HR(E_NOTIMPL);
@@ -198,6 +198,11 @@ OutputCellIterator::operator bool() const noexcept
CATCH_FAIL_FAST();
}
size_t OutputCellIterator::Position() const noexcept
{
return _pos;
}
// Routine Description:
// - Advances the iterator one position over the underlying data source.
// Return Value:
@@ -263,7 +268,7 @@ OutputCellIterator& OutputCellIterator::operator++()
_pos++;
if (operator bool())
{
_currentView = s_GenerateView(til::at(std::get<gsl::span<const OutputCell>>(_run), _pos));
_currentView = s_GenerateView(til::at(std::get<std::span<const OutputCell>>(_run), _pos));
}
break;
}
@@ -273,7 +278,7 @@ OutputCellIterator& OutputCellIterator::operator++()
_pos++;
if (operator bool())
{
_currentView = s_GenerateView(til::at(std::get<gsl::span<const CHAR_INFO>>(_run), _pos));
_currentView = s_GenerateView(til::at(std::get<std::span<const CHAR_INFO>>(_run), _pos));
}
break;
}
@@ -283,7 +288,7 @@ OutputCellIterator& OutputCellIterator::operator++()
_pos++;
if (operator bool())
{
_currentView = s_GenerateViewLegacyAttr(til::at(std::get<gsl::span<const WORD>>(_run), _pos));
_currentView = s_GenerateViewLegacyAttr(til::at(std::get<std::span<const WORD>>(_run), _pos));
}
break;
}

View File

@@ -39,15 +39,16 @@ public:
OutputCellIterator(const CHAR_INFO& charInfo, const size_t fillLimit = 0) noexcept;
OutputCellIterator(const std::wstring_view utf16Text) noexcept;
OutputCellIterator(const std::wstring_view utf16Text, const TextAttribute& attribute, const size_t fillLimit = 0) noexcept;
OutputCellIterator(const gsl::span<const WORD> legacyAttributes) noexcept;
OutputCellIterator(const gsl::span<const CHAR_INFO> charInfos) noexcept;
OutputCellIterator(const gsl::span<const OutputCell> cells);
OutputCellIterator(const std::span<const WORD> legacyAttributes) noexcept;
OutputCellIterator(const std::span<const CHAR_INFO> charInfos) noexcept;
OutputCellIterator(const std::span<const OutputCell> cells);
~OutputCellIterator() = default;
OutputCellIterator& operator=(const OutputCellIterator& it) = default;
operator bool() const noexcept;
size_t Position() const noexcept;
til::CoordType GetCellDistance(OutputCellIterator other) const noexcept;
til::CoordType GetInputDistance(OutputCellIterator other) const noexcept;
friend til::CoordType operator-(OutputCellIterator one, OutputCellIterator two) = delete;
@@ -86,13 +87,13 @@ private:
};
Mode _mode;
gsl::span<const WORD> _legacyAttrs;
std::span<const WORD> _legacyAttrs;
std::variant<
std::wstring_view,
gsl::span<const WORD>,
gsl::span<const CHAR_INFO>,
gsl::span<const OutputCell>,
std::span<const WORD>,
std::span<const CHAR_INFO>,
std::span<const OutputCell>,
std::monostate>
_run;

View File

@@ -34,9 +34,9 @@ OutputCellRect::OutputCellRect(const til::CoordType rows, const til::CoordType c
// - row - The Y position or row index in the buffer.
// Return Value:
// - Read/write span of OutputCells
gsl::span<OutputCell> OutputCellRect::GetRow(const til::CoordType row)
std::span<OutputCell> OutputCellRect::GetRow(const til::CoordType row)
{
return gsl::span<OutputCell>(_FindRowOffset(row), _cols);
return std::span<OutputCell>(_FindRowOffset(row), _cols);
}
// Routine Description:
@@ -47,7 +47,7 @@ gsl::span<OutputCell> OutputCellRect::GetRow(const til::CoordType row)
// - Read-only iterator of OutputCells
OutputCellIterator OutputCellRect::GetRowIter(const til::CoordType row) const
{
const gsl::span<const OutputCell> view(_FindRowOffset(row), _cols);
const std::span<const OutputCell> view(_FindRowOffset(row), _cols);
return OutputCellIterator(view);
}

View File

@@ -32,7 +32,7 @@ public:
OutputCellRect() noexcept;
OutputCellRect(const til::CoordType rows, const til::CoordType cols);
gsl::span<OutputCell> GetRow(const til::CoordType row);
std::span<OutputCell> GetRow(const til::CoordType row);
OutputCellIterator GetRowIter(const til::CoordType row) const;
til::CoordType Height() const noexcept;

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