parent
7b038f9588
commit
e4f9b6a209
@ -0,0 +1,150 @@ |
|||||||
|
package com.otaliastudios.cameraview.filter; |
||||||
|
|
||||||
|
import android.opengl.GLES20; |
||||||
|
|
||||||
|
import androidx.annotation.NonNull; |
||||||
|
|
||||||
|
import com.otaliastudios.cameraview.internal.GlUtils; |
||||||
|
import com.otaliastudios.cameraview.size.Size; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.Collection; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
public class MultiFilter implements Filter { |
||||||
|
|
||||||
|
private static class State { |
||||||
|
boolean isCreated = false; |
||||||
|
int programHandle = -1; |
||||||
|
Size size = null; |
||||||
|
} |
||||||
|
|
||||||
|
private final Map<Filter, State> filters = new HashMap<>(); |
||||||
|
private final Object lock = new Object(); |
||||||
|
private Size size = null; |
||||||
|
|
||||||
|
@SuppressWarnings("WeakerAccess") |
||||||
|
public MultiFilter(@NonNull Filter... filters) { |
||||||
|
this(Arrays.asList(filters)); |
||||||
|
} |
||||||
|
|
||||||
|
@SuppressWarnings("WeakerAccess") |
||||||
|
public MultiFilter(@NonNull Collection<Filter> filters) { |
||||||
|
for (Filter filter : filters) { |
||||||
|
addFilter(filter); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@SuppressWarnings("WeakerAccess") |
||||||
|
public void addFilter(@NonNull Filter filter) { |
||||||
|
if (filter instanceof MultiFilter) { |
||||||
|
MultiFilter multiFilter = (MultiFilter) filter; |
||||||
|
for (Filter multiChild : multiFilter.filters.keySet()) { |
||||||
|
addFilter(multiChild); |
||||||
|
} |
||||||
|
return; |
||||||
|
} |
||||||
|
synchronized (lock) { |
||||||
|
if (!filters.keySet().contains(filter)) { |
||||||
|
filters.put(filter, new State()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// We don't offer a removeFilter method since that would cause issues
|
||||||
|
// with cleanup. Cleanup must happen on the GL thread so we'd have to wait
|
||||||
|
// for new rendering call (which might not even happen).
|
||||||
|
|
||||||
|
private void maybeCreate(@NonNull Filter filter) { |
||||||
|
State state = filters.get(filter); |
||||||
|
//noinspection ConstantConditions
|
||||||
|
if (!state.isCreated) { |
||||||
|
state.isCreated = true; |
||||||
|
state.programHandle = GlUtils.createProgram(filter.getVertexShader(), filter.getFragmentShader()); |
||||||
|
filter.onCreate(state.programHandle); |
||||||
|
// TODO extra creation
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void maybeDestroy(@NonNull Filter filter) { |
||||||
|
State state = filters.get(filter); |
||||||
|
//noinspection ConstantConditions
|
||||||
|
if (state.isCreated) { |
||||||
|
state.isCreated = false; |
||||||
|
filter.onDestroy(); |
||||||
|
GLES20.glDeleteProgram(state.programHandle); |
||||||
|
state.programHandle = -1; |
||||||
|
// TODO extra cleanup.
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void maybeSetSize(@NonNull Filter filter) { |
||||||
|
State state = filters.get(filter); |
||||||
|
//noinspection ConstantConditions
|
||||||
|
if (size != null && !size.equals(state.size)) { |
||||||
|
state.size = size; |
||||||
|
filter.setSize(size.getWidth(), size.getHeight()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@NonNull |
||||||
|
@Override |
||||||
|
public String getVertexShader() { |
||||||
|
return new NoFilter().getVertexShader(); |
||||||
|
} |
||||||
|
|
||||||
|
@NonNull |
||||||
|
@Override |
||||||
|
public String getFragmentShader() { |
||||||
|
return new NoFilter().getFragmentShader(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onCreate(int programHandle) { |
||||||
|
// We'll create children during the draw() op, since some of them
|
||||||
|
// might have been added after this onCreate() is called.
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onDestroy() { |
||||||
|
synchronized (lock) { |
||||||
|
for (Filter filter : filters.keySet()) { |
||||||
|
maybeDestroy(filter); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setSize(int width, int height) { |
||||||
|
size = new Size(width, height); |
||||||
|
synchronized (lock) { |
||||||
|
for (Filter filter : filters.keySet()) { |
||||||
|
maybeSetSize(filter); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void draw(float[] transformMatrix) { |
||||||
|
synchronized (lock) { |
||||||
|
for (Filter filter : filters.keySet()) { |
||||||
|
maybeCreate(filter); |
||||||
|
maybeSetSize(filter); |
||||||
|
} |
||||||
|
} |
||||||
|
// TODO
|
||||||
|
} |
||||||
|
|
||||||
|
@NonNull |
||||||
|
@Override |
||||||
|
public Filter copy() { |
||||||
|
synchronized (lock) { |
||||||
|
MultiFilter copy = new MultiFilter(); |
||||||
|
for (Filter filter : filters.keySet()) { |
||||||
|
copy.addFilter(filter.copy()); |
||||||
|
} |
||||||
|
return copy; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue