jramosd / javachromiumembedded

Automatically exported from code.google.com/p/javachromiumembedded
0 stars 0 forks source link

JCEF MainFrame sample app displays blank over remote deskop on Windows 7 in OSR mode #34

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Connect to a Windows box through remote desktop (e.g. Windows 7)
2. Start the JCEF MainFrame sample app from within that remote desktop session
3. App comes up but open gl area is rendered blank

What is the expected output? What do you see instead?
Expect to see the web site rendered instead of blank

What version of the product are you using? On what operating system?
jcef_binary_3.1650.1501.9_windows64_preview.7z

Please provide any additional information below.

I understand the remote desktop scenario isn't necessarily high on everyone's 
agenda. And the goal isn't to have super high performance rendering over a 
remote session anyway. But note that this pb doesn't affect the native CEF 
client app nor of course the standalone Chrome browser. It's related to a call 
JCEF uses from JOGL.

When creating the GL Canvas from within a remote desktop session, MSFT uses an 
open gl driver that uses software, not hardware support 
(gl2.getContext().isHardwareRasterizer() is false). This doesn’t support some 
Open GL 2.0 features, among them support for npot textures – non power of two 
textures. JCEF gets a buffer from the rendering engine and renders it as an 
open gl texture of size (width,height) with the call glTexImage2D inside 
CefRender.onPaint. That call fails when using the emulated open gl MSFT driver. 
Same issue for glTexSubImage2D.

Here's the code that fails:
gl2.glTexImage2D(gl2.GL_TEXTURE_2D, 0, gl2.GL_RGBA, view_width_, view_height_, 
0,
                         gl2.GL_BGRA, gl2.GL_UNSIGNED_INT_8_8_8_8_REV, buffer);

You can find out by starting MainFrame.java with the flag -Djogl.debug.DebugGL

You'll get this kind of exception:
javax.media.opengl.GLException: Thread[AWT-EventQueue-0,6,main] glGetError() 
returned the following error codes after a call to glTexImage2D(<int> 0xDE1, 
<int> 0x0, <int> 0x1907, <int> 0x310, <int> 0x201, <int> 0x0, <int> 0x1907, 
<int> 0x1401, <java.nio.Buffer> java.nio.DirectByteBuffer[pos=0 lim=1608768 
cap=1608768]): GL_INVALID_VALUE ( 1281 0x501), 
    at javax.media.opengl.DebugGL4bc.writeGLError(DebugGL4bc.java:29412)
    at javax.media.opengl.DebugGL4bc.glTexImage2D(DebugGL4bc.java:19877)
    at org.cef.CefRenderer.onPaint(CefRenderer.java:253)
    at org.cef.CefClient.onPaint(CefClient.java:259)
    at org.cef.CefContext.N_DoMessageLoopWork(Native Method)
    at org.cef.CefContext.doMessageLoopWork(CefContext.java:57)
    at org.cef.MainFrame$1$1.run(MainFrame.java:41)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:694)
    at java.awt.EventQueue$3.run(EventQueue.java:692)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:703)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

This can be reproduced with a pure JOGL example (I can provide it if you wish). 
I've been searching about these open-gl texture calls and I wrote a horrible 
hack - turning the ByteBuffer RGBA received from onPaint into a new ByteBuffer 
RGB with 512x512 and got things to draw over remote desktop - albeit truncated 
of course.

I would appreciate any tip from a JCEF/CEF/JOGL/Open GL guru here :-)

Original issue reported on code.google.com by christop...@gmail.com on 24 Jan 2014 at 2:25

GoogleCodeExporter commented 9 years ago
I explored another workaround listed here.
http://www.opengl.org/discussion_boards/showthread.php/164372-Remote-Desktop
"You can do that with Mesa3D : current version is 7.2, and support OpenGL 2.1 
in a complete software implementation.
Compile or find a windows mesa .dll, and put it as opengl32.dll on your exe 
folder."

I got the mesa opengl32.dll (18MB...) and installed it into the folder that 
contains the java.exe. Then it displayed fine when started from a remote 
desktop session.

