Skip to content

Commit

Permalink
Change targets less in CGContext (#1878)
Browse files Browse the repository at this point in the history
* Change targets less in CGContext
 - CGContext previously changed targets for all draw primitive functions.
   Since changing targets causes an immediate flush, this significantly negatively impacted performance.
   Changed implementation to only change targets when needed (when shadows are enabled)
 - Added drawing tests for a few edge cases regarding shadows and clipping.
 - Removed unnecessary Escape/Unescape functions - these were not necessary to change targets as previously surmised.

Fixes #1810

*  - Enabled all shadow tests, using our current output (as opposed to reference platform) as reference images
 - Make the reversion of transform to the identity matrix safer
 - Misc cleanup

* CR feedback
  • Loading branch information
ms-jihua authored Feb 2, 2017
1 parent bb8777c commit 7f2f36c
Show file tree
Hide file tree
Showing 11 changed files with 285 additions and 252 deletions.
310 changes: 128 additions & 182 deletions Frameworks/CoreGraphics/CGContext.mm

Large diffs are not rendered by default.

8 changes: 0 additions & 8 deletions Frameworks/include/CGContextInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,3 @@ COREGRAPHICS_EXPORT CGImageRef CGBitmapContextGetImage(CGContextRef ctx);
// and only calling BeginDraw()/EndDraw() when the stack is empty/emptied
COREGRAPHICS_EXPORT void _CGContextPushBeginDraw(CGContextRef ctx);
COREGRAPHICS_EXPORT void _CGContextPopEndDraw(CGContextRef ctx);

// If currently in a Begin/EndDraw stack, Escape will EndDraw(), Unescape will BeginDraw()
// 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
// Also counts in a stack-like manner, so that the escape and unescape only happen once
COREGRAPHICS_EXPORT void _CGContextEscapeBeginEndDrawStack(CGContextRef ctx);
COREGRAPHICS_EXPORT void _CGContextUnescapeBeginEndDrawStack(CGContextRef ctx);
2 changes: 0 additions & 2 deletions build/CoreGraphics/dll/CoreGraphics.def
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,6 @@ LIBRARY CoreGraphics
_CGGetPixelFormatProperties
_CGContextPushBeginDraw
_CGContextPopEndDraw
_CGContextEscapeBeginEndDrawStack
_CGContextUnescapeBeginEndDrawStack

; CGDataConsumer.mm
CGDataConsumerCreate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

#include "DrawingTest.h"

DISABLED_DRAW_TEST_F(CGContext, Shadow, WhiteBackgroundTest<>) {
DRAW_TEST_F(CGContext, Shadow, WhiteBackgroundTest<>) {
CGContextRef context = GetDrawingContext();
CGRect bounds = GetDrawingBounds();

Expand All @@ -31,7 +31,7 @@ DISABLED_DRAW_TEST_F(CGContext, Shadow, WhiteBackgroundTest<>) {
CGContextStrokeRect(context, rect);
}

DISABLED_DRAW_TEST_F(CGContext, ShadowWithRotatedCTM, WhiteBackgroundTest<>) {
DRAW_TEST_F(CGContext, ShadowWithRotatedCTM, WhiteBackgroundTest<>) {
CGContextRef context = GetDrawingContext();
CGRect bounds = GetDrawingBounds();

Expand All @@ -50,3 +50,53 @@ DISABLED_DRAW_TEST_F(CGContext, ShadowWithRotatedCTM, WhiteBackgroundTest<>) {

CGContextStrokeRect(context, rect);
}

DRAW_TEST_F(CGContext, ShadowOverlap, WhiteBackgroundTest<>) {
CGContextRef context = GetDrawingContext();
CGRect bounds = GetDrawingBounds();

CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);
CGContextSetLineWidth(context, 5);

CGContextSetShadow(context, CGSize{ 10.f, 10.f }, 1.0);

CGPoint center = _CGRectGetCenter(bounds);
CGRect rect = _CGRectCenteredOnPoint({ 150, 150 }, center);
CGRect rect2 = _CGRectCenteredOnPoint({ 150, 150 }, rect.origin);

CGContextStrokeRect(context, rect);
CGContextStrokeRect(context, rect2);
}

DRAW_TEST_F(CGContext, ShadowEnabledInMiddle, WhiteBackgroundTest<>) {
CGContextRef context = GetDrawingContext();
CGRect bounds = GetDrawingBounds();

CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);
CGContextSetLineWidth(context, 5);

CGPoint center = _CGRectGetCenter(bounds);
CGRect rect = _CGRectCenteredOnPoint({ 150, 150 }, center);
CGRect rect2 = _CGRectCenteredOnPoint({ 150, 150 }, rect.origin);

CGContextStrokeRect(context, rect);
CGContextSetShadow(context, CGSize{ 10.f, 10.f }, 1.0);
CGContextStrokeRect(context, rect2);
}

DRAW_TEST_F(CGContext, ShadowDisabledInMiddle, WhiteBackgroundTest<>) {
CGContextRef context = GetDrawingContext();
CGRect bounds = GetDrawingBounds();

CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);
CGContextSetLineWidth(context, 5);

CGPoint center = _CGRectGetCenter(bounds);
CGRect rect = _CGRectCenteredOnPoint({ 150, 150 }, center);
CGRect rect2 = _CGRectCenteredOnPoint({ 150, 150 }, rect.origin);

CGContextSetShadow(context, CGSize{ 10.f, 10.f }, 1.0);
CGContextStrokeRect(context, rect);
CGContextSetShadow(context, CGSize{ 0, 0 }, 0.0);
CGContextStrokeRect(context, rect2);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
//******************************************************************************
//******************************************************************************

#include "DrawingTest.h"
#include "DrawingTestConfig.h"
Expand Down Expand Up @@ -271,12 +271,12 @@ DRAW_TEST(CGContextClipping, NonOverlappingImageMasks) {
CGContextRef context = GetDrawingContext();
CGRect bounds = GetDrawingBounds();

woc::unique_cf<CGImageRef> clipImage{
__CreateClipImage({64, 64}, ClippingTypeAlpha, [](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(context, { CGPointZero, size });
})
};
woc::unique_cf<CGImageRef> clipImage{ __CreateClipImage({ 64, 64 },
ClippingTypeAlpha,
[](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(context, { CGPointZero, size });
}) };

CGContextClipToMask(context, { CGPointZero, { 64, 64 } }, clipImage.get());
CGContextClipToMask(context, { { 0, bounds.size.height - 64 }, { 64, 64 } }, clipImage.get());
Expand All @@ -291,12 +291,12 @@ DRAW_TEST(CGContextClipping, CrossTransformedImageMasks) {
CGContextRef context = GetDrawingContext();
CGRect bounds = GetDrawingBounds();

woc::unique_cf<CGImageRef> clipImage{
__CreateClipImage({64, 64}, ClippingTypeAlpha, [](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(context, { CGPointZero, size });
})
};
woc::unique_cf<CGImageRef> clipImage{ __CreateClipImage({ 64, 64 },
ClippingTypeAlpha,
[](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(context, { CGPointZero, size });
}) };

CGContextClipToMask(context, { CGPointZero, { 64, 64 } }, clipImage.get());
CGContextTranslateCTM(context, 2.0, 2.0);
Expand All @@ -310,19 +310,19 @@ DRAW_TEST(CGContextClipping, PushClipPopClip) {
CGContextRef context = GetDrawingContext();
CGRect bounds = GetDrawingBounds();

woc::unique_cf<CGImageRef> clipImage1{
__CreateClipImage({64, 64}, ClippingTypeAlpha, [](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 0.5);
CGContextFillRect(context, { CGPointZero, size });
})
};
woc::unique_cf<CGImageRef> clipImage1{ __CreateClipImage({ 64, 64 },
ClippingTypeAlpha,
[](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 0.5);
CGContextFillRect(context, { CGPointZero, size });
}) };

woc::unique_cf<CGImageRef> clipImage2{
__CreateClipImage({64, 64}, ClippingTypeAlpha, [](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 0.5);
CGContextFillEllipseInRect(context, { CGPointZero, size });
})
};
woc::unique_cf<CGImageRef> clipImage2{ __CreateClipImage({ 64, 64 },
ClippingTypeAlpha,
[](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 0.5);
CGContextFillEllipseInRect(context, { CGPointZero, size });
}) };

CGRect clippingRect{ CGPointZero, { 64, 64 } };
CGContextClipToMask(context, clippingRect, clipImage1.get());
Expand All @@ -342,16 +342,49 @@ DRAW_TEST(CGContextClipping, PushClipPopClip) {
CGContextFillRect(context, bounds);
}

DRAW_TEST(CGContextClipping, ClipDrawClipDraw) {
CGContextRef context = GetDrawingContext();
CGRect bounds = GetDrawingBounds();

woc::unique_cf<CGImageRef> clipImage1{ __CreateClipImage({ 64, 64 },
ClippingTypeAlpha,
[](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 0.5);
CGContextFillRect(context, { CGPointZero, size });
}) };

woc::unique_cf<CGImageRef> clipImage2{ __CreateClipImage({ 64, 64 },
ClippingTypeAlpha,
[](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 0.5);
CGContextFillEllipseInRect(context, { CGPointZero, size });
}) };

CGRect clippingRect{ CGPointZero, { 64, 64 } };
CGContextClipToMask(context, clippingRect, clipImage1.get());

// This should draw a 50% alpha square.
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(context, bounds);

CGRect clippingRect2{ { 32, 32 }, { 64, 64 } };
CGContextClipToMask(context, clippingRect2, clipImage2.get());

// This should draw a 25% alpha quarter-circle emanating from one corner of the square.
CGContextSetRGBFillColor(context, 0.0, 1.0, 1.0, 1.0);
CGContextFillRect(context, bounds);
}

