mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Redo the DPI/Density code. It now makes sense.
This commit is contained in:
parent
1254fe414c
commit
5a6622eb37
9 changed files with 108 additions and 70 deletions
|
@ -21,6 +21,7 @@
|
|||
#include "input/input_state.h"
|
||||
#include "audio/mixer.h"
|
||||
#include "math/math_util.h"
|
||||
#include "net/resolve.h"
|
||||
#include "android/native_audio.h"
|
||||
|
||||
#define coord_xres 480
|
||||
|
@ -70,8 +71,8 @@ void LaunchEmail(const char *email_address) {
|
|||
// Remember that all of these need initialization on init! The process
|
||||
// may be reused when restarting the game. Globals are DANGEROUS.
|
||||
|
||||
float xscale = 1;
|
||||
float yscale = 1;
|
||||
float dp_xscale = 1;
|
||||
float dp_yscale = 1;
|
||||
|
||||
InputState input_state;
|
||||
|
||||
|
@ -104,24 +105,6 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init
|
|||
jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jinstallID, jboolean juseNativeAudio) {
|
||||
jniEnvUI = env;
|
||||
|
||||
pixel_xres = xxres;
|
||||
pixel_yres = yyres;
|
||||
|
||||
g_dpi = dpi;
|
||||
|
||||
// We default to 160 dpi and all our UI code is written to assume it. (DENSITY_MEDIUM).
|
||||
g_xres = xxres * 160 / dpi;
|
||||
g_yres = yyres * 160 / dpi;
|
||||
|
||||
use_native_audio = juseNativeAudio;
|
||||
if (g_xres < g_yres)
|
||||
{
|
||||
// Portrait - let's force the imaginary resolution we want
|
||||
g_xres = pixel_xres;
|
||||
g_yres = pixel_yres;
|
||||
}
|
||||
xscale = (float)g_xres / pixel_xres;
|
||||
yscale = (float)g_yres / pixel_yres;
|
||||
memset(&input_state, 0, sizeof(input_state));
|
||||
renderer_inited = false;
|
||||
first_lost = true;
|
||||
|
@ -141,10 +124,18 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init
|
|||
std::string app_nice_name;
|
||||
bool landscape;
|
||||
|
||||
net::Init();
|
||||
|
||||
g_dpi = dpi;
|
||||
pixel_xres = xxres;
|
||||
pixel_yres = yyres;
|
||||
|
||||
NativeGetAppInfo(&app_name, &app_nice_name, &landscape);
|
||||
|
||||
const char *argv[2] = {app_name.c_str(), 0};
|
||||
NativeInit(1, argv, user_data_path.c_str(), installID.c_str());
|
||||
|
||||
use_native_audio = juseNativeAudio;
|
||||
if (use_native_audio) {
|
||||
AndroidAudio_Init(&NativeMix, library_path);
|
||||
}
|
||||
|
@ -164,8 +155,7 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_pause(JNIEnv *, jclass)
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" void Java_com_turboviking_libnative_NativeApp_shutdown
|
||||
(JNIEnv *, jclass) {
|
||||
extern "C" void Java_com_turboviking_libnative_NativeApp_shutdown(JNIEnv *, jclass) {
|
||||
ILOG("NativeShutdown.");
|
||||
if (use_native_audio) {
|
||||
AndroidAudio_Shutdown();
|
||||
|
@ -177,26 +167,35 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_shutdown
|
|||
NativeShutdown();
|
||||
ILOG("VFSShutdown.");
|
||||
VFSShutdown();
|
||||
net::Shutdown();
|
||||
}
|
||||
|
||||
static jmethodID postCommand;
|
||||
|
||||
extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayInit(JNIEnv * env, jobject obj) {
|
||||
if (!renderer_inited) {
|
||||
ILOG("Calling NativeInitGraphics();");
|
||||
ILOG("Calling NativeInitGraphics(); dpi = %i", g_dpi);
|
||||
|
||||
// We default to 240 dpi and all UI code is written to assume it. (DENSITY_HIGH, like Nexus S).
|
||||
// Note that we don't compute dp_xscale and dp_yscale until later! This is so that NativeGetAppInfo
|
||||
// can change the dp resolution if it feels like it.
|
||||
dp_xres = pixel_xres * 240 / g_dpi;
|
||||
dp_yres = pixel_yres * 240 / g_dpi;
|
||||
|
||||
NativeInitGraphics();
|
||||
|
||||
dp_xscale = (float)dp_xres / pixel_xres;
|
||||
dp_yscale = (float)dp_yres / pixel_yres;
|
||||
} else {
|
||||
ILOG("Calling NativeDeviceLost();");
|
||||
}
|
||||
renderer_inited = true;
|
||||
jclass cls = env->GetObjectClass(obj);
|
||||
postCommand = env->GetMethodID(
|
||||
cls, "postCommand", "(Ljava/lang/String;Ljava/lang/String;)V");
|
||||
postCommand = env->GetMethodID(cls, "postCommand", "(Ljava/lang/String;Ljava/lang/String;)V");
|
||||
ILOG("MethodID: %i", (int)postCommand);
|
||||
}
|
||||
|
||||
extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayResize
|
||||
(JNIEnv *, jobject clazz, jint w, jint h) {
|
||||
extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayResize(JNIEnv *, jobject clazz, jint w, jint h) {
|
||||
ILOG("nativeResize (%i, %i), device lost!", w, h);
|
||||
if (first_lost) {
|
||||
first_lost = false;
|
||||
|
@ -205,8 +204,7 @@ extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayResize
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayRender
|
||||
(JNIEnv *env, jobject obj) {
|
||||
extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayRender(JNIEnv *env, jobject obj) {
|
||||
if (renderer_inited) {
|
||||
UpdateInputState(&input_state);
|
||||
NativeUpdate(input_state);
|
||||
|
@ -252,15 +250,20 @@ extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_touch
|
|||
ELOG("Too many pointers: %i", pointerId);
|
||||
return; // We ignore 8+ pointers entirely.
|
||||
}
|
||||
|
||||
input_state.mouse_x[pointerId] = (int)(x * xscale);
|
||||
input_state.mouse_y[pointerId] = (int)(y * yscale);
|
||||
float scaledX = (int)(x * dp_xscale); // why the (int) cast?
|
||||
float scaledY = (int)(y * dp_yscale);
|
||||
input_state.mouse_x[pointerId] = scaledX;
|
||||
input_state.mouse_y[pointerId] = scaledY;
|
||||
if (code == 1) {
|
||||
input_state.mouse_last[pointerId] = input_state.mouse_down[pointerId];
|
||||
input_state.mouse_down[pointerId] = true;
|
||||
NativeTouch(pointerId, scaledX, scaledY, 0, TOUCH_DOWN);
|
||||
} else if (code == 2) {
|
||||
input_state.mouse_last[pointerId] = input_state.mouse_down[pointerId];
|
||||
input_state.mouse_down[pointerId] = false;
|
||||
NativeTouch(pointerId, scaledX, scaledY, 0, TOUCH_UP);
|
||||
} else {
|
||||
NativeTouch(pointerId, scaledX, scaledY, 0, TOUCH_MOVE);
|
||||
}
|
||||
input_state.mouse_valid = true;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@ struct InputState;
|
|||
|
||||
// You must implement this. The first function to get called, just write strings to the two pointers.
|
||||
// This might get called multiple times in some implementations, you must be able to handle that.
|
||||
// The detected DP dimensions of the screen are set as dp_xres and dp_yres and you're free to change
|
||||
// them if you have a fixed-size app that needs to stretch a little to fit.
|
||||
void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, bool *landscape);
|
||||
|
||||
// For the back button to work right, this should return true on your main or title screen.
|
||||
|
@ -28,13 +30,25 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co
|
|||
void NativeInitGraphics();
|
||||
|
||||
// Signals that you need to recreate all buffered OpenGL resources,
|
||||
// like textures, vbo etc. Main thread.
|
||||
// like textures, vbo etc. Also, if you have modified dp_xres and dp_yres, you have to
|
||||
// do it again here. Main thread.
|
||||
void NativeDeviceLost();
|
||||
|
||||
// Called ~sixty times a second, delivers the current input state.
|
||||
// Main thread.
|
||||
void NativeUpdate(const InputState &input);
|
||||
|
||||
// Delivers touch events "instantly", without waiting for the next frame so that NativeUpdate can deliver.
|
||||
// Useful for triggering audio events, saving a few ms.
|
||||
// If you don't care about touch latency, just do a no-op implementation of this.
|
||||
// time is not yet implemented. finger can be from 0 to 7, inclusive.
|
||||
enum TouchEvent {
|
||||
TOUCH_DOWN,
|
||||
TOUCH_MOVE,
|
||||
TOUCH_UP,
|
||||
};
|
||||
void NativeTouch(int finger, float x, float y, double time, TouchEvent event);
|
||||
|
||||
// Called when it's time to render. If the device can keep up, this
|
||||
// will also be called sixty times per second. Main thread.
|
||||
void NativeRender();
|
||||
|
|
|
@ -119,35 +119,34 @@ extern void mixaudio(void *userdata, Uint8 *stream, int len) {
|
|||
#undef main
|
||||
#endif
|
||||
int main(int argc, char *argv[]) {
|
||||
/* // Xoom resolution. Other common tablet resolutions: 1024x600 , 1366x768
|
||||
g_xres = 1280;
|
||||
g_yres = 800;
|
||||
/* // Xoom/Nexus 7 resolution. Other common tablet resolutions: 1024x600 , 1366x768
|
||||
dp_xres = 1280;
|
||||
dp_yres = 800;
|
||||
|
||||
*/
|
||||
std::string app_name;
|
||||
std::string app_name_nice;
|
||||
bool landscape;
|
||||
NativeGetAppInfo(&app_name, &app_name_nice, &landscape);
|
||||
|
||||
float zoom = 1.0f;
|
||||
const char *zoomenv = getenv("ZOOM");
|
||||
if (zoomenv) {
|
||||
zoom = atof(zoomenv);
|
||||
}
|
||||
if (landscape) {
|
||||
|
||||
bool landscape;
|
||||
NativeGetAppInfo(&app_name, &app_name_nice, &landscape);
|
||||
|
||||
if (landscape) {
|
||||
pixel_xres = 800 * zoom;
|
||||
pixel_yres = 480 * zoom;
|
||||
} else {
|
||||
// PC development hack
|
||||
pixel_xres = 1580 * zoom;
|
||||
pixel_yres = 1000 * zoom;
|
||||
// PC development hack for more space
|
||||
//pixel_xres = 1580 * zoom;
|
||||
//pixel_yres = 1000 * zoom;
|
||||
pixel_xres = 480 * zoom;
|
||||
pixel_yres = 800 * zoom;
|
||||
}
|
||||
|
||||
float density = 1.0f;
|
||||
g_xres = (float)pixel_xres * density / zoom;
|
||||
g_yres = (float)pixel_yres * density / zoom;
|
||||
|
||||
printf("Pixels: %i x %i\n", pixel_xres, pixel_yres);
|
||||
printf("Virtual pixels: %i x %i\n", g_xres, g_yres);
|
||||
|
||||
net::Init();
|
||||
|
||||
|
@ -185,27 +184,35 @@ int main(int argc, char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\"));
|
||||
TCHAR path[MAX_PATH];
|
||||
SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path);
|
||||
PathAppend(path, (app_name + "\\").c_str());
|
||||
#else
|
||||
// Mac - what about linux? Also, ugly hardcoding.
|
||||
// Mac / Linux
|
||||
const char *path = getenv("HOME");
|
||||
if (!path) {
|
||||
struct passwd* pwd = getpwuid(getuid());
|
||||
if (pwd)
|
||||
path = pwd->pw_dir;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
NativeInit(argc, (const char **)argv, path, "BADCOFFEE");
|
||||
|
||||
float density = 1.0f;
|
||||
dp_xres = (float)pixel_xres * density / zoom;
|
||||
dp_yres = (float)pixel_yres * density / zoom;
|
||||
|
||||
NativeInitGraphics();
|
||||
|
||||
float dp_xscale = (float)dp_xres / pixel_xres;
|
||||
float dp_yscale = (float)dp_yres / pixel_yres;
|
||||
|
||||
printf("Pixels: %i x %i\n", pixel_xres, pixel_yres);
|
||||
printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres);
|
||||
|
||||
SDL_AudioSpec fmt;
|
||||
fmt.freq = 44100;
|
||||
fmt.format = AUDIO_S16;
|
||||
|
@ -225,44 +232,51 @@ int main(int argc, char *argv[]) {
|
|||
InputState input_state;
|
||||
int framecount = 0;
|
||||
bool nextFrameMD = 0;
|
||||
float t = 0;
|
||||
while (true) {
|
||||
SDL_Event event;
|
||||
|
||||
input_state.accelerometer_valid = false;
|
||||
input_state.mouse_valid = true;
|
||||
int done = 0;
|
||||
int quitRequested = 0;
|
||||
|
||||
// input_state.mouse_down[1] = nextFrameMD;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
float mx = event.motion.x * dp_xscale;
|
||||
float my = event.motion.y * dp_yscale;
|
||||
|
||||
if (event.type == SDL_QUIT) {
|
||||
done = 1;
|
||||
quitRequested = 1;
|
||||
} else if (event.type == SDL_KEYDOWN) {
|
||||
if (event.key.keysym.sym == SDLK_ESCAPE) {
|
||||
done = 1;
|
||||
quitRequested = 1;
|
||||
}
|
||||
} else if (event.type == SDL_MOUSEMOTION) {
|
||||
input_state.mouse_x[0] = event.motion.x * density / zoom;
|
||||
input_state.mouse_y[0] = event.motion.y * density / zoom;
|
||||
input_state.mouse_x[0] = mx;
|
||||
input_state.mouse_y[0] = my;
|
||||
NativeTouch(0, mx, my, 0, TOUCH_MOVE);
|
||||
} else if (event.type == SDL_MOUSEBUTTONDOWN) {
|
||||
if (event.button.button == SDL_BUTTON_LEFT) {
|
||||
//input_state.mouse_buttons_down = 1;
|
||||
input_state.mouse_down[0] = true;
|
||||
nextFrameMD = true;
|
||||
NativeTouch(0, mx, my, 0, TOUCH_DOWN);
|
||||
}
|
||||
} else if (event.type == SDL_MOUSEBUTTONUP) {
|
||||
if (event.button.button == SDL_BUTTON_LEFT) {
|
||||
input_state.mouse_down[0] = false;
|
||||
nextFrameMD = false;
|
||||
//input_state.mouse_buttons_up = 1;
|
||||
NativeTouch(0, mx, my, 0, TOUCH_UP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (done)
|
||||
if (quitRequested)
|
||||
break;
|
||||
|
||||
input_state.mouse_last[0] = input_state.mouse_down[0];
|
||||
uint8 *keys = (uint8 *)SDL_GetKeyState(NULL);
|
||||
const uint8 *keys = (const uint8 *)SDL_GetKeyState(NULL);
|
||||
if (keys[SDLK_ESCAPE])
|
||||
break;
|
||||
SimulateGamepad(keys, &input_state);
|
||||
|
@ -270,14 +284,13 @@ int main(int argc, char *argv[]) {
|
|||
NativeUpdate(input_state);
|
||||
NativeRender();
|
||||
if (framecount % 60 == 0) {
|
||||
// glsl_refresh(); // auto-reloads modified GLSL shaders once per second.
|
||||
// glsl_refresh(); // auto-reloads modified GLSL shaders once per second.
|
||||
}
|
||||
|
||||
SDL_GL_SwapBuffers();
|
||||
|
||||
// Simple framerate limiting
|
||||
static float t=0;
|
||||
while (time_now() < t+1.0f/60.0f) {
|
||||
while (time_now() < t + 1.0f/60.0f) {
|
||||
sleep_ms(0);
|
||||
time_update();
|
||||
}
|
||||
|
@ -293,5 +306,6 @@ int main(int argc, char *argv[]) {
|
|||
NativeShutdown();
|
||||
SDL_CloseAudio();
|
||||
SDL_Quit();
|
||||
net::Shutdown();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "base/display.h"
|
||||
|
||||
int g_xres;
|
||||
int g_yres;
|
||||
int dp_xres;
|
||||
int dp_yres;
|
||||
int pixel_xres;
|
||||
int pixel_yres;
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
// This is meant to be a framework for handling DPI scaling etc.
|
||||
// For now, it just consists of these two ugly globals.
|
||||
|
||||
extern int g_xres;
|
||||
extern int g_yres;
|
||||
extern int dp_xres;
|
||||
extern int dp_yres;
|
||||
extern int pixel_xres;
|
||||
extern int pixel_yres;
|
||||
|
||||
|
|
|
@ -359,7 +359,7 @@ void DrawBuffer::EnableBlend(bool enable) {
|
|||
void DrawBuffer::SetClipRect(float x, float y, float w, float h)
|
||||
{
|
||||
// Sigh, OpenGL is upside down.
|
||||
glScissor(x, g_yres - y, w, h);
|
||||
glScissor(x, dp_yres - y, w, h);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ bool Connection::Resolve(const char *host, int port) {
|
|||
CHECK_GE(tmpres, 0); // << "inet_pton failed";
|
||||
CHECK_NE(0, tmpres); // << ip << " not a valid IP address";
|
||||
remote_.sin_port = htons(port);
|
||||
free((void *)ip);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -53,7 +54,6 @@ void Connection::Connect() {
|
|||
CHECK_GE(port_, 0);
|
||||
sock_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
CHECK_GE(sock_, 0);
|
||||
//VLOG(1) << "Connecting to " << host_ << ":" << port_;
|
||||
|
||||
// poll once per second.. should find a way to do this blocking.
|
||||
int retval = -1;
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
namespace net {
|
||||
|
||||
|
||||
void Init()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
@ -25,6 +24,13 @@ void Init()
|
|||
#endif
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
char *DNSResolve(const char *host)
|
||||
{
|
||||
struct hostent *hent;
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
|
||||
namespace net {
|
||||
|
||||
// Required on Win32
|
||||
// Strictly only required on Win32, but all platforms should call it.
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
// use free() to free the returned string.
|
||||
char *DNSResolve(const char *host);
|
||||
|
|
Loading…
Add table
Reference in a new issue