/*
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;
import java.nio.Buffer;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import jpcsp.Memory;
import jpcsp.util.CpuDurationStatistics;
import jpcsp.util.DurationStatistics;
/**
* @author gid15
*
*/
public class AsyncVertexCache extends VertexCache {
AsyncVertexCacheThread asyncVertexCacheThread;
private boolean useVertexArray = false;
private VertexInfo vinfo = new VertexInfo();
public static AsyncVertexCache getInstance() {
if (instance == null) {
instance = new AsyncVertexCache();
}
return (AsyncVertexCache) instance;
}
protected AsyncVertexCache() {
asyncVertexCacheThread = new AsyncVertexCacheThread(this);
asyncVertexCacheThread.setName("Async Vertex Cache Thread");
asyncVertexCacheThread.setDaemon(true);
asyncVertexCacheThread.start();
}
private void asyncLoadVertex(VertexInfo vertexInfo, AsyncEntry asyncEntry) {
// TODO
}
private void asyncCheckVertex(VertexInfo vertex, VertexInfo vertexInfo, AsyncEntry asyncEntry) {
if (!vertex.equals(vertexInfo, asyncEntry.count)) {
setVertexAlreadyChecked(vertexInfo);
vertex.setDirty();
asyncLoadVertex(vertexInfo, asyncEntry);
}
}
public void asyncCheck(AsyncEntry asyncEntry) {
vinfo.setDirty();
vinfo.processType(asyncEntry.vtype);
vinfo.ptr_vertex = asyncEntry.vertices;
vinfo.ptr_index = asyncEntry.indices;
vinfo.prepareForCache(this, asyncEntry.count, null, 0);
if (useVertexArray) {
int address = vinfo.ptr_vertex;
int length = vinfo.vertexSize * asyncEntry.count;
if (length > 0) {
VertexBuffer vertexBuffer = VertexBufferManager.getInstance().getVertexBuffer(null, address, length, vinfo.vertexSize, useVertexArray);
if (vertexBuffer != null) {
Buffer buffer = Memory.getInstance().getBuffer(address, length);
vertexBuffer.preLoad(buffer, address, length);
}
}
} else {
VertexInfo vertex = getVertex(vinfo);
if (vertex == null) {
asyncLoadVertex(vinfo, asyncEntry);
} else {
asyncCheckVertex(vertex, vinfo, asyncEntry);
}
}
}
public void addAsyncCheck(int prim, int vtype, int count, int indices, int vertices) {
if (Memory.isAddressGood(vertices)) {
AsyncEntry asyncEntry = new AsyncEntry(prim, vtype, count, indices, vertices);
asyncVertexCacheThread.addAsyncEntry(asyncEntry);
}
}
@Override
public void exit() {
super.exit();
asyncVertexCacheThread.exit();
}
public void setUseVertexArray(boolean useVertexArray) {
this.useVertexArray = useVertexArray;
}
private static class AsyncVertexCacheThread extends Thread {
private AsyncVertexCache asyncVertexCache;
private BlockingQueue<AsyncEntry> asyncEntries = new LinkedBlockingQueue<AsyncEntry>();
private volatile boolean done = false;
public CpuDurationStatistics statistics = new CpuDurationStatistics("Async Vertex Cache Thread");
public AsyncVertexCacheThread(AsyncVertexCache asyncVertexCache) {
this.asyncVertexCache = asyncVertexCache;
}
public void exit() {
done = true;
// Add a dummy entry to allow the thread to exit
asyncEntries.add(new AsyncEntry());
if (DurationStatistics.collectStatistics) {
VideoEngine.log.info(statistics);
}
}
@Override
public void run() {
while (!done) {
try {
AsyncEntry asyncEntry = asyncEntries.take();
if (asyncEntry != null && !done) {
statistics.start();
asyncVertexCache.asyncCheck(asyncEntry);
statistics.end();
}
} catch (InterruptedException e) {
// Ignore Exception
}
}
}
public void addAsyncEntry(AsyncEntry asyncEntry) {
asyncEntries.add(asyncEntry);
}
}
private static class AsyncEntry {
public int prim;
public int vtype;
public int count;
public int indices;
public int vertices;
public AsyncEntry() {
}
public AsyncEntry(int prim, int vtype, int count, int indices, int vertices) {
this.prim = prim;
this.vtype = vtype;
this.count = count;
this.indices = indices;
this.vertices = vertices;
}
@Override
public String toString() {
return String.format("AsyncEntry(prim=%d, vtype=0x%X, count=%d, indices=0x%08X, vertices=0x%08X", prim, vtype, count, indices, vertices);
}
}
}