DRAW_TEST(CGContextClipping, ClipATransparencyLayer) {
CGContextRef context = GetDrawingContext();
CGRect bounds = GetDrawingBounds();

woc::unique_cf<CGImageRef> clipImage{
__CreateClipImage({64, 64}, ClippingTypeAlpha, [](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 0.5);
CGContextFillRect(context, { CGPointZero, size });
})
};
woc::unique_cf<CGImageRef> clipImage{ __CreateClipImage({ 64, 64 },
ClippingTypeAlpha,
[](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 0.5);
CGContextFillRect(context, { CGPointZero, size });
}) };

CGRect clippingRect{ CGPointZero, { 64, 64 } };
CGContextClipToMask(context, clippingRect, clipImage.get());
Expand All @@ -376,18 +409,16 @@ DRAW_TEST(CGImage, CreateWithSameSizeMask) {

CGSize imageSize{ static_cast<CGFloat>(CGImageGetWidth(image.get())), static_cast<CGFloat>(CGImageGetHeight(image.get())) };

woc::unique_cf<CGImageRef> alphaMask{
__CreateClipImage(imageSize,
ClippingTypeMask,
[](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(context, { CGPointZero, size });

CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0);
CGContextSetLineWidth(context, 10.0);
CGContextStrokeRect(context, CGRectInset({ CGPointZero, size }, 20, 20));
})
};
woc::unique_cf<CGImageRef> alphaMask{ __CreateClipImage(imageSize,
ClippingTypeMask,
[](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(context, { CGPointZero, size });

CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0);
CGContextSetLineWidth(context, 10.0);
CGContextStrokeRect(context, CGRectInset({ CGPointZero, size }, 20, 20));
}) };

ASSERT_NE(nullptr, alphaMask);

Expand All @@ -410,21 +441,19 @@ DRAW_TEST(CGImage, CreateWithScaledMask) {

CGSize imageSize{ static_cast<CGFloat>(CGImageGetWidth(image.get())), static_cast<CGFloat>(CGImageGetHeight(image.get())) };

woc::unique_cf<CGImageRef> alphaMask{
__CreateClipImage({ 64, 64 },
ClippingTypeMask,
[](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(context, { CGPointZero, size });

CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0);
CGContextSetLineWidth(context, 4.0);
CGPoint points[]{
{ 0, 0 }, { 64, 64 }, { 0, 64 }, { 64, 0 },
};
CGContextStrokeLineSegments(context, points, 4);
})
};
woc::unique_cf<CGImageRef> alphaMask{ __CreateClipImage({ 64, 64 },
ClippingTypeMask,
[](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(context, { CGPointZero, size });

CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0);
CGContextSetLineWidth(context, 4.0);
CGPoint points[]{
{ 0, 0 }, { 64, 64 }, { 0, 64 }, { 64, 0 },
};
CGContextStrokeLineSegments(context, points, 4);
}) };

ASSERT_NE(nullptr, alphaMask);

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 7f2f36c

Please sign in to comment.