Skip to content
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

Merged
merged 2 commits into from
Jan 25, 2017
Merged

Merge #1705 to CGD2D #1750

merged 2 commits into from
Jan 25, 2017

Conversation

ms-jihua
Copy link
Contributor

@ms-jihua ms-jihua commented Jan 20, 2017

  • 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 #1635


This change is Reviewable

@@ -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());
Copy link
Contributor Author

@ms-jihua ms-jihua Jan 20, 2017

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

Copy link

@DHowett-MSFT DHowett-MSFT Jan 25, 2017

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

Copy link
Contributor Author

@ms-jihua ms-jihua Jan 25, 2017

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();
Copy link
Contributor Author

@ms-jihua ms-jihua Jan 20, 2017

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going to do this in a separate PR instead


In reply to: 96997659 [](ancestors = 96997659)

Copy link
Contributor

@rajsesh rajsesh Jan 25, 2017

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#1810


In reply to: 97693686 [](ancestors = 97693686)

Copy link
Contributor

@aballway aballway left a 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;
Copy link
Contributor

@aballway aballway Jan 20, 2017

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());
Copy link
Contributor

@msft-Jeyaram msft-Jeyaram Jan 23, 2017

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

Copy link
Contributor

@rajsesh rajsesh Jan 24, 2017

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

Copy link
Contributor Author

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)

Copy link
Contributor

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)

Copy link
Contributor

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)

Copy link
Contributor

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)

Copy link
Contributor Author

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());
Copy link
Contributor

@msft-Jeyaram msft-Jeyaram Jan 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here #Resolved

@msft-Jeyaram
Copy link
Contributor

:shipit:

// 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,
Copy link
Contributor

@rajsesh rajsesh Jan 24, 2017

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);
Copy link
Contributor

@rajsesh rajsesh Jan 24, 2017

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DHowett-MSFT is taking care of this


In reply to: 97467495 [](ancestors = 97467495)

Copy link
Contributor

@rajsesh rajsesh Jan 25, 2017

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

Copy link

@DHowett-MSFT DHowett-MSFT Jan 25, 2017

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
Copy link
Contributor

@rajsesh rajsesh Jan 24, 2017

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

Copy link
Contributor Author

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)

Copy link
Contributor

@rajsesh rajsesh Jan 25, 2017

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(&centerRect, &fontExtent, _font);
// EbrCenterTextInRectVertically(&centerRect, &fontExtent, _font);
Copy link
Contributor

@rajsesh rajsesh Jan 24, 2017

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DHowett-MSFT is taking care of this


In reply to: 97468215 [](ancestors = 97468215)

Copy link

@DHowett-MSFT DHowett-MSFT Jan 25, 2017

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

Copy link

@DHowett-MSFT DHowett-MSFT Jan 25, 2017

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());
Copy link
Contributor

@rajsesh rajsesh Jan 24, 2017

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

Copy link

@DHowett-MSFT DHowett-MSFT left a 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());
Copy link

@DHowett-MSFT DHowett-MSFT Jan 25, 2017

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

@ms-jihua
Copy link
Contributor Author

ms-jihua commented Jan 25, 2017

Then okay, let me just respond to the feedback on the table for now and get this actually performant later. #Resolved


inline void PopEndDraw() {
if (--(_beginEndDrawDepth) == 0) {
FAIL_FAST_IF_FAILED(deviceContext->EndDraw());
Copy link

@DHowett-MSFT DHowett-MSFT Jan 25, 2017

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants