mirror of
https://github.com/CTCaer/RetroArch.git
synced 2025-01-29 15:32:01 +00:00
beginning framework for EGLImage support, added (untested) example to OpenVG
This commit is contained in:
parent
497f4dfb31
commit
86fb0984d2
@ -307,6 +307,16 @@ static bool gfx_ctx_has_focus(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gfx_ctx_can_egl_image_buffer(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, void **image_handle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const gfx_ctx_driver_t gfx_ctx_android = {
|
||||
gfx_ctx_init,
|
||||
gfx_ctx_destroy,
|
||||
@ -322,5 +332,7 @@ const gfx_ctx_driver_t gfx_ctx_android = {
|
||||
gfx_ctx_swap_buffers,
|
||||
gfx_ctx_input_driver,
|
||||
NULL,
|
||||
gfx_ctx_can_egl_image_buffer,
|
||||
gfx_ctx_write_egl_image,
|
||||
"android",
|
||||
};
|
||||
|
@ -625,6 +625,16 @@ static bool gfx_ctx_bind_api(enum gfx_ctx_api api)
|
||||
}
|
||||
}
|
||||
|
||||
bool gfx_ctx_can_egl_image_buffer(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, void **image_handle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const gfx_ctx_driver_t gfx_ctx_drm_egl = {
|
||||
gfx_ctx_init,
|
||||
gfx_ctx_destroy,
|
||||
@ -640,6 +650,8 @@ const gfx_ctx_driver_t gfx_ctx_drm_egl = {
|
||||
gfx_ctx_swap_buffers,
|
||||
gfx_ctx_input_driver,
|
||||
gfx_ctx_get_proc_address,
|
||||
gfx_ctx_can_egl_image_buffer,
|
||||
gfx_ctx_write_egl_image,
|
||||
"drm-egl",
|
||||
};
|
||||
|
||||
|
@ -462,6 +462,16 @@ static bool gfx_ctx_bind_api(enum gfx_ctx_api api)
|
||||
return api == GFX_CTX_OPENGL_API;
|
||||
}
|
||||
|
||||
bool gfx_ctx_can_egl_image_buffer(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, void **image_handle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const gfx_ctx_driver_t gfx_ctx_glx = {
|
||||
gfx_ctx_init,
|
||||
gfx_ctx_destroy,
|
||||
@ -477,6 +487,8 @@ const gfx_ctx_driver_t gfx_ctx_glx = {
|
||||
gfx_ctx_swap_buffers,
|
||||
gfx_ctx_input_driver,
|
||||
gfx_ctx_get_proc_address,
|
||||
gfx_ctx_can_egl_image_buffer,
|
||||
gfx_ctx_write_egl_image,
|
||||
"glx",
|
||||
};
|
||||
|
||||
|
@ -378,6 +378,16 @@ static bool gfx_ctx_bind_api(enum gfx_ctx_api api)
|
||||
return api == GFX_CTX_OPENGL_API || GFX_CTX_OPENGL_ES_API;
|
||||
}
|
||||
|
||||
bool gfx_ctx_can_egl_image_buffer(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, void **image_handle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const gfx_ctx_driver_t gfx_ctx_ps3 = {
|
||||
gfx_ctx_init,
|
||||
gfx_ctx_destroy,
|
||||
@ -393,6 +403,8 @@ const gfx_ctx_driver_t gfx_ctx_ps3 = {
|
||||
gfx_ctx_swap_buffers,
|
||||
gfx_ctx_input_driver,
|
||||
NULL,
|
||||
gfx_ctx_can_egl_image_buffer,
|
||||
gfx_ctx_write_egl_image,
|
||||
"ps3",
|
||||
|
||||
// RARCH_CONSOLE stuff.
|
||||
|
@ -316,6 +316,16 @@ static bool gfx_ctx_bind_api(enum gfx_ctx_api api)
|
||||
return api == GFX_CTX_OPENGL_API;
|
||||
}
|
||||
|
||||
bool gfx_ctx_can_egl_image_buffer(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, void **image_handle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const gfx_ctx_driver_t gfx_ctx_sdl_gl = {
|
||||
gfx_ctx_init,
|
||||
gfx_ctx_destroy,
|
||||
@ -331,6 +341,8 @@ const gfx_ctx_driver_t gfx_ctx_sdl_gl = {
|
||||
gfx_ctx_swap_buffers,
|
||||
gfx_ctx_input_driver,
|
||||
gfx_ctx_get_proc_address,
|
||||
gfx_ctx_can_egl_image_buffer,
|
||||
gfx_ctx_write_egl_image,
|
||||
"sdl-gl",
|
||||
};
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <EGL/eglext_brcm.h>
|
||||
#include <bcm_host.h>
|
||||
|
||||
static EGLContext g_egl_ctx;
|
||||
@ -48,11 +49,25 @@ static enum gfx_ctx_api g_api;
|
||||
static unsigned g_fb_width; // Just use something for now.
|
||||
static unsigned g_fb_height;
|
||||
|
||||
struct drm_fb
|
||||
/*static EGLImageKHR eglBuffer;
|
||||
static DISPMANX_RESOURCE_HANDLE_T vcBuffer;
|
||||
static VC_RECT_T bufferRect;
|
||||
static unsigned bufferLastWidth;
|
||||
static unsigned bufferLastHeight;
|
||||
static bool bufferLastRgb32;
|
||||
|
||||
PFNEGLCREATEIMAGEKHRPROC peglCreateImageKHR;
|
||||
PFNEGLDESTROYIMAGEKHRPROC peglDestroyImageKHR;
|
||||
|
||||
static inline bool gfx_ctx_egl_query_extension(const char *ext)
|
||||
{
|
||||
struct gbm_bo *bo;
|
||||
uint32_t fb_id;
|
||||
};
|
||||
const char *str = (const char*)eglQueryString(g_egl_dpy, EGL_EXTENSIONS);
|
||||
bool ret = str && strstr(str, ext);
|
||||
RARCH_LOG("Querying EGL extension: %s => %s\n",
|
||||
ext, ret ? "exists" : "doesn't exist");
|
||||
|
||||
return ret;
|
||||
}*/
|
||||
|
||||
static void sighandler(int sig)
|
||||
{
|
||||
@ -285,6 +300,50 @@ static float gfx_ctx_translate_aspect(unsigned width, unsigned height)
|
||||
return (float)width / height;
|
||||
}
|
||||
|
||||
bool gfx_ctx_can_egl_image_buffer(void)
|
||||
{
|
||||
/*peglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)gfx_ctx_get_proc_address("eglCreateImageKHR");
|
||||
peglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)gfx_ctx_get_proc_address("eglDestroyImageKHR");
|
||||
return peglCreateImageKHR && peglDestroyImageKHR && gfx_ctx_egl_query_extension("KHR_image");*/
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, void **image_handle)
|
||||
{
|
||||
/*bool ret = false;
|
||||
if (!eglBuffer || !vcBuffer || (width != bufferLastWidth && height != bufferLastHeight && rgb32 != bufferLastRgb32))
|
||||
{
|
||||
ret = true;
|
||||
|
||||
if (vcBuffer)
|
||||
{
|
||||
vc_dispmanx_resource_delete(vcBuffer);
|
||||
}
|
||||
|
||||
if (eglBuffer)
|
||||
{
|
||||
peglDestroyImageKHR(g_egl_dpy, eglBuffer);
|
||||
}
|
||||
|
||||
uint32_t temp = 0xff;
|
||||
vcBuffer = vc_dispmanx_resource_create((rgb32 ? VC_IMAGE_XRGB8888 : VC_IMAGE_RGB565), width, height, &temp);
|
||||
rarch_assert(vcBuffer);
|
||||
RARCH_LOG("temp: %08x\n", temp);
|
||||
|
||||
eglBuffer = peglCreateImageKHR(g_egl_dpy, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_CLIENT_SIDE_BRCM, (EGLClientBuffer) &vcBuffer, NULL);
|
||||
RARCH_ERR("ERROR: %08x\n", eglGetError());
|
||||
rarch_assert(eglBuffer);
|
||||
|
||||
vc_dispmanx_rect_set(&bufferRect, 0, 0, width, height);
|
||||
}
|
||||
|
||||
vc_dispmanx_resource_write_data(vcBuffer, (rgb32 ? VC_IMAGE_XRGB8888 : VC_IMAGE_RGB565), pitch, (void *)frame, &bufferRect);
|
||||
*image_handle = eglBuffer;
|
||||
|
||||
return ret;*/
|
||||
return false;
|
||||
}
|
||||
|
||||
const gfx_ctx_driver_t gfx_ctx_videocore = {
|
||||
gfx_ctx_init,
|
||||
gfx_ctx_destroy,
|
||||
@ -300,6 +359,7 @@ const gfx_ctx_driver_t gfx_ctx_videocore = {
|
||||
gfx_ctx_swap_buffers,
|
||||
gfx_ctx_input_driver,
|
||||
gfx_ctx_get_proc_address,
|
||||
gfx_ctx_can_egl_image_buffer,
|
||||
gfx_ctx_write_egl_image,
|
||||
"videocore",
|
||||
};
|
||||
|
||||
|
@ -404,6 +404,16 @@ static bool gfx_ctx_bind_api(enum gfx_ctx_api api)
|
||||
return api == GFX_CTX_OPENGL_API;
|
||||
}
|
||||
|
||||
bool gfx_ctx_can_egl_image_buffer(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, void **image_handle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const gfx_ctx_driver_t gfx_ctx_wgl = {
|
||||
gfx_ctx_init,
|
||||
gfx_ctx_destroy,
|
||||
@ -419,6 +429,8 @@ const gfx_ctx_driver_t gfx_ctx_wgl = {
|
||||
gfx_ctx_swap_buffers,
|
||||
gfx_ctx_input_driver,
|
||||
gfx_ctx_get_proc_address,
|
||||
gfx_ctx_can_egl_image_buffer,
|
||||
gfx_ctx_write_egl_image,
|
||||
"wgl",
|
||||
};
|
||||
|
||||
|
@ -525,7 +525,15 @@ int gfx_ctx_xdk_check_resolution(unsigned resolution_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool gfx_ctx_can_egl_image_buffer(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, void **image_handle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const gfx_ctx_driver_t gfx_ctx_xdk = {
|
||||
gfx_ctx_xdk_init,
|
||||
@ -542,6 +550,8 @@ const gfx_ctx_driver_t gfx_ctx_xdk = {
|
||||
gfx_ctx_xdk_swap_buffers,
|
||||
gfx_ctx_xdk_input_driver,
|
||||
NULL,
|
||||
gfx_ctx_can_egl_image_buffer,
|
||||
gfx_ctx_write_egl_image,
|
||||
"xdk",
|
||||
|
||||
// RARCH_CONSOLE stuff.
|
||||
|
@ -503,6 +503,16 @@ static bool gfx_ctx_bind_api(enum gfx_ctx_api api)
|
||||
}
|
||||
}
|
||||
|
||||
bool gfx_ctx_can_egl_image_buffer(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, void **image_handle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const gfx_ctx_driver_t gfx_ctx_x_egl = {
|
||||
gfx_ctx_init,
|
||||
gfx_ctx_destroy,
|
||||
@ -518,6 +528,8 @@ const gfx_ctx_driver_t gfx_ctx_x_egl = {
|
||||
gfx_ctx_swap_buffers,
|
||||
gfx_ctx_input_driver,
|
||||
gfx_ctx_get_proc_address,
|
||||
gfx_ctx_can_egl_image_buffer,
|
||||
gfx_ctx_write_egl_image,
|
||||
"x-egl",
|
||||
};
|
||||
|
||||
|
@ -80,6 +80,13 @@ typedef struct gfx_ctx_driver
|
||||
// Wraps whatever gl_proc_address() there is.
|
||||
gfx_ctx_proc_t (*get_proc_address)(const char*);
|
||||
|
||||
// Returns true if this context supports EGL Image buffers for screen drawing.
|
||||
bool (*can_egl_image_buffer)(void);
|
||||
|
||||
// Writes the frame to the EGL Image and sets image_handle to it. Returns true if a new image handle is created.
|
||||
// Always returns true the first time it's called. The graphics core must handle a change in the handle correctly.
|
||||
bool (*write_egl_image)(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, void **image_handle);
|
||||
|
||||
// Human readable string.
|
||||
const char *ident;
|
||||
|
||||
|
76
gfx/vg.c
76
gfx/vg.c
@ -16,12 +16,15 @@
|
||||
|
||||
#include <math.h>
|
||||
#include <VG/openvg.h>
|
||||
#include <VG/vgext.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include "gfx_context.h"
|
||||
#include "math/matrix_3x3.h"
|
||||
#include "../libretro.h"
|
||||
#include "../general.h"
|
||||
#include "../driver.h"
|
||||
#include "../benchmark.h"
|
||||
|
||||
#ifdef HAVE_FREETYPE
|
||||
#include "fonts/fonts.h"
|
||||
@ -36,6 +39,7 @@ typedef struct
|
||||
bool should_resize;
|
||||
float mScreenAspect;
|
||||
bool mKeepAspect;
|
||||
bool mEglImageBuf;
|
||||
unsigned mTextureWidth;
|
||||
unsigned mTextureHeight;
|
||||
unsigned mRenderWidth;
|
||||
@ -46,6 +50,7 @@ typedef struct
|
||||
VGImage mImage;
|
||||
math_matrix_3x3 mTransformMatrix;
|
||||
VGint scissor[4];
|
||||
EGLImageKHR last_egl_image;
|
||||
|
||||
#ifdef HAVE_FREETYPE
|
||||
char *mLastMsg;
|
||||
@ -60,12 +65,24 @@ typedef struct
|
||||
#endif
|
||||
} vg_t;
|
||||
|
||||
static PFNVGCREATEEGLIMAGETARGETKHRPROC pvgCreateEGLImageTargetKHR;
|
||||
|
||||
static void vg_set_nonblock_state(void *data, bool state)
|
||||
{
|
||||
vg_t *vg = (vg_t*)data;
|
||||
vg->driver->swap_interval(state ? 0 : 1);
|
||||
}
|
||||
|
||||
static inline bool vg_query_extension(const char *ext)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
static void *vg_init(const video_info_t *video, const input_driver_t **input, void **input_data)
|
||||
{
|
||||
vg_t *vg = (vg_t*)calloc(1, sizeof(vg_t));
|
||||
@ -157,6 +174,23 @@ static void *vg_init(const video_info_t *video, const input_driver_t **input, vo
|
||||
}
|
||||
#endif
|
||||
|
||||
if (vg_query_extension("KHR_EGL_image") && vg->driver->can_egl_image_buffer())
|
||||
{
|
||||
pvgCreateEGLImageTargetKHR = (PFNVGCREATEEGLIMAGETARGETKHRPROC)vg->driver->get_proc_address("vgCreateEGLImageTargetKHR");
|
||||
|
||||
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
|
||||
|
||||
return vg;
|
||||
}
|
||||
|
||||
@ -309,8 +343,40 @@ static void vg_calculate_quad(vg_t *vg)
|
||||
vgSetiv(VG_SCISSOR_RECTS, 4, vg->scissor);
|
||||
}
|
||||
|
||||
static void vg_copy_frame(void *data, const void *frame, unsigned width, unsigned height, unsigned pitch)
|
||||
{
|
||||
vg_t *vg = (vg_t*)data;
|
||||
|
||||
if (vg->mEglImageBuf)
|
||||
{
|
||||
EGLImageKHR img = 0;
|
||||
bool new_egl = vg->driver->write_egl_image(frame, width, height, pitch, (vg->mTexType == VG_sXRGB_8888), &img);
|
||||
rarch_assert(img != EGL_NO_IMAGE_KHR);
|
||||
|
||||
if (new_egl)
|
||||
{
|
||||
vgDestroyImage(vg->mImage);
|
||||
RARCH_LOG("[VG] %08x\n", img);
|
||||
vg->mImage = pvgCreateEGLImageTargetKHR((VGeglImageKHR) img);
|
||||
if (!vg->mImage)
|
||||
{
|
||||
RARCH_ERR("[VG] Error creating image: %08x\n", vgGetError());
|
||||
exit(2);
|
||||
}
|
||||
vg->last_egl_image = img;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vgImageSubData(vg->mImage, frame, pitch, vg->mTexType, 0, 0, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
static bool vg_frame(void *data, const void *frame, unsigned width, unsigned height, unsigned pitch, const char *msg)
|
||||
{
|
||||
|
||||
RARCH_PERFORMANCE_INIT(vg_fr);
|
||||
RARCH_PERFORMANCE_START(vg_fr);
|
||||
vg_t *vg = (vg_t*)data;
|
||||
vg->frame_count++;
|
||||
|
||||
@ -333,7 +399,12 @@ static bool vg_frame(void *data, const void *frame, unsigned width, unsigned hei
|
||||
vgClear(0, 0, vg->mScreenWidth, vg->mScreenHeight);
|
||||
vgSeti(VG_SCISSORING, VG_TRUE);
|
||||
|
||||
vgImageSubData(vg->mImage, frame, pitch, vg->mTexType, 0, 0, width, height);
|
||||
RARCH_PERFORMANCE_INIT(vg_image);
|
||||
RARCH_PERFORMANCE_START(vg_image);
|
||||
vg_copy_frame(vg, frame, width, height, pitch);
|
||||
RARCH_PERFORMANCE_STOP(vg_image);
|
||||
RARCH_PERFORMANCE_LOG("vg_copy_frame", vg_image);
|
||||
|
||||
vgDrawImage(vg->mImage);
|
||||
|
||||
#ifdef HAVE_FREETYPE
|
||||
@ -343,6 +414,9 @@ static bool vg_frame(void *data, const void *frame, unsigned width, unsigned hei
|
||||
(void)msg;
|
||||
#endif
|
||||
|
||||
RARCH_PERFORMANCE_STOP(vg_fr);
|
||||
RARCH_PERFORMANCE_LOG("vg_frame", vg_fr);
|
||||
|
||||
vg->driver->swap_buffers();
|
||||
|
||||
return true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user