CGLayer resolution on iPhone with Retina display

  • In my UIView's drawRect: I derive a CGLayer from the current context, draw
    into it, and then draw the layer into the context (the view). This still
    works on iPhone with a Retina display, but the drawing is blocky. You can
    see the problem perfectly with Apple's own example code (DrawFlag) in the
    CGLayer Drawing page of the Quartz 2D Programming Guide - the stars in the
    flag are blocky.

    I can work around the problem for a double-resolution screen by creating a
    CGLayer twice the size I need, applying a doubling scale transform, drawing
    as before into the CGLayer, and then drawing the CGLayer into my view's
    context scaled back down again.

    But I feel I shouldn't have to do this. Given that the documentation claims
    that "a CGLayer has all the characteristics of the graphics context [from
    which it is derived] - its resolution, colorspace, and graphics state
    settings," might we call this a bug?

    m.

    --
    matt neuburg, phd = <matt...>, http://www.tidbits.com/matt/
    pantes anthropoi tou eidenai oregontai phusei
    Among the 2007 MacTech Top 25, http://tinyurl.com/2rh4pf
    AppleScript: the Definitive Guide, 2nd edition
    http://www.tidbits.com/matt/default.html#applescriptthings
    Take Control of Exploring & Customizing Snow Leopard
    http://tinyurl.com/kufyy8
    RubyFrontier! http://www.apeth.com/RubyFrontierDocs/default.html
    TidBITS, Mac news and reviews since 1990, http://www.tidbits.com
  • I believe you need to set the scale of the layer to the scale of the device. Here is how we do it where appContentScaleFactor is a global variable we store the scale from at startup:

    if ([[UIScreen mainScreen] respondsToSelector: @selector(scale)])
      appContentScaleFactor = [[UIScreen mainScreen] scale];

      if ([mainLayer respondsToSelector: @selector(setContentsScale:)])
      mainLayer.contentsScale = appContentScaleFactor;

    On Aug 28, 2010, at 3:22 PM, Matt Neuburg wrote:

    > In my UIView's drawRect: I derive a CGLayer from the current context, draw
    > into it, and then draw the layer into the context (the view). This still
    > works on iPhone with a Retina display, but the drawing is blocky. You can
    > see the problem perfectly with Apple's own example code (DrawFlag) in the
    > CGLayer Drawing page of the Quartz 2D Programming Guide - the stars in the
    > flag are blocky.
    >
    > I can work around the problem for a double-resolution screen by creating a
    > CGLayer twice the size I need, applying a doubling scale transform, drawing
    > as before into the CGLayer, and then drawing the CGLayer into my view's
    > context scaled back down again.
    >
    > But I feel I shouldn't have to do this. Given that the documentation claims
    > that "a CGLayer has all the characteristics of the graphics context [from
    > which it is derived] - its resolution, colorspace, and graphics state
    > settings," might we call this a bug?
    >
    > m.
    >
    > --
    > matt neuburg, phd = <matt...>, http://www.tidbits.com/matt/
    > pantes anthropoi tou eidenai oregontai phusei
    > Among the 2007 MacTech Top 25, http://tinyurl.com/2rh4pf
    > AppleScript: the Definitive Guide, 2nd edition
    > http://www.tidbits.com/matt/default.html#applescriptthings
    > Take Control of Exploring & Customizing Snow Leopard
    > http://tinyurl.com/kufyy8
    > RubyFrontier! http://www.apeth.com/RubyFrontierDocs/default.html
    > TidBITS, Mac news and reviews since 1990, http://www.tidbits.com

    Alex Kac - President and Founder
    Web Information Solutions, Inc.

    "Forgiveness is not an occasional act: it is a permanent attitude."
    -- Dr. Martin Luther King
  • On Aug 28, 2010, at 1:37 PM, Alex Kac wrote:

    > I believe you need to set the scale of the layer to the scale of the device. Here is how we do it where appContentScaleFactor is a global variable we store the scale from at startup:
    >
    > if ([[UIScreen mainScreen] respondsToSelector: @selector(scale)])
    > appContentScaleFactor = [[UIScreen mainScreen] scale];
    >
    >
    > if ([mainLayer respondsToSelector: @selector(setContentsScale:)])
    > mainLayer.contentsScale = appContentScaleFactor;
    >

    Sure, but a CGLayer has no contentsScale properties (or any other properties). A CGLayer isn't a CALayer... In fact I'm not sure they have anything in common. m.

    >
    > On Aug 28, 2010, at 3:22 PM, Matt Neuburg wrote:
    >
    >> In my UIView's drawRect: I derive a CGLayer from the current context, draw
    >> into it, and then draw the layer into the context (the view). This still
    >> works on iPhone with a Retina display, but the drawing is blocky. You can
    >> see the problem perfectly with Apple's own example code (DrawFlag) in the
    >> CGLayer Drawing page of the Quartz 2D Programming Guide - the stars in the
    >> flag are blocky.
    >>
    >> I can work around the problem for a double-resolution screen by creating a
    >> CGLayer twice the size I need, applying a doubling scale transform, drawing
    >> as before into the CGLayer, and then drawing the CGLayer into my view's
    >> context scaled back down again.
    >>
    >> But I feel I shouldn't have to do this. Given that the documentation claims
    >> that "a CGLayer has all the characteristics of the graphics context [from
    >> which it is derived] - its resolution, colorspace, and graphics state
    >> settings," might we call this a bug?
    >>
    >> m.
    >>
    >> --
    >> matt neuburg, phd = <matt...>, http://www.tidbits.com/matt/
    >> pantes anthropoi tou eidenai oregontai phusei
    >> Among the 2007 MacTech Top 25, http://tinyurl.com/2rh4pf
    >> AppleScript: the Definitive Guide, 2nd edition
    >> http://www.tidbits.com/matt/default.html#applescriptthings
    >> Take Control of Exploring & Customizing Snow Leopard
    >> http://tinyurl.com/kufyy8
    >> RubyFrontier! http://www.apeth.com/RubyFrontierDocs/default.html
    >> TidBITS, Mac news and reviews since 1990, http://www.tidbits.com
    >
    > Alex Kac - President and Founder
    > Web Information Solutions, Inc.
    >
    > "Forgiveness is not an occasional act: it is a permanent attitude."
    > -- Dr. Martin Luther King
    >
    >
    >
    >
  • On Aug 28, 2010, at 1:22 PM, Matt Neuburg wrote:

    > In my UIView's drawRect: I derive a CGLayer from the current context, draw
    > into it, and then draw the layer into the context (the view).

    Out of curiosity is there any particular reason you are taking this approach?

    --
    David Duncan
  • Ah, I just read the Layer part and didn’t think of a CGLayer. You are right - a CGLayer has nothing in common. That’s what I get for reading too quickly.

    On Aug 28, 2010, at 9:18 PM, Matt Neuburg wrote:

    >
    > On Aug 28, 2010, at 1:37 PM, Alex Kac wrote:
    >
    >> I believe you need to set the scale of the layer to the scale of the device. Here is how we do it where appContentScaleFactor is a global variable we store the scale from at startup:
    >>
    >> if ([[UIScreen mainScreen] respondsToSelector: @selector(scale)])
    >> appContentScaleFactor = [[UIScreen mainScreen] scale];
    >>
    >>
    >> if ([mainLayer respondsToSelector: @selector(setContentsScale:)])
    >> mainLayer.contentsScale = appContentScaleFactor;
    >>
    >
    > Sure, but a CGLayer has no contentsScale properties (or any other properties). A CGLayer isn't a CALayer... In fact I'm not sure they have anything in common. m.
    >
    >
    >
    >>
    >> On Aug 28, 2010, at 3:22 PM, Matt Neuburg wrote:
    >>
    >>> In my UIView's drawRect: I derive a CGLayer from the current context, draw
    >>> into it, and then draw the layer into the context (the view). This still
    >>> works on iPhone with a Retina display, but the drawing is blocky. You can
    >>> see the problem perfectly with Apple's own example code (DrawFlag) in the
    >>> CGLayer Drawing page of the Quartz 2D Programming Guide - the stars in the
    >>> flag are blocky.
    >>>
    >>> I can work around the problem for a double-resolution screen by creating a
    >>> CGLayer twice the size I need, applying a doubling scale transform, drawing
    >>> as before into the CGLayer, and then drawing the CGLayer into my view's
    >>> context scaled back down again.
    >>>
    >>> But I feel I shouldn't have to do this. Given that the documentation claims
    >>> that "a CGLayer has all the characteristics of the graphics context [from
    >>> which it is derived] - its resolution, colorspace, and graphics state
    >>> settings," might we call this a bug?
    >>>
    >>> m.
    >>>
    >>> --
    >>> matt neuburg, phd = <matt...>, http://www.tidbits.com/matt/
    >>> pantes anthropoi tou eidenai oregontai phusei
    >>> Among the 2007 MacTech Top 25, http://tinyurl.com/2rh4pf
    >>> AppleScript: the Definitive Guide, 2nd edition
    >>> http://www.tidbits.com/matt/default.html#applescriptthings
    >>> Take Control of Exploring & Customizing Snow Leopard
    >>> http://tinyurl.com/kufyy8
    >>> RubyFrontier! http://www.apeth.com/RubyFrontierDocs/default.html
    >>> TidBITS, Mac news and reviews since 1990, http://www.tidbits.com
    >>
    >> Alex Kac - President and Founder
    >> Web Information Solutions, Inc.
    >>
    >> "Forgiveness is not an occasional act: it is a permanent attitude."
    >> -- Dr. Martin Luther King
    >>
    >>
    >>
    >>
    >

    Alex Kac - President and Founder
    Web Information Solutions, Inc.

    "I am not young enough to know everything."
    --Oscar Wilde
  • On or about 8/28/10 9:31 PM, thus spake "David Duncan"
    <david.duncan...>:

    > In the case of iOS for example, caching contents to CGLayers is rarely useful
    > because it is rarely useful to use a software cache ­ it is usually far more
    > useful to use a hardware cache, which means CALayer or UIView, not CGLayer.

    I bow to all you say; still the question remains whether, taken
    dispassionately and in the abstract, it might be a useful behavior if
    calling CGLayerCreateWithContext() would cause the resulting CGLayer to have
    the "resolution" of the context from which it is created, as advertised, so
    that drawing back into the same context with e.g. CGContextDrawLayerAtPoint
    would not cause the ultimate drawing to have half the "resolution" on the
    iPhone 4?

    Just to repeat, the flag-drawing example on this page:

    <http://developer.apple.com/iphone/library/documentation/GraphicsImaging/Con
    ceptual/drawingwithquartz2d/dq_layers/dq_layers.html
    >

    ...is Apple's own, and behaves undesirably when the screen is
    double-resolution, visibly drawing the flag's stars in single resolution. m.

    --
    matt neuburg, phd = <matt...>, http://www.tidbits.com/matt/
    pantes anthropoi tou eidenai oregontai phusei
    Among the 2007 MacTech Top 25, http://tinyurl.com/2rh4pf
    AppleScript: the Definitive Guide, 2nd edition
    http://www.tidbits.com/matt/default.html#applescriptthings
    Take Control of Exploring & Customizing Snow Leopard
    http://tinyurl.com/kufyy8
    RubyFrontier! http://www.apeth.com/RubyFrontierDocs/default.html
    TidBITS, Mac news and reviews since 1990, http://www.tidbits.com
  • I would recommend you file a bug.

    --
    David Duncan

    On Aug 29, 2010, at 9:38 AM, Matt Neuburg <matt...> wrote:

    > On or about 8/28/10 9:31 PM, thus spake "David Duncan"
    > <david.duncan...>:
    >
    >> In the case of iOS for example, caching contents to CGLayers is rarely useful
    >> because it is rarely useful to use a software cache – it is usually far more
    >> useful to use a hardware cache, which means CALayer or UIView, not CGLayer.
    >
    > I bow to all you say; still the question remains whether, taken
    > dispassionately and in the abstract, it might be a useful behavior if
    > calling CGLayerCreateWithContext() would cause the resulting CGLayer to have
    > the "resolution" of the context from which it is created, as advertised, so
    > that drawing back into the same context with e.g. CGContextDrawLayerAtPoint
    > would not cause the ultimate drawing to have half the "resolution" on the
    > iPhone 4?
    >
    > Just to repeat, the flag-drawing example on this page:
    >
    > <http://developer.apple.com/iphone/library/documentation/GraphicsImaging/Con

    > ceptual/drawingwithquartz2d/dq_layers/dq_layers.html>
    >
    > ...is Apple's own, and behaves undesirably when the screen is
    > double-resolution, visibly drawing the flag's stars in single resolution. m.
    >
    > --
    > matt neuburg, phd = <matt...>, http://www.tidbits.com/matt/
    > pantes anthropoi tou eidenai oregontai phusei
    > Among the 2007 MacTech Top 25, http://tinyurl.com/2rh4pf
    > AppleScript: the Definitive Guide, 2nd edition
    > http://www.tidbits.com/matt/default.html#applescriptthings
    > Take Control of Exploring & Customizing Snow Leopard
    > http://tinyurl.com/kufyy8
    > RubyFrontier! http://www.apeth.com/RubyFrontierDocs/default.html
    > TidBITS, Mac news and reviews since 1990, http://www.tidbits.com
    >
    >
    >
  • On or about 8/28/10 9:31 PM, thus spake "David Duncan"
    <david.duncan...>:

    > it is usually far more
    > useful to use a hardware cache, which means CALayer or UIView, not CGLayer.

    Sorry to keep coming back to this, but the documentation implies that
    CGLayer *is* a hardware cache - that's why I was using it. For example, the
    documentation says:

    > Before you call this or any routine that uses CGLayer objects, you must check
    > to make sure that the system is running Mac OS X v10.4 or later and has a
    > graphics card that supports using CGLayer objects

    This suggests that CGLayer is implemented in hardware; otherwise surely the
    check for a proper graphics card wouldn't be necessary? But perhaps I'm
    misunderstanding.... m.

    --
    matt neuburg, phd = <matt...>, http://www.tidbits.com/matt/
    pantes anthropoi tou eidenai oregontai phusei
    Among the 2007 MacTech Top 25, http://tinyurl.com/2rh4pf
    AppleScript: the Definitive Guide, 2nd edition
    http://www.tidbits.com/matt/default.html#applescriptthings
    Take Control of Exploring & Customizing Snow Leopard
    http://tinyurl.com/kufyy8
    RubyFrontier! http://www.apeth.com/RubyFrontierDocs/default.html
    TidBITS, Mac news and reviews since 1990, http://www.tidbits.com
  • On Aug 29, 2010, at 11:21 AM, Matt Neuburg wrote:

    > On or about 8/28/10 9:31 PM, thus spake "David Duncan"
    > <david.duncan...>:
    >
    >> it is usually far more
    >> useful to use a hardware cache, which means CALayer or UIView, not CGLayer.
    >
    > Sorry to keep coming back to this, but the documentation implies that
    > CGLayer *is* a hardware cache - that's why I was using it. For example, the
    > documentation says:

    It is (potentially) a hardware cache on the desktop in certain situations. Nothing in CG is hardware accelerated on iOS however, and CGLayer is no exception.

    >> Before you call this or any routine that uses CGLayer objects, you must check
    >> to make sure that the system is running Mac OS X v10.4 or later and has a
    >> graphics card that supports using CGLayer objects
    >
    > This suggests that CGLayer is implemented in hardware; otherwise surely the
    > check for a proper graphics card wouldn't be necessary? But perhaps I'm
    > misunderstanding.... m.

    If you require hardware acceleration of CGLayer objects perhaps, but to simply use CGLayers requires no such check. This would be a bug in the documentation.

    Much of the shared documentation between iOS and Mac OS X will contain information that is incorrect for one platform or another. We strive to point out where information applies to only one platform or another, but this is an ongoing effort.
    --
    David Duncan
  • On Sun, Aug 29, 2010 at 2:10 PM, David Duncan <david.duncan...>wrote:

    > On Aug 29, 2010, at 11:21 AM, Matt Neuburg wrote:
    >
    >> On or about 8/28/10 9:31 PM, thus spake "David Duncan"
    >> <david.duncan...>:
    >>
    >>> it is usually far more
    >>> useful to use a hardware cache, which means CALayer or UIView, not
    > CGLayer.
    >>
    >> Sorry to keep coming back to this, but the documentation implies that
    >> CGLayer *is* a hardware cache - that's why I was using it. For example,
    > the
    >> documentation says:
    >
    > It is (potentially) a hardware cache on the desktop in certain situations.
    > Nothing in CG is hardware accelerated on iOS however, and CGLayer is no
    > exception.
    >

    Additionally, I don't think it's actually hardware accelerated on the
    desktop either.

    In practice at the moment, a CGLayer is basically a CGImage together with a
    CGBitmapContext.  I can think of case where something different happens, but
    that case still doesn't use the GPU.

    -Ken
    Cocoa Frameworks

    >
    >>> Before you call this or any routine that uses CGLayer objects, you must
    > check
    >>> to make sure that the system is running Mac OS X v10.4 or later and has
    > a
    >>> graphics card that supports using CGLayer objects
    >>
    >> This suggests that CGLayer is implemented in hardware; otherwise surely
    > the
    >> check for a proper graphics card wouldn't be necessary? But perhaps I'm
    >> misunderstanding.... m.
    >
    >
    > If you require hardware acceleration of CGLayer objects perhaps, but to
    > simply use CGLayers requires no such check. This would be a bug in the
    > documentation.
    >
    > Much of the shared documentation between iOS and Mac OS X will contain
    > information that is incorrect for one platform or another. We strive to
    > point out where information applies to only one platform or another, but
    > this is an ongoing effort.
    > --
    > David Duncan
    >
  • On or about 8/29/10 2:54 PM, thus spake "Ken Ferry" <kenferry...>:

    > In practice at the moment, a CGLayer is basically a CGImage together with a
    > CGBitmapContext.  I can think of case where something different happens, but
    > that case still doesn't use the GPU.

    Cool, once again I got the education I was after. Thx to all - m.

    --
    matt neuburg, phd = <matt...>, http://www.tidbits.com/matt/
    pantes anthropoi tou eidenai oregontai phusei
    Among the 2007 MacTech Top 25, http://tinyurl.com/2rh4pf
    AppleScript: the Definitive Guide, 2nd edition
    http://www.tidbits.com/matt/default.html#applescriptthings
    Take Control of Exploring & Customizing Snow Leopard
    http://tinyurl.com/kufyy8
    RubyFrontier! http://www.apeth.com/RubyFrontierDocs/default.html
    TidBITS, Mac news and reviews since 1990, http://www.tidbits.com
previous month august 2010 next month
MTWTFSS
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
Go to today