diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 300782102..9312cf05f 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -1598,8 +1598,8 @@ opencomputers { # This setting assigns the budget call cost to invoke bitblt to write vram # to a screen. Video ram can bitblit to a screen which can cause real life # network laod the defaults settings put bitblit network impact close to gpu.set - # Increase these values to throttle bitblt more. These values appear inverted - # but the cost of bitblt is based on the max resolution of the device - bitbltCosts: [ 1, 2, 8 ] + # Increase these values to throttle bitblt more. The cost tier N is bitbltCost * 2^(tier) + # default is .5, which gives: .5, 1, 4 + bitbltCost: 0.5 } } diff --git a/src/main/scala/li/cil/oc/Settings.scala b/src/main/scala/li/cil/oc/Settings.scala index 0a266ce65..72c06a1d2 100644 --- a/src/main/scala/li/cil/oc/Settings.scala +++ b/src/main/scala/li/cil/oc/Settings.scala @@ -476,12 +476,7 @@ class Settings(val config: Config) { Array(1, 2, 3) } - val bitbltCosts: Array[Double] = Array(config.getDoubleList("gpu.bitbltCosts"): _*) match { - case Array(tier1, tier2, tier3) => Array(tier1: Double, tier2: Double, tier3: Double) - case _ => - OpenComputers.log.warn("Bad number of bitblit costs (expected 3), ignoring.") - Array(1, 2, 8) - } + val bitbltCost: Double = if (config.hasPath("gpu.bitbltCost")) config.getDouble("gpu.bitbltCost") else 0.5 } object Settings { diff --git a/src/main/scala/li/cil/oc/server/component/GraphicsCard.scala b/src/main/scala/li/cil/oc/server/component/GraphicsCard.scala index e4e4130c8..2868ee98b 100644 --- a/src/main/scala/li/cil/oc/server/component/GraphicsCard.scala +++ b/src/main/scala/li/cil/oc/server/component/GraphicsCard.scala @@ -71,7 +71,7 @@ class GraphicsCard(val tier: Int) extends prefab.ManagedEnvironment with DeviceI // These are dirty page bitblt budget costs // a single bitblt can send a screen of data, which is n*set calls where set is writing an entire line // So for each tier, we multiple the set cost with the number of lines the screen may have - final val bitbltCost: Double = Settings.get.bitbltCosts(0 max tier min 2) + final val bitbltCost: Double = Settings.get.bitbltCost * scala.math.pow(2, tier) final val totalVRAM: Double = (maxResolution._1 * maxResolution._2) * Settings.get.vramSizes(0 max tier min 2) var budgetExhausted: Boolean = false // for especially expensive calls, bitblt diff --git a/src/main/scala/li/cil/oc/util/NbtDataStream.scala b/src/main/scala/li/cil/oc/util/NbtDataStream.scala new file mode 100644 index 000000000..b56149310 --- /dev/null +++ b/src/main/scala/li/cil/oc/util/NbtDataStream.scala @@ -0,0 +1,49 @@ +package li.cil.oc.util + +import net.minecraft.nbt.NBTTagCompound + +object NbtDataStream { + def getShortArray(nbt: NBTTagCompound, key: String, array2d: Array[Array[Short]], w: Int, h: Int) : Boolean = { + if (!nbt.hasKey(key)) { + return false + } + + val rawByteReader = new java.io.ByteArrayInputStream(nbt.getByteArray(key)) + val memReader = new java.io.DataInputStream(rawByteReader) + for (y <- 0 until h) { + for (x <- 0 until w) { + if (2 > memReader.available()) { + return true // not great, but get out now + } + array2d(y)(x) = memReader.readShort() + } + } + true + } + + def getIntArrayLegacy(nbt: NBTTagCompound, key: String, array2d: Array[Array[Short]], w: Int, h: Int) : Boolean = { + if (!nbt.hasKey(key)) { + return false + } + // legacy format + val c = nbt.getIntArray(key) + for (y <- 0 until h) { + val rowColor = array2d(y) + for (x <- 0 until w) { + val index = x + y * w + if (index >= c.length) { + return true // not great, but, the read at least started + } + rowColor(x) = c(index).toShort + } + } + true + } + + def setShortArray(nbt: NBTTagCompound, key: String, array: Array[Short]): Unit = { + val rawByteWriter = new java.io.ByteArrayOutputStream() + val memWriter = new java.io.DataOutputStream(rawByteWriter) + array.foreach(memWriter.writeShort(_)) + nbt.setByteArray(key, rawByteWriter.toByteArray) + } +} diff --git a/src/main/scala/li/cil/oc/util/TextBuffer.scala b/src/main/scala/li/cil/oc/util/TextBuffer.scala index 3b4de3105..382a425a5 100644 --- a/src/main/scala/li/cil/oc/util/TextBuffer.scala +++ b/src/main/scala/li/cil/oc/util/TextBuffer.scala @@ -262,15 +262,8 @@ class TextBuffer(var width: Int, var height: Int, initialFormat: PackedColor.Col foreground = PackedColor.Color(nbt.getInteger("foreground"), nbt.getBoolean("foregroundIsPalette")) background = PackedColor.Color(nbt.getInteger("background"), nbt.getBoolean("backgroundIsPalette")) - val c = nbt.getIntArray("color") - for (i <- 0 until h) { - val rowColor = color(i) - for (j <- 0 until w) { - val index = j + i * w - if (index < c.length) { - rowColor(j) = c(index).toShort - } - } + if (!NbtDataStream.getShortArray(nbt, "color_bytes", color, w, h)) { + NbtDataStream.getIntArrayLegacy(nbt, "color", color, w, h) } } @@ -291,10 +284,10 @@ class TextBuffer(var width: Int, var height: Int, initialFormat: PackedColor.Col nbt.setInteger("background", _background.value) nbt.setBoolean("backgroundIsPalette", _background.isPalette) - nbt.setTag("color", new NBTTagIntArray(color.flatten.map(_.toInt))) + NbtDataStream.setShortArray(nbt, "color_bytes", color.flatten.map(_.toShort)) } - override def toString = { + override def toString: String = { val b = StringBuilder.newBuilder if (buffer.length > 0) { b.appendAll(buffer(0))