All Downloads are FREE. Search and download functionalities are using the official Maven repository.

apparat.pbj.PbjInputStream.scala Maven / Gradle / Ivy

/*
 * This file is part of Apparat.
 *
 * Apparat is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Apparat is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Apparat. If not, see .
 *
 * Copyright (C) 2009 Joa Ebert
 * http://www.joa-ebert.com/
 *
 */
package apparat.pbj

import java.io.{InputStream => JInputStream}
import apparat.pbj.pbjdata.implicits._
import apparat.pbj.pbjdata._
import annotation.tailrec
import apparat.utils.IO

/**
 * @author Joa Ebert
 */
class PbjInputStream(input: JInputStream) extends JInputStream {
	def foreach(body: POp => Unit) = while(available() > 0) { body(readOp()) }
	
	@inline private def signed(mask: Long, r: Long): Int = {
		if (0 != (r & mask)) ((r & (mask - 1L)) - mask).asInstanceOf[Int]
		else r.asInstanceOf[Int]
	}
	
	def readFloat() = java.lang.Float.intBitsToFloat((read() << 0x18) | (read() << 0x10) | (read() << 0x08) | read())

	def readString() = {
		@tailrec def loop(seq: List[Byte]): List[Byte] = readUI08() match {
			case 0 => seq
			case y => loop(y.asInstanceOf[Byte] :: seq)
		}

		new String(loop(Nil).reverse.toArray, "UTF8")
	}

	def readUI08(): Int = read()

	def readUI16(): Int = read() | (read() << 0x08)

	def readUI24(): Int = read() | (read() << 0x08) | (read() << 0x10)

	def readUI32(): Long = read() | (read() << 0x08) | (read() << 0x10) | (read() << 0x18)

	def readSI32(): Int = signed(0x80000000L, readUI32())

	def readConst(`type`: PType): PConst = `type` match {
		case PFloatType => PFloat(readFloat())
		case PFloat2Type => PFloat2(readFloat(), readFloat())
		case PFloat3Type => PFloat3(readFloat(), readFloat(), readFloat())
		case PFloat4Type => PFloat4(readFloat(), readFloat(), readFloat(), readFloat())
		case PFloat2x2Type => PFloat2x2(readFloat(), readFloat(), readFloat(), readFloat())
		case PFloat3x3Type => PFloat3x3(
			readFloat(), readFloat(), readFloat(),
			readFloat(), readFloat(), readFloat(),
			readFloat(), readFloat(), readFloat())
		case PFloat4x4Type => PFloat4x4(
			readFloat(), readFloat(), readFloat(), readFloat(),
			readFloat(), readFloat(), readFloat(), readFloat(),
			readFloat(), readFloat(), readFloat(), readFloat(),
			readFloat(), readFloat(), readFloat(), readFloat())
		case PIntType => PInt(readUI16())
		case PInt2Type => PInt2(readUI16(), readUI16()) 
		case PInt3Type => PInt3(readUI16(), readUI16(), readUI16())
		case PInt4Type => PInt4(readUI16(), readUI16(), readUI16(), readUI16())
		case PStringType => PString(readString())
		case PBoolType => PBool(readUI16() == 1)
		case PBool2Type => PBool2(readUI16() == 1, readUI16() == 1)
		case PBool3Type => PBool3(readUI16() == 1, readUI16() == 1, readUI16() == 1)
		case PBool4Type => PBool4(readUI16() == 1, readUI16() == 1, readUI16() == 1, readUI16() == 1)
	}

	def readType(): PType = readUI08()

	def readMeta(): PMeta = {
		val `type` = readType()
		PMeta(readString(), readConst(`type`))
	}

	def readParam(): PParam = {
		import PbjRegisterMagic._
		val qualifier = readUI08()
		val `type` = readType() match {
			case PStringType => error("Parameter must not be of type String.")
			case x: PNumeric => x
		}
		val register = readUI16()
		val mask = `type` match {
			case PFloat2x2Type => assert(readUI08() == 2); 0xf
			case PFloat3x3Type => assert(readUI08() == 3); 0xf
			case PFloat4x4Type => assert(readUI08() == 4); 0xf
			case _ => val b = readUI08(); assert((b >> 4) == 0); b
		}
		val name = readString()

		qualifier match {
			case 1 => PInParameter(name, `type`, createDstRegister(register, mask))
			case 2 => POutParameter(name, `type`, createDstRegister(register, mask))
			case _ => error("Qualifier must be either \"1\" or \"2\".")
		}
	}

	def readTexture() = {
		val index = readUI08()
		val channels = readUI08()
		val name = readString()
		PTexture(name, index, channels)
	}
	
