diff --git a/cogl/Makefile.am b/cogl/Makefile.am index 1e39005fd..a99ccd8e7 100644 --- a/cogl/Makefile.am +++ b/cogl/Makefile.am @@ -416,7 +416,8 @@ cogl_sources_c += \ endif if SUPPORT_EGL_PLATFORM_KMS cogl_experimental_h += \ - $(srcdir)/cogl-kms-renderer.h + $(srcdir)/cogl-kms-renderer.h \ + $(srcdir)/cogl-kms-display.h cogl_sources_c += \ $(srcdir)/winsys/cogl-winsys-egl-kms.c \ $(srcdir)/winsys/cogl-winsys-egl-kms-private.h diff --git a/cogl/cogl-kms-display.h b/cogl/cogl-kms-display.h new file mode 100644 index 000000000..012f871d0 --- /dev/null +++ b/cogl/cogl-kms-display.h @@ -0,0 +1,58 @@ + +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2012 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only <cogl/cogl.h> can be included directly." +#endif + +#ifndef __COGL_KMS_DISPLAY_H__ +#define __COGL_KMS_DISPLAY_H__ + +#include <cogl/cogl-types.h> +#include <cogl/cogl-display.h> + +G_BEGIN_DECLS + +/** + * cogl_kms_display_queue_modes_reset: + * @display: A #CoglDisplay + * + * Asks Cogl to explicitly reset the crtc output modes at the next + * #CoglOnscreen swap_buffers request. For applications that support + * VT switching they may want to re-assert the output modes when + * switching back to the applications VT since the modes are often not + * correctly restored automatically. + * + * <note>The @display must have been either explicitly setup via + * cogl_display_setup() or implicitily setup by having created a + * context using the @display</note> + * + * Since: 2.0 + * Stability: unstable + */ +void +cogl_kms_display_queue_modes_reset (CoglDisplay *display); + +G_END_DECLS +#endif /* __COGL_KMS_DISPLAY_H__ */ diff --git a/cogl/cogl.h b/cogl/cogl.h index 8663f9557..3f1eb5303 100644 --- a/cogl/cogl.h +++ b/cogl/cogl.h @@ -105,6 +105,7 @@ #include <cogl/cogl-poll.h> #if defined (COGL_HAS_EGL_PLATFORM_KMS_SUPPORT) #include <cogl/cogl-kms-renderer.h> +#include <cogl/cogl-kms-display.h> #endif #if COGL_HAS_WIN32_SUPPORT #include <cogl/cogl-win32-renderer.h> diff --git a/cogl/winsys/cogl-winsys-egl-kms.c b/cogl/winsys/cogl-winsys-egl-kms.c index 2fd391040..f5d1e28a6 100644 --- a/cogl/winsys/cogl-winsys-egl-kms.c +++ b/cogl/winsys/cogl-winsys-egl-kms.c @@ -50,6 +50,7 @@ #include "cogl-framebuffer-private.h" #include "cogl-onscreen-private.h" #include "cogl-kms-renderer.h" +#include "cogl-kms-display.h" static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable; @@ -76,6 +77,7 @@ typedef struct _CoglDisplayKMS { GList *outputs; int width, height; + gboolean pending_set_crtc; gboolean pending_swap_notify; } CoglDisplayKMS; @@ -356,23 +358,26 @@ find_output (int _index, return output; } -static gboolean -set_crtc (int fd, uint32_t fb_id, CoglOutputKMS *output, GError **error) +static void +setup_crtc_modes (CoglDisplay *display, int fb_id) { - int ret = drmModeSetCrtc (fd, - output->encoder->crtc_id, - fb_id, 0, 0, - &output->connector->connector_id, 1, - &output->mode); - if (ret) - { - g_set_error (error, COGL_WINSYS_ERROR, - COGL_WINSYS_ERROR_INIT, - "Failed to set mode %s: %m", output->mode.name); - return FALSE; - } + CoglDisplayEGL *egl_display = display->winsys; + CoglDisplayKMS *kms_display = egl_display->platform; + CoglRendererEGL *egl_renderer = display->renderer->winsys; + CoglRendererKMS *kms_renderer = egl_renderer->platform; + GList *l; - return TRUE; + for (l = kms_display->outputs; l; l = l->next) + { + CoglOutputKMS *output = l->data; + int ret = drmModeSetCrtc (kms_renderer->fd, + output->encoder->crtc_id, + fb_id, 0, 0, + &output->connector->connector_id, 1, + &output->mode); + if (ret) + g_warning ("Failed to set crtc mode %s: %m", output->mode.name); + } } static gboolean @@ -388,10 +393,6 @@ _cogl_winsys_egl_display_setup (CoglDisplay *display, drmModeRes *resources; CoglOutputKMS *output0, *output1; gboolean mirror; - struct gbm_bo *bo; - uint32_t handle, pitch, fb_id; - int width; - int height; kms_display = g_slice_new0 (CoglDisplayKMS); egl_display->platform = kms_display; @@ -475,37 +476,12 @@ _cogl_winsys_egl_display_setup (CoglDisplay *display, else output0->mode = output0->modes[0]; - width = output0->mode.hdisplay; - height = output0->mode.vdisplay; + kms_display->width = output0->mode.hdisplay; + kms_display->height = output0->mode.vdisplay; - bo = gbm_bo_create (kms_renderer->gbm, - width, height, GBM_BO_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT); - pitch = gbm_bo_get_pitch (bo); - handle = gbm_bo_get_handle (bo).u32; - if (drmModeAddFB (kms_renderer->fd, - width, - height, - 24, /* depth */ - 32, /* bpp */ - pitch, - handle, - &fb_id) != 0) - { - g_set_error (error, COGL_WINSYS_ERROR, - COGL_WINSYS_ERROR_INIT, - "Failed to create initial framebuffer"); - return FALSE; - } - - if (!set_crtc (kms_renderer->fd, fb_id, output0, error)) - return FALSE; - - if (mirror) - if (!set_crtc (kms_renderer->fd, fb_id, output1, error)) - return FALSE; - - kms_display->width = width; - kms_display->height = height; + /* We defer setting the crtc modes until the first swap_buffers request of a + * CoglOnscreen framebuffer. */ + kms_display->pending_set_crtc = TRUE; return TRUE; } @@ -705,6 +681,14 @@ _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen) return; } + /* If this is the first framebuffer to be presented then we now setup the + * crtc modes... */ + if (kms_display->pending_set_crtc) + { + setup_crtc_modes (context->display, kms_onscreen->next_fb_id); + kms_display->pending_set_crtc = FALSE; + } + flip = g_slice_new0 (CoglFlipKMS); flip->onscreen = onscreen; @@ -985,3 +969,14 @@ cogl_kms_renderer_get_kms_fd (CoglRenderer *renderer) else return -1; } + +void +cogl_kms_display_queue_modes_reset (CoglDisplay *display) +{ + if (display->setup) + { + CoglDisplayEGL *egl_display = display->winsys; + CoglDisplayKMS *kms_display = egl_display->platform; + kms_display->pending_set_crtc = TRUE; + } +}