android: don't use storage for default buttons.png

This commit is contained in:
Flyinghead 2020-03-24 23:31:34 +01:00
parent c098790f3b
commit 5894992f70
15 changed files with 154 additions and 174 deletions

View File

@ -14,6 +14,7 @@
#include <xxhash.h>
#include "CustomTexture.h"
#include <png.h>
#include <pngstruct.h>
u8* vq_codebook;
u32 palette_index;
@ -955,54 +956,22 @@ void rend_text_invl(vram_block* bl)
libCore_vramlock_Unlock_block_wb(bl);
}
static FILE* pngfile;
void png_cstd_read(png_structp png_ptr, png_bytep data, png_size_t length)
static u8* loadPNGData(const u8 *header, png_voidp io_ptr, png_rw_ptr read_func, int &width, int &height)
{
if (fread(data, 1, length, pngfile) != length)
png_error(png_ptr, "Truncated read error");
}
u8* loadPNGData(const string& fname, int &width, int &height)
{
const char* filename=fname.c_str();
FILE* file = fopen(filename, "rb");
pngfile=file;
if (!file)
{
EMUERROR("Error opening %s", filename);
return NULL;
}
//header for testing if it is a png
png_byte header[8];
//read the header
if (fread(header, 1, 8, file) != 8)
{
fclose(file);
WARN_LOG(RENDERER, "Not a PNG file : %s", filename);
return NULL;
}
//test if png
int is_png = !png_sig_cmp(header, 0, 8);
if (!is_png)
{
fclose(file);
WARN_LOG(RENDERER, "Not a PNG file : %s", filename);
WARN_LOG(RENDERER, "Passed data isn't a PNG file");
return NULL;
}
//create png struct
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
NULL, NULL);
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
{
fclose(file);
WARN_LOG(RENDERER, "Unable to create PNG struct : %s", filename);
return (NULL);
WARN_LOG(RENDERER, "Unable to create PNG struct");
return NULL;
}
//create png info struct
@ -1010,9 +979,8 @@ u8* loadPNGData(const string& fname, int &width, int &height)
if (!info_ptr)
{
png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
WARN_LOG(RENDERER, "Unable to create PNG info : %s", filename);
fclose(file);
return (NULL);
WARN_LOG(RENDERER, "Unable to create PNG info");
return NULL;
}
//create png info struct
@ -1020,23 +988,21 @@ u8* loadPNGData(const string& fname, int &width, int &height)
if (!end_info)
{
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
WARN_LOG(RENDERER, "Unable to create PNG end info : %s", filename);
fclose(file);
return (NULL);
WARN_LOG(RENDERER, "Unable to create PNG end info");
return NULL;
}
//png error stuff, not sure libpng man suggests this.
if (setjmp(png_jmpbuf(png_ptr)))
{
fclose(file);
WARN_LOG(RENDERER, "Error during setjmp : %s", filename);
WARN_LOG(RENDERER, "Error during setjmp");
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
return (NULL);
return NULL;
}
//init png reading
//png_init_io(png_ptr, fp);
png_set_read_fn(png_ptr, NULL, png_cstd_read);
png_set_read_fn(png_ptr, io_ptr, read_func);
//let libpng know you already read the first 8 bytes
png_set_sig_bytes(png_ptr, 8);
@ -1068,8 +1034,7 @@ u8* loadPNGData(const string& fname, int &width, int &height)
{
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
WARN_LOG(RENDERER, "Unable to allocate image_data while loading %s", filename);
fclose(file);
WARN_LOG(RENDERER, "Unable to allocate image_data");
return NULL;
}
@ -1080,8 +1045,7 @@ u8* loadPNGData(const string& fname, int &width, int &height)
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
delete[] image_data;
WARN_LOG(RENDERER, "Unable to allocate row_pointer while loading %s", filename);
fclose(file);
WARN_LOG(RENDERER, "Unable to allocate row_pointer");
return NULL;
}
@ -1094,11 +1058,58 @@ u8* loadPNGData(const string& fname, int &width, int &height)
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
delete[] row_pointers;
fclose(file);
return image_data;
}
static size_t png_offset;
static void png_read_vector(png_structp png_ptr, png_bytep data, png_size_t length)
{
const std::vector<u8> *v = (const std::vector<u8> *)png_ptr->io_ptr;
memcpy(data, v->data() + png_offset, length);
png_offset += length;
}
u8* loadPNGData(const std::vector<u8>& data, int &width, int &height)
{
png_offset = 8;
return loadPNGData(data.data(), (void *)&data, png_read_vector, width, height);
}
static void png_cstd_read(png_structp png_ptr, png_bytep data, png_size_t length)
{
if (fread(data, 1, length, (FILE *)png_ptr->io_ptr) != length)
png_error(png_ptr, "Truncated read error");
}
u8* loadPNGData(const string& fname, int &width, int &height)
{
const char* filename=fname.c_str();
FILE* file = fopen(filename, "rb");
if (!file)
{
EMUERROR("Error opening %s", filename);
return NULL;
}
//header for testing if it is a png
png_byte header[8];
//read the header
if (fread(header, 1, 8, file) != 8)
{
fclose(file);
WARN_LOG(RENDERER, "Not a PNG file : %s", filename);
return NULL;
}
u8 *data = loadPNGData(header, file, png_cstd_read, width, height);
fclose(file);
return data;
}
#ifdef TEST_AUTOMATION
void dump_screenshot(u8 *buffer, u32 width, u32 height, bool alpha, u32 rowPitch, bool invertY)
{

View File

@ -819,6 +819,7 @@ static inline void MakeFogTexture(u8 *tex_data)
}
}
u8* loadPNGData(const string& fname, int &width, int &height);
u8* loadPNGData(const std::vector<u8>& data, int &width, int &height);
void dump_screenshot(u8 *buffer, u32 width, u32 height, bool alpha = false, u32 rowPitch = 0, bool invertY = true);
extern const std::array<f32, 16> D_Adjust_LoD_Bias;

