-
Notifications
You must be signed in to change notification settings - Fork 805
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merge #1705 to CGD2D #1750
Merge #1705 to CGD2D #1750
Conversation
@@ -2138,8 +2174,9 @@ void CGContextClearRect(CGContextRef context, CGRect rect) { | |||
ComPtr<ID2D1CommandList> commandList; | |||
RETURN_IF_FAILED(deviceContext->CreateCommandList(&commandList)); | |||
|
|||
deviceContext->BeginDraw(); | |||
EscapeBeginEndDrawStack(); | |||
deviceContext->SetTarget(commandList.Get()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DHowett-MSFT I think this is more correct placed here, right? #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're correct. I recall Begin->Set->End being specified in one of the MSDN documents. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I lied and it doesn't matter https://msdn.microsoft.com/en-us/library/windows/desktop/hh404533(v=vs.85).aspx leaving as-is for now, will look more deeply at this in the followup PR
In reply to: 97687941 [](ancestors = 97687941)
@@ -2138,8 +2174,9 @@ void CGContextClearRect(CGContextRef context, CGRect rect) { | |||
ComPtr<ID2D1CommandList> commandList; | |||
RETURN_IF_FAILED(deviceContext->CreateCommandList(&commandList)); | |||
|
|||
deviceContext->BeginDraw(); | |||
EscapeBeginEndDrawStack(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because of the need to escape before changing targets, and because most functions in this file currently filter down to this function and thus change targets, #1705 has close-to-zero or probably negative impact on CGD2D as it currently is. Since we don't need a new command list each time this is called, I am going to add another iteration to this PR, tying the creation of new command lists to the stack. #WontFix
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please open a tracking issue to do this work. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approval pending command list iteration
} | ||
} | ||
} else { | ||
if (!_noDefaultImages) { | ||
CGContextRef ctx = UIGraphicsGetCurrentContext(); | ||
CGContextRef ctx = ctx; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: not needed #Resolved
microsoft#1705) * CoreText Performance: Call ID2D1RenderTarget::BeginDraw()/EndDraw() fewer times Fixes microsoft#1620 * - Added Begin/EndDraw pairs to a few more places - Mitigated an issue with cairo where ID2D1RenderTarget would sometimes cache a before state during begin draw, and wipe out any changes cairo made, breaking APIs like CGContextFillRect. - Changed implementation/naming of the 'escape the current begin/end draw stack' functions
|
||
inline void EscapeBeginEndDrawStack() { | ||
if ((_beginEndDrawDepth > 0) && ((_escapeBeginEndDrawDepth)++ == 0)) { | ||
THROW_IF_FAILED(deviceContext->EndDraw()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
THROW_IF_FAILED [](start = 12, length = 15)
who is catching the throws?
We standardized on FAIL_FAST #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The standardization we agreed on was to capture exceptions at the API boundary (which is usually the API entry point). Failing fast in the leaf nodes will lead to code that just arbitrarily quits with no possible recovery. Particularly when drawing to hardware device contexts, EndDraw() can fail, so we need to handle this with care. See #1194. #Pending
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what you're actually advocating I do here, considering handling #1194 appears too large for the scope of this PR. As such, I'm going to take @msft-Jeyaram 's recommendation to follow the standard for now.
In reply to: 97468410 [](ancestors = 97468410)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The recommendation is wrong, we agreed not to FAIL_FAST at arbitrary points in the CG code and instead throw. Any exceptions must be caught at the "C" entry point, where we decide either to return an error code/null or fail-fast if it is void.
In reply to: 97695158 [](ancestors = 97695158,97468410)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although this is only one step away from the entry point.
In reply to: 97696710 [](ancestors = 97696710,97695158,97468410)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am going to approve this PR given that this is only one step away from the entry point.
In reply to: 97696881 [](ancestors = 97696881,97696710,97695158,97468410)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i actually already made the change anyway
In reply to: 97697849 [](ancestors = 97697849,97696881,97696710,97695158,97468410)
|
||
inline void PopEndDraw() { | ||
if (--(_beginEndDrawDepth) == 0) { | ||
THROW_IF_FAILED(deviceContext->EndDraw()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here #Resolved
// For scenarios where a Begin/EndDraw pair needs to be temporarily escaped, to be returned to at a later time | ||
// Ie: | ||
// - Switching render targets - Illegal to do so if currently in a Begin/EndDraw pair | ||
// - Cairo - ID2D1RenderTarget is considered to 'own' the bitmap during Begin/EndDraw, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can safely remove comment about cairo now. #Resolved
|
||
CGRect bounds; | ||
// TODO(DH) | ||
bounds = self.bounds; | ||
//bounds = CGContextGetClipBoundingBox(context); | ||
// bounds = CGContextGetClipBoundingBox(context); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: remove commented out line. Also, the whole thing could be CGRect bounds = self.bounds, or even just [self drawRect:self.bounds] since it is not being reused. #WontFix
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DHowett-MSFT, do we have an issue tracking this TODO? #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#1811 #Resolved
@@ -242,6 +242,10 @@ LIBRARY CoreGraphics | |||
_CGContextCreateWithD2DRenderTarget | |||
_CGGetD2DFactory | |||
_CGGetPixelFormatProperties | |||
_CGContextPushBeginDraw | |||
_CGContextPopEndDraw | |||
_CGContextEscapeBeginEndDrawStack |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These names are not ideal - they are vague (what does escaping the stack mean), and reveal the implementation detail (there is a stack). The later is not a big deal, but essentially what you doing here is ability to deal with a layer, so it might make sense to just call this _CGContextForceEndDraw() and _CGContextForceBeginDraw(), or _CGContextBeginLayerDraw/EndLayerDraw(). #WontFix
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but they don't force an enddraw or a begindraw, nor are they exclusively tied to layers. they are 'enddraw if needed' and 'begindraw if needed', where 'needed' is kind of vague (if currently in the stack) and difficult to describe without mentioning the stack.
i agree that these names are bad, but the suggestions are less factually accurate, so i am won'tfixing this for now.
In reply to: 97468082 [](ancestors = 97468082)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think BeginDrawIfNeeded(), EndDrawIfNeeded() are more descriptive than EscapeStack. Won't fix is okay. #WontFix
@@ -759,7 +763,7 @@ - (CGSize)sizeThatFits:(CGSize)fitSize { | |||
centerRect.origin.y = 0; | |||
centerRect.size = fontExtent; | |||
// TODO(DH) | |||
//EbrCenterTextInRectVertically(¢erRect, &fontExtent, _font); | |||
// EbrCenterTextInRectVertically(¢erRect, &fontExtent, _font); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove commented code? also looks like there is a missing TODO issue, lets create it now. #WontFix
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might not be necessary, but I'll add an issue to track "something about vertical text centering in UITextField"
This is more of a CT concern, but EbrCenterTextInRectVertically was part of CGContext for some unknown reason. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#1812 #Resolved
|
||
inline void EscapeBeginEndDrawStack() { | ||
if ((_beginEndDrawDepth > 0) && ((_escapeBeginEndDrawDepth)++ == 0)) { | ||
THROW_IF_FAILED(deviceContext->EndDraw()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The standardization we agreed on was to capture exceptions at the API boundary (which is usually the API entry point). Failing fast in the leaf nodes will lead to code that just arbitrarily quits with no possible recovery. Particularly when drawing to hardware device contexts, EndDraw() can fail, so we need to handle this with care. See #1194. #Pending
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Contingent upon @rajsesh-msft's requested changes, I think this is safe to go in.
We can improve the drawing stack later, but this will unblock our merge.
@@ -2138,8 +2174,9 @@ void CGContextClearRect(CGContextRef context, CGRect rect) { | |||
ComPtr<ID2D1CommandList> commandList; | |||
RETURN_IF_FAILED(deviceContext->CreateCommandList(&commandList)); | |||
|
|||
deviceContext->BeginDraw(); | |||
EscapeBeginEndDrawStack(); | |||
deviceContext->SetTarget(commandList.Get()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're correct. I recall Begin->Set->End being specified in one of the MSDN documents. #Resolved
Then okay, let me just respond to the feedback on the table for now and get this actually performant later. #Resolved |
2ba1689
to
19bebee
Compare
|
||
inline void PopEndDraw() { | ||
if (--(_beginEndDrawDepth) == 0) { | ||
FAIL_FAST_IF_FAILED(deviceContext->EndDraw()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The true recommendation was to have inner functions return HRESULT
and FAIL_FAST or ignore the error gracefully at the C API boundary. #Pending
- Add PushBeginDraw/PopEndDraw pairs to UISegment, UIImage (not on develop since this likely would've actually hurt performance there) - Add Escape/Unescape pairs to CGContext areas where the target is changed Fixes microsoft#1635 cr feedback cr feedback
a7c7161
to
0ac5491
Compare
(not on develop since this likely would've actually hurt performance there)
Fixes #1635
This change is