/* 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.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import jpcsp.graphics.RE.IRenderingEngine; import jpcsp.util.CpuDurationStatistics; import jpcsp.util.DurationStatistics; /** * @author gid15 * */ public class VertexArrayManager { private static VertexArrayManager instance; private static final int maxSize = 1000; private List<VertexArray> vertexArrays = new LinkedList<VertexArray>(); private CpuDurationStatistics statistics = new CpuDurationStatistics("VertexArrayManager"); private HashMap<Integer, VertexArray> fastLookup = new HashMap<Integer, VertexArray>(); public static VertexArrayManager getInstance() { if (instance == null) { instance = new VertexArrayManager(); } return instance; } public static void exit() { if (instance != null) { if (DurationStatistics.collectStatistics) { VideoEngine.log.info(instance.statistics); } } } private static int getFastLookupKey(int vtype, VertexBuffer vertexBuffer, int address, int stride) { return vertexBuffer.getId() + (vtype << 8); } public VertexArray getVertexArray(IRenderingEngine re, int vtype, VertexBuffer vertexBuffer, int address, int stride) { statistics.start(); int fastLookupKey = getFastLookupKey(vtype, vertexBuffer, address, stride); VertexArray vertexArray = fastLookup.get(fastLookupKey); if (vertexArray != null) { if (vertexArray.isMatching(vtype, vertexBuffer, address, stride)) { statistics.end(); return vertexArray; } } boolean first = true; for (ListIterator<VertexArray> lit = vertexArrays.listIterator(); lit.hasNext(); ) { vertexArray = lit.next(); if (vertexArray.isMatching(vtype, vertexBuffer, address, stride)) { if (!first) { // Move the VertexArray to the head of the list lit.remove(); vertexArrays.add(0, vertexArray); } fastLookup.put(fastLookupKey, vertexArray); statistics.end(); return vertexArray; } first = false; } vertexArray = new VertexArray(vtype, vertexBuffer, stride); vertexArrays.add(0, vertexArray); if (vertexArrays.size() > maxSize) { VertexArray toBeDeleted = vertexArrays.remove(vertexArrays.size() - 1); if (toBeDeleted != null) { toBeDeleted.delete(re); } } statistics.end(); return vertexArray; } public void onVertexBufferDeleted(IRenderingEngine re, VertexBuffer vertexBuffer) { // Delete all the VertexArray using the deleted VertexBuffer for (ListIterator<VertexArray> lit = vertexArrays.listIterator(); lit.hasNext(); ) { VertexArray vertexArray = lit.next(); if (vertexArray.getVertexBuffer() == vertexBuffer) { lit.remove(); vertexArray.delete(re); } } } public void forceReloadAllVertexArrays() { for (VertexArray vertexArray : vertexArrays) { vertexArray.forceReload(); } } protected void displayStatistics() { for (VertexArray vertexArray : vertexArrays) { VideoEngine.log.info(vertexArray); } VideoEngine.log.info(String.format("VertexArrayManager: %d VAOs", vertexArrays.size())); } }