Index: dev/src/3rdparty/chromium/media/gpu/vaapi/vaapi_picture_factory.cc
===================================================================
--- dev.orig/src/3rdparty/chromium/media/gpu/vaapi/vaapi_picture_factory.cc
+++ dev/src/3rdparty/chromium/media/gpu/vaapi/vaapi_picture_factory.cc
@@ -115,7 +115,16 @@
 
 uint32_t VaapiPictureFactory::GetGLTextureTarget() {
 #if defined(USE_OZONE)
-  return GL_TEXTURE_EXTERNAL_OES;
+  switch (gl::GetGLImplementation()) {
+    case gl::kGLImplementationEGLGLES2:
+    case gl::kGLImplementationEGLANGLE:
+        return GL_TEXTURE_EXTERNAL_OES; // for EGL
+    case gl::kGLImplementationDesktopGL:
+        return GL_TEXTURE_2D;  // for GLX
+    default:
+      NOTREACHED();
+      return GL_TEXTURE_2D;
+  }    
 #else
   return GL_TEXTURE_2D;
 #endif
@@ -123,7 +132,16 @@
 
 gfx::BufferFormat VaapiPictureFactory::GetBufferFormat() {
 #if defined(USE_OZONE)
-  return gfx::BufferFormat::YUV_420_BIPLANAR;
+  switch (gl::GetGLImplementation()) {
+    case gl::kGLImplementationEGLGLES2:
+    case gl::kGLImplementationEGLANGLE:
+        return gfx::BufferFormat::YUV_420_BIPLANAR; // for EGL
+    case gl::kGLImplementationDesktopGL:
+        return gfx::BufferFormat::RGBX_8888;  // for GLX
+    default:
+      NOTREACHED();
+      return gfx::BufferFormat::RGBX_8888;
+  }
 #else
   return gfx::BufferFormat::RGBX_8888;
 #endif
  Index: dev/src/3rdparty/chromium/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.h
===================================================================
--- dev.orig/src/3rdparty/chromium/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.h
+++ dev/src/3rdparty/chromium/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.h
@@ -14,6 +14,8 @@
 #include "ui/gfx/buffer_types.h"
 #include "ui/gfx/geometry/size.h"
 
+#include "ui/gfx/x/x11_types.h"
+
 namespace gfx {
 class NativePixmap;
 }  // namespace gfx
@@ -44,8 +46,13 @@
       gfx::BufferFormat format,
       gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle) override;
 
+  VASurfaceID va_surface_id() const override;
+  bool DownloadFromSurface(scoped_refptr<VASurface> va_surface) override;
+      
  private:
   bool Initialize(scoped_refptr<gfx::NativePixmap> pixmap);
+  bool InitializeXPixmap(gfx::BufferFormat format);
+  XID x_pixmap_;
 
   DISALLOW_COPY_AND_ASSIGN(VaapiPictureNativePixmapOzone);
 };
 Index: dev/src/3rdparty/chromium/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.cc
===================================================================
--- dev.orig/src/3rdparty/chromium/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.cc
+++ dev/src/3rdparty/chromium/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.cc
@@ -6,10 +6,12 @@
 
 #include "media/gpu/vaapi/va_surface.h"
 #include "media/gpu/vaapi/vaapi_wrapper.h"
+#include "ui/gfx/buffer_format_util.h"
 #include "ui/gfx/gpu_memory_buffer.h"
 #include "ui/gfx/native_pixmap.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_image_native_pixmap.h"
+#include "ui/gl/gl_image_glx_native_pixmap.h"   
 #include "ui/gl/scoped_binders.h"
 #include "ui/ozone/public/ozone_platform.h"
 #include "ui/ozone/public/surface_factory_ozone.h"
@@ -34,7 +36,7 @@
                                visible_size,
                                texture_id,
                                client_texture_id,
-                               texture_target) {
+                               texture_target), x_pixmap_(0) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Either |texture_id| and |client_texture_id| are both zero, or not.
   DCHECK((texture_id == 0 && client_texture_id == 0) ||
@@ -47,6 +49,10 @@
     gl_image_->ReleaseTexImage(texture_target_);
     DCHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR));
   }
