diff --git a/gfx/context/androidegl_ctx.c b/gfx/context/androidegl_ctx.c index ec631fa613..a687eba0c4 100644 --- a/gfx/context/androidegl_ctx.c +++ b/gfx/context/androidegl_ctx.c @@ -307,7 +307,7 @@ static bool gfx_ctx_has_focus(void) 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; } @@ -332,7 +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_init_egl_image_buffer, gfx_ctx_write_egl_image, "android", }; diff --git a/gfx/context/drm_egl_ctx.c b/gfx/context/drm_egl_ctx.c index 614f7f00e5..6f0a7646d8 100644 --- a/gfx/context/drm_egl_ctx.c +++ b/gfx/context/drm_egl_ctx.c @@ -625,7 +625,7 @@ 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; } @@ -650,7 +650,7 @@ 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_init_egl_image_buffer, gfx_ctx_write_egl_image, "drm-egl", }; diff --git a/gfx/context/glx_ctx.c b/gfx/context/glx_ctx.c index e1f452447b..4dacbe1bb5 100644 --- a/gfx/context/glx_ctx.c +++ b/gfx/context/glx_ctx.c @@ -462,7 +462,7 @@ static bool gfx_ctx_bind_api(enum gfx_ctx_api 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; } @@ -487,7 +487,7 @@ 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_init_egl_image_buffer, gfx_ctx_write_egl_image, "glx", }; diff --git a/gfx/context/ps3_ctx.c b/gfx/context/ps3_ctx.c index f6e7f97149..9fae55c697 100644 --- a/gfx/context/ps3_ctx.c +++ b/gfx/context/ps3_ctx.c @@ -378,7 +378,7 @@ static bool gfx_ctx_bind_api(enum gfx_ctx_api 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; } @@ -403,7 +403,7 @@ 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_init_egl_image_buffer, gfx_ctx_write_egl_image, "ps3", diff --git a/gfx/context/sdl_ctx.c b/gfx/context/sdl_ctx.c index ca984b8ea6..7db4f694d4 100644 --- a/gfx/context/sdl_ctx.c +++ b/gfx/context/sdl_ctx.c @@ -316,7 +316,7 @@ static bool gfx_ctx_bind_api(enum gfx_ctx_api 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; } @@ -341,7 +341,7 @@ 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_init_egl_image_buffer, gfx_ctx_write_egl_image, "sdl-gl", }; diff --git a/gfx/context/vc_egl_ctx.c b/gfx/context/vc_egl_ctx.c index 030cd2bdb0..4d866c991e 100644 --- a/gfx/context/vc_egl_ctx.c +++ b/gfx/context/vc_egl_ctx.c @@ -34,6 +34,7 @@ #include #include #include +#include #include static EGLContext g_egl_ctx; @@ -46,15 +47,13 @@ static bool g_inited; static unsigned g_interval; 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 EGLImageKHR eglBuffer; -static DISPMANX_RESOURCE_HANDLE_T vcBuffer; -static VC_RECT_T bufferRect; -static unsigned bufferLastWidth; -static unsigned bufferLastHeight; -static bool bufferLastRgb32; +static EGLImageKHR eglBuffer; +static EGLContext g_eglimage_ctx; +static EGLSurface g_pbuff_surf; +static VGImage g_egl_vgimage; PFNEGLCREATEIMAGEKHRPROC peglCreateImageKHR; PFNEGLDESTROYIMAGEKHRPROC peglDestroyImageKHR; @@ -67,7 +66,7 @@ static inline bool gfx_ctx_egl_query_extension(const char *ext) ext, ret ? "exists" : "doesn't exist"); return ret; -}*/ +} static void sighandler(int sig) { @@ -238,24 +237,65 @@ static bool gfx_ctx_set_video_mode( static void gfx_ctx_destroy(void) { + if (g_egl_dpy) { + if (eglBuffer && peglDestroyImageKHR) + { + eglBindAPI(EGL_OPENGL_VG_API); + eglMakeCurrent(g_egl_dpy, g_pbuff_surf, g_pbuff_surf, g_eglimage_ctx); + peglDestroyImageKHR(e_egl_dpy, eglBuffer); + } + + if (g_egl_vgimage) + { + eglBindAPI(EGL_OPENGL_VG_API); + eglMakeCurrent(g_egl_dpy, g_pbuff_surf, g_pbuff_surf, g_eglimage_ctx); + vgDestroyImage(g_egl_vgimage); + } + if (g_egl_ctx) { + gfx_ctx_bind_api(g_api); eglMakeCurrent(g_egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroyContext(g_egl_dpy, g_egl_ctx); } + if (g_eglimage_ctx) + { + eglBindAPI(EGL_OPENGL_VG_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) + { + gfx_ctx_bind_api(g_api); eglDestroySurface(g_egl_dpy, g_egl_surf); + } + + if (g_pbuff_surf) + { + eglBindAPI(EGL_OPENGL_VG_API); + eglDestroySurface(g_egl_dpy, g_pbuff_surf); + } + + eglBindAPI(EGL_OPENGL_VG_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); } - g_egl_ctx = NULL; - g_egl_surf = NULL; - g_egl_dpy = NULL; - g_config = 0; - g_inited = false; + g_egl_ctx = NULL; + g_eglimage_ctx = NULL + g_egl_surf = NULL; + g_pbuff_surf = NULL; + g_egl_dpy = NULL; + eglBuffer = NULL; + g_egl_vgimage = NULL; + g_config = 0; + g_inited = false; } static void gfx_ctx_input_driver(const input_driver_t **input, void **input_data) @@ -300,48 +340,102 @@ static float gfx_ctx_translate_aspect(unsigned width, unsigned 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"); - return peglCreateImageKHR && peglDestroyImageKHR && gfx_ctx_egl_query_extension("KHR_image");*/ + + if (!peglCreateImageKHR || !peglDestroyImageKHR || !gfx_ctx_egl_query_extension("KHR_image")) + { + return false; + } + + unsigned res = video->input_scale * RARCH_SCALE_BASE; + + EGLint pbufsurface_list[] = + { + EGL_WIDTH, res, + EGL_HEIGHT, 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; + } + + 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; + } + + g_egl_vgimage = vgCreateImage(VG_sXRGB_8888, res, res, video->smooth ? VG_IMAGE_QUALITY_BETTER : VG_IMAGE_QUALITY_NONANTIALIASED); + eglBuffer = peglCreateImageKHR(g_egl_dpy, g_eglimage_ctx, EGL_VG_PARENT_IMAGE_KHR, (EGLClientBuffer)g_egl_vgimage, NULL); + + gfx_ctx_bind_api(g_api); + eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx); + + 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; } static 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; + static bool first = true; + eglBindAPI(EGL_OPENVG_API); + eglMakeCurrent(g_egl_dpy, g_pbuff_surf, g_pbuff_surf, g_eglimage_ctx); - 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); + vgImageSubData(g_egl_vgimage, frame, pitch, (rgb32 ? VG_sXRGB_8888 : VG_sARGB_1555), 0, 0, width, height); *image_handle = eglBuffer; - return ret;*/ - return false; + gfx_ctx_bind_api(g_api); + eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx); + + if (first) + { + first = false; + return true; + } + else + { + return false; + } } const gfx_ctx_driver_t gfx_ctx_videocore = { @@ -359,7 +453,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_init_egl_image_buffer, gfx_ctx_write_egl_image, "videocore", }; diff --git a/gfx/context/wgl_ctx.c b/gfx/context/wgl_ctx.c index b458e7e835..e15fecf502 100644 --- a/gfx/context/wgl_ctx.c +++ b/gfx/context/wgl_ctx.c @@ -404,7 +404,7 @@ static bool gfx_ctx_bind_api(enum gfx_ctx_api 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; } @@ -429,7 +429,7 @@ 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_init_egl_image_buffer, gfx_ctx_write_egl_image, "wgl", }; diff --git a/gfx/context/xdk_ctx.c b/gfx/context/xdk_ctx.c index db268579fc..ec16af9adc 100644 --- a/gfx/context/xdk_ctx.c +++ b/gfx/context/xdk_ctx.c @@ -525,7 +525,7 @@ int gfx_ctx_xdk_check_resolution(unsigned resolution_id) 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; } @@ -550,7 +550,7 @@ 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_init_egl_image_buffer, gfx_ctx_write_egl_image, "xdk", diff --git a/gfx/context/xegl_ctx.c b/gfx/context/xegl_ctx.c index ca03c981be..f454f7efb8 100644 --- a/gfx/context/xegl_ctx.c +++ b/gfx/context/xegl_ctx.c @@ -503,7 +503,7 @@ 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; } @@ -528,7 +528,7 @@ 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_init_egl_image_buffer, gfx_ctx_write_egl_image, "x-egl", }; diff --git a/gfx/gfx_context.h b/gfx/gfx_context.h index 5571bd0798..fb756a9e98 100644 --- a/gfx/gfx_context.h +++ b/gfx/gfx_context.h @@ -80,8 +80,8 @@ 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); + // Returns true if this context supports EGL Image buffers for screen drawing and was initalized correctly. + 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. // Always returns true the first time it's called. The graphics core must handle a change in the handle correctly. diff --git a/gfx/vg.c b/gfx/vg.c index acd1d9360f..98d3a945d1 100644 --- a/gfx/vg.c +++ b/gfx/vg.c @@ -174,7 +174,7 @@ 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()) + if (vg_query_extension("KHR_EGL_image") && vg->driver->init_egl_image_buffer(video)) { pvgCreateEGLImageTargetKHR = (PFNVGCREATEEGLIMAGETARGETKHRPROC)vg->driver->get_proc_address("vgCreateEGLImageTargetKHR"); @@ -356,7 +356,7 @@ static void vg_copy_frame(void *data, const void *frame, unsigned width, unsigne if (new_egl) { vgDestroyImage(vg->mImage); - RARCH_LOG("[VG] %08x\n", img); + RARCH_LOG("[VG] %08x\n", (unsigned) img); vg->mImage = pvgCreateEGLImageTargetKHR((VGeglImageKHR) img); if (!vg->mImage) {