gpu: framebuffer is now UnsafePtr instead of being Pixmap

This commit is contained in:
minjaesong
2022-04-27 10:57:14 +09:00
parent 6650861ad6
commit b37124bc4e
4 changed files with 69 additions and 63 deletions

View File

@@ -155,7 +155,7 @@ From the start of the memory space:
1 byte 1 byte
command (writing to this memory address changes the status) command (writing to this memory address changes the status)
1: reset palette to default 1: reset palette to default
2: fill framebuffer with given colour (arg1) 2: fill framebuffer with given colour (arg1). If framebuffer 2 is there, it will be filled with arg2
3: do '1' then do '2' 3: do '1' then do '2'
16: copy Low Font ROM (char 0127) to mapping area 16: copy Low Font ROM (char 0127) to mapping area

View File

@@ -16,11 +16,7 @@ class DMADelegate(val vm: VM) {
fun ramToFrame(from: Int, devnum: Int, offset: Int, length: Int) { fun ramToFrame(from: Int, devnum: Int, offset: Int, length: Int) {
(vm.peripheralTable[devnum].peripheral as? GraphicsAdapter)?.let { (vm.peripheralTable[devnum].peripheral as? GraphicsAdapter)?.let {
val data = ByteArray(length) UnsafeHelper.memcpyRaw(null, vm.usermem.ptr + from, null, it.framebuffer.ptr + offset, length.toLong())
UnsafeHelper.memcpyRaw(null, vm.usermem.ptr + from, data, UnsafeHelper.getArrayOffset(data), length.toLong())
it.framebuffer.pixels.position(offset)
it.framebuffer.pixels.put(data)
it.framebuffer.pixels.position(0) // rewinding to avoid graphical glitch
} }
} }
@@ -35,11 +31,7 @@ class DMADelegate(val vm: VM) {
fun frameToRam(from: Int, to: Int, devnum: Int, length: Int) { fun frameToRam(from: Int, to: Int, devnum: Int, length: Int) {
(vm.peripheralTable[devnum].peripheral as? GraphicsAdapter)?.let { (vm.peripheralTable[devnum].peripheral as? GraphicsAdapter)?.let {
val data = ByteArray(length) UnsafeHelper.memcpyRaw(null, it.framebuffer.ptr + from, null, vm.usermem.ptr + to, length.toLong())
it.framebuffer.pixels.position(from)
it.framebuffer.pixels.get(data)
it.framebuffer.pixels.position(0) // rewinding to avoid graphical glitch
UnsafeHelper.memcpyRaw(data, UnsafeHelper.getArrayOffset(data), null, vm.usermem.ptr + to, length.toLong())
} }
} }

View File

@@ -69,8 +69,8 @@ class GraphicsJSR223Delegate(val vm: VM) {
fun scrollFrame(xdelta: Int, ydelta: Int) { fun scrollFrame(xdelta: Int, ydelta: Int) {
getFirstGPU()?.let { getFirstGPU()?.let {
it.framebufferScrollX = (it.framebufferScrollX + xdelta) fmod it.framebuffer.width it.framebufferScrollX = (it.framebufferScrollX + xdelta) fmod it.WIDTH
it.framebufferScrollY = (it.framebufferScrollY + ydelta) fmod it.framebuffer.height it.framebufferScrollY = (it.framebufferScrollY + ydelta) fmod it.HEIGHT
} }
} }
@@ -97,7 +97,7 @@ class GraphicsJSR223Delegate(val vm: VM) {
fun getGraphicsMode() = getFirstGPU()?.mmio_read(12L)?.toUint() ?: 0 fun getGraphicsMode() = getFirstGPU()?.mmio_read(12L)?.toUint() ?: 0
fun getPixelDimension(): IntArray { fun getPixelDimension(): IntArray {
getFirstGPU()?.let { return intArrayOf(it.framebuffer.width, it.framebuffer.height) } getFirstGPU()?.let { return intArrayOf(it.WIDTH, it.HEIGHT) }
return intArrayOf(-1, -1) return intArrayOf(-1, -1)
} }

View File

@@ -54,16 +54,17 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
return vm return vm
} }
protected val WIDTH = config.width val WIDTH = config.width
protected val HEIGHT = config.height val HEIGHT = config.height
protected val VRAM_SIZE = config.vramSize val VRAM_SIZE = config.vramSize
protected val TTY_FORE_DEFAULT = config.ttyDefaultFore protected val TTY_FORE_DEFAULT = config.ttyDefaultFore
protected val TTY_BACK_DEFAULT = config.ttyDefaultBack protected val TTY_BACK_DEFAULT = config.ttyDefaultBack
protected val theme = config.theme protected val theme = config.theme
protected val TAB_SIZE = 8 protected val TAB_SIZE = 8
internal val framebuffer = Pixmap(WIDTH, HEIGHT, Pixmap.Format.Alpha) internal val framebuffer = UnsafeHelper.allocate(WIDTH.toLong() * HEIGHT)//Pixmap(WIDTH, HEIGHT, Pixmap.Format.Alpha)
internal val framebuffer2 = Pixmap(WIDTH, HEIGHT, Pixmap.Format.RGBA8888) internal val framebuffer2 = if (sgr.bankCount >= 2) UnsafeHelper.allocate(WIDTH.toLong() * HEIGHT) else null
internal val framebufferOut = Pixmap(WIDTH, HEIGHT, Pixmap.Format.RGBA8888)
protected var rendertex = Texture(1, 1, Pixmap.Format.RGBA8888) protected var rendertex = Texture(1, 1, Pixmap.Format.RGBA8888)
internal val paletteOfFloats = FloatArray(1024) { internal val paletteOfFloats = FloatArray(1024) {
val rgba = DEFAULT_PALETTE[it / 4] val rgba = DEFAULT_PALETTE[it / 4]
@@ -159,12 +160,11 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
outFBObatch.projectionMatrix = m outFBObatch.projectionMatrix = m
framebuffer.blending = Pixmap.Blending.None framebufferOut.blending = Pixmap.Blending.None
framebuffer2.blending = Pixmap.Blending.None
textForePixmap.blending = Pixmap.Blending.None textForePixmap.blending = Pixmap.Blending.None
textBackPixmap.blending = Pixmap.Blending.None textBackPixmap.blending = Pixmap.Blending.None
framebuffer.setColor(-1) framebuffer.fillWith(-1) // FF for palette mode, RGBA(15, 15, x, x) for direct colour
framebuffer.fill() framebuffer2?.fillWith(-16) // RGBA(x, x, 15, 0) for direct colour
unusedArea.fillWith(0) unusedArea.fillWith(0)
scanlineOffsets.fillWith(0) scanlineOffsets.fillWith(0)
@@ -191,14 +191,18 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
} }
setCursorPos(0, 0) setCursorPos(0, 0)
println("Framebuffer pixels limit: ${framebuffer.pixels.limit()}")
} }
override fun peek(addr: Long): Byte? { override fun peek(addr: Long): Byte? {
val adi = addr.toInt() val adi = addr.toInt()
if (framebuffer2 != null) {
return when (addr - 262144) {
in 0 until 250880 -> framebuffer2[addr]
else -> null
}
}
return when (addr) { return when (addr) {
in 0 until 250880 -> framebuffer.pixels.get(adi)//framebuffer.getPixel(adi % WIDTH, adi / WIDTH).toByte() in 0 until 250880 -> framebuffer[addr]
in 252030 until 252030+1920 -> mappedFontRom[adi- 252030] in 252030 until 252030+1920 -> mappedFontRom[adi- 252030]
in 250880 until 250880+1024 -> unusedArea[addr - 250880] in 250880 until 250880+1024 -> unusedArea[addr - 250880]
in 253950 until 261632 -> textArea[addr - 253950] in 253950 until 261632 -> textArea[addr - 253950]
@@ -214,10 +218,19 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
override fun poke(addr: Long, byte: Byte) { override fun poke(addr: Long, byte: Byte) {
val adi = addr.toInt() val adi = addr.toInt()
val bi = byte.toInt().and(255) val bi = byte.toInt().and(255)
if (framebuffer2 != null) {
when (addr - 262144) {
in 0 until 250880 -> {
lastUsedColour = byte
framebuffer2[addr] = byte
return
}
}
}
when (addr) { when (addr) {
in 0 until 250880 -> { in 0 until 250880 -> {
lastUsedColour = byte lastUsedColour = byte
framebuffer.pixels.put(adi, byte) framebuffer[addr] = byte
} }
250883L -> { 250883L -> {
unusedArea[addr - 250880] = byte unusedArea[addr - 250880] = byte
@@ -311,8 +324,8 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
} }
} }
2 -> { 2 -> {
framebuffer.setColor(0f,0f,0f,arg1 / 255f) framebuffer.fillWith(arg1.toByte())
framebuffer.fill() framebuffer2?.fillWith(arg2.toByte())
} }
3 -> { 3 -> {
for (it in 0 until 1024) { for (it in 0 until 1024) {
@@ -320,8 +333,8 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
val channel = it % 4 val channel = it % 4
rgba.shr((3 - channel) * 8).and(255) / 255f rgba.shr((3 - channel) * 8).and(255) / 255f
} }
framebuffer.setColor(0f,0f,0f,arg1 / 255f) framebuffer.fillWith(arg1.toByte())
framebuffer.fill() framebuffer2?.fillWith(arg2.toByte())
} }
16, 17 -> readFontRom(opcode - 16) 16, 17 -> readFontRom(opcode - 16)
18, 19 -> writeFontRom(opcode - 18) 18, 19 -> writeFontRom(opcode - 18)
@@ -335,8 +348,8 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
open fun readFontRom(mode: Int) { open fun readFontRom(mode: Int) {
// max char size: 8*15 // max char size: 8*15
fontRomMappingMode = mode fontRomMappingMode = mode
val cw = config.width / config.textCols val cw = WIDTH / config.textCols
val ch = config.height / config.textRows val ch = HEIGHT / config.textRows
if (cw > 8 || ch > 15) throw UnsupportedOperationException() if (cw > 8 || ch > 15) throw UnsupportedOperationException()
val pixmap = chrrom val pixmap = chrrom
@@ -368,8 +381,8 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
open fun writeFontRom(mode: Int) { open fun writeFontRom(mode: Int) {
// max char size: 8*15 // max char size: 8*15
fontRomMappingMode = mode fontRomMappingMode = mode
val cw = config.width / config.textCols val cw = WIDTH / config.textCols
val ch = config.height / config.textRows val ch = HEIGHT / config.textRows
if (cw > 8 || ch > 15) throw UnsupportedOperationException() if (cw > 8 || ch > 15) throw UnsupportedOperationException()
@@ -701,8 +714,9 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
override fun dispose() { override fun dispose() {
//testTex.dispose() //testTex.dispose()
framebuffer.dispose() framebuffer.destroy()
framebuffer2.dispose() framebuffer2?.destroy()
framebufferOut.dispose()
rendertex.dispose() rendertex.dispose()
textArea.destroy() textArea.destroy()
textForePixmap.dispose() textForePixmap.dispose()
@@ -733,18 +747,18 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
unusedArea[1].toInt().and(15).toFloat() / 15f, unusedArea[1].toInt().and(15).toFloat() / 15f,
unusedArea[2].toInt().and(15).toFloat() / 15f, 1f) unusedArea[2].toInt().and(15).toFloat() / 15f, 1f)
private val isRefSize = (config.width == 560 && config.height == 448) private val isRefSize = (WIDTH == 560 && HEIGHT == 448)
open fun render(delta: Float, uiBatch: SpriteBatch, xoff: Float, yoff: Float, flipY: Boolean = false, uiFBO: FrameBuffer? = null) { open fun render(delta: Float, uiBatch: SpriteBatch, xoff: Float, yoff: Float, flipY: Boolean = false, uiFBO: FrameBuffer? = null) {
uiFBO?.end() uiFBO?.end()
// must reset positions as pixmaps expect them to be zero // must reset positions as pixmaps expect them to be zero
framebuffer.pixels.position(0) framebufferOut.pixels.position(0)
framebuffer2.pixels.position(0)
chrrom.pixels.position(0) chrrom.pixels.position(0)
framebuffer2.setColor(-1);framebuffer2.fill() framebufferOut.setColor(-1);framebufferOut.fill()
// if (isRefSize && graphicsMode == 4 && )
if (isRefSize && (graphicsMode == 1 || graphicsMode == 2)) { if (isRefSize && (graphicsMode == 1 || graphicsMode == 2)) {
val layerOrder = (if (graphicsMode == 1) LAYERORDERS4 else LAYERORDERS2)[layerArrangement] val layerOrder = (if (graphicsMode == 1) LAYERORDERS4 else LAYERORDERS2)[layerArrangement]
for (y in 0..223) { for (y in 0..223) {
@@ -756,7 +770,7 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
for (x in xs) { for (x in xs) {
val colour = layerOrder.map { layer -> val colour = layerOrder.map { layer ->
if (graphicsMode == 1) { if (graphicsMode == 1) {
val colourIndex = framebuffer.pixels.get((280 * 224 * layer) + (y * 280 + x)).toUint() val colourIndex = framebuffer[(280L * 224 * layer) + (y * 280 + x)].toUint()
Color( Color(
paletteOfFloats[4 * colourIndex], paletteOfFloats[4 * colourIndex],
paletteOfFloats[4 * colourIndex + 1], paletteOfFloats[4 * colourIndex + 1],
@@ -765,8 +779,8 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
) )
} }
else { else {
val lowBits = framebuffer.pixels.get((280 * 224 * layer * 2) + (y * 280 + x)).toUint() val lowBits = framebuffer[(280L * 224 * layer * 2) + (y * 280 + x)].toUint()
val highBits = framebuffer.pixels.get((280 * 224 * (layer*2 + 1)) + (y * 280 + x)).toUint() val highBits = framebuffer[(280L * 224 * (layer*2 + 1)) + (y * 280 + x)].toUint()
val r = lowBits.ushr(4).and(15) val r = lowBits.ushr(4).and(15)
val g = lowBits.and(15) val g = lowBits.and(15)
val b = highBits.ushr(4).and(15) val b = highBits.ushr(4).and(15)
@@ -793,31 +807,31 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
) )
} }
framebuffer2.setColor(colour) framebufferOut.setColor(colour)
framebuffer2.drawPixel(x*2, y*2) framebufferOut.drawPixel(x*2, y*2)
framebuffer2.drawPixel(x*2+1, y*2) framebufferOut.drawPixel(x*2+1, y*2)
framebuffer2.drawPixel(x*2, y*2+1) framebufferOut.drawPixel(x*2, y*2+1)
framebuffer2.drawPixel(x*2+1, y*2+1) framebufferOut.drawPixel(x*2+1, y*2+1)
} }
} }
} }
} }
else { else {
for (y in 0 until config.height) { for (y in 0 until HEIGHT) {
var xoff = scanlineOffsets[2L * y].toUint() or scanlineOffsets[2L * y + 1].toUint().shl(8) var xoff = scanlineOffsets[2L * y].toUint() or scanlineOffsets[2L * y + 1].toUint().shl(8)
if (xoff.and(0x8000) != 0) xoff = xoff or 0xFFFF0000.toInt() if (xoff.and(0x8000) != 0) xoff = xoff or 0xFFFF0000.toInt()
val xs = (0 + xoff).coerceIn(0, config.width - 1)..(config.width - 1 + xoff).coerceIn(0, config.width - 1) val xs = (0 + xoff).coerceIn(0, WIDTH - 1)..(WIDTH - 1 + xoff).coerceIn(0, WIDTH - 1)
if (xoff in -(config.width - 1) until config.width) { if (xoff in -(WIDTH - 1) until WIDTH) {
for (x in xs) { for (x in xs) {
// this only works because framebuffer is guaranteed to be 8bpp // this only works because framebuffer is guaranteed to be 8bpp
/*framebuffer2.pixels.put( /*framebuffer2.pixels.put(
y * config.width + x, y * WIDTH + x,
framebuffer.pixels.get(y * config.width + (x - xoff)) // coerceIn not required as (x - xoff) never escapes 0..559 framebuffer.pixels.get(y * WIDTH + (x - xoff)) // coerceIn not required as (x - xoff) never escapes 0..559
)*/ )*/
val colourIndex = framebuffer.pixels.get(y * config.width + (x - xoff)).toUint() // coerceIn not required as (x - xoff) never escapes 0..559 val colourIndex = framebuffer[y.toLong() * WIDTH + (x - xoff)].toUint() // coerceIn not required as (x - xoff) never escapes 0..559
framebuffer2.setColor(paletteOfFloats[4*colourIndex], paletteOfFloats[4*colourIndex+1], paletteOfFloats[4*colourIndex+2], paletteOfFloats[4*colourIndex+3]) framebufferOut.setColor(paletteOfFloats[4*colourIndex], paletteOfFloats[4*colourIndex+1], paletteOfFloats[4*colourIndex+2], paletteOfFloats[4*colourIndex+3])
framebuffer2.drawPixel(x, y) framebufferOut.drawPixel(x, y)
} }
} }
} }
@@ -826,10 +840,10 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
chrrom0.dispose() chrrom0.dispose()
chrrom0 = Texture(chrrom) chrrom0 = Texture(chrrom)
rendertex.dispose() rendertex.dispose()
rendertex = Texture(framebuffer2, Pixmap.Format.RGBA8888, false) rendertex = Texture(framebufferOut, Pixmap.Format.RGBA8888, false)
val texOffX = (framebufferScrollX fmod framebuffer.width) * -1f val texOffX = (framebufferScrollX fmod WIDTH) * -1f
val texOffY = (framebufferScrollY fmod framebuffer.height) * 1f val texOffY = (framebufferScrollY fmod HEIGHT) * 1f
outFBOs[1].inUse { outFBOs[1].inUse {
outFBObatch.inUse { outFBObatch.inUse {
@@ -868,9 +882,9 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
// draw framebuffer // draw framebuffer
outFBObatch.draw(rendertex, texOffX, texOffY) outFBObatch.draw(rendertex, texOffX, texOffY)
outFBObatch.draw(rendertex, texOffX + framebuffer.width, texOffY) outFBObatch.draw(rendertex, texOffX + WIDTH, texOffY)
outFBObatch.draw(rendertex, texOffX + framebuffer.width, texOffY - framebuffer.height) outFBObatch.draw(rendertex, texOffX + WIDTH, texOffY - HEIGHT)
outFBObatch.draw(rendertex, texOffX, texOffY - framebuffer.height) outFBObatch.draw(rendertex, texOffX, texOffY - HEIGHT)
// draw texts or sprites // draw texts or sprites