/*
This file is part of jpcsp.
Jpcsp is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jpcsp 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jpcsp. If not, see <http://www.gnu.org/licenses/>.
*/
package jpcsp.graphics.RE.software;
import jpcsp.Memory;
import jpcsp.Allegrex.compiler.RuntimeContext;
import jpcsp.graphics.GeCommands;
import jpcsp.memory.IMemoryReaderWriter;
/**
* @author gid15
*
*/
public class RendererWriter {
public static IRendererWriter getRendererWriter(int fbAddress, int fbBufferWidth, int fbPixelFormat, int depthAddress, int depthBufferWidth, int depthPixelFormat, boolean needDepthRead, boolean needDepthWrite) {
if (RuntimeContext.hasMemoryInt()) {
return getFastMemoryRendererWriter(fbAddress, fbBufferWidth, fbPixelFormat, depthAddress, depthBufferWidth, depthPixelFormat, needDepthRead, needDepthWrite);
}
return getRendererWriterGeneric(fbAddress, fbBufferWidth, fbPixelFormat, depthAddress, depthBufferWidth, depthPixelFormat, needDepthRead, needDepthWrite);
}
private static IRendererWriter getFastMemoryRendererWriter(int fbAddress, int fbBufferWidth, int fbPixelFormat, int depthAddress, int depthBufferWidth, int depthPixelFormat, boolean needDepthRead, boolean needDepthWrite) {
int[] memInt = RuntimeContext.getMemoryInt();
if (depthPixelFormat == BaseRenderer.depthBufferPixelFormat) {
switch (fbPixelFormat) {
case GeCommands.TPSM_PIXEL_STORAGE_MODE_32BIT_ABGR8888:
if (needDepthRead) {
if (needDepthWrite) {
return new RendererWriterInt32(memInt, fbAddress, depthAddress);
}
return new RendererWriterNoDepthWriteInt32(memInt, fbAddress, depthAddress);
}
if (needDepthWrite) {
return new RendererWriterNoDepthReadInt32(memInt, fbAddress, depthAddress);
}
return new RendererWriterNoDepthReadWriteInt32(memInt, fbAddress);
}
}
return getRendererWriterGeneric(fbAddress, fbBufferWidth, fbPixelFormat, depthAddress, depthBufferWidth, depthPixelFormat, needDepthRead, needDepthWrite);
}
private static IRendererWriter getRendererWriterGeneric(int fbAddress, int fbBufferWidth, int fbPixelFormat, int depthAddress, int depthBufferWidth, int depthPixelFormat, boolean needDepthRead, boolean needDepthWrite) {
if (!needDepthRead && !needDepthWrite) {
return new RendererWriterGenericNoDepth(fbAddress, fbBufferWidth, fbPixelFormat);
}
return new RendererWriterGeneric(fbAddress, fbBufferWidth, fbPixelFormat, depthAddress, depthBufferWidth, depthPixelFormat);
}
private static final class RendererWriterGeneric implements IRendererWriter {
private final IMemoryReaderWriter fbWriter;
private final IMemoryReaderWriter depthWriter;
public RendererWriterGeneric(int fbAddress, int fbBufferWidth, int fbPixelFormat, int depthAddress, int depthBufferWidth, int depthPixelFormat) {
fbWriter = ImageWriter.getImageWriter(fbAddress, fbBufferWidth, fbBufferWidth, fbPixelFormat);
depthWriter = ImageWriter.getImageWriter(depthAddress, depthBufferWidth, depthBufferWidth, depthPixelFormat);
}
@Override
public void readCurrent(ColorDepth colorDepth) {
colorDepth.color = fbWriter.readCurrent();
colorDepth.depth = depthWriter.readCurrent();
}
@Override
public void writeNext(ColorDepth colorDepth) {
fbWriter.writeNext(colorDepth.color);
depthWriter.writeNext(colorDepth.depth);
}
@Override
public void writeNextColor(int color) {
fbWriter.writeNext(color);
depthWriter.skip(1);
}
@Override
public void skip(int fbCount, int depthCount) {
fbWriter.skip(fbCount);
depthWriter.skip(depthCount);
}
@Override
public void flush() {
fbWriter.flush();
depthWriter.flush();
}
}
private static final class RendererWriterGenericNoDepth implements IRendererWriter {
private final IMemoryReaderWriter fbWriter;
public RendererWriterGenericNoDepth(int fbAddress, int fbBufferWidth, int fbPixelFormat) {
fbWriter = ImageWriter.getImageWriter(fbAddress, fbBufferWidth, fbBufferWidth, fbPixelFormat);
}
@Override
public void readCurrent(ColorDepth colorDepth) {
colorDepth.color = fbWriter.readCurrent();
}
@Override
public void writeNext(ColorDepth colorDepth) {
fbWriter.writeNext(colorDepth.color);
}
@Override
public void writeNextColor(int color) {
fbWriter.writeNext(color);
}
@Override
public void skip(int fbCount, int depthCount) {
fbWriter.skip(fbCount);
}
@Override
public void flush() {
fbWriter.flush();
}
}
private static final class RendererWriterInt32 implements IRendererWriter {
private int fbIndex;
private int depthIndex;
private int depthOffset;
private final int[] memInt;
public RendererWriterInt32(int[] memInt, int fbAddress, int depthAddress) {
this.memInt = memInt;
fbIndex = (fbAddress & Memory.addressMask) >> 2;
depthIndex = (depthAddress & Memory.addressMask) >> 2;
depthOffset = (depthAddress >> 1) & 1;
}
@Override
public void readCurrent(ColorDepth colorDepth) {
colorDepth.color = memInt[fbIndex];
if (depthOffset == 0) {
colorDepth.depth = memInt[depthIndex] & 0x0000FFFF;
} else {
colorDepth.depth = memInt[depthIndex] >>> 16;
}
}
private void next() {
fbIndex++;
if (depthOffset == 0) {
depthOffset = 1;
} else {
depthIndex++;
depthOffset = 0;
}
}
@Override
public void writeNext(ColorDepth colorDepth) {
memInt[fbIndex] = colorDepth.color;
if (depthOffset == 0) {
memInt[depthIndex] = (memInt[depthIndex] & 0xFFFF0000) | (colorDepth.depth & 0x0000FFFF);
} else {
memInt[depthIndex] = (memInt[depthIndex] & 0x0000FFFF) | (colorDepth.depth << 16);
}
next();
}
@Override
public void writeNextColor(int color) {
memInt[fbIndex] = color;
next();
}
@Override
public void skip(int fbCount, int depthCount) {
fbIndex += fbCount;
depthOffset += depthCount;
depthIndex += depthOffset >> 1;
depthOffset &= 1;
}
@Override
public void flush() {
}
}
private static final class RendererWriterNoDepthReadInt32 implements IRendererWriter {
private int fbIndex;
private int depthIndex;
private int depthOffset;
private final int[] memInt;
public RendererWriterNoDepthReadInt32(int[] memInt, int fbAddress, int depthAddress) {
this.memInt = memInt;
fbIndex = (fbAddress & Memory.addressMask) >> 2;
depthIndex = (depthAddress & Memory.addressMask) >> 2;
depthOffset = (depthAddress >> 1) & 1;
}
@Override
public void readCurrent(ColorDepth colorDepth) {
colorDepth.color = memInt[fbIndex];
}
private void next() {
fbIndex++;
if (depthOffset == 0) {
depthOffset = 1;
} else {
depthIndex++;
depthOffset = 0;
}
}
@Override
public void writeNext(ColorDepth colorDepth) {
memInt[fbIndex] = colorDepth.color;
if (depthOffset == 0) {
memInt[depthIndex] = (memInt[depthIndex] & 0xFFFF0000) | (colorDepth.depth & 0x0000FFFF);
} else {
memInt[depthIndex] = (memInt[depthIndex] & 0x0000FFFF) | (colorDepth.depth << 16);
}
next();
}
@Override
public void writeNextColor(int color) {
memInt[fbIndex] = color;
next();
}
@Override
public void skip(int fbCount, int depthCount) {
fbIndex += fbCount;
depthOffset += depthCount;
depthIndex += depthOffset >> 1;
depthOffset &= 1;
}
@Override
public void flush() {
}
}
private static final class RendererWriterNoDepthWriteInt32 implements IRendererWriter {
private int fbIndex;
private int depthIndex;
private int depthOffset;
private final int[] memInt;
public RendererWriterNoDepthWriteInt32(int[] memInt, int fbAddress, int depthAddress) {
this.memInt = memInt;
fbIndex = (fbAddress & Memory.addressMask) >> 2;
depthIndex = (depthAddress & Memory.addressMask) >> 2;
depthOffset = (depthAddress >> 1) & 1;
}
@Override
public void readCurrent(ColorDepth colorDepth) {
colorDepth.color = memInt[fbIndex];
if (depthOffset == 0) {
colorDepth.depth = memInt[depthIndex] & 0x0000FFFF;
} else {
colorDepth.depth = memInt[depthIndex] >>> 16;
}
}
private void next() {
fbIndex++;
if (depthOffset == 0) {
depthOffset = 1;
} else {
depthIndex++;
depthOffset = 0;
}
}
@Override
public void writeNext(ColorDepth colorDepth) {
memInt[fbIndex] = colorDepth.color;
next();
}
@Override
public void writeNextColor(int color) {
memInt[fbIndex] = color;
next();
}
@Override
public void skip(int fbCount, int depthCount) {
fbIndex += fbCount;
depthOffset += depthCount;
depthIndex += depthOffset >> 1;
depthOffset &= 1;
}
@Override
public void flush() {
}
}
private static final class RendererWriterNoDepthReadWriteInt32 implements IRendererWriter {
private int fbIndex;
private final int[] memInt;
public RendererWriterNoDepthReadWriteInt32(int[] memInt, int fbAddress) {
this.memInt = memInt;
fbIndex = (fbAddress & Memory.addressMask) >> 2;
}
@Override
public void readCurrent(ColorDepth colorDepth) {
colorDepth.color = memInt[fbIndex];
}
@Override
public void writeNext(ColorDepth colorDepth) {
memInt[fbIndex] = colorDepth.color;
fbIndex++;
}
@Override
public void writeNextColor(int color) {
memInt[fbIndex] = color;
fbIndex++;
}
@Override
public void skip(int fbCount, int depthCount) {
fbIndex += fbCount;
}
@Override
public void flush() {
}
}
}