Skip to content

Commit bc256f5

Browse files
authored
feat: accelerated paint (#16)
**CEF supports** hardware-accelerated off-screen rendering by enabling `shared_texture_enabled` via `WindowInfo` and passing `--off-screen-rendering-enabled --shared-texture-enabled` as arguments. - https://bitbucket.org/chromiumembedded/cef/pull-requests/734 - https://github.com/chromiumembedded/cef/blob/2c411892e273c564dfb6650dcee8fea458849178/include/cef_render_handler.h#L151-L173.
2 parents 000eba0 + 6ad431c commit bc256f5

15 files changed

+469
-173
lines changed

java/org/cef/CefBrowserSettings.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,29 @@ public class CefBrowserSettings {
2020
*/
2121
public int windowless_frame_rate = 0;
2222

23+
/**
24+
* Set to true to enable shared texture rendering. When enabled, the browser
25+
* will render to a shared texture that can be accessed by the host application
26+
* for hardware-accelerated compositing. This is supported on Windows via D3D11,
27+
* macOS via Metal/OpenGL, and Linux via native buffers.
28+
*/
29+
public boolean shared_texture_enabled = false;
30+
31+
/**
32+
* Set to true to enable external begin frame scheduling. When enabled, the
33+
* client must call CefBrowserHost::SendExternalBeginFrame to trigger frame
34+
* rendering at the specified frame rate.
35+
*/
36+
public boolean external_begin_frame_enabled = false;
37+
2338
public CefBrowserSettings() {}
2439

2540
@Override
2641
public CefBrowserSettings clone() {
2742
CefBrowserSettings tmp = new CefBrowserSettings();
2843
tmp.windowless_frame_rate = windowless_frame_rate;
44+
tmp.shared_texture_enabled = shared_texture_enabled;
45+
tmp.external_begin_frame_enabled = external_begin_frame_enabled;
2946
return tmp;
3047
}
3148
}

java/org/cef/CefClient.java

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public CefBrowser createBrowser(String url, boolean isTransparent,
8787
}
8888

8989
public CefBrowser createBrowser(String url, boolean isTransparent,
90-
CefRequestContext context, CefBrowserSettings settings) {
90+
CefRequestContext context, CefBrowserSettings settings) {
9191
if (isDisposed_)
9292
throw new IllegalStateException("Can't create browser. CefClient is disposed");
9393
return CefBrowserFactory.create(
@@ -122,7 +122,7 @@ protected CefDialogHandler getDialogHandler() {
122122
protected CefDisplayHandler getDisplayHandler() {
123123
return this;
124124
}
125-
125+
126126
@Override
127127
protected CefAudioHandler getAudioHandler() {
128128
return this;
@@ -230,7 +230,7 @@ public void removeDialogHandler() {
230230
@Override
231231
public boolean onFileDialog(CefBrowser browser, FileDialogMode mode, String title,
232232
String defaultFilePath, Vector<String> acceptFilters, Vector<String> acceptExtensions,
233-
Vector<String> acceptDescriptions, CefFileDialogCallback callback) {
233+
Vector<String> acceptDescriptions, CefFileDialogCallback callback) {
234234
if (dialogHandler_ != null && browser != null) {
235235
return dialogHandler_.onFileDialog(browser, mode, title, defaultFilePath, acceptFilters,
236236
acceptExtensions, acceptDescriptions, callback);
@@ -322,7 +322,7 @@ public void removeDownloadHandler() {
322322

323323
@Override
324324
public boolean onBeforeDownload(CefBrowser browser, CefDownloadItem downloadItem,
325-
String suggestedName, CefBeforeDownloadCallback callback) {
325+
String suggestedName, CefBeforeDownloadCallback callback) {
326326
if (downloadHandler_ != null && browser != null)
327327
return downloadHandler_.onBeforeDownload(
328328
browser, downloadItem, suggestedName, callback);
@@ -693,6 +693,15 @@ public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects,
693693
realHandler.onPaint(browser, popup, dirtyRects, buffer, width, height);
694694
}
695695

696+
@Override
697+
public void onAcceleratedPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, CefAcceleratedPaintInfo info) {
698+
if (browser == null) return;
699+
700+
CefRenderHandler realHandler = browser.getRenderHandler();
701+
if (realHandler != null)
702+
realHandler.onAcceleratedPaint(browser, popup, dirtyRects, info);
703+
}
704+
696705
@Override
697706
public void addOnPaintListener(Consumer<CefPaintEvent> listener) {}
698707

@@ -702,6 +711,15 @@ public void setOnPaintListener(Consumer<CefPaintEvent> listener) {}
702711
@Override
703712
public void removeOnPaintListener(Consumer<CefPaintEvent> listener) {}
704713

714+
@Override
715+
public void addOnAcceleratedPaintListener(Consumer<CefAcceleratedPaintEvent> listener) {}
716+
717+
@Override
718+
public void setOnAcceleratedPaintListener(Consumer<CefAcceleratedPaintEvent> listener) {}
719+
720+
@Override
721+
public void removeOnAcceleratedPaintListener(Consumer<CefAcceleratedPaintEvent> listener) {}
722+
705723
@Override
706724
public boolean startDragging(CefBrowser browser, CefDragData dragData, int mask, int x, int y) {
707725
if (browser == null) return false;
@@ -808,39 +826,39 @@ public void onMouseEvent(
808826
public boolean getScreenInfo(CefBrowser arg0, CefScreenInfo arg1) {
809827
return false;
810828
}
811-
829+
812830
// CefAudioHandler
813-
831+
814832
public CefClient addAudioHandler(CefAudioHandler handler) {
815833
if (audioHandler_ == null) audioHandler_ = handler;
816834
return this;
817835
}
818-
836+
819837
public void removeAudioHandler() {
820838
audioHandler_ = null;
821839
}
822-
840+
823841
@Override
824842
public boolean getAudioParameters(CefBrowser browser, CefAudioParameters params) {
825843
if (audioHandler_ != null) return audioHandler_.getAudioParameters(browser, params);
826844
return false;
827845
}
828-
846+
829847
@Override
830848
public void onAudioStreamStarted(CefBrowser browser, CefAudioParameters params, int channels) {
831849
if (audioHandler_ != null) audioHandler_.onAudioStreamStarted(browser, params, channels);
832850
}
833-
851+
834852
@Override
835853
public void onAudioStreamPacket(CefBrowser browser, DataPointer data, int frames, long pts) {
836854
if (audioHandler_ != null) audioHandler_.onAudioStreamPacket(browser, data, frames, pts);
837855
}
838-
856+
839857
@Override
840858
public void onAudioStreamStopped(CefBrowser browser) {
841859
if (audioHandler_ != null) audioHandler_.onAudioStreamStopped(browser);
842860
}
843-
861+
844862
@Override
845863
public void onAudioStreamError(CefBrowser browser, String text) {
846864
if (audioHandler_ != null) audioHandler_.onAudioStreamError(browser, text);
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
2+
// reserved. Use of this source code is governed by a BSD-style license that
3+
// can be found in the LICENSE file.
4+
5+
package org.cef.browser;
6+
7+
import org.cef.handler.CefAcceleratedPaintInfo;
8+
9+
import java.awt.*;
10+
11+
public class CefAcceleratedPaintEvent {
12+
private final CefBrowser browser;
13+
private final boolean popup;
14+
private final Rectangle[] dirtyRects;
15+
private final CefAcceleratedPaintInfo acceleratedPaintInfo;
16+
17+
public CefAcceleratedPaintEvent(CefBrowser browser, boolean popup, Rectangle[] dirtyRects,
18+
CefAcceleratedPaintInfo acceleratedPaintInfo) {
19+
this.browser = browser;
20+
this.popup = popup;
21+
this.dirtyRects = dirtyRects;
22+
this.acceleratedPaintInfo = acceleratedPaintInfo;
23+
}
24+
25+
public CefBrowser getBrowser() {
26+
return browser;
27+
}
28+
29+
public boolean getPopup() {
30+
return popup;
31+
}
32+
33+
public Rectangle[] getDirtyRects() {
34+
return dirtyRects;
35+
}
36+
37+
public CefAcceleratedPaintInfo getAcceleratedPaintInfo() {
38+
return acceleratedPaintInfo;
39+
}
40+
41+
public int getWidth() {
42+
return acceleratedPaintInfo.width;
43+
}
44+
45+
public int getHeight() {
46+
return acceleratedPaintInfo.height;
47+
}
48+
}

java/org/cef/browser/CefBrowser.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,15 @@ public void runFileDialog(FileDialogMode mode, String title, String defaultFileP
398398
*/
399399
public void setWindowlessFrameRate(int frameRate);
400400

401+
/**
402+
* Send an external begin frame to trigger frame rendering when external begin frame
403+
* scheduling is enabled. This method should be called at the desired frame rate when
404+
* CefBrowserSettings.external_begin_frame_enabled is set to true.
405+
*
406+
* @throws UnsupportedOperationException if not supported
407+
*/
408+
public void sendExternalBeginFrame();
409+
401410
/**
402411
* Returns the maximum rate in frames per second (fps) that {@code CefRenderHandler::onPaint}
403412
* will be called for a windowless browser. The actual fps may be lower if the browser cannot

0 commit comments

Comments
 (0)