Image returned by getClippedImage is very slow to draw on macOS

I have a large bitmap background that is obtained via getClippedImage on a slightly larger image. I just noticed that on macOS, calls to drawImage are ~6x longer when the image has been obtained via getClippedImage() of the larger image. This is on a retina screen, but I assume it is not required. When the image is obtained via getClippedImage, Instruments shows that 80% of the time spent in CGContextDrawImage is in “ripc_AcquireRIPImageData” and 15% is in ripc_RenderImage. When the image is not clipped, the 80% of ripc_AcquireRIPImageData disappear.

Here is an example that show the issue:

class MyComponent : public Component, public Timer
{
    int width=900, height=700;
    Image img, img0;
    int y;
    TextButton bt;
    bool clip = true;
    int retina_scaling = 2;
public:
    MyComponent() {
        setOpaque(true);
        updateImg();
        setSize(width, height);
        y = 0;
        startTimer(20);
        bt.setBounds(0,0,80,20);
        bt.setButtonText("CLIP");
        addAndMakeVisible(bt);
        bt.onClick = [this]() { clip = !clip; updateImg(); bt.setToggleState(clip,    dontSendNotification); };
    }
    void updateImg() {
      img = Image(Image::RGB, width*retina_scaling, height*retina_scaling+100, true,  NativeImageType());
      Graphics g(img);
      g.setColour(Colours::yellow);

      g.fillCheckerBoard(Rectangle<float>(0, 0, img.getWidth(), img.getHeight()), 10, 10,   Colours::white, Colour(0xffB0B0B0));

      img0 = img;
      img = img0.getClippedImage({0, 50, img.getWidth(), img.getHeight()-100});
      if (!clip) { img.duplicateIfShared(); }
    }
    void paint(Graphics &g) {
        double t0 = Time::getMillisecondCounterHiRes();
        g.drawImageTransformed(img, AffineTransform::scale(1./retina_scaling)); 
        g.setColour(Colours::green); g.drawHorizontalLine((y++)%getHeight(), 0, getWidth());
        double t1 = Time::getMillisecondCounterHiRes();
        std::cerr << "clip=" << clip << " t=" << t1-t0 << "ms\n";
    }
    void timerCallback() { repaint(); }
  };

I’m not sure if it can be fixed, but I believe it is good to be aware of that. I also think it would be useful to have tools that allow us to identify where we are not using the renderers efficiently. For example an option to measure the rendering time of the various components in order to spot the ones who are unusually slow.

1 Like