6#include "windowthumbnail.h"
8#include <KWindowSystem>
11#include <QGuiApplication>
13#include <QOpenGLContext>
14#include <QOpenGLFunctions>
15#include <QQuickWindow>
17#include <QSGImageNode>
21#include <xcb/composite.h>
24typedef void (*glXBindTexImageEXT_func)(
Display *dpy, GLXDrawable drawable,
int buffer,
const int *attrib_list);
25typedef void (*glXReleaseTexImageEXT_func)(
Display *dpy, GLXDrawable drawable,
int buffer);
29typedef EGLImageKHR (*eglCreateImageKHR_func)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer,
const EGLint *);
30typedef EGLBoolean (*eglDestroyImageKHR_func)(EGLDisplay, EGLImageKHR);
31typedef GLvoid (*glEGLImageTargetTexture2DOES_func)(GLenum, GLeglImageOES);
40class DiscardTextureProviderRunnable :
public QRunnable
43 explicit DiscardTextureProviderRunnable(WindowTextureProvider *provider)
44 : m_provider(provider)
54 WindowTextureProvider *m_provider;
60class DiscardGlxPixmapRunnable :
public QRunnable
63 DiscardGlxPixmapRunnable(uint, QFunctionPointer, xcb_pixmap_t);
68 QFunctionPointer m_releaseTexImage;
69 xcb_pixmap_t m_glxPixmap;
72DiscardGlxPixmapRunnable::DiscardGlxPixmapRunnable(uint texture, QFunctionPointer deleteFunction, xcb_pixmap_t pixmap)
75 , m_releaseTexImage(deleteFunction)
80void DiscardGlxPixmapRunnable::run()
82 if (m_glxPixmap != XCB_PIXMAP_NONE) {
84 ((glXReleaseTexImageEXT_func)(m_releaseTexImage))(d, m_glxPixmap, GLX_FRONT_LEFT_EXT);
85 glXDestroyPixmap(d, m_glxPixmap);
86 glDeleteTextures(1, &m_texture);
92class DiscardEglPixmapRunnable :
public QRunnable
95 DiscardEglPixmapRunnable(uint, QFunctionPointer, EGLImageKHR);
100 QFunctionPointer m_eglDestroyImageKHR;
104DiscardEglPixmapRunnable::DiscardEglPixmapRunnable(uint texture, QFunctionPointer deleteFunction, EGLImageKHR image)
107 , m_eglDestroyImageKHR(deleteFunction)
112void DiscardEglPixmapRunnable::run()
114 if (m_image != EGL_NO_IMAGE_KHR) {
115 ((eglDestroyImageKHR_func)(m_eglDestroyImageKHR))(eglGetCurrentDisplay(), m_image);
116 glDeleteTextures(1, &m_texture);
122QSGTexture *WindowTextureProvider::texture()
const
124 return m_texture.get();
127void WindowTextureProvider::setTexture(
QSGTexture *texture)
129 m_texture.reset(texture);
130 Q_EMIT textureChanged();
133#if HAVE_XCB_COMPOSITE
134std::optional<bool> WindowThumbnail::s_hasPixmapExtension = std::nullopt;
137WindowThumbnail::WindowThumbnail(
QQuickItem *parent)
141 setFlag(ItemHasContents);
146 gui->installNativeEventFilter(
this);
147#if HAVE_XCB_COMPOSITE
149 xcb_prefetch_extension_data(c, &xcb_composite_id);
150 const auto *compositeReply = xcb_get_extension_data(c, &xcb_composite_id);
151 m_composite = (compositeReply && compositeReply->present);
153 xcb_prefetch_extension_data(c, &xcb_damage_id);
154 const auto *reply = xcb_get_extension_data(c, &xcb_damage_id);
155 m_damageEventBase = reply->first_event;
156 if (reply->present) {
157 xcb_damage_query_version_unchecked(c, XCB_DAMAGE_MAJOR_VERSION, XCB_DAMAGE_MINOR_VERSION);
164WindowThumbnail::~WindowThumbnail()
172void WindowThumbnail::itemChange(ItemChange change,
const ItemChangeData &data)
175 case ItemSceneChange:
179 m_scene = data.window;
184 if (startRedirecting()) {
190 case ItemEnabledHasChanged:
192 case ItemVisibleHasChanged:
193 if (data.boolValue) {
194 if (startRedirecting()) {
210void WindowThumbnail::releaseResources()
213 if (m_textureProvider) {
215 m_textureProvider =
nullptr;
218#if HAVE_XCB_COMPOSITE
220#if HAVE_GLX && HAVE_EGL
222 Q_ASSERT(m_glxPixmap == XCB_PIXMAP_NONE || m_image == EGL_NO_IMAGE_KHR);
229 if (m_glxPixmap != XCB_PIXMAP_NONE) {
230 window()->scheduleRenderJob(
new DiscardGlxPixmapRunnable(m_texture, m_releaseTexImage, m_glxPixmap), m_renderStage);
232 m_glxPixmap = XCB_PIXMAP_NONE;
237 if (m_image != EGL_NO_IMAGE_KHR) {
238 window()->scheduleRenderJob(
new DiscardEglPixmapRunnable(m_texture, m_eglDestroyImageKHR, m_image), m_renderStage);
239 m_image = EGL_NO_IMAGE_KHR;
249void WindowThumbnail::invalidateSceneGraph()
251 delete m_textureProvider;
252 m_textureProvider =
nullptr;
254 if (m_glxPixmap != XCB_PIXMAP_NONE) {
257 auto runnable =
new DiscardGlxPixmapRunnable(m_texture, m_releaseTexImage, m_glxPixmap);
259 m_glxPixmap = XCB_PIXMAP_NONE;
264 if (m_image != EGL_NO_IMAGE_KHR) {
265 auto runnable =
new DiscardEglPixmapRunnable(m_texture, m_eglDestroyImageKHR, m_image);
267 m_image = EGL_NO_IMAGE_KHR;
273uint32_t WindowThumbnail::winId()
const
278void WindowThumbnail::setWinId(uint32_t winId)
280 if (m_winId == winId) {
294 if (isEnabled() && isVisible()) {
298 Q_EMIT winIdChanged();
301void WindowThumbnail::resetWinId()
306qreal WindowThumbnail::paintedWidth()
const
308 return m_paintedSize.width();
311qreal WindowThumbnail::paintedHeight()
const
313 return m_paintedSize.height();
316bool WindowThumbnail::thumbnailAvailable()
const
318 return m_thumbnailAvailable;
321QSGNode *WindowThumbnail::updatePaintNode(
QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData)
323 Q_UNUSED(updatePaintNodeData)
325 if (!m_textureProvider) {
326 m_textureProvider =
new WindowTextureProvider();
329 if (!m_xcb || m_winId == 0 || (
window() &&
window()->winId() == m_winId)) {
330 iconToTexture(m_textureProvider);
332 windowToTexture(m_textureProvider);
337 node =
window()->createImageNode();
338 qsgnode_set_description(node, QStringLiteral(
"windowthumbnail"));
342 node->
setTexture(m_textureProvider->texture());
344 if (size != m_paintedSize) {
345 m_paintedSize = size;
346 Q_EMIT paintedSizeChanged();
348 const qreal x = boundingRect().x() + (boundingRect().width() - size.width()) / 2;
349 const qreal y = boundingRect().y() + (boundingRect().height() - size.height()) / 2;
354bool WindowThumbnail::nativeEventFilter(
const QByteArray &eventType,
void *message, qintptr *result)
357 if (!m_xcb || !m_composite || eventType != QByteArrayLiteral(
"xcb_generic_event_t")) {
361#if HAVE_XCB_COMPOSITE
362 xcb_generic_event_t *
event =
static_cast<xcb_generic_event_t *
>(message);
363 const uint8_t responseType =
event->response_type & ~0x80;
364 if (responseType == m_damageEventBase + XCB_DAMAGE_NOTIFY) {
365 if (
reinterpret_cast<xcb_damage_notify_event_t *
>(event)->drawable == m_winId) {
369 }
else if (responseType == XCB_CONFIGURE_NOTIFY) {
370 if (
reinterpret_cast<xcb_configure_notify_event_t *
>(event)->window == m_winId) {
374 m_pixmap = XCB_PIXMAP_NONE;
379 }
else if (responseType == XCB_MAP_NOTIFY) {
380 if (
reinterpret_cast<xcb_map_notify_event_t *
>(event)->window == m_winId) {
393void WindowThumbnail::iconToTexture(WindowTextureProvider *textureProvider)
397 icon = KX11Extras::self()->icon(m_winId, boundingRect().width(), boundingRect().height());
406#if HAVE_XCB_COMPOSITE
408bool WindowThumbnail::windowToTextureGLX(WindowTextureProvider *textureProvider)
412 if (!m_openGLFunctionsResolved) {
413 resolveGLXFunctions();
415 if (!m_bindTexImage || !m_releaseTexImage) {
418 if (m_glxPixmap == XCB_PIXMAP_NONE) {
420 auto attrCookie = xcb_get_window_attributes_unchecked(c, m_winId);
421 auto geometryCookie = xcb_get_geometry_unchecked(c, m_pixmap);
433 m_depth =
geo->depth;
434 m_visualid = attr->visual;
436 if (!loadGLXTexture()) {
440 textureProvider->setTexture(
443 openglContext->functions()->glBindTexture(GL_TEXTURE_2D, m_texture);
452bool WindowThumbnail::xcbWindowToTextureEGL(WindowTextureProvider *textureProvider)
454 EGLContext context = eglGetCurrentContext();
456 if (context != EGL_NO_CONTEXT) {
457 if (!m_eglFunctionsResolved) {
458 resolveEGLFunctions();
460 if (
QByteArrayView((
char *)glGetString(GL_RENDERER)).contains(
"llvmpipe")) {
463 if (!m_eglCreateImageKHR || !m_eglDestroyImageKHR || !m_glEGLImageTargetTexture2DOES) {
466 if (m_image == EGL_NO_IMAGE_KHR) {
468 auto geometryCookie = xcb_get_geometry_unchecked(c, m_pixmap);
470 const EGLint attribs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
471 m_image = ((eglCreateImageKHR_func)(m_eglCreateImageKHR))(eglGetCurrentDisplay(),
473 EGL_NATIVE_PIXMAP_KHR,
474 (EGLClientBuffer)(uintptr_t)m_pixmap,
477 if (m_image == EGL_NO_IMAGE_KHR) {
478 qDebug() <<
"failed to create egl image";
482 glGenTextures(1, &m_texture);
499void WindowThumbnail::resolveEGLFunctions()
501 EGLDisplay display = eglGetCurrentDisplay();
502 if (display == EGL_NO_DISPLAY) {
506 if (!s_hasPixmapExtension.has_value()) {
507#if defined(__clang__) && __clang_major__ < 16
508 QByteArray queryResult(eglQueryString(display, EGL_EXTENSIONS));
509 auto extensions = queryResult.split(
' ');
511 QByteArrayView queryResult(eglQueryString(display, EGL_EXTENSIONS));
512 auto extensions = queryResult | std::views::split(
' ');
514 auto filter = [](
const auto ext) {
516 || std::ranges::equal(ext,
QByteArrayView(
"EGL_KHR_image_pixmap"));
518 s_hasPixmapExtension = std::ranges::any_of(extensions, filter);
521 if (s_hasPixmapExtension.value()) {
522 qDebug() <<
"Have EGL texture from pixmap";
523 m_eglCreateImageKHR = context->getProcAddress(QByteArrayLiteral(
"eglCreateImageKHR"));
524 m_eglDestroyImageKHR = context->getProcAddress(QByteArrayLiteral(
"eglDestroyImageKHR"));
525 m_glEGLImageTargetTexture2DOES = context->getProcAddress(QByteArrayLiteral(
"glEGLImageTargetTexture2DOES"));
527 m_eglFunctionsResolved =
true;
530void WindowThumbnail::bindEGLTexture()
532 ((glEGLImageTargetTexture2DOES_func)(m_glEGLImageTargetTexture2DOES))(GL_TEXTURE_2D, (GLeglImageOES)m_image);
539void WindowThumbnail::windowToTexture(WindowTextureProvider *textureProvider)
541 if (!m_damaged && textureProvider->texture()) {
544#if HAVE_XCB_COMPOSITE
545 if (m_pixmap == XCB_PIXMAP_NONE) {
546 m_pixmap = pixmapForWindow();
548 if (m_pixmap == XCB_PIXMAP_NONE) {
550 iconToTexture(textureProvider);
551 setThumbnailAvailable(
false);
554 bool fallbackToIcon =
true;
556 fallbackToIcon = !windowToTextureGLX(textureProvider);
559 if (fallbackToIcon) {
561 fallbackToIcon = !xcbWindowToTextureEGL(textureProvider);
564 if (fallbackToIcon) {
566 iconToTexture(textureProvider);
568 setThumbnailAvailable(!fallbackToIcon);
570 iconToTexture(textureProvider);
574#if HAVE_XCB_COMPOSITE
575xcb_pixmap_t WindowThumbnail::pixmapForWindow()
578 return XCB_PIXMAP_NONE;
582 xcb_pixmap_t pix = xcb_generate_id(c);
583 auto cookie = xcb_composite_name_window_pixmap_checked(c, m_winId, pix);
586 return XCB_PIXMAP_NONE;
592void WindowThumbnail::resolveGLXFunctions()
596 if (!s_hasPixmapExtension.has_value()) {
597 auto filter = [](
const auto ext) {
598 return std::ranges::equal(ext,
QByteArrayView(
"GLX_EXT_texture_from_pixmap"));
600#if defined(__clang__) && __clang_major__ < 16
601 QByteArray queryResult(glXQueryExtensionsString(display, DefaultScreen(display)));
604 QByteArrayView queryResult(glXQueryExtensionsString(display, DefaultScreen(display)));
605 auto extensions = queryResult | std::views::split(
' ');
607 s_hasPixmapExtension = std::ranges::any_of(extensions, filter);
609 if (s_hasPixmapExtension.value()) {
610 m_bindTexImage = context->getProcAddress(QByteArrayLiteral(
"glXBindTexImageEXT"));
611 m_releaseTexImage = context->getProcAddress(QByteArrayLiteral(
"glXReleaseTexImageEXT"));
613 qWarning() <<
"couldn't resolve GLX_EXT_texture_from_pixmap functions";
615 m_openGLFunctionsResolved =
true;
618void WindowThumbnail::bindGLXTexture()
621 ((glXReleaseTexImageEXT_func)(m_releaseTexImage))(d, m_glxPixmap, GLX_FRONT_LEFT_EXT);
622 ((glXBindTexImageEXT_func)(m_bindTexImage))(d, m_glxPixmap, GLX_FRONT_LEFT_EXT,
nullptr);
627 GLXFBConfig fbConfig;
631struct GlxGlobalData {
637 reply = xcb_render_query_pict_formats_reply(conn, xcb_render_query_pict_formats_unchecked(conn),
nullptr);
640 for (
auto screens = xcb_render_query_pict_formats_screens_iterator(reply); screens.rem; xcb_render_pictscreen_next(&screens)) {
641 for (
auto depths = xcb_render_pictscreen_depths_iterator(screens.data); depths.rem; xcb_render_pictdepth_next(&depths)) {
642 const xcb_render_pictvisual_t *visuals = xcb_render_pictdepth_visuals(depths.data);
643 const int len = xcb_render_pictdepth_visuals_length(depths.data);
645 for (
int i = 0; i < len; i++) {
646 visualPictFormatHash.insert(visuals[i].visual, visuals[i].format);
652 const xcb_render_pictforminfo_t *formats = xcb_render_query_pict_formats_formats(reply);
653 const int len = xcb_render_query_pict_formats_formats_length(reply);
655 for (
int i = 0; i < len; i++) {
656 if (formats[i].type == XCB_RENDER_PICT_TYPE_DIRECT) {
657 formatInfoHash.insert(formats[i].
id, &formats[i].direct);
662 const xcb_setup_t *setup = xcb_get_setup(conn);
664 for (
auto screen = xcb_setup_roots_iterator(setup); screen.rem; xcb_screen_next(&screen)) {
665 for (
auto depth = xcb_screen_allowed_depths_iterator(screen.data); depth.rem; xcb_depth_next(&depth)) {
666 const int len = xcb_depth_visuals_length(depth.data);
667 const xcb_visualtype_t *visuals = xcb_depth_visuals(depth.data);
669 for (
int i = 0; i < len; i++) {
670 visualDepthHash.insert(visuals[i].visual_id, depth.data->depth);
678 qDeleteAll(visualFbConfigHash);
682 xcb_render_query_pict_formats_reply_t *reply;
689Q_GLOBAL_STATIC(GlxGlobalData, g_glxGlobalData)
691static xcb_render_pictformat_t findPictFormat(xcb_visualid_t visual)
693 GlxGlobalData *d = g_glxGlobalData;
694 return d->visualPictFormatHash.value(visual);
697static const xcb_render_directformat_t *findPictFormatInfo(xcb_render_pictformat_t format)
699 GlxGlobalData *d = g_glxGlobalData;
700 return d->formatInfoHash.value(format);
703static int visualDepth(xcb_visualid_t visual)
705 GlxGlobalData *d = g_glxGlobalData;
706 return d->visualDepthHash.value(visual);
709FbConfigInfo *getConfig(xcb_visualid_t visual)
712 const xcb_render_pictformat_t format = findPictFormat(visual);
713 const xcb_render_directformat_t *direct = findPictFormatInfo(format);
719 const int red_bits = qPopulationCount(direct->red_mask);
720 const int green_bits = qPopulationCount(direct->green_mask);
721 const int blue_bits = qPopulationCount(direct->blue_mask);
722 const int alpha_bits = qPopulationCount(direct->alpha_mask);
724 const int depth = visualDepth(visual);
726 const auto rgb_sizes = std::tie(red_bits, green_bits, blue_bits);
728 const int attribs[] = {GLX_RENDER_TYPE,
731 GLX_WINDOW_BIT | GLX_PIXMAP_BIT,
738 GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT,
741 red_bits + green_bits + blue_bits + alpha_bits,
756 if (
QByteArrayView((
char *)glGetString(GL_RENDERER)).contains(
"llvmpipe")) {
761 GLXFBConfig *configs = glXChooseFBConfig(dpy, DefaultScreen(dpy), attribs, &count);
775 for (
int i = 0; i < count; i++) {
779 glXGetFBConfigAttrib(dpy, configs[i], GLX_RED_SIZE, &red);
780 glXGetFBConfigAttrib(dpy, configs[i], GLX_GREEN_SIZE, &green);
781 glXGetFBConfigAttrib(dpy, configs[i], GLX_BLUE_SIZE, &blue);
783 if (std::tie(red, green, blue) != rgb_sizes) {
787 xcb_visualid_t visual;
788 glXGetFBConfigAttrib(dpy, configs[i], GLX_VISUAL_ID, (
int *)&visual);
790 if (visualDepth(visual) != depth) {
796 glXGetFBConfigAttrib(dpy, configs[i], GLX_BIND_TO_TEXTURE_RGBA_EXT, &bind_rgba);
797 glXGetFBConfigAttrib(dpy, configs[i], GLX_BIND_TO_TEXTURE_RGB_EXT, &bind_rgb);
799 if (!bind_rgb && !bind_rgba) {
804 glXGetFBConfigAttrib(dpy, configs[i], GLX_BIND_TO_TEXTURE_TARGETS_EXT, &texture_targets);
806 if ((texture_targets & GLX_TEXTURE_2D_BIT_EXT) == 0) {
812 glXGetFBConfigAttrib(dpy, configs[i], GLX_DEPTH_SIZE, &depth);
813 glXGetFBConfigAttrib(dpy, configs[i], GLX_STENCIL_SIZE, &stencil);
817 texture_format = bind_rgba ? GLX_TEXTURE_FORMAT_RGBA_EXT : GLX_TEXTURE_FORMAT_RGB_EXT;
819 texture_format = bind_rgb ? GLX_TEXTURE_FORMAT_RGB_EXT : GLX_TEXTURE_FORMAT_RGBA_EXT;
822 candidates.
append(FBConfig{configs[i], depth, stencil, texture_format});
827 std::stable_sort(candidates.
begin(), candidates.
end(), [](
const FBConfig &left,
const FBConfig &right) {
828 if (left.depth < right.depth) {
839 FbConfigInfo *info =
nullptr;
842 const FBConfig &candidate = candidates.
front();
844 info =
new FbConfigInfo;
845 info->fbConfig = candidate.config;
846 info->textureFormat = candidate.format;
852bool WindowThumbnail::loadGLXTexture()
854 GLXContext glxContext = glXGetCurrentContext();
859 FbConfigInfo *info =
nullptr;
861 auto &hashTable = g_glxGlobalData->visualFbConfigHash;
862 auto it = hashTable.constFind(m_visualid);
864 if (it != hashTable.constEnd()) {
867 info = getConfig(m_visualid);
868 hashTable.insert(m_visualid, info);
875 glGenTextures(1, &m_texture);
878 const int attrs[] = {
879 GLX_TEXTURE_FORMAT_EXT,
881 GLX_MIPMAP_TEXTURE_EXT,
883 GLX_TEXTURE_TARGET_EXT,
896void WindowThumbnail::resetDamaged()
899#if HAVE_XCB_COMPOSITE
900 if (m_damage == XCB_NONE) {
907void WindowThumbnail::stopRedirecting()
909 if (!m_xcb || !m_composite) {
912#if HAVE_XCB_COMPOSITE
914 if (m_pixmap != XCB_PIXMAP_NONE) {
915 xcb_free_pixmap(c, m_pixmap);
916 m_pixmap = XCB_PIXMAP_NONE;
918 if (m_winId == XCB_WINDOW_NONE) {
922 xcb_composite_unredirect_window(c, m_winId, XCB_COMPOSITE_REDIRECT_AUTOMATIC);
924 m_redirecting =
false;
925 if (m_damage == XCB_NONE) {
928 xcb_damage_destroy(c, m_damage);
933bool WindowThumbnail::startRedirecting()
935 if (!m_xcb || !m_composite || !
window() || !
window()->isVisible() ||
window()->winId() == m_winId || !isEnabled() || !isVisible()) {
938#if HAVE_XCB_COMPOSITE
939 if (m_winId == XCB_WINDOW_NONE) {
945 const auto attribsCookie = xcb_get_window_attributes_unchecked(c, m_winId);
948 xcb_composite_redirect_window(c, m_winId, XCB_COMPOSITE_REDIRECT_AUTOMATIC);
949 m_redirecting =
true;
952 m_damage = xcb_generate_id(c);
953 xcb_damage_create(c, m_damage, m_winId, XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY);
956 uint32_t events = XCB_EVENT_MASK_STRUCTURE_NOTIFY;
957 if (!attr.isNull()) {
958 events = events | attr->your_event_mask;
962 xcb_change_window_attributes(c, m_winId, XCB_CW_EVENT_MASK, &events);
971void WindowThumbnail::setThumbnailAvailable(
bool thumbnailAvailable)
973 if (m_thumbnailAvailable != thumbnailAvailable) {
974 m_thumbnailAvailable = thumbnailAvailable;
975 Q_EMIT thumbnailAvailableChanged();
979void WindowThumbnail::sceneVisibilityChanged(
bool visible)
982 if (startRedirecting()) {
991bool WindowThumbnail::isTextureProvider()
const
1005 if (!m_textureProvider) {
1006 m_textureProvider =
new WindowTextureProvider();
1009 return m_textureProvider;
1014#include "moc_windowthumbnail.cpp"
static bool isPlatformX11()
void update(Part *part, const QByteArray &data, qint64 dataSize)
GeoCoordinates geo(const QVariant &location)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
Namespace for everything in libplasma.
QCoreApplication * instance()
void removeNativeEventFilter(QAbstractNativeEventFilter *filterObject)
QPixmap pixmap(QWindow *window, const QSize &size, Mode mode, State state) const const
QIcon fromTheme(const QString &name)
void append(QList< T > &&value)
bool isEmpty() const const
QSGTexture * fromNative(GLuint textureId, QQuickWindow *window, const QSize &size, QQuickWindow::CreateTextureOptions options)
int * connection() const const
int * display() const const
QOpenGLFunctions * functions() const const
QNativeInterface * nativeInterface() const const
void glBindTexture(GLenum target, GLuint texture)
QImage toImage() const const
virtual bool isTextureProvider() const const
virtual void itemChange(ItemChange change, const ItemChangeData &value)
virtual QSGTextureProvider * textureProvider() const const
virtual void setFiltering(QSGTexture::Filtering filtering)=0
virtual void setRect(const QRectF &rect)=0
virtual void setTexture(QSGTexture *texture)=0
virtual QSGTexture * texture() const const=0
virtual QSize textureSize() const const=0
QSize scaled(const QSize &s, Qt::AspectRatioMode mode) const const
void setHeight(int height)
QTextStream & left(QTextStream &stream)
QTextStream & right(QTextStream &stream)
QFuture< void > filter(QThreadPool *pool, Sequence &sequence, KeepFunctor &&filterFunction)
QFuture< T > run(Function function,...)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void visibleChanged(bool arg)