First cut at allowing portrait mode (on mobile devices)

This commit is contained in:
Aaron Culliney 2016-02-07 13:12:59 -08:00
parent 70afe71c82
commit 5354b0cfd5
14 changed files with 242 additions and 99 deletions

View File

@ -66,6 +66,7 @@
#include <sys/stat.h>
#include "misc.h"
#include "json_parse.h"
#include "vm.h"
#include "timing.h"
#include "cpu.h"

View File

@ -1180,8 +1180,8 @@ void video_shutdown(bool emulatorShuttingDown) {
render_thread_id = 0;
}
void video_reshape(int w, int h) {
video_backend->reshape(w, h);
void video_reshape(int w, int h, bool landscape) {
video_backend->reshape(w, h, landscape);
}
void video_render(void) {

View File

@ -71,7 +71,7 @@ void _video_setRenderThread(pthread_t id);
/*
* Reshape the display to particular dimensions.
*/
void video_reshape(int w, int h);
void video_reshape(int w, int h, bool landscape);
/*
* Setup the display. This may be called multiple times in a run, and is

View File

@ -22,6 +22,7 @@ bool (*interface_isTouchMenuAvailable)(void) = NULL;
void (*interface_setTouchMenuEnabled)(bool enabled) = NULL;
void (*interface_setTouchMenuVisibility)(float inactiveAlpha, float activeAlpha) = NULL;
void (*interface_setGlyphScale)(int glyphScale) = NULL;
void (*(*interface_getModelDataSetter)(interface_device_t device))(const char *jsonData) = NULL;
#endif
// 2015/04/12 : This was legacy code for rendering the menu interfaces on desktop Linux. Portions here are resurrected

View File

@ -46,9 +46,13 @@ void interface_plotMessage(uint8_t *fb, interface_colorscheme_t cs, char *messag
#if INTERFACE_TOUCH
typedef enum interface_device_t {
TOUCH_DEVICE_NONE = 0,
TOUCH_DEVICE_FRAMEBUFFER = 0,
TOUCH_DEVICE_JOYSTICK,
TOUCH_DEVICE_JOYSTICK_KEYPAD,
TOUCH_DEVICE_KEYBOARD,
TOUCH_DEVICE_TOPMENU,
TOUCH_DEVICE_ALERT,
// ...
TOUCH_DEVICE_DEVICE_MAX,
} interface_device_t;
@ -90,6 +94,9 @@ extern void (*interface_setTouchMenuVisibility)(float inactiveAlpha, float activ
// set a finer-grained font size (if glyphScale > 1)
extern void (*interface_setGlyphScale)(int glyphScale);
// get model-specific functions
extern void (*(*interface_getModelDataSetter)(interface_device_t device))(const char *jsonData);
#endif
#define EXT_GZ ".gz"

View File

@ -14,6 +14,9 @@
#define MODEL_DEPTH -0.0625
#define ALERT_MODEL_W 0.7
#define ALERT_MODEL_H 0.7
static bool isEnabled = true;
static pthread_mutex_t messageMutex = PTHREAD_MUTEX_INITIALIZER;
static char *nextMessage = NULL;
@ -21,6 +24,7 @@ static unsigned int nextMessageCols = 0;
static unsigned int nextMessageRows = 0;
static struct timespec messageTimingBegin = { 0 };
static GLModel *messageModel = NULL;
static GLfloat landscapeScale = 1.f;
// ----------------------------------------------------------------------------
@ -58,12 +62,13 @@ static void _alertToModel(char *message, unsigned int messageCols, unsigned int
const unsigned int fbWidth = (messageCols * FONT80_WIDTH_PIXELS);
const unsigned int fbHeight = (messageRows * FONT_HEIGHT_PIXELS);
GLfloat modelHeight = (ALERT_MODEL_H * landscapeScale);
messageModel = mdlCreateQuad((GLModelParams_s){
.skew_x = -0.3,
.skew_y = -0.3,
.skew_x = -1.0 + ALERT_MODEL_W,
.skew_y = 1.0 - modelHeight,
.z = MODEL_DEPTH,
.obj_w = 0.7,
.obj_h = 0.7,
.obj_w = ALERT_MODEL_W,
.obj_h = (ALERT_MODEL_H * landscapeScale),
.positionUsageHint = GL_STATIC_DRAW, // positions don't change
.tex_w = fbWidth,
.tex_h = fbHeight,
@ -196,8 +201,9 @@ static void alert_render(void) {
glhud_renderDefault(messageModel);
}
static void alert_reshape(int w, int h) {
// no-op
static void alert_reshape(int w, int h, bool landscape) {
swizzleDimensions(&w, &h, landscape);
landscapeScale = landscape ? 1.f : ((GLfloat)w/h);
}
#if INTERFACE_TOUCH
@ -380,7 +386,9 @@ static void _init_glalert(void) {
.render = &alert_render,
.reshape = &alert_reshape,
#if INTERFACE_TOUCH
.type = TOUCH_DEVICE_ALERT,
.onTouchEvent = &alert_onTouchEvent,
.setData = NULL,
#endif
});
}

View File

@ -116,7 +116,7 @@ static void _glnode_initGLUTPre(void) {
}
static void _glnode_reshapeGLUT(int w, int h) {
video_reshape(w, h);
video_reshape(w, h, /*landscape:*/true);
}
static void _glnode_initGLUTPost(void) {
@ -202,10 +202,10 @@ static void glnode_renderNodes(void) {
#endif
}
static void glnode_reshapeNodes(int w, int h) {
static void glnode_reshapeNodes(int w, int h, bool landscape) {
glnode_array_node_s *p = head;
while (p) {
p->node.reshape(w, h);
p->node.reshape(w, h, landscape);
p = p->next;
}
}
@ -224,6 +224,17 @@ static int64_t glnode_onTouchEvent(interface_touch_event_t action, int pointer_c
}
return flags;
}
void (*glnode_getModelDataSetter(interface_device_t type))(const char *jsonData) {
glnode_array_node_s *p = head;
while (p) {
if (p->node.type == type) {
return p->node.setData;
}
p = p->next;
}
return NULL;
}
#endif
static void glnode_mainLoop(void) {
@ -256,5 +267,6 @@ static void _init_glnode_manager(void) {
#if INTERFACE_TOUCH
interface_onTouchEvent = &glnode_onTouchEvent;
interface_getModelDataSetter = &glnode_getModelDataSetter;
#endif
}

View File

@ -21,6 +21,9 @@
// TODO: implement 3D CRT object, possibly with perspective drawing?
#define PERSPECTIVE 0
#define PREF_PORTRAIT_HEIGHT_SCALE "portraitHeightScale"
#define PREF_PORTRAIT_POSITION_SCALE "portraitPositionScale"
enum {
TEXTURE_ID_FRAMEBUFFER=0,
TEXTURE_ID_MESSAGE,
@ -97,14 +100,25 @@ typedef struct GLNode {
void (*setup)(void);
void (*shutdown)(void);
void (*render)(void);
void (*reshape)(int w, int h, bool landscape);
#if INTERFACE_TOUCH
interface_device_t type;
int64_t (*onTouchEvent)(interface_touch_event_t action, int pointer_count, int pointer_idx, float *x_coords, float *y_coords);
void (*setData)(const char *jsonData);
#endif
void (*reshape)(int w, int h);
} GLNode;
// registers a node with manager
void glnode_registerNode(glnode_render_order_t order, GLNode node);
// swizzle width/height if they don't match landscape/portrait
static void inline swizzleDimensions(int *w, int *h, bool landscape) {
if ( (landscape && (*w < *h)) || (!landscape && (*w > *h)) ) {
int x = *w;
*w = *h;
*h = x;
}
}
#endif // whole file

View File

@ -68,6 +68,9 @@ static struct {
int buttonY;
int buttonYMax;
// Are we in landscape mode
bool landscape;
// TODO FIXME : support 2-players!
} touchport = { 0 };
@ -543,41 +546,29 @@ static void gltouchjoy_render(void) {
}
}
static void gltouchjoy_reshape(int w, int h) {
LOG("gltouchjoy_reshape(%d, %d)", w, h);
static void gltouchjoy_reshape(int w, int h, bool landscape) {
LOG("w:%d h:%d landscape:%d", w, h, landscape);
touchport.landscape = landscape;
swizzleDimensions(&w, &h, landscape);
touchport.width = w;
touchport.height = h;
touchport.axisY = 0;
touchport.axisYMax = h;
touchport.buttonY = 0;
touchport.buttonYMax = h;
if (joyglobals.axisIsOnLeft) {
touchport.axisX = 0;
touchport.axisY = 0;
touchport.buttonY = 0;
if (w >= touchport.width) {
touchport.width = w;
touchport.axisXMax = (w * joyglobals.screenDivider);
touchport.buttonX = (w * joyglobals.screenDivider);
touchport.buttonXMax = w;
}
if (h >= touchport.height) {
touchport.height = h;
touchport.axisYMax = h;
touchport.buttonYMax = h;
}
touchport.axisXMax = (w * joyglobals.screenDivider);
touchport.buttonX = (w * joyglobals.screenDivider);
touchport.buttonXMax = w;
} else {
touchport.buttonX = 0;
touchport.buttonY = 0;
touchport.axisY = 0;
if (w >= touchport.width) {
touchport.width = w;
touchport.buttonXMax = (w * joyglobals.screenDivider);
touchport.axisX = (w * joyglobals.screenDivider);
touchport.axisXMax = w;
}
if (h >= touchport.height) {
touchport.height = h;
touchport.buttonYMax = h;
touchport.axisYMax = h;
}
touchport.buttonXMax = (w * joyglobals.screenDivider);
touchport.axisX = (w * joyglobals.screenDivider);
touchport.axisXMax = w;
}
}
@ -941,22 +932,20 @@ static void gltouchjoy_setTouchAxisTypes(uint8_t rosetteChars[(ROSETTE_ROWS * RO
static void gltouchjoy_setScreenDivision(float screenDivider) {
joyglobals.screenDivider = screenDivider;
// force reshape here to apply changes ...
gltouchjoy_reshape(touchport.width, touchport.height);
gltouchjoy_reshape(touchport.width, touchport.height, touchport.landscape);
}
static void gltouchjoy_setAxisOnLeft(bool axisIsOnLeft) {
joyglobals.axisIsOnLeft = axisIsOnLeft;
// force reshape here to apply changes ...
gltouchjoy_reshape(touchport.width, touchport.height);
gltouchjoy_reshape(touchport.width, touchport.height, touchport.landscape);
}
static void gltouchjoy_beginCalibration(void) {
video_clear();
joyglobals.isCalibrating = true;
}
static void gltouchjoy_endCalibration(void) {
video_redraw();
joyglobals.isCalibrating = false;
}
@ -1039,11 +1028,13 @@ static void _init_gltouchjoy(void) {
joydriver_isCalibrating = &gltouchjoy_isCalibrating;
glnode_registerNode(RENDER_LOW, (GLNode){
.type = TOUCH_DEVICE_JOYSTICK,
.setup = &gltouchjoy_setup,
.shutdown = &gltouchjoy_shutdown,
.render = &gltouchjoy_render,
.reshape = &gltouchjoy_reshape,
.onTouchEvent = &gltouchjoy_onTouchEvent,
.setData = NULL,
});
}

View File

@ -11,7 +11,6 @@
#include "video/glhudmodel.h"
#include "video/glnode.h"
#include "json_parse.h"
#if !INTERFACE_TOUCH
#error this is a touch interface module, possibly you mean to not compile this at all?
@ -26,7 +25,7 @@
#define MODEL_DEPTH -1/32.f
#define KBD_TEMPLATE_COLS 10
#define KBD_TEMPLATE_COLS 10 // 10 cols for a mobile keyboard in portrait seems to be a defacto standard across iOS/Android ...
#define KBD_TEMPLATE_ROWS 8
#define DEFAULT_CTRL_COL 2
@ -38,8 +37,8 @@
#define KBD_FB_WIDTH (KBD_TEMPLATE_COLS * FONT80_WIDTH_PIXELS) // 10 * 7 == 70
#define KBD_FB_HEIGHT (KBD_TEMPLATE_ROWS * FONT_HEIGHT_PIXELS) // 8 * 16 == 128
#define KBD_OBJ_W 2.0
#define KBD_OBJ_H 2.0
#define KBD_OBJ_W GL_MODEL_MAX // model width fits screen
#define KBD_OBJ_H_LANDSCAPE GL_MODEL_MAX
static bool isAvailable = false; // Were there any OpenGL/memory errors on gltouchkbd initialization?
static bool isEnabled = true; // Does player want touchkbd enabled?
@ -108,6 +107,11 @@ static struct {
int kbdW;
int kbdH;
// raw device dimensions
int rawWidth;
int rawHeight;
int isLandscape;
} touchport = { 0 };
// keyboard variables
@ -115,6 +119,10 @@ static struct {
static struct {
GLModel *model;
GLfloat modelHeight;
GLfloat modelSkewY;
bool modelDirty;
int selectedCol;
int selectedRow;
@ -124,6 +132,8 @@ static struct {
bool ctrlPressed;
unsigned int glyphMultiplier;
float portraitHeightScale;
float portraitPositionScale;
struct timespec timingBegin;
@ -176,6 +186,29 @@ static void _rerender_character(int col, int row) {
kbd.model->texDirty = true;
}
// non-destructively adjust model height/position
static void _reset_model(void) {
/* 2...3
* .
* .
* .
* 0...1
*/
const GLfloat skew_x = -GL_MODEL_HALF;
const GLfloat skew_y = kbd.modelSkewY;
const GLfloat obj_w = KBD_OBJ_W;
const GLfloat obj_h = kbd.modelHeight;
GLfloat *quad = (GLfloat *)(kbd.model->positions);
quad[0 +0] = skew_x; quad[0 +1] = skew_y;
quad[4 +0] = skew_x+obj_w; quad[4 +1] = skew_y;
quad[8 +0] = skew_x; quad[8 +1] = skew_y+obj_h;
quad[12+0] = skew_x+obj_w; quad[12+1] = skew_y+obj_h;
kbd.modelDirty = true;
}
static inline void _rerender_selected(int col, int row) {
if ((col >= 0) && (row >= 0)) {
_rerender_character(col, row);
@ -481,12 +514,12 @@ static void gltouchkbd_setup(void) {
gltouchkbd_shutdown();
kbd.model = mdlCreateQuad((GLModelParams_s){
.skew_x = -1.0,
.skew_y = -1.0,
.skew_x = -GL_MODEL_HALF,
.skew_y = kbd.modelSkewY,
.z = MODEL_DEPTH,
.obj_w = KBD_OBJ_W,
.obj_h = KBD_OBJ_H,
.positionUsageHint = GL_STATIC_DRAW, // positions don't change
.obj_h = kbd.modelHeight,
.positionUsageHint = GL_DYNAMIC_DRAW, // positions might change
.tex_w = KBD_FB_WIDTH * kbd.glyphMultiplier,
.tex_h = KBD_FB_HEIGHT * kbd.glyphMultiplier,
.texcoordUsageHint = GL_DYNAMIC_DRAW, // but key texture does
@ -546,28 +579,64 @@ static void gltouchkbd_render(void) {
_HACKAROUND_GLTEXIMAGE2D_PRE(TEXTURE_ACTIVE_TOUCHKBD, kbd.model->textureName);
glTexImage2D(GL_TEXTURE_2D, /*level*/0, TEX_FORMAT_INTERNAL, kbd.model->texWidth, kbd.model->texHeight, /*border*/0, TEX_FORMAT, TEX_TYPE, kbd.model->texPixels);
}
if (kbd.modelDirty) {
kbd.modelDirty = false;
glBindBuffer(GL_ARRAY_BUFFER, kbd.model->posBufferName);
glBufferData(GL_ARRAY_BUFFER, kbd.model->positionArraySize, kbd.model->positions, GL_DYNAMIC_DRAW);
}
glUniform1i(texSamplerLoc, TEXTURE_ID_TOUCHKBD);
glhud_renderDefault(kbd.model);
}
}
static void gltouchkbd_reshape(int w, int h) {
LOG("gltouchkbd_reshape(%d, %d)", w, h);
static void gltouchkbd_reshape(int w, int h, bool landscape) {
LOG("w:%d h:%d landscape:%d", w, h, landscape);
touchport.rawWidth = w;
touchport.rawHeight = h;
touchport.isLandscape = landscape;
touchport.kbdX = 0;
if (w > touchport.width) {
touchport.width = w;
touchport.kbdXMax = w * (KBD_OBJ_W/2.f);
}
if (h > touchport.height) {
touchport.height = h;
touchport.kbdY = h * (1.f - (KBD_OBJ_H/2.f));
touchport.kbdYMax = h;
}
swizzleDimensions(&w, &h, landscape);
touchport.width = w;
touchport.height = h;
kbd.modelHeight = landscape ? KBD_OBJ_H_LANDSCAPE : (GL_MODEL_MAX * kbd.portraitHeightScale);
kbd.modelSkewY = -GL_MODEL_HALF + ((GL_MODEL_MAX - kbd.modelHeight) * kbd.portraitPositionScale);
touchport.kbdXMax = w * (KBD_OBJ_W/GL_MODEL_MAX);
touchport.kbdY = h * (GL_MODEL_HALF - (kbd.modelHeight/GL_MODEL_MAX));
touchport.kbdY = h * ((GL_MODEL_MAX - (kbd.modelSkewY + GL_MODEL_HALF + kbd.modelHeight)) / GL_MODEL_MAX);
touchport.kbdYMax = h * ((GL_MODEL_MAX - (kbd.modelSkewY + GL_MODEL_HALF)) / GL_MODEL_MAX);
LOG("modelHeight:%f modelSkewY:%f kbdY:%d kbdYMax:%d", kbd.modelHeight, kbd.modelSkewY, touchport.kbdY, touchport.kbdYMax);
touchport.kbdW = touchport.kbdXMax - touchport.kbdX;
touchport.kbdH = touchport.kbdYMax - touchport.kbdY;
if (kbd.model) {
_reset_model();
}
}
static void gltouchkbd_setData(const char *jsonData) {
JSON_s parsedData = { 0 };
int tokCount = json_createFromString(jsonData, &parsedData);
do {
if (tokCount < 0) {
break;
}
json_mapParseFloatValue(&parsedData, PREF_PORTRAIT_HEIGHT_SCALE, &kbd.portraitHeightScale);
json_mapParseFloatValue(&parsedData, PREF_PORTRAIT_POSITION_SCALE, &kbd.portraitPositionScale);
gltouchkbd_reshape(touchport.rawWidth, touchport.rawHeight, touchport.isLandscape);
} while (0);
json_destroy(&parsedData);
}
static int64_t gltouchkbd_onTouchEvent(interface_touch_event_t action, int pointer_count, int pointer_idx, float *x_coords, float *y_coords) {
@ -698,12 +767,10 @@ static void gltouchkbd_setLowercaseEnabled(bool enabled) {
}
static void gltouchkbd_beginCalibration(void) {
video_clear();
isCalibrating = true;
}
static void gltouchkbd_endCalibration(void) {
video_redraw();
isCalibrating = false;
}
@ -991,6 +1058,9 @@ static void _init_gltouchkbd(void) {
keydriver_loadAltKbd = &gltouchkbd_loadAltKbd;
keydriver_setGlyphScale = &gltouchkbd_setGlyphScale;
kbd.portraitHeightScale = 0.5f;
kbd.portraitPositionScale = 0.f;
kbd.selectedCol = -1;
kbd.selectedRow = -1;
@ -1000,11 +1070,13 @@ static void _init_gltouchkbd(void) {
kbd.glyphMultiplier = 1;
glnode_registerNode(RENDER_LOW, (GLNode){
.type = TOUCH_DEVICE_KEYBOARD,
.setup = &gltouchkbd_setup,
.shutdown = &gltouchkbd_shutdown,
.render = &gltouchkbd_render,
.reshape = &gltouchkbd_reshape,
.onTouchEvent = &gltouchkbd_onTouchEvent,
.setData = &gltouchkbd_setData,
});
}

View File

@ -25,7 +25,8 @@
#define MENU_FB_HEIGHT (MENU_TEMPLATE_ROWS * FONT_HEIGHT_PIXELS)
#define MENU_OBJ_W 2.0
#define MENU_OBJ_H 0.5 // NOTE : intent is to complement touch keyboard height
#define MENU_OBJ_H_LANDSCAPE (2.0/4.0) // NOTE : intent is to match touch keyboard height in landscape mode
#define MENU_OBJ_H_PORTRAIT (1.0/4.0)
static bool isAvailable = false; // Were there any OpenGL/memory errors on initialization?
static bool isEnabled = true; // Does player want this enabled?
@ -58,6 +59,7 @@ static struct {
int topRightYHalf;
int topRightYMax;
GLfloat modelHeight;
} touchport = { 0 };
// touch menu variables
@ -360,10 +362,10 @@ static void gltouchmenu_setup(void) {
menu.model = mdlCreateQuad((GLModelParams_s){
.skew_x = -1.0,
.skew_y = 1.0-MENU_OBJ_H,
.skew_y = 1.0-touchport.modelHeight,
.z = MODEL_DEPTH,
.obj_w = MENU_OBJ_W,
.obj_h = MENU_OBJ_H,
.obj_h = touchport.modelHeight,
.positionUsageHint = GL_STATIC_DRAW, // positions don't change
.tex_w = MENU_FB_WIDTH * menu.glyphMultiplier,
.tex_h = MENU_FB_HEIGHT * menu.glyphMultiplier,
@ -428,30 +430,31 @@ static void gltouchmenu_render(void) {
GL_ERRLOG("gltouchmenu_render");
}
static void gltouchmenu_reshape(int w, int h) {
LOG("gltouchmenu_reshape(%d, %d)", w, h);
static void gltouchmenu_reshape(int w, int h, bool landscape) {
LOG("w:%d h:%d landscape:%d", w, h, landscape);
touchport.topLeftX = 0;
touchport.topLeftY = 0;
touchport.topRightY = 0;
if (w > touchport.width) {
touchport.width = w;
const unsigned int keyW = touchport.width / MENU_TEMPLATE_COLS;
touchport.topLeftXHalf = keyW;
touchport.topLeftXMax = keyW*2;
touchport.topRightX = w - (keyW*2);
touchport.topRightXHalf = w - keyW;
touchport.topRightXMax = w;
}
if (h > touchport.height) {
touchport.height = h;
const unsigned int menuH = h * (MENU_OBJ_H/2.0);
touchport.topLeftYHalf = menuH/2;
touchport.topLeftYMax = menuH;
touchport.topRightYHalf = menuH/2;
touchport.topRightYMax = menuH;
}
swizzleDimensions(&w, &h, landscape);
touchport.width = w;
touchport.height = h;
touchport.modelHeight = landscape ? MENU_OBJ_H_LANDSCAPE : MENU_OBJ_H_PORTRAIT;;
const unsigned int keyW = touchport.width / MENU_TEMPLATE_COLS;
touchport.topLeftXHalf = keyW;
touchport.topLeftXMax = keyW*2;
touchport.topRightX = w - (keyW*2);
touchport.topRightXHalf = w - keyW;
touchport.topRightXMax = w;
const unsigned int menuH = h * (touchport.modelHeight/2.0);
touchport.topLeftYHalf = menuH/2;
touchport.topLeftYMax = menuH;
touchport.topRightYHalf = menuH/2;
touchport.topRightYMax = menuH;
}
static int64_t gltouchmenu_onTouchEvent(interface_touch_event_t action, int pointer_count, int pointer_idx, float *x_coords, float *y_coords) {
@ -565,11 +568,13 @@ static void _init_gltouchmenu(void) {
menu.maxAlpha = 1.f;
glnode_registerNode(RENDER_TOP, (GLNode){
.type = TOUCH_DEVICE_TOPMENU,
.setup = &gltouchmenu_setup,
.shutdown = &gltouchmenu_shutdown,
.render = &gltouchmenu_render,
.reshape = &gltouchmenu_reshape,
.onTouchEvent = &gltouchmenu_onTouchEvent,
.setData = NULL,
});
}

View File

@ -20,6 +20,11 @@ static int viewportY = 0;
static int viewportWidth = SCANWIDTH*1.5;
static int viewportHeight = SCANHEIGHT*1.5;
static int rawWidth = SCANWIDTH*1.5;
static int rawHeight = SCANHEIGHT*1.5;
static bool isLandscape = true;
static float portraitPositionScale = 3/4.f;
GLint texSamplerLoc = UNINITIALIZED_GL;
GLint alphaValue = UNINITIALIZED_GL;
GLuint mainShaderProgram = UNINITIALIZED_GL;
@ -155,8 +160,8 @@ static void glvideo_init(void) {
.skew_x = -1.0, // model space coords
.skew_y = -1.0,
.z = 0.0,
.obj_w = 2.0, // entire model space (-1.0 to 1.0)
.obj_h = 2.0,
.obj_w = GL_MODEL_MAX, // entire model space (-1.0 to 1.0)
.obj_h = GL_MODEL_MAX,
.positionUsageHint = GL_STATIC_DRAW, // positions don't change
.tex_w = SCANWIDTH,
.tex_h = SCANHEIGHT,
@ -277,9 +282,7 @@ static void glvideo_render(void) {
}
glClear(GL_COLOR_BUFFER_BIT);
#if MOBILE_DEVICE
glViewport(viewportX, viewportY, viewportWidth, viewportHeight);
#endif
#if PERSPECTIVE
// Calculate modelview and projection matrices
@ -379,8 +382,14 @@ static void glvideo_render(void) {
GL_ERRLOG("glvideo_render");
}
static void glvideo_reshape(int w, int h) {
//LOG("reshape to w:%d h:%d", w, h);
static void glvideo_reshape(int w, int h, bool landscape) {
LOG("w:%d h:%d landscape:%d", w, h, landscape);
rawWidth = w;
rawHeight = h;
isLandscape = landscape;
swizzleDimensions(&w, &h, landscape);
int w2 = ((float)h * (SCANWIDTH/(float)SCANHEIGHT));
int h2 = ((float)w / (SCANWIDTH/(float)SCANHEIGHT));
@ -397,6 +406,9 @@ static void glvideo_reshape(int w, int h) {
viewportY = (h-h2)/2;
viewportWidth = w;
viewportHeight = h2;
if (!isLandscape) {
viewportY = (h-h2) * portraitPositionScale;
}
//LOG("OK2 : x:%d,y:%d w:%d,h:%d", viewportX, viewportY, viewportWidth, viewportHeight);
} else {
viewportX = 0;
@ -405,11 +417,26 @@ static void glvideo_reshape(int w, int h) {
viewportHeight = h;
//LOG("small viewport : x:%d,y:%d w:%d,h:%d", viewportX, viewportY, viewportWidth, viewportHeight);
}
glViewport(viewportX, viewportY, viewportWidth, viewportHeight);
}
#if INTERFACE_TOUCH
static void glvideo_setData(const char *jsonData) {
JSON_s parsedData = { 0 };
int tokCount = json_createFromString(jsonData, &parsedData);
do {
if (tokCount < 0) {
break;
}
json_mapParseFloatValue(&parsedData, PREF_PORTRAIT_POSITION_SCALE, &portraitPositionScale);
glvideo_reshape(rawWidth, rawHeight, isLandscape);
} while (0);
json_destroy(&parsedData);
}
static int64_t glvideo_onTouchEvent(interface_touch_event_t action, int pointer_count, int pointer_idx, float *x_coords, float *y_coords) {
// no-op
return 0x0;
@ -428,7 +455,9 @@ static void _init_glvideo(void) {
.render = &glvideo_render,
.reshape = &glvideo_reshape,
#if INTERFACE_TOUCH
.type = TOUCH_DEVICE_FRAMEBUFFER,
.onTouchEvent = &glvideo_onTouchEvent,
.setData = &glvideo_setData,
#endif
});
}

View File

@ -19,7 +19,7 @@
typedef struct video_backend_s {
void (*init)(void *context);
void (*main_loop)(void);
void (*reshape)(int width, int height);
void (*reshape)(int width, int height, bool landscape);
void (*render)(void);
void (*shutdown)(bool emulatorShuttingDown);
} video_backend_s;

View File

@ -16,6 +16,9 @@
#include "common.h"
#define GL_MODEL_MAX 2.0 // entire model space (-1.0 to 1.0)
#define GL_MODEL_HALF 1.0
enum {
POS_ATTRIB_IDX,
TEXCOORD_ATTRIB_IDX,