diff --git a/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java b/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java index 5f4e1803f9..be1375f592 100644 --- a/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java +++ b/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java @@ -45,6 +45,8 @@ public class ScreenCapture extends SurfaceCapture { private AffineMatrix transform; private OpenGLRunner glRunner; + private boolean useGl; + private Rect layerStackRect; public ScreenCapture(VirtualDisplayListener vdListener, Options options) { this.vdListener = vdListener; @@ -85,19 +87,40 @@ public void prepare() throws ConfigurationException { captureOrientation = Orientation.fromRotation(displayInfo.getRotation()); } + layerStackRect = null; + + boolean simpleCrop = crop != null + && angle == 0f + && captureOrientationLock == Orientation.Lock.Unlocked + && captureOrientation == Orientation.Orient0; + VideoFilter filter = new VideoFilter(displaySize); if (crop != null) { boolean transposed = (displayInfo.getRotation() % 2) != 0; filter.addCrop(crop, transposed); + if (simpleCrop) { + if (transposed) { + layerStackRect = new Rect(crop.top, crop.left, crop.bottom, crop.right); + } else { + layerStackRect = new Rect(crop); + } + } } - boolean locked = captureOrientationLock != Orientation.Lock.Unlocked; - filter.addOrientation(displayInfo.getRotation(), locked, captureOrientation); - filter.addAngle(angle); + if (simpleCrop) { + useGl = false; + transform = filter.getInverseTransform(); + videoSize = filter.getOutputSize().limit(maxSize).round8(); + } else { + useGl = true; + boolean locked = captureOrientationLock != Orientation.Lock.Unlocked; + filter.addOrientation(displayInfo.getRotation(), locked, captureOrientation); + filter.addAngle(angle); - transform = filter.getInverseTransform(); - videoSize = filter.getOutputSize().limit(maxSize).round8(); + transform = filter.getInverseTransform(); + videoSize = filter.getOutputSize().limit(maxSize).round8(); + } } @Override @@ -112,7 +135,7 @@ public void start(Surface surface) throws IOException { } Size inputSize; - if (transform != null) { + if (useGl) { // If there is a filter, it must receive the full display content inputSize = displayInfo.getSize(); assert glRunner == null; @@ -124,22 +147,46 @@ public void start(Surface surface) throws IOException { inputSize = videoSize; } - try { - virtualDisplay = ServiceManager.getDisplayManager() - .createVirtualDisplay("scrcpy", inputSize.getWidth(), inputSize.getHeight(), displayId, surface); - Ln.d("Display: using DisplayManager API"); - } catch (Exception displayManagerException) { + boolean wantSurfaceControl = layerStackRect != null; + if (!wantSurfaceControl) { + try { + virtualDisplay = ServiceManager.getDisplayManager() + .createVirtualDisplay("scrcpy", inputSize.getWidth(), inputSize.getHeight(), displayId, surface); + Ln.d("Display: using DisplayManager API"); + } catch (Exception displayManagerException) { + try { + display = createDisplay(); + + Size deviceSize = displayInfo.getSize(); + int layerStack = displayInfo.getLayerStack(); + Rect deviceRect = layerStackRect != null ? layerStackRect : deviceSize.toRect(); + setDisplaySurface(display, surface, deviceRect, inputSize.toRect(), layerStack); + Ln.d("Display: using SurfaceControl API"); + } catch (Exception surfaceControlException) { + Ln.e("Could not create display using DisplayManager", displayManagerException); + Ln.e("Could not create display using SurfaceControl", surfaceControlException); + throw new AssertionError("Could not create display"); + } + } + } else { try { display = createDisplay(); Size deviceSize = displayInfo.getSize(); int layerStack = displayInfo.getLayerStack(); - setDisplaySurface(display, surface, deviceSize.toRect(), inputSize.toRect(), layerStack); + Rect deviceRect = layerStackRect != null ? layerStackRect : deviceSize.toRect(); + setDisplaySurface(display, surface, deviceRect, inputSize.toRect(), layerStack); Ln.d("Display: using SurfaceControl API"); } catch (Exception surfaceControlException) { - Ln.e("Could not create display using DisplayManager", displayManagerException); Ln.e("Could not create display using SurfaceControl", surfaceControlException); - throw new AssertionError("Could not create display"); + try { + virtualDisplay = ServiceManager.getDisplayManager() + .createVirtualDisplay("scrcpy", inputSize.getWidth(), inputSize.getHeight(), displayId, surface); + Ln.d("Display: fallback to DisplayManager API"); + } catch (Exception displayManagerException) { + Ln.e("Could not create display using DisplayManager", displayManagerException); + throw new AssertionError("Could not create display"); + } } }