diff --git a/gfx/drivers_context/cgl_ctx.c b/gfx/drivers_context/cgl_ctx.c
new file mode 100644
index 0000000000..10de6a83c5
--- /dev/null
+++ b/gfx/drivers_context/cgl_ctx.c
@@ -0,0 +1,253 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2015 - Daniel De Matteis
+ *
+ * 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 .
+ */
+
+/* Apple CGL context. */
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "../../driver.h"
+#include "../video_context_driver.h"
+#include "../video_monitor.h"
+
+typedef int CGSConnectionID;
+typedef int CGSWindowID;
+typedef int CGSSurfaceID;
+
+/* Undocumented CGS */
+extern CGSConnectionID CGSMainConnectionID(void);
+extern CGError CGSAddSurface(CGSConnectionID cid, CGWindowID wid, CGSSurfaceID *sid);
+extern CGError CGSSetSurfaceBounds(CGSConnectionID cid, CGWindowID wid, CGSSurfaceID sid, CGRect rect);
+extern CGError CGSOrderSurface(CGSConnectionID cid, CGWindowID wid, CGSSurface sid, int a, int b);
+
+/* Undocumented CGL */
+extern CGLError CGLSetSurface(CGLContextObj gl, CGSConnectionID, cid, CGSWindowID wid, CGSSurfaceID sid);
+
+typedef struct gfx_ctx_cgl_data
+{
+ CGLContextObj glCtx;
+ CGDirectDisplayID displayID;
+ int width, height;
+} gfx_ctx_cgl_data_t;
+
+static void gfx_ctx_cgl_swap_interval(void *data, unsigned interval)
+{
+ gfx_ctx_cgl_data_t *cgl = (gfx_ctx_cgl_data_t*)data;
+ GLint params = interval;
+
+ CGLSetParameter(cgl->glCtx, kCGLCPSwapInterval, ¶ms);
+}
+
+static void gfx_ctx_cgl_check_window(void *data, bool *quit,
+ bool *resize, unsigned *width, unsigned *height, unsigned frame_count)
+{
+ (void)frame_count;
+ (void)data;
+ (void)quit;
+ (void)width;
+ (void)height;
+ (void)resize;
+}
+
+static void gfx_ctx_cgl_swap_buffers(void *data)
+{
+ gfx_ctx_cgl_data_t *cgl = (gfx_ctx_cgl_data_t*)data;
+
+ CGLFlushDrawable(cgl->glCtx);
+}
+
+static void gfx_ctx_cgl_set_resize(void *data, unsigned width, unsigned height)
+{
+ (void)data;
+ (void)width;
+ (void)height;
+}
+
+static void gfx_ctx_cgl_update_window_title(void *data)
+{
+ (void)data;
+}
+
+static void gfx_ctx_cgl_get_video_size(void *data, unsigned *width, unsigned *height)
+{
+ (void)data;
+ *width = 320;
+ *height = 240;
+}
+
+static bool gfx_ctx_cgl_set_video_mode(void *data,
+ unsigned width, unsigned height,
+ bool fullscreen)
+{
+ (void)data;
+ (void)width;
+ (void)height;
+ (void)fullscreen;
+
+ return true;
+}
+
+static void gfx_ctx_cgl_destroy(void *data)
+{
+ gfx_ctx_cgl_data_t *cgl = (gfx_ctx_cgl_data_t*)data;
+
+ if (cgl->glCtx)
+ {
+ CGLSetCurrentContext(NULL);
+ CGLDestroyContext(cgl->glCtx);
+ }
+
+ if (cgl->displayID)
+ CGDisplayRelease(cgl->displayID);
+
+ if (cgl)
+ free(cgl);
+}
+
+static void gfx_ctx_cgl_input_driver(void *data, const input_driver_t **input, void **input_data)
+{
+ (void)data;
+ (void)input;
+ (void)input_data;
+}
+
+static bool gfx_ctx_cgl_has_focus(void *data)
+{
+ (void)data;
+ return true;
+}
+
+static bool gfx_ctx_cgl_suppress_screensaver(void *data, bool enable)
+{
+ (void)data;
+ (void)enable;
+ return false;
+}
+
+static bool gfx_ctx_cgl_has_windowed(void *data)
+{
+ (void)data;
+ return true;
+}
+
+static bool gfx_ctx_cgl_bind_api(void *data, enum gfx_ctx_api api, unsigned major, unsigned minor)
+{
+ (void)data;
+ (void)api;
+ (void)major;
+ (void)minor;
+
+ return true;
+}
+
+static void gfx_ctx_cgl_show_mouse(void *data, bool state)
+{
+ (void)data;
+ (void)state;
+}
+
+static void gfx_ctx_cgl_bind_hw_render(void *data, bool enable)
+{
+ gfx_ctx_cgl_data_t *cgl = (gfx_ctx_cgl_data_t*)data;
+
+ (void)enable;
+
+ CGLSetCurrentContext(cgl->glCtx);
+
+ /* TODO - needs to handle HW render context too */
+}
+
+static CGLContextObj gfx_ctx_cgl_init_create(void)
+{
+ CGLint num;
+ CGLPixelFormatObj pix;
+ CGLContextObj glCtx = NULL;
+ CGLPixelFormatAttribute attributes[] = {
+ kCGLPFAAccelerated,
+ kCGLPFADoublebuffer,
+ (CGLPixelFormatAttribute)0
+ };
+
+ CGLChoosePixelFormat(attributes, &pix, &num);
+ CGLCreateContext(pix, NULL, &glCtx);
+ CGLDestroyPixelFormat(pix);
+
+ return glCtx;
+}
+
+static bool gfx_ctx_cgl_init(void *data)
+{
+ CGError err;
+ gfx_ctx_cgl_data_t *cgl = (gfx_ctx_cgl_data_t*)calloc(1, sizeof(gfx_ctx_cgl_data_t));
+
+ if (!cgl)
+ goto false;
+
+ cgl->displayID = CGMainDisplayID();
+
+ err = CGDisplayCapture(cgl->displayID);
+
+ if (err != kCGErrorSuccess)
+ goto error;
+
+ cgl->glCtx = gfx_ctx_cgl_init_create();
+
+ if (!cgl->glCtx)
+ goto error;
+
+ driver->video_context_data = cgl;
+
+ return true;
+
+error:
+ gfx_ctx_cgl_destroy(cgl);
+
+ return false;
+}
+
+const gfx_ctx_driver_t gfx_ctx_cgl = {
+ gfx_ctx_cgl_init,
+ gfx_ctx_cgl_destroy,
+ gfx_ctx_cgl_bind_api,
+ gfx_ctx_cgl_swap_interval,
+ gfx_ctx_cgl_set_video_mode,
+ gfx_ctx_cgl_get_video_size,
+ NULL, /* get_video_output_size */
+ NULL, /* get_video_output_prev */
+ NULL, /* get_video_output_next */
+ NULL, /* get_metrics */
+ NULL,
+ gfx_ctx_cgl_update_window_title,
+ gfx_ctx_cgl_check_window,
+ gfx_ctx_cgl_set_resize,
+ gfx_ctx_cgl_has_focus,
+ gfx_ctx_cgl_suppress_screensaver,
+ gfx_ctx_cgl_has_windowed,
+ gfx_ctx_cgl_swap_buffers,
+ gfx_ctx_cgl_input_driver,
+ NULL,
+ NULL,
+ NULL,
+ gfx_ctx_cgl_show_mouse,
+ "cgl",
+ gfx_ctx_cgl_bind_hw_render,
+};
diff --git a/gfx/video_context_driver.h b/gfx/video_context_driver.h
index 2dab64fca5..c081dabbc3 100644
--- a/gfx/video_context_driver.h
+++ b/gfx/video_context_driver.h
@@ -163,6 +163,7 @@ extern const gfx_ctx_driver_t gfx_ctx_ps3;
extern const gfx_ctx_driver_t gfx_ctx_wgl;
extern const gfx_ctx_driver_t gfx_ctx_videocore;
extern const gfx_ctx_driver_t gfx_ctx_bbqnx;
+extern const gfx_ctx_driver_t gfx_ctx_cgl;
extern const gfx_ctx_driver_t gfx_ctx_cocoagl;
extern const gfx_ctx_driver_t gfx_ctx_emscripten;
extern const gfx_ctx_driver_t gfx_ctx_null;