View File

@ -516,8 +516,6 @@ static bool gl_create_resources()
create_modvol_shader();
gl_load_osd_resources();
// Create the buffer for Translucent poly params
glGenBuffers(1, &gl4.vbo.tr_poly_params);
// Bind it

View File

@ -756,9 +756,18 @@ void gl_load_osd_resources()
glUniform1i(glGetUniformLocation(gl.OSD_SHADER.program, "tex"), 0); //bind osd texture to slot 0
#ifdef __ANDROID__
int w, h;
if (gl.OSD_SHADER.osd_tex == 0)
gl.OSD_SHADER.osd_tex = loadPNG(get_readonly_data_path(DATA_PATH "buttons.png"), w, h);
{
int width, height;
u8 *image_data = loadOSDButtons(width, height);
//Now generate the OpenGL texture object
gl.OSD_SHADER.osd_tex = glcache.GenTexture();
glcache.BindTexture(GL_TEXTURE_2D, gl.OSD_SHADER.osd_tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)image_data);
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
delete[] image_data;
}
#endif
SetupOSDVBO();
}
@ -821,8 +830,6 @@ bool gl_create_resources()
create_modvol_shader();
gl_load_osd_resources();
return true;
}
@ -1283,24 +1290,4 @@ struct glesrend : Renderer
}
};
GLuint loadPNG(const string& fname, int &width, int &height)
{
png_byte *image_data = loadPNGData(fname, width, height);
if (image_data == NULL)
return TEXTURE_LOAD_ERROR;
//Now generate the OpenGL texture object
GLuint texture = glcache.GenTexture();
glcache.BindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, (GLvoid*) image_data);
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
delete[] image_data;
return texture;
}
Renderer* rend_GLES2() { return new glesrend(); }