+  
+  if (x_pixmap_) {
+      XFreePixmap(gfx::GetXDisplay(), x_pixmap_);
+  }
 }
 
 bool VaapiPictureNativePixmapOzone::Initialize(
@@ -65,7 +71,7 @@
   if (texture_id_ == 0 && client_texture_id_ == 0)
     return true;
 
-  // Import dmabuf fds into the output gl texture through EGLImage.
+  // Import dmabuf fds into the output gl texture through GLImage.
   if (make_context_current_cb_ && !make_context_current_cb_.Run())
     return false;
 
@@ -73,13 +79,77 @@
 
   const gfx::BufferFormat format = pixmap->GetBufferFormat();
 
-  auto image =
-      base::MakeRefCounted<gl::GLImageNativePixmap>(visible_size_, format);
-  if (!image->Initialize(std::move(pixmap))) {
-    LOG(ERROR) << "Failed to create GLImage";
+  switch (gl::GetGLImplementation()) {
+    case gl::kGLImplementationEGLGLES2:
+    case gl::kGLImplementationEGLANGLE:  { // EGL 
+        auto image = base::MakeRefCounted<gl::GLImageNativePixmap>(visible_size_, format);
+        if (!image->Initialize(std::move(pixmap))) {
+            LOG(ERROR) << "Failed to create GLImage (egl): " << visible_size_.ToString() << ", " << gfx::BufferFormatToString(format);
+            return false;
+        }
+        gl_image_ = image;
+    }
+    break;
+    
+    case gl::kGLImplementationDesktopGL: { // GLX
+        auto image = base::MakeRefCounted<gl::GLImageGLXNativePixmap>(visible_size_, gfx::BufferFormat::BGRX_8888); // format: taken from vaapi_picture_tfp
+        if (!image->Initialize(std::move(pixmap))) {
+            LOG(ERROR) << "Failed to create GLImage (glx): " << visible_size_.ToString() << ", " << gfx::BufferFormatToString(format);
+            return false;
+        }
+        gl_image_ = image;
+    }
+    break;
+    
+    default:
+      NOTREACHED();
+      return false;
+  }  
+  
+  if (!gl_image_->BindTexImage(texture_target_)) {
+    LOG(ERROR) << "Failed to bind texture to GLImage";
+    return false;
+  }
+
+  if (bind_image_cb_ &&
+      !bind_image_cb_.Run(client_texture_id_, texture_target_, gl_image_,
+                          true /* can_bind_to_sampler */)) {
+    LOG(ERROR) << "Failed to bind client_texture_id";
+    return false;
+  }
+
+  return true;
+}
+
+bool VaapiPictureNativePixmapOzone::InitializeXPixmap(gfx::BufferFormat format) { /// ONLY called for glx mode!
+ 
+  // simeon: for xpixmap, we do NOT create a VA Surface (instead it will be created automatically by VaapiVideoDecodeAccelerator).
+    
+//   // Create a |va_surface_| for xpixmap
+//   va_surface_ = vaapi_wrapper_->CreateVASurfaceForXPixmap(x_pixmap_, format, visible_size_);
+//   if (!va_surface_) {
+//     LOG(ERROR) << "Failed creating VASurface for NativePixmap";
+//     return false;
+//   }
+    
+  // ARC++ has no texture ids.
+  if (texture_id_ == 0 && client_texture_id_ == 0) {
+    return true;
+  }
+
+  // Import dmabuf fds into the output gl texture through GLImage.
+  if (make_context_current_cb_ && !make_context_current_cb_.Run()) {
     return false;
   }
+    
+  gl::ScopedTextureBinder texture_binder(texture_target_, texture_id_);
 
+  auto image = base::MakeRefCounted<gl::GLImageGLX>(visible_size_, gfx::BufferFormat::BGRX_8888); // format: taken from vaapi_picture_tfp
+  if (!image->Initialize(x_pixmap_)) {
+    LOG(ERROR) << "Failed to create GLImage (glx) from XPixmap: " << visible_size_.ToString() << ", " << gfx::BufferFormatToString(format);
+    return false;
+  }
+  
   gl_image_ = image;
   if (!gl_image_->BindTexImage(texture_target_)) {
     LOG(ERROR) << "Failed to bind texture to GLImage";
@@ -104,9 +174,24 @@
   auto pixmap = factory->CreateNativePixmap(
       gfx::kNullAcceleratedWidget, VK_NULL_HANDLE, size_, format,
       gfx::BufferUsage::SCANOUT_VDA_WRITE, /*framebuffer_size=*/visible_size_);
+  
   if (!pixmap) {
-    LOG(ERROR) << "Failed allocating a pixmap";
-    return false;
+      if (gl::GetGLImplementation() == gl::kGLImplementationDesktopGL) { // GLX : fallback mechanism: allocate XPixmap:          
+        LOG(WARNING) << "Failed to allocate gbm buffer, falling back on XPixmap.";  
+        auto* display = gfx::GetXDisplay();
+        const int depth = 24;  // simeon: depth might depend on the selected profile/video in VaapiVideoDecodeAccelerator.. However, 24 bit seems to work (12bit not).
+        x_pixmap_ = XCreatePixmap(display, DefaultRootWindow(display),
+                            visible_size_.width(), visible_size_.height(), depth);
+        if (!x_pixmap_) {
+            LOG(ERROR) << "Failed creating an XPixmap. Hardware acceleration will NOT work.";
+            return false;
+        }
+        
+        return InitializeXPixmap(format);
+      } else {      
+        LOG(ERROR) << "Failed allocating a pixmap";
+        return false;
+      }
   }
 
   return Initialize(std::move(pixmap));
@@ -141,4 +226,21 @@
   return Initialize(std::move(pixmap));
 }
 
+VASurfaceID VaapiPictureNativePixmapOzone::va_surface_id() const {
+  if (x_pixmap_) { /// for xpixmap fallback mode, vaSurface will be allocated by VaapiVideoDecodeAccelerator
+    return VA_INVALID_ID;      
+  } else {
+    return VaapiPictureNativePixmap::va_surface_id();
+  }
+}
+
+bool VaapiPictureNativePixmapOzone::DownloadFromSurface(scoped_refptr<VASurface> va_surface) {
+  if (x_pixmap_) {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    return vaapi_wrapper_->PutSurfaceIntoPixmap(va_surface->id(), x_pixmap_, va_surface->size());
+  } else {
+      return VaapiPictureNativePixmap::DownloadFromSurface(va_surface);
+  }
+}
+
 }  // namespace media
Index: dev/src/3rdparty/chromium/ui/gfx/linux/BUILD.gn
===================================================================
*** dev.orig/src/3rdparty/chromium/ui/gfx/linux/BUILD.gn
+++ dev/src/3rdparty/chromium/ui/gfx/linux/BUILD.gn
@@ -5,7 +5,7 @@
 import("//build/config/ui.gni")
 import("//ui/ozone/ozone.gni")
 
-assert(use_x11 || ozone_platform_gbm || ozone_platform_wayland)
+assert(use_x11 || ozone_platform_gbm || ozone_platform_wayland || use_qt)
 
 source_set("drm") {
   sources = [
@@ -45,7 +45,7 @@
   ]
 }
 
-if (use_x11) {
+if (use_x11 || use_qt) {
   component("gpu_memory_buffer_support_x11") {
     configs += [ "//build/config/linux:x11" ]
     sources = [
Index: dev/src/3rdparty/chromium/ui/gfx/x/BUILD.gn
===================================================================
--- dev.orig/src/3rdparty/chromium/ui/gfx/x/BUILD.gn
+++ dev/src/3rdparty/chromium/ui/gfx/x/BUILD.gn
@@ -6,7 +6,7 @@
 import("//build/config/ui.gni")
 import("//ui/ozone/ozone.gni")
 
-assert(use_x11 || ozone_platform_x11)
+assert(use_x11 || ozone_platform_x11 || use_qt)
 
 jumbo_component("x") {
   output_name = "gfx_x11"

Index: dev/src/core/ozone/drm_render_node_handle.h
===================================================================
*** dev.orig/src/core/ozone/drm_render_node_handle.h
+++ dev/src/core/ozone/drm_render_node_handle.h
@@ -0,0 +1,34 @@
+/// simeon: copied from ui/ozone/platforms/wayland/gpu
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_WAYLAND_GPU_DRM_RENDER_NODE_HANDLE_H_
+#define UI_OZONE_PLATFORM_WAYLAND_GPU_DRM_RENDER_NODE_HANDLE_H_
+
+#include "base/files/file_path.h"
+#include "base/files/scoped_file.h"
+#include "base/macros.h"
+
+namespace ui {
+
+// A wrapper around a DRM render node device handle.
+class DrmRenderNodeHandle {
+ public:
+  DrmRenderNodeHandle();
+  ~DrmRenderNodeHandle();
+
+  bool Initialize(const base::FilePath& path);
+
+  base::ScopedFD PassFD();
+
+ private:
+  base::ScopedFD drm_fd_;
+
+  DISALLOW_COPY_AND_ASSIGN(DrmRenderNodeHandle);
+};
+
+}  // namespace ui
+
+#endif  // UI_OZONE_PLATFORM_WAYLAND_GPU_DRM_RENDER_NODE_HANDLE_H_
+
Index: dev/src/core/ozone/drm_render_node_handle.cpp
===================================================================
*** dev.orig/src/core/ozone/drm_render_node_handle.cpp
+++ dev/src/core/ozone/drm_render_node_handle.cpp
@@ -0,0 +1,39 @@
+/// simeon: copied from ui/ozone/platforms/wayland/gpu
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "drm_render_node_handle.h"
+
+#include <fcntl.h>
+#include <xf86drm.h>
+
+namespace ui {
+
+DrmRenderNodeHandle::DrmRenderNodeHandle() = default;
+
+DrmRenderNodeHandle::~DrmRenderNodeHandle() = default;
+
+bool DrmRenderNodeHandle::Initialize(const base::FilePath& path) {
+  LOG(WARNING) << "Initialize DrmRenderNode: " << path.value().c_str();
+
+  base::ScopedFD drm_fd(open(path.value().c_str(), O_RDWR));
+  if (drm_fd.get() < 0)
+    return false;
+
+  drmVersionPtr drm_version = drmGetVersion(drm_fd.get());
+  if (!drm_version) {
+    LOG(FATAL) << "Can't get version for device: '" << path << "'";
+    return false;
+  }
+
+  drm_fd_ = std::move(drm_fd);
+  return true;
+}
+
+base::ScopedFD DrmRenderNodeHandle::PassFD() {
+  return std::move(drm_fd_);
+}
+
+}  // namespace ui
+
Index: dev/src/core/ozone/drm_render_node_path_finder.h
===================================================================
*** dev.orig/src/core/ozone/drm_render_node_path_finder.h
+++ dev/src/core/ozone/drm_render_node_path_finder.h
@@ -0,0 +1,35 @@
+/// simeon: copied from ui/ozone/platforms/wayland/gpu
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_WAYLAND_GPU_DRM_RENDER_NODE_PATH_FINDER_H_
+#define UI_OZONE_PLATFORM_WAYLAND_GPU_DRM_RENDER_NODE_PATH_FINDER_H_
+
+#include "base/files/file_path.h"
+#include "base/macros.h"
+
+namespace ui {
+
+// A helper class that finds a DRM render node device and returns a path to it.
+class DrmRenderNodePathFinder {
+ public:
+  // Triggers FindDrmRenderNodePath.
+  DrmRenderNodePathFinder();
+  ~DrmRenderNodePathFinder();
+
+  // Returns a path to a drm render node device.
+  base::FilePath GetDrmRenderNodePath() const;
+
+ private:
+  void FindDrmRenderNodePath();
+
+  base::FilePath drm_render_node_path_;
+
+  DISALLOW_COPY_AND_ASSIGN(DrmRenderNodePathFinder);
+};
+
+}  // namespace ui
+
+#endif  // UI_OZONE_PLATFORM_WAYLAND_GPU_DRM_RENDER_NODE_PATH_FINDER_H_
+
Index: dev/src/core/ozone/drm_render_node_path_finder.cc
===================================================================
*** dev.orig/src/core/ozone/drm_render_node_path_finder.cpp
+++ dev/src/core/ozone/drm_render_node_path_finder.cpp
@@ -0,0 +1,66 @@
+/// simeon: copied from ui/ozone/platforms/wayland/gpu
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "drm_render_node_path_finder.h"
+
+#include <fcntl.h>
+#include <cstdlib>
+
+#include "base/files/scoped_file.h"
+#include "base/strings/stringprintf.h"
+
+namespace ui {
+
+namespace {
+
+// Drm render node path template.
+constexpr char kDriRenderNodeTemplate[] = "/dev/dri/renderD%u";
+
+// Number of files to look for when discovering DRM devices.
+constexpr uint32_t kDrmMaxMinor = 15;
+constexpr uint32_t kRenderNodeStart = 128;
+constexpr uint32_t kRenderNodeEnd = kRenderNodeStart + kDrmMaxMinor + 1;
+
+}  // namespace
+
+DrmRenderNodePathFinder::DrmRenderNodePathFinder() {
+  FindDrmRenderNodePath();
+}
+
+DrmRenderNodePathFinder::~DrmRenderNodePathFinder() = default;
+
+base::FilePath DrmRenderNodePathFinder::GetDrmRenderNodePath() const {
+  return drm_render_node_path_;
+}
+
+void DrmRenderNodePathFinder::FindDrmRenderNodePath() {
+    
+  // simeon: check env variable to specify custom render path
+  const char* env_gf_render_node = std::getenv("GF_WEBENGINE_GBM_DEVICE");
+  if (env_gf_render_node) {
+      LOG(WARNING) << "Try custom drm render path.";
+      std::string dri_render_node(env_gf_render_node);
+      base::ScopedFD drm_fd(open(dri_render_node.c_str(), O_RDWR));
+      if (drm_fd.get() < 0) {
+        LOG(ERROR) << "Custom drm render path is invalid: " << env_gf_render_node;
+      } else {
+        LOG(WARNING) << "Check passed. Use custom render path: " << env_gf_render_node;
+        drm_render_node_path_ = base::FilePath(dri_render_node);
+      }
+        return;
+  }
+    
+  for (uint32_t i = kRenderNodeStart; i < kRenderNodeEnd; i++) {
+    std::string dri_render_node(base::StringPrintf(kDriRenderNodeTemplate, i));
+    base::ScopedFD drm_fd(open(dri_render_node.c_str(), O_RDWR));
+    if (drm_fd.get() < 0)
+      continue;
+
+    drm_render_node_path_ = base::FilePath(dri_render_node);
+    break;
+  }
+}
+
+}  // namespace ui
+
Index: dev/src/core/ozone/surface_factory_qt.h
===================================================================
*** dev.orig/src/core/ozone/surface_factory_qt.h
+++ dev/src/core/ozone/surface_factory_qt.h
@@ -43,18 +43,44 @@
 #if defined(USE_OZONE)
 
 #include "ui/ozone/public/surface_factory_ozone.h"
+#include "third_party/minigbm/src/gbm.h" /// simeon: necessary, since gbm_wrapper might include "wrong" gbm.h from system (with some defines missing).
+#include "ui/gfx/linux/gbm_wrapper.h"
 
 namespace QtWebEngineCore {
 
 class SurfaceFactoryQt : public ui::SurfaceFactoryOzone
 {
 public:
-    SurfaceFactoryQt();
+    SurfaceFactoryQt(std::unique_ptr<ui::GbmDevice> gbm);
     std::vector<gl::GLImplementation> GetAllowedGLImplementations() override;
     ui::GLOzone* GetGLOzone(gl::GLImplementation implementation) override;
+
+    /// simeon: added
+    scoped_refptr<gfx::NativePixmap> CreateNativePixmap(
+      gfx::AcceleratedWidget widget,
+      VkDevice vk_device,
+      gfx::Size size,
+      gfx::BufferFormat format,
+      gfx::BufferUsage usage,
+      base::Optional<gfx::Size> framebuffer_size = base::nullopt) override;
+    void CreateNativePixmapAsync(gfx::AcceleratedWidget widget,
+                               VkDevice vk_device,
+                               gfx::Size size,
+                               gfx::BufferFormat format,
+                               gfx::BufferUsage usage,
+                               NativePixmapCallback callback) override;
+    scoped_refptr<gfx::NativePixmap> CreateNativePixmapFromHandle(
+      gfx::AcceleratedWidget widget,
+      gfx::Size size,
+      gfx::BufferFormat format,
+      gfx::NativePixmapHandle handle) override;
+      
 private:
     gl::GLImplementation m_impl;
     std::unique_ptr<ui::GLOzone> m_ozone;
+
+    /// simeon added:
+    std::unique_ptr<ui::GbmDevice> gbm_device;
 };
 
 } // namespace QtWebEngineCore
Index: dev/src/core/ozone/surface_factory_qt.cpp
===================================================================
--- dev.orig/src/core/ozone/surface_factory_qt.cpp
+++ dev/src/core/ozone/surface_factory_qt.cpp
@@ -46,19 +46,33 @@
 #include "ozone/gl_ozone_glx_qt.h"
 #endif
 
+/// simeon: added
+#include "ui/gfx/buffer_format_util.h"
+#include "ui/gfx/buffer_usage_util.h"
+#include "ui/gfx/linux/native_pixmap_dmabuf.h"
+#include "ui/gfx/linux/drm_util_linux.h"
+#include "ui/gfx/linux/gbm_buffer.h"
+#include "ui/gfx/linux/gbm_util.h"
+
+#include <cstdlib>
+
+using namespace ui;
+
 namespace QtWebEngineCore {
 
-SurfaceFactoryQt::SurfaceFactoryQt()
+SurfaceFactoryQt::SurfaceFactoryQt(std::unique_ptr<GbmDevice> gbm) : gbm_device(std::move(gbm))
 {
 #if defined(USE_GLX)
     if (GLContextHelper::getGlXConfig()) {
         m_impl = gl::kGLImplementationDesktopGL;
         m_ozone.reset(new ui::GLOzoneGLXQt());
+       LOG(WARNING) << "surface factory qt: use glx backend.";
     } else
 #endif
     if (GLContextHelper::getEGLConfig()) {
         m_impl = gl::kGLImplementationEGLGLES2;
         m_ozone.reset(new ui::GLOzoneEGLQt());
+       LOG(WARNING) << "surface factory qt: use egl backend.";
     } else {
         qFatal("No suitable graphics backend found\n");
     }
@@ -74,6 +88,80 @@
     return m_ozone.get();
 }
 
+/// simeon: added
+scoped_refptr<gfx::NativePixmap> SurfaceFactoryQt::CreateNativePixmap(
+    gfx::AcceleratedWidget widget,
+    VkDevice vk_device,
+    gfx::Size size,
+    gfx::BufferFormat format,
+    gfx::BufferUsage usage,
+    base::Optional<gfx::Size> framebuffer_size) {
+        
+    if (framebuffer_size &&
+        !gfx::Rect(size).Contains(gfx::Rect(*framebuffer_size))) {
+      return nullptr;
+    }
+
+    if (!gbm_device) {
+        LOG(ERROR) << "Gbm Device not initialized.";
+        return nullptr;
+    }
+    
+    const char* disable_gbm_buffer_allocation = std::getenv("GF_DISABLE_GBM_ALLOCATION");
+    if (disable_gbm_buffer_allocation) {
+        LOG(WARNING) << "Skipping gbm buffer allocation due to environment variable GF_DISABLE_GBM_ALLOCATION.";
+        return nullptr;
+    }
+    
+    uint32_t gbmFlags = BufferUsageToGbmFlags(usage);
+    std::unique_ptr<GbmBuffer> buffer = gbm_device->CreateBuffer(GetFourCCFormatFromBufferFormat(format), size, gbmFlags);
+    
+    if (!buffer) {
+      if (format == gfx::BufferFormat::RGBX_8888) { 
+        LOG(WARNING) << "Gbm Buffer allocation failed. Retry with changed flags.";
+        /// intel driver does not support GBM_BO_USE_HW_VIDEO_DECODER for RGBX_8888, however it seems not necessary anyways..
+        gbmFlags &= ~GBM_BO_USE_HW_VIDEO_DECODER;
+        // try once again
+        buffer = gbm_device->CreateBuffer(GetFourCCFormatFromBufferFormat(format), size, gbmFlags);
+      }
+    }
+    
+    if (!buffer) {
+      if (m_impl == gl::kGLImplementationDesktopGL) {
+        LOG(ERROR) << "Failed to create native buffer, fallback to XPixmap allocation.";
+      } else {
+        LOG(ERROR) << "Failed to create native buffer. HW acceleration will NOT work.";
+      }
+      return nullptr;
+    }
+    
+    /// create a Native dma-buf pixmap from buffer:
+    return base::MakeRefCounted<gfx::NativePixmapDmaBuf>(size, format, std::move(buffer->ExportHandle()));
+}
+
+void SurfaceFactoryQt::CreateNativePixmapAsync(
+    gfx::AcceleratedWidget widget,
+    VkDevice vk_device,
+    gfx::Size size,
+    gfx::BufferFormat format,
+    gfx::BufferUsage usage,
+    NativePixmapCallback callback) {
+  // CreateNativePixmap is non-blocking operation. Thus, it is safe to call it
+  // and return the result with the provided callback.
+  std::move(callback).Run(
+      CreateNativePixmap(widget, vk_device, size, format, usage));
+}
+
+scoped_refptr<gfx::NativePixmap>
+SurfaceFactoryQt::CreateNativePixmapFromHandle(
+    gfx::AcceleratedWidget widget,
+    gfx::Size size,
+    gfx::BufferFormat format,
+    gfx::NativePixmapHandle handle) {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
 } // namespace QtWebEngineCore
 #endif // defined(USE_OZONE)
 
Index: dev/src/core/ozone/ozone_platform_qt.cpp
===================================================================
--- dev.orig/src/core/ozone/ozone_platform_qt.cpp
+++ dev/src/core/ozone/ozone_platform_qt.cpp
@@ -53,6 +53,11 @@
 #include "ui/platform_window/platform_window_delegate.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
+#include "ui/gfx/linux/client_native_pixmap_dmabuf.h"
+#include "ui/gfx/linux/gbm_wrapper.h"
+#include "drm_render_node_handle.h"
+#include "drm_render_node_path_finder.h"
+
 #include "surface_factory_qt.h"
 #include "platform_window_qt.h"
 
@@ -75,6 +80,8 @@
     ui::OverlayManagerOzone* GetOverlayManager() override;
     std::unique_ptr<InputMethod> CreateInputMethod(internal::InputMethodDelegate *delegate, gfx::AcceleratedWidget widget) override;
     std::unique_ptr<ui::PlatformScreen> CreateScreen() override { return nullptr; }
+    bool IsNativePixmapConfigSupported(gfx::BufferFormat format, gfx::BufferUsage usage) const override;
+
 private:
     void InitializeUI(const ui::OzonePlatform::InitParams &) override;
     void InitializeGPU(const ui::OzonePlatform::InitParams &) override;
@@ -86,6 +93,8 @@
     std::unique_ptr<InputController> input_controller_;
     std::unique_ptr<OverlayManagerOzone> overlay_manager_;
 
+    DrmRenderNodePathFinder path_finder_;
+    
     DISALLOW_COPY_AND_ASSIGN(OzonePlatformQt);
 };
 
@@ -135,6 +144,19 @@
     return nullptr;
 }
 
+bool OzonePlatformQt::IsNativePixmapConfigSupported(gfx::BufferFormat format,
+                                   gfx::BufferUsage usage) const 
+{
+  // If there is no drm render node device available, native pixmaps are not
+  // supported.
+  const base::FilePath drm_node_path = path_finder_.GetDrmRenderNodePath();
+  if (drm_node_path.empty()) {
+    return false;
+  }
+  
+  return gfx::ClientNativePixmapDmaBuf::IsConfigurationSupported(format, usage);
+}
+
 void OzonePlatformQt::InitializeUI(const ui::OzonePlatform::InitParams &)
 {
     overlay_manager_.reset(new StubOverlayManager());
@@ -145,7 +168,24 @@
 
 void OzonePlatformQt::InitializeGPU(const ui::OzonePlatform::InitParams &)
 {
-    surface_factory_ozone_.reset(new QtWebEngineCore::SurfaceFactoryQt());
+    const base::FilePath drm_node_path = path_finder_.GetDrmRenderNodePath();
+    if (drm_node_path.empty()) {
+      LOG(WARNING) << "Failed to find drm render node path.";
+    } else {
+      DrmRenderNodeHandle handle;
+      if (!handle.Initialize(drm_node_path)) {
+        LOG(WARNING) << "Failed to initialize drm render node handle.";
+      } else {
+        auto gbm = CreateGbmDevice(handle.PassFD().release());
+        if (!gbm)
+          LOG(WARNING) << "Failed to initialize gbm device.";
+        surface_factory_ozone_ = std::make_unique<QtWebEngineCore::SurfaceFactoryQt>(std::move(gbm));
+        return;
+      }
+    }
+    
+    /// fallback:
+    surface_factory_ozone_ = std::make_unique<QtWebEngineCore::SurfaceFactoryQt>(nullptr);
 }
 
 std::unique_ptr<InputMethod> OzonePlatformQt::CreateInputMethod(internal::InputMethodDelegate *, gfx::AcceleratedWidget)
Index: dev/src/core/ozone/BUILD.gn
===================================================================
*** dev.orig/src/core/ozone/BUILD.gn
+++ dev/src/core/ozone/BUILD.gn
@@ -6,6 +6,12 @@
   sources = [
     "ozone_platform_qt.h",
     "ozone_platform_qt.cpp",
+    
+    # simeon: added
+    "drm_render_node_handle.h",
+    "drm_render_node_handle.cpp",
+    "drm_render_node_path_finder.cpp",
+    "drm_render_node_path_finder.h",
   ]
 
   import("//ui/base/ui_features.gni")
@@ -15,6 +21,14 @@
     "//base",
     "//ui/ozone:ozone_base",
     "//ui/ozone/common",
+    
+    # simeon: added
+    "//build/config/linux/libdrm",
+    "//third_party/minigbm",
+    "//ui/gfx",
+    "//ui/gl",
+    "//ui/gfx/linux:gbm",
+    "//ui/gfx/linux:drm",
   ]
 
   defines = [ "OZONE_IMPLEMENTATION" ]
 Index: dev/src/3rdparty/chromium/third_party/minigbm/BUILD.gn
===================================================================
*** dev.orig/src/3rdparty/chromium/third_party/minigbm/BUILD.gn
+++ dev/src/3rdparty/chromium/third_party/minigbm/BUILD.gn
@@ -65,7 +65,7 @@
     }
   }
 
-  shared_library("minigbm") {
+  static_library("minigbm") {
     sources = [
       "src/amdgpu.c",
       "src/drv.c",
 Index: dev/src/3rdparty/chromium/ui/gfx/linux/gbm_wrapper.cc
==============================================================
--- dev.orig/src/3rdparty/chromium/ui/gfx/linux/gbm_wrapper.cc
+++ dev/src/3rdparty/chromium/ui/gfx/linux/gbm_wrapper.cc
@@ -385,8 +385,12 @@
 
 std::unique_ptr<GbmDevice> CreateGbmDevice(int fd) {
   gbm_device* device = gbm_create_device(fd);
-  if (!device)
+  if (!device) {
+    LOG(ERROR) << "Failed to create GbmDevice.";
     return nullptr;
+  } else {
+    LOG(WARNING) << "Created GbmDevice with backend: " << gbm_device_get_backend_name(device);
+  }
   return std::make_unique<gbm_wrapper::Device>(device);
 }

  Index: dev/src/3rdparty/chromium/ui/gl/gl_image_glx_native_pixmap.h
==============================================================
--- dev.orig/src/3rdparty/chromium/ui//gl/gl_image_glx_native_pixmap.h
+++ dev/src/3rdparty/chromium/ui//gl/gl_image_glx_native_pixmap.h
@@ -13,6 +13,9 @@
 #include "ui/gl/gl_export.h"
 #include "ui/gl/gl_image_glx.h"
 
+// simeon: added
+#include "ui/gfx/x/x11_types.h"
+
 namespace gl {
 
 class GL_EXPORT GLImageGLXNativePixmap : public GLImageGLX {
@@ -25,6 +28,8 @@
 
  private:
   scoped_refptr<gfx::NativePixmap> native_pixmap_;
+  // simeon: added
+  XID x_pixmap_id_;
 
   DISALLOW_COPY_AND_ASSIGN(GLImageGLXNativePixmap);
 };
  Index: dev/src/3rdparty/chromium/ui/gl/gl_image_glx_native_pixmap.cc
==============================================================
--- dev.orig/src/3rdparty/chromium/ui//gl/gl_image_glx_native_pixmap.cc
+++ dev/src/3rdparty/chromium/ui//gl/gl_image_glx_native_pixmap.cc
@@ -72,17 +72,24 @@
 
 GLImageGLXNativePixmap::GLImageGLXNativePixmap(const gfx::Size& size,
                                                gfx::BufferFormat format)
-    : GLImageGLX(size, format) {}
+    : GLImageGLX(size, format), x_pixmap_id_(0) {}
 
-GLImageGLXNativePixmap::~GLImageGLXNativePixmap() = default;
+GLImageGLXNativePixmap::~GLImageGLXNativePixmap() 
+{    
+  if (x_pixmap_id_) {
+    XFreePixmap(gfx::GetXDisplay(), x_pixmap_id_);
+  }
+}
 
 bool GLImageGLXNativePixmap::Initialize(
     scoped_refptr<gfx::NativePixmap> pixmap) {
   native_pixmap_ = pixmap;
 
-  return GLImageGLX::Initialize(XPixmapFromNativePixmap(
+  x_pixmap_id_ = XPixmapFromNativePixmap(
       *static_cast<gfx::NativePixmapDmaBuf*>(native_pixmap_.get()),
-      Depth(format()), Bpp(format())));
+      Depth(format()), Bpp(format()));
+  
+  return GLImageGLX::Initialize(x_pixmap_id_);
 }
 
 }  // namespace gl

 Index: dev/src/3rdparty/chromium/media/gpu/vaapi/va_stub_header.fragment
==============================================================
--- dev.orig/src/3rdparty/chromium/media/gpu/vaapi/va_stub_header.fragment
+++ dev/src/src/3rdparty/chromium/media/gpu/vaapi/va_stub_header.fragment
@@ -5,8 +5,8 @@
 
 #include <va/va_drm.h>
 #include <va/va.h>
-#if defined(USE_X11)
+//#if defined(USE_X11)
 #include <va/va_x11.h>
-#endif
+//#endif
 
 }
 Index: dev/src/3rdparty/chromium/media/gpu/vaapi/vaapi_wrapper.h
==============================================================
--- dev.orig/src/3rdparty/chromium/media/gpu/vaapi/vaapi_wrapper.h
+++ dev/src/src/3rdparty/chromium/media/gpu/vaapi/vaapi_wrapper.h
@@ -32,9 +32,9 @@
 #include "media/video/video_encode_accelerator.h"
 #include "ui/gfx/geometry/size.h"
 
-#if defined(USE_X11)
+//#if defined(USE_X11)
 #include "ui/gfx/x/x11.h"
-#endif  // USE_X11
+//#endif  // USE_X11
 
 namespace gfx {
 enum class BufferFormat;
@@ -324,13 +324,13 @@
   // buffers. Return false if Execute() fails.
   bool ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id);
 
-#if defined(USE_X11)
+//#if defined(USE_X11)
   // Put data from |va_surface_id| into |x_pixmap| of size
   // |dest_size|, converting/scaling to it.
   bool PutSurfaceIntoPixmap(VASurfaceID va_surface_id,
                             Pixmap x_pixmap,
                             gfx::Size dest_size);
-#endif  // USE_X11
+//#endif  // USE_X11
 
   // Creates a ScopedVAImage from a VASurface |va_surface_id| and map it into
   // memory with the given |format| and |size|. If |format| is not equal to the
 Index: dev/src/3rdparty/chromium/media/gpu/vaapi/vaapi_wrapper.cc
==============================================================
--- dev.orig/src/3rdparty/chromium/media/gpu/vaapi/vaapi_wrapper.cc
+++ dev/src/src/3rdparty/chromium/media/gpu/vaapi/vaapi_wrapper.cc 
@@ -54,26 +54,28 @@
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_implementation.h"
 
-#if defined(USE_X11)
+//#if defined(USE_X11)
 #include <va/va_x11.h>
 #include "ui/gfx/x/x11_types.h"  // nogncheck
-#endif
+//#endif
 
 #if defined(USE_OZONE)
 #include "ui/ozone/public/ozone_platform.h"
 #include "ui/ozone/public/surface_factory_ozone.h"
 #endif
 
+#include <cstdlib>
+
 using media_gpu_vaapi::kModuleVa;
 using media_gpu_vaapi::kModuleVa_drm;
-#if defined(USE_X11)
+//#if defined(USE_X11)
 using media_gpu_vaapi::kModuleVa_x11;
-#endif
+//#endif
 using media_gpu_vaapi::InitializeStubs;
 using media_gpu_vaapi::IsVaInitialized;
-#if defined(USE_X11)
+//#if defined(USE_X11)
 using media_gpu_vaapi::IsVa_x11Initialized;
-#endif
+//#endif
 using media_gpu_vaapi::IsVa_drmInitialized;
 using media_gpu_vaapi::StubPathMap;
 
@@ -359,7 +361,10 @@
   VADisplay va_display() const { return va_display_; }
   const std::string& va_vendor_string() const { return va_vendor_string_; }
 
-  void SetDrmFd(base::PlatformFile fd) { drm_fd_.reset(HANDLE_EINTR(dup(fd))); }
+  void SetDrmFd(base::PlatformFile fd, bool gf_apply_custom_vaapi_device) { 
+    drm_fd_.reset(HANDLE_EINTR(dup(fd))); 
+    gf_use_custom_vaapi_device_=gf_apply_custom_vaapi_device;
+  }
 
  private:
   friend class base::NoDestructor<VADisplayState>;
@@ -380,6 +385,8 @@
   // Drm fd used to obtain access to the driver interface by VA.
   base::ScopedFD drm_fd_;
 
+  bool gf_use_custom_vaapi_device_;
+
   // The VADisplay handle.
   VADisplay va_display_;
 
@@ -400,12 +407,25 @@
 
 // static
 void VADisplayState::PreSandboxInitialization() {
+
+  const char *gf_vaapi_render_device = std::getenv("GF_WEBENGINE_VAAPI_DEVICE");
+  if (gf_vaapi_render_device) {
+    base::File gf_drm_file = base::File(
+        base::FilePath::FromUTF8Unsafe(gf_vaapi_render_device),
+        base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE);
+    if (gf_drm_file.IsValid()) {
+      LOG(WARNING) << "Use custom vaapi device: " << gf_vaapi_render_device;
+      VADisplayState::Get()->SetDrmFd(gf_drm_file.GetPlatformFile(), true);
+      return;
+    }
+  }
+  
   const char kDriRenderNode0Path[] = "/dev/dri/renderD128";
   base::File drm_file = base::File(
       base::FilePath::FromUTF8Unsafe(kDriRenderNode0Path),
       base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE);
   if (drm_file.IsValid()) {
-    VADisplayState::Get()->SetDrmFd(drm_file.GetPlatformFile());
+    VADisplayState::Get()->SetDrmFd(drm_file.GetPlatformFile(), false);
     return;
   }
 
@@ -414,20 +434,20 @@
       base::FilePath::FromUTF8Unsafe(kNvidiaPath),
       base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE);
   if(nvidia_file.IsValid()) {
-    VADisplayState::Get()->SetDrmFd(nvidia_file.GetPlatformFile());
+    VADisplayState::Get()->SetDrmFd(nvidia_file.GetPlatformFile(), false);
   }
 }
 
 VADisplayState::VADisplayState()
-    : refcount_(0), va_display_(nullptr), va_initialized_(false) {}
+    : refcount_(0), gf_use_custom_vaapi_device_(false), va_display_(nullptr), va_initialized_(false) {}
 
 bool VADisplayState::Initialize() {
   base::AutoLock auto_lock(va_lock_);
 
   if (!IsVaInitialized() ||
-#if defined(USE_X11)
+//#if defined(USE_X11)
       !IsVa_x11Initialized() ||
-#endif
+//#endif
       !IsVa_drmInitialized()) {
     return false;
   }
@@ -448,20 +468,24 @@
       va_display_ = vaGetDisplayDRM(drm_fd_.get());
       break;
     case gl::kGLImplementationDesktopGL:
-#if defined(USE_X11)
-      va_display_ = vaGetDisplay(gfx::GetXDisplay());
-      if (vaDisplayIsValid(va_display_))
-        break;
-#endif  // USE_X11
+//#if defined(USE_X11)
+      if (!gf_use_custom_vaapi_device_) {
+        va_display_ = vaGetDisplay(gfx::GetXDisplay());
+        if (vaDisplayIsValid(va_display_))
+          break;
+      }
+//#endif  // USE_X11
       va_display_ = vaGetDisplayDRM(drm_fd_.get());
       break;
     // Cannot infer platform from GL, try all available displays
     case gl::kGLImplementationNone:
-#if defined(USE_X11)
-      va_display_ = vaGetDisplay(gfx::GetXDisplay());
-      if (vaDisplayIsValid(va_display_))
-        break;
-#endif  // USE_X11
+//#if defined(USE_X11)
+      if (!gf_use_custom_vaapi_device_) {
+        va_display_ = vaGetDisplay(gfx::GetXDisplay());
+        if (vaDisplayIsValid(va_display_))
+          break;
+      }
+//#endif  // USE_X11
       va_display_ = vaGetDisplayDRM(drm_fd_.get());
       break;
 
@@ -1849,7 +1873,7 @@
   return result;
 }
 
-#if defined(USE_X11)
+//#if defined(USE_X11)
 bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id,
                                         Pixmap x_pixmap,
                                         gfx::Size dest_size) {
@@ -1868,7 +1892,7 @@
   VA_SUCCESS_OR_RETURN(va_res, "vaPutSurface", false);
   return true;
 }
-#endif  // USE_X11
+//#endif  // USE_X11
 
 std::unique_ptr<ScopedVAImage> VaapiWrapper::CreateVaImage(
     VASurfaceID va_surface_id,
@@ -2173,9 +2197,9 @@
 
   paths[kModuleVa].push_back(std::string("libva.so.") + va_suffix);
   paths[kModuleVa_drm].push_back(std::string("libva-drm.so.") + va_suffix);
-#if defined(USE_X11)
+//#if defined(USE_X11)
   paths[kModuleVa_x11].push_back(std::string("libva-x11.so.") + va_suffix);
-#endif
+//#endif
 
   // InitializeStubs dlopen() VA-API libraries
   // libva.so
 Index: dev/src/3rdparty/chromium/media/gpu/vaapi/BUILD.gn
==============================================================
--- dev.orig/src/3rdparty/chromium/media/gpu/vaapi/BUILD.gn
+++ dev/src/src/3rdparty/chromium/media/gpu/vaapi/BUILD.gn
@@ -16,9 +16,9 @@
 generate_stubs("libva_stubs") {
   extra_header = "va_stub_header.fragment"
   sigs = [ "va.sigs" ]
-  if (use_x11) {
+  #if (use_x11) {
     sigs += [ "va_x11.sigs" ]
-  }
+  #}
   sigs += [ "va_drm.sigs" ]
 
   output_name = "va_stubs"   
