void (CefBrowser browser, boolean popup, Rectangle[] dirtyRects, ByteBuffer buffer, int width, int height) { myFpsMeter.onPaintStarted(); JBHiDPIScaledImage image = popup ? myPopupImage : myImage; Dimension size = getRealImageSize(image); if (size.width != width || size.height != height) { image = (JBHiDPIScaledImage)RetinaImage.createFrom(new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE), myScale.getJreBiased(), null); } assert image != null; if (popup) { synchronized (myPopupMutex) { drawByteBuffer(image, buffer, dirtyRects); myPopupImage = image; } } else { drawByteBuffer(image, buffer, dirtyRects); myImage = image; } myContentOutdated = true; SwingUtilities.invokeLater(() -> { if (!myComponent.isShowing()) return; JRootPane root = myComponent.getRootPane(); RepaintManager rm = RepaintManager.currentManager(root); Rectangle dirtySrc = new Rectangle(0, 0, myComponent.getWidth(), myComponent.getHeight()); Rectangle dirtyDst = SwingUtilities.convertRectangle(myComponent, dirtySrc, root); int dx = 1; // NOTE: should mark area outside browser (otherwise background component won't be repainted) rm.addDirtyRegion(root, dirtyDst.x - dx, dirtyDst.y - dx, dirtyDst.width + dx * 2, dirtyDst.height + dx * 2); }); { // notify fps-meter long pixCount = 0; for (Rectangle r : dirtyRects) pixCount += (long)r.width * r.height; myFpsMeter.onPaintFinished(pixCount); } }