@Override
  protected void drawVolatileImage(VolatileImage vi) {
    final SharedMemory.WithRaster frame = myCurrentFrame;
    if (frame == null) // nothing to do.
      return;

    // Shared-memory frame presented, so draw it into volatile image.
    synchronized (frame) {
      try {
        frame.lock();
        if (!FORCE_USE_SOFTWARE_RENDERING && JBR.isNativeRasterLoaderSupported()) {
          JBR.getNativeRasterLoader().loadNativeRaster(vi, frame.getPtr(), frame.getWidth(), frame.getHeight(),
                                                       frame.getPtr() + 4L * frame.getWidth() * frame.getHeight(),
                                                       frame.getDirtyRectsCount());
          return;
        }

        // Use slow code-path: load shared memory into buffered image
        JBHiDPIScaledImage image = myImage;
        if (image == null || image.getDelegate() == null
            || image.getDelegate().getWidth(null) != frame.getWidth()
            || image.getDelegate().getHeight(null) != frame.getHeight()) {
          image = (JBHiDPIScaledImage)RetinaImage.createFrom(
            new BufferedImage(frame.getWidth(), frame.getHeight(), BufferedImage.TYPE_INT_ARGB_PRE),
            getPixelDensity(), null);
        }
        loadBuffered((BufferedImage)Objects.requireNonNull(image.getDelegate()), frame);
        myImage = image;
      }
      finally {
        frame.unlock();
      }
    }

    // We are here then !JBR.isNativeRasterLoaderSupported() => myImage is prepared to be drawn onto volatile image.
    super.drawVolatileImage(vi);
  }
@Override
  protected void drawVolatileImage(VolatileImage vi)