/* JWildfire - an image and animation processor written in Java Copyright (C) 1995-2017 Andreas Maschke This 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 2.1 of the License, or (at your option) any later version. This software 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 this software; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jwildfire.create.tina.render; import java.util.ArrayList; import java.util.List; import org.jwildfire.base.Prefs; import org.jwildfire.create.tina.base.Layer; public abstract class DefaultRenderThread extends AbstractRenderThread { private static final int MAX_ERRORS = 100; protected long startIter; protected long iter; protected List<DefaultRenderIterationState> iterationState; public DefaultRenderThread(Prefs pPrefs, int pThreadId, int pThreadGroupSize, FlameRenderer pRenderer, List<RenderPacket> pRenderPackets, long pSamples, List<RenderSlice> pSlices) { super(pPrefs, pThreadId, pThreadGroupSize, pRenderer, pRenderPackets, pSamples, pSlices); iterationState = new ArrayList<DefaultRenderIterationState>(); for (RenderPacket packet : pRenderPackets) { List<Layer> layers = getValidLayers(packet.getFlame()); for (Layer layer : layers) { DefaultRenderIterationState state = createState(packet, layer); iterationState.add(state); } } } protected abstract DefaultRenderIterationState createState(RenderPacket pRenderPacket, Layer pLayer); @Override protected RenderThreadPersistentState saveState() { DefaultRenderThreadPersistentState res = new DefaultRenderThreadPersistentState(); res.currSample = currSample; res.startIter = iter; for (DefaultRenderIterationState state : iterationState) { DefaultRenderThreadPersistentState.IterationState persist = new DefaultRenderThreadPersistentState.IterationState(); persist.packetIdx = renderPackets.indexOf(state.packet); persist.layerIdx = state.flame.getLayers().indexOf(state.layer); persist.xfIndex = (state.xf != null) ? state.layer.getXForms().indexOf(state.xf) : -1; persist.affineT = state.affineT != null ? state.affineT.makeCopy() : null; persist.varT = state.varT != null ? state.varT.makeCopy() : null; persist.p = state.p != null ? state.p.makeCopy() : null; persist.q = state.q != null ? state.q.makeCopy() : null; res.getLayerState().add(persist); } return res; } @Override protected void restoreState(RenderThreadPersistentState pState) { iterationState.clear(); DefaultRenderThreadPersistentState state = (DefaultRenderThreadPersistentState) pState; currSample = state.currSample; startIter = state.startIter; for (DefaultRenderThreadPersistentState.IterationState persist : state.getLayerState()) { RenderPacket packet = renderPackets.get(persist.packetIdx); Layer layer = packet.getFlame().getLayers().get(persist.layerIdx); DefaultRenderIterationState restored = createState(packet, layer); restored.xf = (persist.xfIndex >= 0) ? restored.layer.getXForms().get(persist.xfIndex) : null; restored.affineT = persist.affineT != null ? persist.affineT.makeCopy() : null; restored.varT = persist.varT != null ? persist.varT.makeCopy() : null; restored.p = persist.p != null ? persist.p.makeCopy() : null; restored.q = persist.q != null ? persist.q.makeCopy() : null; iterationState.add(restored); } } @Override protected void preFuseIter() { for (DefaultRenderIterationState state : iterationState) { state.preFuseIter(); } } @Override protected void initState() { startIter = 0; preFuseIter(); } @Override protected void iterate() { final int iterInc = iterationState.size(); if (iterInc < 1) { return; } for (DefaultRenderIterationState state : iterationState) { state.init(); } int errors = 0; try { for (iter = startIter; !forceAbort && (samples < 0 || iter < samples); iter += iterInc) { if (iter % 1000 == 0) { currSample = iter; for (DefaultRenderIterationState state : iterationState) { state.validateState(); } } for (DefaultRenderIterationState state : iterationState) { try { state.iterateNext(); } catch (Exception ex) { errors++; state.validateState(); if (errors > MAX_ERRORS) { System.out.println("INVALID FLAME"); iter = samples; break; } } } } } finally { for (DefaultRenderIterationState state : iterationState) { try { state.cleanup(); } catch (Exception ex) { ex.printStackTrace(); } } } } @Override protected void iterateSlices(List<RenderSlice> pSlices) { final int iterInc = iterationState.size(); if (iterInc < 1) { return; } for (DefaultRenderIterationState state : iterationState) { state.init(); } for (iter = startIter; !forceAbort && (samples < 0 || iter < samples); iter += iterInc) { if (iter % 10000000 == 0) { preFuseIter(); } else if (iter % 10000 == 0) { currSample = iter; for (DefaultRenderIterationState state : iterationState) { state.validateState(); } } for (DefaultRenderIterationState state : iterationState) { state.iterateNext(pSlices); } } } }