mirror of
https://github.com/Ryujinx/Ryujinx.git
synced 2024-11-10 11:21:42 +00:00
138 lines
3.8 KiB
C#
138 lines
3.8 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
|
|
namespace Ryujinx.Graphics.Texture.Astc
|
|
{
|
|
class AstcPixel
|
|
{
|
|
public short R { get; set; }
|
|
public short G { get; set; }
|
|
public short B { get; set; }
|
|
public short A { get; set; }
|
|
|
|
byte[] _bitDepth = new byte[4];
|
|
|
|
public AstcPixel(short a, short r, short g, short b)
|
|
{
|
|
A = a;
|
|
R = r;
|
|
G = g;
|
|
B = b;
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
_bitDepth[i] = 8;
|
|
}
|
|
|
|
public void ClampByte()
|
|
{
|
|
R = Math.Min(Math.Max(R, (short)0), (short)255);
|
|
G = Math.Min(Math.Max(G, (short)0), (short)255);
|
|
B = Math.Min(Math.Max(B, (short)0), (short)255);
|
|
A = Math.Min(Math.Max(A, (short)0), (short)255);
|
|
}
|
|
|
|
public short GetComponent(int index)
|
|
{
|
|
switch(index)
|
|
{
|
|
case 0: return A;
|
|
case 1: return R;
|
|
case 2: return G;
|
|
case 3: return B;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
public void SetComponent(int index, int value)
|
|
{
|
|
switch (index)
|
|
{
|
|
case 0:
|
|
A = (short)value;
|
|
break;
|
|
case 1:
|
|
R = (short)value;
|
|
break;
|
|
case 2:
|
|
G = (short)value;
|
|
break;
|
|
case 3:
|
|
B = (short)value;
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void ChangeBitDepth(byte[] depth)
|
|
{
|
|
for (int i = 0; i< 4; i++)
|
|
{
|
|
int value = ChangeBitDepth(GetComponent(i), _bitDepth[i], depth[i]);
|
|
|
|
SetComponent(i, value);
|
|
_bitDepth[i] = depth[i];
|
|
}
|
|
}
|
|
|
|
short ChangeBitDepth(short value, byte oldDepth, byte newDepth)
|
|
{
|
|
Debug.Assert(newDepth <= 8);
|
|
Debug.Assert(oldDepth <= 8);
|
|
|
|
if (oldDepth == newDepth)
|
|
{
|
|
// Do nothing
|
|
return value;
|
|
}
|
|
else if (oldDepth == 0 && newDepth != 0)
|
|
{
|
|
return (short)((1 << newDepth) - 1);
|
|
}
|
|
else if (newDepth > oldDepth)
|
|
{
|
|
return (short)BitArrayStream.Replicate(value, oldDepth, newDepth);
|
|
}
|
|
else
|
|
{
|
|
// oldDepth > newDepth
|
|
if (newDepth == 0)
|
|
{
|
|
return 0xFF;
|
|
}
|
|
else
|
|
{
|
|
byte bitsWasted = (byte)(oldDepth - newDepth);
|
|
short tempValue = value;
|
|
|
|
tempValue = (short)((tempValue + (1 << (bitsWasted - 1))) >> bitsWasted);
|
|
tempValue = Math.Min(Math.Max((short)0, tempValue), (short)((1 << newDepth) - 1));
|
|
|
|
return (byte)(tempValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
public int Pack()
|
|
{
|
|
AstcPixel newPixel = new AstcPixel(A, R, G, B);
|
|
byte[] eightBitDepth = { 8, 8, 8, 8 };
|
|
|
|
newPixel.ChangeBitDepth(eightBitDepth);
|
|
|
|
return (byte)newPixel.A << 24 |
|
|
(byte)newPixel.B << 16 |
|
|
(byte)newPixel.G << 8 |
|
|
(byte)newPixel.R << 0;
|
|
}
|
|
|
|
// Adds more precision to the blue channel as described
|
|
// in C.2.14
|
|
public static AstcPixel BlueContract(int a, int r, int g, int b)
|
|
{
|
|
return new AstcPixel((short)(a),
|
|
(short)((r + b) >> 1),
|
|
(short)((g + b) >> 1),
|
|
(short)(b));
|
|
}
|
|
}
|
|
}
|