[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

mesa: Changes to 'ubuntu'



 .gitignore                            |    1 
 debian/changelog                      |   10 
 debian/control                        |    4 
 debian/patches/egl-platform-rs.patch  | 1185 ++++++++++++++++++++++++++++++++++
 debian/patches/khr_platform_mir.patch |   82 ++
 debian/patches/series                 |    3 
 debian/patches/vulkan-mir.patch       | 1065 ++++++++++++++++++++++++++++++
 debian/rules                          |    1 
 8 files changed, 2349 insertions(+), 2 deletions(-)

New commits:
commit e7332d41cc28a6e1b6606be1c41b682949a923ae
Author: Timo Aaltonen <tjaalton@debian.org>
Date:   Tue Mar 28 19:48:32 2017 +0300

    upload to zesty

diff --git a/debian/changelog b/debian/changelog
index 08dffad..cd5ad0d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,4 +1,4 @@
-mesa (17.0.2-1ubuntu2) UNRELEASED; urgency=medium
+mesa (17.0.2-1ubuntu2) zesty; urgency=medium
 
   [ Cemil Azizoglu ]
   * egl-platform-rs.patch: Add support for Mir's new render surface based
@@ -6,7 +6,7 @@ mesa (17.0.2-1ubuntu2) UNRELEASED; urgency=medium
   * khr_platform_mir.patch: Add EGL_KHR_platform_mir
   * vulkan-mir.patch: Add Vulkan WSI driver for Mir
 
- -- Timo Aaltonen <tjaalton@debian.org>  Tue, 28 Mar 2017 19:15:55 +0300
+ -- Timo Aaltonen <tjaalton@debian.org>  Tue, 28 Mar 2017 19:22:29 +0300
 
 mesa (17.0.2-1ubuntu1) zesty; urgency=medium
 

commit fb51f537b0a542a149a7e83806117405c2b0f1c6
Author: Cemil Azizoglu <cemil.azizoglu@canonical.com>
Date:   Mon Feb 13 11:09:32 2017 -0600

    Add platform-rs, vulkan-mir, EGL_KHR_platform_mir.
    
    This commit
    - incorporates support for Mir's new render surface based EGL driver
    (alpha)
    - adds Vulkan WSI driver for Mir (alpha)
    - adds EGL_KHR_platform_mir (yet to be ratified)
    
    The render surface-based backend is implemented as a new platform so the
    legacy (buffer stream-based) backend can be supported simultaneously.
    
    TODO:
    - Mir-team intends to change the name 'render surface' (and all its
    associated symbols) to 'surface' in the very new feature. As soon as
    that happens this patch will require a refresh.

diff --git a/.gitignore b/.gitignore
index 9644092..991556e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,3 +50,4 @@ Makefile.in
 .install-gallium-links
 /src/git_sha1.h
 TAGS
+/.project
diff --git a/debian/changelog b/debian/changelog
index 38ee0c7..08dffad 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,13 @@
+mesa (17.0.2-1ubuntu2) UNRELEASED; urgency=medium
+
+  [ Cemil Azizoglu ]
+  * egl-platform-rs.patch: Add support for Mir's new render surface based
+    EGL driver
+  * khr_platform_mir.patch: Add EGL_KHR_platform_mir
+  * vulkan-mir.patch: Add Vulkan WSI driver for Mir
+
+ -- Timo Aaltonen <tjaalton@debian.org>  Tue, 28 Mar 2017 19:15:55 +0300
+
 mesa (17.0.2-1ubuntu1) zesty; urgency=medium
 
   * Merge from Debian experimental.
diff --git a/debian/control b/debian/control
index 0cb9185..b678c73 100644
--- a/debian/control
+++ b/debian/control
@@ -38,7 +38,7 @@ Build-Depends:
  libxcb-randr0-dev,
  libxcb-sync-dev,
  libxshmfence-dev (>= 1.1),
- libmirclient-dev [linux-any],
+ libmirclient-dev (>= 0.26.2) [linux-any],
  mir-client-platform-mesa-dev [linux-any],
  python,
  python-mako,
@@ -157,7 +157,7 @@ Depends:
  libx11-xcb-dev,
  libwayland-dev (>= 1.11.0) [linux-any],
  ${misc:Depends},
- libmirclient-dev [!arm64 !powerpc !ppc64 !ppc64el !kfreebsd-any !hurd-any],
+ libmirclient-dev (>= 0.26.2) [!arm64 !powerpc !ppc64 !ppc64el !kfreebsd-any !hurd-any],
 Multi-Arch: same
 Description: free implementation of the EGL API -- development files
  This package contains the development environment required for compiling
diff --git a/debian/patches/egl-platform-rs.patch b/debian/patches/egl-platform-rs.patch
new file mode 100644
index 0000000..210f4f4
--- /dev/null
+++ b/debian/patches/egl-platform-rs.patch
@@ -0,0 +1,1185 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -91,6 +91,7 @@ XSHMFENCE_REQUIRED=1.1
+ XVMC_REQUIRED=1.0.6
+ PYTHON_MAKO_REQUIRED=0.8.0
+ LIBSENSORS_REQUIRED=4.0.0
++MIR_REQUIRED=0.26.2
+ 
+ dnl LLVM versions
+ LLVM_REQUIRED_GALLIUM=3.3.0
+@@ -2131,9 +2132,15 @@ for plat in $egl_platforms; do
+ 	android)
+ 		PKG_CHECK_MODULES([ANDROID], [cutils hardware sync])
+ 		;;
+-        mir)
+-                PKG_CHECK_MODULES([MIR], [mirclient mir-client-platform-mesa])
+-                ;;
++
++	mir)
++		PKG_CHECK_MODULES([MIR], [mirclient mir-client-platform-mesa])
++		;;
++
++	rs)
++		PKG_CHECK_MODULES([RS], [mirclient >= $MIR_REQUIRED])
++		;;
++
+ 	*)
+ 		AC_MSG_ERROR([EGL platform '$plat' does not exist])
+ 		;;
+@@ -2161,6 +2168,7 @@ AM_CONDITIONAL(HAVE_EGL_PLATFORM_DRM, ec
+ AM_CONDITIONAL(HAVE_EGL_PLATFORM_SURFACELESS, echo "$egl_platforms" | grep -q 'surfaceless')
+ AM_CONDITIONAL(HAVE_EGL_PLATFORM_ANDROID, echo "$egl_platforms" | grep -q 'android')
+ AM_CONDITIONAL(HAVE_EGL_PLATFORM_MIR, echo "$egl_platforms" | grep -q 'mir')
++AM_CONDITIONAL(HAVE_EGL_PLATFORM_RS, echo "$egl_platforms" | grep -q 'rs')
+ 
+ AC_SUBST([EGL_NATIVE_PLATFORM])
+ AC_SUBST([EGL_CFLAGS])
+--- a/include/EGL/eglplatform.h
++++ b/include/EGL/eglplatform.h
+@@ -112,6 +112,13 @@ typedef MirEGLNativeDisplayType EGLNativ
+ typedef void                   *EGLNativePixmapType;
+ typedef MirEGLNativeWindowType  EGLNativeWindowType;
+ 
++#elif defined(RS_EGL_PLATFORM)
++
++#include <mir_toolkit/mir_client_library.h>
++typedef MirEGLNativeDisplayType EGLNativeDisplayType;
++typedef void                   *EGLNativePixmapType;
++typedef MirEGLNativeWindowType  EGLNativeWindowType;
++
+ #elif defined(__unix__) || defined(__APPLE__)
+ 
+ #if defined(MESA_EGL_NO_X11_HEADERS)
+--- a/src/egl/Makefile.am
++++ b/src/egl/Makefile.am
+@@ -97,6 +97,13 @@ AM_CFLAGS += $(MIR_CFLAGS)
+ dri2_backend_FILES += drivers/dri2/platform_mir.c
+ endif
+ 
++if HAVE_EGL_PLATFORM_RS
++AM_CFLAGS += -DHAVE_RS_PLATFORM
++AM_CFLAGS += $(RS_CFLAGS)
++libEGL_la_LIBADD += $(RS_LIBS)
++dri2_backend_FILES += drivers/dri2/platform_rs.c
++endif
++
+ AM_CFLAGS += \
+ 	-I$(top_srcdir)/src/loader \
+ 	-I$(top_srcdir)/src/egl/drivers/dri2 \
+--- a/src/egl/drivers/dri2/egl_dri2.c
++++ b/src/egl/drivers/dri2/egl_dri2.c
+@@ -844,6 +844,11 @@ dri2_initialize(_EGLDriver *drv, _EGLDis
+       ret = dri2_initialize_android(drv, disp);
+       break;
+ #endif
++#ifdef HAVE_RS_PLATFORM
++   case _EGL_PLATFORM_RS:
++      ret = dri2_initialize_rs(drv, disp);
++      break;
++#endif
+    default:
+       _eglLog(_EGL_WARNING, "No EGL platform enabled.");
+       return EGL_FALSE;
+@@ -911,6 +916,13 @@ dri2_display_release(_EGLDisplay *disp)
+       }
+       break;
+ #endif
++#ifdef HAVE_RS_PLATFORM
++   case _EGL_PLATFORM_RS:
++      if (dri2_dpy->own_device) {
++         gbm_device_destroy(&dri2_dpy->gbm_dri->base.base);
++      }
++      break;
++#endif
+ #ifdef HAVE_MIR_PLATFORM
+    case _EGL_PLATFORM_MIR:
+       if (dri2_dpy->own_device) {
+@@ -941,7 +953,8 @@ dri2_display_release(_EGLDisplay *disp)
+     * for the cleanup.
+     */
+    if (disp->Platform != _EGL_PLATFORM_DRM &&
+-       disp->Platform != _EGL_PLATFORM_MIR) {
++       disp->Platform != _EGL_PLATFORM_MIR &&
++       disp->Platform != _EGL_PLATFORM_RS) {
+       for (i = 0; dri2_dpy->driver_configs[i]; i++)
+          free((__DRIconfig *) dri2_dpy->driver_configs[i]);
+       free(dri2_dpy->driver_configs);
+--- a/src/egl/drivers/dri2/egl_dri2.h
++++ b/src/egl/drivers/dri2/egl_dri2.h
+@@ -74,6 +74,10 @@
+ #include <mir_toolkit/mesa/native_display.h>
+ #endif
+ 
++#ifdef HAVE_RS_PLATFORM
++#include <mir_toolkit/mir_connection.h>
++#endif
++
+ #include "eglconfig.h"
+ #include "eglcontext.h"
+ #include "egldisplay.h"
+@@ -234,6 +238,11 @@ struct dri2_egl_display
+ #ifdef HAVE_MIR_PLATFORM
+    MirMesaEGLNativeDisplay *mir_disp;
+ #endif
++#ifdef HAVE_RS_PLATFORM
++   MirConnection*  mir_conn;
++   pthread_mutex_t lock;
++   pthread_cond_t  cv;
++#endif
+ };
+ 
+ struct dri2_egl_context
+@@ -292,10 +301,10 @@ struct dri2_egl_surface
+       void *data;
+       int data_size;
+ #endif
+-#if HAVE_DRM_PLATFORM || defined(HAVE_MIR_PLATFORM)
++#if HAVE_DRM_PLATFORM || defined(HAVE_MIR_PLATFORM) || defined(HAVE_RS_PLATFORM)
+       struct gbm_bo       *bo;
+ #endif
+-#ifdef HAVE_MIR_PLATFORM
++#if defined(HAVE_MIR_PLATFORM) || defined(HAVE_RS_PLATFORM)
+       int                 fd;
+       int                 buffer_age;
+ #endif
+@@ -314,6 +323,10 @@ struct dri2_egl_surface
+    __DRIbuffer           *local_buffers[__DRI_BUFFER_COUNT];
+ #endif
+ 
++#ifdef HAVE_RS_PLATFORM
++   void* sc;
++#endif
++
+ #if defined(HAVE_SURFACELESS_PLATFORM)
+       __DRIimage           *front;
+       unsigned int         visual;
+@@ -413,6 +426,9 @@ dri2_initialize_surfaceless(_EGLDriver *
+ EGLBoolean
+ dri2_initialize_mir(_EGLDriver *drv, _EGLDisplay *disp);
+ 
++EGLBoolean
++dri2_initialize_rs(_EGLDriver *drv, _EGLDisplay *disp);
++
+ void
+ dri2_flush_drawable_for_swapbuffers(_EGLDisplay *disp, _EGLSurface *draw);
+ 
+@@ -443,5 +459,4 @@ dri2_set_WL_bind_wayland_display(_EGLDri
+    }
+ #endif
+ }
+-
+ #endif /* EGL_DRI2_INCLUDED */
+--- /dev/null
++++ b/src/egl/drivers/dri2/platform_rs.c
+@@ -0,0 +1,962 @@
++/*
++ * Copyright © 2016 Canonical, Inc
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
++ * Authors:
++ *    Cemil Azizoglu <cemil.azizoglu@canonical.com>
++ */
++
++#include <mir_toolkit/mir_presentation_chain.h>
++#include <mir_toolkit/mir_buffer.h>
++#include <mir_toolkit/rs/mir_render_surface.h>
++#include <mir_toolkit/extensions/gbm_buffer.h>
++#include <mir_toolkit/extensions/mesa_drm_auth.h>
++
++#include <string.h>
++#include <stdio.h>
++#include <xf86drm.h>
++
++#include "egl_dri2.h"
++#include "egl_dri2_fallbacks.h"
++#include "loader.h"
++
++#define MAX_BUFFERS (4)
++#define NUM_DEFAULT_BUFFERS (3) /* Can be at most MAX_BUFFERS */
++
++enum buffer_state
++{
++   buffer_state_none = 0,
++   buffer_state_available,
++   buffer_state_acquired,
++   buffer_state_submitted,
++};
++
++typedef struct SwapChain
++{
++    MirRenderSurface*                     surface;
++    MirPresentationChain*                 chain;
++    MirPixelFormat                        format;
++    uint32_t                              gbm_format;
++    unsigned int                          buffer_count;
++    MirBuffer*                            buffers[MAX_BUFFERS];
++    enum buffer_state                     state[MAX_BUFFERS];
++    uint32_t                              next_buffer_to_use;
++    pthread_mutex_t                       lock;
++    pthread_cond_t                        cv;
++    struct MirExtensionGbmBufferV2 const* gbm_buffer_ext;
++} SwapChain;
++
++static uint32_t
++mir_format_to_gbm_format(MirPixelFormat format)
++{
++    uint32_t gbm_pf;
++
++    switch (format)
++    {
++    case mir_pixel_format_argb_8888:
++        gbm_pf = GBM_FORMAT_ARGB8888;
++        break;
++    case mir_pixel_format_xrgb_8888:
++        gbm_pf = GBM_FORMAT_XRGB8888;
++        break;
++    case mir_pixel_format_abgr_8888:
++        gbm_pf = GBM_FORMAT_ABGR8888;
++        break;
++    case mir_pixel_format_xbgr_8888:
++        gbm_pf = GBM_FORMAT_XBGR8888;
++        break;
++    case mir_pixel_format_rgb_565:
++        gbm_pf = GBM_FORMAT_RGB565;
++        break;
++    default:
++        gbm_pf = UINT32_MAX;
++        break;
++    }
++
++    return gbm_pf;
++}
++
++static int
++get_format_bpp(MirPixelFormat format)
++{
++   int bpp;
++
++   switch (format) {
++   case mir_pixel_format_argb_8888:
++   case mir_pixel_format_xrgb_8888:
++   case mir_pixel_format_abgr_8888:
++   case mir_pixel_format_xbgr_8888:
++      bpp = 4;
++      break;
++   case mir_pixel_format_rgb_565:
++      bpp = 2;
++      break;
++   default:
++      bpp = 0;
++      break;
++   }
++
++   return bpp;
++}
++
++static struct gbm_bo *
++create_gbm_bo_from_buffer(struct gbm_device* gbm_dev, int fd, int width, int height, uint32_t stride, uint32_t format)
++{
++   struct gbm_import_fd_data data;
++
++   _eglLog(_EGL_INFO, "importing fd=%d", fd);
++   data.fd = fd;
++   data.width = width;
++   data.height = height;
++   data.format = format;
++   data.stride = stride;
++
++   return gbm_bo_import(gbm_dev, GBM_BO_IMPORT_FD, &data, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
++}
++
++static void
++clear_cached_buffers(struct dri2_egl_surface *dri2_surf)
++{
++   size_t i;
++   for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
++      if (dri2_surf->color_buffers[i].bo != NULL)
++         gbm_bo_destroy(dri2_surf->color_buffers[i].bo);
++      dri2_surf->color_buffers[i].bo = NULL;
++      dri2_surf->color_buffers[i].fd = -1;
++      dri2_surf->color_buffers[i].age = 0;
++   }
++}
++
++static ssize_t
++find_cached_buffer_with_fd(struct dri2_egl_surface *dri2_surf, int fd)
++{
++   ssize_t i;
++
++   for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
++      if (dri2_surf->color_buffers[i].fd == fd)
++         return i;
++   }
++
++   return -1;
++}
++
++static void
++cache_buffer(struct dri2_egl_surface *dri2_surf, size_t slot,
++                         int fd, int width, int height, uint32_t stride)
++{
++   SwapChain* sc = (SwapChain *)dri2_surf->sc;
++   struct dri2_egl_display *dri2_dpy =
++      dri2_egl_display(dri2_surf->base.Resource.Display);
++
++   if (dri2_surf->color_buffers[slot].bo != NULL)
++      gbm_bo_destroy(dri2_surf->color_buffers[slot].bo);
++
++   dri2_surf->color_buffers[slot].bo = create_gbm_bo_from_buffer(
++      &dri2_dpy->gbm_dri->base.base,
++      fd, width, height, stride,
++      sc->gbm_format);
++
++   _eglLog(_EGL_INFO, " imported bo : %p format = %d (GBM_FORMAT_ARGB8888=%d)",
++      (void*)dri2_surf->color_buffers[slot].bo, gbm_bo_get_format(dri2_surf->color_buffers[slot].bo), GBM_FORMAT_ARGB8888);
++
++   dri2_surf->color_buffers[slot].fd = fd;
++}
++
++static size_t
++find_best_cache_slot(struct dri2_egl_surface *dri2_surf)
++{
++   size_t i;
++   size_t start_slot = 0;
++
++   /*
++    * If we have a back buffer, start searching after it to ensure
++    * we don't reuse the slot too soon.
++    */
++   if (dri2_surf->back != NULL) {
++      start_slot = dri2_surf->back - dri2_surf->color_buffers;
++      start_slot = (start_slot + 1) % ARRAY_SIZE(dri2_surf->color_buffers);
++   }
++
++   /* Try to find an empty slot */
++   for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
++      size_t slot = (start_slot + i) % ARRAY_SIZE(dri2_surf->color_buffers);
++      if (dri2_surf->color_buffers[slot].bo == NULL)
++         return slot;
++   }
++
++   /* If we don't have an empty slot, use the start slot */
++   return start_slot;
++}
++
++static void
++update_cached_buffer_ages(struct dri2_egl_surface *dri2_surf, size_t used_slot)
++{
++   /*
++    * If 3 (Mir surfaces are triple buffered at most) other buffers have been
++    * used since a buffer was used, we probably won't need this buffer again.
++    */
++   static const int destruction_age = 3;
++   size_t i;
++
++   for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
++      if (dri2_surf->color_buffers[i].bo != NULL) {
++         if (i == used_slot) {
++            dri2_surf->color_buffers[i].age = 0;
++         }
++         else {
++            ++dri2_surf->color_buffers[i].age;
++            if (dri2_surf->color_buffers[i].age == destruction_age) {
++               gbm_bo_destroy(dri2_surf->color_buffers[i].bo);
++               dri2_surf->color_buffers[i].bo = NULL;
++               dri2_surf->color_buffers[i].fd = -1;
++            }
++         }
++      }
++   }
++}
++
++static int
++dri2_rs_authenticate(_EGLDisplay *disp, uint32_t id)
++{
++   return 0;
++}
++
++static void
++buffer_submit_callback(MirBuffer* buffer, void* context)
++{
++   SwapChain* sc = (SwapChain*) context;
++
++//  _eglLog(_EGL_DEBUG, "Buffer %p returned from server", (void*) buffer);
++  for (uint32_t i = 0; i < sc->buffer_count; i++)
++     if (sc->buffers[i] == buffer)
++     {
++        pthread_mutex_lock(&sc->lock);
++        assert(sc->state[i] == buffer_state_submitted);
++        sc->state[i] = buffer_state_available;
++        pthread_mutex_unlock(&sc->lock);
++        pthread_cond_broadcast(&sc->cv);
++     }
++}
++
++static EGLBoolean
++mir_submit_buffer(struct dri2_egl_surface *dri2_surf)
++{
++   SwapChain* sc = (SwapChain *)dri2_surf->sc;
++
++   for (uint32_t i = 0; i < sc->buffer_count; i++)
++   {
++      if (sc->state[i] == buffer_state_acquired)
++      {
++         int buffer_fd = sc->gbm_buffer_ext->fd(sc->buffers[i]);
++         if (buffer_fd == dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]->fd)
++         {
++//            _eglLog(_EGL_DEBUG, "..submitting buffer %p", sc->buffers[i]);
++            sc->state[i] = buffer_state_submitted;
++            mir_presentation_chain_submit_buffer(sc->chain,
++                                                 sc->buffers[i],
++                                                 buffer_submit_callback,
++                                                 sc);
++            break;
++         }
++      }
++   }
++
++   return EGL_TRUE;
++}
++
++static EGLBoolean
++mir_acquire_buffer(struct dri2_egl_display *dri2_dpy, struct dri2_egl_surface *dri2_surf)
++{
++   SwapChain* sc = (SwapChain *)dri2_surf->sc;
++   MirBuffer* buffer = NULL;
++   unsigned int buffer_width, buffer_height;
++   bool found = false;
++   ssize_t buf_slot = -1;
++
++   if (!sc)
++       return EGL_TRUE;
++
++   uint32_t wrap = (sc->next_buffer_to_use-1)%(sc->buffer_count);
++   do
++   {
++      uint32_t const next_buffer = sc->next_buffer_to_use;
++      if (sc->state[next_buffer] == buffer_state_available)
++      {
++          int rs_width, rs_height;
++
++          found = true;
++          sc->state[next_buffer] = buffer_state_acquired;
++          buffer = sc->buffers[next_buffer];
++          buffer_width = mir_buffer_get_width(buffer);
++          buffer_height = mir_buffer_get_height(buffer);
++
++    //          _eglLog(_EGL_DEBUG, "..acquired buffer %p with fd = %d", sc->buffers[sc->next_buffer_to_use], mbp->fd[0]);
++          mir_render_surface_get_size(sc->surface, &rs_width, &rs_height);
++          if ((rs_width != buffer_width) || (rs_height != buffer_height))
++          {
++              // release the old buffer
++              mir_buffer_release(buffer);
++              // .. replace it with a new buffer
++              sc->buffers[next_buffer] =
++                 sc->gbm_buffer_ext->allocate_buffer_gbm_sync(
++                    dri2_dpy->mir_conn,
++                    rs_width, rs_height,
++                    sc->gbm_format,
++                    GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
++
++              buffer = sc->buffers[next_buffer];
++              buffer_width = rs_width;
++              buffer_height = rs_height;
++           }
++      }
++      else
++      {
++         if (next_buffer == wrap)
++         {
++            pthread_mutex_lock(&sc->lock);
++            pthread_cond_wait(&sc->cv, &sc->lock);
++            pthread_mutex_unlock(&sc->lock);
++         }
++      }
++
++      sc->next_buffer_to_use = (next_buffer+1)%(sc->buffer_count);
++   }
++   while(!found);
++
++   if (buffer_width && buffer_height) {
++      dri2_surf->base.Width = buffer_width;
++      dri2_surf->base.Height = buffer_height;
++   }
++
++   int buffer_fd = sc->gbm_buffer_ext->fd(buffer);
++   assert(buffer_fd > 0);
++   unsigned int buffer_age = sc->gbm_buffer_ext->age(buffer);
++   uint32_t buffer_stride = sc->gbm_buffer_ext->stride(buffer);
++   buf_slot = find_cached_buffer_with_fd(dri2_surf, buffer_fd);
++
++   if (buf_slot != -1) {
++      /*
++       * If we get a new buffer with an fd of a previously cached buffer,
++       * replace the old buffer in the cache...
++       */
++      if (buffer_age == 0)
++         cache_buffer(dri2_surf, buf_slot, buffer_fd, buffer_width, buffer_height, buffer_stride);
++      /* ... otherwise just reuse the existing cached buffer */
++   }
++   else {
++      /* We got a new buffer with an fd that's not in the cache, so add it */
++      buf_slot = find_best_cache_slot(dri2_surf);
++      cache_buffer(dri2_surf, buf_slot, buffer_fd, buffer_width, buffer_height, buffer_stride);
++   }
++
++   update_cached_buffer_ages(dri2_surf, buf_slot);
++
++   dri2_surf->back = &dri2_surf->color_buffers[buf_slot];
++   dri2_surf->back->buffer_age = buffer_age;
++   dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]->name = 0;
++   dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]->fd = buffer_fd;
++   dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]->pitch = buffer_stride;
++
++   return EGL_TRUE;
++}
++
++static _EGLSurface *
++dri2_rs_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
++                               _EGLConfig *conf, EGLNativeWindowType window,
++                               const EGLint *attrib_list)
++{
++   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
++   struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
++   struct dri2_egl_surface *dri2_surf;
++   const __DRIconfig *config;
++   MirRenderSurface* surface = window;
++   SwapChain *sc = calloc(1, sizeof(SwapChain));
++   int width = 0, height = 0;
++   uint32_t num_buffers = 0;
++
++   if (!mir_render_surface_is_valid(surface))
++   {
++      _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_rs_create_window_surface: surface is bad");
++      return NULL;
++   }
++
++   sc->surface = surface;
++   sc->format = dri2_conf->base.NativeVisualID;
++   _eglLog(_EGL_INFO, "Mir pixel format requested : %d", sc->format);
++   sc->gbm_format = mir_format_to_gbm_format(sc->format);
++
++   if (sc->gbm_format == UINT32_MAX)
++   {
++      _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_rs_create_window_surface: bad format");
++      return NULL;
++   }
++
++   mir_render_surface_get_size(surface, &width, &height);
++   _eglLog(_EGL_INFO, "render surface of size : %dx%d", width, height);
++
++   sc->chain = mir_render_surface_get_presentation_chain(surface);
++   if (!mir_presentation_chain_is_valid(sc->chain))
++   {
++      _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_rs_create_window_surface: pc is bad");
++      return NULL;
++   }
++
++   pthread_mutex_init(&sc->lock, NULL);
++   pthread_cond_init(&sc->cv, NULL);
++
++   char* str_num = getenv("MIR_EGL_CLIENT_BUFFERS");
++   if (str_num)
++      num_buffers = atoi(str_num);
++   if ((num_buffers < 2) || (num_buffers > MAX_BUFFERS))
++      num_buffers = NUM_DEFAULT_BUFFERS;
++
++   _eglLog(_EGL_INFO, "Allocating %d buffers", num_buffers);
++   sc->gbm_buffer_ext = mir_extension_gbm_buffer_v2(dri2_dpy->mir_conn);
++   assert(sc->gbm_buffer_ext);
++   assert(sc->gbm_buffer_ext->allocate_buffer_gbm_sync);
++   assert(sc->gbm_buffer_ext->fd);
++   assert(sc->gbm_buffer_ext->stride);
++   assert(sc->gbm_buffer_ext->age);
++
++   for (unsigned int i = 0; i < num_buffers; i++)
++   {
++       sc->buffers[i] =
++          sc->gbm_buffer_ext->allocate_buffer_gbm_sync(dri2_dpy->mir_conn,
++                                                       width, height,
++                                                       sc->gbm_format,
++                                                       GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
++       assert(sc->state[i] == buffer_state_none);
++       sc->state[i] = buffer_state_available;
++       sc->buffer_count++;
++   }
++
++   _eglLog(_EGL_INFO, "Presentation chain : %p", sc->chain);
++   _eglLog(_EGL_INFO, "\tcontains %d buffers", sc->buffer_count);
++   for (uint32_t i=0; i<sc->buffer_count; i++) {
++      _eglLog(_EGL_INFO, "Buffer #%d %dx%d: %p",
++                         i,
++                         mir_buffer_get_width(sc->buffers[i]),
++                         mir_buffer_get_height(sc->buffers[i]),
++                         sc->buffers[i]);
++   }
++
++   dri2_surf = calloc(1, sizeof *dri2_surf);
++   if (!dri2_surf) {
++      _eglError(EGL_BAD_ALLOC, "dri2_rs_create_window_surface");
++      return NULL;
++   }
++
++   if (!_eglInitSurface(&dri2_surf->base, disp, EGL_WINDOW_BIT, conf, attrib_list))
++      goto cleanup_surf;
++
++   dri2_surf->sc = sc;
++
++   dri2_surf->base.Width = width;
++   dri2_surf->base.Height = height;
++
++   dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT] =
++      calloc(sizeof(*dri2_surf->dri_buffers[0]), 1);
++   dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT] =
++      calloc(sizeof(*dri2_surf->dri_buffers[0]), 1);
++
++   dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]->attachment =
++      __DRI_BUFFER_BACK_LEFT;
++
++   dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]->cpp = get_format_bpp(sc->format);
++
++   clear_cached_buffers(dri2_surf);
++
++   if(!mir_acquire_buffer(dri2_dpy, dri2_surf))
++      goto cleanup_surf;
++
++   config = dri2_get_dri_config(dri2_conf, EGL_WINDOW_BIT,
++                                dri2_surf->base.GLColorspace);
++
++   if (dri2_dpy->gbm_dri) {
++      struct gbm_dri_surface *surf = malloc(sizeof *surf);
++
++      dri2_surf->gbm_surf = surf;
++      surf->base.gbm = &dri2_dpy->gbm_dri->base.base;
++      surf->base.width = dri2_surf->base.Width;
++      surf->base.height = dri2_surf->base.Height;
++      surf->base.format = sc->gbm_format;
++      surf->base.flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
++      surf->dri_private = dri2_surf;
++
++      dri2_surf->dri_drawable =
++          (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
++                                                config,
++                                                dri2_surf->gbm_surf);
++   }
++   else {
++      dri2_surf->dri_drawable =
++          (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
++                                                config,
++                                                dri2_surf);
++   }
++
++   if (dri2_surf->dri_drawable == NULL) {
++      _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
++   }
++
++   return &dri2_surf->base;
++
++cleanup_surf:
++   free(dri2_surf);
++   return NULL;
++}
++
++static _EGLSurface *
++dri2_rs_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
++                              _EGLConfig *conf, void *native_window,
++                              const EGLint *attrib_list)
++{
++   _eglError(EGL_BAD_PARAMETER, "EGL pixmap surfaces are unsupported on Mir (RS)");
++   return NULL;
++}
++
++static EGLBoolean
++dri2_rs_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
++{
++   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
++   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
++   int i;
++
++   (void) drv;
++
++   if (!_eglPutSurface(surf))
++      return EGL_TRUE;
++
++   clear_cached_buffers(dri2_surf);
++
++   (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
++
++   for (i = 0; i < __DRI_BUFFER_COUNT; ++i) {
++      if (dri2_surf->dri_buffers[i]) {
++         if ((i == __DRI_BUFFER_FRONT_LEFT) ||
++             (i == __DRI_BUFFER_BACK_LEFT)) {
++            free(dri2_surf->dri_buffers[i]);
++         }
++         else {
++            dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
++                                          dri2_surf->dri_buffers[i]);
++         }
++      }
++   }
++
++   free(dri2_surf->gbm_surf);
++
++   SwapChain *sc = (SwapChain *)dri2_surf->sc;
++   dri2_surf->sc = NULL;
++
++   bool wait_for_buffers;
++   do
++   {
++      sleep(0);
++      wait_for_buffers = false;
++
++      for (uint32_t i = 0; i < sc->buffer_count; i++)
++      {
++         if (sc->state[i] > buffer_state_available)
++            wait_for_buffers = true;
++      }
++   } while(wait_for_buffers);
++
++   for (uint32_t i = 0; i < sc->buffer_count; i++) {
++      if(sc->buffers[i])
++      {
++         mir_buffer_release(sc->buffers[i]);
++         sc->buffers[i] = NULL;
++      }
++   }
++
++   pthread_mutex_destroy(&sc->lock);
++   pthread_cond_destroy(&sc->cv);
++
++   free(sc);
++   free(surf);
++
++   return EGL_TRUE;
++}
++
++static _EGLImage *
++dri2_rs_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
++                         _EGLContext *ctx, EGLenum target,
++                         EGLClientBuffer buffer, const EGLint *attr_list)
++{
++   (void) drv;
++
++   switch (target) {
++   case EGL_NATIVE_PIXMAP_KHR:
++      _eglError(EGL_BAD_PARAMETER, "Mir has no native pixmaps");
++      return NULL;
++   default:
++      return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
++   }
++}
++
++static EGLBoolean
++dri2_rs_swap_interval(_EGLDriver *drv, _EGLDisplay *disp,
++                       _EGLSurface *surf, EGLint interval)
++{
++    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
++    SwapChain* sc = (SwapChain *)dri2_surf->sc;
++    MirPresentationChain* chain = sc->chain;
++    MirPresentMode mode;
++
++    switch (interval) {
++    case 0:
++       mode = mir_present_mode_mailbox;
++       break;
++    case 1:
++       mode = mir_present_mode_fifo;
++       break;
++    default:
++       _eglError(EGL_BAD_PARAMETER, "Mir only supports swap interval 0 and 1");
++       return EGL_FALSE;
++    }
++
++    mir_presentation_chain_set_mode(chain, mode);
++    return EGL_TRUE;
++}
++
++static EGLBoolean
++dri2_rs_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
++{
++   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
++   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
++   int rc;
++
++   (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
++
++   rc = mir_submit_buffer(dri2_surf);
++
++   if (rc)
++      rc = mir_acquire_buffer(dri2_dpy, dri2_surf);
++
++   (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
++
++   return rc;
++}
++
++static EGLint
++dri2_rs_query_buffer_age(_EGLDriver *drv, _EGLDisplay *dpy,
++                          _EGLSurface *surf)
++{
++   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
++   if (dri2_surf->back)
++   {
++      return dri2_surf->back->buffer_age;
++   }
++   return 0;
++}
++
++static __DRIbuffer*
++dri2_rs_get_buffers_with_format(__DRIdrawable *driDrawable,
++                                 int *width,
++                                 int *height,
++                                 unsigned int *attachments,
++                                 int count,
++                                 int *out_count,
++                                 void *data)
++{
++   struct dri2_egl_surface *dri2_surf = data;
++   struct dri2_egl_display *dri2_dpy =
++      dri2_egl_display(dri2_surf->base.Resource.Display);
++   int i;
++
++   dri2_surf->buffer_count = 0;
++   for (i = 0; i < 2*count; i+=2) {
++      assert(attachments[i] < __DRI_BUFFER_COUNT);
++      assert(dri2_surf->buffer_count < 5);
++
++      if (dri2_surf->dri_buffers[attachments[i]] == NULL) {
++         /* Our frame callback must keep these buffers valid */
++         assert(attachments[i] != __DRI_BUFFER_FRONT_LEFT);
++         assert(attachments[i] != __DRI_BUFFER_BACK_LEFT);
++
++         dri2_surf->dri_buffers[attachments[i]] =
++            dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
++                  attachments[i], attachments[i+1],
++                  dri2_surf->base.Width, dri2_surf->base.Height);
++
++         if (!dri2_surf->dri_buffers[attachments[i]])
++            continue;
++      }
++
++      memcpy(&dri2_surf->buffers[dri2_surf->buffer_count],
++             dri2_surf->dri_buffers[attachments[i]],
++             sizeof(__DRIbuffer));
++
++      dri2_surf->buffer_count++;
++   }
++
++   assert(dri2_surf->base.Type == EGL_PIXMAP_BIT ||


Reply to: