From cb34500d68fecdf53e671f8dea9521038703c1c9 Mon Sep 17 00:00:00 2001 From: Izuna Seikatsu Date: Thu, 26 Jun 2025 03:01:32 +0200 Subject: [PATCH 1/3] feat: accelerated paint --- java/org/cef/CefBrowserSettings.java | 19 +++++ java/org/cef/CefClient.java | 10 +++ java/org/cef/browser/CefBrowser.java | 9 +++ java/org/cef/browser/CefBrowserOsr.java | 6 ++ java/org/cef/browser/CefBrowser_N.java | 9 +++ .../cef/handler/CefAcceleratedPaintInfo.java | 43 ++++++++++++ .../cef/handler/CefOsrRendererSettings.java | 69 +++++++++++++++++++ java/org/cef/handler/CefRenderHandler.java | 11 +++ .../cef/handler/CefRenderHandlerAdapter.java | 4 ++ native/CefBrowser_N.cpp | 14 +++- native/CefBrowser_N.h | 9 +++ native/jni_util.cpp | 14 ++++ native/jni_util.h | 5 ++ native/render_handler.cpp | 42 +++++++++++ native/render_handler.h | 4 ++ 15 files changed, 267 insertions(+), 1 deletion(-) create mode 100644 java/org/cef/handler/CefAcceleratedPaintInfo.java create mode 100644 java/org/cef/handler/CefOsrRendererSettings.java diff --git a/java/org/cef/CefBrowserSettings.java b/java/org/cef/CefBrowserSettings.java index 8733a418..67a184b3 100644 --- a/java/org/cef/CefBrowserSettings.java +++ b/java/org/cef/CefBrowserSettings.java @@ -4,6 +4,8 @@ package org.cef; +import org.cef.handler.CefOsrRendererSettings; + /** * Browser initialization settings. Specify NULL or 0 to get the recommended * default values. The consequences of using custom values may not be well @@ -20,12 +22,29 @@ public class CefBrowserSettings { */ public int windowless_frame_rate = 0; + /** + * Set to true to enable shared texture rendering. When enabled, the browser + * will render to a shared texture that can be accessed by the host application + * for hardware-accelerated compositing. This is supported on Windows via D3D11, + * macOS via Metal/OpenGL, and Linux via native buffers. + */ + public boolean shared_texture_enabled = false; + + /** + * Set to true to enable external begin frame scheduling. When enabled, the + * client must call CefBrowserHost::SendExternalBeginFrame to trigger frame + * rendering at the specified frame rate. + */ + public boolean external_begin_frame_enabled = false; + public CefBrowserSettings() {} @Override public CefBrowserSettings clone() { CefBrowserSettings tmp = new CefBrowserSettings(); tmp.windowless_frame_rate = windowless_frame_rate; + tmp.shared_texture_enabled = shared_texture_enabled; + tmp.external_begin_frame_enabled = external_begin_frame_enabled; return tmp; } } diff --git a/java/org/cef/CefClient.java b/java/org/cef/CefClient.java index 687be93d..b9fc4559 100644 --- a/java/org/cef/CefClient.java +++ b/java/org/cef/CefClient.java @@ -17,6 +17,7 @@ import org.cef.callback.CefMenuModel; import org.cef.callback.CefPrintDialogCallback; import org.cef.callback.CefPrintJobCallback; +import org.cef.handler.CefAcceleratedPaintInfo; import org.cef.handler.CefClientHandler; import org.cef.handler.CefContextMenuHandler; import org.cef.handler.CefDialogHandler; @@ -768,6 +769,15 @@ public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, realHandler.onPaint(browser, popup, dirtyRects, buffer, width, height); } + @Override + public void onAcceleratedPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, CefAcceleratedPaintInfo info) { + if (browser == null) return; + + CefRenderHandler realHandler = browser.getRenderHandler(); + if (realHandler != null) + realHandler.onAcceleratedPaint(browser, popup, dirtyRects, info); + } + @Override public void addOnPaintListener(Consumer listener) {} diff --git a/java/org/cef/browser/CefBrowser.java b/java/org/cef/browser/CefBrowser.java index 96f8e1ab..16e22749 100644 --- a/java/org/cef/browser/CefBrowser.java +++ b/java/org/cef/browser/CefBrowser.java @@ -405,6 +405,15 @@ public void runFileDialog(FileDialogMode mode, String title, String defaultFileP */ public void setWindowlessFrameRate(int frameRate); + /** + * Send an external begin frame to trigger frame rendering when external begin frame + * scheduling is enabled. This method should be called at the desired frame rate when + * CefBrowserSettings.external_begin_frame_enabled is set to true. + * + * @throws UnsupportedOperationException if not supported + */ + public void sendExternalBeginFrame(); + /** * Returns the maximum rate in frames per second (fps) that {@code CefRenderHandler::onPaint} * will be called for a windowless browser. The actual fps may be lower if the browser cannot diff --git a/java/org/cef/browser/CefBrowserOsr.java b/java/org/cef/browser/CefBrowserOsr.java index b999b6ba..907271b1 100644 --- a/java/org/cef/browser/CefBrowserOsr.java +++ b/java/org/cef/browser/CefBrowserOsr.java @@ -19,6 +19,7 @@ import org.cef.CefClient; import org.cef.OS; import org.cef.callback.CefDragData; +import org.cef.handler.CefAcceleratedPaintInfo; import org.cef.handler.CefRenderHandler; import org.cef.handler.CefScreenInfo; @@ -409,6 +410,11 @@ public void run() { } } + @Override + public void onAcceleratedPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, CefAcceleratedPaintInfo info) { + // TODO: Implement example for accelerated paint + } + @Override public boolean onCursorChange(CefBrowser browser, final int cursorType) { SwingUtilities.invokeLater(new Runnable() { diff --git a/java/org/cef/browser/CefBrowser_N.java b/java/org/cef/browser/CefBrowser_N.java index e46327f1..8df594f6 100644 --- a/java/org/cef/browser/CefBrowser_N.java +++ b/java/org/cef/browser/CefBrowser_N.java @@ -799,6 +799,14 @@ public void setWindowlessFrameRate(int frameRate) { } } + public void sendExternalBeginFrame() { + try { + N_SendExternalBeginFrame(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + public CompletableFuture getWindowlessFrameRate() { final CompletableFuture future = new CompletableFuture<>(); try { @@ -882,5 +890,6 @@ private final native void N_DragTargetDragEnter( private final native void N_SetParent(long windowHandle, Component canvas); private final native void N_NotifyMoveOrResizeStarted(); private final native void N_SetWindowlessFrameRate(int frameRate); + private final native void N_SendExternalBeginFrame(); private final native void N_GetWindowlessFrameRate(IntCallback frameRateCallback); } diff --git a/java/org/cef/handler/CefAcceleratedPaintInfo.java b/java/org/cef/handler/CefAcceleratedPaintInfo.java new file mode 100644 index 00000000..bd8aeedc --- /dev/null +++ b/java/org/cef/handler/CefAcceleratedPaintInfo.java @@ -0,0 +1,43 @@ +// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.handler; + +/** + * Structure representing shared texture info for accelerated painting. + */ +public class CefAcceleratedPaintInfo { + /** + * Shared texture handle. The meaning depends on the platform: + * - Windows: HANDLE to a texture that can be opened with D3D11 OpenSharedResource + * - macOS: IOSurface pointer that can be opened with Metal or OpenGL + * - Linux: Contains several planes, each with an fd to the underlying system native buffer + */ + public long shared_texture_handle = 0; + + /** + * Format of the shared texture. + */ + public int format = 0; + + /** + * Size information for the shared texture. + */ + public int width = 0; + public int height = 0; + + public CefAcceleratedPaintInfo() {} + + public CefAcceleratedPaintInfo(long shared_texture_handle, int format, int width, int height) { + this.shared_texture_handle = shared_texture_handle; + this.format = format; + this.width = width; + this.height = height; + } + + @Override + public CefAcceleratedPaintInfo clone() { + return new CefAcceleratedPaintInfo(shared_texture_handle, format, width, height); + } +} diff --git a/java/org/cef/handler/CefOsrRendererSettings.java b/java/org/cef/handler/CefOsrRendererSettings.java new file mode 100644 index 00000000..a417f03d --- /dev/null +++ b/java/org/cef/handler/CefOsrRendererSettings.java @@ -0,0 +1,69 @@ +// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.handler; + +/** + * Settings for off-screen rendering (OSR) configuration. + * Based on CEF's OsrRendererSettings structure. + */ +public class CefOsrRendererSettings { + + /** + * If true draw a border around update rectangles. + */ + public boolean show_update_rect = false; + + /** + * If true return real screen bounds from GetRootScreenRect/GetScreenInfo. + * - Allows window.outerWidth/Height and window.screenX/Y to return correct values. + * - Allows JavaScript window.moveTo/By() and window.resizeTo/By() to provide + * bounds that include the window frame. + * - Causes HTML select popups to be cropped (limitation of implementation). + */ + public boolean real_screen_bounds = true; + + /** + * Background color. Enables transparency if the alpha component is 0. + * 32-bit ARGB color value, not premultiplied. + */ + public int background_color = 0; + + /** + * Render using shared textures. Supported on Windows only via D3D11. + * When enabled, the browser will render to a shared texture that can be + * accessed by the host application for hardware-accelerated compositing. + */ + public boolean shared_texture_enabled = false; + + /** + * Client implements a BeginFrame timer by calling + * CefBrowserHost::SendExternalBeginFrame at the specified frame rate. + */ + public boolean external_begin_frame_enabled = false; + + /** + * Frame rate for external begin frame when external_begin_frame_enabled is true. + */ + public int begin_frame_rate = 0; + + public CefOsrRendererSettings() {} + + /** + * Copy constructor. + */ + public CefOsrRendererSettings(CefOsrRendererSettings other) { + this.show_update_rect = other.show_update_rect; + this.real_screen_bounds = other.real_screen_bounds; + this.background_color = other.background_color; + this.shared_texture_enabled = other.shared_texture_enabled; + this.external_begin_frame_enabled = other.external_begin_frame_enabled; + this.begin_frame_rate = other.begin_frame_rate; + } + + @Override + public CefOsrRendererSettings clone() { + return new CefOsrRendererSettings(this); + } +} diff --git a/java/org/cef/handler/CefRenderHandler.java b/java/org/cef/handler/CefRenderHandler.java index 258df884..68b5de6a 100644 --- a/java/org/cef/handler/CefRenderHandler.java +++ b/java/org/cef/handler/CefRenderHandler.java @@ -67,6 +67,17 @@ public interface CefRenderHandler { public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, ByteBuffer buffer, int width, int height); + /** + * Called when an element has been rendered to the shared texture handle. + * This method is only called when CefWindowInfo::shared_texture_enabled is set to true. + * @param browser The browser generating the event. + * @param popup True if painting a popup window. + * @param dirtyRects Array of dirty regions. + * @param info Contains the shared handle and texture information. + */ + public void onAcceleratedPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, + CefAcceleratedPaintInfo info); + /** * Add provided listener. * @param listener Code that gets executed after a frame was rendered. diff --git a/java/org/cef/handler/CefRenderHandlerAdapter.java b/java/org/cef/handler/CefRenderHandlerAdapter.java index ea782830..9ff45419 100644 --- a/java/org/cef/handler/CefRenderHandlerAdapter.java +++ b/java/org/cef/handler/CefRenderHandlerAdapter.java @@ -42,6 +42,10 @@ public void onPopupSize(CefBrowser browser, Rectangle size) {} public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, ByteBuffer buffer, int width, int height) {} + @Override + public void onAcceleratedPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, + CefAcceleratedPaintInfo info) {} + @Override public boolean onCursorChange(CefBrowser browser, int cursorType) { return false; diff --git a/native/CefBrowser_N.cpp b/native/CefBrowser_N.cpp index 0e5f8118..ffc6fb8f 100644 --- a/native/CefBrowser_N.cpp +++ b/native/CefBrowser_N.cpp @@ -505,7 +505,7 @@ KeyboardCode KeyboardCodeFromXKeysym(unsigned int keysym) { return VKEY_OEM_7; case XK_ISO_Level5_Shift: return VKEY_OEM_8; - case XK_Shift_L: + case XK_Shift_L: case XK_Shift_R: return VKEY_SHIFT; case XK_Control_L: @@ -1010,6 +1010,10 @@ void create(std::shared_ptr objs, objs->jbrowserSettings != nullptr) { // Dev-tools settings are null GetJNIFieldInt(env, cefBrowserSettings, objs->jbrowserSettings, "windowless_frame_rate", &settings.windowless_frame_rate); + GetJNIFieldBoolean(env, cefBrowserSettings, objs->jbrowserSettings, + "shared_texture_enabled", &windowInfo.shared_texture_enabled); + GetJNIFieldBoolean(env, cefBrowserSettings, objs->jbrowserSettings, + "external_begin_frame_enabled", &windowInfo.external_begin_frame_enabled); } CefRefPtr browserObj; @@ -2170,6 +2174,14 @@ Java_org_cef_browser_CefBrowser_1N_N_1SetWindowlessFrameRate(JNIEnv* env, host->SetWindowlessFrameRate(frameRate); } +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1SendExternalBeginFrame(JNIEnv* env, + jobject jbrowser) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, jbrowser); + CefRefPtr host = browser->GetHost(); + host->SendExternalBeginFrame(); +} + void getWindowlessFrameRate(CefRefPtr host, CefRefPtr callback) { callback->onComplete((jint)host->GetWindowlessFrameRate()); diff --git a/native/CefBrowser_N.h b/native/CefBrowser_N.h index b0348d5d..780dbefb 100644 --- a/native/CefBrowser_N.h +++ b/native/CefBrowser_N.h @@ -567,6 +567,15 @@ Java_org_cef_browser_CefBrowser_1N_N_1GetWindowlessFrameRate(JNIEnv*, jobject, jobject); +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_SendExternalBeginFrame + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1SendExternalBeginFrame(JNIEnv*, + jobject); + #ifdef __cplusplus } #endif diff --git a/native/jni_util.cpp b/native/jni_util.cpp index 9d948330..32120195 100644 --- a/native/jni_util.cpp +++ b/native/jni_util.cpp @@ -895,6 +895,20 @@ bool SetJNIFieldBoolean(JNIEnv* env, return false; } +bool SetJNIFieldLong(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + jlong value) { + jfieldID field = env->GetFieldID(cls, field_name, "J"); + if (field) { + env->SetLongField(obj, field, value); + return true; + } + env->ExceptionClear(); + return false; +} + bool GetJNIFieldStaticInt(JNIEnv* env, jclass cls, const char* field_name, diff --git a/native/jni_util.h b/native/jni_util.h index dd9ba18b..2c1c9d1f 100644 --- a/native/jni_util.h +++ b/native/jni_util.h @@ -154,6 +154,11 @@ bool SetJNIFieldBoolean(JNIEnv* env, jobject obj, const char* field_name, int value); +bool SetJNIFieldLong(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + jlong value); // Retrieve the static int value stored in the |field_name| field of |cls|. bool GetJNIFieldStaticInt(JNIEnv* env, diff --git a/native/render_handler.cpp b/native/render_handler.cpp index dee74281..cedb72ef 100644 --- a/native/render_handler.cpp +++ b/native/render_handler.cpp @@ -270,6 +270,48 @@ void RenderHandler::OnPaint(CefRefPtr browser, jdirectBuffer.get(), width, height); } +void RenderHandler::OnAcceleratedPaint(CefRefPtr browser, + PaintElementType type, + const RectList& dirtyRects, + const CefAcceleratedPaintInfo& info) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + jboolean jtype = type == PET_VIEW ? JNI_FALSE : JNI_TRUE; + ScopedJNIObjectLocal jrectArray(env, NewJNIRectArray(env, dirtyRects)); + + // Create CefAcceleratedPaintInfo Java object + ScopedJNIClass cls(env, "org/cef/handler/CefAcceleratedPaintInfo"); + if (!cls) + return; + ScopedJNIObjectLocal jpaintInfo(env, NewJNIObject(env, cls)); + if (!jpaintInfo) + return; + + // Get view rect to determine width and height + CefRect viewRect; + GetViewRect(browser, viewRect); + // Set the fields of the paint info object +#if defined(OS_WIN) + SetJNIFieldLong(env, cls, jpaintInfo, "shared_texture_handle", + reinterpret_cast(info.shared_texture_handle)); +#else + // On non-Windows platforms, shared_texture_handle is not available + SetJNIFieldLong(env, cls, jpaintInfo, "shared_texture_handle", 0); +#endif + SetJNIFieldInt(env, cls, jpaintInfo, "format", info.format); + SetJNIFieldInt(env, cls, jpaintInfo, "width", viewRect.width); + SetJNIFieldInt(env, cls, jpaintInfo, "height", viewRect.height); + + JNI_CALL_VOID_METHOD(env, handle_, "onAcceleratedPaint", + "(Lorg/cef/browser/CefBrowser;Z[Ljava/awt/" + "Rectangle;Lorg/cef/handler/CefAcceleratedPaintInfo;)V", + jbrowser.get(), jtype, jrectArray.get(), + jpaintInfo.get()); +} + bool RenderHandler::StartDragging(CefRefPtr browser, CefRefPtr drag_data, DragOperationsMask allowed_ops, diff --git a/native/render_handler.h b/native/render_handler.h index 27379d6e..55352392 100644 --- a/native/render_handler.h +++ b/native/render_handler.h @@ -40,6 +40,10 @@ class RenderHandler : public CefRenderHandler { const void* buffer, int width, int height) override; + virtual void OnAcceleratedPaint(CefRefPtr browser, + PaintElementType type, + const RectList& dirtyRects, + const CefAcceleratedPaintInfo& info) override; virtual bool StartDragging(CefRefPtr browser, CefRefPtr drag_data, DragOperationsMask allowed_ops, From 8219703221226f17daf2b10e56f322e15dc7d6b4 Mon Sep 17 00:00:00 2001 From: Izuna Seikatsu Date: Thu, 26 Jun 2025 03:18:56 +0200 Subject: [PATCH 2/3] refactor: remove unused CefOsrRendererSettings --- java/org/cef/CefBrowserSettings.java | 2 - .../cef/handler/CefOsrRendererSettings.java | 69 ------------------- 2 files changed, 71 deletions(-) delete mode 100644 java/org/cef/handler/CefOsrRendererSettings.java diff --git a/java/org/cef/CefBrowserSettings.java b/java/org/cef/CefBrowserSettings.java index 67a184b3..36e09598 100644 --- a/java/org/cef/CefBrowserSettings.java +++ b/java/org/cef/CefBrowserSettings.java @@ -4,8 +4,6 @@ package org.cef; -import org.cef.handler.CefOsrRendererSettings; - /** * Browser initialization settings. Specify NULL or 0 to get the recommended * default values. The consequences of using custom values may not be well diff --git a/java/org/cef/handler/CefOsrRendererSettings.java b/java/org/cef/handler/CefOsrRendererSettings.java deleted file mode 100644 index a417f03d..00000000 --- a/java/org/cef/handler/CefOsrRendererSettings.java +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package org.cef.handler; - -/** - * Settings for off-screen rendering (OSR) configuration. - * Based on CEF's OsrRendererSettings structure. - */ -public class CefOsrRendererSettings { - - /** - * If true draw a border around update rectangles. - */ - public boolean show_update_rect = false; - - /** - * If true return real screen bounds from GetRootScreenRect/GetScreenInfo. - * - Allows window.outerWidth/Height and window.screenX/Y to return correct values. - * - Allows JavaScript window.moveTo/By() and window.resizeTo/By() to provide - * bounds that include the window frame. - * - Causes HTML select popups to be cropped (limitation of implementation). - */ - public boolean real_screen_bounds = true; - - /** - * Background color. Enables transparency if the alpha component is 0. - * 32-bit ARGB color value, not premultiplied. - */ - public int background_color = 0; - - /** - * Render using shared textures. Supported on Windows only via D3D11. - * When enabled, the browser will render to a shared texture that can be - * accessed by the host application for hardware-accelerated compositing. - */ - public boolean shared_texture_enabled = false; - - /** - * Client implements a BeginFrame timer by calling - * CefBrowserHost::SendExternalBeginFrame at the specified frame rate. - */ - public boolean external_begin_frame_enabled = false; - - /** - * Frame rate for external begin frame when external_begin_frame_enabled is true. - */ - public int begin_frame_rate = 0; - - public CefOsrRendererSettings() {} - - /** - * Copy constructor. - */ - public CefOsrRendererSettings(CefOsrRendererSettings other) { - this.show_update_rect = other.show_update_rect; - this.real_screen_bounds = other.real_screen_bounds; - this.background_color = other.background_color; - this.shared_texture_enabled = other.shared_texture_enabled; - this.external_begin_frame_enabled = other.external_begin_frame_enabled; - this.begin_frame_rate = other.begin_frame_rate; - } - - @Override - public CefOsrRendererSettings clone() { - return new CefOsrRendererSettings(this); - } -} From c5d269e70c42153441fa9630de51a6dab1bd68b5 Mon Sep 17 00:00:00 2001 From: Izuna Seikatsu Date: Thu, 26 Jun 2025 06:22:07 +0200 Subject: [PATCH 3/3] feat: CefAcceleratedPaintEvent --- java/org/cef/CefClient.java | 9 ++++ .../cef/browser/CefAcceleratedPaintEvent.java | 48 ++++++++++++++++++ java/org/cef/browser/CefBrowserOsr.java | 50 ++++++++++++++++++- java/org/cef/handler/CefRenderHandler.java | 19 +++++++ 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 java/org/cef/browser/CefAcceleratedPaintEvent.java diff --git a/java/org/cef/CefClient.java b/java/org/cef/CefClient.java index b9fc4559..cfd1d87b 100644 --- a/java/org/cef/CefClient.java +++ b/java/org/cef/CefClient.java @@ -787,6 +787,15 @@ public void setOnPaintListener(Consumer listener) {} @Override public void removeOnPaintListener(Consumer listener) {} + @Override + public void addOnAcceleratedPaintListener(Consumer listener) {} + + @Override + public void setOnAcceleratedPaintListener(Consumer listener) {} + + @Override + public void removeOnAcceleratedPaintListener(Consumer listener) {} + @Override public boolean startDragging(CefBrowser browser, CefDragData dragData, int mask, int x, int y) { if (browser == null) return false; diff --git a/java/org/cef/browser/CefAcceleratedPaintEvent.java b/java/org/cef/browser/CefAcceleratedPaintEvent.java new file mode 100644 index 00000000..4b840b10 --- /dev/null +++ b/java/org/cef/browser/CefAcceleratedPaintEvent.java @@ -0,0 +1,48 @@ +// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.browser; + +import org.cef.handler.CefAcceleratedPaintInfo; + +import java.awt.*; + +public class CefAcceleratedPaintEvent { + private final CefBrowser browser; + private final boolean popup; + private final Rectangle[] dirtyRects; + private final CefAcceleratedPaintInfo acceleratedPaintInfo; + + public CefAcceleratedPaintEvent(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, + CefAcceleratedPaintInfo acceleratedPaintInfo) { + this.browser = browser; + this.popup = popup; + this.dirtyRects = dirtyRects; + this.acceleratedPaintInfo = acceleratedPaintInfo; + } + + public CefBrowser getBrowser() { + return browser; + } + + public boolean getPopup() { + return popup; + } + + public Rectangle[] getDirtyRects() { + return dirtyRects; + } + + public CefAcceleratedPaintInfo getAcceleratedPaintInfo() { + return acceleratedPaintInfo; + } + + public int getWidth() { + return acceleratedPaintInfo.width; + } + + public int getHeight() { + return acceleratedPaintInfo.height; + } +} diff --git a/java/org/cef/browser/CefBrowserOsr.java b/java/org/cef/browser/CefBrowserOsr.java index 907271b1..1cd45040 100644 --- a/java/org/cef/browser/CefBrowserOsr.java +++ b/java/org/cef/browser/CefBrowserOsr.java @@ -91,6 +91,9 @@ class CefBrowserOsr extends CefBrowser_N implements CefRenderHandler { private CopyOnWriteArrayList> onPaintListeners = new CopyOnWriteArrayList<>(); + private CopyOnWriteArrayList> onAcceleratedPaintListeners = + new CopyOnWriteArrayList<>(); + CefBrowserOsr(CefClient client, String url, boolean transparent, CefRequestContext context, CefBrowserSettings settings) { this(client, url, transparent, context, null, null, settings); @@ -379,6 +382,22 @@ public void removeOnPaintListener(Consumer listener) { onPaintListeners.remove(listener); } + @Override + public void addOnAcceleratedPaintListener(Consumer listener) { + onAcceleratedPaintListeners.add(listener); + } + + @Override + public void setOnAcceleratedPaintListener(Consumer listener) { + onAcceleratedPaintListeners.clear(); + onAcceleratedPaintListeners.add(listener); + } + + @Override + public void removeOnAcceleratedPaintListener(Consumer listener) { + onAcceleratedPaintListeners.remove(listener); + } + @Override public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, ByteBuffer buffer, int width, int height) { @@ -412,7 +431,36 @@ public void run() { @Override public void onAcceleratedPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, CefAcceleratedPaintInfo info) { - // TODO: Implement example for accelerated paint + // If window is closing, canvas_ or opengl context could be null + final GLContext context = canvas_ != null ? canvas_.getContext() : null; + + if (context == null) { + return; + } + + // This result can occur due to GLContext re-initialization when changing displays. + if (context.makeCurrent() == GLContext.CONTEXT_NOT_CURRENT) { + return; + } + + // TODO: Implement renderer handling for accelerated paint + // On Windows, convert the D3D11 shared texture handle using ImportMemoryWin32HandleEXT + // through OpenGL's EXT_external_objects_win32. LWJGL supports it, but I am not familiar with JOGL's API. + // renderer_.onAcceleratedPaint(canvas_.getGL().getGL2(), popup, dirtyRects, info); + + context.release(); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + canvas_.display(); + } + }); + if (!onAcceleratedPaintListeners.isEmpty()) { + CefAcceleratedPaintEvent paintEvent = + new CefAcceleratedPaintEvent(browser, popup, dirtyRects, info); + for (Consumer l : onAcceleratedPaintListeners) { + l.accept(paintEvent); + } + } } @Override diff --git a/java/org/cef/handler/CefRenderHandler.java b/java/org/cef/handler/CefRenderHandler.java index 68b5de6a..47754504 100644 --- a/java/org/cef/handler/CefRenderHandler.java +++ b/java/org/cef/handler/CefRenderHandler.java @@ -4,6 +4,7 @@ package org.cef.handler; +import org.cef.browser.CefAcceleratedPaintEvent; import org.cef.browser.CefBrowser; import org.cef.browser.CefPaintEvent; import org.cef.callback.CefDragData; @@ -78,6 +79,24 @@ public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, public void onAcceleratedPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, CefAcceleratedPaintInfo info); + /** + * Add provided listener for accelerated paint events. + * @param listener Code that gets executed after a frame was rendered with accelerated painting. + */ + public void addOnAcceleratedPaintListener(Consumer listener); + + /** + * Remove existing accelerated paint listeners and replace with provided listener. + * @param listener Code that gets executed after a frame was rendered with accelerated painting. + */ + public void setOnAcceleratedPaintListener(Consumer listener); + + /** + * Remove provided accelerated paint listener. + * @param listener Code that gets executed after a frame was rendered with accelerated painting. + */ + public void removeOnAcceleratedPaintListener(Consumer listener); + /** * Add provided listener. * @param listener Code that gets executed after a frame was rendered.