/* * Cogl * * An object oriented GL/GLES Abstraction/Utility Layer * * Copyright (C) 2011 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see * . * * * Authors: * Robert Bragg * Neil Roberts */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "cogl-winsys-egl-null-private.h" #include "cogl-winsys-egl-private.h" #include "cogl-renderer-private.h" #include "cogl-framebuffer-private.h" #include "cogl-onscreen-private.h" static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable; typedef struct _CoglDisplayNull { int egl_surface_width; int egl_surface_height; CoglBool have_onscreen; } CoglDisplayNull; static void _cogl_winsys_renderer_disconnect (CoglRenderer *renderer) { CoglRendererEGL *egl_renderer = renderer->winsys; eglTerminate (egl_renderer->edpy); g_slice_free (CoglRendererEGL, egl_renderer); } static CoglBool _cogl_winsys_renderer_connect (CoglRenderer *renderer, GError **error) { CoglRendererEGL *egl_renderer; renderer->winsys = g_slice_new0 (CoglRendererEGL); egl_renderer = renderer->winsys; egl_renderer->platform_vtable = &_cogl_winsys_egl_vtable; egl_renderer->edpy = eglGetDisplay (EGL_DEFAULT_DISPLAY); if (!_cogl_winsys_egl_renderer_connect_common (renderer, error)) goto error; return TRUE; error: _cogl_winsys_renderer_disconnect (renderer); return FALSE; } static CoglBool _cogl_winsys_egl_context_created (CoglDisplay *display, GError **error) { CoglRenderer *renderer = display->renderer; CoglRendererEGL *egl_renderer = renderer->winsys; CoglDisplayEGL *egl_display = display->winsys; CoglDisplayNull *null_display = egl_display->platform; const char *error_message; egl_display->egl_surface = eglCreateWindowSurface (egl_renderer->edpy, egl_display->egl_config, (NativeWindowType) NULL, NULL); if (egl_display->egl_surface == EGL_NO_SURFACE) { error_message = "Unable to create EGL window surface"; goto fail; } if (!_cogl_winsys_egl_make_current (display, egl_display->egl_surface, egl_display->egl_surface, egl_display->egl_context)) { error_message = "Unable to eglMakeCurrent with egl surface"; goto fail; } eglQuerySurface (egl_renderer->edpy, egl_display->egl_surface, EGL_WIDTH, &null_display->egl_surface_width); eglQuerySurface (egl_renderer->edpy, egl_display->egl_surface, EGL_HEIGHT, &null_display->egl_surface_height); return TRUE; fail: g_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_CONTEXT, "%s", error_message); return FALSE; } static CoglBool _cogl_winsys_egl_display_setup (CoglDisplay *display, GError **error) { CoglDisplayEGL *egl_display = display->winsys; CoglDisplayNull *null_display; null_display = g_slice_new0 (CoglDisplayNull); egl_display->platform = null_display; return TRUE; } static void _cogl_winsys_egl_display_destroy (CoglDisplay *display) { CoglDisplayEGL *egl_display = display->winsys; g_slice_free (CoglDisplayNull, egl_display->platform); } static void _cogl_winsys_egl_cleanup_context (CoglDisplay *display) { CoglRenderer *renderer = display->renderer; CoglRendererEGL *egl_renderer = renderer->winsys; CoglDisplayEGL *egl_display = display->winsys; if (egl_display->egl_surface != EGL_NO_SURFACE) { eglDestroySurface (egl_renderer->edpy, egl_display->egl_surface); egl_display->egl_surface = EGL_NO_SURFACE; } } static CoglBool _cogl_winsys_egl_onscreen_init (CoglOnscreen *onscreen, EGLConfig egl_config, GError **error) { CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); CoglContext *context = framebuffer->context; CoglDisplay *display = context->display; CoglDisplayEGL *egl_display = display->winsys; CoglDisplayNull *null_display = egl_display->platform; CoglOnscreenEGL *egl_onscreen = onscreen->winsys; if (null_display->have_onscreen) { g_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_ONSCREEN, "EGL platform only supports a single onscreen window"); return FALSE; } egl_onscreen->egl_surface = egl_display->egl_surface; _cogl_framebuffer_winsys_update_size (framebuffer, null_display->egl_surface_width, null_display->egl_surface_height); null_display->have_onscreen = TRUE; return TRUE; } static void _cogl_winsys_egl_onscreen_deinit (CoglOnscreen *onscreen) { CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); CoglContext *context = framebuffer->context; CoglDisplay *display = context->display; CoglDisplayEGL *egl_display = display->winsys; CoglDisplayNull *null_display = egl_display->platform; null_display->have_onscreen = FALSE; } static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable = { .display_setup = _cogl_winsys_egl_display_setup, .display_destroy = _cogl_winsys_egl_display_destroy, .context_created = _cogl_winsys_egl_context_created, .cleanup_context = _cogl_winsys_egl_cleanup_context, .onscreen_init = _cogl_winsys_egl_onscreen_init, .onscreen_deinit = _cogl_winsys_egl_onscreen_deinit }; const CoglWinsysVtable * _cogl_winsys_egl_null_get_vtable (void) { static CoglBool vtable_inited = FALSE; static CoglWinsysVtable vtable; if (!vtable_inited) { /* The EGL_NULL winsys is a subclass of the EGL winsys so we start by copying its vtable */ vtable = *_cogl_winsys_egl_get_vtable (); vtable.id = COGL_WINSYS_ID_EGL_NULL; vtable.name = "EGL_NULL"; vtable.renderer_connect = _cogl_winsys_renderer_connect; vtable.renderer_disconnect = _cogl_winsys_renderer_disconnect; vtable_inited = TRUE; } return &vtable; }