init
This commit is contained in:
+90
@@ -0,0 +1,90 @@
|
||||
package pw.binom.rayneovm.glasses.shizuku
|
||||
|
||||
import android.graphics.SurfaceTexture
|
||||
import android.os.IBinder
|
||||
import android.util.Log
|
||||
import android.view.Surface
|
||||
import pw.binom.mercury.binocular.SurfaceTextureFrameSource
|
||||
import pw.binom.mercury.shizuku.ShizukuVdBinder
|
||||
import pw.binom.mercury.shizuku.ShizukuVdClient
|
||||
|
||||
/**
|
||||
* Связка между VirtualDisplay на стороне очков и [FrameSource] для бинокулярного рендерера.
|
||||
*
|
||||
* Жизненный цикл:
|
||||
* 1. Создаём SurfaceTexture в этом процессе (он будет жить в GL-контексте рендерера).
|
||||
* 2. Оборачиваем её в Surface.
|
||||
* 3. Получаем Shizuku Binder и создаём VirtualDisplay через [ShizukuVdBinder.createDisplay],
|
||||
* передавая клиентский Surface. Display пишет кадры прямо в этот Surface → рендерер
|
||||
* читает кадры из той же SurfaceTexture.
|
||||
* 4. Возвращаем [FrameSource] рендереру — он получает кадры через onFrameAvailable.
|
||||
* 5. При release — [ShizukuVdBinder.releaseDisplay] и SurfaceTexture.release().
|
||||
*/
|
||||
class VirtualDisplayFrameSource private constructor(
|
||||
source: SurfaceTexture,
|
||||
private val surface: Surface,
|
||||
private val binder: IBinder,
|
||||
private val displayId: Int,
|
||||
width: Int,
|
||||
height: Int,
|
||||
) : SurfaceTextureFrameSource(source, width, height) {
|
||||
|
||||
override fun release() {
|
||||
runCatching { ShizukuVdBinder.releaseDisplay(binder, displayId) }
|
||||
runCatching { surface.release() }
|
||||
super.release()
|
||||
Log.i(TAG, "VirtualDisplayFrameSource released: displayId=$displayId")
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "VirtualDisplayFrameSource"
|
||||
|
||||
/**
|
||||
* Создаёт VirtualDisplay и возвращает FrameSource для рендерера.
|
||||
*
|
||||
* @param context Android context
|
||||
* @param surfaceTexture GL-текстура, привязанная к GLSurfaceView (рендерер создаёт сам)
|
||||
* @param serviceClass класс ShizukuVdService наследника (например, VmShizukuService::class.java)
|
||||
* @param width виртуальный размер дисплея (для очков одного глаза — 640×480)
|
||||
* @param height то же
|
||||
* @param density плотность экрана (dpi)
|
||||
*/
|
||||
suspend fun acquire(
|
||||
context: android.content.Context,
|
||||
surfaceTexture: SurfaceTexture,
|
||||
serviceClass: Class<*>,
|
||||
width: Int = 640,
|
||||
height: Int = 480,
|
||||
density: Int = 160,
|
||||
): VirtualDisplayFrameSource? {
|
||||
val surface = Surface(surfaceTexture)
|
||||
val client = ShizukuVdClient(context, serviceClass)
|
||||
return try {
|
||||
var binder: IBinder? = null
|
||||
client.start { b -> binder = b }
|
||||
val b = binder ?: run {
|
||||
Log.w(TAG, "Shizuku binder not ready, returning null")
|
||||
surface.release()
|
||||
client.stop()
|
||||
return null
|
||||
}
|
||||
val displayId = ShizukuVdBinder.createDisplay(
|
||||
b, "VmDisplay", width, height, density, surface
|
||||
)
|
||||
if (displayId <= 0) {
|
||||
Log.w(TAG, "createDisplay returned $displayId")
|
||||
surface.release()
|
||||
client.stop()
|
||||
return null
|
||||
}
|
||||
Log.i(TAG, "Acquired VirtualDisplay id=$displayId ${width}x${height}")
|
||||
VirtualDisplayFrameSource(surfaceTexture, surface, b, displayId, width, height)
|
||||
} catch (t: Throwable) {
|
||||
Log.e(TAG, "acquire failed", t)
|
||||
runCatching { surface.release() }
|
||||
client.stop()
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user