[Libreoffice-commits] core.git: Branch 'feature/skia' - 3 commits - external/skia vcl/inc vcl/Library_vcl.mk vcl/skia
Luboš Luňák (via logerrit)
logerrit at kemper.freedesktop.org
Tue Nov 12 16:31:04 UTC 2019
external/skia/README | 6
external/skia/UnpackedTarball_skia.mk | 8
external/skia/share-grcontext.patch.1 | 499 ++++++++++++++++++++++++++++++++++
vcl/Library_vcl.mk | 3
vcl/inc/skia/gdiimpl.hxx | 6
vcl/inc/skia/vulkan.hxx | 29 -
vcl/inc/skia/x11/gdiimpl.hxx | 1
vcl/inc/test/outputdevice.hxx | 2
vcl/skia/README | 16 +
vcl/skia/gdiimpl.cxx | 72 ++++
vcl/skia/vulkan.cxx | 39 --
vcl/skia/win/gdiimpl.cxx | 22 -
vcl/skia/x11/gdiimpl.cxx | 54 +--
13 files changed, 631 insertions(+), 126 deletions(-)
New commits:
commit 55ee7805a4e0e13ded88682b643f84607aec4b02
Author: Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Tue Nov 12 16:10:50 2019 +0100
Commit: Luboš Luňák <l.lunak at collabora.com>
CommitDate: Tue Nov 12 17:29:51 2019 +0100
fix Skia offscreen GPU-backed drawing
The previous approach of using multiple GrContext instances apparently
does not work, it's not possible to do drawing operations that
involve objects using two different GrContext's. So patch Skia to use
just one GrContext for our needs. See vcl/skia/README for details.
Change-Id: I2bd3d3c618bf7f8ff45b2f37cbd086d2289940aa
diff --git a/external/skia/README b/external/skia/README
index 767f12e91936..95be1561d4fb 100644
--- a/external/skia/README
+++ b/external/skia/README
@@ -17,3 +17,9 @@ tar cvJf skia-mXX-$id.tar.xz skia
(where XX refers to the branch version)
And review differences for BUILD.gn and relevant files in gn/ .
+
+
+GrContext sharing
+=================
+
+For details about the share-grcontext patch, see vcl/skia/README.
diff --git a/external/skia/UnpackedTarball_skia.mk b/external/skia/UnpackedTarball_skia.mk
index e9905f5abfa7..c3988042a012 100644
--- a/external/skia/UnpackedTarball_skia.mk
+++ b/external/skia/UnpackedTarball_skia.mk
@@ -12,7 +12,13 @@ $(eval $(call gb_UnpackedTarball_UnpackedTarball,skia))
$(eval $(call gb_UnpackedTarball_set_tarball,skia,$(SKIA_TARBALL)))
# TODO
-skia_patches := lerp.patch fix-pch.patch fix-ddi.patch make-api-visible.patch.1 fix-shader-locale.patch.1
+skia_patches := \
+ lerp.patch \
+ fix-pch.patch \
+ fix-ddi.patch \
+ make-api-visible.patch.1 \
+ fix-shader-locale.patch.1 \
+ share-grcontext.patch.1
$(eval $(call gb_UnpackedTarball_set_patchlevel,skia,1))
diff --git a/external/skia/share-grcontext.patch.1 b/external/skia/share-grcontext.patch.1
new file mode 100644
index 000000000000..0492bd948240
--- /dev/null
+++ b/external/skia/share-grcontext.patch.1
@@ -0,0 +1,499 @@
+diff --git a/tools/sk_app/VulkanWindowContext.cpp b/tools/sk_app/VulkanWindowContext.cpp
+index 793c88c158..21164cac67 100644
+--- a/tools/sk_app/VulkanWindowContext.cpp
++++ b/tools/sk_app/VulkanWindowContext.cpp
+@@ -1,4 +1,3 @@
+-
+ /*
+ * Copyright 2015 Google Inc.
+ *
+@@ -24,8 +23,10 @@
+ #undef CreateSemaphore
+ #endif
+
+-#define GET_PROC(F) f ## F = (PFN_vk ## F) fGetInstanceProcAddr(fInstance, "vk" #F)
+-#define GET_DEV_PROC(F) f ## F = (PFN_vk ## F) fGetDeviceProcAddr(fDevice, "vk" #F)
++#define GET_PROC(F) f ## F = (PFN_vk ## F) fGetInstanceProcAddr(fShared->fInstance, "vk" #F)
++#define GET_DEV_PROC(F) f ## F = (PFN_vk ## F) fGetDeviceProcAddr(fShared->fDevice, "vk" #F)
++#define GET_PROC_GLOBAL(F) fGlobalShared->f ## F = (PFN_vk ## F) fGetInstanceProcAddr(fGlobalShared->fInstance, "vk" #F)
++#define GET_DEV_PROC_GLOBAL(F) fGlobalShared->f ## F = (PFN_vk ## F) fGetDeviceProcAddr(fGlobalShared->fDevice, "vk" #F)
+
+ namespace sk_app {
+
+@@ -49,6 +50,14 @@ VulkanWindowContext::VulkanWindowContext(const DisplayParams& params,
+ }
+
+ void VulkanWindowContext::initializeContext() {
++ fShared = fGlobalShared;
++ if( !fShared )
++ {
++ // TODO do we need a mutex?
++
++ fGlobalShared = sk_make_sp<Shared>();
++ Shared* d = fGlobalShared.get(); // shorter variable name
++
+ // any config code here (particularly for msaa)?
+
+ PFN_vkGetInstanceProcAddr getInstanceProc = fGetInstanceProcAddr;
+@@ -62,24 +71,25 @@ void VulkanWindowContext::initializeContext() {
+ };
+ GrVkBackendContext backendContext;
+ GrVkExtensions extensions;
+- VkPhysicalDeviceFeatures2 features;
+- if (!sk_gpu_test::CreateVkBackendContext(getProc, &backendContext, &extensions, &features,
+- &fDebugCallback, &fPresentQueueIndex, fCanPresentFn)) {
+- sk_gpu_test::FreeVulkanFeaturesStructs(&features);
++ if (!sk_gpu_test::CreateVkBackendContext(getProc, &backendContext, &extensions, &d->features,
++ &d->fDebugCallback, &d->fPresentQueueIndex, fCanPresentFn)) {
++ sk_gpu_test::FreeVulkanFeaturesStructs(&d->features);
++ fGlobalShared.reset();
+ return;
+ }
+
+ if (!extensions.hasExtension(VK_KHR_SURFACE_EXTENSION_NAME, 25) ||
+ !extensions.hasExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME, 68)) {
+- sk_gpu_test::FreeVulkanFeaturesStructs(&features);
++ sk_gpu_test::FreeVulkanFeaturesStructs(&d->features);
++ fGlobalShared.reset();
+ return;
+ }
+
+- fInstance = backendContext.fInstance;
+- fPhysicalDevice = backendContext.fPhysicalDevice;
+- fDevice = backendContext.fDevice;
+- fGraphicsQueueIndex = backendContext.fGraphicsQueueIndex;
+- fGraphicsQueue = backendContext.fQueue;
++ d->fInstance = backendContext.fInstance;
++ d->fPhysicalDevice = backendContext.fPhysicalDevice;
++ d->fDevice = backendContext.fDevice;
++ d->fGraphicsQueueIndex = backendContext.fGraphicsQueueIndex;
++ d->fGraphicsQueue = backendContext.fQueue;
+
+ PFN_vkGetPhysicalDeviceProperties localGetPhysicalDeviceProperties =
+ reinterpret_cast<PFN_vkGetPhysicalDeviceProperties>(
+@@ -87,21 +97,31 @@ void VulkanWindowContext::initializeContext() {
+ backendContext.fInstance,
+ VK_NULL_HANDLE));
+ if (!localGetPhysicalDeviceProperties) {
+- sk_gpu_test::FreeVulkanFeaturesStructs(&features);
++ sk_gpu_test::FreeVulkanFeaturesStructs(&d->features);
++ fGlobalShared.reset();
+ return;
+ }
+ VkPhysicalDeviceProperties physDeviceProperties;
+ localGetPhysicalDeviceProperties(backendContext.fPhysicalDevice, &physDeviceProperties);
+ uint32_t physDevVersion = physDeviceProperties.apiVersion;
+
+- fInterface.reset(new GrVkInterface(backendContext.fGetProc, fInstance, fDevice,
++ d->fInterface.reset(new GrVkInterface(backendContext.fGetProc, d->fInstance, d->fDevice,
+ backendContext.fInstanceVersion, physDevVersion,
+ &extensions));
+
+- GET_PROC(DestroyInstance);
+- if (fDebugCallback != VK_NULL_HANDLE) {
+- GET_PROC(DestroyDebugReportCallbackEXT);
++ d->fContext = GrContext::MakeVulkan(backendContext, fDisplayParams.fGrContextOptions);
++
++ GET_PROC_GLOBAL(DestroyInstance);
++ GET_DEV_PROC_GLOBAL(DestroyDevice);
++ if (fGlobalShared->fDebugCallback != VK_NULL_HANDLE) {
++ GET_PROC_GLOBAL(DestroyDebugReportCallbackEXT);
+ }
++
++ fShared = fGlobalShared;
++ } // if( !fShared )
++
++ fContext = fShared->fContext;
++
+ GET_PROC(DestroySurfaceKHR);
+ GET_PROC(GetPhysicalDeviceSurfaceSupportKHR);
+ GET_PROC(GetPhysicalDeviceSurfaceCapabilitiesKHR);
+@@ -109,7 +129,6 @@ void VulkanWindowContext::initializeContext() {
+ GET_PROC(GetPhysicalDeviceSurfacePresentModesKHR);
+ GET_DEV_PROC(DeviceWaitIdle);
+ GET_DEV_PROC(QueueWaitIdle);
+- GET_DEV_PROC(DestroyDevice);
+ GET_DEV_PROC(CreateSwapchainKHR);
+ GET_DEV_PROC(DestroySwapchainKHR);
+ GET_DEV_PROC(GetSwapchainImagesKHR);
+@@ -117,46 +136,40 @@ void VulkanWindowContext::initializeContext() {
+ GET_DEV_PROC(QueuePresentKHR);
+ GET_DEV_PROC(GetDeviceQueue);
+
+- fContext = GrContext::MakeVulkan(backendContext, fDisplayParams.fGrContextOptions);
+-
+- fSurface = fCreateVkSurfaceFn(fInstance);
++ fSurface = fCreateVkSurfaceFn(fShared->fInstance);
+ if (VK_NULL_HANDLE == fSurface) {
+ this->destroyContext();
+- sk_gpu_test::FreeVulkanFeaturesStructs(&features);
+ return;
+ }
+
+ VkBool32 supported;
+- VkResult res = fGetPhysicalDeviceSurfaceSupportKHR(fPhysicalDevice, fPresentQueueIndex,
++ VkResult res = fGetPhysicalDeviceSurfaceSupportKHR(fShared->fPhysicalDevice, fShared->fPresentQueueIndex,
+ fSurface, &supported);
+ if (VK_SUCCESS != res) {
+ this->destroyContext();
+- sk_gpu_test::FreeVulkanFeaturesStructs(&features);
+ return;
+ }
+
+ if (!this->createSwapchain(-1, -1, fDisplayParams)) {
+ this->destroyContext();
+- sk_gpu_test::FreeVulkanFeaturesStructs(&features);
+ return;
+ }
+
+ // create presentQueue
+- fGetDeviceQueue(fDevice, fPresentQueueIndex, 0, &fPresentQueue);
+- sk_gpu_test::FreeVulkanFeaturesStructs(&features);
++ fGetDeviceQueue(fShared->fDevice, fShared->fPresentQueueIndex, 0, &fPresentQueue);
+ }
+
+ bool VulkanWindowContext::createSwapchain(int width, int height,
+ const DisplayParams& params) {
+ // check for capabilities
+ VkSurfaceCapabilitiesKHR caps;
+- VkResult res = fGetPhysicalDeviceSurfaceCapabilitiesKHR(fPhysicalDevice, fSurface, &caps);
++ VkResult res = fGetPhysicalDeviceSurfaceCapabilitiesKHR(fShared->fPhysicalDevice, fSurface, &caps);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+
+ uint32_t surfaceFormatCount;
+- res = fGetPhysicalDeviceSurfaceFormatsKHR(fPhysicalDevice, fSurface, &surfaceFormatCount,
++ res = fGetPhysicalDeviceSurfaceFormatsKHR(fShared->fPhysicalDevice, fSurface, &surfaceFormatCount,
+ nullptr);
+ if (VK_SUCCESS != res) {
+ return false;
+@@ -164,14 +177,14 @@ bool VulkanWindowContext::createSwapchain(int width, int height,
+
+ SkAutoMalloc surfaceFormatAlloc(surfaceFormatCount * sizeof(VkSurfaceFormatKHR));
+ VkSurfaceFormatKHR* surfaceFormats = (VkSurfaceFormatKHR*)surfaceFormatAlloc.get();
+- res = fGetPhysicalDeviceSurfaceFormatsKHR(fPhysicalDevice, fSurface, &surfaceFormatCount,
++ res = fGetPhysicalDeviceSurfaceFormatsKHR(fShared->fPhysicalDevice, fSurface, &surfaceFormatCount,
+ surfaceFormats);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+
+ uint32_t presentModeCount;
+- res = fGetPhysicalDeviceSurfacePresentModesKHR(fPhysicalDevice, fSurface, &presentModeCount,
++ res = fGetPhysicalDeviceSurfacePresentModesKHR(fShared->fPhysicalDevice, fSurface, &presentModeCount,
+ nullptr);
+ if (VK_SUCCESS != res) {
+ return false;
+@@ -179,7 +192,7 @@ bool VulkanWindowContext::createSwapchain(int width, int height,
+
+ SkAutoMalloc presentModeAlloc(presentModeCount * sizeof(VkPresentModeKHR));
+ VkPresentModeKHR* presentModes = (VkPresentModeKHR*)presentModeAlloc.get();
+- res = fGetPhysicalDeviceSurfacePresentModesKHR(fPhysicalDevice, fSurface, &presentModeCount,
++ res = fGetPhysicalDeviceSurfacePresentModesKHR(fShared->fPhysicalDevice, fSurface, &presentModeCount,
+ presentModes);
+ if (VK_SUCCESS != res) {
+ return false;
+@@ -286,8 +299,8 @@ bool VulkanWindowContext::createSwapchain(int width, int height,
+ swapchainCreateInfo.imageArrayLayers = 1;
+ swapchainCreateInfo.imageUsage = usageFlags;
+
+- uint32_t queueFamilies[] = { fGraphicsQueueIndex, fPresentQueueIndex };
+- if (fGraphicsQueueIndex != fPresentQueueIndex) {
++ uint32_t queueFamilies[] = { fShared->fGraphicsQueueIndex, fShared->fPresentQueueIndex };
++ if (fShared->fGraphicsQueueIndex != fShared->fPresentQueueIndex) {
+ swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
+ swapchainCreateInfo.queueFamilyIndexCount = 2;
+ swapchainCreateInfo.pQueueFamilyIndices = queueFamilies;
+@@ -303,18 +316,18 @@ bool VulkanWindowContext::createSwapchain(int width, int height,
+ swapchainCreateInfo.clipped = true;
+ swapchainCreateInfo.oldSwapchain = fSwapchain;
+
+- res = fCreateSwapchainKHR(fDevice, &swapchainCreateInfo, nullptr, &fSwapchain);
++ res = fCreateSwapchainKHR(fShared->fDevice, &swapchainCreateInfo, nullptr, &fSwapchain);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+
+ // destroy the old swapchain
+ if (swapchainCreateInfo.oldSwapchain != VK_NULL_HANDLE) {
+- fDeviceWaitIdle(fDevice);
++ fDeviceWaitIdle(fShared->fDevice);
+
+ this->destroyBuffers();
+
+- fDestroySwapchainKHR(fDevice, swapchainCreateInfo.oldSwapchain, nullptr);
++ fDestroySwapchainKHR(fShared->fDevice, swapchainCreateInfo.oldSwapchain, nullptr);
+ }
+
+ this->createBuffers(swapchainCreateInfo.imageFormat, colorType);
+@@ -323,10 +336,10 @@ bool VulkanWindowContext::createSwapchain(int width, int height,
+ }
+
+ void VulkanWindowContext::createBuffers(VkFormat format, SkColorType colorType) {
+- fGetSwapchainImagesKHR(fDevice, fSwapchain, &fImageCount, nullptr);
++ fGetSwapchainImagesKHR(fShared->fDevice, fSwapchain, &fImageCount, nullptr);
+ SkASSERT(fImageCount);
+ fImages = new VkImage[fImageCount];
+- fGetSwapchainImagesKHR(fDevice, fSwapchain, &fImageCount, fImages);
++ fGetSwapchainImagesKHR(fShared->fDevice, fSwapchain, &fImageCount, fImages);
+
+ // set up initial image layouts and create surfaces
+ fImageLayouts = new VkImageLayout[fImageCount];
+@@ -341,7 +354,7 @@ void VulkanWindowContext::createBuffers(VkFormat format, SkColorType colorType)
+ info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
+ info.fFormat = format;
+ info.fLevelCount = 1;
+- info.fCurrentQueueFamily = fPresentQueueIndex;
++ info.fCurrentQueueFamily = fShared->fPresentQueueIndex;
+
+ if (fSampleCount == 1) {
+ GrBackendRenderTarget backendRT(fWidth, fHeight, fSampleCount, info);
+@@ -372,8 +385,8 @@ void VulkanWindowContext::createBuffers(VkFormat format, SkColorType colorType)
+ fBackbuffers = new BackbufferInfo[fImageCount + 1];
+ for (uint32_t i = 0; i < fImageCount + 1; ++i) {
+ fBackbuffers[i].fImageIndex = -1;
+- GR_VK_CALL_ERRCHECK(fInterface,
+- CreateSemaphore(fDevice, &semaphoreInfo,
++ GR_VK_CALL_ERRCHECK(fShared->fInterface,
++ CreateSemaphore(fShared->fDevice, &semaphoreInfo,
+ nullptr, &fBackbuffers[i].fRenderSemaphore));
+ }
+ fCurrentBackbufferIndex = fImageCount;
+@@ -384,8 +397,8 @@ void VulkanWindowContext::destroyBuffers() {
+ if (fBackbuffers) {
+ for (uint32_t i = 0; i < fImageCount + 1; ++i) {
+ fBackbuffers[i].fImageIndex = -1;
+- GR_VK_CALL(fInterface,
+- DestroySemaphore(fDevice,
++ GR_VK_CALL(fShared->fInterface,
++ DestroySemaphore(fShared->fDevice,
+ fBackbuffers[i].fRenderSemaphore,
+ nullptr));
+ }
+@@ -410,41 +423,55 @@ VulkanWindowContext::~VulkanWindowContext() {
+ void VulkanWindowContext::destroyContext() {
+ if (this->isValid()) {
+ fQueueWaitIdle(fPresentQueue);
+- fDeviceWaitIdle(fDevice);
++ fDeviceWaitIdle(fShared->fDevice);
+
+ this->destroyBuffers();
+
+ if (VK_NULL_HANDLE != fSwapchain) {
+- fDestroySwapchainKHR(fDevice, fSwapchain, nullptr);
++ fDestroySwapchainKHR(fShared->fDevice, fSwapchain, nullptr);
+ fSwapchain = VK_NULL_HANDLE;
+ }
+
+ if (VK_NULL_HANDLE != fSurface) {
+- fDestroySurfaceKHR(fInstance, fSurface, nullptr);
++ fDestroySurfaceKHR(fShared->fInstance, fSurface, nullptr);
+ fSurface = VK_NULL_HANDLE;
+ }
+ }
+
+ fContext.reset();
+- fInterface.reset();
++ fShared.reset();
++
++ checkDestroyShared();
++}
+
+- if (VK_NULL_HANDLE != fDevice) {
+- fDestroyDevice(fDevice, nullptr);
+- fDevice = VK_NULL_HANDLE;
++void VulkanWindowContext::checkDestroyShared()
++{
++ if(!fGlobalShared || !fGlobalShared->unique()) // TODO mutex?
++ return;
++ SkASSERT(fGlobalShared->fContext->unique());
++ fGlobalShared->fContext.reset();
++ fGlobalShared->fInterface.reset();
++
++ if (VK_NULL_HANDLE != fGlobalShared->fDevice) {
++ fGlobalShared->fDestroyDevice(fGlobalShared->fDevice, nullptr);
++ fGlobalShared->fDevice = VK_NULL_HANDLE;
+ }
+
+ #ifdef SK_ENABLE_VK_LAYERS
+- if (fDebugCallback != VK_NULL_HANDLE) {
+- fDestroyDebugReportCallbackEXT(fInstance, fDebugCallback, nullptr);
++ if (fGlobalShared->fDebugCallback != VK_NULL_HANDLE) {
++ fGlobalShared->fDestroyDebugReportCallbackEXT(fGlobalShared->fInstance, fDebugCallback, nullptr);
+ }
+ #endif
+
+- fPhysicalDevice = VK_NULL_HANDLE;
++ fGlobalShared->fPhysicalDevice = VK_NULL_HANDLE;
+
+- if (VK_NULL_HANDLE != fInstance) {
+- fDestroyInstance(fInstance, nullptr);
+- fInstance = VK_NULL_HANDLE;
++ if (VK_NULL_HANDLE != fGlobalShared->fInstance) {
++ fGlobalShared->fDestroyInstance(fGlobalShared->fInstance, nullptr);
++ fGlobalShared->fInstance = VK_NULL_HANDLE;
+ }
++
++ sk_gpu_test::FreeVulkanFeaturesStructs(&fGlobalShared->features);
++ fGlobalShared.reset();
+ }
+
+ VulkanWindowContext::BackbufferInfo* VulkanWindowContext::getAvailableBackbuffer() {
+@@ -470,34 +497,34 @@ sk_sp<SkSurface> VulkanWindowContext::getBackbufferSurface() {
+ semaphoreInfo.pNext = nullptr;
+ semaphoreInfo.flags = 0;
+ VkSemaphore semaphore;
+- GR_VK_CALL_ERRCHECK(fInterface, CreateSemaphore(fDevice, &semaphoreInfo,
++ GR_VK_CALL_ERRCHECK(fShared->fInterface, CreateSemaphore(fShared->fDevice, &semaphoreInfo,
+ nullptr, &semaphore));
+
+ // acquire the image
+- VkResult res = fAcquireNextImageKHR(fDevice, fSwapchain, UINT64_MAX,
++ VkResult res = fAcquireNextImageKHR(fShared->fDevice, fSwapchain, UINT64_MAX,
+ semaphore, VK_NULL_HANDLE,
+ &backbuffer->fImageIndex);
+ if (VK_ERROR_SURFACE_LOST_KHR == res) {
+ // need to figure out how to create a new vkSurface without the platformData*
+ // maybe use attach somehow? but need a Window
+- GR_VK_CALL(fInterface, DestroySemaphore(fDevice, semaphore, nullptr));
++ GR_VK_CALL(fShared->fInterface, DestroySemaphore(fShared->fDevice, semaphore, nullptr));
+ return nullptr;
+ }
+ if (VK_ERROR_OUT_OF_DATE_KHR == res) {
+ // tear swapchain down and try again
+ if (!this->createSwapchain(-1, -1, fDisplayParams)) {
+- GR_VK_CALL(fInterface, DestroySemaphore(fDevice, semaphore, nullptr));
++ GR_VK_CALL(fShared->fInterface, DestroySemaphore(fShared->fDevice, semaphore, nullptr));
+ return nullptr;
+ }
+ backbuffer = this->getAvailableBackbuffer();
+
+ // acquire the image
+- res = fAcquireNextImageKHR(fDevice, fSwapchain, UINT64_MAX,
++ res = fAcquireNextImageKHR(fShared->fDevice, fSwapchain, UINT64_MAX,
+ semaphore, VK_NULL_HANDLE,
+ &backbuffer->fImageIndex);
+
+ if (VK_SUCCESS != res) {
+- GR_VK_CALL(fInterface, DestroySemaphore(fDevice, semaphore, nullptr));
++ GR_VK_CALL(fShared->fInterface, DestroySemaphore(fShared->fDevice, semaphore, nullptr));
+ return nullptr;
+ }
+ }
+@@ -541,4 +568,6 @@ void VulkanWindowContext::swapBuffers() {
+ fQueuePresentKHR(fPresentQueue, &presentInfo);
+ }
+
++SK_API sk_sp<VulkanWindowContext::Shared> VulkanWindowContext::fGlobalShared;
++
+ } //namespace sk_app
+diff --git a/tools/sk_app/VulkanWindowContext.h b/tools/sk_app/VulkanWindowContext.h
+index 2db9e79ae6..7950dc159b 100644
+--- a/tools/sk_app/VulkanWindowContext.h
++++ b/tools/sk_app/VulkanWindowContext.h
+@@ -1,4 +1,3 @@
+-
+ /*
+ * Copyright 2016 Google Inc.
+ *
+@@ -23,14 +22,30 @@ class GrRenderTarget;
+
+ namespace sk_app {
+
+-class VulkanWindowContext : public WindowContext {
++class SK_API VulkanWindowContext : public WindowContext {
++ struct Shared;
+ public:
+ ~VulkanWindowContext() override;
+
++ class SharedGrContext {
++ public:
++ SharedGrContext() {}
++ GrContext* getGrContext() { return shared ? shared->fContext.get() : nullptr; }
++ ~SharedGrContext() { shared.reset(); checkDestroyShared(); }
++ bool operator!() const { return !shared; }
++ void reset() { shared.reset(); }
++ private:
++ friend class VulkanWindowContext;
++ SharedGrContext(sk_sp<Shared>& sh ) : shared( sh ) {}
++ sk_sp<Shared> shared;
++ };
++
++ static SharedGrContext getSharedGrContext() { return SharedGrContext( fGlobalShared ); }
++
+ sk_sp<SkSurface> getBackbufferSurface() override;
+ void swapBuffers() override;
+
+- bool isValid() override { return fDevice != VK_NULL_HANDLE; }
++ bool isValid() override { return fShared->fDevice != VK_NULL_HANDLE; }
+
+ void resize(int w, int h) override {
+ this->createSwapchain(w, h, fDisplayParams);
+@@ -53,6 +68,7 @@ public:
+ private:
+ void initializeContext();
+ void destroyContext();
++ static void checkDestroyShared();
+
+ struct BackbufferInfo {
+ uint32_t fImageIndex; // image this is associated with
+@@ -64,11 +80,6 @@ private:
+ void createBuffers(VkFormat format, SkColorType colorType);
+ void destroyBuffers();
+
+- VkInstance fInstance = VK_NULL_HANDLE;
+- VkPhysicalDevice fPhysicalDevice = VK_NULL_HANDLE;
+- VkDevice fDevice = VK_NULL_HANDLE;
+- VkDebugReportCallbackEXT fDebugCallback = VK_NULL_HANDLE;
+-
+ // Create functions
+ CreateVkSurfaceFn fCreateVkSurfaceFn;
+ CanPresentFn fCanPresentFn;
+@@ -90,20 +101,41 @@ private:
+ PFN_vkAcquireNextImageKHR fAcquireNextImageKHR = nullptr;
+ PFN_vkQueuePresentKHR fQueuePresentKHR = nullptr;
+
+- PFN_vkDestroyInstance fDestroyInstance = nullptr;
+ PFN_vkDeviceWaitIdle fDeviceWaitIdle = nullptr;
+- PFN_vkDestroyDebugReportCallbackEXT fDestroyDebugReportCallbackEXT = nullptr;
+ PFN_vkQueueWaitIdle fQueueWaitIdle = nullptr;
+- PFN_vkDestroyDevice fDestroyDevice = nullptr;
+ PFN_vkGetDeviceQueue fGetDeviceQueue = nullptr;
+
++ // We need to use just one GrContext, so share all the relevant data.
++ struct Shared : public SkRefCnt
++ {
++ PFN_vkDestroyInstance fDestroyInstance = nullptr;
++ PFN_vkDestroyDevice fDestroyDevice = nullptr;
++ PFN_vkDestroyDebugReportCallbackEXT fDestroyDebugReportCallbackEXT = nullptr;
++
++ VkInstance fInstance = VK_NULL_HANDLE;
++ VkPhysicalDevice fPhysicalDevice = VK_NULL_HANDLE;
++ VkDevice fDevice = VK_NULL_HANDLE;
++ VkDebugReportCallbackEXT fDebugCallback = VK_NULL_HANDLE;
++
+ sk_sp<const GrVkInterface> fInterface;
+
+- VkSurfaceKHR fSurface;
+- VkSwapchainKHR fSwapchain;
++ // Original code had this as a function-local variable, but that seems wrong.
++ // It should exist as long as the context exists.
++ VkPhysicalDeviceFeatures2 features;
++
+ uint32_t fGraphicsQueueIndex;
+ VkQueue fGraphicsQueue;
+ uint32_t fPresentQueueIndex;
++
++ sk_sp<GrContext> fContext;
++ };
++
++ sk_sp<Shared> fShared;
++
++ static sk_sp<Shared> fGlobalShared;
++
++ VkSurfaceKHR fSurface;
++ VkSwapchainKHR fSwapchain;
+ VkQueue fPresentQueue;
+
+ uint32_t fImageCount;
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 0bb9f8f64198..c33c4e90db43 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -579,8 +579,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/skia/SkiaHelper \
$(if $(filter SKIA,$(BUILD_TYPE)), \
vcl/skia/salbmp \
- vcl/skia/gdiimpl \
- vcl/skia/vulkan) \
+ vcl/skia/gdiimpl) \
))
# runtime dependency
diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx
index 04f96cb7bd11..195b5d877eed 100644
--- a/vcl/inc/skia/gdiimpl.hxx
+++ b/vcl/inc/skia/gdiimpl.hxx
@@ -26,6 +26,7 @@
#include <salgeom.hxx>
#include <SkSurface.h>
+#include <tools/sk_app/VulkanWindowContext.h>
class SkiaFlushIdle;
@@ -210,6 +211,7 @@ protected:
void destroySurface();
// Reimplemented for X11.
virtual bool avoidRecreateByResize() const { return false; }
+ void createOffscreenSurface();
void privateDrawAlphaRect(long nX, long nY, long nWidth, long nHeight, double nTransparency,
bool blockAA = false);
@@ -265,6 +267,8 @@ protected:
// The Skia surface that is target of all the rendering.
sk_sp<SkSurface> mSurface;
bool mIsGPU; // whether the surface is GPU-backed
+ // Keep reference to shared GrContext.
+ sk_app::VulkanWindowContext::SharedGrContext mOffscreenGrContext;
vcl::Region mClipRegion;
Color mLineColor;
Color mFillColor;
diff --git a/vcl/inc/skia/vulkan.hxx b/vcl/inc/skia/vulkan.hxx
deleted file mode 100644
index 6c8e3c7bfa44..000000000000
--- a/vcl/inc/skia/vulkan.hxx
+++ /dev/null
@@ -1,29 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-#ifndef INCLUDED_VCL_INC_SKIA_VULKAN_HXX
-#define INCLUDED_VCL_INC_SKIA_VULKAN_HXX
-
-#include <GrContext.h>
-
-#include <vcl/dllapi.h>
-
-// Create and handle GrContext for Vulkan drawing to offscreen surfaces.
-// Skia already provides WindowContext class that does this for surfaces
-// used for drawing to windows, but it does not seem to provide a simple
-// way to get GrContext without a window.
-class VCL_PLUGIN_PUBLIC SkiaVulkanGrContext
-{
-public:
- static GrContext* getGrContext();
-};
-
-#endif // INCLUDED_VCL_INC_SKIA_VULKAN_HXX
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/skia/README b/vcl/skia/README
index 793c16e8dd39..f1248d90c3ea 100644
--- a/vcl/skia/README
+++ b/vcl/skia/README
@@ -17,3 +17,19 @@ Skia supports several methods to draw:
- Vulkan - Vulkan-based GPU drawing, this is the default
There are more (OpenGL, Metal on Mac, etc.), but (as of now) they are not supported by VCL.
+
+GrContext sharing:
+==================
+
+We use Skia's sk_app::WindowContext class for creating surfaces for windows, that class
+takes care of the internals. But of offscreen drawing, we need an instance of class
+GrContext. There is sk_app::WindowContext::getGrContext(), but each instance creates
+its own GrContext, and apparently it does not work to mix them. Which means that
+for offscreen drawing we would need to know which window (and only that window)
+the contents will be eventually painted to, which is not possible (it may not even
+be known at the time).
+
+To solve this problem we patch sk_app::WindowContext to create just one GrContext object
+and share it between instances. Additionally, using sk_app::WindowContext::SharedGrContext
+it is possible to share it also for offscreen drawing, including keeping proper reference
+count.
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index 776e44216c45..ac47d254cc03 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -23,12 +23,14 @@
#include <skia/salbmp.hxx>
#include <vcl/idle.hxx>
#include <vcl/svapp.hxx>
+#include <vcl/lazydelete.hxx>
#include <SkCanvas.h>
#include <SkPath.h>
#include <SkRegion.h>
#include <SkDashPathEffect.h>
#include <GrBackendSurface.h>
+#include <GrContextFactory.h>
#include <basegfx/polygon/b2dpolygontools.hxx>
@@ -190,7 +192,11 @@ SkiaSalGraphicsImpl::SkiaSalGraphicsImpl(SalGraphics& rParent, SalGeometryProvid
{
}
-SkiaSalGraphicsImpl::~SkiaSalGraphicsImpl() {}
+SkiaSalGraphicsImpl::~SkiaSalGraphicsImpl()
+{
+ assert(!mSurface);
+ assert(!mOffscreenGrContext);
+}
void SkiaSalGraphicsImpl::Init() {}
@@ -208,8 +214,7 @@ void SkiaSalGraphicsImpl::recreateSurface()
void SkiaSalGraphicsImpl::createSurface()
{
- // Create surface for offscreen graphics. Subclasses will create GPU-backed
- // surfaces as appropriate.
+ // Create raster surface. Subclasses will create GPU-backed surfaces as appropriate.
mSurface = SkSurface::MakeRasterN32Premul(GetWidth(), GetHeight());
mIsGPU = false;
#ifdef DBG_UTIL
@@ -217,6 +222,53 @@ void SkiaSalGraphicsImpl::createSurface()
#endif
}
+void SkiaSalGraphicsImpl::createOffscreenSurface()
+{
+ assert(isOffscreen());
+ destroySurface();
+ switch (renderMethodToUse())
+ {
+ case RenderVulkan:
+ {
+ mOffscreenGrContext = sk_app::VulkanWindowContext::getSharedGrContext();
+ GrContext* grContext = mOffscreenGrContext.getGrContext();
+ // We may not get a GrContext if called before any onscreen window is created,
+ // but that happens very early, so this should be rare and insignificant.
+ // Unittests are an exception, they usually do not create any windows,
+ // so in that case do create GrContext that has no window associated.
+ if (!grContext)
+ {
+ static bool isUnitTest = (getenv("LO_TESTNAME") != nullptr);
+ if (isUnitTest)
+ {
+ static vcl::DeleteOnDeinit<sk_gpu_test::GrContextFactory> factory(
+ new sk_gpu_test::GrContextFactory);
+ // The factory owns the context.
+ grContext
+ = factory.get()->get(sk_gpu_test::GrContextFactory::kVulkan_ContextType);
+ }
+ }
+ if (grContext)
+ {
+ mSurface = SkSurface::MakeRenderTarget(
+ grContext, SkBudgeted::kNo,
+ SkImageInfo::MakeN32Premul(GetWidth(), GetHeight()));
+ mIsGPU = true;
+ assert(mSurface.get());
+#ifdef DBG_UTIL
+ prefillSurface();
+#endif
+ return;
+ }
+ SAL_WARN("vcl.skia", "cannot create Vulkan GPU offscreen surface");
+ break;
+ }
+ default:
+ break;
+ }
+ return SkiaSalGraphicsImpl::createSurface(); // create a raster one
+}
+
void SkiaSalGraphicsImpl::destroySurface()
{
if (mSurface)
@@ -237,6 +289,7 @@ void SkiaSalGraphicsImpl::destroySurface()
mSurface->flush();
mSurface.reset();
mIsGPU = false;
+ mOffscreenGrContext.reset();
}
void SkiaSalGraphicsImpl::DeInit() { destroySurface(); }
diff --git a/vcl/skia/vulkan.cxx b/vcl/skia/vulkan.cxx
deleted file mode 100644
index c5c9093739fc..000000000000
--- a/vcl/skia/vulkan.cxx
+++ /dev/null
@@ -1,39 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Some of this code is based on Skia source code, covered by the following
- * license notice (see readlicense_oo for the full license):
- *
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- */
-
-#include <skia/vulkan.hxx>
-
-#include <GrContextFactory.h>
-
-#include <vcl/lazydelete.hxx>
-
-static GrContext* createGrContext()
-{
- static vcl::DeleteOnDeinit<sk_gpu_test::GrContextFactory> factory(
- new sk_gpu_test::GrContextFactory);
- // The factory owns the context.
- return factory.get()->get(sk_gpu_test::GrContextFactory::kVulkan_ContextType);
-}
-
-GrContext* SkiaVulkanGrContext::getGrContext()
-{
- static GrContext* context = createGrContext();
- return context;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx
index e9db555c25c0..8f30c3486dac 100644
--- a/vcl/skia/win/gdiimpl.cxx
+++ b/vcl/skia/win/gdiimpl.cxx
@@ -12,7 +12,6 @@
#include <tools/sk_app/win/WindowContextFactory_win.h>
#include <tools/sk_app/WindowContext.h>
#include <win/saldata.hxx>
-#include <skia/vulkan.hxx>
#include <SkColorFilter.h>
#include <SkPixelRef.h>
@@ -45,26 +44,9 @@ void WinSkiaSalGraphicsImpl::Init()
void WinSkiaSalGraphicsImpl::createSurface()
{
- destroySurface();
if (isOffscreen())
- {
- switch (renderMethodToUse())
- {
- case RenderVulkan:
- mSurface = SkSurface::MakeRenderTarget(
- SkiaVulkanGrContext::getGrContext(), SkBudgeted::kNo,
- SkImageInfo::MakeN32Premul(GetWidth(), GetHeight()));
- mIsGPU = true;
- assert(mSurface.get());
-#ifdef DBG_UTIL
- prefillSurface();
-#endif
- return;
- default:
- break;
- }
- return SkiaSalGraphicsImpl::createSurface();
- }
+ return createOffscreenSurface();
+ destroySurface();
// When created, Init() gets called with size (0,0), which is invalid size
// for Skia. Creating the actual surface is delayed, so the size should be always
// valid here, but better check.
diff --git a/vcl/skia/x11/gdiimpl.cxx b/vcl/skia/x11/gdiimpl.cxx
index e349074e70e1..ef381c5e56d3 100644
--- a/vcl/skia/x11/gdiimpl.cxx
+++ b/vcl/skia/x11/gdiimpl.cxx
@@ -21,8 +21,6 @@
#include <tools/sk_app/unix/WindowContextFactory_unix.h>
#include <tools/sk_app/WindowContext.h>
-#include <skia/vulkan.hxx>
-
X11SkiaSalGraphicsImpl::X11SkiaSalGraphicsImpl(X11SalGraphics& rParent)
: SkiaSalGraphicsImpl(rParent, rParent.GetGeometryProvider())
, mX11Parent(rParent)
@@ -40,29 +38,12 @@ void X11SkiaSalGraphicsImpl::Init()
void X11SkiaSalGraphicsImpl::createSurface()
{
- destroySurface();
if (isOffscreen())
- {
- switch (renderMethodToUse())
- {
- case RenderVulkan:
- mSurface = SkSurface::MakeRenderTarget(
- SkiaVulkanGrContext::getGrContext(), SkBudgeted::kNo,
- SkImageInfo::MakeN32Premul(GetWidth(), GetHeight()));
- mIsGPU = true;
- assert(mSurface.get());
-#ifdef DBG_UTIL
- prefillSurface();
-#endif
- return;
- default:
- break;
- }
- return SkiaSalGraphicsImpl::createSurface();
- }
+ return createOffscreenSurface();
+ destroySurface();
sk_app::DisplayParams displayParams;
- // TODO The Skia Xlib code actually requires the non-native color type to work properly.
// Use a macro to hide an unreachable code warning.
+ // TODO The Skia Xlib code actually requires the non-native color type to work properly.
#define GET_FORMAT \
kN32_SkColorType == kBGRA_8888_SkColorType ? kRGBA_8888_SkColorType : kBGRA_8888_SkColorType
displayParams.fColorType = GET_FORMAT;
@@ -73,6 +54,13 @@ void X11SkiaSalGraphicsImpl::createSurface()
assert(winInfo.fDisplay && winInfo.fWindow != None);
winInfo.fFBConfig = nullptr; // not used
winInfo.fVisualInfo = const_cast<SalVisual*>(&mX11Parent.GetVisual());
+#ifdef DBG_UTIL
+ // Our patched Skia has VulkanWindowContext that shares GrContext, which requires
+ // that the X11 visual is always the same. Ensure it is so.
+ static VisualID checkVisualID = -1U;
+ assert(checkVisualID == -1U || winInfo.fVisualInfo->visualid == checkVisualID);
+ checkVisualID = winInfo.fVisualInfo->visualid;
+#endif
winInfo.fWidth = GetWidth();
winInfo.fHeight = GetHeight();
switch (renderMethodToUse())
commit 36dfe2344dfda38fbff00af48c4c9c2c82805fdc
Author: Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Tue Nov 12 15:50:00 2019 +0100
Commit: Luboš Luňák <l.lunak at collabora.com>
CommitDate: Tue Nov 12 17:29:43 2019 +0100
clean up properly in VCL backend tests
VclPtr is a smart pointer, but it does not clean up automatically,
ScopedVclPtr does.
Change-Id: If792111cdd489b1743a1bcf060b56c52a4aa79d5
diff --git a/vcl/inc/test/outputdevice.hxx b/vcl/inc/test/outputdevice.hxx
index 520436f66fea..f2f4784d086c 100644
--- a/vcl/inc/test/outputdevice.hxx
+++ b/vcl/inc/test/outputdevice.hxx
@@ -34,7 +34,7 @@ class VCL_DLLPUBLIC OutputDeviceTestCommon
{
protected:
- VclPtr<VirtualDevice> mpVirtualDevice;
+ ScopedVclPtr<VirtualDevice> mpVirtualDevice;
tools::Rectangle maVDRectangle;
static const Color constBackgroundColor;
commit 626095635545812eea3a10b3febca42ec91d4dcf
Author: Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Tue Nov 12 10:57:30 2019 +0100
Commit: Luboš Luňák <l.lunak at collabora.com>
CommitDate: Tue Nov 12 17:29:34 2019 +0100
avoid repeated SkSurface recreating because of X11 being asynchronous
Sometimes VCL and X11 (and thus Skia) will have a different idea
about what the size of a window is. Check for the mismatch and avoid
recreating if it wouldn't do anything.
Change-Id: Icf3ebba9589cc6f12612e5f280840346cb0edaeb
diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx
index 8225e76d27ff..04f96cb7bd11 100644
--- a/vcl/inc/skia/gdiimpl.hxx
+++ b/vcl/inc/skia/gdiimpl.hxx
@@ -208,6 +208,8 @@ protected:
void checkSurface();
void recreateSurface();
void destroySurface();
+ // Reimplemented for X11.
+ virtual bool avoidRecreateByResize() const { return false; }
void privateDrawAlphaRect(long nX, long nY, long nWidth, long nHeight, double nTransparency,
bool blockAA = false);
diff --git a/vcl/inc/skia/x11/gdiimpl.hxx b/vcl/inc/skia/x11/gdiimpl.hxx
index 1c40aa6b2c28..1dc5064e6667 100644
--- a/vcl/inc/skia/x11/gdiimpl.hxx
+++ b/vcl/inc/skia/x11/gdiimpl.hxx
@@ -37,6 +37,7 @@ public:
protected:
virtual void createSurface() override;
virtual void performFlush() override;
+ virtual bool avoidRecreateByResize() const override;
private:
std::unique_ptr<sk_app::WindowContext> mWindowContext;
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index 6215317b18ee..776e44216c45 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -267,11 +267,14 @@ void SkiaSalGraphicsImpl::checkSurface()
}
else if (GetWidth() != mSurface->width() || GetHeight() != mSurface->height())
{
- Size oldSize(mSurface->width(), mSurface->height());
- recreateSurface();
- SAL_INFO("vcl.skia", "recreate(" << this << "): old " << oldSize << " new "
- << Size(mSurface->width(), mSurface->height())
- << " requested " << Size(GetWidth(), GetHeight()));
+ if (!avoidRecreateByResize())
+ {
+ Size oldSize(mSurface->width(), mSurface->height());
+ recreateSurface();
+ SAL_INFO("vcl.skia", "recreate(" << this << "): old " << oldSize << " new "
+ << Size(mSurface->width(), mSurface->height())
+ << " requested " << Size(GetWidth(), GetHeight()));
+ }
}
}
diff --git a/vcl/skia/x11/gdiimpl.cxx b/vcl/skia/x11/gdiimpl.cxx
index 72fc311f7aaa..e349074e70e1 100644
--- a/vcl/skia/x11/gdiimpl.cxx
+++ b/vcl/skia/x11/gdiimpl.cxx
@@ -73,10 +73,6 @@ void X11SkiaSalGraphicsImpl::createSurface()
assert(winInfo.fDisplay && winInfo.fWindow != None);
winInfo.fFBConfig = nullptr; // not used
winInfo.fVisualInfo = const_cast<SalVisual*>(&mX11Parent.GetVisual());
- // TODO Vulkan does not use these dimensions, instead it uses dimensions of the actual
- // drawable, which may lead to repeated createSurface() calls from checkSurface()
- // if the window is being resized and VCL already knows the new size but Vulkan doesn't.
- // Avoid this somehow.
winInfo.fWidth = GetWidth();
winInfo.fHeight = GetHeight();
switch (renderMethodToUse())
@@ -100,6 +96,24 @@ void X11SkiaSalGraphicsImpl::createSurface()
#endif
}
+bool X11SkiaSalGraphicsImpl::avoidRecreateByResize() const
+{
+ if (!mSurface)
+ return false;
+ // Skia's WindowContext uses actual dimensions of the X window, which due to X11 being
+ // asynchronous may be temporarily different from what VCL thinks are the dimensions.
+ // That can lead to us repeatedly calling recreateSurface() because of "incorrect"
+ // size, and we otherwise need to check for size changes, because VCL does not inform us.
+ // Avoid the problem here by checking the size of the X window and bail out if Skia
+ // would just return the same size as it is now.
+ Window r;
+ int x, y;
+ unsigned int w, h, border, depth;
+ XGetGeometry(mX11Parent.GetXDisplay(), mX11Parent.GetDrawable(), &r, &x, &y, &w, &h, &border,
+ &depth);
+ return mSurface->width() == int(w) && mSurface->height() == int(h);
+}
+
void X11SkiaSalGraphicsImpl::DeInit()
{
SkiaSalGraphicsImpl::DeInit();
More information about the Libreoffice-commits
mailing list