View File

@ -152,9 +152,6 @@ PipelineShader *GetProgram(u32 cp_AlphaTest, u32 pp_ClipTestMode,
GLuint gl_CompileShader(const char* shader, GLuint type);
GLuint gl_CompileAndLink(const char* VertexShader, const char* FragmentShader);
bool CompilePipelineShader(PipelineShader* s);
#define TEXTURE_LOAD_ERROR 0
u8* loadPNGData(const string& subpath, int &width, int &height);
GLuint loadPNG(const string& subpath, int &width, int &height);
extern struct ShaderUniforms_t
{

View File

@ -123,6 +123,9 @@ void TextureCacheData::UploadToGPU(int width, int height, u8 *temp_tex_buffer, b
case TextureType::_8888:
internalFormat = GL_RGBA8;
break;
default:
die("Unsupported texture format");
break;
}
if (Updates == 1)
{

View File

@ -18,6 +18,7 @@
#include "types.h"
#include "input/gamepad.h"
#include "input/gamepad_device.h"
#include "TexCache.h"
#if defined(__ANDROID__)
extern float vjoy_pos[15][8];
@ -53,6 +54,7 @@ static const float vjoy_sz[2][15] = {
};
static std::vector<OSDVertex> osdVertices;
std::vector<u8> DefaultOSDButtons;
void HideOSD()
{
@ -142,3 +144,14 @@ static void setVjoyUV()
static OnLoad setVjoyUVOnLoad(&setVjoyUV);
u8 *loadOSDButtons(int &width, int &height)
{
u8 *image_data = loadPNGData(get_readonly_data_path(DATA_PATH "buttons.png"), width, height);
if (image_data == nullptr)
{
if (DefaultOSDButtons.empty())
die("No default OSD buttons");
image_data = loadPNGData(DefaultOSDButtons, width, height);
}
return image_data;
}

View File

@ -29,3 +29,6 @@ struct OSDVertex
};
const std::vector<OSDVertex>& GetOSDVertices();
extern std::vector<u8> DefaultOSDButtons;
u8 *loadOSDButtons(int &width, int &height);

View File

@ -50,27 +50,20 @@ public:
if (!vjoyTexture)
{
int w, h;
u8 *image_data = loadPNGData(get_readonly_data_path(DATA_PATH "buttons.png"), w, h);
if (image_data == nullptr)
{
WARN_LOG(RENDERER, "Cannot load buttons.png image");
}
else
{
texCommandPool.BeginFrame();
vjoyTexture = std::unique_ptr<Texture>(new Texture());
vjoyTexture->tex_type = TextureType::_8888;
vjoyTexture->tcw.full = 0;
vjoyTexture->tsp.full = 0;
vjoyTexture->SetPhysicalDevice(GetContext()->GetPhysicalDevice());
vjoyTexture->SetDevice(GetContext()->GetDevice());
vjoyTexture->SetCommandBuffer(texCommandPool.Allocate());
vjoyTexture->UploadToGPU(OSD_TEX_W, OSD_TEX_H, image_data, false);
vjoyTexture->SetCommandBuffer(nullptr);
texCommandPool.EndFrame();
delete [] image_data;
osdPipeline.Init(&normalShaderManager, vjoyTexture->GetImageView(), GetContext()->GetRenderPass());
}
u8 *image_data = loadOSDButtons(w, h);
texCommandPool.BeginFrame();
vjoyTexture = std::unique_ptr<Texture>(new Texture());
vjoyTexture->tex_type = TextureType::_8888;
vjoyTexture->tcw.full = 0;
vjoyTexture->tsp.full = 0;
vjoyTexture->SetPhysicalDevice(GetContext()->GetPhysicalDevice());
vjoyTexture->SetDevice(GetContext()->GetDevice());
vjoyTexture->SetCommandBuffer(texCommandPool.Allocate());
vjoyTexture->UploadToGPU(OSD_TEX_W, OSD_TEX_H, image_data, false);
vjoyTexture->SetCommandBuffer(nullptr);
texCommandPool.EndFrame();
delete [] image_data;
osdPipeline.Init(&normalShaderManager, vjoyTexture->GetImageView(), GetContext()->GetRenderPass());
}
if (!osdBuffer)
{

View File

@ -46,27 +46,20 @@ public:
if (!vjoyTexture)
{
int w, h;
u8 *image_data = loadPNGData(get_readonly_data_path(DATA_PATH "buttons.png"), w, h);
if (image_data == nullptr)
{
WARN_LOG(RENDERER, "Cannot load buttons.png image");
}
else
{
texCommandPool.BeginFrame();
vjoyTexture = std::unique_ptr<Texture>(new Texture());
vjoyTexture->tex_type = TextureType::_8888;
vjoyTexture->tcw.full = 0;
vjoyTexture->tsp.full = 0;
vjoyTexture->SetPhysicalDevice(GetContext()->GetPhysicalDevice());
vjoyTexture->SetDevice(GetContext()->GetDevice());
vjoyTexture->SetCommandBuffer(texCommandPool.Allocate());
vjoyTexture->UploadToGPU(OSD_TEX_W, OSD_TEX_H, image_data, false);
vjoyTexture->SetCommandBuffer(nullptr);
texCommandPool.EndFrame();
delete [] image_data;
osdPipeline.Init(&shaderManager, vjoyTexture->GetImageView(), GetContext()->GetRenderPass());
}
u8 *image_data = loadOSDButtons(w, h);
texCommandPool.BeginFrame();
vjoyTexture = std::unique_ptr<Texture>(new Texture());
vjoyTexture->tex_type = TextureType::_8888;
vjoyTexture->tcw.full = 0;
vjoyTexture->tsp.full = 0;
vjoyTexture->SetPhysicalDevice(GetContext()->GetPhysicalDevice());
vjoyTexture->SetDevice(GetContext()->GetDevice());
vjoyTexture->SetCommandBuffer(texCommandPool.Allocate());
vjoyTexture->UploadToGPU(OSD_TEX_W, OSD_TEX_H, image_data, false);
vjoyTexture->SetCommandBuffer(nullptr);
texCommandPool.EndFrame();
delete [] image_data;
osdPipeline.Init(&shaderManager, vjoyTexture->GetImageView(), GetContext()->GetRenderPass());
}
if (!osdBuffer)
{

View File

@ -30,6 +30,8 @@ import com.reicast.emulator.emu.JNIdc;
import com.reicast.emulator.periph.InputDeviceManager;
import com.reicast.emulator.periph.SipEmulator;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@ -84,6 +86,7 @@ public abstract class BaseGLActivity extends Activity implements ActivityCompat.
return;
}
installButtons();
setStorageDirectories();
@ -127,7 +130,6 @@ public abstract class BaseGLActivity extends Activity implements ActivityCompat.
pathList.addAll(FileBrowser.getExternalMounts());
Log.i("flycast", "External storage dirs: " + pathList);
JNIdc.setExternalStorageDirectories(pathList.toArray());
FileBrowser.installButtons(prefs);
}
@Override
@ -298,6 +300,21 @@ public abstract class BaseGLActivity extends Activity implements ActivityCompat.
}
private void installButtons() {
try {
InputStream in = Emulator.getAppContext().getAssets().open("buttons.png");
if (in != null) {
byte[] buf = new byte[in.available()];
in.read(buf);
in.close();
JNIdc.setButtons(buf);
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
// Called from native code
protected void generateErrorLog() {
try {

View File

@ -8,7 +8,6 @@ import android.support.v7.app.AppCompatDelegate;
import android.util.Log;
import com.reicast.emulator.config.Config;
import com.reicast.emulator.emu.AudioBackend;
import com.reicast.emulator.emu.JNIdc;
public class Emulator extends Application {
@ -57,7 +56,6 @@ public class Emulator extends Application {
prefs.edit()
.putString(Config.pref_home, homeDirectory).apply();
FileBrowser.installButtons(prefs);
if (micPluggedIn() && currentActivity instanceof BaseGLActivity) {
((BaseGLActivity)currentActivity).requestRecordAudioPermission();
}

View File

@ -1,19 +1,8 @@
package com.reicast.emulator;
import android.content.SharedPreferences;
import android.os.Environment;
import com.reicast.emulator.config.Config;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashSet;
public class FileBrowser {
@ -56,40 +45,4 @@ public class FileBrowser {
}
return out;
}
public static void installButtons(SharedPreferences prefs) {
try {
File buttons = null;
// TODO button themes
//String theme = prefs.getString(Config.pref_theme, null);
//if (theme != null) {
// buttons = new File(theme);
//}
String home_directory = prefs.getString(Config.pref_home, Environment.getExternalStorageDirectory().getAbsolutePath());
File file = new File(home_directory, "data/buttons.png");
InputStream in = null;
if (buttons != null && buttons.exists()) {
in = new FileInputStream(buttons);
} else if (!file.exists() || file.length() == 0) {
in = Emulator.getAppContext().getAssets().open("buttons.png");
}
if (in != null) {
OutputStream out = new FileOutputStream(file);
// Transfer bytes from in to out
byte[] buf = new byte[4096];
int len;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
in.close();
out.flush();
out.close();
}
} catch (FileNotFoundException fnf) {
fnf.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}

View File

@ -1,6 +1,5 @@
package com.reicast.emulator.emu;
import android.util.Log;
import android.view.Surface;
import com.reicast.emulator.Emulator;
@ -43,4 +42,6 @@ public final class JNIdc
JNIdc.vjoy(14, 1, 0, 0, 0);
}
public static native void hideOsd();
public static native void setButtons(byte data[]);
}

View File

@ -23,6 +23,7 @@
#include "oslib/audiostream.h"
#include "imgread/common.h"
#include "rend/gui.h"
#include "rend/osd.h"
#include "cfg/cfg.h"
#include "log/LogManager.h"
#include "wsi/context.h"
@ -112,6 +113,7 @@ JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_screenDpi(JNIEnv *env
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_guiOpenSettings(JNIEnv *env,jobject obj) __attribute__((visibility("default")));
JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_guiIsOpen(JNIEnv *env,jobject obj) __attribute__((visibility("default")));
JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_guiIsContentBrowser(JNIEnv *env,jobject obj) __attribute__((visibility("default")));
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_setButtons(JNIEnv *env, jobject obj, jbyteArray data) __attribute__((visibility("default")));
JNIEXPORT void JNICALL Java_com_reicast_emulator_periph_InputDeviceManager_init(JNIEnv *env, jobject obj) __attribute__((visibility("default")));
JNIEXPORT void JNICALL Java_com_reicast_emulator_periph_InputDeviceManager_joystickAdded(JNIEnv *env, jobject obj, jint id, jstring name, jint maple_port, jstring junique_id) __attribute__((visibility("default")));
@ -656,3 +658,13 @@ void android_send_logs()
jmethodID generateErrorLogMID = env->GetMethodID(env->GetObjectClass(g_activity), "generateErrorLog", "()V");
env->CallVoidMethod(g_activity, generateErrorLogMID);
}
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_setButtons(JNIEnv *env, jobject obj, jbyteArray data)
{
u32 len = env->GetArrayLength(data);
DefaultOSDButtons.resize(len);
jboolean isCopy;
jbyte* b = env->GetByteArrayElements(data, &isCopy);
memcpy(DefaultOSDButtons.data(), b, len);
env->ReleaseByteArrayElements(data, b, JNI_ABORT);
}