android: Add color correction shader setting
Former-commit-id: 894a0d6d6a07b16d3333739d565bba853ce13fc4
This commit is contained in:
parent
2aa0eec95e
commit
3db61d1804
|
@ -51,6 +51,7 @@ dependencies {
|
||||||
implementation 'com.google.android.material:material:1.1.0'
|
implementation 'com.google.android.material:material:1.1.0'
|
||||||
implementation "androidx.documentfile:documentfile:1.0.1"
|
implementation "androidx.documentfile:documentfile:1.0.1"
|
||||||
implementation 'androidx.preference:preference:1.1.0'
|
implementation 'androidx.preference:preference:1.1.0'
|
||||||
|
implementation 'commons-io:commons-io:2.6'
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
||||||
|
|
|
@ -13,10 +13,10 @@
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@drawable/icon"
|
android:icon="@drawable/icon"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@drawable/icon"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme">
|
android:theme="@style/AppTheme">
|
||||||
<activity android:name=".ui.snapshots.SnapshotPickerActivity"></activity>
|
<activity android:name=".ui.snapshots.SnapshotPickerActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.snapshots.SnapshotListFragment"
|
android:name=".ui.snapshots.SnapshotListFragment"
|
||||||
android:label="@string/title_activity_snapshot" />
|
android:label="@string/title_activity_snapshot" />
|
||||||
|
|
|
@ -377,7 +377,7 @@ public class EmulatorActivity extends AppCompatActivity implements View.OnClickL
|
||||||
|
|
||||||
SharedPreferences sharedPreferences =
|
SharedPreferences sharedPreferences =
|
||||||
PreferenceManager.getDefaultSharedPreferences(this /* Activity context */);
|
PreferenceManager.getDefaultSharedPreferences(this /* Activity context */);
|
||||||
Boolean skipBios = sharedPreferences.getBoolean("skip_bios", false);
|
boolean skipBios = sharedPreferences.getBoolean("skip_bios", false);
|
||||||
|
|
||||||
if (null != savedInstanceState && (saveFilePath = savedInstanceState.getString("saveFile")) != null) {
|
if (null != savedInstanceState && (saveFilePath = savedInstanceState.getString("saveFile")) != null) {
|
||||||
final EmulatorActivity thisActivity = this;
|
final EmulatorActivity thisActivity = this;
|
||||||
|
@ -451,6 +451,10 @@ public class EmulatorActivity extends AppCompatActivity implements View.OnClickL
|
||||||
case R.id.action_save_snapshot:
|
case R.id.action_save_snapshot:
|
||||||
doSaveSnapshot();
|
doSaveSnapshot();
|
||||||
return true;
|
return true;
|
||||||
|
case R.id.action_settings:
|
||||||
|
Intent intent = new Intent(this, SettingsActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,24 @@
|
||||||
package com.mrmichel.rustdroid_emu.ui;
|
package com.mrmichel.rustdroid_emu.ui;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.opengl.GLES20;
|
import android.opengl.GLES20;
|
||||||
import android.opengl.GLSurfaceView;
|
import android.opengl.GLSurfaceView;
|
||||||
import android.opengl.GLUtils;
|
import android.opengl.GLUtils;
|
||||||
|
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
|
import com.mrmichel.rustdroid_emu.R;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import javax.microedition.khronos.egl.EGLConfig;
|
import javax.microedition.khronos.egl.EGLConfig;
|
||||||
import javax.microedition.khronos.opengles.GL10;
|
import javax.microedition.khronos.opengles.GL10;
|
||||||
|
@ -16,12 +27,53 @@ public class ScreenRenderer implements GLSurfaceView.Renderer {
|
||||||
|
|
||||||
private ScreenTexture texture;
|
private ScreenTexture texture;
|
||||||
private boolean ready = false;
|
private boolean ready = false;
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
public ScreenRenderer(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateTexture(int[] frameBuffer) {
|
||||||
|
this.texture.update(frameBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initTextureIfNotInitialized() {
|
||||||
|
if (this.texture == null) {
|
||||||
|
this.texture = new ScreenTexture(this.context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
||||||
|
initTextureIfNotInitialized();
|
||||||
|
ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSurfaceChanged(GL10 gl, int width, int height) {
|
||||||
|
gl.glViewport(0, 0, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDrawFrame(GL10 gl) {
|
||||||
|
this.texture.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isReady() {
|
||||||
|
return ready;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColorCorrection(boolean colorCorrection) {
|
||||||
|
this.texture.setColorCorrection(colorCorrection);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private class to manage the screen texture rendering
|
* Private class to manage the screen texture rendering
|
||||||
*/
|
*/
|
||||||
private class ScreenTexture {
|
private class ScreenTexture {
|
||||||
int shaderProgram;
|
int normalShaderProgram;
|
||||||
|
int colorCorrectionShaderProgram;
|
||||||
|
int currentShaderProgram;
|
||||||
int positionHandle;
|
int positionHandle;
|
||||||
int texCoordHandle;
|
int texCoordHandle;
|
||||||
int samplerHandle;
|
int samplerHandle;
|
||||||
|
@ -32,6 +84,7 @@ public class ScreenRenderer implements GLSurfaceView.Renderer {
|
||||||
private ByteBuffer indicesBuffer;
|
private ByteBuffer indicesBuffer;
|
||||||
|
|
||||||
private Bitmap bitmap;
|
private Bitmap bitmap;
|
||||||
|
private Context context;
|
||||||
|
|
||||||
// square vertices
|
// square vertices
|
||||||
private float[] vertices = {
|
private float[] vertices = {
|
||||||
|
@ -55,26 +108,75 @@ public class ScreenRenderer implements GLSurfaceView.Renderer {
|
||||||
0, 2, 3
|
0, 2, 3
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final String VERTEX_SHADER_CODE =
|
public ScreenTexture(Context context) {
|
||||||
"attribute vec4 a_position; \n" +
|
this.context = context;
|
||||||
"attribute vec2 a_texCoord; \n" +
|
this.bitmap = Bitmap.createBitmap(240, 160, Bitmap.Config.RGB_565);
|
||||||
"varying vec2 v_texCoord; \n" +
|
|
||||||
"void main() \n" +
|
|
||||||
"{ \n" +
|
|
||||||
" gl_Position = a_position; \n" +
|
|
||||||
" v_texCoord = a_texCoord; \n" +
|
|
||||||
"} \n";
|
|
||||||
|
|
||||||
private static final String FRAGMENT_SHADER_CODE =
|
GLES20.glEnable(GLES20.GL_TEXTURE_2D);
|
||||||
"precision mediump float; \n" +
|
|
||||||
"varying vec2 v_texCoord; \n" +
|
|
||||||
"uniform sampler2D s_texture; \n" +
|
|
||||||
"void main() \n" +
|
|
||||||
"{ \n" +
|
|
||||||
" vec4 color = texture2D( s_texture, v_texCoord ); \n" +
|
|
||||||
" gl_FragColor = color; \n" +
|
|
||||||
"} \n";
|
|
||||||
|
|
||||||
|
// create vertex array
|
||||||
|
vertexBuffer = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
|
||||||
|
vertexBuffer.put(vertices);
|
||||||
|
vertexBuffer.position(0);
|
||||||
|
|
||||||
|
// create texture coordinate array
|
||||||
|
textureBuffer = ByteBuffer.allocateDirect(textureVertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
|
||||||
|
textureBuffer.put(textureVertices);
|
||||||
|
textureBuffer.position(0);
|
||||||
|
|
||||||
|
// create triangle index array
|
||||||
|
indicesBuffer = ByteBuffer.allocateDirect(indicies.length).order(ByteOrder.nativeOrder());
|
||||||
|
indicesBuffer.put(indicies);
|
||||||
|
indicesBuffer.position(0);
|
||||||
|
|
||||||
|
textureId = createTexture();
|
||||||
|
|
||||||
|
String vertexShader = readShaderResource(R.raw.screen_texture_vertex_shader);
|
||||||
|
String normalFragmentShader = readShaderResource(R.raw.screen_texture_fragment_shader);
|
||||||
|
String colorCorrectionFragmentShader = readShaderResource(R.raw.screen_texture_color_correction_fragment_shader);
|
||||||
|
|
||||||
|
normalShaderProgram = createShaderProgram(vertexShader, normalFragmentShader);
|
||||||
|
colorCorrectionShaderProgram = createShaderProgram(vertexShader, colorCorrectionFragmentShader);
|
||||||
|
|
||||||
|
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this.context);
|
||||||
|
boolean colorCorrection = sharedPreferences.getBoolean("color_correction", false);
|
||||||
|
setColorCorrection(colorCorrection);
|
||||||
|
|
||||||
|
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setColorCorrection(boolean colorCorrection) {
|
||||||
|
|
||||||
|
if (colorCorrection) {
|
||||||
|
currentShaderProgram = colorCorrectionShaderProgram;
|
||||||
|
} else {
|
||||||
|
currentShaderProgram = normalShaderProgram;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use the program
|
||||||
|
GLES20.glUseProgram(currentShaderProgram);
|
||||||
|
|
||||||
|
positionHandle = GLES20.glGetAttribLocation(currentShaderProgram, "a_position");
|
||||||
|
|
||||||
|
texCoordHandle = GLES20.glGetAttribLocation(currentShaderProgram, "a_texCoord");
|
||||||
|
|
||||||
|
samplerHandle = GLES20.glGetUniformLocation(currentShaderProgram, "s_texture");
|
||||||
|
|
||||||
|
|
||||||
|
// load the vertex position
|
||||||
|
GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);
|
||||||
|
GLES20.glEnableVertexAttribArray(positionHandle);
|
||||||
|
// load texture coordinate
|
||||||
|
GLES20.glVertexAttribPointer(texCoordHandle, 2, GLES20.GL_FLOAT, false, 0, textureBuffer);
|
||||||
|
GLES20.glEnableVertexAttribArray(texCoordHandle);
|
||||||
|
|
||||||
|
|
||||||
|
GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);
|
||||||
|
GLES20.glEnableVertexAttribArray(positionHandle);
|
||||||
|
// load texture coordinate
|
||||||
|
GLES20.glVertexAttribPointer(texCoordHandle, 2, GLES20.GL_FLOAT, false, 0, textureBuffer);
|
||||||
|
GLES20.glEnableVertexAttribArray(texCoordHandle);
|
||||||
|
}
|
||||||
|
|
||||||
private int compileShader(int type, String code) {
|
private int compileShader(int type, String code) {
|
||||||
int shader = GLES20.glCreateShader(type);
|
int shader = GLES20.glCreateShader(type);
|
||||||
|
@ -123,58 +225,28 @@ public class ScreenRenderer implements GLSurfaceView.Renderer {
|
||||||
return texturesIds[0];
|
return texturesIds[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScreenTexture() {
|
private String readShaderResource(int resourceId) {
|
||||||
this.bitmap = Bitmap.createBitmap(240, 160, Bitmap.Config.RGB_565);
|
InputStream in = context.getResources().openRawResource(resourceId);
|
||||||
|
String code;
|
||||||
GLES20.glEnable(GLES20.GL_TEXTURE_2D);
|
try {
|
||||||
|
code = IOUtils.toString(in, StandardCharsets.UTF_8);
|
||||||
// create vertex array
|
} catch (IOException e) {
|
||||||
vertexBuffer = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
|
code = "";
|
||||||
vertexBuffer.put(vertices);
|
}
|
||||||
vertexBuffer.position(0);
|
return code;
|
||||||
|
|
||||||
// create texture coordinate array
|
|
||||||
textureBuffer = ByteBuffer.allocateDirect(textureVertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
|
|
||||||
textureBuffer.put(textureVertices);
|
|
||||||
textureBuffer.position(0);
|
|
||||||
|
|
||||||
// create triangle index array
|
|
||||||
indicesBuffer = ByteBuffer.allocateDirect(indicies.length).order(ByteOrder.nativeOrder());
|
|
||||||
indicesBuffer.put(indicies);
|
|
||||||
indicesBuffer.position(0);
|
|
||||||
|
|
||||||
textureId = createTexture();
|
|
||||||
|
|
||||||
shaderProgram = createShaderProgram(VERTEX_SHADER_CODE, FRAGMENT_SHADER_CODE);
|
|
||||||
|
|
||||||
// use the program
|
|
||||||
GLES20.glUseProgram(shaderProgram);
|
|
||||||
|
|
||||||
positionHandle = GLES20.glGetAttribLocation(shaderProgram, "a_position");
|
|
||||||
|
|
||||||
texCoordHandle = GLES20.glGetAttribLocation(shaderProgram, "a_texCoord");
|
|
||||||
|
|
||||||
samplerHandle = GLES20.glGetUniformLocation(shaderProgram, "s_texture");
|
|
||||||
|
|
||||||
|
|
||||||
// load the vertex position
|
|
||||||
GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);
|
|
||||||
GLES20.glEnableVertexAttribArray(positionHandle);
|
|
||||||
// load texture coordinate
|
|
||||||
GLES20.glVertexAttribPointer(texCoordHandle, 2, GLES20.GL_FLOAT, false, 0, textureBuffer);
|
|
||||||
GLES20.glEnableVertexAttribArray(texCoordHandle);
|
|
||||||
|
|
||||||
|
|
||||||
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void destroy() {
|
protected void destroy() {
|
||||||
GLES20.glDeleteProgram(shaderProgram);
|
GLES20.glDeleteProgram(normalShaderProgram);
|
||||||
|
GLES20.glDeleteProgram(colorCorrectionShaderProgram);
|
||||||
int[] textures = {textureId};
|
int[] textures = {textureId};
|
||||||
GLES20.glDeleteTextures(1, textures, 0);
|
GLES20.glDeleteTextures(1, textures, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render() {
|
public void render() {
|
||||||
|
// use the shader program
|
||||||
|
GLES20.glUseProgram(currentShaderProgram);
|
||||||
|
|
||||||
// clear the color buffer
|
// clear the color buffer
|
||||||
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
|
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
@ -190,34 +262,4 @@ public class ScreenRenderer implements GLSurfaceView.Renderer {
|
||||||
GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 6, GLES20.GL_UNSIGNED_BYTE, indicesBuffer);
|
GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 6, GLES20.GL_UNSIGNED_BYTE, indicesBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateTexture(int[] frameBuffer) {
|
|
||||||
this.texture.update(frameBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initTextureIfNotInitialized() {
|
|
||||||
if (this.texture == null) {
|
|
||||||
this.texture = new ScreenTexture();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
|
||||||
initTextureIfNotInitialized();
|
|
||||||
ready = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSurfaceChanged(GL10 gl, int width, int height) {
|
|
||||||
gl.glViewport(0, 0, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDrawFrame(GL10 gl) {
|
|
||||||
this.texture.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isReady() {
|
|
||||||
return ready;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
package com.mrmichel.rustdroid_emu.ui;
|
package com.mrmichel.rustdroid_emu.ui;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.opengl.GLSurfaceView;
|
import android.opengl.GLSurfaceView;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
public class ScreenView extends GLSurfaceView {
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
|
public class ScreenView extends GLSurfaceView implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
private ScreenRenderer mRenderer;
|
private ScreenRenderer mRenderer;
|
||||||
|
|
||||||
public ScreenView(Context context) {
|
public ScreenView(Context context) {
|
||||||
|
@ -21,7 +24,11 @@ public class ScreenView extends GLSurfaceView {
|
||||||
this.setEGLContextClientVersion(2);
|
this.setEGLContextClientVersion(2);
|
||||||
this.setPreserveEGLContextOnPause(true);
|
this.setPreserveEGLContextOnPause(true);
|
||||||
|
|
||||||
mRenderer = new ScreenRenderer();
|
SharedPreferences sharedPreferences =
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
|
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
|
||||||
|
|
||||||
|
mRenderer = new ScreenRenderer(getContext());
|
||||||
this.setRenderer(mRenderer);
|
this.setRenderer(mRenderer);
|
||||||
this.setRenderMode(RENDERMODE_WHEN_DIRTY);
|
this.setRenderMode(RENDERMODE_WHEN_DIRTY);
|
||||||
}
|
}
|
||||||
|
@ -34,4 +41,12 @@ public class ScreenView extends GLSurfaceView {
|
||||||
public ScreenRenderer getRenderer() {
|
public ScreenRenderer getRenderer() {
|
||||||
return mRenderer;
|
return mRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||||
|
if (key.equals("color_correction")) {
|
||||||
|
boolean colorCorrection = sharedPreferences.getBoolean("color_correction", false);
|
||||||
|
mRenderer.setColorCorrection(colorCorrection);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,18 +2,32 @@ package com.mrmichel.rustdroid_emu.ui;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.ActionBar;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
|
|
||||||
import com.mrmichel.rustdroid_emu.R;
|
import com.mrmichel.rustdroid_emu.R;
|
||||||
|
|
||||||
public class SettingsActivity extends AppCompatActivity {
|
public class SettingsActivity extends AppCompatActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_settings);
|
setContentView(R.layout.activity_settings);
|
||||||
getSupportFragmentManager()
|
getSupportFragmentManager()
|
||||||
.beginTransaction()
|
.beginTransaction()
|
||||||
.replace(R.id.settings_container, new SettingsFragment())
|
.replace(R.id.settings, new SettingsFragment())
|
||||||
.commit();
|
.commit();
|
||||||
|
ActionBar actionBar = getSupportActionBar();
|
||||||
|
if (actionBar != null) {
|
||||||
|
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SettingsFragment extends PreferenceFragmentCompat {
|
||||||
|
@Override
|
||||||
|
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||||
|
setPreferencesFromResource(R.xml.app_preferences, rootKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,7 +13,6 @@ import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.webkit.MimeTypeMap;
|
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.GridView;
|
import android.widget.GridView;
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent">
|
||||||
android:orientation="vertical" >
|
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/settings_container"
|
android:id="@+id/settings"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent" />
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
Port of byuu's color correction shader as described in https://byuu.net/video/color-emulation
|
||||||
|
*/
|
||||||
|
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
varying vec2 v_texCoord;
|
||||||
|
uniform sampler2D s_texture;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
float lcdGamma = 4.0, outGamma = 2.2;
|
||||||
|
|
||||||
|
vec4 color = texture2D( s_texture, v_texCoord );
|
||||||
|
|
||||||
|
color.rgb = pow(color.rgb, vec3(lcdGamma));
|
||||||
|
gl_FragColor.r = pow(( 0.0 * color.b + 50.0 * color.g + 255.0 * color.r) / 255.0, 1.0 / outGamma) * 255.0 / 280.0;
|
||||||
|
gl_FragColor.g = pow(( 30.0 * color.b + 230.0 * color.g + 10.0 * color.r) / 255.0, 1.0 / outGamma) * 255.0 / 280.0;
|
||||||
|
gl_FragColor.b = pow((220.0 * color.b + 10.0 * color.g + 50.0 * color.r) / 255.0, 1.0 / outGamma) * 255.0 / 280.0;
|
||||||
|
gl_FragColor.a = 1.0;
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
precision mediump float;
|
||||||
|
varying vec2 v_texCoord;
|
||||||
|
uniform sampler2D s_texture;
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 color = texture2D( s_texture, v_texCoord );
|
||||||
|
gl_FragColor = color;
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
attribute vec4 a_position;
|
||||||
|
attribute vec2 a_texCoord;
|
||||||
|
varying vec2 v_texCoord;
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = a_position;
|
||||||
|
v_texCoord = a_texCoord;
|
||||||
|
}
|
|
@ -16,4 +16,9 @@
|
||||||
<string name="action_delete">Delete</string>
|
<string name="action_delete">Delete</string>
|
||||||
|
|
||||||
<string name="title_activity_snapshot">Snapshot Manager</string>
|
<string name="title_activity_snapshot">Snapshot Manager</string>
|
||||||
|
|
||||||
|
<string name="color_correction_setting">Apply color correction shader</string>
|
||||||
|
<string name="color_correction_summary">
|
||||||
|
Makes colors look closer to the real GBA LCD screen.
|
||||||
|
</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,8 +1,18 @@
|
||||||
<PreferenceScreen
|
<PreferenceScreen
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<CheckBoxPreference
|
<PreferenceCategory app:title="Emulation">
|
||||||
|
<SwitchPreferenceCompat
|
||||||
app:key="skip_bios"
|
app:key="skip_bios"
|
||||||
app:title="Skip bios boot animation"/>
|
app:title="Skip bios boot animation"/>
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory app:title="Graphics">
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
app:key="color_correction"
|
||||||
|
app:title="@string/color_correction_setting"
|
||||||
|
app:summary="@string/color_correction_summary"
|
||||||
|
/>
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
Reference in a new issue