	def readOp(): POp = {
		import POp._
		import PbjRegisterMagic._
		
		@inline def create(f: (PReg, PReg) => POp with PDstAndSrc): POp with PDstAndSrc = {
			val dstIndex = readUI16()
			val mask = readUI08()
			val swizzle = mask >> 4
			val size = (mask & 3) + 1
			val matrix = (mask >> 2) & 3
			val srcIndex = readUI24()

			assert(0 == readUI08())

			if(0 != matrix) {
				assert(0 == (srcIndex >> 16))
				assert(1 == size)
				f(	if(mask == 0) {
						createMatrixRegister(dstIndex, matrix)
					} else {
						createDstRegister(dstIndex, swizzle)
					}, createMatrixRegister(srcIndex, matrix))
			} else {
				f(createDstRegister(dstIndex, swizzle), createSrcRegister(srcIndex, size))
			}
		}

		@inline def sample(f: (PReg, PReg, Int) => POp with PDstAndSrc): POp with PDstAndSrc = {
			val dstIndex = readUI16()
			val mask = readUI08()
			val srcIndex = readUI24()
			val texture = readUI08()
			assert(1 == (mask & 0xf))
			f(createDstRegister(dstIndex, mask >> 4), createSrcRegister(srcIndex, 2), texture)
		}

		@inline def skipBytesAndReturn[@specialized A](x: => A): A = {
			assert(0 == readUI24())
			assert(0 == readUI32())
			x
		}

		readUI08() match {
			case Nop => skipBytesAndReturn { PNop() } 
			case Add => create(PAdd(_, _))
			case Subtract => create(PSubtract(_, _))
			case Multiply => create(PMultiply(_, _))
			case Reciprocal => create(PReciprocal(_, _))
			case Divide => create(PDivide(_, _))
			case Atan2 => create(PAtan2(_, _))
			case Pow => create(PPow(_, _))
			case Mod => create(PMod(_, _))
			case Min => create(PMin(_, _))
			case Max => create(PMax(_, _))
			case Step => create(PStep(_, _))
			case Sin => create(PSin(_, _))
			case Cos => create(PCos(_, _))
			case Tan => create(PTan(_, _))
			case ASin => create(PASin(_, _))
			case ACos => create(PACos(_, _))
			case ATan => create(PATan(_, _))
			case Exp => create(PExp(_, _))
			case Exp2 => create(PExp2(_, _))
			case Log => create(PLog(_, _))
			case Log2 => create(PLog2(_, _))
			case Sqrt => create(PSqrt(_, _))
			case RSqrt => create(PRSqrt(_, _))
			case Abs => create(PAbs(_, _))
			case Sign => create(PSign(_, _))
			case Floor => create(PFloor(_, _))
			case Ceil => create(PCeil(_, _))
			case Fract => create(PFract(_, _))
			case Copy => create(PCopy(_, _))
			case FloatToInt => create(PFloatToInt(_, _))
			case IntToFloat => create(PIntToFloat(_, _))
			case MatrixMatrixMultiply => create(PMatrixMatrixMultiply(_, _))
			case VectorMatrixMultiply => create(PVectorMatrixMultiply(_, _))
			case MatrixVectorMultiply => create(PMatrixVectorMultiply(_, _))
			case Normalize => create(PNormalize(_, _))
			case Length => create(PLength(_, _))
			case Distance => create(PDistance(_, _))
			case DotProduct => create(PDotProduct(_, _))
			case CrossProduct => create(PCrossProduct(_, _))
			case Equal => create(PEqual(_, _))
			case NotEqual => create(PNotEqual(_, _))
			case LessThan => create(PLessThan(_, _))
			case LessThanEqual => create(PLessThanEqual(_, _))
			case LogicalNot => create(PLogicalNot(_, _))
			case LogicalAnd => create(PLogicalAnd(_, _))
			case LogicalOr => create(PLogicalOr(_, _))
			case LogicalXor => create(PLogicalXor(_, _))
			case SampleNearest => sample(PSampleNearest(_, _, _))
			case SampleBilinear => sample(PSampleBilinear(_, _, _))
			case LoadConstant => {
				val dstIndex = readUI16()
				val mask = readUI08()
				assert(0 == (mask & 0xf))
				createDstRegister(dstIndex, mask >> 4) match {
					case r @ PIntReg(_, _) => PLoadInt(r, readSI32())
					case r @ PFloatReg(_, _) => PLoadFloat(r, readFloat())
				}
			}
			case Select =>
				val dstIndex = readUI16()
				val mask = readUI08()
				val swizzle = mask >> 4
				val size = (mask & 3) + 1
				val matrix = (mask >> 2) & 3
				val srcIndex = readUI24()
				assert(0 == readUI08())

				val src0Index = readUI24()
				assert(0 == readUI08())

				val src1Index = readUI24()
				assert(0 == readUI08())

				if(0 != matrix) {
					error("Matrix not expected.")
				}
				
				PSelect(createDstRegister(dstIndex, swizzle),
					createSrcRegister(srcIndex, size),
					createSrcRegister(src0Index, size),
					createSrcRegister(src1Index, size))
			case If => {
				assert(0 == readUI24())
				val src = readUI24()
				assert(0 == readUI08())
				PIf(createSrcRegister(src,1))
			}
			case Else => skipBytesAndReturn { PElse() }
			case Endif => skipBytesAndReturn { PEndif() }
			case FloatToBool => create(PFloatToBool(_, _))
			case BoolToFloat => create(PBoolToFloat(_, _))
			case IntToBool => create(PIntToBool(_, _))
			case BoolToInt => create(PBoolToInt(_, _))
			case VectorEqual => create(PVectorEqual(_, _))
			case VectorNotEqual => create(PVectorNotEqual(_, _))
			case Any => create(PAny(_, _))
			case All => create(PAll(_, _))
			case KernelMetaData => PKernelMetaData(readMeta())
			case ParameterData => PParameterData(readParam())
			case ParameterMetaData => PParameterMetaData(readMeta())
			case TextureData => PTextureData(readTexture())
			case KernelName => PKernelName(new String(IO.read(readUI16())(this), "UTF8"))
			case VersionData => PVersionData(readUI32().asInstanceOf[Int])
			case other => error("Unknown opcode "+other+".")
		}
	}

	override def available() = input.available()

	override def close() = input.close()

	override def read() = input.read()

	override def read(b: Array[Byte]) = input.read(b)

	override def read(b: Array[Byte], off: Int, len: Int) = input.read(b, off, len)

	override def reset() = input.reset()

	override def skip(n: Long) = input.skip(n)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy