aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2019-12-07 08:33:48 +0100
committerSven Gothel <[email protected]>2019-12-07 08:33:48 +0100
commit6f750711fbcdf746451995e71165bbd119694269 (patch)
treec6f24d7d497650bce021a74f16851492ae1c813c
parentb992423477ea1a76fb28946e28959a3feea97680 (diff)
Bug 1156: DRM/GBM NEWT: Clarify drmModeSetCrtc(..)'s x/y parameter and earmark spanning across monitors
drmModeSetCrtc(..)'s x/y parameter are the surface's offset to be scanned out from one CRT!
-rw-r--r--src/newt/classes/jogamp/newt/driver/egl/gbm/WindowDriver.java163
-rw-r--r--src/newt/native/drm_gbm_legacy.c81
2 files changed, 84 insertions, 160 deletions
diff --git a/src/newt/classes/jogamp/newt/driver/egl/gbm/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/egl/gbm/WindowDriver.java
index ce1ffc1da..6d9940b95 100644
--- a/src/newt/classes/jogamp/newt/driver/egl/gbm/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/egl/gbm/WindowDriver.java
@@ -33,8 +33,6 @@ import com.jogamp.common.nio.Buffers;
import com.jogamp.nativewindow.AbstractGraphicsScreen;
import com.jogamp.nativewindow.NativeWindowException;
import com.jogamp.nativewindow.util.Point;
-import com.jogamp.nativewindow.util.Rectangle;
-import com.jogamp.nativewindow.util.RectangleImmutable;
import com.jogamp.newt.Display;
import com.jogamp.newt.event.MouseEvent;
import com.jogamp.opengl.GLCapabilitiesChooser;
@@ -70,95 +68,24 @@ public class WindowDriver extends WindowImpl {
windowHandleClose = 0;
}
- /**
- * Clamp given rectangle to given screen bounds.
- *
- * @param screen
- * @param rect the {@link RectangleImmutable} in pixel units
- * @param definePosSize if {@code true} issue {@link #definePosition(int, int)} and {@link #defineSize(int, int)}
- * if either has changed.
- * @return If position or size has been clamped a new {@link RectangleImmutable} instance w/ clamped values
- * will be returned, otherwise the given {@code rect} is returned.
- */
- private RectangleImmutable clampRect(final ScreenDriver screen, final RectangleImmutable rect, final boolean definePosSize) {
- int x = rect.getX();
- int y = rect.getY();
- int w = rect.getWidth();
- int h = rect.getHeight();
- final int s_w = screen.getWidth();
- final int s_h = screen.getHeight();
+ private void zeroPosition(final ScreenDriver screen, int x, int y) {
boolean modPos = false;
- boolean modSize = false;
- if( 0 > x ) {
+ if( 0 != x ) {
x = 0;
modPos = true;
}
- if( 0 > y ) {
+ if( 0 != y ) {
y = 0;
modPos = true;
}
- if( s_w < x + w ) {
- if( 0 < x ) {
- x = 0;
- modPos = true;
- }
- if( s_w < w ) {
- w = s_w;
- modSize = true;
- }
- }
- if( s_h < y + h ) {
- if( 0 < y ) {
- y = 0;
- modPos = true;
- }
- if( s_h < h ) {
- h = s_h;
- modSize = true;
- }
- }
- if( modPos || modSize ) {
- if( definePosSize ) {
- if( modPos ) {
- definePosition(x, y);
- }
- if( modSize ) {
- defineSize(w, h);
- }
- }
- return new Rectangle(x, y, w, h);
- } else {
- return rect;
+ if( modPos ) {
+ definePosition(x, y);
}
}
-
- /**
- * Align given rectangle to given screen bounds.
- *
- * @param screen
- * @param rect the {@link RectangleImmutable} in pixel units
- * @param definePosSize if {@code true} issue {@link #definePosition(int, int)} and {@link #defineSize(int, int)}
- * if either has changed.
- * @return If position or size has been aligned a new {@link RectangleImmutable} instance w/ clamped values
- * will be returned, otherwise the given {@code rect} is returned.
- */
- private RectangleImmutable alignRect2Screen(final ScreenDriver screen, final RectangleImmutable rect, final boolean definePosSize) {
- int x = rect.getX();
- int y = rect.getY();
- int w = rect.getWidth();
- int h = rect.getHeight();
+ private void adjustSize(final ScreenDriver screen, int w, int h) {
final int s_w = screen.getWidth();
final int s_h = screen.getHeight();
- boolean modPos = false;
boolean modSize = false;
- if( 0 != x ) {
- x = 0;
- modPos = true;
- }
- if( 0 != y ) {
- y = 0;
- modPos = true;
- }
if( s_w != w ) {
w = s_w;
modSize = true;
@@ -167,29 +94,15 @@ public class WindowDriver extends WindowImpl {
h = s_h;
modSize = true;
}
- if( modPos || modSize ) {
- if( definePosSize ) {
- if( modPos ) {
- definePosition(x, y);
- }
- if( modSize ) {
- defineSize(w, h);
- }
- }
- return new Rectangle(x, y, w, h);
- } else {
- return rect;
+ if( modSize ) {
+ defineSize(w, h);
}
}
@Override
protected boolean canCreateNativeImpl() {
- // clamp if required incl. redefinition of position and size
- // clampRect((ScreenDriver) getScreen(), new Rectangle(getX(), getY(), getWidth(), getHeight()), true);
-
- // Turns out DRM / GBM can only handle full screen size FB and crtc-modesetting (?)
- alignRect2Screen((ScreenDriver) getScreen(), new Rectangle(getX(), getY(), getWidth(), getHeight()), true);
-
+ zeroPosition((ScreenDriver) getScreen(), getX(), getY());
+ adjustSize((ScreenDriver) getScreen(), getWidth(), getHeight());
return true; // default: always able to be created
}
@@ -292,15 +205,19 @@ public class WindowDriver extends WindowImpl {
final GLContext ctx = GLContext.getCurrent();
final int swapInterval = ctx.getSwapInterval();
- ctx.getGL().glFinish(); // FIXME: Poor man's SYNC: glFenceSync () with glWaitSync() (remove later!)
+ ctx.getGL().glFinish(); // Poor man's SYNC: glFenceSync () with glWaitSync() (remove later!)
if(!EGL.eglSwapBuffers(display.getHandle(), eglSurface)) {
throw new GLException("Error swapping buffers, eglError "+toHexString(EGL.eglGetError())+", "+this);
}
if( 0 == lastBO ) {
- lastBO = FirstSwapSurface(d.drmFd, d.getCrtcIDs()[0], getX(), getY(), d.getConnectors()[0].getConnector_id(),
- d.getModes()[0], nativeWindowHandle, swapInterval);
+ // FIXME: Support spanning across multiple CRTC (surface tiling)
+ final int surfaceOffsetX = 0;
+ final int surfaceOffsetY = 0;
+ lastBO = FirstSwapSurface(d.drmFd, d.getCrtcIDs()[0], surfaceOffsetX, surfaceOffsetY,
+ d.getConnectors()[0].getConnector_id(),
+ d.getModes()[0], nativeWindowHandle);
} else {
- lastBO = NextSwapSurface(d.drmFd, d.getCrtcIDs()[0], getX(), getY(), d.getConnectors()[0].getConnector_id(),
+ lastBO = NextSwapSurface(d.drmFd, d.getCrtcIDs()[0], d.getConnectors()[0].getConnector_id(),
d.getModes()[0], nativeWindowHandle, lastBO, swapInterval);
}
return true; // eglSwapBuffers done!
@@ -382,33 +299,59 @@ public class WindowDriver extends WindowImpl {
protected static native boolean initIDs();
// private native void reconfigure0(long eglWindowHandle, int x, int y, int width, int height, int flags);
- private long FirstSwapSurface(final int drmFd, final int crtc_id, final int x, final int y,
+ /**
+ * First surface swap, actually initial surface/crtc setup.
+ * <p>
+ * {@code surfaceOffsetX} and {@code surfaceOffsetY} explained here
+ * <https://lists.freedesktop.org/archives/dri-devel/2014-February/053826.html>,
+ * useful to span surface across multiple monitors.
+ * </p>
+ * @param drmFd
+ * @param crtc_id the crtc to map to
+ * @param surfaceOffsetX the x-offset of the surface, which could span cross multiple crtc
+ * @param surfaceOffsetY the x-offset of the surface, which could span cross multiple crtc
+ * @param connector_id
+ * @param drmMode
+ * @param gbmSurface the surface to set on the crtc_id
+ * @return
+ */
+ private long FirstSwapSurface(final int drmFd, final int crtc_id, final int surfaceOffsetX, final int surfaceOffsetY,
final int connector_id, final drmModeModeInfo drmMode,
- final long gbmSurface, final int swapInterval) {
+ final long gbmSurface) {
final ByteBuffer bb = drmMode.getBuffer();
if(!Buffers.isDirect(bb)) {
throw new IllegalArgumentException("drmMode's buffer is not direct (NIO)");
}
- return FirstSwapSurface0(drmFd, crtc_id, x, y, connector_id,
+ return FirstSwapSurface0(drmFd, crtc_id, surfaceOffsetX, surfaceOffsetY, connector_id,
bb, Buffers.getDirectBufferByteOffset(bb),
- gbmSurface, swapInterval);
+ gbmSurface);
}
- private native long FirstSwapSurface0(int drmFd, int crtc_id, int x, int y,
+ private native long FirstSwapSurface0(int drmFd, int crtc_id, int surfaceOffsetX, int surfaceOffsetY,
int connector_id, Object mode, int mode_byte_offset,
- long gbmSurface, int swapInterval);
+ long gbmSurface);
- private long NextSwapSurface(final int drmFd, final int crtc_id, final int x, final int y,
+ /**
+ * @param drmFd
+ * @param crtc_id the crtc to swap
+ * @param connector_id
+ * @param drmMode
+ * @param gbmSurface the surface to swap on the given crtc_id
+ * @param lastBO
+ * @param swapInterval the desired swap interval. Zero implies no vsync, otherwise vsync.
+ * @return
+ */
+ private long NextSwapSurface(final int drmFd, final int crtc_id,
final int connector_id, final drmModeModeInfo drmMode,
final long gbmSurface, final long lastBO, final int swapInterval) {
final ByteBuffer bb = drmMode.getBuffer();
if(!Buffers.isDirect(bb)) {
throw new IllegalArgumentException("drmMode's buffer is not direct (NIO)");
}
- return NextSwapSurface0(drmFd, crtc_id, x, y, connector_id,
+ return NextSwapSurface0(drmFd, crtc_id, connector_id,
bb, Buffers.getDirectBufferByteOffset(bb),
gbmSurface, lastBO, swapInterval);
}
- private native long NextSwapSurface0(int drmFd, int crtc_id, int x, int y,
+ private native long NextSwapSurface0(int drmFd, int crtc_id,
int connector_id, Object mode, int mode_byte_offset,
long gbmSurface, long lastBO, int swapInterval);
}
diff --git a/src/newt/native/drm_gbm_legacy.c b/src/newt/native/drm_gbm_legacy.c
index cec3297a8..9c4e19dc3 100644
--- a/src/newt/native/drm_gbm_legacy.c
+++ b/src/newt/native/drm_gbm_legacy.c
@@ -43,7 +43,6 @@ gbm_bo_get_offset(struct gbm_bo *bo, int plane);
typedef struct {
struct gbm_bo *bo;
uint32_t fb_id;
- uint32_t x, y;
} DRM_FB;
static void page_flip_handler(int fd, unsigned int frame,
@@ -180,11 +179,12 @@ static DRM_FB * drm_fb_get_from_bo(int drmFd, struct gbm_bo *bo)
}
JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_egl_gbm_WindowDriver_FirstSwapSurface0
- (JNIEnv *env, jobject obj, jint drmFd, jint jcrtc_id, jint jx, jint jy,
- jint jconnector_id, jobject jmode, jint jmode_byte_offset,
- jlong jgbmSurface, jint swapInterval)
+ (JNIEnv *env, jobject obj, jint drmFd, jint jcrtc_id, jint jsurfaceOffsetX, jint jsurfaceOffsetY,
+ jint jconnector_id, jobject jmode, jint jmode_byte_offset, jlong jgbmSurface)
{
- uint32_t crtc_id = (uint32_t)jcrtc_id;
+ const uint32_t crtc_id = (uint32_t)jcrtc_id;
+ const uint32_t surfaceOffsetX = (uint32_t)jsurfaceOffsetX;
+ const uint32_t surfaceOffsetY = (uint32_t)jsurfaceOffsetY;
uint32_t connector_id = (uint32_t)jconnector_id;
drmModeModeInfo *drmMode = NULL;
struct gbm_surface *gbmSurface = (struct gbm_surface *) (intptr_t) jgbmSurface;
@@ -202,23 +202,34 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_egl_gbm_WindowDriver_FirstSwapSu
ERR_PRINT("Failed to get a new framebuffer BO (0)\n");
return 0;
}
- fb->x = (uint32_t)jx;
- fb->y = (uint32_t)jy;
/**
* Set Mode
*
* Fails with x/y != 0: -28 No space left on device
* drmModeSetCrtc.0 failed to set mode: fd 26, crtc_id 0x27, fb_id 0x54, pos 10/10, conn_id 0x4d, curMode 1920x1080: -28 No space left on device
+ *
+ * See https://lists.freedesktop.org/archives/dri-devel/2014-February/053826.html:
+ *
+ * - The X,Y in drmModeSetCrtc does in fact specify the "source" offset into
+ * your framebuffer (not the destination on the CRTC) which is what I was looking for.
+ *
+ * - We were able to allocate both a Dumb buffer, and a GBM buffer the size of
+ * 6 1920x1200 monitors in a 1x6 configuration, so basically we didn't have
+ * any memory issues with a single buffer that big.
+ *
+ * - drmModeSetCrtc worked with both Dumb and GBM buffers, and we didn't have
+ * to do anything special on our end, so it clearly is handling the tiling
+ * issues behind the scenes (woot).
*/
- ret = drmModeSetCrtc(drmFd, crtc_id, fb->fb_id, fb->x, fb->y,
+ ret = drmModeSetCrtc(drmFd, crtc_id, fb->fb_id, surfaceOffsetX, surfaceOffsetY,
&connector_id, 1, drmMode);
if (ret) {
- ERR_PRINT("drmModeSetCrtc.0 failed to set mode: fd %d, crtc_id 0x%x, fb_id 0x%x, pos %d/%d, conn_id 0x%x, curMode %s: %d %s\n",
- drmFd, crtc_id, fb->fb_id, jx, jy, connector_id, drmMode->name, ret, strerror(errno));
+ ERR_PRINT("drmModeSetCrtc.0 failed to set mode: fd %d, crtc_id 0x%x, fb_id 0x%x (offset %d/%d), conn_id 0x%x, curMode %s: %d %s\n",
+ drmFd, crtc_id, fb->fb_id, surfaceOffsetX, surfaceOffsetY, connector_id, drmMode->name, ret, strerror(errno));
return 0;
}
- DBG_PRINT( "EGL_GBM.Window FirstSwapSurface0 swapInterval %d, nextBO %p, fd %d, crtc_id 0x%x, fb_id 0x%x, pos %d/%d, conn_id 0x%x, curMode %s\n",
- swapInterval, nextBO, drmFd, crtc_id, fb->fb_id, jx, jy, connector_id, drmMode->name);
+ DBG_PRINT( "EGL_GBM.Window FirstSwapSurface0 nextBO %p, fd %d, crtc_id 0x%x, fb_id 0x%x (offset %d/%d), conn_id 0x%x, curMode %s\n",
+ nextBO, drmFd, crtc_id, fb->fb_id, surfaceOffsetX, surfaceOffsetY, connector_id, drmMode->name);
return (jlong) (intptr_t) nextBO;
}
@@ -227,17 +238,16 @@ static int nextSwapVerboseOnce = 1;
#endif
JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_egl_gbm_WindowDriver_NextSwapSurface0
- (JNIEnv *env, jobject obj, jint drmFd, jint jcrtc_id, jint jx, jint jy,
+ (JNIEnv *env, jobject obj, jint drmFd, jint jcrtc_id,
jint jconnector_id, jobject jmode, jint jmode_byte_offset,
jlong jgbmSurface, jlong jlastBO, jint swapInterval)
{
- uint32_t crtc_id = (uint32_t)jcrtc_id;
- uint32_t x = (uint32_t)jx;
- uint32_t y = (uint32_t)jy;
- uint32_t connector_id = (uint32_t)jconnector_id;
+ const uint32_t crtc_id = (uint32_t)jcrtc_id;
+ const uint32_t connector_id = (uint32_t)jconnector_id;
drmModeModeInfo *drmMode = NULL;
struct gbm_surface *gbmSurface = (struct gbm_surface *) (intptr_t) jgbmSurface;
- struct gbm_bo *lastBO = (struct gbm_bo*) (intptr_t) jlastBO, *nextBO = NULL;
+ struct gbm_bo *lastBO = (struct gbm_bo*) (intptr_t) jlastBO;
+ struct gbm_bo *nextBO = NULL;
DRM_FB *fbNext = NULL;
int ret, waiting_for_flip = 1;
fd_set fds;
@@ -252,30 +262,8 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_egl_gbm_WindowDriver_NextSwapSur
ERR_PRINT("Failed to get a new framebuffer BO (1)\n");
return 0;
}
-#if 0
- if( fbNext->x != x || fbNext->y != y ) {
- // position changed, hard drmModeSetCrtc(..) w/o vsync
- fbNext->x = x;
- fbNext->y = y;
-
- /**
- * Set Mode
- *
- * Fails with x/y != 0: -28 No space left on device
- * drmModeSetCrtc.0 failed to set mode: fd 26, crtc_id 0x27, fb_id 0x54, pos 10/10, conn_id 0x4d, curMode 1920x1080: -28 No space left on device
- */
- ret = drmModeSetCrtc(drmFd, crtc_id, fbNext->fb_id, fbNext->x, fbNext->y,
- &connector_id, 1, drmMode);
-
- if (ret) {
- ERR_PRINT("drmModeSetCrtc.1 failed to set mode: fd %d, crtc_id 0x%x, fb_id 0x%x, pos %d/%d, conn_id 0x%x, curMode %s: %d %s\n",
- drmFd, crtc_id, fbNext->fb_id, jx, jy, connector_id, drmMode->name, ret, strerror(errno));
- return 0;
- }
- } else
-#endif
if( 0 != swapInterval) {
- // same position, use vsync
+ // https://github.com/dvdhrm/docs/blob/master/drm-howto/modeset-vsync.c#L614
ret = drmModePageFlip(drmFd, crtc_id, fbNext->fb_id,
DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip);
if (ret) {
@@ -286,9 +274,6 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_egl_gbm_WindowDriver_NextSwapSur
while (waiting_for_flip) {
FD_ZERO(&fds);
-#if 0
- FD_SET(0, &fds); // STDIN_FILENO: We don't want to listen to
-#endif
FD_SET(drmFd, &fds);
ret = select(drmFd + 1, &fds, NULL, NULL, NULL);
@@ -298,10 +283,6 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_egl_gbm_WindowDriver_NextSwapSur
} else if (ret == 0) {
ERR_PRINT("drm.select: select timeout!\n");
return -1;
-#if 0
- } else if (FD_ISSET(0, &fds)) {
- DBG_PRINT("drm.select: stdin carriage return pressed!\n");
-#endif
}
drmHandleEvent(drmFd, &drm_event_ctx);
}
@@ -315,8 +296,8 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_egl_gbm_WindowDriver_NextSwapSur
#ifdef VERBOSE_ON
if( nextSwapVerboseOnce ) {
nextSwapVerboseOnce = 0;
- DBG_PRINT( "EGL_GBM.Window NextSwapSurface0 swapInterval %d, bo %p -> %p, fd %d, crtc_id 0x%x, fb_id 0x%x, pos %d/%d, conn_id 0x%x, curMode %s\n",
- swapInterval, lastBO, nextBO, drmFd, crtc_id, fbNext->fb_id, jx, jy, connector_id, drmMode->name);
+ DBG_PRINT( "EGL_GBM.Window NextSwapSurface0 swapInterval %d, bo %p -> %p, fd %d, crtc_id 0x%x, fb_id 0x%x, conn_id 0x%x, curMode %s\n",
+ swapInterval, lastBO, nextBO, drmFd, crtc_id, fbNext->fb_id, connector_id, drmMode->name);
}
#endif
return (jlong) (intptr_t) nextBO;