package com.marshalchen.common.uimodule.imageprocessing.filter; import java.util.ArrayList; import java.util.List; import com.marshalchen.common.uimodule.imageprocessing.input.GLTextureOutputRenderer; import com.marshalchen.common.uimodule.imageprocessing.output.GLTextureInputRenderer; /** * A multiple filter renderer extension of the BasicFilter. * This class allows for a filter that contains multiple filters to create the output. * This class can be used as the base for a filter which is made up of multiple filters. * Similar to the CompositeFilter, the GroupFilter consists of multiple filters. * The difference is that the CompositeFilter has its own shaders whereas the GroupFilter does not. * This class is simply a wrapper for a small pipeline of filters. Like the CompositeFilter, all filters * must be registered. The filters that begin the internal pipeline of this filter should be registered as * initial filters. The filters that end the pipeline and produce output for the next filter in the external chain * should be registered as terminal filters. All other filters that are internal to this class should be * registered using registerFilter(BasicFilter filter). In most cases there should only be one terminalFilter because * there is no way to separate the outputs into different streams. * @author Chris Batt */ public abstract class GroupFilter extends BasicFilter { private List<BasicFilter> initialFilters; private List<BasicFilter> filters; private List<BasicFilter> terminalFilters; /** * Creates a GroupFilter with any number of initial filters or filter graphs. */ public GroupFilter() { initialFilters = new ArrayList<BasicFilter>(); terminalFilters = new ArrayList<BasicFilter>(); filters = new ArrayList<BasicFilter>(); } /* (non-Javadoc) * @see com.marshalchen.common.uimodule.imageprocessing.input.GLTextureOutputRenderer#destroy() */ @Override public void destroy() { super.destroy(); for(BasicFilter filter : filters) { filter.destroy(); } } /* * If the source is one of the end points of the input filters then it is the result * of one of the internal filters. When all internal filters have finished we can * draw the multi-input filter. If the source is not in the list of renderers then it * must be an external input which should be passed to each of the initial renderers * of this multi-input filter. */ /* (non-Javadoc) * @see com.marshalchen.common.uimodule.imageprocessing.filter.BasicFilter#newTextureReady(int, com.marshalchen.common.uimodule.imageprocessing.input.GLTextureOutputRenderer) */ @Override public void newTextureReady(int texture, GLTextureOutputRenderer source, boolean newData) { if(terminalFilters.contains(source)) { setWidth(source.getWidth()); setHeight(source.getHeight()); synchronized(getLockObject()) { for(GLTextureInputRenderer target : getTargets()) { target.newTextureReady(texture, this, newData); } } } else { for(BasicFilter initialFilter : initialFilters) { initialFilter.newTextureReady(texture, source, newData); } } } protected void registerFilter(BasicFilter filter) { if(!filters.contains(filter)) { filters.add(filter); } } protected void registerInitialFilter(BasicFilter filter) { initialFilters.add(filter); registerFilter(filter); } protected void registerTerminalFilter(BasicFilter filter) { terminalFilters.add(filter); registerFilter(filter); } /* (non-Javadoc) * @see com.marshalchen.common.uimodule.imageprocessing.GLRenderer#setRenderSize(int, int) */ @Override public void setRenderSize(int width, int height) { for(BasicFilter filter : filters) { filter.setRenderSize(width, height); } } }