Unverified Commit 67e0c0b8 authored by Igor Demin's avatar Igor Demin Committed by GitHub

Fix "ComposePanel doesn't use hardware acceleration with...

Fix "ComposePanel doesn't use hardware acceleration with RenderSettings.SwingGraphics on Linux" (#1103)

Fixes https://youtrack.jetbrains.com/issue/CMP-8936

`glXChooseFBConfig` fails to find a config with `GLX_DOUBLEBUFFER,
False` on my machine, it only has double buffered configs. But
double/single buffering doesn't matter as we use pixel buffers.

Also choose a correct config that is required by
https://registry.khronos.org/OpenGL-Refpages/gl2.1/xhtml/glXCreatePbuffer.xml:
```
BadMatch is generated if config does not support rendering to pixel buffers (e.g., GLX_DRAWABLE_TYPE does not contain GLX_PBUFFER_BIT)
```

## Testing
- manually, in the clocks example
- the modified test failed before the fix, now it doesn't fail

## Release Notes (Skiko)
Fix "SkiaSwingLayer doesn't use hardware acceleration on Linux"

## Release Notes (Compose)
### Fixes - Desktop 
Fix "ComposePanel doesn't use hardware acceleration with
RenderSettings.SwingGraphics on Linux"
parent 6e963769
...@@ -164,7 +164,7 @@ jobs: ...@@ -164,7 +164,7 @@ jobs:
sudo apt-get install gcc-9-aarch64-linux-gnu g++-9-aarch64-linux-gnu -y sudo apt-get install gcc-9-aarch64-linux-gnu g++-9-aarch64-linux-gnu -y
sudo update-alternatives --install /usr/bin/aarch64-linux-gnu-gcc aarch64-linux-gnu-gcc /usr/bin/aarch64-linux-gnu-gcc-9 60 --slave /usr/bin/aarch64-linux-gnu-g++ aarch64-linux-gnu-g++ /usr/bin/aarch64-linux-gnu-g++-9 sudo update-alternatives --install /usr/bin/aarch64-linux-gnu-gcc aarch64-linux-gnu-gcc /usr/bin/aarch64-linux-gnu-gcc-9 60 --slave /usr/bin/aarch64-linux-gnu-g++ aarch64-linux-gnu-g++ /usr/bin/aarch64-linux-gnu-g++-9
sudo update-alternatives --config aarch64-linux-gnu-gcc sudo update-alternatives --config aarch64-linux-gnu-gcc
sudo Xvfb :0 -screen 0 1280x720x24 & sudo Xvfb :0 -screen 0 1280x720x24 +extension GLX &
- shell: bash - shell: bash
name: 'Compile and run Linux x64 tests' name: 'Compile and run Linux x64 tests'
...@@ -238,7 +238,7 @@ jobs: ...@@ -238,7 +238,7 @@ jobs:
sudo apt-get remove g++ -y sudo apt-get remove g++ -y
sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-11 100 sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-11 100
sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-11 100 sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-11 100
sudo Xvfb :0 -screen 0 1280x720x24 & sudo Xvfb :0 -screen 0 1280x720x24 +extension GLX &
- shell: bash - shell: bash
name: 'Run Linux arm64 tests' name: 'Run Linux arm64 tests'
...@@ -286,9 +286,10 @@ jobs: ...@@ -286,9 +286,10 @@ jobs:
java-version: '21' java-version: '21'
cache: 'gradle' cache: 'gradle'
# OPENGL is ignored as it doesn't exist on the Windows GitHub agent
- shell: bash - shell: bash
name: 'Compile and run AWT tests' name: 'Compile and run AWT tests'
run: ./gradlew --stacktrace --info -Pskiko.test.onci=true :skiko:awtTest run: ./gradlew --stacktrace --info -Pskiko.test.onci=true -Pskiko.test.ui.renderApi.ignoreAssertsFor=OPENGL :skiko:awtTest
- shell: bash - shell: bash
name: 'Publish to Maven Local, check AWT sample' name: 'Publish to Maven Local, check AWT sample'
......
...@@ -504,6 +504,7 @@ fun SkikoProjectContext.setupJvmTestTask(skikoAwtJarForTests: TaskProvider<Jar>, ...@@ -504,6 +504,7 @@ fun SkikoProjectContext.setupJvmTestTask(skikoAwtJarForTests: TaskProvider<Jar>,
) )
systemProperty("skiko.test.ui.enabled", System.getProperty("skiko.test.ui.enabled", canRunUiTests.toString())) systemProperty("skiko.test.ui.enabled", System.getProperty("skiko.test.ui.enabled", canRunUiTests.toString()))
systemProperty("skiko.test.ui.renderApi", System.getProperty("skiko.test.ui.renderApi", "all")) systemProperty("skiko.test.ui.renderApi", System.getProperty("skiko.test.ui.renderApi", "all"))
systemProperty("skiko.test.ui.renderApi.ignoreAssertsFor", System.getProperty("skiko.test.ui.renderApi.ignoreAssertsFor", "OPENGL"))
systemProperty("skiko.test.debug", buildType == SkiaBuildType.DEBUG) systemProperty("skiko.test.debug", buildType == SkiaBuildType.DEBUG)
// Tests should be deterministic, so disable scaling. // Tests should be deterministic, so disable scaling.
......
...@@ -30,9 +30,8 @@ public: ...@@ -30,9 +30,8 @@ public:
static OffScreenContext* create() { static OffScreenContext* create() {
const int glxContextAttribs[] { const int glxContextAttribs[] {
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DOUBLEBUFFER, False,
GLX_RED_SIZE, 8, GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8, GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8, GLX_BLUE_SIZE, 8,
......
...@@ -182,6 +182,8 @@ class SkiaLayerTest { ...@@ -182,6 +182,8 @@ class SkiaLayerTest {
window.layer.needRedraw() window.layer.needRedraw()
delay(1000) delay(1000)
screenshots.assert(window.bounds, "frame2") screenshots.assert(window.bounds, "frame2")
assertRenderApiFor(window.layer)
} finally { } finally {
window.close() window.close()
} }
...@@ -211,6 +213,8 @@ class SkiaLayerTest { ...@@ -211,6 +213,8 @@ class SkiaLayerTest {
layer.repaint() layer.repaint()
delay(1000) delay(1000)
screenshots.assert(window.bounds, "frame2") screenshots.assert(window.bounds, "frame2")
assertRenderApiFor(layer)
} finally { } finally {
window.close() window.close()
} }
...@@ -237,6 +241,8 @@ class SkiaLayerTest { ...@@ -237,6 +241,8 @@ class SkiaLayerTest {
window.layer.needRedraw() window.layer.needRedraw()
delay(1000) delay(1000)
screenshots.assert(window.bounds, "frame2") screenshots.assert(window.bounds, "frame2")
assertRenderApiFor(window.layer)
} finally { } finally {
window.close() window.close()
} }
...@@ -288,6 +294,8 @@ class SkiaLayerTest { ...@@ -288,6 +294,8 @@ class SkiaLayerTest {
layer.size = Dimension(40, 40) layer.size = Dimension(40, 40)
delay(1000) delay(1000)
assertEquals((40 * density).toInt(), renderedWidth) assertEquals((40 * density).toInt(), renderedWidth)
assertRenderApiFor(layer)
} finally { } finally {
layer.dispose() layer.dispose()
window.close() window.close()
...@@ -330,6 +338,8 @@ class SkiaLayerTest { ...@@ -330,6 +338,8 @@ class SkiaLayerTest {
box.setBounds(100, 0, 100, 100) box.setBounds(100, 0, 100, 100)
delay(1000) delay(1000)
screenshots.assert(window.bounds, "frame2") screenshots.assert(window.bounds, "frame2")
assertRenderApiFor(layer)
} finally { } finally {
layer.dispose() layer.dispose()
window.close() window.close()
...@@ -352,6 +362,8 @@ class SkiaLayerTest { ...@@ -352,6 +362,8 @@ class SkiaLayerTest {
delay(1000) delay(1000)
screenshots.assert(window.bounds) screenshots.assert(window.bounds)
assertRenderApiFor(window.layer)
} finally { } finally {
window.close() window.close()
} }
...@@ -386,6 +398,10 @@ class SkiaLayerTest { ...@@ -386,6 +398,10 @@ class SkiaLayerTest {
window3.toFront() window3.toFront()
delay(1000) delay(1000)
screenshots.assert(window3.bounds, "window3") screenshots.assert(window3.bounds, "window3")
assertRenderApiFor(window1.layer)
assertRenderApiFor(window2.layer)
assertRenderApiFor(window3.layer)
} finally { } finally {
window1.close() window1.close()
window2.close() window2.close()
...@@ -410,6 +426,7 @@ class SkiaLayerTest { ...@@ -410,6 +426,7 @@ class SkiaLayerTest {
delay(1000) delay(1000)
assertEquals(true, stateRemainsFullscreen) assertEquals(true, stateRemainsFullscreen)
assertRenderApiFor(window.layer)
} finally { } finally {
window.close() window.close()
...@@ -490,6 +507,10 @@ class SkiaLayerTest { ...@@ -490,6 +507,10 @@ class SkiaLayerTest {
if (delayCount > 0) { if (delayCount > 0) {
delay(delayCount * 10) delay(delayCount * 10)
} }
openedWindows.forEach {
assertRenderApiFor(it.layer)
}
} }
openedWindows.forEach(JFrame::close) openedWindows.forEach(JFrame::close)
...@@ -514,6 +535,7 @@ class SkiaLayerTest { ...@@ -514,6 +535,7 @@ class SkiaLayerTest {
repeat(100) { repeat(100) {
window.size = Dimension(200 + Random.nextInt(200), 200 + Random.nextInt(200)) window.size = Dimension(200 + Random.nextInt(200), 200 + Random.nextInt(200))
window.paint(window.graphics) window.paint(window.graphics)
assertRenderApiFor(window.layer)
yield() yield()
} }
...@@ -542,6 +564,7 @@ class SkiaLayerTest { ...@@ -542,6 +564,7 @@ class SkiaLayerTest {
window.layer.needRedraw() window.layer.needRedraw()
yield() yield()
window.paint(window.graphics) window.paint(window.graphics)
assertRenderApiFor(window.layer)
window.close() window.close()
} }
} }
...@@ -690,6 +713,7 @@ class SkiaLayerTest { ...@@ -690,6 +713,7 @@ class SkiaLayerTest {
window.isVisible = true window.isVisible = true
onDrawCompleted.await() onDrawCompleted.await()
assertRenderApiFor(window.layer)
} finally { } finally {
window.close() window.close()
} }
...@@ -977,6 +1001,7 @@ class SkiaLayerTest { ...@@ -977,6 +1001,7 @@ class SkiaLayerTest {
assertEquals(0, lineMetrics.first().lineNumber) assertEquals(0, lineMetrics.first().lineNumber)
screenshots.assert(window.bounds) screenshots.assert(window.bounds)
assertRenderApiFor(window.layer)
} finally { } finally {
window.close() window.close()
} }
......
...@@ -3,6 +3,8 @@ package org.jetbrains.skiko.util ...@@ -3,6 +3,8 @@ package org.jetbrains.skiko.util
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.jetbrains.skiko.* import org.jetbrains.skiko.*
import org.jetbrains.skiko.swing.SkiaSwingLayer
import org.junit.Assert.assertEquals
import org.junit.Assume.assumeFalse import org.junit.Assume.assumeFalse
import org.junit.Assume.assumeTrue import org.junit.Assume.assumeTrue
import java.awt.GraphicsEnvironment import java.awt.GraphicsEnvironment
...@@ -60,6 +62,25 @@ internal class UiTestScope( ...@@ -60,6 +62,25 @@ internal class UiTestScope(
setupContent() setupContent()
} }
} }
private val ignoreAssertsFor =
System.getProperty("skiko.test.ui.renderApi.ignoreAssertsFor")
.split(",")
.filter { it.isNotBlank() }
.map(GraphicsApi::valueOf)
fun assertRenderApiFor(layer: SkiaLayer) {
if (renderApi !in ignoreAssertsFor) {
assertEquals(renderApi, layer.renderApi)
}
}
@OptIn(ExperimentalSkikoApi::class)
fun assertRenderApiFor(layer: SkiaSwingLayer) {
if (renderApi !in ignoreAssertsFor) {
assertEquals(renderApi, layer.renderApi)
}
}
} }
internal abstract class UiTestWindow : JFrame() { internal abstract class UiTestWindow : JFrame() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment