Example #1
0
static CoglBool
_cogl_winsys_egl_onscreen_init (CoglOnscreen *onscreen,
                                EGLConfig egl_config,
                                CoglError **error)
{
  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
  CoglContext *context = framebuffer->context;
  CoglDisplay *display = context->display;
  CoglDisplayEGL *egl_display = display->winsys;
  CoglDisplayGDL *gdl_display = egl_display->platform;
  CoglOnscreenEGL *egl_onscreen = onscreen->winsys;

  if (gdl_display->have_onscreen)
    {
      _cogl_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,
                                        gdl_display->egl_surface_width,
                                        gdl_display->egl_surface_height);
  gdl_display->have_onscreen = TRUE;

  return TRUE;
}
Example #2
0
void
cogl_wayland_onscreen_resize (CoglOnscreen *onscreen,
                              int           width,
                              int           height,
                              int           offset_x,
                              int           offset_y)
{
  CoglFramebuffer *fb;

  fb = COGL_FRAMEBUFFER (onscreen);
  if (fb->allocated)
    {
      CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
      CoglOnscreenWayland *wayland_onscreen = egl_onscreen->platform;

      if (cogl_framebuffer_get_width (fb) != width ||
          cogl_framebuffer_get_height (fb) != height ||
          offset_x ||
          offset_y)
        {
          wayland_onscreen->pending_width = width;
          wayland_onscreen->pending_height = height;
          wayland_onscreen->pending_dx += offset_x;
          wayland_onscreen->pending_dy += offset_y;
          wayland_onscreen->has_pending = TRUE;
        }
    }
  else
    _cogl_framebuffer_winsys_update_size (fb, width, height);
}
static void
flush_pending_resize (CoglOnscreen *onscreen)
{
  CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
  CoglOnscreenWayland *wayland_onscreen = egl_onscreen->platform;

  if (wayland_onscreen->has_pending)
    {
      wl_egl_window_resize (wayland_onscreen->wayland_egl_native_window,
                            wayland_onscreen->pending_width,
                            wayland_onscreen->pending_height,
                            wayland_onscreen->pending_dx,
                            wayland_onscreen->pending_dy);

      _cogl_framebuffer_winsys_update_size (COGL_FRAMEBUFFER (onscreen),
                                            wayland_onscreen->pending_width,
                                            wayland_onscreen->pending_height);

      _cogl_onscreen_queue_full_dirty (onscreen);

      wayland_onscreen->pending_dx = 0;
      wayland_onscreen->pending_dy = 0;
      wayland_onscreen->has_pending = FALSE;
    }
}
Example #4
0
static void
notify_resize (CoglContext *context,
               Window drawable,
               int width,
               int height)
{
  CoglRenderer *renderer = context->display->renderer;
  CoglRendererEGL *egl_renderer = renderer->winsys;
  CoglOnscreen *onscreen = find_onscreen_for_xid (context, drawable);
  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
  CoglOnscreenEGL *egl_onscreen;

  if (!onscreen)
    return;

  egl_onscreen = onscreen->winsys;

  _cogl_framebuffer_winsys_update_size (framebuffer, width, height);

  /* We only want to notify that a resize happened when the
   * application calls cogl_context_dispatch so instead of immediately
   * notifying we queue an idle callback */
  if (!egl_renderer->resize_notify_idle)
    {
      egl_renderer->resize_notify_idle =
        _cogl_poll_renderer_add_idle (renderer,
                                      flush_pending_resize_notifications_idle,
                                      context,
                                      NULL);
    }

  egl_onscreen->pending_resize_notify = TRUE;
}
Example #5
0
void
cogl_android_onscreen_update_size (CoglOnscreen *onscreen,
                                   int width,
                                   int height)
{
  CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen);
  _cogl_framebuffer_winsys_update_size (fb, width, height);
}
static CoglBool
_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
                            CoglError **error)
{
  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
  CoglContext *context = framebuffer->context;
  CoglDisplay *display = context->display;
  CoglDisplayEGL *egl_display = display->winsys;
  CoglDisplayKMS *kms_display = egl_display->platform;
  CoglRenderer *renderer = display->renderer;
  CoglRendererEGL *egl_renderer = renderer->winsys;
  CoglRendererKMS *kms_renderer = egl_renderer->platform;
  CoglOnscreenEGL *egl_onscreen;
  CoglOnscreenKMS *kms_onscreen;

  _COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context, FALSE);

  onscreen->winsys = g_slice_new0 (CoglOnscreenEGL);
  egl_onscreen = onscreen->winsys;

  kms_onscreen = g_slice_new0 (CoglOnscreenKMS);
  egl_onscreen->platform = kms_onscreen;

  kms_onscreen->surface =
    gbm_surface_create (kms_renderer->gbm,
                        kms_display->width,
                        kms_display->height,
                        GBM_BO_FORMAT_XRGB8888,
                        GBM_BO_USE_SCANOUT |
                        GBM_BO_USE_RENDERING);

  if (!kms_onscreen->surface)
    {
      _cogl_set_error (error, COGL_WINSYS_ERROR,
                   COGL_WINSYS_ERROR_CREATE_ONSCREEN,
                   "Failed to allocate surface");
      return FALSE;
    }

  egl_onscreen->egl_surface =
    eglCreateWindowSurface (egl_renderer->edpy,
                            egl_display->egl_config,
                            (NativeWindowType) kms_onscreen->surface,
                            NULL);
  if (egl_onscreen->egl_surface == EGL_NO_SURFACE)
    {
      _cogl_set_error (error, COGL_WINSYS_ERROR,
                   COGL_WINSYS_ERROR_CREATE_ONSCREEN,
                   "Failed to allocate surface");
      return FALSE;
    }

  _cogl_framebuffer_winsys_update_size (framebuffer,
                                        kms_display->width,
                                        kms_display->height);

  return TRUE;
}
Example #7
0
void
cogl_onscreen_clutter_backend_set_size (int width, int height)
{
  CoglFramebuffer *framebuffer;

  _COGL_GET_CONTEXT (ctx, NO_RETVAL);

  if (_cogl_context_get_winsys (ctx) != _cogl_winsys_stub_get_vtable ())
    return;

  framebuffer = COGL_FRAMEBUFFER (ctx->window_buffer);

  _cogl_framebuffer_winsys_update_size (framebuffer, width, height);
}
Example #8
0
static CoglFilterReturn
sdl_event_filter_cb (SDL_Event *event, void *data)
{
  if (event->type == SDL_WINDOWEVENT &&
      event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
    {
      CoglContext *context = data;
      CoglDisplay *display = context->display;
      CoglDisplaySdl2 *sdl_display = display->winsys;
      float width = event->window.data1;
      float height = event->window.data2;
      CoglFramebuffer *framebuffer;
      CoglOnscreenSdl2 *sdl_onscreen;
      SDL_Window *window;

      window = SDL_GetWindowFromID (event->window.windowID);

      if (window == NULL)
        return COGL_FILTER_CONTINUE;

      framebuffer = SDL_GetWindowData (window, COGL_SDL_WINDOW_DATA_KEY);

      if (framebuffer == NULL || framebuffer->context != context)
        return COGL_FILTER_CONTINUE;

      _cogl_framebuffer_winsys_update_size (framebuffer, width, height);

      sdl_onscreen = COGL_ONSCREEN (framebuffer)->winsys;

      /* We only want to notify that a resize happened when the
         application calls cogl_context_dispatch so instead of immediately
         notifying we'll set a flag to remember to notify later */
      sdl_display->pending_resize_notify = TRUE;
      sdl_onscreen->pending_resize_notify = TRUE;

      return COGL_FILTER_CONTINUE;
    }

  return COGL_FILTER_CONTINUE;
}
void
cogl_wayland_onscreen_resize (CoglOnscreen *onscreen,
                              int           width,
                              int           height,
                              int           offset_x,
                              int           offset_y)
{
  CoglFramebuffer *fb;

  fb = COGL_FRAMEBUFFER (onscreen);
  if (fb->allocated)
    {
      CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
      CoglOnscreenWayland *wayland_onscreen = egl_onscreen->platform;

      if (cogl_framebuffer_get_width (fb) != width ||
          cogl_framebuffer_get_height (fb) != height ||
          offset_x ||
          offset_y)
        {
          wayland_onscreen->pending_width = width;
          wayland_onscreen->pending_height = height;
          wayland_onscreen->pending_dx += offset_x;
          wayland_onscreen->pending_dy += offset_y;
          wayland_onscreen->has_pending = TRUE;

          /* If nothing has been drawn to the framebuffer since the
           * last swap then wl_egl_window_resize will take effect
           * immediately. Otherwise it might not take effect until the
           * next swap, depending on the version of Mesa. To keep
           * consistent behaviour we'll delay the resize until the
           * next swap unless we're sure nothing has been drawn */
          if (!fb->mid_scene)
            flush_pending_resize (onscreen);
        }
    }
  else
    _cogl_framebuffer_winsys_update_size (fb, width, height);
}
Example #10
0
static void
_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
{
  CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen);
  CoglContext *context = fb->context;
  CoglRenderer *renderer = context->display->renderer;
  CoglRendererEGL *egl_renderer = renderer->winsys;
  CoglRendererWayland *wayland_renderer = egl_renderer->platform;
  CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
  CoglOnscreenWayland *wayland_onscreen = egl_onscreen->platform;

  if (wayland_onscreen->has_pending)
    {
      wl_egl_window_resize (wayland_onscreen->wayland_egl_native_window,
                            wayland_onscreen->pending_width,
                            wayland_onscreen->pending_height,
                            wayland_onscreen->pending_dx,
                            wayland_onscreen->pending_dy);

      _cogl_framebuffer_winsys_update_size (fb,
                                            wayland_onscreen->pending_width,
                                            wayland_onscreen->pending_height);
      wayland_onscreen->has_pending = FALSE;
    }

  /* chain-up */
  parent_vtable->onscreen_swap_buffers (onscreen);

  /*
   * The implementation of eglSwapBuffers may do a flush however the semantics
   * of eglSwapBuffers on Wayland has changed in the past. So to be safe to
   * the implementation changing we should explicitly ensure all messages are
   * sent.
   */
  wl_display_flush (wayland_renderer->wayland_display);
}
Example #11
0
static CoglBool
_cogl_winsys_egl_onscreen_init (CoglOnscreen *onscreen,
                                EGLConfig egl_config,
                                CoglError **error)
{
  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
  CoglContext *context = framebuffer->context;
  CoglDisplay *display = context->display;
  CoglRenderer *renderer = display->renderer;
  CoglRendererEGL *egl_renderer = renderer->winsys;
  CoglXlibRenderer *xlib_renderer =
    _cogl_xlib_renderer_get_data (renderer);
  CoglOnscreenXlib *xlib_onscreen;
  CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
  Window xwin;

  /* FIXME: We need to explicitly Select for ConfigureNotify events.
   * For foreign windows we need to be careful not to mess up any
   * existing event mask.
   * We need to document that for windows we create then toolkits
   * must be careful not to clear event mask bits that we select.
   */

  /* XXX: Note we ignore the user's original width/height when
   * given a foreign X window. */
  if (onscreen->foreign_xid)
    {
      Status status;
      CoglXlibTrapState state;
      XWindowAttributes attr;
      int xerror;

      xwin = onscreen->foreign_xid;

      _cogl_xlib_renderer_trap_errors (display->renderer, &state);

      status = XGetWindowAttributes (xlib_renderer->xdpy, xwin, &attr);
      xerror = _cogl_xlib_renderer_untrap_errors (display->renderer,
                                                  &state);
      if (status == 0 || xerror)
        {
          char message[1000];
          XGetErrorText (xlib_renderer->xdpy, xerror,
                         message, sizeof (message));
          _cogl_set_error (error, COGL_WINSYS_ERROR,
                       COGL_WINSYS_ERROR_CREATE_ONSCREEN,
                       "Unable to query geometry of foreign "
                       "xid 0x%08lX: %s",
                       xwin, message);
          return FALSE;
        }

      _cogl_framebuffer_winsys_update_size (framebuffer,
                                            attr.width, attr.height);

      /* Make sure the app selects for the events we require... */
      onscreen->foreign_update_mask_callback (onscreen,
                                              COGL_ONSCREEN_X11_EVENT_MASK,
                                              onscreen->
                                              foreign_update_mask_data);
    }
  else
    {
      int width;
      int height;
      CoglXlibTrapState state;
      XVisualInfo *xvisinfo;
      XSetWindowAttributes xattr;
      unsigned long mask;
      int xerror;

      width = cogl_framebuffer_get_width (framebuffer);
      height = cogl_framebuffer_get_height (framebuffer);

      _cogl_xlib_renderer_trap_errors (display->renderer, &state);

      xvisinfo = get_visual_info (display, egl_config);
      if (xvisinfo == NULL)
        {
          _cogl_set_error (error, COGL_WINSYS_ERROR,
                       COGL_WINSYS_ERROR_CREATE_ONSCREEN,
                       "Unable to retrieve the X11 visual of context's "
                       "fbconfig");
          return FALSE;
        }

      /* window attributes */
      xattr.background_pixel =
        WhitePixel (xlib_renderer->xdpy,
                    DefaultScreen (xlib_renderer->xdpy));
      xattr.border_pixel = 0;
      /* XXX: is this an X resource that we are leaking‽... */
      xattr.colormap =
        XCreateColormap (xlib_renderer->xdpy,
                         DefaultRootWindow (xlib_renderer->xdpy),
                         xvisinfo->visual,
                         AllocNone);
      xattr.event_mask = COGL_ONSCREEN_X11_EVENT_MASK;

      mask = CWBorderPixel | CWColormap | CWEventMask;

      xwin = XCreateWindow (xlib_renderer->xdpy,
                            DefaultRootWindow (xlib_renderer->xdpy),
                            0, 0,
                            width, height,
                            0,
                            xvisinfo->depth,
                            InputOutput,
                            xvisinfo->visual,
                            mask, &xattr);

      XFree (xvisinfo);

      XSync (xlib_renderer->xdpy, False);
      xerror =
        _cogl_xlib_renderer_untrap_errors (display->renderer, &state);
      if (xerror)
        {
          char message[1000];
          XGetErrorText (xlib_renderer->xdpy, xerror,
                         message, sizeof (message));
          _cogl_set_error (error, COGL_WINSYS_ERROR,
                       COGL_WINSYS_ERROR_CREATE_ONSCREEN,
                       "X error while creating Window for CoglOnscreen: %s",
                       message);
          return FALSE;
        }
    }

  xlib_onscreen = g_slice_new (CoglOnscreenXlib);
  egl_onscreen->platform = xlib_onscreen;

  xlib_onscreen->xwin = xwin;
  xlib_onscreen->is_foreign_xwin = onscreen->foreign_xid ? TRUE : FALSE;

  egl_onscreen->egl_surface =
    eglCreateWindowSurface (egl_renderer->edpy,
                            egl_config,
                            (EGLNativeWindowType) xlib_onscreen->xwin,
                            NULL);

  return TRUE;
}
Example #12
0
static gboolean
_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
                            GError **error)
{
  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
  CoglContext *context = framebuffer->context;
  CoglDisplay *display = context->display;
  CoglDisplayEGL *egl_display = display->winsys;
  CoglDisplayKMS *kms_display = egl_display->platform;
  CoglRenderer *renderer = display->renderer;
  CoglRendererEGL *egl_renderer = renderer->winsys;
  CoglRendererKMS *kms_renderer = egl_renderer->platform;
  CoglOnscreenEGL *egl_onscreen;
  CoglOnscreenKMS *kms_onscreen;
  int i;

  _COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context, FALSE);

  onscreen->winsys = g_slice_new0 (CoglOnscreenEGL);
  egl_onscreen = onscreen->winsys;

  kms_onscreen = g_slice_new0 (CoglOnscreenKMS);
  egl_onscreen->platform = kms_onscreen;

  context->glGenRenderbuffers (2, kms_onscreen->color_rb);

  for (i = 0; i < 2; i++)
    {
      uint32_t handle, stride;

      kms_onscreen->bo[i] =
        gbm_bo_create (kms_renderer->gbm,
                       kms_display->mode.hdisplay, kms_display->mode.vdisplay,
                       GBM_BO_FORMAT_XRGB8888,
                       GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
      if (!kms_onscreen->bo[i])
        {
          g_set_error (error, COGL_WINSYS_ERROR,
                       COGL_WINSYS_ERROR_CREATE_CONTEXT,
                       "Failed to allocate buffer");
          return FALSE;
        }

      kms_onscreen->image[i] =
        _cogl_egl_create_image (context,
                                EGL_NATIVE_PIXMAP_KHR,
                                kms_onscreen->bo[i],
                                NULL);

      if (kms_onscreen->image[i] == EGL_NO_IMAGE_KHR)
        {
          g_set_error (error, COGL_WINSYS_ERROR,
                       COGL_WINSYS_ERROR_CREATE_CONTEXT,
                       "Failed to create EGL image");
          return FALSE;
        }

      context->glBindRenderbuffer (GL_RENDERBUFFER_EXT,
                                   kms_onscreen->color_rb[i]);
      context->glEGLImageTargetRenderbufferStorage (GL_RENDERBUFFER,
                                                    kms_onscreen->image[i]);
      context->glBindRenderbuffer (GL_RENDERBUFFER_EXT, 0);

      handle = gbm_bo_get_handle (kms_onscreen->bo[i]).u32;
      stride = gbm_bo_get_pitch (kms_onscreen->bo[i]);

      if (drmModeAddFB (kms_renderer->fd,
                        kms_display->mode.hdisplay,
                        kms_display->mode.vdisplay,
                        24, 32,
                        stride,
                        handle,
                        &kms_onscreen->fb_id[i]) != 0)
        {
          g_set_error (error, COGL_WINSYS_ERROR,
                       COGL_WINSYS_ERROR_CREATE_CONTEXT,
                       "Failed to create framebuffer from buffer");
          return FALSE;
        }
    }

  context->glGenFramebuffers (1, &kms_onscreen->fb);
  context->glBindFramebuffer (GL_FRAMEBUFFER_EXT, kms_onscreen->fb);

  context->glGenRenderbuffers (1, &kms_onscreen->depth_rb);
  context->glBindRenderbuffer (GL_RENDERBUFFER_EXT, kms_onscreen->depth_rb);
  context->glRenderbufferStorage (GL_RENDERBUFFER_EXT,
                                  GL_DEPTH_COMPONENT16,
                                  kms_display->mode.hdisplay,
                                  kms_display->mode.vdisplay);
  context->glBindRenderbuffer (GL_RENDERBUFFER_EXT, 0);

  context->glFramebufferRenderbuffer (GL_FRAMEBUFFER_EXT,
                                      GL_DEPTH_ATTACHMENT_EXT,
                                      GL_RENDERBUFFER_EXT,
                                      kms_onscreen->depth_rb);

  kms_onscreen->current_frame = 0;
  _cogl_winsys_onscreen_swap_buffers (onscreen);

  _cogl_framebuffer_winsys_update_size (framebuffer,
                                        kms_display->width,
                                        kms_display->height);

  return TRUE;
}