But copying things to the JDK/JRE folder isn't great. I was hoping MSFT would 
search for the current dir or entries in %PATH% before reaching to the 
system32, but that didn't work in my test. The only way it would use it would 
be after I remove MSFT's opengl32.dll from system32/.

Tips welcome, I'm interested in a friendly workaround - either by avoiding the 
calls not supported by MSFT opengl32.dll or by finding a way to tell jogl to 
use an alternative opengl32.dll in the current dir...

Original comment by christop...@gmail.com on 24 Jan 2014 at 6:24

GoogleCodeExporter commented 9 years ago
In case anyone wants to test comment 1 above, here's a link to a binary of mesa 
opengl32.dll : 
http://hivelocity.dl.sourceforge.net/project/msys2/REPOS/MINGW/x86_64/mingw-w64-
x86_64-mesa-10.0.1-2-any.pkg.tar.xz

Original comment by christop...@gmail.com on 24 Jan 2014 at 6:46

GoogleCodeExporter commented 9 years ago
The following code renders the whole buffer with glDrawPixels when we detect 
hardware rendering isn't available. This works over MSFT Remote Desktop. What 
do you think? I suspect a CEF or OpenGL expert would have better alternatives 
to suggest?

CefRenderer.java

  //Workaround for Windows Remote Desktop unable to deal with npot textures
  private boolean useDrawPixels = false;

  protected void initialize(GL2 gl2) {
    if (initialized_)
      return;

    if (!gl2.getContext().isHardwareRasterizer()) {
        useDrawPixels = true;
        System.out.println("opengl rendering may be slow as hardware rendering isn't available");
        initialized_ = true;
        return;
    }
...

  protected void render(GL2 gl2) {
    if (useDrawPixels) {
        return;
    }
...

  protected void onPaint(GL2 gl2,
                         boolean popup,
                         Rectangle[] dirtyRects,
                         ByteBuffer buffer,
                         int width,
                         int height) {
    if (!initialized_)
      initialize(gl2);

    if (useDrawPixels) {
        gl2.glRasterPos2f(-1,1);
        gl2.glPixelZoom( 1, -1 );
        gl2.glDrawPixels(width, height, GL2.GL_BGRA, GL2.GL_UNSIGNED_BYTE, buffer);
        return;
    }
...

Original comment by christop...@gmail.com on 27 Jan 2014 at 4:31

GoogleCodeExporter commented 9 years ago
How does the glDrawPixels approach behave from a performance standpoint 
(framerate, CPU/GPU usage) compared to the texture approach?

Other approaches include creating the view from a grid of tiled power-of-2 
textures, or creating a single power-of-2 texture that is larger than the 
window size and only rendering to a portion of it.

To support the maximal number of devices it might be worthwhile to use only 
GLES2 interfaces (issue #19).

Original comment by magreenb...@gmail.com on 27 Jan 2014 at 11:05

GoogleCodeExporter commented 9 years ago
> How does the glDrawPixels approach behave from a performance standpoint 
(framerate, CPU/GPU usage) compared to the texture approach?

I pointed MainFrame.java to this site http://www.smashcat.org/av/canvas_test/ . 
If you have a preferred graphics benchmark, let me know and I'll re-run the 
tests.

To my surprise, there wasn't much difference between the 2 approaches in this 
particular case. The FPS wasn't affected and the GPU/CPU load didn't really 
differ.

1) Original (textures)
FPS: ~ 160
GPU load: ~ 17%
CPU load: ~ 5%

2) glDrawPixels
FPS: ~ 160
GPU load: ~ 21%
CPU load: ~ 6%

3) glDrawPixels over Remote Desktop (over a fast LAN)
FPS: ~ 174 (not sure this is the effective RDP rate but it felt smooth anyway)

Original comment by christop...@gmail.com on 28 Jan 2014 at 2:18

GoogleCodeExporter commented 9 years ago

Original comment by magreenb...@gmail.com on 17 Jun 2014 at 6:34

GoogleCodeExporter commented 9 years ago
Thanks, added in revision 86. There's probably a better way to test if non-pot 
textures are supported (there might be some hardware that doesn't support it 
too), but I'm not sure what it is.

Original comment by magreenb...@gmail.com on 17 Jun 2014 at 6:50