commit
cc4e41dafb
|
@ -307,12 +307,12 @@ static bool gfx_ctx_has_focus(void)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_can_egl_image_buffer(void)
|
static bool gfx_ctx_init_egl_image_buffer(const video_info_t *video)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, void **image_handle)
|
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, unsigned index, void **image_handle)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -332,7 +332,7 @@ const gfx_ctx_driver_t gfx_ctx_android = {
|
||||||
gfx_ctx_swap_buffers,
|
gfx_ctx_swap_buffers,
|
||||||
gfx_ctx_input_driver,
|
gfx_ctx_input_driver,
|
||||||
NULL,
|
NULL,
|
||||||
gfx_ctx_can_egl_image_buffer,
|
gfx_ctx_init_egl_image_buffer,
|
||||||
gfx_ctx_write_egl_image,
|
gfx_ctx_write_egl_image,
|
||||||
"android",
|
"android",
|
||||||
};
|
};
|
||||||
|
|
|
@ -625,12 +625,12 @@ static bool gfx_ctx_bind_api(enum gfx_ctx_api api)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_can_egl_image_buffer(void)
|
static bool gfx_ctx_init_egl_image_buffer(const video_info_t *video)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, void **image_handle)
|
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, unsigned index, void **image_handle)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -650,7 +650,7 @@ const gfx_ctx_driver_t gfx_ctx_drm_egl = {
|
||||||
gfx_ctx_swap_buffers,
|
gfx_ctx_swap_buffers,
|
||||||
gfx_ctx_input_driver,
|
gfx_ctx_input_driver,
|
||||||
gfx_ctx_get_proc_address,
|
gfx_ctx_get_proc_address,
|
||||||
gfx_ctx_can_egl_image_buffer,
|
gfx_ctx_init_egl_image_buffer,
|
||||||
gfx_ctx_write_egl_image,
|
gfx_ctx_write_egl_image,
|
||||||
"drm-egl",
|
"drm-egl",
|
||||||
};
|
};
|
||||||
|
|
|
@ -462,12 +462,12 @@ static bool gfx_ctx_bind_api(enum gfx_ctx_api api)
|
||||||
return api == GFX_CTX_OPENGL_API;
|
return api == GFX_CTX_OPENGL_API;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_can_egl_image_buffer(void)
|
static bool gfx_ctx_init_egl_image_buffer(const video_info_t *video)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, void **image_handle)
|
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, unsigned index, void **image_handle)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -487,7 +487,7 @@ const gfx_ctx_driver_t gfx_ctx_glx = {
|
||||||
gfx_ctx_swap_buffers,
|
gfx_ctx_swap_buffers,
|
||||||
gfx_ctx_input_driver,
|
gfx_ctx_input_driver,
|
||||||
gfx_ctx_get_proc_address,
|
gfx_ctx_get_proc_address,
|
||||||
gfx_ctx_can_egl_image_buffer,
|
gfx_ctx_init_egl_image_buffer,
|
||||||
gfx_ctx_write_egl_image,
|
gfx_ctx_write_egl_image,
|
||||||
"glx",
|
"glx",
|
||||||
};
|
};
|
||||||
|
|
|
@ -378,12 +378,12 @@ static bool gfx_ctx_bind_api(enum gfx_ctx_api api)
|
||||||
return api == GFX_CTX_OPENGL_API || GFX_CTX_OPENGL_ES_API;
|
return api == GFX_CTX_OPENGL_API || GFX_CTX_OPENGL_ES_API;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_can_egl_image_buffer(void)
|
static bool gfx_ctx_init_egl_image_buffer(const video_info_t *video)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, void **image_handle)
|
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, unsigned index, void **image_handle)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -403,7 +403,7 @@ const gfx_ctx_driver_t gfx_ctx_ps3 = {
|
||||||
gfx_ctx_swap_buffers,
|
gfx_ctx_swap_buffers,
|
||||||
gfx_ctx_input_driver,
|
gfx_ctx_input_driver,
|
||||||
NULL,
|
NULL,
|
||||||
gfx_ctx_can_egl_image_buffer,
|
gfx_ctx_init_egl_image_buffer,
|
||||||
gfx_ctx_write_egl_image,
|
gfx_ctx_write_egl_image,
|
||||||
"ps3",
|
"ps3",
|
||||||
|
|
||||||
|
|
|
@ -316,12 +316,12 @@ static bool gfx_ctx_bind_api(enum gfx_ctx_api api)
|
||||||
return api == GFX_CTX_OPENGL_API;
|
return api == GFX_CTX_OPENGL_API;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_can_egl_image_buffer(void)
|
static bool gfx_ctx_init_egl_image_buffer(const video_info_t *video)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, void **image_handle)
|
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, unsigned index, void **image_handle)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -341,7 +341,7 @@ const gfx_ctx_driver_t gfx_ctx_sdl_gl = {
|
||||||
gfx_ctx_swap_buffers,
|
gfx_ctx_swap_buffers,
|
||||||
gfx_ctx_input_driver,
|
gfx_ctx_input_driver,
|
||||||
gfx_ctx_get_proc_address,
|
gfx_ctx_get_proc_address,
|
||||||
gfx_ctx_can_egl_image_buffer,
|
gfx_ctx_init_egl_image_buffer,
|
||||||
gfx_ctx_write_egl_image,
|
gfx_ctx_write_egl_image,
|
||||||
"sdl-gl",
|
"sdl-gl",
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#include <EGL/eglext.h>
|
#include <EGL/eglext.h>
|
||||||
#include <EGL/eglext_brcm.h>
|
#include <EGL/eglext_brcm.h>
|
||||||
|
#include <VG/openvg.h>
|
||||||
#include <bcm_host.h>
|
#include <bcm_host.h>
|
||||||
|
|
||||||
static EGLContext g_egl_ctx;
|
static EGLContext g_egl_ctx;
|
||||||
|
@ -46,15 +47,15 @@ static bool g_inited;
|
||||||
static unsigned g_interval;
|
static unsigned g_interval;
|
||||||
static enum gfx_ctx_api g_api;
|
static enum gfx_ctx_api g_api;
|
||||||
|
|
||||||
static unsigned g_fb_width; // Just use something for now.
|
static unsigned g_fb_width;
|
||||||
static unsigned g_fb_height;
|
static unsigned g_fb_height;
|
||||||
|
|
||||||
/*static EGLImageKHR eglBuffer;
|
static EGLImageKHR eglBuffer[MAX_EGLIMAGE_TEXTURES];
|
||||||
static DISPMANX_RESOURCE_HANDLE_T vcBuffer;
|
static EGLContext g_eglimage_ctx;
|
||||||
static VC_RECT_T bufferRect;
|
static EGLSurface g_pbuff_surf;
|
||||||
static unsigned bufferLastWidth;
|
static VGImage g_egl_vgimage[MAX_EGLIMAGE_TEXTURES];
|
||||||
static unsigned bufferLastHeight;
|
static bool g_smooth;
|
||||||
static bool bufferLastRgb32;
|
static unsigned g_egl_res;
|
||||||
|
|
||||||
PFNEGLCREATEIMAGEKHRPROC peglCreateImageKHR;
|
PFNEGLCREATEIMAGEKHRPROC peglCreateImageKHR;
|
||||||
PFNEGLDESTROYIMAGEKHRPROC peglDestroyImageKHR;
|
PFNEGLDESTROYIMAGEKHRPROC peglDestroyImageKHR;
|
||||||
|
@ -67,7 +68,7 @@ static inline bool gfx_ctx_egl_query_extension(const char *ext)
|
||||||
ext, ret ? "exists" : "doesn't exist");
|
ext, ret ? "exists" : "doesn't exist");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
static void sighandler(int sig)
|
static void sighandler(int sig)
|
||||||
{
|
{
|
||||||
|
@ -236,26 +237,90 @@ static bool gfx_ctx_set_video_mode(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool gfx_ctx_bind_api(enum gfx_ctx_api api)
|
||||||
|
{
|
||||||
|
g_api = api;
|
||||||
|
switch (api)
|
||||||
|
{
|
||||||
|
case GFX_CTX_OPENGL_API:
|
||||||
|
return eglBindAPI(EGL_OPENGL_API);
|
||||||
|
case GFX_CTX_OPENGL_ES_API:
|
||||||
|
return eglBindAPI(EGL_OPENGL_ES_API);
|
||||||
|
case GFX_CTX_OPENVG_API:
|
||||||
|
return eglBindAPI(EGL_OPENVG_API);
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void gfx_ctx_destroy(void)
|
static void gfx_ctx_destroy(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (g_egl_dpy)
|
if (g_egl_dpy)
|
||||||
{
|
{
|
||||||
|
for (unsigned i = 0; i < MAX_EGLIMAGE_TEXTURES; i++)
|
||||||
|
{
|
||||||
|
if (eglBuffer[i] && peglDestroyImageKHR)
|
||||||
|
{
|
||||||
|
eglBindAPI(EGL_OPENVG_API);
|
||||||
|
eglMakeCurrent(g_egl_dpy, g_pbuff_surf, g_pbuff_surf, g_eglimage_ctx);
|
||||||
|
peglDestroyImageKHR(g_egl_dpy, eglBuffer[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_egl_vgimage[i])
|
||||||
|
{
|
||||||
|
eglBindAPI(EGL_OPENVG_API);
|
||||||
|
eglMakeCurrent(g_egl_dpy, g_pbuff_surf, g_pbuff_surf, g_eglimage_ctx);
|
||||||
|
vgDestroyImage(g_egl_vgimage[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (g_egl_ctx)
|
if (g_egl_ctx)
|
||||||
{
|
{
|
||||||
|
gfx_ctx_bind_api(g_api);
|
||||||
eglMakeCurrent(g_egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
eglMakeCurrent(g_egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
eglDestroyContext(g_egl_dpy, g_egl_ctx);
|
eglDestroyContext(g_egl_dpy, g_egl_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_eglimage_ctx)
|
||||||
|
{
|
||||||
|
eglBindAPI(EGL_OPENVG_API);
|
||||||
|
eglMakeCurrent(g_egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
|
eglDestroyContext(g_egl_dpy, g_eglimage_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
if (g_egl_surf)
|
if (g_egl_surf)
|
||||||
|
{
|
||||||
|
gfx_ctx_bind_api(g_api);
|
||||||
eglDestroySurface(g_egl_dpy, g_egl_surf);
|
eglDestroySurface(g_egl_dpy, g_egl_surf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_pbuff_surf)
|
||||||
|
{
|
||||||
|
eglBindAPI(EGL_OPENVG_API);
|
||||||
|
eglDestroySurface(g_egl_dpy, g_pbuff_surf);
|
||||||
|
}
|
||||||
|
|
||||||
|
eglBindAPI(EGL_OPENVG_API);
|
||||||
|
eglMakeCurrent(g_egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
|
gfx_ctx_bind_api(g_api);
|
||||||
|
eglMakeCurrent(g_egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
eglTerminate(g_egl_dpy);
|
eglTerminate(g_egl_dpy);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_egl_ctx = NULL;
|
g_egl_ctx = NULL;
|
||||||
g_egl_surf = NULL;
|
g_eglimage_ctx = NULL;
|
||||||
g_egl_dpy = NULL;
|
g_egl_surf = NULL;
|
||||||
g_config = 0;
|
g_pbuff_surf = NULL;
|
||||||
g_inited = false;
|
g_egl_dpy = NULL;
|
||||||
|
g_config = 0;
|
||||||
|
g_inited = false;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < MAX_EGLIMAGE_TEXTURES; i++)
|
||||||
|
{
|
||||||
|
eglBuffer[i] = NULL;
|
||||||
|
g_egl_vgimage[i] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gfx_ctx_input_driver(const input_driver_t **input, void **input_data)
|
static void gfx_ctx_input_driver(const input_driver_t **input, void **input_data)
|
||||||
|
@ -275,22 +340,6 @@ static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol)
|
||||||
return eglGetProcAddress(symbol);
|
return eglGetProcAddress(symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_bind_api(enum gfx_ctx_api api)
|
|
||||||
{
|
|
||||||
g_api = api;
|
|
||||||
switch (api)
|
|
||||||
{
|
|
||||||
case GFX_CTX_OPENGL_API:
|
|
||||||
return eglBindAPI(EGL_OPENGL_API);
|
|
||||||
case GFX_CTX_OPENGL_ES_API:
|
|
||||||
return eglBindAPI(EGL_OPENGL_ES_API);
|
|
||||||
case GFX_CTX_OPENVG_API:
|
|
||||||
return eglBindAPI(EGL_OPENVG_API);
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static float gfx_ctx_translate_aspect(unsigned width, unsigned height)
|
static float gfx_ctx_translate_aspect(unsigned width, unsigned height)
|
||||||
{
|
{
|
||||||
// check for SD televisions: they should always be 4:3.
|
// check for SD televisions: they should always be 4:3.
|
||||||
|
@ -300,48 +349,107 @@ static float gfx_ctx_translate_aspect(unsigned width, unsigned height)
|
||||||
return (float)width / height;
|
return (float)width / height;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_can_egl_image_buffer(void)
|
static bool gfx_ctx_init_egl_image_buffer(const video_info_t *video)
|
||||||
{
|
{
|
||||||
/*peglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)gfx_ctx_get_proc_address("eglCreateImageKHR");
|
if (g_api == GFX_CTX_OPENVG_API) // don't bother, we just use VGImages for our EGLImage anyway
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
peglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)gfx_ctx_get_proc_address("eglCreateImageKHR");
|
||||||
peglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)gfx_ctx_get_proc_address("eglDestroyImageKHR");
|
peglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)gfx_ctx_get_proc_address("eglDestroyImageKHR");
|
||||||
return peglCreateImageKHR && peglDestroyImageKHR && gfx_ctx_egl_query_extension("KHR_image");*/
|
|
||||||
|
if (!peglCreateImageKHR || !peglDestroyImageKHR || !gfx_ctx_egl_query_extension("KHR_image"))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_egl_res = video->input_scale * RARCH_SCALE_BASE;
|
||||||
|
|
||||||
|
EGLint pbufsurface_list[] =
|
||||||
|
{
|
||||||
|
EGL_WIDTH, g_egl_res,
|
||||||
|
EGL_HEIGHT, g_egl_res,
|
||||||
|
EGL_NONE
|
||||||
|
};
|
||||||
|
|
||||||
|
EGLBoolean result;
|
||||||
|
|
||||||
|
eglBindAPI(EGL_OPENVG_API);
|
||||||
|
g_pbuff_surf = eglCreatePbufferSurface(g_egl_dpy, g_config, pbufsurface_list);
|
||||||
|
if (g_pbuff_surf == EGL_NO_SURFACE)
|
||||||
|
{
|
||||||
|
RARCH_ERR("[VideoCore:EGLImage] failed to create PbufferSurface\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_eglimage_ctx = eglCreateContext(g_egl_dpy, g_config, NULL, NULL);
|
||||||
|
if (g_eglimage_ctx == EGL_NO_CONTEXT)
|
||||||
|
{
|
||||||
|
RARCH_ERR("[VideoCore:EGLImage] failed to create context\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
// test to make sure we can switch context
|
||||||
|
result = eglMakeCurrent(g_egl_dpy, g_pbuff_surf, g_pbuff_surf, g_eglimage_ctx);
|
||||||
|
if (result == EGL_FALSE)
|
||||||
|
{
|
||||||
|
RARCH_ERR("[VideoCore:EGLImage] failed to make context current\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx_ctx_bind_api(g_api);
|
||||||
|
eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx);
|
||||||
|
|
||||||
|
g_smooth = video->smooth;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (g_pbuff_surf != EGL_NO_SURFACE)
|
||||||
|
{
|
||||||
|
eglDestroySurface(g_egl_dpy, g_pbuff_surf);
|
||||||
|
g_pbuff_surf = EGL_NO_SURFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_eglimage_ctx != EGL_NO_CONTEXT)
|
||||||
|
{
|
||||||
|
eglDestroyContext(g_egl_dpy, g_eglimage_ctx);
|
||||||
|
g_pbuff_surf = EGL_NO_CONTEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx_ctx_bind_api(g_api);
|
||||||
|
eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, void **image_handle)
|
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, unsigned index, void **image_handle)
|
||||||
{
|
{
|
||||||
/*bool ret = false;
|
bool ret = false;
|
||||||
if (!eglBuffer || !vcBuffer || (width != bufferLastWidth && height != bufferLastHeight && rgb32 != bufferLastRgb32))
|
|
||||||
|
if (index >= MAX_EGLIMAGE_TEXTURES)
|
||||||
{
|
{
|
||||||
ret = true;
|
*image_handle = NULL;
|
||||||
|
return false;
|
||||||
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);
|
eglBindAPI(EGL_OPENVG_API);
|
||||||
*image_handle = eglBuffer;
|
eglMakeCurrent(g_egl_dpy, g_pbuff_surf, g_pbuff_surf, g_eglimage_ctx);
|
||||||
|
|
||||||
return ret;*/
|
if (!eglBuffer[index] || !g_egl_vgimage[index])
|
||||||
return false;
|
{
|
||||||
|
g_egl_vgimage[index] = vgCreateImage(VG_sXRGB_8888, g_egl_res, g_egl_res, g_smooth ? VG_IMAGE_QUALITY_BETTER : VG_IMAGE_QUALITY_NONANTIALIASED);
|
||||||
|
eglBuffer[index] = peglCreateImageKHR(g_egl_dpy, g_eglimage_ctx, EGL_VG_PARENT_IMAGE_KHR, (EGLClientBuffer)g_egl_vgimage[index], NULL);
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
vgImageSubData(g_egl_vgimage[index], frame, pitch, (rgb32 ? VG_sXRGB_8888 : VG_sARGB_1555), 0, 0, width, height);
|
||||||
|
*image_handle = eglBuffer[index];
|
||||||
|
|
||||||
|
gfx_ctx_bind_api(g_api);
|
||||||
|
eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
const gfx_ctx_driver_t gfx_ctx_videocore = {
|
const gfx_ctx_driver_t gfx_ctx_videocore = {
|
||||||
|
@ -359,7 +467,7 @@ const gfx_ctx_driver_t gfx_ctx_videocore = {
|
||||||
gfx_ctx_swap_buffers,
|
gfx_ctx_swap_buffers,
|
||||||
gfx_ctx_input_driver,
|
gfx_ctx_input_driver,
|
||||||
gfx_ctx_get_proc_address,
|
gfx_ctx_get_proc_address,
|
||||||
gfx_ctx_can_egl_image_buffer,
|
gfx_ctx_init_egl_image_buffer,
|
||||||
gfx_ctx_write_egl_image,
|
gfx_ctx_write_egl_image,
|
||||||
"videocore",
|
"videocore",
|
||||||
};
|
};
|
||||||
|
|
|
@ -404,12 +404,12 @@ static bool gfx_ctx_bind_api(enum gfx_ctx_api api)
|
||||||
return api == GFX_CTX_OPENGL_API;
|
return api == GFX_CTX_OPENGL_API;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_can_egl_image_buffer(void)
|
static bool gfx_ctx_init_egl_image_buffer(const video_info_t *video)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, void **image_handle)
|
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, unsigned index, void **image_handle)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -429,7 +429,7 @@ const gfx_ctx_driver_t gfx_ctx_wgl = {
|
||||||
gfx_ctx_swap_buffers,
|
gfx_ctx_swap_buffers,
|
||||||
gfx_ctx_input_driver,
|
gfx_ctx_input_driver,
|
||||||
gfx_ctx_get_proc_address,
|
gfx_ctx_get_proc_address,
|
||||||
gfx_ctx_can_egl_image_buffer,
|
gfx_ctx_init_egl_image_buffer,
|
||||||
gfx_ctx_write_egl_image,
|
gfx_ctx_write_egl_image,
|
||||||
"wgl",
|
"wgl",
|
||||||
};
|
};
|
||||||
|
|
|
@ -525,12 +525,12 @@ int gfx_ctx_xdk_check_resolution(unsigned resolution_id)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_can_egl_image_buffer(void)
|
static bool gfx_ctx_init_egl_image_buffer(const video_info_t *video)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, void **image_handle)
|
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, unsigned index, void **image_handle)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -550,7 +550,7 @@ const gfx_ctx_driver_t gfx_ctx_xdk = {
|
||||||
gfx_ctx_xdk_swap_buffers,
|
gfx_ctx_xdk_swap_buffers,
|
||||||
gfx_ctx_xdk_input_driver,
|
gfx_ctx_xdk_input_driver,
|
||||||
NULL,
|
NULL,
|
||||||
gfx_ctx_can_egl_image_buffer,
|
gfx_ctx_init_egl_image_buffer,
|
||||||
gfx_ctx_write_egl_image,
|
gfx_ctx_write_egl_image,
|
||||||
"xdk",
|
"xdk",
|
||||||
|
|
||||||
|
|
|
@ -503,12 +503,12 @@ static bool gfx_ctx_bind_api(enum gfx_ctx_api api)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_can_egl_image_buffer(void)
|
static bool gfx_ctx_init_egl_image_buffer(const video_info_t *video)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, void **image_handle)
|
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, unsigned index, void **image_handle)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -528,7 +528,7 @@ const gfx_ctx_driver_t gfx_ctx_x_egl = {
|
||||||
gfx_ctx_swap_buffers,
|
gfx_ctx_swap_buffers,
|
||||||
gfx_ctx_input_driver,
|
gfx_ctx_input_driver,
|
||||||
gfx_ctx_get_proc_address,
|
gfx_ctx_get_proc_address,
|
||||||
gfx_ctx_can_egl_image_buffer,
|
gfx_ctx_init_egl_image_buffer,
|
||||||
gfx_ctx_write_egl_image,
|
gfx_ctx_write_egl_image,
|
||||||
"x-egl",
|
"x-egl",
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MAX_EGLIMAGE_TEXTURES 32
|
||||||
|
|
||||||
enum gfx_ctx_api
|
enum gfx_ctx_api
|
||||||
{
|
{
|
||||||
GFX_CTX_OPENGL_API,
|
GFX_CTX_OPENGL_API,
|
||||||
|
@ -80,12 +82,12 @@ typedef struct gfx_ctx_driver
|
||||||
// Wraps whatever gl_proc_address() there is.
|
// Wraps whatever gl_proc_address() there is.
|
||||||
gfx_ctx_proc_t (*get_proc_address)(const char*);
|
gfx_ctx_proc_t (*get_proc_address)(const char*);
|
||||||
|
|
||||||
// Returns true if this context supports EGL Image buffers for screen drawing.
|
// Returns true if this context supports EGLImage buffers for screen drawing and was initalized correctly.
|
||||||
bool (*can_egl_image_buffer)(void);
|
bool (*init_egl_image_buffer)(const video_info_t*);
|
||||||
|
|
||||||
// Writes the frame to the EGL Image and sets image_handle to it. Returns true if a new image handle is created.
|
// Writes the frame to the EGLImage 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.
|
// Always returns true the first time it's called for a new index. 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);
|
bool (*write_egl_image)(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, unsigned index, void **image_handle);
|
||||||
|
|
||||||
// Human readable string.
|
// Human readable string.
|
||||||
const char *ident;
|
const char *ident;
|
||||||
|
|
72
gfx/gl.c
72
gfx/gl.c
|
@ -94,13 +94,23 @@ const GLfloat *default_vertex_ptr = vertexes_flipped;
|
||||||
memcpy(&(pgl##SYM), &sym, sizeof(sym)); \
|
memcpy(&(pgl##SYM), &sym, sizeof(sym)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_EGL
|
||||||
|
static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC pglEGLImageTargetTexture2DOES;
|
||||||
|
|
||||||
|
static bool load_eglimage_proc(gl_t *gl)
|
||||||
|
{
|
||||||
|
LOAD_GL_SYM(EGLImageTargetTexture2DOES);
|
||||||
|
return pglEGLImageTargetTexture2DOES;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_FBO
|
#ifdef HAVE_FBO
|
||||||
#if defined(_WIN32) && !defined(RARCH_CONSOLE)
|
#if defined(_WIN32) && !defined(RARCH_CONSOLE)
|
||||||
static PFNGLGENFRAMEBUFFERSPROC pglGenFramebuffers = NULL;
|
static PFNGLGENFRAMEBUFFERSPROC pglGenFramebuffers;
|
||||||
static PFNGLBINDFRAMEBUFFERPROC pglBindFramebuffer = NULL;
|
static PFNGLBINDFRAMEBUFFERPROC pglBindFramebuffer;
|
||||||
static PFNGLFRAMEBUFFERTEXTURE2DPROC pglFramebufferTexture2D = NULL;
|
static PFNGLFRAMEBUFFERTEXTURE2DPROC pglFramebufferTexture2D;
|
||||||
static PFNGLCHECKFRAMEBUFFERSTATUSPROC pglCheckFramebufferStatus = NULL;
|
static PFNGLCHECKFRAMEBUFFERSTATUSPROC pglCheckFramebufferStatus;
|
||||||
static PFNGLDELETEFRAMEBUFFERSPROC pglDeleteFramebuffers = NULL;
|
static PFNGLDELETEFRAMEBUFFERSPROC pglDeleteFramebuffers;
|
||||||
|
|
||||||
static bool load_fbo_proc(gl_t *gl)
|
static bool load_fbo_proc(gl_t *gl)
|
||||||
{
|
{
|
||||||
|
@ -926,22 +936,41 @@ static void gl_init_textures(gl_t *gl)
|
||||||
static inline void gl_copy_frame(gl_t *gl, const void *frame, unsigned width, unsigned height, unsigned pitch)
|
static inline void gl_copy_frame(gl_t *gl, const void *frame, unsigned width, unsigned height, unsigned pitch)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_OPENGLES2
|
#ifdef HAVE_OPENGLES2
|
||||||
// No GL_UNPACK_ROW_LENGTH ;(
|
#ifdef HAVE_EGL
|
||||||
unsigned pitch_width = pitch / gl->base_size;
|
if (gl->egl_images)
|
||||||
if (width == pitch_width) // Happy path :D
|
|
||||||
{
|
{
|
||||||
glTexSubImage2D(GL_TEXTURE_2D,
|
EGLImageKHR img = 0;
|
||||||
0, 0, 0, width, height, gl->texture_type,
|
bool new_egl = gl->ctx_driver->write_egl_image(frame, width, height, pitch, (gl->base_size == 4), gl->tex_index, &img);
|
||||||
gl->texture_fmt, frame);
|
|
||||||
|
if (img == EGL_NO_IMAGE_KHR)
|
||||||
|
{
|
||||||
|
RARCH_ERR("[GL]: Failed to create EGL image.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_egl)
|
||||||
|
pglEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)img);
|
||||||
}
|
}
|
||||||
else // Slower path.
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
const uint8_t *src = (const uint8_t*)frame;
|
// No GL_UNPACK_ROW_LENGTH ;(
|
||||||
for (unsigned h = 0; h < height; h++, src += pitch)
|
unsigned pitch_width = pitch / gl->base_size;
|
||||||
|
if (width == pitch_width) // Happy path :D
|
||||||
{
|
{
|
||||||
glTexSubImage2D(GL_TEXTURE_2D,
|
glTexSubImage2D(GL_TEXTURE_2D,
|
||||||
0, 0, h, width, 1, gl->texture_type,
|
0, 0, 0, width, height, gl->texture_type,
|
||||||
gl->texture_fmt, src);
|
gl->texture_fmt, frame);
|
||||||
|
}
|
||||||
|
else // Slower path.
|
||||||
|
{
|
||||||
|
const uint8_t *src = (const uint8_t*)frame;
|
||||||
|
for (unsigned h = 0; h < height; h++, src += pitch)
|
||||||
|
{
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D,
|
||||||
|
0, 0, h, width, 1, gl->texture_type,
|
||||||
|
gl->texture_fmt, src);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -957,7 +986,6 @@ static inline void gl_copy_frame(gl_t *gl, const void *frame, unsigned width, un
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / gl->base_size);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / gl->base_size);
|
||||||
|
|
||||||
glTexSubImage2D(GL_TEXTURE_2D,
|
glTexSubImage2D(GL_TEXTURE_2D,
|
||||||
0, 0, 0, width, height, gl->texture_type,
|
0, 0, 0, width, height, gl->texture_type,
|
||||||
gl->texture_fmt, frame);
|
gl->texture_fmt, frame);
|
||||||
|
@ -1024,6 +1052,9 @@ static void gl_render_menu(gl_t *gl)
|
||||||
|
|
||||||
static bool gl_frame(void *data, const void *frame, unsigned width, unsigned height, unsigned pitch, const char *msg)
|
static bool gl_frame(void *data, const void *frame, unsigned width, unsigned height, unsigned pitch, const char *msg)
|
||||||
{
|
{
|
||||||
|
RARCH_PERFORMANCE_INIT(frame_run);
|
||||||
|
RARCH_PERFORMANCE_START(frame_run);
|
||||||
|
|
||||||
gl_t *gl = (gl_t*)data;
|
gl_t *gl = (gl_t*)data;
|
||||||
|
|
||||||
gl_shader_use(1);
|
gl_shader_use(1);
|
||||||
|
@ -1095,6 +1126,9 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei
|
||||||
gl->ctx_driver->update_window_title(false);
|
gl->ctx_driver->update_window_title(false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
RARCH_PERFORMANCE_STOP(frame_run);
|
||||||
|
RARCH_PERFORMANCE_LOG("gl_frame", frame_run);
|
||||||
|
|
||||||
#ifdef RARCH_CONSOLE
|
#ifdef RARCH_CONSOLE
|
||||||
if (!gl->block_swap)
|
if (!gl->block_swap)
|
||||||
#endif
|
#endif
|
||||||
|
@ -1375,6 +1409,10 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_EGL
|
||||||
|
gl->egl_images = load_eglimage_proc(gl) && gl->ctx_driver->init_egl_image_buffer(video);
|
||||||
|
#endif
|
||||||
|
|
||||||
return gl;
|
return gl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,11 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_EGL
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#include <EGL/eglext.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
#include <OpenGL/gl.h>
|
#include <OpenGL/gl.h>
|
||||||
#include <OpenGL/glext.h>
|
#include <OpenGL/glext.h>
|
||||||
|
@ -36,8 +41,6 @@
|
||||||
#include <PSGL/psglu.h>
|
#include <PSGL/psglu.h>
|
||||||
#include <GLES/glext.h>
|
#include <GLES/glext.h>
|
||||||
#elif defined(HAVE_OPENGL_MODERN)
|
#elif defined(HAVE_OPENGL_MODERN)
|
||||||
#include <EGL/egl.h>
|
|
||||||
#include <EGL/eglext.h>
|
|
||||||
#include <GL3/gl3.h>
|
#include <GL3/gl3.h>
|
||||||
#include <GL3/gl3ext.h>
|
#include <GL3/gl3ext.h>
|
||||||
#elif defined(HAVE_OPENGLES2)
|
#elif defined(HAVE_OPENGLES2)
|
||||||
|
@ -234,6 +237,10 @@ typedef struct gl
|
||||||
bool menu_render;
|
bool menu_render;
|
||||||
GLuint menu_texture_id;
|
GLuint menu_texture_id;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_EGL
|
||||||
|
bool egl_images;
|
||||||
|
#endif
|
||||||
} gl_t;
|
} gl_t;
|
||||||
|
|
||||||
// Windows ... <_<
|
// Windows ... <_<
|
||||||
|
|
7
gfx/vg.c
7
gfx/vg.c
|
@ -174,7 +174,7 @@ static void *vg_init(const video_info_t *video, const input_driver_t **input, vo
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (vg_query_extension("KHR_EGL_image") && vg->driver->can_egl_image_buffer())
|
if (vg_query_extension("KHR_EGL_image") && vg->driver->init_egl_image_buffer(video))
|
||||||
{
|
{
|
||||||
pvgCreateEGLImageTargetKHR = (PFNVGCREATEEGLIMAGETARGETKHRPROC)vg->driver->get_proc_address("vgCreateEGLImageTargetKHR");
|
pvgCreateEGLImageTargetKHR = (PFNVGCREATEEGLIMAGETARGETKHRPROC)vg->driver->get_proc_address("vgCreateEGLImageTargetKHR");
|
||||||
|
|
||||||
|
@ -350,17 +350,16 @@ static void vg_copy_frame(void *data, const void *frame, unsigned width, unsigne
|
||||||
if (vg->mEglImageBuf)
|
if (vg->mEglImageBuf)
|
||||||
{
|
{
|
||||||
EGLImageKHR img = 0;
|
EGLImageKHR img = 0;
|
||||||
bool new_egl = vg->driver->write_egl_image(frame, width, height, pitch, (vg->mTexType == VG_sXRGB_8888), &img);
|
bool new_egl = vg->driver->write_egl_image(frame, width, height, pitch, (vg->mTexType == VG_sXRGB_8888), 0, &img);
|
||||||
rarch_assert(img != EGL_NO_IMAGE_KHR);
|
rarch_assert(img != EGL_NO_IMAGE_KHR);
|
||||||
|
|
||||||
if (new_egl)
|
if (new_egl)
|
||||||
{
|
{
|
||||||
vgDestroyImage(vg->mImage);
|
vgDestroyImage(vg->mImage);
|
||||||
RARCH_LOG("[VG] %08x\n", img);
|
|
||||||
vg->mImage = pvgCreateEGLImageTargetKHR((VGeglImageKHR) img);
|
vg->mImage = pvgCreateEGLImageTargetKHR((VGeglImageKHR) img);
|
||||||
if (!vg->mImage)
|
if (!vg->mImage)
|
||||||
{
|
{
|
||||||
RARCH_ERR("[VG] Error creating image: %08x\n", vgGetError());
|
RARCH_ERR("[VG:EGLImage] Error creating image: %08x\n", vgGetError());
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
vg->last_egl_image = img;
|
vg->last_egl_image = img;
|
||||||
|
|
Loading…
Reference in New Issue