2012-06-19 19:01:34 +00:00
|
|
|
/* RetroArch - A frontend for libretro.
|
2014-01-01 00:50:59 +00:00
|
|
|
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
2015-01-07 17:06:50 +00:00
|
|
|
* Copyright (C) 2012-2015 - Michael Lelli
|
2012-09-18 23:41:58 +00:00
|
|
|
*
|
2012-06-19 19:01:34 +00:00
|
|
|
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
|
|
|
* of the GNU General Public License as published by the Free Software Found-
|
|
|
|
* ation, either version 3 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE. See the GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along with RetroArch.
|
|
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
#include <VG/openvg.h>
|
2012-10-18 22:59:56 +00:00
|
|
|
#include <VG/vgext.h>
|
2012-06-19 19:01:34 +00:00
|
|
|
#include <EGL/egl.h>
|
2012-10-18 22:59:56 +00:00
|
|
|
#include <EGL/eglext.h>
|
2015-01-12 20:53:04 +00:00
|
|
|
#include "../video_context_driver.h"
|
2014-10-23 05:46:02 +00:00
|
|
|
#include <gfx/math/matrix_3x3.h>
|
2015-03-15 03:37:54 +00:00
|
|
|
#include <retro_inline.h>
|
2015-01-12 05:45:12 +00:00
|
|
|
#include "../../libretro.h"
|
|
|
|
#include "../../general.h"
|
|
|
|
#include "../../retroarch.h"
|
|
|
|
#include "../../driver.h"
|
|
|
|
#include "../../performance.h"
|
2015-01-12 22:35:40 +00:00
|
|
|
#include "../font_renderer_driver.h"
|
2015-01-12 05:45:12 +00:00
|
|
|
#include "../../content.h"
|
2015-03-15 17:29:05 +00:00
|
|
|
#include "../../runloop.h"
|
2015-02-14 16:49:21 +00:00
|
|
|
#include "../video_viewport.h"
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2012-06-22 17:16:53 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
2015-05-09 13:41:10 +00:00
|
|
|
uint64_t frame_count;
|
2012-09-29 18:18:24 +00:00
|
|
|
bool should_resize;
|
2012-06-19 19:01:34 +00:00
|
|
|
float mScreenAspect;
|
|
|
|
bool mKeepAspect;
|
2012-10-18 22:59:56 +00:00
|
|
|
bool mEglImageBuf;
|
2012-06-19 19:01:34 +00:00
|
|
|
unsigned mTextureWidth;
|
|
|
|
unsigned mTextureHeight;
|
|
|
|
unsigned mRenderWidth;
|
|
|
|
unsigned mRenderHeight;
|
|
|
|
unsigned x1, y1, x2, y2;
|
|
|
|
VGImageFormat mTexType;
|
|
|
|
VGImage mImage;
|
2012-09-24 23:30:24 +00:00
|
|
|
math_matrix_3x3 mTransformMatrix;
|
2012-06-19 19:01:34 +00:00
|
|
|
VGint scissor[4];
|
2012-10-18 22:59:56 +00:00
|
|
|
EGLImageKHR last_egl_image;
|
2012-06-19 19:01:34 +00:00
|
|
|
|
|
|
|
char *mLastMsg;
|
|
|
|
uint32_t mFontHeight;
|
|
|
|
VGFont mFont;
|
2012-12-15 10:02:35 +00:00
|
|
|
void *mFontRenderer;
|
2012-12-14 19:41:18 +00:00
|
|
|
const font_renderer_driver_t *font_driver;
|
2012-06-19 19:01:34 +00:00
|
|
|
bool mFontsOn;
|
|
|
|
VGuint mMsgLength;
|
|
|
|
VGuint mGlyphIndices[1024];
|
|
|
|
VGPaint mPaintFg;
|
|
|
|
VGPaint mPaintBg;
|
2012-09-24 19:19:07 +00:00
|
|
|
} vg_t;
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2012-10-18 22:59:56 +00:00
|
|
|
static PFNVGCREATEEGLIMAGETARGETKHRPROC pvgCreateEGLImageTargetKHR;
|
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
static void vg_set_nonblock_state(void *data, bool state)
|
2012-06-19 19:01:34 +00:00
|
|
|
{
|
2015-04-10 06:33:07 +00:00
|
|
|
gfx_ctx_swap_interval(data, state ? 0 : 1);
|
2012-06-19 19:01:34 +00:00
|
|
|
}
|
|
|
|
|
2015-03-15 03:37:54 +00:00
|
|
|
static INLINE bool vg_query_extension(const char *ext)
|
2012-10-18 22:59:56 +00:00
|
|
|
{
|
|
|
|
const char *str = (const char*)vgGetString(VG_EXTENSIONS);
|
|
|
|
bool ret = str && strstr(str, ext);
|
|
|
|
RARCH_LOG("Querying VG extension: %s => %s\n",
|
|
|
|
ext, ret ? "exists" : "doesn't exist");
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
static void *vg_init(const video_info_t *video, const input_driver_t **input, void **input_data)
|
2012-06-19 19:01:34 +00:00
|
|
|
{
|
2015-03-20 21:08:36 +00:00
|
|
|
VGfloat clearColor[4] = {0, 0, 0, 1};
|
2015-04-09 16:46:24 +00:00
|
|
|
settings_t *settings = config_get_ptr();
|
|
|
|
driver_t *driver = driver_get_ptr();
|
2015-04-26 04:04:16 +00:00
|
|
|
global_t *global = global_get_ptr();
|
2015-04-09 16:46:24 +00:00
|
|
|
const gfx_ctx_driver_t *ctx = NULL;
|
|
|
|
vg_t *vg = (vg_t*)calloc(1, sizeof(vg_t));
|
2015-03-20 21:08:36 +00:00
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
if (!vg)
|
2015-04-09 16:46:24 +00:00
|
|
|
goto error;
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2015-04-09 16:46:24 +00:00
|
|
|
ctx = gfx_ctx_init_first(vg, settings->video.context_driver,
|
2014-10-24 00:15:30 +00:00
|
|
|
GFX_CTX_OPENVG_API, 0, 0, false);
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2015-04-09 16:46:24 +00:00
|
|
|
if (!ctx)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
driver->video_context = ctx;
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2015-04-26 04:04:16 +00:00
|
|
|
gfx_ctx_get_video_size(vg, &global->video_data.width, &global->video_data.height);
|
|
|
|
RARCH_LOG("Detecting screen resolution %ux%u.\n", global->video_data.width, global->video_data.height);
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2015-04-10 06:33:07 +00:00
|
|
|
gfx_ctx_swap_interval(vg, video->vsync ? 1 : 0);
|
2015-04-10 06:26:43 +00:00
|
|
|
|
|
|
|
gfx_ctx_update_window_title(vg);
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2012-10-22 21:28:12 +00:00
|
|
|
vg->mTexType = video->rgb32 ? VG_sXRGB_8888 : VG_sRGB_565;
|
2012-09-24 19:19:07 +00:00
|
|
|
vg->mKeepAspect = video->force_aspect;
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2012-09-25 00:47:48 +00:00
|
|
|
unsigned win_width = video->width;
|
|
|
|
unsigned win_height = video->height;
|
|
|
|
if (video->fullscreen && (win_width == 0) && (win_height == 0))
|
|
|
|
{
|
2015-04-26 04:04:16 +00:00
|
|
|
win_width = global->video_data.width;
|
|
|
|
win_height = global->video_data.height;
|
2012-09-25 00:47:48 +00:00
|
|
|
}
|
|
|
|
|
2015-04-10 07:05:07 +00:00
|
|
|
if (!gfx_ctx_set_video_mode(vg, win_width, win_height, video->fullscreen))
|
2015-04-09 16:46:24 +00:00
|
|
|
goto error;
|
2012-09-25 00:47:48 +00:00
|
|
|
|
2015-04-26 04:04:16 +00:00
|
|
|
gfx_ctx_get_video_size(vg, &global->video_data.width, &global->video_data.height);
|
|
|
|
RARCH_LOG("Verified window resolution %ux%u.\n", global->video_data.width, global->video_data.height);
|
2012-09-29 18:18:24 +00:00
|
|
|
vg->should_resize = true;
|
2012-09-25 00:47:48 +00:00
|
|
|
|
2015-04-26 04:04:16 +00:00
|
|
|
vg->mScreenAspect = (float)global->video_data.width / global->video_data.height;
|
2015-04-10 04:52:51 +00:00
|
|
|
|
2015-04-26 04:04:16 +00:00
|
|
|
gfx_ctx_translate_aspect(vg, &vg->mScreenAspect, global->video_data.width, global->video_data.height);
|
2012-06-19 19:01:34 +00:00
|
|
|
|
|
|
|
vgSetfv(VG_CLEAR_COLOR, 4, clearColor);
|
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
vg->mTextureWidth = vg->mTextureHeight = video->input_scale * RARCH_SCALE_BASE;
|
2012-10-22 21:28:12 +00:00
|
|
|
vg->mImage = vgCreateImage(vg->mTexType, vg->mTextureWidth, vg->mTextureHeight,
|
2012-06-22 17:16:53 +00:00
|
|
|
video->smooth ? VG_IMAGE_QUALITY_BETTER : VG_IMAGE_QUALITY_NONANTIALIASED);
|
2012-09-24 19:19:07 +00:00
|
|
|
vg_set_nonblock_state(vg, !video->vsync);
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2015-04-10 06:53:45 +00:00
|
|
|
gfx_ctx_input_driver(vg, input, input_data);
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2015-03-20 21:08:36 +00:00
|
|
|
if (settings->video.font_enable && font_renderer_create_default(&vg->font_driver, &vg->mFontRenderer,
|
|
|
|
*settings->video.font_path ? settings->video.font_path : NULL, settings->video.font_size))
|
2012-06-19 19:01:34 +00:00
|
|
|
{
|
2015-04-10 04:51:00 +00:00
|
|
|
vg->mFont = vgCreateFont(0);
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2012-12-14 19:32:39 +00:00
|
|
|
if (vg->mFont != VG_INVALID_HANDLE)
|
2012-06-19 19:01:34 +00:00
|
|
|
{
|
2015-04-10 04:51:00 +00:00
|
|
|
vg->mFontsOn = true;
|
|
|
|
vg->mFontHeight = settings->video.font_size;
|
|
|
|
vg->mPaintFg = vgCreatePaint();
|
|
|
|
vg->mPaintBg = vgCreatePaint();
|
2015-03-20 21:08:36 +00:00
|
|
|
VGfloat paintFg[] = { settings->video.msg_color_r, settings->video.msg_color_g, settings->video.msg_color_b, 1.0f };
|
|
|
|
VGfloat paintBg[] = { settings->video.msg_color_r / 2.0f, settings->video.msg_color_g / 2.0f, settings->video.msg_color_b / 2.0f, 0.5f };
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
vgSetParameteri(vg->mPaintFg, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
|
|
|
|
vgSetParameterfv(vg->mPaintFg, VG_PAINT_COLOR, 4, paintFg);
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
vgSetParameteri(vg->mPaintBg, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
|
|
|
|
vgSetParameterfv(vg->mPaintBg, VG_PAINT_COLOR, 4, paintBg);
|
2012-06-19 19:01:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-10 07:02:24 +00:00
|
|
|
if (vg_query_extension("KHR_EGL_image") && gfx_ctx_image_buffer_init(vg, video))
|
2012-10-18 22:59:56 +00:00
|
|
|
{
|
2015-04-10 07:24:10 +00:00
|
|
|
pvgCreateEGLImageTargetKHR = (PFNVGCREATEEGLIMAGETARGETKHRPROC)gfx_ctx_get_proc_address("vgCreateEGLImageTargetKHR");
|
2012-10-18 22:59:56 +00:00
|
|
|
|
|
|
|
if (pvgCreateEGLImageTargetKHR)
|
|
|
|
{
|
|
|
|
RARCH_LOG("[VG] Using EGLImage buffer\n");
|
|
|
|
vg->mEglImageBuf = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
const char *ext = (const char*)vgGetString(VG_EXTENSIONS);
|
|
|
|
if (ext)
|
|
|
|
RARCH_LOG("[VG] Supported extensions: %s\n", ext);
|
|
|
|
#endif
|
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
return vg;
|
2015-04-09 16:46:24 +00:00
|
|
|
|
|
|
|
error:
|
|
|
|
if (vg)
|
|
|
|
free(vg);
|
|
|
|
if (driver)
|
|
|
|
driver->video_context = NULL;
|
|
|
|
return NULL;
|
2012-06-19 19:01:34 +00:00
|
|
|
}
|
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
static void vg_free(void *data)
|
2012-06-19 19:01:34 +00:00
|
|
|
{
|
2015-04-09 16:46:24 +00:00
|
|
|
vg_t *vg = (vg_t*)data;
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2014-09-15 12:17:16 +00:00
|
|
|
if (!vg)
|
|
|
|
return;
|
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
vgDestroyImage(vg->mImage);
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
if (vg->mFontsOn)
|
2012-06-19 19:01:34 +00:00
|
|
|
{
|
2012-09-24 19:19:07 +00:00
|
|
|
vgDestroyFont(vg->mFont);
|
2012-12-14 19:32:39 +00:00
|
|
|
vg->font_driver->free(vg->mFontRenderer);
|
2012-09-24 19:19:07 +00:00
|
|
|
vgDestroyPaint(vg->mPaintFg);
|
|
|
|
vgDestroyPaint(vg->mPaintBg);
|
2012-06-19 19:01:34 +00:00
|
|
|
}
|
|
|
|
|
2015-05-02 20:37:27 +00:00
|
|
|
gfx_ctx_free(vg);
|
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
free(vg);
|
2012-06-19 19:01:34 +00:00
|
|
|
}
|
|
|
|
|
2014-06-08 11:23:56 +00:00
|
|
|
#if 0
|
2012-09-24 19:19:07 +00:00
|
|
|
static void vg_render_message(vg_t *vg, const char *msg)
|
2012-06-19 19:01:34 +00:00
|
|
|
{
|
2012-09-24 19:19:07 +00:00
|
|
|
free(vg->mLastMsg);
|
|
|
|
vg->mLastMsg = strdup(msg);
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
if (vg->mMsgLength)
|
2012-06-19 19:01:34 +00:00
|
|
|
{
|
2012-09-24 19:19:07 +00:00
|
|
|
while (--vg->mMsgLength)
|
|
|
|
vgClearGlyph(vg->mFont, vg->mMsgLength);
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
vgClearGlyph(vg->mFont, 0);
|
2012-06-19 19:01:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct font_output_list out;
|
2012-12-14 19:41:18 +00:00
|
|
|
vg->font_driver->render_msg(vg->mFontRenderer, msg, &out);
|
2012-06-19 19:01:34 +00:00
|
|
|
struct font_output *head = out.head;
|
|
|
|
|
|
|
|
while (head)
|
|
|
|
{
|
2012-09-24 19:19:07 +00:00
|
|
|
if (vg->mMsgLength >= 1024)
|
2012-06-19 19:01:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
VGfloat origin[2], escapement[2];
|
|
|
|
VGImage img;
|
|
|
|
|
2012-06-22 17:16:53 +00:00
|
|
|
escapement[0] = head->advance_x;
|
|
|
|
escapement[1] = head->advance_y;
|
|
|
|
origin[0] = -head->char_off_x;
|
2012-07-10 11:40:13 +00:00
|
|
|
origin[1] = -head->char_off_y;
|
2012-06-19 19:01:34 +00:00
|
|
|
|
|
|
|
img = vgCreateImage(VG_A_8, head->width, head->height, VG_IMAGE_QUALITY_NONANTIALIASED);
|
|
|
|
|
|
|
|
// flip it
|
|
|
|
for (unsigned i = 0; i < head->height; i++)
|
|
|
|
vgImageSubData(img, head->output + head->pitch * i, head->pitch, VG_A_8, 0, head->height - i - 1, head->width, 1);
|
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
vgSetGlyphToImage(vg->mFont, vg->mMsgLength, img, origin, escapement);
|
2012-06-19 19:01:34 +00:00
|
|
|
vgDestroyImage(img);
|
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
vg->mMsgLength++;
|
2012-06-19 19:01:34 +00:00
|
|
|
head = head->next;
|
|
|
|
}
|
|
|
|
|
2012-12-14 19:41:18 +00:00
|
|
|
vg->font_driver->free_output(vg->mFontRenderer, &out);
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
for (unsigned i = 0; i < vg->mMsgLength; i++)
|
|
|
|
vg->mGlyphIndices[i] = i;
|
2012-06-19 19:01:34 +00:00
|
|
|
}
|
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
static void vg_draw_message(vg_t *vg, const char *msg)
|
2012-06-19 19:01:34 +00:00
|
|
|
{
|
2015-03-20 21:08:36 +00:00
|
|
|
settings_t *settings = config_get_ptr();
|
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
if (!vg->mLastMsg || strcmp(vg->mLastMsg, msg))
|
|
|
|
vg_render_message(vg, msg);
|
2012-06-19 19:01:34 +00:00
|
|
|
|
|
|
|
vgSeti(VG_SCISSORING, VG_FALSE);
|
|
|
|
vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_STENCIL);
|
|
|
|
|
2012-06-22 17:16:53 +00:00
|
|
|
VGfloat origins[] = {
|
2015-04-26 04:04:16 +00:00
|
|
|
global->video_data.width * settings->video.msg_pos_x - 2.0f,
|
|
|
|
global->video_data.height * settings->video.msg_pos_y - 2.0f,
|
2012-06-22 17:16:53 +00:00
|
|
|
};
|
|
|
|
|
2012-06-19 19:01:34 +00:00
|
|
|
vgSetfv(VG_GLYPH_ORIGIN, 2, origins);
|
2012-09-24 19:19:07 +00:00
|
|
|
vgSetPaint(vg->mPaintBg, VG_FILL_PATH);
|
|
|
|
vgDrawGlyphs(vg->mFont, vg->mMsgLength, vg->mGlyphIndices, NULL, NULL, VG_FILL_PATH, VG_TRUE);
|
2012-06-19 19:01:34 +00:00
|
|
|
origins[0] += 2.0f;
|
|
|
|
origins[1] += 2.0f;
|
|
|
|
vgSetfv(VG_GLYPH_ORIGIN, 2, origins);
|
2012-09-24 19:19:07 +00:00
|
|
|
vgSetPaint(vg->mPaintFg, VG_FILL_PATH);
|
|
|
|
vgDrawGlyphs(vg->mFont, vg->mMsgLength, vg->mGlyphIndices, NULL, NULL, VG_FILL_PATH, VG_TRUE);
|
2012-06-19 19:01:34 +00:00
|
|
|
|
|
|
|
vgSeti(VG_SCISSORING, VG_TRUE);
|
|
|
|
vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL);
|
|
|
|
}
|
2014-06-08 11:23:56 +00:00
|
|
|
#endif
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
static void vg_calculate_quad(vg_t *vg)
|
2012-06-19 19:01:34 +00:00
|
|
|
{
|
2015-04-26 21:19:19 +00:00
|
|
|
global_t *global = global_get_ptr();
|
|
|
|
|
2015-04-11 06:45:55 +00:00
|
|
|
/* set viewport for aspect ratio, taken from the OpenGL driver. */
|
2012-09-24 19:19:07 +00:00
|
|
|
if (vg->mKeepAspect)
|
2012-06-19 19:01:34 +00:00
|
|
|
{
|
2015-03-21 03:43:18 +00:00
|
|
|
float desired_aspect = global->system.aspect_ratio;
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2015-04-11 06:45:55 +00:00
|
|
|
/* If the aspect ratios of screen and desired aspect ratio
|
|
|
|
* are sufficiently equal (floating point stuff),
|
|
|
|
* assume they are actually equal. */
|
2012-09-24 19:19:07 +00:00
|
|
|
if (fabs(vg->mScreenAspect - desired_aspect) < 0.0001)
|
2012-06-19 19:01:34 +00:00
|
|
|
{
|
2012-09-24 19:19:07 +00:00
|
|
|
vg->x1 = 0;
|
|
|
|
vg->y1 = 0;
|
2015-04-26 04:04:16 +00:00
|
|
|
vg->x2 = global->video_data.width;
|
|
|
|
vg->y2 = global->video_data.height;
|
2012-06-19 19:01:34 +00:00
|
|
|
}
|
2012-09-24 19:19:07 +00:00
|
|
|
else if (vg->mScreenAspect > desired_aspect)
|
2012-06-19 19:01:34 +00:00
|
|
|
{
|
2012-09-24 19:19:07 +00:00
|
|
|
float delta = (desired_aspect / vg->mScreenAspect - 1.0) / 2.0 + 0.5;
|
2015-04-26 04:04:16 +00:00
|
|
|
vg->x1 = global->video_data.width * (0.5 - delta);
|
2012-09-24 19:19:07 +00:00
|
|
|
vg->y1 = 0;
|
2015-04-26 04:04:16 +00:00
|
|
|
vg->x2 = 2.0 * global->video_data.width * delta + vg->x1;
|
|
|
|
vg->y2 = global->video_data.height + vg->y1;
|
2012-06-19 19:01:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-09-24 19:19:07 +00:00
|
|
|
float delta = (vg->mScreenAspect / desired_aspect - 1.0) / 2.0 + 0.5;
|
|
|
|
vg->x1 = 0;
|
2015-04-26 04:04:16 +00:00
|
|
|
vg->y1 = global->video_data.height * (0.5 - delta);
|
|
|
|
vg->x2 = global->video_data.width + vg->x1;
|
|
|
|
vg->y2 = 2.0 * global->video_data.height * delta + vg->y1;
|
2012-06-19 19:01:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-09-24 19:19:07 +00:00
|
|
|
vg->x1 = 0;
|
|
|
|
vg->y1 = 0;
|
2015-04-26 04:04:16 +00:00
|
|
|
vg->x2 = global->video_data.width;
|
|
|
|
vg->y2 = global->video_data.height;
|
2012-06-19 19:01:34 +00:00
|
|
|
}
|
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
vg->scissor[0] = vg->x1;
|
|
|
|
vg->scissor[1] = vg->y1;
|
|
|
|
vg->scissor[2] = vg->x2 - vg->x1;
|
|
|
|
vg->scissor[3] = vg->y2 - vg->y1;
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
vgSetiv(VG_SCISSOR_RECTS, 4, vg->scissor);
|
2012-06-19 19:01:34 +00:00
|
|
|
}
|
|
|
|
|
2015-04-11 06:45:55 +00:00
|
|
|
static void vg_copy_frame(void *data, const void *frame,
|
|
|
|
unsigned width, unsigned height, unsigned pitch)
|
2012-10-18 22:59:56 +00:00
|
|
|
{
|
|
|
|
vg_t *vg = (vg_t*)data;
|
|
|
|
|
|
|
|
if (vg->mEglImageBuf)
|
|
|
|
{
|
|
|
|
EGLImageKHR img = 0;
|
2015-04-10 07:02:24 +00:00
|
|
|
bool new_egl = gfx_ctx_image_buffer_write(vg,
|
2015-04-09 16:46:24 +00:00
|
|
|
frame, width, height, pitch, (vg->mTexType == VG_sXRGB_8888), 0, &img);
|
|
|
|
|
2012-10-18 22:59:56 +00:00
|
|
|
rarch_assert(img != EGL_NO_IMAGE_KHR);
|
|
|
|
|
|
|
|
if (new_egl)
|
|
|
|
{
|
|
|
|
vgDestroyImage(vg->mImage);
|
|
|
|
vg->mImage = pvgCreateEGLImageTargetKHR((VGeglImageKHR) img);
|
|
|
|
if (!vg->mImage)
|
|
|
|
{
|
2012-10-20 03:08:53 +00:00
|
|
|
RARCH_ERR("[VG:EGLImage] Error creating image: %08x\n", vgGetError());
|
2012-10-18 22:59:56 +00:00
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
vg->last_egl_image = img;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
vgImageSubData(vg->mImage, frame, pitch, vg->mTexType, 0, 0, width, height);
|
|
|
|
}
|
|
|
|
|
2015-04-11 06:45:55 +00:00
|
|
|
static bool vg_frame(void *data, const void *frame,
|
|
|
|
unsigned width, unsigned height, unsigned pitch, const char *msg)
|
2012-06-19 19:01:34 +00:00
|
|
|
{
|
2015-04-10 07:02:24 +00:00
|
|
|
vg_t *vg = (vg_t*)data;
|
2015-04-26 21:19:19 +00:00
|
|
|
global_t *global = global_get_ptr();
|
2015-04-10 07:02:24 +00:00
|
|
|
|
2013-12-18 18:10:57 +00:00
|
|
|
RARCH_PERFORMANCE_INIT(vg_fr);
|
|
|
|
RARCH_PERFORMANCE_START(vg_fr);
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2012-09-29 18:18:24 +00:00
|
|
|
if (width != vg->mRenderWidth || height != vg->mRenderHeight || vg->should_resize)
|
2012-06-19 19:01:34 +00:00
|
|
|
{
|
2012-09-24 19:19:07 +00:00
|
|
|
vg->mRenderWidth = width;
|
|
|
|
vg->mRenderHeight = height;
|
|
|
|
vg_calculate_quad(vg);
|
2012-09-24 23:30:24 +00:00
|
|
|
matrix_3x3_quad_to_quad(
|
2012-09-24 19:19:07 +00:00
|
|
|
vg->x1, vg->y1, vg->x2, vg->y1, vg->x2, vg->y2, vg->x1, vg->y2,
|
2015-04-10 04:52:51 +00:00
|
|
|
/* needs to be flipped, Khronos loves their bottom-left origin */
|
2012-06-19 19:01:34 +00:00
|
|
|
0, height, width, height, width, 0, 0, 0,
|
2012-09-24 23:30:24 +00:00
|
|
|
&vg->mTransformMatrix);
|
2012-06-19 19:01:34 +00:00
|
|
|
vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
|
2012-09-24 23:30:24 +00:00
|
|
|
vgLoadMatrix(vg->mTransformMatrix.data);
|
2012-09-29 18:18:24 +00:00
|
|
|
|
|
|
|
vg->should_resize = false;
|
2012-06-19 19:01:34 +00:00
|
|
|
}
|
|
|
|
vgSeti(VG_SCISSORING, VG_FALSE);
|
2015-04-26 04:04:16 +00:00
|
|
|
vgClear(0, 0, global->video_data.width, global->video_data.height);
|
2012-06-19 19:01:34 +00:00
|
|
|
vgSeti(VG_SCISSORING, VG_TRUE);
|
|
|
|
|
2013-12-18 18:10:57 +00:00
|
|
|
RARCH_PERFORMANCE_INIT(vg_image);
|
|
|
|
RARCH_PERFORMANCE_START(vg_image);
|
2012-10-18 22:59:56 +00:00
|
|
|
vg_copy_frame(vg, frame, width, height, pitch);
|
2013-12-18 18:10:57 +00:00
|
|
|
RARCH_PERFORMANCE_STOP(vg_image);
|
2012-10-18 22:59:56 +00:00
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
vgDrawImage(vg->mImage);
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2014-06-08 11:23:56 +00:00
|
|
|
#if 0
|
2012-09-24 19:19:07 +00:00
|
|
|
if (msg && vg->mFontsOn)
|
|
|
|
vg_draw_message(vg, msg);
|
2014-06-08 11:23:56 +00:00
|
|
|
#endif
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2015-04-10 06:26:43 +00:00
|
|
|
gfx_ctx_update_window_title(vg);
|
2012-12-29 03:30:37 +00:00
|
|
|
|
2013-12-18 18:10:57 +00:00
|
|
|
RARCH_PERFORMANCE_STOP(vg_fr);
|
2015-04-10 04:51:00 +00:00
|
|
|
|
|
|
|
gfx_ctx_swap_buffers(vg);
|
2012-06-19 19:01:34 +00:00
|
|
|
|
2015-05-09 13:41:10 +00:00
|
|
|
vg->frame_count++;
|
|
|
|
|
2012-06-19 19:01:34 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
static bool vg_alive(void *data)
|
2012-06-19 19:01:34 +00:00
|
|
|
{
|
2012-09-29 18:18:24 +00:00
|
|
|
bool quit;
|
2015-04-26 04:04:16 +00:00
|
|
|
vg_t *vg = (vg_t*)data;
|
|
|
|
global_t *global = global_get_ptr();
|
2012-09-18 23:41:58 +00:00
|
|
|
|
2015-04-10 04:51:00 +00:00
|
|
|
gfx_ctx_check_window(data, &quit,
|
2015-04-26 04:04:16 +00:00
|
|
|
&vg->should_resize, &global->video_data.width, &global->video_data.height);
|
2012-09-18 23:41:58 +00:00
|
|
|
return !quit;
|
2012-06-19 19:01:34 +00:00
|
|
|
}
|
|
|
|
|
2012-09-24 19:19:07 +00:00
|
|
|
static bool vg_focus(void *data)
|
2012-06-19 19:01:34 +00:00
|
|
|
{
|
2015-04-10 04:51:00 +00:00
|
|
|
return gfx_ctx_focus(data);
|
2014-10-08 15:23:02 +00:00
|
|
|
}
|
|
|
|
|
2015-01-18 21:32:14 +00:00
|
|
|
static bool vg_suppress_screensaver(void *data, bool enable)
|
|
|
|
{
|
2015-04-10 04:51:00 +00:00
|
|
|
return gfx_ctx_suppress_screensaver(data, enable);
|
2015-01-18 21:32:14 +00:00
|
|
|
}
|
|
|
|
|
2014-10-08 15:23:02 +00:00
|
|
|
static bool vg_has_windowed(void *data)
|
|
|
|
{
|
2015-04-10 04:51:00 +00:00
|
|
|
return gfx_ctx_has_windowed(data);
|
2012-06-19 19:01:34 +00:00
|
|
|
}
|
|
|
|
|
2014-09-09 18:18:06 +00:00
|
|
|
static bool vg_set_shader(void *data,
|
|
|
|
enum rarch_shader_type type, const char *path)
|
|
|
|
{
|
|
|
|
(void)data;
|
|
|
|
(void)type;
|
|
|
|
(void)path;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void vg_set_rotation(void *data, unsigned rotation)
|
|
|
|
{
|
|
|
|
(void)data;
|
|
|
|
(void)rotation;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void vg_viewport_info(void *data,
|
2015-02-14 04:52:05 +00:00
|
|
|
struct video_viewport *vp)
|
2014-09-09 18:18:06 +00:00
|
|
|
{
|
|
|
|
(void)data;
|
|
|
|
(void)vp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool vg_read_viewport(void *data, uint8_t *buffer)
|
|
|
|
{
|
|
|
|
(void)data;
|
|
|
|
(void)buffer;
|
|
|
|
|
2014-09-09 20:41:04 +00:00
|
|
|
return true;
|
2014-09-09 18:18:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void vg_get_poke_interface(void *data,
|
|
|
|
const video_poke_interface_t **iface)
|
|
|
|
{
|
|
|
|
(void)data;
|
|
|
|
(void)iface;
|
|
|
|
}
|
|
|
|
|
2014-09-11 05:06:20 +00:00
|
|
|
video_driver_t video_vg = {
|
2012-09-24 19:19:07 +00:00
|
|
|
vg_init,
|
|
|
|
vg_frame,
|
|
|
|
vg_set_nonblock_state,
|
|
|
|
vg_alive,
|
|
|
|
vg_focus,
|
2015-01-18 21:32:14 +00:00
|
|
|
vg_suppress_screensaver,
|
2014-10-08 15:23:02 +00:00
|
|
|
vg_has_windowed,
|
2014-09-09 18:18:06 +00:00
|
|
|
vg_set_shader,
|
2012-09-24 19:19:07 +00:00
|
|
|
vg_free,
|
2014-09-09 18:18:06 +00:00
|
|
|
"vg",
|
2015-04-26 17:46:59 +00:00
|
|
|
NULL, /* set_viewport */
|
2014-09-09 18:18:06 +00:00
|
|
|
vg_set_rotation,
|
|
|
|
vg_viewport_info,
|
|
|
|
vg_read_viewport,
|
2015-03-16 08:33:16 +00:00
|
|
|
NULL, /* read_frame_raw */
|
2014-09-09 18:18:06 +00:00
|
|
|
#ifdef HAVE_OVERLAY
|
|
|
|
NULL, /* overlay_interface */
|
|
|
|
#endif
|
|
|
|
vg_get_poke_interface
|
2012-06-19 19:01:34 +00:00
|
|
|
};
|