summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/.prev_configure.cmake1225
-rw-r--r--src/gui/CMakeLists.txt11
-rw-r--r--src/gui/accessible/qaccessible.cpp39
-rw-r--r--src/gui/accessible/qaccessible.h27
-rw-r--r--src/gui/configure.cmake10
-rw-r--r--src/gui/configure.json1841
-rw-r--r--src/gui/doc/snippets/code/src_gui_vulkan_qvulkaninstance.cpp6
-rw-r--r--src/gui/doc/snippets/code/src_gui_vulkan_qvulkanwindow.cpp2
-rw-r--r--src/gui/image/qbitmap.cpp4
-rw-r--r--src/gui/image/qicon.cpp2
-rw-r--r--src/gui/image/qimage.cpp337
-rw-r--r--src/gui/image/qimage.h23
-rw-r--r--src/gui/image/qimage_conversions.cpp394
-rw-r--r--src/gui/image/qimage_p.h51
-rw-r--r--src/gui/image/qpnghandler.cpp4
-rw-r--r--src/gui/itemmodels/qfilesystemmodel.cpp7
-rw-r--r--src/gui/kernel/qaction.cpp19
-rw-r--r--src/gui/kernel/qcursor.cpp4
-rw-r--r--src/gui/kernel/qevent.cpp10
-rw-r--r--src/gui/kernel/qeventpoint.cpp8
-rw-r--r--src/gui/kernel/qguiapplication.cpp25
-rw-r--r--src/gui/kernel/qguiapplication_p.h3
-rw-r--r--src/gui/kernel/qkeymapper.cpp4
-rw-r--r--src/gui/kernel/qoffscreensurface.cpp4
-rw-r--r--src/gui/kernel/qopenglcontext.cpp7
-rw-r--r--src/gui/kernel/qpalette.cpp5
-rw-r--r--src/gui/kernel/qplatformscreen_p.h17
-rw-r--r--src/gui/kernel/qplatformwindow_p.h6
-rw-r--r--src/gui/kernel/qscreen.cpp25
-rw-r--r--src/gui/kernel/qscreen.h3
-rw-r--r--src/gui/kernel/qwindow.cpp26
-rw-r--r--src/gui/kernel/qwindow.h3
-rw-r--r--src/gui/math3d/qmatrix4x4.cpp8
-rw-r--r--src/gui/math3d/qquaternion.cpp6
-rw-r--r--src/gui/painting/qcolorspace.cpp11
-rw-r--r--src/gui/painting/qcolorspace_p.h1
-rw-r--r--src/gui/painting/qcolortransform.cpp445
-rw-r--r--src/gui/painting/qcolortransform.h1
-rw-r--r--src/gui/painting/qcolortransform_p.h9
-rw-r--r--src/gui/painting/qcompositionfunctions.cpp1250
-rw-r--r--src/gui/painting/qdrawhelper.cpp1421
-rw-r--r--src/gui/painting/qdrawhelper_avx2.cpp385
-rw-r--r--src/gui/painting/qdrawhelper_p.h133
-rw-r--r--src/gui/painting/qdrawhelper_sse4.cpp75
-rw-r--r--src/gui/painting/qicc.cpp2
-rw-r--r--src/gui/painting/qimagescale.cpp223
-rw-r--r--src/gui/painting/qmemrotate.cpp66
-rw-r--r--src/gui/painting/qpagesize.h2
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp18
-rw-r--r--src/gui/painting/qpaintengine_raster_p.h1
-rw-r--r--src/gui/painting/qpainter.h28
-rw-r--r--src/gui/painting/qpixellayout.cpp850
-rw-r--r--src/gui/painting/qpixellayout_p.h32
-rw-r--r--src/gui/painting/qrgbaf.h135
-rw-r--r--src/gui/painting/qrgbaf.qdoc248
-rw-r--r--src/gui/platform/unix/qtx11extras_p.h2
-rw-r--r--src/gui/platform/unix/qunixnativeinterface.cpp4
-rw-r--r--src/gui/platform/unix/qxkbcommon.cpp20
-rw-r--r--src/gui/rhi/qrhi.cpp122
-rw-r--r--src/gui/rhi/qrhi_p.h27
-rw-r--r--src/gui/rhi/qrhi_p_p.h12
-rw-r--r--src/gui/rhi/qrhid3d11.cpp207
-rw-r--r--src/gui/rhi/qrhid3d11_p_p.h13
-rw-r--r--src/gui/rhi/qrhigles2.cpp260
-rw-r--r--src/gui/rhi/qrhigles2_p_p.h23
-rw-r--r--src/gui/rhi/qrhimetal.mm91
-rw-r--r--src/gui/rhi/qrhimetal_p_p.h3
-rw-r--r--src/gui/rhi/qrhinull.cpp18
-rw-r--r--src/gui/rhi/qrhinull_p_p.h5
-rw-r--r--src/gui/rhi/qrhiprofiler.cpp7
-rw-r--r--src/gui/rhi/qrhivulkan.cpp180
-rw-r--r--src/gui/rhi/qrhivulkan_p_p.h19
-rw-r--r--src/gui/rhi/qshader.cpp7
-rw-r--r--src/gui/rhi/qshader_p.h5
-rw-r--r--src/gui/text/freetype/qfontengine_ft.cpp4
-rw-r--r--src/gui/text/qfont.cpp20
-rw-r--r--src/gui/text/qfontdatabase.cpp2
-rw-r--r--src/gui/text/qtextdocumentfragment.cpp3
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp12
-rw-r--r--src/gui/text/qtextengine.cpp13
-rw-r--r--src/gui/text/qtextformat.cpp4
-rw-r--r--src/gui/text/qtexthtmlparser.cpp94
-rw-r--r--src/gui/text/qtexthtmlparser_p.h3
-rw-r--r--src/gui/text/qtextlayout.cpp3
-rw-r--r--src/gui/text/qtextmarkdownimporter.cpp4
-rw-r--r--src/gui/text/windows/qwindowsfontenginedirectwrite.cpp3
-rw-r--r--src/gui/util/qvalidator.cpp4
-rw-r--r--src/gui/vulkan/qbasicvulkanplatforminstance.cpp1
-rw-r--r--src/gui/vulkan/qbasicvulkanplatforminstance_p.h2
-rw-r--r--src/gui/vulkan/qvulkanwindow.cpp3
90 files changed, 6854 insertions, 3848 deletions
diff --git a/src/gui/.prev_configure.cmake b/src/gui/.prev_configure.cmake
deleted file mode 100644
index 56dbde24b9..0000000000
--- a/src/gui/.prev_configure.cmake
+++ /dev/null
@@ -1,1225 +0,0 @@
-
-
-#### Inputs
-
-# input freetype
-set(INPUT_freetype "undefined" CACHE STRING "")
-set_property(CACHE INPUT_freetype PROPERTY STRINGS undefined no qt system)
-
-# input harfbuzz
-set(INPUT_harfbuzz "undefined" CACHE STRING "")
-set_property(CACHE INPUT_harfbuzz PROPERTY STRINGS undefined no qt system)
-
-# input libjpeg
-set(INPUT_libjpeg "undefined" CACHE STRING "")
-set_property(CACHE INPUT_libjpeg PROPERTY STRINGS undefined no qt system)
-
-# input libmd4c
-set(INPUT_libmd4c "undefined" CACHE STRING "")
-set_property(CACHE INPUT_libmd4c PROPERTY STRINGS undefined no qt system)
-
-# input libpng
-set(INPUT_libpng "undefined" CACHE STRING "")
-set_property(CACHE INPUT_libpng PROPERTY STRINGS undefined no qt system)
-
-
-
-#### Libraries
-
-qt_find_package(ATSPI2 PROVIDED_TARGETS PkgConfig::ATSPI2 MODULE_NAME gui QMAKE_LIB atspi)
-qt_find_package(DirectFB PROVIDED_TARGETS PkgConfig::DirectFB MODULE_NAME gui QMAKE_LIB directfb)
-qt_find_package(Libdrm PROVIDED_TARGETS Libdrm::Libdrm MODULE_NAME gui QMAKE_LIB drm)
-qt_find_package(EGL PROVIDED_TARGETS EGL::EGL MODULE_NAME gui QMAKE_LIB egl)
-qt_find_package(WrapSystemFreetype 2.2.0 PROVIDED_TARGETS WrapSystemFreetype::WrapSystemFreetype MODULE_NAME gui QMAKE_LIB freetype)
-set_package_properties(WrapFreetype PROPERTIES TYPE REQUIRED)
-if(QT_FEATURE_system_zlib)
- qt_add_qmake_lib_dependency(freetype zlib)
-endif()
-qt_find_package(Fontconfig PROVIDED_TARGETS Fontconfig::Fontconfig MODULE_NAME gui QMAKE_LIB fontconfig)
-qt_add_qmake_lib_dependency(fontconfig freetype)
-qt_find_package(gbm PROVIDED_TARGETS gbm::gbm MODULE_NAME gui QMAKE_LIB gbm)
-qt_find_package(WrapSystemHarfbuzz 2.6.0 PROVIDED_TARGETS WrapSystemHarfbuzz::WrapSystemHarfbuzz MODULE_NAME gui QMAKE_LIB harfbuzz)
-qt_find_package(Libinput PROVIDED_TARGETS Libinput::Libinput MODULE_NAME gui QMAKE_LIB libinput)
-qt_find_package(JPEG PROVIDED_TARGETS JPEG::JPEG MODULE_NAME gui QMAKE_LIB libjpeg)
-qt_find_package(WrapSystemPNG PROVIDED_TARGETS WrapSystemPNG::WrapSystemPNG MODULE_NAME gui QMAKE_LIB libpng)
-if(QT_FEATURE_system_zlib)
- qt_add_qmake_lib_dependency(libpng zlib)
-endif()
-qt_find_package(Mtdev PROVIDED_TARGETS PkgConfig::Mtdev MODULE_NAME gui QMAKE_LIB mtdev)
-qt_find_package(WrapOpenGL PROVIDED_TARGETS WrapOpenGL::WrapOpenGL MODULE_NAME gui QMAKE_LIB opengl)
-qt_find_package(GLESv2 PROVIDED_TARGETS GLESv2::GLESv2 MODULE_NAME gui QMAKE_LIB opengl_es2)
-qt_find_package(Tslib PROVIDED_TARGETS PkgConfig::Tslib MODULE_NAME gui QMAKE_LIB tslib)
-qt_find_package(Vulkan PROVIDED_TARGETS Vulkan::Vulkan MODULE_NAME gui QMAKE_LIB vulkan)
-if((LINUX) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(Wayland PROVIDED_TARGETS Wayland::Server MODULE_NAME gui QMAKE_LIB wayland_server)
-endif()
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(X11 PROVIDED_TARGETS X11::X11 MODULE_NAME gui QMAKE_LIB xlib)
-endif()
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(X11 PROVIDED_TARGETS ${X11_SM_LIB} ${X11_ICE_LIB} MODULE_NAME gui QMAKE_LIB x11sm)
-endif()
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(XCB 1.11 PROVIDED_TARGETS XCB::XCB MODULE_NAME gui QMAKE_LIB xcb)
-endif()
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(XCB 0.3.9 COMPONENTS ICCCM PROVIDED_TARGETS XCB::ICCCM MODULE_NAME gui QMAKE_LIB xcb_icccm)
-endif()
-qt_add_qmake_lib_dependency(xcb_icccm xcb)
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(XCB 0.3.9 COMPONENTS IMAGE PROVIDED_TARGETS XCB::IMAGE MODULE_NAME gui QMAKE_LIB xcb_image)
-endif()
-qt_add_qmake_lib_dependency(xcb_image xcb_shm xcb)
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(XCB 0.3.9 COMPONENTS KEYSYMS PROVIDED_TARGETS XCB::KEYSYMS MODULE_NAME gui QMAKE_LIB xcb_keysyms)
-endif()
-qt_add_qmake_lib_dependency(xcb_keysyms xcb)
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(XCB 0.3.9 COMPONENTS RENDERUTIL PROVIDED_TARGETS XCB::RENDERUTIL MODULE_NAME gui QMAKE_LIB xcb_renderutil)
-endif()
-qt_add_qmake_lib_dependency(xcb_renderutil xcb xcb_render)
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(XCB COMPONENTS RANDR PROVIDED_TARGETS XCB::RANDR MODULE_NAME gui QMAKE_LIB xcb_randr)
-endif()
-qt_add_qmake_lib_dependency(xcb_randr xcb)
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(XCB COMPONENTS SHAPE PROVIDED_TARGETS XCB::SHAPE MODULE_NAME gui QMAKE_LIB xcb_shape)
-endif()
-qt_add_qmake_lib_dependency(xcb_shape xcb)
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(XCB COMPONENTS SHM PROVIDED_TARGETS XCB::SHM MODULE_NAME gui QMAKE_LIB xcb_shm)
-endif()
-qt_add_qmake_lib_dependency(xcb_shm xcb)
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(XCB COMPONENTS SYNC PROVIDED_TARGETS XCB::SYNC MODULE_NAME gui QMAKE_LIB xcb_sync)
-endif()
-qt_add_qmake_lib_dependency(xcb_sync xcb)
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(XCB COMPONENTS XFIXES PROVIDED_TARGETS XCB::XFIXES MODULE_NAME gui QMAKE_LIB xcb_xfixes)
-endif()
-qt_add_qmake_lib_dependency(xcb_xfixes xcb)
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(X11_XCB PROVIDED_TARGETS X11::XCB MODULE_NAME gui QMAKE_LIB xcb_xlib)
-endif()
-qt_add_qmake_lib_dependency(xcb_xlib xcb xlib)
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(XCB COMPONENTS XKB PROVIDED_TARGETS XCB::XKB MODULE_NAME gui QMAKE_LIB xcb_xkb)
-endif()
-qt_add_qmake_lib_dependency(xcb_xkb xcb)
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(XCB COMPONENTS RENDER PROVIDED_TARGETS XCB::RENDER MODULE_NAME gui QMAKE_LIB xcb_render)
-endif()
-qt_add_qmake_lib_dependency(xcb_render xcb)
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(XCB COMPONENTS GLX PROVIDED_TARGETS XCB::GLX MODULE_NAME gui QMAKE_LIB xcb_glx)
-endif()
-qt_add_qmake_lib_dependency(xcb_glx xcb)
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(XCB 1.12 COMPONENTS XINPUT PROVIDED_TARGETS XCB::XINPUT MODULE_NAME gui QMAKE_LIB xcb_xinput)
-endif()
-qt_add_qmake_lib_dependency(xcb_xinput xcb)
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(XKB 0.5.0 PROVIDED_TARGETS XKB::XKB MODULE_NAME gui QMAKE_LIB xkbcommon)
-endif()
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(XKB_COMMON_X11 0.5.0 PROVIDED_TARGETS PkgConfig::XKB_COMMON_X11 MODULE_NAME gui QMAKE_LIB xkbcommon_x11)
-endif()
-if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(XRender 0.6 PROVIDED_TARGETS PkgConfig::XRender MODULE_NAME gui QMAKE_LIB xrender)
-endif()
-qt_add_qmake_lib_dependency(xrender xlib)
-
-
-#### Tests
-
-# drm_atomic
-qt_config_compile_test(drm_atomic
- LABEL "DRM Atomic API"
- LIBRARIES
- Libdrm::Libdrm
- CODE
-"#include <stdlib.h>
-#include <stdint.h>
-extern \"C\" {
-#include <xf86drmMode.h>
-#include <xf86drm.h>
-}
-
-int main(void)
-{
- /* BEGIN TEST: */
-drmModeAtomicReq *request;
- /* END TEST: */
- return 0;
-}
-")
-
-# egl-x11
-qt_config_compile_test(egl_x11
- LABEL "EGL on X11"
- LIBRARIES
- EGL::EGL
- X11::X11
- CODE
-"// Check if EGL is compatible with X. Some EGL implementations, typically on
-// embedded devices, are not intended to be used together with X. EGL support
-// has to be disabled in plugins like xcb in this case since the native display,
-// window and pixmap types will be different than what an X-based platform
-// plugin would expect.
-#include <EGL/egl.h>
-#include <X11/Xlib.h>
-
-int main(void)
-{
- /* BEGIN TEST: */
-Display *dpy = EGL_DEFAULT_DISPLAY;
-EGLNativeDisplayType egldpy = XOpenDisplay(\"\");
-dpy = egldpy;
-EGLNativeWindowType w = XCreateWindow(dpy, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
-XDestroyWindow(dpy, w);
-XCloseDisplay(dpy);
- /* END TEST: */
- return 0;
-}
-")
-
-# egl-brcm
-qt_config_compile_test(egl_brcm
- LABEL "Broadcom EGL (Raspberry Pi)"
- LIBRARIES
- EGL::EGL
- CODE
-"#include <EGL/egl.h>
-#include <bcm_host.h>
-
-int main(void)
-{
- /* BEGIN TEST: */
-vc_dispmanx_display_open(0);
- /* END TEST: */
- return 0;
-}
-"# FIXME: use: unmapped library: bcm_host
-)
-
-# egl-egldevice
-qt_config_compile_test(egl_egldevice
- LABEL "EGLDevice"
- LIBRARIES
- EGL::EGL
- CODE
-"#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-int main(void)
-{
- /* BEGIN TEST: */
-EGLDeviceEXT device = 0;
-EGLStreamKHR stream = 0;
-EGLOutputLayerEXT layer = 0;
-(void) EGL_DRM_CRTC_EXT;
- /* END TEST: */
- return 0;
-}
-")
-
-# egl-mali
-qt_config_compile_test(egl_mali
- LABEL "Mali EGL"
- LIBRARIES
- EGL::EGL
- CODE
-"#include <EGL/fbdev_window.h>
-#include <EGL/egl.h>
-#include <GLES2/gl2.h>
-
-int main(void)
-{
- /* BEGIN TEST: */
-fbdev_window *w = 0;
- /* END TEST: */
- return 0;
-}
-")
-
-# egl-mali-2
-qt_config_compile_test(egl_mali_2
- LABEL "Mali 2 EGL"
- LIBRARIES
- EGL::EGL
- CODE
-"#include <EGL/egl.h>
-#include <GLES2/gl2.h>
-
-int main(void)
-{
- /* BEGIN TEST: */
-mali_native_window *w = 0;
- /* END TEST: */
- return 0;
-}
-")
-
-# egl-viv
-qt_config_compile_test(egl_viv
- LABEL "i.Mx6 EGL"
- LIBRARIES
- EGL::EGL
- CODE
-"#include <EGL/egl.h>
-#include <EGL/eglvivante.h>
-
-int main(void)
-{
- /* BEGIN TEST: */
-#ifdef __INTEGRITY
-fbGetDisplay();
-#else
-// Do not rely on fbGetDisplay(), since the signature has changed over time.
-// Stick to fbGetDisplayByIndex().
-fbGetDisplayByIndex(0);
-#endif
- /* END TEST: */
- return 0;
-}
-"# FIXME: qmake: ['DEFINES += EGL_API_FB=1', '!integrity: DEFINES += LINUX=1']
-)
-
-# egl-openwfd
-qt_config_compile_test(egl_openwfd
- LABEL "OpenWFD EGL"
- LIBRARIES
- EGL::EGL
- CODE
-"#include <wfd.h>
-
-int main(void)
-{
- /* BEGIN TEST: */
-wfdEnumerateDevices(nullptr, 0, nullptr);
- /* END TEST: */
- return 0;
-}
-")
-
-# egl-rcar
-qt_config_compile_test(egl_rcar
- LABEL "RCAR EGL"
- LIBRARIES
- EGL::EGL
- GLESv2::GLESv2
- CODE
-"#include <EGL/egl.h>
-extern \"C\" {
-extern unsigned long PVRGrfxServerInit(void);
-}
-
-int main(void)
-{
- /* BEGIN TEST: */
-PVRGrfxServerInit();
- /* END TEST: */
- return 0;
-}
-")
-
-# evdev
-qt_config_compile_test(evdev
- LABEL "evdev"
- CODE
-"#if defined(__FreeBSD__)
-# include <dev/evdev/input.h>
-#else
-# include <linux/input.h>
-# include <linux/kd.h>
-#endif
-enum {
- e1 = ABS_PRESSURE,
- e2 = ABS_X,
- e3 = REL_X,
- e4 = SYN_REPORT,
-};
-
-int main(void)
-{
- /* BEGIN TEST: */
-input_event buf[32];
-(void) buf;
- /* END TEST: */
- return 0;
-}
-")
-
-# integrityfb
-qt_config_compile_test(integrityfb
- LABEL "INTEGRITY framebuffer"
- CODE
-"#include <device/fbdriver.h>
-
-int main(void)
-{
- /* BEGIN TEST: */
-FBDriver *driver = 0;
- /* END TEST: */
- return 0;
-}
-")
-
-# linuxfb
-qt_config_compile_test(linuxfb
- LABEL "LinuxFB"
- CODE
-"#include <linux/fb.h>
-#include <sys/kd.h>
-#include <sys/ioctl.h>
-
-int main(void)
-{
- /* BEGIN TEST: */
-fb_fix_screeninfo finfo;
-fb_var_screeninfo vinfo;
-int fd = 3;
-ioctl(fd, FBIOGET_FSCREENINFO, &finfo);
-ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
- /* END TEST: */
- return 0;
-}
-")
-
-# opengles3
-qt_config_compile_test(opengles3
- LABEL "OpenGL ES 3.0"
- LIBRARIES
- GLESv2::GLESv2
- CODE
-"#ifdef __APPLE__
-# include <OpenGLES/ES3/gl.h>
-#else
-# define GL_GLEXT_PROTOTYPES
-# include <GLES3/gl3.h>
-#endif
-
-int main(void)
-{
- /* BEGIN TEST: */
-static GLfloat f[6];
-glGetStringi(GL_EXTENSIONS, 0);
-glReadBuffer(GL_COLOR_ATTACHMENT1);
-glUniformMatrix2x3fv(0, 0, GL_FALSE, f);
-glMapBufferRange(GL_ARRAY_BUFFER, 0, 0, GL_MAP_READ_BIT);
- /* END TEST: */
- return 0;
-}
-")
-
-# opengles31
-qt_config_compile_test(opengles31
- LABEL "OpenGL ES 3.1"
- LIBRARIES
- GLESv2::GLESv2
- CODE
-"#include <GLES3/gl31.h>
-
-int main(void)
-{
- /* BEGIN TEST: */
-glDispatchCompute(1, 1, 1);
-glProgramUniform1i(0, 0, 0);
- /* END TEST: */
- return 0;
-}
-")
-
-# opengles32
-qt_config_compile_test(opengles32
- LABEL "OpenGL ES 3.2"
- LIBRARIES
- GLESv2::GLESv2
- CODE
-"#include <GLES3/gl32.h>
-
-int main(void)
-{
- /* BEGIN TEST: */
-glFramebufferTexture(GL_TEXTURE_2D, GL_DEPTH_STENCIL_ATTACHMENT, 1, 0);
- /* END TEST: */
- return 0;
-}
-")
-
-# xcb_syslibs
-qt_config_compile_test(xcb_syslibs
- LABEL "XCB (extensions)"
- LIBRARIES
- XCB::ICCCM
- XCB::IMAGE
- XCB::KEYSYMS
- XCB::RANDR
- XCB::RENDER
- XCB::RENDERUTIL
- XCB::SHAPE
- XCB::SHM
- XCB::SYNC
- XCB::XFIXES
- XCB::XKB
- XCB::XCB
- CODE
-"// xkb.h is using a variable called 'explicit', which is a reserved keyword in C++
-#define explicit dont_use_cxx_explicit
-#include <xcb/xcb.h>
-#include <xcb/xcb_image.h>
-#include <xcb/xcb_keysyms.h>
-#include <xcb/randr.h>
-#include <xcb/render.h>
-#include <xcb/shape.h>
-#include <xcb/shm.h>
-#include <xcb/sync.h>
-#include <xcb/xfixes.h>
-#include <xcb/xcb_icccm.h>
-#include <xcb/xcb_renderutil.h>
-#include <xcb/xkb.h>
-#undef explicit
-
-int main(void)
-{
- /* BEGIN TEST: */
-int primaryScreen = 0;
-xcb_connection_t *c = xcb_connect(\"\", &primaryScreen);
-/* RENDER */
-xcb_generic_error_t *error = nullptr;
-xcb_render_query_pict_formats_cookie_t formatsCookie =
- xcb_render_query_pict_formats(c);
-xcb_render_query_pict_formats_reply_t *formatsReply =
- xcb_render_query_pict_formats_reply(c, formatsCookie, &error);
-/* RENDERUTIL: xcb_renderutil.h include won't compile unless version >= 0.3.9 */
-xcb_render_util_find_standard_format(nullptr, XCB_PICT_STANDARD_ARGB_32);
-/* XKB: This takes more arguments in xcb-xkb < 1.11 */
-xcb_xkb_get_kbd_by_name_replies_key_names_value_list_sizeof(nullptr, 0, 0, 0, 0, 0, 0, 0, 0);
- /* END TEST: */
- return 0;
-}
-")
-
-
-
-#### Features
-
-qt_feature("accessibility-atspi-bridge" PUBLIC PRIVATE
- LABEL "ATSPI Bridge"
- CONDITION QT_FEATURE_accessibility AND QT_FEATURE_xcb AND QT_FEATURE_dbus AND ATSPI2_FOUND
-)
-qt_feature_definition("accessibility-atspi-bridge" "QT_NO_ACCESSIBILITY_ATSPI_BRIDGE" NEGATE VALUE "1")
-qt_feature("directfb" PRIVATE
- SECTION "Platform plugins"
- LABEL "DirectFB"
- AUTODETECT OFF
- CONDITION DirectFB_FOUND
-)
-qt_feature("directwrite" PRIVATE
- LABEL "DirectWrite"
- CONDITION libs.dwrite_2 OR FIXME
- EMIT_IF WIN32
-)
-qt_feature("directwrite3" PRIVATE
- LABEL "DirectWrite 3"
- CONDITION QT_FEATURE_directwrite AND libs.dwrite_3 OR FIXME
- EMIT_IF WIN32
-)
-qt_feature("direct2d" PRIVATE
- LABEL "Direct 2D"
- CONDITION WIN32 AND libs.d2d1 OR FIXME
-)
-qt_feature("direct2d1_1" PRIVATE
- LABEL "Direct 2D 1.1"
- CONDITION QT_FEATURE_direct2d AND libs.d2d1_1 OR FIXME
-)
-qt_feature("evdev" PRIVATE
- LABEL "evdev"
- CONDITION QT_FEATURE_thread AND TEST_evdev
-)
-qt_feature("freetype" PUBLIC PRIVATE
- SECTION "Fonts"
- LABEL "FreeType"
- PURPOSE "Supports the FreeType 2 font engine (and its supported font formats)."
-)
-qt_feature_definition("freetype" "QT_NO_FREETYPE" NEGATE VALUE "1")
-qt_feature("system-freetype" PRIVATE
- LABEL " Using system FreeType"
- AUTODETECT NOT MSVC
- CONDITION QT_FEATURE_freetype AND WrapSystemFreetype_FOUND
- ENABLE INPUT_freetype STREQUAL 'system'
- DISABLE INPUT_freetype STREQUAL 'qt'
-)
-qt_feature("fontconfig" PUBLIC PRIVATE
- LABEL "Fontconfig"
- AUTODETECT NOT APPLE
- CONDITION NOT WIN32 AND QT_FEATURE_system_freetype AND FONTCONFIG_FOUND
-)
-qt_feature_definition("fontconfig" "QT_NO_FONTCONFIG" NEGATE VALUE "1")
-qt_feature("gbm"
- LABEL "GBM"
- CONDITION gbm_FOUND
-)
-qt_feature_config("gbm" QMAKE_PUBLIC_QT_CONFIG)
-qt_feature("harfbuzz" PUBLIC PRIVATE
- LABEL "HarfBuzz"
-)
-qt_feature_definition("harfbuzz" "QT_NO_HARFBUZZ" NEGATE VALUE "1")
-qt_feature("system-harfbuzz" PRIVATE
- LABEL " Using system HarfBuzz"
- AUTODETECT NOT APPLE AND NOT WIN32
- CONDITION QT_FEATURE_harfbuzz AND WrapSystemHarfbuzz_FOUND
- ENABLE INPUT_harfbuzz STREQUAL 'system'
- DISABLE INPUT_harfbuzz STREQUAL 'qt'
-)
-qt_feature("qqnx_imf" PRIVATE
- LABEL "IMF"
- CONDITION libs.imf OR FIXME
- EMIT_IF QNX
-)
-qt_feature("integrityfb" PRIVATE
- SECTION "Platform plugins"
- LABEL "INTEGRITY framebuffer"
- CONDITION INTEGRITY AND TEST_integrityfb
-)
-qt_feature("kms" PRIVATE
- LABEL "KMS"
- CONDITION Libdrm_FOUND
-)
-qt_feature_config("kms" QMAKE_PUBLIC_QT_CONFIG)
-qt_feature("drm_atomic" PRIVATE
- LABEL "DRM Atomic API"
- CONDITION Libdrm_FOUND AND TEST_drm_atomic
-)
-qt_feature("libinput" PRIVATE
- LABEL "libinput"
- CONDITION QT_FEATURE_libudev AND Libinput_FOUND
-)
-qt_feature("integrityhid" PRIVATE
- LABEL "INTEGRITY HID"
- CONDITION INTEGRITY AND libs.integrityhid OR FIXME
-)
-qt_feature("libinput-axis-api" PRIVATE
- LABEL "axis API in libinput"
- CONDITION QT_FEATURE_libinput AND ON
-)
-qt_feature("lgmon"
- LABEL "lgmon"
- CONDITION libs.lgmon OR FIXME
- EMIT_IF QNX
-)
-qt_feature_config("lgmon" QMAKE_PRIVATE_CONFIG)
-qt_feature("linuxfb" PRIVATE
- SECTION "Platform plugins"
- LABEL "LinuxFB"
- CONDITION TEST_linuxfb AND QT_FEATURE_regularexpression
-)
-qt_feature("vsp2" PRIVATE
- LABEL "VSP2"
- AUTODETECT OFF
- CONDITION libs.v4l2 OR FIXME
-)
-qt_feature("vnc" PRIVATE
- SECTION "Platform plugins"
- LABEL "VNC"
- CONDITION ( UNIX AND NOT ANDROID AND NOT APPLE AND NOT WASM ) AND ( QT_FEATURE_regularexpression AND QT_FEATURE_network )
-)
-qt_feature("mtdev" PRIVATE
- LABEL "mtdev"
- CONDITION Mtdev_FOUND
-)
-qt_feature("opengles2" PUBLIC
- LABEL "OpenGL ES 2.0"
- CONDITION NOT WIN32 AND NOT WATCHOS AND NOT QT_FEATURE_opengl_desktop AND GLESv2_FOUND
- ENABLE INPUT_opengl STREQUAL 'es2'
- DISABLE INPUT_opengl STREQUAL 'desktop' OR INPUT_opengl STREQUAL 'dynamic' OR INPUT_opengl STREQUAL 'no'
-)
-qt_feature_config("opengles2" QMAKE_PUBLIC_QT_CONFIG)
-qt_feature("opengles3" PUBLIC
- LABEL "OpenGL ES 3.0"
- CONDITION QT_FEATURE_opengles2 AND TEST_opengles3
-)
-qt_feature("opengles31" PUBLIC
- LABEL "OpenGL ES 3.1"
- CONDITION QT_FEATURE_opengles3 AND TEST_opengles31
-)
-qt_feature("opengles32" PUBLIC
- LABEL "OpenGL ES 3.2"
- CONDITION QT_FEATURE_opengles31 AND TEST_opengles32
-)
-qt_feature("opengl-desktop"
- LABEL "Desktop OpenGL"
- AUTODETECT NOT WIN32
- CONDITION ( WIN32 AND ( MSVC OR WrapOpenGL_FOUND ) ) OR ( NOT WATCHOS AND NOT WIN32 AND NOT WASM AND WrapOpenGL_FOUND )
- ENABLE INPUT_opengl STREQUAL 'desktop'
- DISABLE INPUT_opengl STREQUAL 'es2' OR INPUT_opengl STREQUAL 'dynamic' OR INPUT_opengl STREQUAL 'no'
-)
-qt_feature("opengl-dynamic"
- LABEL "Dynamic OpenGL"
- CONDITION WIN32
- DISABLE INPUT_opengl STREQUAL 'no' OR INPUT_opengl STREQUAL 'desktop'
-)
-qt_feature("dynamicgl" PUBLIC
- LABEL "Dynamic OpenGL: dynamicgl"
- CONDITION QT_FEATURE_opengl_dynamic
- DISABLE INPUT_opengl STREQUAL 'no' OR INPUT_opengl STREQUAL 'desktop'
-)
-qt_feature_definition("opengl-dynamic" "QT_OPENGL_DYNAMIC")
-qt_feature("opengl" PUBLIC
- LABEL "OpenGL"
- CONDITION QT_FEATURE_opengl_desktop OR QT_FEATURE_opengl_dynamic OR QT_FEATURE_opengles2
-)
-qt_feature_definition("opengl" "QT_NO_OPENGL" NEGATE VALUE "1")
-qt_feature("vkgen" PRIVATE
- LABEL "vkgen"
- CONDITION QT_FEATURE_xmlstreamreader
-)
-qt_feature("vulkan" PUBLIC
- LABEL "Vulkan"
- CONDITION QT_FEATURE_vkgen AND Vulkan_FOUND
-)
-qt_feature("openvg" PUBLIC
- LABEL "OpenVG"
- CONDITION libs.openvg OR FIXME
-)
-qt_feature("egl" PUBLIC
- LABEL "EGL"
- CONDITION ( QT_FEATURE_opengl OR QT_FEATURE_openvg ) AND EGL_FOUND AND ( QT_FEATURE_dlopen OR NOT UNIX OR INTEGRITY )
-)
-qt_feature_definition("egl" "QT_NO_EGL" NEGATE VALUE "1")
-qt_feature("egl_x11" PRIVATE
- LABEL "EGL on X11"
- CONDITION QT_FEATURE_thread AND QT_FEATURE_egl AND TEST_egl_x11
-)
-qt_feature("eglfs" PRIVATE
- SECTION "Platform plugins"
- LABEL "EGLFS"
- CONDITION NOT ANDROID AND NOT APPLE AND NOT WIN32 AND NOT WASM AND QT_FEATURE_egl
-)
-qt_feature("eglfs_brcm" PRIVATE
- LABEL "EGLFS Raspberry Pi"
- CONDITION QT_FEATURE_eglfs AND TEST_egl_brcm
-)
-qt_feature("eglfs_egldevice" PRIVATE
- LABEL "EGLFS EGLDevice"
- CONDITION QT_FEATURE_eglfs AND TEST_egl_egldevice AND QT_FEATURE_kms
-)
-qt_feature("eglfs_gbm" PRIVATE
- LABEL "EGLFS GBM"
- CONDITION QT_FEATURE_eglfs AND gbm_FOUND AND QT_FEATURE_kms
-)
-qt_feature("eglfs_vsp2" PRIVATE
- LABEL "EGLFS VSP2"
- CONDITION QT_FEATURE_eglfs AND gbm_FOUND AND QT_FEATURE_kms AND QT_FEATURE_vsp2
-)
-qt_feature("eglfs_mali" PRIVATE
- LABEL "EGLFS Mali"
- CONDITION QT_FEATURE_eglfs AND ( TEST_egl_mali OR TEST_egl_mali_2 )
-)
-qt_feature("eglfs_viv" PRIVATE
- LABEL "EGLFS i.Mx6"
- CONDITION QT_FEATURE_eglfs AND TEST_egl_viv
-)
-qt_feature("eglfs_rcar" PRIVATE
- LABEL "EGLFS RCAR"
- CONDITION INTEGRITY AND QT_FEATURE_eglfs AND TEST_egl_rcar
-)
-qt_feature("eglfs_viv_wl" PRIVATE
- LABEL "EGLFS i.Mx6 Wayland"
- CONDITION QT_FEATURE_eglfs_viv AND Wayland_FOUND
-)
-qt_feature("eglfs_openwfd" PRIVATE
- LABEL "EGLFS OpenWFD"
- CONDITION INTEGRITY AND QT_FEATURE_eglfs AND TEST_egl_openwfd
-)
-qt_feature("eglfs_x11" PRIVATE
- LABEL "EGLFS X11"
- CONDITION QT_FEATURE_eglfs AND QT_FEATURE_xcb_xlib AND QT_FEATURE_egl_x11
-)
-qt_feature("gif" PRIVATE
- LABEL "GIF"
- CONDITION QT_FEATURE_imageformatplugin
-)
-qt_feature_definition("gif" "QT_NO_IMAGEFORMAT_GIF" NEGATE)
-qt_feature("ico" PUBLIC PRIVATE
- LABEL "ICO"
- CONDITION QT_FEATURE_imageformatplugin
-)
-qt_feature_definition("ico" "QT_NO_ICO" NEGATE VALUE "1")
-qt_feature("jpeg" PRIVATE
- LABEL "JPEG"
- CONDITION QT_FEATURE_imageformatplugin
- DISABLE INPUT_libjpeg STREQUAL 'no'
-)
-qt_feature_definition("jpeg" "QT_NO_IMAGEFORMAT_JPEG" NEGATE)
-qt_feature("system-jpeg" PRIVATE
- LABEL " Using system libjpeg"
- CONDITION QT_FEATURE_jpeg AND JPEG_FOUND
- ENABLE INPUT_libjpeg STREQUAL 'system'
- DISABLE INPUT_libjpeg STREQUAL 'qt'
-)
-qt_feature("png" PRIVATE
- LABEL "PNG"
- DISABLE INPUT_libpng STREQUAL 'no'
-)
-qt_feature_definition("png" "QT_NO_IMAGEFORMAT_PNG" NEGATE)
-qt_feature("system-png" PRIVATE
- LABEL " Using system libpng"
- AUTODETECT QT_FEATURE_system_zlib
- CONDITION QT_FEATURE_png AND WrapSystemPNG_FOUND
- ENABLE INPUT_libpng STREQUAL 'system'
- DISABLE INPUT_libpng STREQUAL 'qt'
-)
-qt_feature("imageio-text-loading" PRIVATE
- LABEL "Image Text section loading"
-)
-qt_feature_definition("imageio-text-loading" "QT_NO_IMAGEIO_TEXT_LOADING" NEGATE)
-qt_feature("sessionmanager" PUBLIC
- SECTION "Kernel"
- LABEL "Session Management"
- PURPOSE "Provides an interface to the windowing system's session management."
-)
-qt_feature_definition("sessionmanager" "QT_NO_SESSIONMANAGER" NEGATE VALUE "1")
-qt_feature("tslib" PRIVATE
- LABEL "tslib"
- CONDITION Tslib_FOUND
-)
-qt_feature("tuiotouch" PRIVATE
- LABEL "TuioTouch"
- PURPOSE "Provides the TuioTouch input plugin."
- CONDITION QT_FEATURE_network AND QT_FEATURE_udpsocket
-)
-qt_feature("xcb" PRIVATE
- SECTION "Platform plugins"
- LABEL "XCB"
- AUTODETECT NOT APPLE
- CONDITION QT_FEATURE_thread AND TARGET XCB::XCB AND TEST_xcb_syslibs AND QT_FEATURE_xkbcommon_x11
-)
-qt_feature("xcb-glx-plugin" PUBLIC
- LABEL "GLX Plugin"
- CONDITION QT_FEATURE_xcb_xlib AND QT_FEATURE_opengl AND NOT QT_FEATURE_opengles2
- EMIT_IF QT_FEATURE_xcb
-)
-qt_feature("xcb-glx" PRIVATE
- LABEL " XCB GLX"
- CONDITION XCB_GLX_FOUND
- EMIT_IF QT_FEATURE_xcb AND QT_FEATURE_xcb_glx_plugin
-)
-qt_feature("xcb-egl-plugin" PRIVATE
- LABEL "EGL-X11 Plugin"
- CONDITION QT_FEATURE_egl_x11 AND QT_FEATURE_opengl
- EMIT_IF QT_FEATURE_xcb
-)
-qt_feature("xcb-native-painting" PRIVATE
- LABEL "Native painting (experimental)"
- AUTODETECT OFF
- CONDITION QT_FEATURE_xcb_xlib AND QT_FEATURE_fontconfig AND XRender_FOUND
- EMIT_IF QT_FEATURE_xcb
-)
-qt_feature("xrender" PRIVATE
- LABEL "XRender for native painting"
- CONDITION QT_FEATURE_xcb_native_painting
- EMIT_IF QT_FEATURE_xcb AND QT_FEATURE_xcb_native_painting
-)
-qt_feature("xcb-xlib" PRIVATE
- LABEL "XCB Xlib"
- CONDITION QT_FEATURE_xlib AND X11_XCB_FOUND
-)
-qt_feature("xcb-sm" PRIVATE
- LABEL "xcb-sm"
- CONDITION QT_FEATURE_sessionmanager AND X11_SM_FOUND
- EMIT_IF QT_FEATURE_xcb
-)
-qt_feature("system-xcb-xinput" PRIVATE
- LABEL "Using system-provided xcb-xinput"
- CONDITION XCB_XINPUT_FOUND
- ENABLE INPUT_bundled_xcb_xinput STREQUAL 'no'
- DISABLE INPUT_bundled_xcb_xinput STREQUAL 'yes'
- EMIT_IF QT_FEATURE_xcb
-)
-qt_feature("xkbcommon" PRIVATE
- LABEL "xkbcommon"
- CONDITION XKB_FOUND
-)
-qt_feature("xkbcommon-x11" PRIVATE
- LABEL "xkbcommon-x11"
- CONDITION QT_FEATURE_xkbcommon AND XKB_COMMON_X11_FOUND
-)
-qt_feature("xlib" PRIVATE
- LABEL "XLib"
- AUTODETECT NOT APPLE OR QT_FEATURE_xcb
- CONDITION X11_FOUND
-)
-qt_feature("texthtmlparser" PUBLIC
- SECTION "Kernel"
- LABEL "HtmlParser"
- PURPOSE "Provides a parser for HTML."
-)
-qt_feature_definition("texthtmlparser" "QT_NO_TEXTHTMLPARSER" NEGATE VALUE "1")
-qt_feature("textmarkdownreader" PUBLIC
- SECTION "Kernel"
- LABEL "MarkdownReader"
- PURPOSE "Provides a Markdown (CommonMark and GitHub) reader"
- ENABLE INPUT_libmd4c STREQUAL 'system' OR INPUT_libmd4c STREQUAL 'qt' OR INPUT_libmd4c STREQUAL 'yes'
- DISABLE INPUT_libmd4c STREQUAL 'no'
-)
-qt_feature("system-textmarkdownreader" PUBLIC
- SECTION "Kernel"
- LABEL " Using system libmd4c"
- CONDITION libs.libmd4c OR FIXME
- ENABLE INPUT_libmd4c STREQUAL 'system'
- DISABLE INPUT_libmd4c STREQUAL 'qt'
-)
-qt_feature("textmarkdownwriter" PUBLIC
- SECTION "Kernel"
- LABEL "MarkdownWriter"
- PURPOSE "Provides a Markdown (CommonMark) writer"
-)
-qt_feature("textodfwriter" PUBLIC
- SECTION "Kernel"
- LABEL "OdfWriter"
- PURPOSE "Provides an ODF writer."
- CONDITION QT_FEATURE_xmlstreamwriter
-)
-qt_feature_definition("textodfwriter" "QT_NO_TEXTODFWRITER" NEGATE VALUE "1")
-qt_feature("cssparser" PUBLIC
- SECTION "Kernel"
- LABEL "CssParser"
- PURPOSE "Provides a parser for Cascading Style Sheets."
-)
-qt_feature_definition("cssparser" "QT_NO_CSSPARSER" NEGATE VALUE "1")
-qt_feature("draganddrop" PUBLIC
- SECTION "Kernel"
- LABEL "Drag and Drop"
- PURPOSE "Supports the drag and drop mechansim."
- CONDITION QT_FEATURE_imageformat_xpm
-)
-qt_feature_definition("draganddrop" "QT_NO_DRAGANDDROP" NEGATE VALUE "1")
-qt_feature("action" PUBLIC
- SECTION "Kernel"
- LABEL "Q(Gui)Action(Group)"
- PURPOSE "Provides abstract user interface actions."
-)
-qt_feature_definition("action" "QT_NO_ACTION" NEGATE VALUE "1")
-qt_feature("cursor" PUBLIC
- SECTION "Kernel"
- LABEL "QCursor"
- PURPOSE "Provides mouse cursors."
-)
-qt_feature_definition("cursor" "QT_NO_CURSOR" NEGATE VALUE "1")
-qt_feature("clipboard" PUBLIC
- SECTION "Kernel"
- LABEL "QClipboard"
- PURPOSE "Provides cut and paste operations."
- CONDITION NOT INTEGRITY AND NOT QNX AND NOT rtems
-)
-qt_feature_definition("clipboard" "QT_NO_CLIPBOARD" NEGATE VALUE "1")
-qt_feature("wheelevent" PUBLIC
- SECTION "Kernel"
- LABEL "QWheelEvent"
- PURPOSE "Supports wheel events."
-)
-qt_feature_definition("wheelevent" "QT_NO_WHEELEVENT" NEGATE VALUE "1")
-qt_feature("tabletevent" PUBLIC
- SECTION "Kernel"
- LABEL "QTabletEvent"
- PURPOSE "Supports tablet events."
-)
-qt_feature_definition("tabletevent" "QT_NO_TABLETEVENT" NEGATE VALUE "1")
-qt_feature("im" PUBLIC
- SECTION "Kernel"
- LABEL "QInputContext"
- PURPOSE "Provides complex input methods."
- CONDITION QT_FEATURE_library
-)
-qt_feature_definition("im" "QT_NO_IM" NEGATE VALUE "1")
-qt_feature("highdpiscaling" PUBLIC
- SECTION "Kernel"
- LABEL "High DPI Scaling"
- PURPOSE "Provides automatic scaling of DPI-unaware applications on high-DPI displays."
-)
-qt_feature_definition("highdpiscaling" "QT_NO_HIGHDPISCALING" NEGATE VALUE "1")
-qt_feature("validator" PUBLIC
- SECTION "Widgets"
- LABEL "QValidator"
- PURPOSE "Supports validation of input text."
-)
-qt_feature_definition("validator" "QT_NO_VALIDATOR" NEGATE VALUE "1")
-qt_feature("standarditemmodel" PUBLIC
- SECTION "ItemViews"
- LABEL "QStandardItemModel"
- PURPOSE "Provides a generic model for storing custom data."
- CONDITION QT_FEATURE_itemmodel
-)
-qt_feature_definition("standarditemmodel" "QT_NO_STANDARDITEMMODEL" NEGATE VALUE "1")
-qt_feature("filesystemmodel" PUBLIC
- SECTION "File I/O"
- LABEL "QFileSystemModel"
- PURPOSE "Provides a data model for the local filesystem."
- CONDITION QT_FEATURE_itemmodel
-)
-qt_feature_definition("filesystemmodel" "QT_NO_FILESYSTEMMODEL" NEGATE VALUE "1")
-qt_feature("imageformatplugin" PUBLIC
- SECTION "Images"
- LABEL "QImageIOPlugin"
- PURPOSE "Provides a base for writing a image format plugins."
-)
-qt_feature_definition("imageformatplugin" "QT_NO_IMAGEFORMATPLUGIN" NEGATE VALUE "1")
-qt_feature("movie" PUBLIC
- SECTION "Images"
- LABEL "QMovie"
- PURPOSE "Supports animated images."
-)
-qt_feature_definition("movie" "QT_NO_MOVIE" NEGATE VALUE "1")
-qt_feature("imageformat_bmp" PUBLIC
- SECTION "Images"
- LABEL "BMP Image Format"
- PURPOSE "Supports Microsoft's Bitmap image file format."
-)
-qt_feature_definition("imageformat_bmp" "QT_NO_IMAGEFORMAT_BMP" NEGATE VALUE "1")
-qt_feature("imageformat_ppm" PUBLIC
- SECTION "Images"
- LABEL "PPM Image Format"
- PURPOSE "Supports the Portable Pixmap image file format."
-)
-qt_feature_definition("imageformat_ppm" "QT_NO_IMAGEFORMAT_PPM" NEGATE VALUE "1")
-qt_feature("imageformat_xbm" PUBLIC
- SECTION "Images"
- LABEL "XBM Image Format"
- PURPOSE "Supports the X11 Bitmap image file format."
-)
-qt_feature_definition("imageformat_xbm" "QT_NO_IMAGEFORMAT_XBM" NEGATE VALUE "1")
-qt_feature("imageformat_xpm" PUBLIC
- SECTION "Images"
- LABEL "XPM Image Format"
- PURPOSE "Supports the X11 Pixmap image file format."
-)
-qt_feature_definition("imageformat_xpm" "QT_NO_IMAGEFORMAT_XPM" NEGATE VALUE "1")
-qt_feature("imageformat_png" PUBLIC
- SECTION "Images"
- LABEL "PNG Image Format"
- PURPOSE "Supports the Portable Network Graphics image file format."
-)
-qt_feature_definition("imageformat_png" "QT_NO_IMAGEFORMAT_PNG" NEGATE VALUE "1")
-qt_feature("imageformat_jpeg" PUBLIC
- SECTION "Images"
- LABEL "JPEG Image Format"
- PURPOSE "Supports the Joint Photographic Experts Group image file format."
-)
-qt_feature_definition("imageformat_jpeg" "QT_NO_IMAGEFORMAT_JPEG" NEGATE VALUE "1")
-qt_feature("image_heuristic_mask" PUBLIC
- SECTION "Images"
- LABEL "QImage::createHeuristicMask()"
- PURPOSE "Supports creating a 1-bpp heuristic mask for images."
-)
-qt_feature_definition("image_heuristic_mask" "QT_NO_IMAGE_HEURISTIC_MASK" NEGATE VALUE "1")
-qt_feature("image_text" PUBLIC
- SECTION "Images"
- LABEL "Image Text"
- PURPOSE "Supports image file text strings."
-)
-qt_feature_definition("image_text" "QT_NO_IMAGE_TEXT" NEGATE VALUE "1")
-qt_feature("picture" PUBLIC
- SECTION "Painting"
- LABEL "QPicture"
- PURPOSE "Supports recording and replaying QPainter commands."
-)
-qt_feature_definition("picture" "QT_NO_PICTURE" NEGATE VALUE "1")
-qt_feature("colornames" PUBLIC
- SECTION "Painting"
- LABEL "Color Names"
- PURPOSE "Supports color names such as \"red\", used by QColor and by some HTML documents."
-)
-qt_feature_definition("colornames" "QT_NO_COLORNAMES" NEGATE VALUE "1")
-qt_feature("pdf" PUBLIC
- SECTION "Painting"
- LABEL "QPdf"
- PURPOSE "Provides a PDF backend for QPainter."
- CONDITION QT_FEATURE_temporaryfile
-)
-qt_feature_definition("pdf" "QT_NO_PDF" NEGATE VALUE "1")
-qt_feature("desktopservices" PUBLIC
- SECTION "Utilities"
- LABEL "QDesktopServices"
- PURPOSE "Provides methods for accessing common desktop services."
-)
-qt_feature_definition("desktopservices" "QT_NO_DESKTOPSERVICES" NEGATE VALUE "1")
-qt_feature("systemtrayicon" PUBLIC
- SECTION "Utilities"
- LABEL "QSystemTrayIcon"
- PURPOSE "Provides an icon for an application in the system tray."
- CONDITION QT_FEATURE_temporaryfile
-)
-qt_feature_definition("systemtrayicon" "QT_NO_SYSTEMTRAYICON" NEGATE VALUE "1")
-qt_feature("accessibility" PUBLIC
- SECTION "Utilities"
- LABEL "Accessibility"
- PURPOSE "Provides accessibility support."
- CONDITION QT_FEATURE_properties
-)
-qt_feature_definition("accessibility" "QT_NO_ACCESSIBILITY" NEGATE VALUE "1")
-qt_feature("multiprocess" PRIVATE
- SECTION "Utilities"
- LABEL "Multi process"
- PURPOSE "Provides support for detecting the desktop environment, launching external processes and opening URLs."
- CONDITION NOT INTEGRITY AND NOT rtems
-)
-qt_feature("whatsthis" PUBLIC
- SECTION "Widget Support"
- LABEL "QWhatsThis"
- PURPOSE "Supports displaying \"What's this\" help."
-)
-qt_feature_definition("whatsthis" "QT_NO_WHATSTHIS" NEGATE VALUE "1")
-qt_feature("raster-64bit" PRIVATE
- SECTION "Painting"
- LABEL "QPainter - 64 bit raster"
- PURPOSE "Internal painting support for 64 bit (16 bpc) rasterization."
-)
-qt_feature("undocommand" PUBLIC
- SECTION "Utilities"
- LABEL "QUndoCommand"
- PURPOSE "Applies (redo or) undo of a single change in a document."
-)
-qt_feature_definition("undocommand" "QT_NO_UNDOCOMMAND" NEGATE VALUE "1")
-qt_feature("undostack" PUBLIC
- SECTION "Utilities"
- LABEL "QUndoStack"
- PURPOSE "Provides the ability to (redo or) undo a list of changes in a document."
- CONDITION QT_FEATURE_undocommand
-)
-qt_feature_definition("undostack" "QT_NO_UNDOSTACK" NEGATE VALUE "1")
-qt_feature("undogroup" PUBLIC
- SECTION "Utilities"
- LABEL "QUndoGroup"
- PURPOSE "Provides the ability to cluster QUndoCommands."
- CONDITION QT_FEATURE_undostack
-)
-qt_feature_definition("undogroup" "QT_NO_UNDOGROUP" NEGATE VALUE "1")
-qt_configure_add_summary_section(NAME "Qt Gui")
-qt_configure_add_summary_entry(ARGS "accessibility")
-qt_configure_add_summary_entry(ARGS "freetype")
-qt_configure_add_summary_entry(ARGS "system-freetype")
-qt_configure_add_summary_entry(ARGS "harfbuzz")
-qt_configure_add_summary_entry(ARGS "system-harfbuzz")
-qt_configure_add_summary_entry(ARGS "fontconfig")
-qt_configure_add_summary_section(NAME "Image formats")
-qt_configure_add_summary_entry(ARGS "gif")
-qt_configure_add_summary_entry(ARGS "ico")
-qt_configure_add_summary_entry(ARGS "jpeg")
-qt_configure_add_summary_entry(ARGS "system-jpeg")
-qt_configure_add_summary_entry(ARGS "png")
-qt_configure_add_summary_entry(ARGS "system-png")
-qt_configure_end_summary_section() # end of "Image formats" section
-qt_configure_add_summary_section(NAME "Text formats")
-qt_configure_add_summary_entry(ARGS "texthtmlparser")
-qt_configure_add_summary_entry(ARGS "cssparser")
-qt_configure_add_summary_entry(ARGS "textodfwriter")
-qt_configure_add_summary_entry(ARGS "textmarkdownreader")
-qt_configure_add_summary_entry(ARGS "system-textmarkdownreader")
-qt_configure_add_summary_entry(ARGS "textmarkdownwriter")
-qt_configure_end_summary_section() # end of "Text formats" section
-qt_configure_add_summary_entry(ARGS "egl")
-qt_configure_add_summary_entry(ARGS "openvg")
-qt_configure_add_summary_section(NAME "OpenGL")
-qt_configure_add_summary_entry(ARGS "opengl-desktop")
-qt_configure_add_summary_entry(
- ARGS "opengl-dynamic"
- CONDITION WIN32
-)
-qt_configure_add_summary_entry(ARGS "opengles2")
-qt_configure_add_summary_entry(ARGS "opengles3")
-qt_configure_add_summary_entry(ARGS "opengles31")
-qt_configure_add_summary_entry(ARGS "opengles32")
-qt_configure_end_summary_section() # end of "OpenGL" section
-qt_configure_add_summary_entry(ARGS "vulkan")
-qt_configure_add_summary_entry(ARGS "sessionmanager")
-qt_configure_end_summary_section() # end of "Qt Gui" section
-qt_configure_add_summary_section(NAME "Features used by QPA backends")
-qt_configure_add_summary_entry(ARGS "evdev")
-qt_configure_add_summary_entry(ARGS "libinput")
-qt_configure_add_summary_entry(ARGS "integrityhid")
-qt_configure_add_summary_entry(ARGS "mtdev")
-qt_configure_add_summary_entry(ARGS "tslib")
-qt_configure_add_summary_entry(ARGS "xkbcommon")
-qt_configure_add_summary_section(NAME "X11 specific")
-qt_configure_add_summary_entry(ARGS "xlib")
-qt_configure_add_summary_entry(ARGS "xcb-xlib")
-qt_configure_add_summary_entry(ARGS "egl_x11")
-qt_configure_add_summary_entry(ARGS "xkbcommon-x11")
-qt_configure_end_summary_section() # end of "X11 specific" section
-qt_configure_end_summary_section() # end of "Features used by QPA backends" section
-qt_configure_add_summary_section(NAME "QPA backends")
-qt_configure_add_summary_entry(ARGS "directfb")
-qt_configure_add_summary_entry(ARGS "eglfs")
-qt_configure_add_summary_section(NAME "EGLFS details")
-qt_configure_add_summary_entry(ARGS "eglfs_openwfd")
-qt_configure_add_summary_entry(ARGS "eglfs_viv")
-qt_configure_add_summary_entry(ARGS "eglfs_viv_wl")
-qt_configure_add_summary_entry(ARGS "eglfs_rcar")
-qt_configure_add_summary_entry(ARGS "eglfs_egldevice")
-qt_configure_add_summary_entry(ARGS "eglfs_gbm")
-qt_configure_add_summary_entry(ARGS "eglfs_vsp2")
-qt_configure_add_summary_entry(ARGS "eglfs_mali")
-qt_configure_add_summary_entry(ARGS "eglfs_brcm")
-qt_configure_add_summary_entry(ARGS "eglfs_x11")
-qt_configure_end_summary_section() # end of "EGLFS details" section
-qt_configure_add_summary_entry(ARGS "linuxfb")
-qt_configure_add_summary_entry(ARGS "vnc")
-qt_configure_add_summary_entry(
- ARGS "integrityfb"
- CONDITION INTEGRITY
-)
-qt_configure_add_summary_section(NAME "QNX")
-qt_configure_add_summary_entry(ARGS "lgmon")
-qt_configure_add_summary_entry(ARGS "qqnx_imf")
-qt_configure_end_summary_section() # end of "QNX" section
-qt_configure_add_summary_section(NAME "XCB")
-qt_configure_add_summary_entry(ARGS "system-xcb-xinput")
-qt_configure_add_summary_entry(ARGS "xcb-native-painting")
-qt_configure_add_summary_section(NAME "GL integrations")
-qt_configure_add_summary_entry(ARGS "xcb-glx-plugin")
-qt_configure_add_summary_entry(ARGS "xcb-glx")
-qt_configure_add_summary_entry(ARGS "xcb-egl-plugin")
-qt_configure_end_summary_section() # end of "GL integrations" section
-qt_configure_end_summary_section() # end of "XCB" section
-qt_configure_add_summary_section(NAME "Windows")
-qt_configure_add_summary_entry(ARGS "direct2d")
-qt_configure_add_summary_entry(ARGS "directwrite")
-qt_configure_add_summary_entry(ARGS "directwrite3")
-qt_configure_end_summary_section() # end of "Windows" section
-qt_configure_end_summary_section() # end of "QPA backends" section
-qt_configure_add_report_entry(
- TYPE NOTE
- MESSAGE "XCB support on macOS is minimal and untested. Some features will not work properly or at all (e.g. OpenGL, desktop services or accessibility), or may depend on your system and XQuartz setup."
- CONDITION QT_FEATURE_xcb AND APPLE
-)
-qt_configure_add_report_entry(
- TYPE NOTE
- MESSAGE "Disabling X11 Accessibility Bridge: D-Bus or AT-SPI is missing."
- CONDITION QT_FEATURE_accessibility AND QT_FEATURE_xcb AND NOT QT_FEATURE_accessibility_atspi_bridge
-)
-qt_configure_add_report_entry(
- TYPE WARNING
- MESSAGE "No QPA platform plugin enabled! This will produce a Qt that cannot run GUI applications. See \"Platform backends\" in the output of --help."
- CONDITION QT_FEATURE_gui AND LINUX AND NOT ANDROID AND NOT QT_FEATURE_xcb AND NOT QT_FEATURE_eglfs AND NOT QT_FEATURE_directfb AND NOT QT_FEATURE_linuxfb
-)
-qt_configure_add_report_entry(
- TYPE WARNING
- MESSAGE "On OS X, AAT is supported only with -qt-harfbuzz."
- CONDITION APPLE AND QT_FEATURE_system_harfbuzz
-)
-qt_configure_add_report_entry(
- TYPE ERROR
- MESSAGE "The OpenGL functionality tests failed! You might need to modify the include and library search paths by editing QMAKE_INCDIR_OPENGL[_ES2], QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your platform."
- CONDITION QT_FEATURE_gui AND NOT WATCHOS AND ( NOT INPUT_opengl STREQUAL 'no' ) AND NOT QT_FEATURE_opengl_desktop AND NOT QT_FEATURE_opengles2 AND NOT QT_FEATURE_opengl_dynamic
-)
-qt_configure_add_report_entry(
- TYPE WARNING
- MESSAGE "Accessibility disabled. This configuration of Qt is unsupported."
- CONDITION NOT QT_FEATURE_accessibility
-)
-qt_configure_add_report_entry(
- TYPE ERROR
- MESSAGE "XCB plugin requires xkbcommon and xkbcommon-x11, but -no-xkbcommon was provided."
- CONDITION ( NOT INPUT_xcb STREQUAL '' ) AND ( NOT INPUT_xcb STREQUAL 'no' ) AND INPUT_xkbcommon STREQUAL 'no'
-)
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index 217ee4a4af..5fe4d59d10 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -24,7 +24,7 @@ if (QT_FEATURE_gui)
elseif(QNX)
set(_default_platform "qnx")
elseif(INTEGRITY)
- set(_default_platform "integrityfb")
+ set(_default_platform "eglfs")
elseif(HAIKU)
set(_default_platform "haiku")
elseif(WASM)
@@ -195,6 +195,7 @@ qt_internal_add_module(Gui
painting/qregion.cpp painting/qregion.h
painting/qrgb.h
painting/qrgba64.h painting/qrgba64_p.h
+ painting/qrgbaf.h
painting/qstroker.cpp painting/qstroker_p.h
painting/qtextureglyphcache.cpp painting/qtextureglyphcache_p.h
painting/qtransform.cpp painting/qtransform.h
@@ -279,12 +280,12 @@ qt_internal_add_module(Gui
)
# Resources:
-set_source_files_properties("painting/../../3rdparty/icc/sRGB2014.icc"
+set_source_files_properties("../3rdparty/icc/sRGB2014.icc"
PROPERTIES QT_RESOURCE_ALIAS "sRGB2014.icc"
)
set(qpdf_resource_files
- "../../3rdparty/icc/sRGB2014.icc"
- "qpdfa_metadata.xml"
+ "../3rdparty/icc/sRGB2014.icc"
+ "painting/qpdfa_metadata.xml"
)
qt_internal_add_resource(Gui "qpdf"
@@ -681,7 +682,7 @@ qt_internal_extend_target(Gui CONDITION QT_FEATURE_textmarkdownreader
qt_internal_extend_target(Gui CONDITION QT_FEATURE_system_textmarkdownreader AND QT_FEATURE_textmarkdownreader
LIBRARIES
- libmd4c
+ WrapSystemMd4c::WrapSystemMd4c
)
qt_internal_extend_target(Gui CONDITION QT_FEATURE_textmarkdownreader AND NOT QT_FEATURE_system_textmarkdownreader
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index dc6794ac9c..1ba206e82a 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -448,6 +448,7 @@ Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
\omitvalue ImageInterface \omit For objects that represent an image. This interface is generally less important. \endomit
\value TableInterface For lists, tables and trees.
\value TableCellInterface For cells in a TableInterface object.
+ \value HyperlinkInterface For hyperlink nodes (usually embedded as children of text nodes)
\sa QAccessibleInterface::interface_cast(), QAccessibleTextInterface, QAccessibleValueInterface, QAccessibleActionInterface, QAccessibleTableInterface, QAccessibleTableCellInterface
*/
@@ -2958,6 +2959,44 @@ QString qAccessibleLocalizedActionDescription(const QString &actionName)
return accessibleActionStrings()->localizedDescription(actionName);
}
+/*!
+ \internal
+ \fn QString QAccessibleHyperlinkInterface::anchor() const
+
+ The logical/human readable name of the hyperlink
+*/
+
+/*!
+ \internal
+ \fn QString QAccessibleHyperlinkInterface::anchorTarget() const
+
+ The target url of the hyperlink
+*/
+
+/*!
+ \internal
+ \fn int QAccessibleHyperlinkInterface::startIndex() const
+
+ Returns the start index that will refer to the first character in the text where the hyperlink
+ begins. The index corresponds to the index that the QAccessibleTextInterface needs in order
+ to find the start of the hyperlink.
+
+*/
+
+/*!
+ \internal
+ \fn int QAccessibleHyperlinkInterface::endIndex() const
+
+ Returns the end index that will refer to the first character in the text where the hyperlink
+ begins. The index corresponds to the index that the QAccessibleTextInterface needs in order
+ to find the end of the hyperlink.
+*/
+
+QAccessibleHyperlinkInterface::~QAccessibleHyperlinkInterface()
+{
+
+}
+
#endif // QT_NO_ACCESSIBILITY
QT_END_NAMESPACE
diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h
index 093a48e211..d7bb31706e 100644
--- a/src/gui/accessible/qaccessible.h
+++ b/src/gui/accessible/qaccessible.h
@@ -384,7 +384,8 @@ public:
ActionInterface,
ImageInterface,
TableInterface,
- TableCellInterface
+ TableCellInterface,
+ HyperlinkInterface
};
enum TextBoundaryType {
@@ -451,6 +452,7 @@ class QAccessibleActionInterface;
class QAccessibleImageInterface;
class QAccessibleTableInterface;
class QAccessibleTableCellInterface;
+class QAccessibleHyperlinkInterface;
class QAccessibleTableModelChangeEvent;
class Q_GUI_EXPORT QAccessibleInterface
@@ -508,6 +510,9 @@ public:
inline QAccessibleTableCellInterface *tableCellInterface()
{ return reinterpret_cast<QAccessibleTableCellInterface *>(interface_cast(QAccessible::TableCellInterface)); }
+ inline QAccessibleHyperlinkInterface *hyperlinkInterface()
+ { return reinterpret_cast<QAccessibleHyperlinkInterface *>(interface_cast(QAccessible::HyperlinkInterface)); }
+
virtual void virtual_hook(int id, void *data);
virtual void *interface_cast(QAccessible::InterfaceType)
@@ -659,6 +664,17 @@ public:
virtual QPoint imagePosition() const = 0;
};
+class Q_GUI_EXPORT QAccessibleHyperlinkInterface
+{
+public:
+ virtual ~QAccessibleHyperlinkInterface();
+
+ virtual QString anchor() const = 0;
+ virtual QString anchorTarget() const = 0;
+ virtual int startIndex() const = 0;
+ virtual int endIndex() const = 0;
+ virtual bool isValid() const = 0;
+};
class Q_GUI_EXPORT QAccessibleEvent
{
@@ -715,6 +731,7 @@ protected:
QAccessible::Id m_uniqueId;
};
+ friend class QTestAccessibility;
};
class Q_GUI_EXPORT QAccessibleStateChangeEvent :public QAccessibleEvent
@@ -802,13 +819,13 @@ class Q_GUI_EXPORT QAccessibleTextInsertEvent : public QAccessibleTextCursorEven
{
public:
inline QAccessibleTextInsertEvent(QObject *obj, int position, const QString &text)
- : QAccessibleTextCursorEvent(obj, position + text.length())
+ : QAccessibleTextCursorEvent(obj, position + int(text.length()))
, m_position(position), m_text(text)
{
m_type = QAccessible::TextInserted;
}
inline QAccessibleTextInsertEvent(QAccessibleInterface *iface, int position, const QString &text)
- : QAccessibleTextCursorEvent(iface, position + text.length())
+ : QAccessibleTextCursorEvent(iface, position + int(text.length()))
, m_position(position), m_text(text)
{
m_type = QAccessible::TextInserted;
@@ -862,13 +879,13 @@ class Q_GUI_EXPORT QAccessibleTextUpdateEvent : public QAccessibleTextCursorEven
{
public:
inline QAccessibleTextUpdateEvent(QObject *obj, int position, const QString &oldText, const QString &text)
- : QAccessibleTextCursorEvent(obj, position + text.length())
+ : QAccessibleTextCursorEvent(obj, position + int(text.length()))
, m_position(position), m_oldText(oldText), m_text(text)
{
m_type = QAccessible::TextUpdated;
}
inline QAccessibleTextUpdateEvent(QAccessibleInterface *iface, int position, const QString &oldText, const QString &text)
- : QAccessibleTextCursorEvent(iface, position + text.length())
+ : QAccessibleTextCursorEvent(iface, position + int(text.length()))
, m_position(position), m_oldText(oldText), m_text(text)
{
m_type = QAccessible::TextUpdated;
diff --git a/src/gui/configure.cmake b/src/gui/configure.cmake
index cb6b0a5cc2..20c5b9624b 100644
--- a/src/gui/configure.cmake
+++ b/src/gui/configure.cmake
@@ -41,6 +41,7 @@ qt_find_package(gbm PROVIDED_TARGETS gbm::gbm MODULE_NAME gui QMAKE_LIB gbm)
qt_find_package(WrapSystemHarfbuzz 2.6.0 PROVIDED_TARGETS WrapSystemHarfbuzz::WrapSystemHarfbuzz MODULE_NAME gui QMAKE_LIB harfbuzz)
qt_find_package(Libinput PROVIDED_TARGETS Libinput::Libinput MODULE_NAME gui QMAKE_LIB libinput)
qt_find_package(JPEG PROVIDED_TARGETS JPEG::JPEG MODULE_NAME gui QMAKE_LIB libjpeg)
+qt_find_package(WrapSystemMd4c PROVIDED_TARGETS WrapSystemMd4c::WrapSystemMd4c MODULE_NAME gui QMAKE_LIB libmd4c)
qt_find_package(WrapSystemPNG PROVIDED_TARGETS WrapSystemPNG::WrapSystemPNG MODULE_NAME gui QMAKE_LIB libpng)
if(QT_FEATURE_system_zlib)
qt_add_qmake_lib_dependency(libpng zlib)
@@ -750,7 +751,7 @@ qt_feature("vkgen" PRIVATE
)
qt_feature("vulkan" PUBLIC
LABEL "Vulkan"
- CONDITION QT_FEATURE_vkgen AND Vulkan_FOUND
+ CONDITION QT_FEATURE_library AND QT_FEATURE_vkgen AND Vulkan_FOUND
)
qt_feature("vkkhrdisplay" PRIVATE
SECTION "Platform plugins"
@@ -945,7 +946,7 @@ qt_feature("textmarkdownreader" PUBLIC
qt_feature("system-textmarkdownreader" PUBLIC
SECTION "Kernel"
LABEL " Using system libmd4c"
- CONDITION libs.libmd4c OR FIXME
+ CONDITION QT_FEATURE_textmarkdownreader AND WrapSystemMd4c_FOUND
ENABLE INPUT_libmd4c STREQUAL 'system'
DISABLE INPUT_libmd4c STREQUAL 'qt'
)
@@ -1154,6 +1155,11 @@ qt_feature("raster-64bit" PRIVATE
LABEL "QPainter - 64 bit raster"
PURPOSE "Internal painting support for 64 bit (16 bpc) rasterization."
)
+qt_feature("raster-fp" PRIVATE
+ SECTION "Painting"
+ LABEL "QPainter - floating point raster"
+ PURPOSE "Internal painting support for floating point rasterization."
+)
qt_feature("undocommand" PUBLIC
SECTION "Utilities"
LABEL "QUndoCommand"
diff --git a/src/gui/configure.json b/src/gui/configure.json
deleted file mode 100644
index ad53dca292..0000000000
--- a/src/gui/configure.json
+++ /dev/null
@@ -1,1841 +0,0 @@
-{
- "module": "gui",
- "depends": [
- "core-private",
- "network"
- ],
- "testDir": "../../config.tests",
-
- "commandline": {
- "options": {
- "accessibility": "boolean",
- "direct2d": "boolean",
- "directfb": "boolean",
- "directwrite": "boolean",
- "egl": "boolean",
- "eglfs": "boolean",
- "evdev": "boolean",
- "fontconfig": "boolean",
- "freetype": { "type": "enum", "values": [ "no", "qt", "system" ] },
- "gbm": "boolean",
- "gif": "boolean",
- "harfbuzz": { "type": "enum", "values": [ "no", "qt", "system" ] },
- "ico": "boolean",
- "imf": { "type": "boolean", "name": "qqnx_imf" },
- "kms": "boolean",
- "lgmon": "boolean",
- "libinput": "boolean",
- "libjpeg": { "type": "enum", "values": [ "no", "qt", "system" ] },
- "libmd4c": { "type": "enum", "values": [ "no", "qt", "system" ] },
- "libpng": { "type": "enum", "values": [ "no", "qt", "system" ] },
- "linuxfb": "boolean",
- "mtdev": "boolean",
- "opengl": { "type": "optionalString", "values": [ "no", "yes", "desktop", "es2", "dynamic" ] },
- "opengl-es-2": { "type": "void", "name": "opengl", "value": "es2" },
- "opengles3": "boolean",
- "openvg": "boolean",
- "qpa": { "type": "string", "name": "qpa_default_platform" },
- "sm": { "type": "boolean", "name": "sessionmanager" },
- "tslib": "boolean",
- "vulkan": "boolean",
- "xcb": "boolean",
- "bundled-xcb-xinput": "boolean",
- "xcb-native-painting": "boolean",
- "xcb-xlib": "boolean",
- "xkbcommon": "boolean"
- }
- },
-
- "libraries": {
- "atspi": {
- "label": "atspi",
- "sources": [
- { "type": "pkgConfig", "args": "atspi-2" }
- ]
- },
- "bcm_host": {
- "export": "",
- "headers": ["bcm_host.h"],
- "sources": [
- { "type": "pkgConfig", "args": "bcm_host" },
- { "type": "makeSpec", "spec": "BCM_HOST" }
- ]
- },
- "d2d1": {
- "label": "Direct2D 1",
- "headers": [ "d2d1.h", "d2d1helper.h" ],
- "sources": [
- "-ld2d1"
- ]
- },
- "d2d1_1": {
- "label": "Direct2D 1.1",
- "test": {
- "main": [
- "ID2D1Factory1 *d2dFactory;",
- "D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &d2dFactory);"
- ]
- },
- "headers": [ "d2d1_1.h", "d2d1_1helper.h" ],
- "sources": [
- "-ld2d1"
- ]
- },
- "directfb": {
- "label": "DirectFB",
- "test": {
- "tail": [
- "#ifdef __typeof__",
- "# error DirectFB headers are unclean and cannot compile",
- "#endif"
- ]
- },
- "headers": "directfb.h",
- "sources": [
- { "type": "pkgConfig", "args": "directfb" }
- ]
- },
- "dwrite_2": {
- "label": "DirectWrite 2",
- "test": {
- "main": [
- "IUnknown *factory = 0;",
- "(void)(size_t(DWRITE_E_NOCOLOR) + sizeof(IDWriteFontFace2));",
- "DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory2),",
- " &factory);"
- ]
- },
- "headers": "dwrite_2.h",
- "sources": [
- "-ldwrite"
- ]
- },
- "dwrite_3": {
- "label": "DirectWrite 3",
- "test": {
- "main": [
- "IUnknown *factory = 0;",
- "DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory3),",
- " &factory);"
- ]
- },
- "headers": "dwrite_3.h",
- "sources": [
- "-ldwrite"
- ]
- },
- "drm": {
- "label": "KMS",
- "test": {
- "head": [
- "#include <stdlib.h>",
- "#include <stdint.h>",
- "extern \"C\" {"
- ],
- "tail": [
- "}"
- ],
- "main": "(void) drmModeGetCrtc(0, 0);"
- },
- "headers": [ "xf86drmMode.h", "xf86drm.h" ],
- "sources": [
- { "type": "pkgConfig", "args": "libdrm" },
- { "libs": "-ldrm", "condition": "!config.integrity" },
- { "libs": "-ldrm-nvdc -lposix -livfs -lnvll -lnvdc -lnvrm -lnvrm_graphics -lnvos -lnvtegrahv", "condition": "config.integrity" }
- ]
- },
- "egl": {
- "label": "EGL",
- "test": {
- "main": [
- "EGLint x = 0; EGLDisplay dpy = 0; EGLContext ctx = 0;",
- "eglDestroyContext(dpy, ctx);"
- ]
- },
- "headers": "EGL/egl.h",
- "sources": [
- { "type": "pkgConfig", "args": "egl" },
- { "type": "makeSpec", "spec": "EGL" }
- ]
- },
- "freetype": {
- "label": "FreeType",
- "test": {
- "tail": [
- "#include FT_FREETYPE_H",
- "#if ((FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) < 20200)",
- "# error This version of freetype is too old.",
- "#endif"
- ],
- "main": [
- "FT_Face face = 0;"
- ]
- },
- "headers": "ft2build.h",
- "sources": [
- { "type": "pkgConfig", "args": "freetype2" },
- { "type": "freetype", "libs": "-lfreetype", "condition": "!config.wasm" },
- { "libs": "-s USE_FREETYPE=1", "condition": "config.wasm" },
- { "libs": "-lfreetype" }
- ],
- "use": [
- { "lib": "zlib", "condition": "features.system-zlib" }
- ]
- },
- "fontconfig": {
- "label": "Fontconfig",
- "test": {
- "tail": [
- "#ifndef FC_RGBA_UNKNOWN",
- "# error This version of fontconfig is too old, it is missing the FC_RGBA_UNKNOWN define",
- "#endif"
- ],
- "main": [
- "FcPattern *pattern = 0;"
- ]
- },
- "headers": "fontconfig/fontconfig.h",
- "sources": [
- { "type": "pkgConfig", "args": "fontconfig" },
- { "type": "freetype", "libs": "-lfontconfig" }
- ],
- "use": "freetype"
- },
- "gbm": {
- "label": "GBM",
- "test": {
- "head": [
- "#include <stdlib.h>",
- "#include <stdint.h>",
- "extern \"C\" {"
- ],
- "tail": [
- "}"
- ],
- "main": "gbm_surface *surface = 0;"
- },
- "headers": "gbm.h",
- "sources": [
- { "type": "pkgConfig", "args": "gbm" }
- ]
- },
- "harfbuzz": {
- "label": "HarfBuzz",
- "test": {
- "tail": [
- "#if !HB_VERSION_ATLEAST(2, 6, 0)",
- "# error This version of harfbuzz is too old.",
- "#endif"
- ],
- "main": [
- "hb_buffer_t *buffer = hb_buffer_create();",
- "const uint16_t string[] = { 'A', 'b', 'c' };",
- "hb_buffer_add_utf16(buffer, string, 3, 0, 3);",
- "hb_buffer_guess_segment_properties(buffer);",
- "hb_buffer_set_flags(buffer, hb_buffer_flags_t(HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES));",
- "hb_buffer_destroy(buffer);"
- ]
- },
- "headers": "hb.h",
- "sources": [
- "-lharfbuzz"
- ]
- },
- "imf": {
- "label": "IMF",
- "export": "",
- "test": {
- "main": "imf_client_init();"
- },
- "headers": "imf/imf_client.h",
- "sources": [
- "-linput_client"
- ]
- },
- "lgmon": {
- "label": "lgmon",
- "test": {
- "main": "lgmon_supported(getpid());"
- },
- "headers": "lgmon.h",
- "sources": [
- "-llgmon"
- ]
- },
- "libinput": {
- "label": "libinput",
- "test": {
- "main": "libinput_udev_create_context(NULL, NULL, NULL);"
- },
- "headers": "libinput.h",
- "sources": [
- { "type": "pkgConfig", "args": "libinput" }
- ]
- },
- "integrityhid": {
- "label": "integrityhid",
- "test": {
- "head": [
- "#include <stdlib.h>",
- "#include <stdint.h>"
- ],
- "main": [
- "HIDDriver *driver;",
- "uintptr_t devicecontext;",
- "uint32_t device_id;",
- "gh_hid_enum_devices(driver, &device_id, &devicecontext);"
- ]
- },
- "headers": "device/hiddriver.h",
- "sources": [
- { "libs": "-lhiddev -lusbhid -lusb" }
- ]
- },
- "libjpeg": {
- "label": "libjpeg",
- "test": {
- "head": [
- "#include <sys/types.h>",
- "#include <stdio.h>",
- "extern \"C\" {"
- ],
- "tail": [
- "}",
- "",
- "j_compress_ptr cinfo;"
- ],
- "main": "jpeg_create_compress(cinfo);"
- },
- "headers": "jpeglib.h",
- "sources": [
- { "type": "pkgConfig", "args": "libjpeg" },
- { "libs": "-llibjpeg", "condition": "config.msvc" },
- "-ljpeg"
- ]
- },
- "libmd4c": {
- "label": "libmd4c",
- "test": {
- "main": "md_parse(\"hello\", 5, nullptr, nullptr);"
- },
- "headers": "md4c.h",
- "sources": [
- { "type": "pkgConfig", "args": "md4c" },
- { "libs": "-lmd4c" }
- ]
- },
- "libpng": {
- "label": "libpng",
- "test": {
- "main": "(void) png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);"
- },
- "headers": "png.h",
- "sources": [
- { "type": "pkgConfig", "args": "libpng" },
- { "libs": "-llibpng16", "condition": "config.msvc" },
- { "libs": "-llibpng", "condition": "config.msvc" },
- { "libs": "-lpng16", "condition": "!config.msvc" },
- { "libs": "-lpng", "condition": "!config.msvc" },
- { "libs": "-s USE_LIBPNG=1", "condition": "config.wasm" }
- ],
- "use": [
- { "lib": "zlib", "condition": "features.system-zlib" }
- ]
- },
- "mtdev": {
- "label": "mtdev",
- "test": {
- "main": [
- "mtdev m;",
- "mtdev_open(&m, 0);"
- ]
- },
- "headers": "mtdev.h",
- "sources": [
- { "type": "pkgConfig", "args": "mtdev" }
- ]
- },
- "opengl": {
- "label": "Desktop OpenGL",
- "test": {
- "head": [
- "#ifdef __APPLE__",
- "# include <OpenGL/gl.h>",
- "#else",
- "# define GL_GLEXT_PROTOTYPES",
- "# include <GL/gl.h>",
- "#endif"
- ],
- "main": [
- "glBegin(GL_TRIANGLES);",
- " glVertex2f(20.0f, 10.0f);",
- " glVertex2f(10.0f, 30.0f);",
- " glVertex2f(20.0f, 50.0f);",
- "glEnd();"
- ]
- },
- "sources": [
- { "type": "pkgConfig", "args": "gl", "condition": "!config.darwin" },
- { "type": "makeSpec", "spec": "OPENGL" }
- ]
- },
- "opengl_es2": {
- "label": "OpenGL ES 2.0",
- "test": {
- "head": [
- "#ifdef __APPLE__",
- "# include <OpenGLES/ES2/gl.h>",
- "#else",
- "# define GL_GLEXT_PROTOTYPES",
- "# include <GLES2/gl2.h>",
- "#endif"
- ],
- "main": [
- "glUniform1f(1, GLfloat(1.0));",
- "glClear(GL_COLOR_BUFFER_BIT);"
- ]
- },
- "sources": [
- { "type": "pkgConfig", "args": "glesv2", "condition": "!config.darwin" },
- { "type": "makeSpec", "spec": "OPENGL_ES2" }
- ]
- },
- "openvg": {
- "label": "OpenVG",
- "test": {
- "main": "VGint i = 2; vgFlush();"
- },
- "headers": "VG/openvg.h",
- "sources": [
- { "type": "pkgConfig", "args": "vg" },
- { "type": "makeSpec", "spec": "OPENVG" }
- ]
- },
- "tslib": {
- "label": "tslib",
- "test": {
- "main": "ts_setup(nullptr, 0);"
- },
- "headers": "tslib.h",
- "sources": [
- "-lts"
- ]
- },
- "v4l2": {
- "label": "V4L2",
- "test": {
- "head": [
- "#include <cstddef>",
- "extern \"C\" {"
- ],
- "tail": [
- "}"
- ],
- "main": [
- "v4l2_format fmt;",
- "media_pad *pad = nullptr;",
- "media_device *device = media_device_new(\"/dev/media\");",
- "v4l2_subdev_set_format(nullptr, nullptr, 0, V4L2_SUBDEV_FORMAT_ACTIVE);"
- ]
- },
- "headers": [ "mediactl/mediactl.h", "mediactl/v4l2subdev.h" ],
- "sources": [
- { "type": "pkgConfig", "args": "libv4l2 libmediactl" },
- "-lmediactl -lv4l2 -lv4l2subdev"
- ]
- },
- "vulkan": {
- "label": "Vulkan",
- "test": {
- "comment": "Note: Qt does not rely on linking to a Vulkan library directly.",
- "tail": [
- "// The pData parameter has changed from uint32_t* to void* at some point.",
- "// Ensure the headers have the updated one to prevent compile errors later on.",
- "PFN_vkCmdUpdateBuffer cmdUpdBuf;",
- "void testUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData)",
- "{",
- " cmdUpdBuf(commandBuffer, dstBuffer, dstOffset, dataSize, pData);",
- "}"
- ],
- "main": [
- "VkInstanceCreateInfo info;",
- "testUpdateBuffer(0, 0, 0, 0, 0);"
- ]
- },
- "headers": "vulkan/vulkan.h",
- "sources": [
- { "type": "pkgConfig", "args": "vulkan" },
- { "type": "makeSpec", "spec": "VULKAN" }
- ]
- },
- "wayland_server": {
- "label": "Wayland Server",
- "test": {
- "main": "wl_display_create();"
- },
- "headers": "wayland-server.h",
- "sources": [
- { "type": "pkgConfig", "args": "wayland-server" }
- ]
- },
- "xlib": {
- "label": "XLib",
- "test": {
- "main": [
- "Display *d = XOpenDisplay(NULL);",
- "XCloseDisplay(d);"
- ]
- },
- "headers": "X11/Xlib.h",
- "sources": [
- { "type": "makeSpec", "spec": "X11" }
- ]
- },
- "x11sm": {
- "label": "X11 session management",
- "sources": [
- { "type": "pkgConfig", "args": "sm ice" }
- ]
- },
- "xcb": {
- "label": "XCB >= 1.11",
- "test": {
- "main": [
- "int primaryScreen = 0;",
- "(void)xcb_connect(\"\", &primaryScreen);",
- "/* XCB_PACKED define was added in libxcb 1.11 */",
- "#ifdef XCB_PACKED",
- " return 0;",
- "#else",
- " return -1;",
- "#endif"
- ]
- },
- "headers": "xcb/xcb.h",
- "sources": [
- { "type": "pkgConfig", "args": "xcb >= 1.11" },
- "-lxcb"
- ]
- },
- "xcb_icccm": {
- "label": "XCB ICCCM >= 0.3.9",
- "headers": "xcb/xcb_icccm.h",
- "sources": [
- { "type": "pkgConfig", "args": "xcb-icccm >= 0.3.9" },
- "-lxcb-icccm"
- ],
- "use": "xcb"
- },
- "xcb_image": {
- "label": "XCB Image >= 0.3.9",
- "headers": "xcb/xcb_image.h",
- "sources": [
- { "type": "pkgConfig", "args": "xcb-image >= 0.3.9" },
- "-lxcb-image"
- ],
- "use": "xcb_shm xcb"
- },
- "xcb_keysyms": {
- "label": "XCB Keysyms >= 0.3.9",
- "headers": "xcb/xcb_keysyms.h",
- "sources": [
- { "type": "pkgConfig", "args": "xcb-keysyms >= 0.3.9" },
- "-lxcb-keysyms"
- ],
- "use": "xcb"
- },
- "xcb_renderutil": {
- "label": "XCB Renderutil >= 0.3.9",
- "headers": "xcb/xcb_renderutil.h",
- "sources": [
- { "type": "pkgConfig", "args": "xcb-renderutil >= 0.3.9" },
- "-lxcb-render-util"
- ],
- "use": "xcb xcb_render"
- },
- "xcb_randr": {
- "label": "XCB RandR",
- "headers": "xcb/randr.h",
- "sources": [
- { "type": "pkgConfig", "args": "xcb-randr" },
- "-lxcb-randr"
- ],
- "use": "xcb"
- },
- "xcb_shape": {
- "label": "XCB Shape",
- "headers": "xcb/shape.h",
- "sources": [
- { "type": "pkgConfig", "args": "xcb-shape" },
- "-lxcb-shape"
- ],
- "use": "xcb"
- },
- "xcb_shm": {
- "label": "XCB SHM",
- "headers": "xcb/shm.h",
- "sources": [
- { "type": "pkgConfig", "args": "xcb-shm" },
- "-lxcb-shm"
- ],
- "use": "xcb"
- },
- "xcb_sync": {
- "label": "XCB Sync",
- "headers": "xcb/sync.h",
- "sources": [
- { "type": "pkgConfig", "args": "xcb-sync" },
- "-lxcb-sync"
- ],
- "use": "xcb"
- },
- "xcb_xfixes": {
- "label": "XCB Xfixes",
- "headers": "xcb/xfixes.h",
- "sources": [
- { "type": "pkgConfig", "args": "xcb-xfixes" },
- "-lxcb-xfixes"
- ],
- "use": "xcb"
- },
- "xcb_xlib": {
- "label": "XCB Xlib",
- "test": {
- "main": "(void) XGetXCBConnection((Display *)0);"
- },
- "headers": "X11/Xlib-xcb.h",
- "sources": [
- { "type": "pkgConfig", "args": "x11-xcb" },
- "-lX11-xcb"
- ],
- "use": "xcb xlib"
- },
- "xcb_xkb": {
- "label": "XCB XKB",
- "headers": "xcb/xkb.h",
- "sources": [
- { "type": "pkgConfig", "args": "xcb-xkb" },
- "-lxcb-xkb"
- ],
- "use": "xcb"
- },
- "xcb_render": {
- "label": "XCB XRender",
- "headers": "xcb/render.h",
- "sources": [
- { "type": "pkgConfig", "args": "xcb-render" },
- "-lxcb-render"
- ],
- "use": "xcb"
- },
- "xcb_glx": {
- "label": "XCB GLX",
- "test": {
- "main": [
- "xcb_connection_t *connection = 0;",
- "xcb_generic_error_t *error = 0;",
- "xcb_glx_query_version_cookie_t xglx_query_cookie = xcb_glx_query_version(",
- " connection, XCB_GLX_MAJOR_VERSION, XCB_GLX_MINOR_VERSION);",
- "xcb_glx_query_version_reply(connection, xglx_query_cookie, &error);"
- ]
- },
- "headers": "xcb/glx.h",
- "sources": [
- { "type": "pkgConfig", "args": "xcb-glx" },
- "-lxcb-glx"
- ],
- "use": "xcb"
- },
- "xcb_xinput": {
- "label": "XCB XInput",
- "test": {
- "main": [
- "xcb_connection_t *connection = 0;",
- "xcb_generic_error_t *error = 0;",
- "xcb_input_xi_query_version_cookie_t xinput_query_cookie = xcb_input_xi_query_version(",
- " connection, XCB_INPUT_MAJOR_VERSION, XCB_INPUT_MINOR_VERSION);",
- "xcb_input_xi_query_version_reply(connection, xinput_query_cookie, &error);"
- ]
- },
- "headers": "xcb/xinput.h",
- "sources": [
- { "type": "pkgConfig", "args": "xcb-xinput >= 1.12" },
- "-lxcb-xinput"
- ],
- "use": "xcb"
- },
- "xkbcommon": {
- "label": "xkbcommon >= 0.5.0",
- "test": {
- "main": "xkb_context_new(XKB_CONTEXT_NO_FLAGS);"
- },
- "headers": [ "xkbcommon/xkbcommon.h" ],
- "sources": [
- { "type": "pkgConfig", "args": "xkbcommon >= 0.5.0" },
- "-lxkbcommon"
- ]
- },
- "xkbcommon_x11": {
- "label": "xkbcommon-x11",
- "test": {
- "main": "xkb_x11_setup_xkb_extension_flags flag = XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS;"
- },
- "headers": [ "xkbcommon/xkbcommon-x11.h" ],
- "sources": [
- { "type": "pkgConfig", "args": "xkbcommon-x11" },
- "-lxkbcommon -lxkbcommon-x11"
- ]
- },
- "xrender": {
- "label": "XRender for native painting",
- "test": {
- "tail": [
- "#if RENDER_MAJOR == 0 && RENDER_MINOR < 5",
- "# error Required Xrender version 0.6 not found.",
- "#endif"
- ],
- "main": "XRenderPictFormat *format = 0;"
- },
- "headers": "X11/extensions/Xrender.h",
- "sources": [
- "-lXrender"
- ],
- "use": "xlib"
- }
- },
-
- "tests": {
- "drm_atomic": {
- "label": "DRM Atomic API",
- "type": "compile",
- "test": {
- "head": [
- "#include <stdlib.h>",
- "#include <stdint.h>",
- "extern \"C\" {"
- ],
- "include": [
- "xf86drmMode.h",
- "xf86drm.h"
- ],
- "tail": [
- "}"
- ],
- "main": "drmModeAtomicReq *request;"
- },
- "use": "drm"
- },
- "egl-x11": {
- "label": "EGL on X11",
- "type": "compile",
- "test": {
- "head": [
- "// Check if EGL is compatible with X. Some EGL implementations, typically on",
- "// embedded devices, are not intended to be used together with X. EGL support",
- "// has to be disabled in plugins like xcb in this case since the native display,",
- "// window and pixmap types will be different than what an X-based platform",
- "// plugin would expect."
- ],
- "include": [ "EGL/egl.h", "X11/Xlib.h" ],
- "main": [
- "Display *dpy = EGL_DEFAULT_DISPLAY;",
- "EGLNativeDisplayType egldpy = XOpenDisplay(\"\");",
- "dpy = egldpy;",
- "EGLNativeWindowType w = XCreateWindow(dpy, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);",
- "XDestroyWindow(dpy, w);",
- "XCloseDisplay(dpy);"
- ]
- },
- "use": "egl xlib"
- },
- "egl-brcm": {
- "label": "Broadcom EGL (Raspberry Pi)",
- "type": "compile",
- "test": {
- "include": [ "EGL/egl.h", "bcm_host.h" ],
- "main": "vc_dispmanx_display_open(0);"
- },
- "use": "egl bcm_host"
- },
- "egl-egldevice": {
- "label": "EGLDevice",
- "type": "compile",
- "test": {
- "include": [ "EGL/egl.h", "EGL/eglext.h" ],
- "main": [
- "EGLDeviceEXT device = 0;",
- "EGLStreamKHR stream = 0;",
- "EGLOutputLayerEXT layer = 0;",
- "(void) EGL_DRM_CRTC_EXT;"
- ]
- },
- "use": "egl"
- },
- "egl-mali": {
- "label": "Mali EGL",
- "type": "compile",
- "test": {
- "include": [ "EGL/fbdev_window.h", "EGL/egl.h", "GLES2/gl2.h" ],
- "main": "fbdev_window *w = 0;"
- },
- "use": "egl"
- },
- "egl-mali-2": {
- "label": "Mali 2 EGL",
- "type": "compile",
- "test": {
- "include": [ "EGL/egl.h", "GLES2/gl2.h" ],
- "main": "mali_native_window *w = 0;"
- },
- "use": "egl"
- },
- "egl-viv": {
- "label": "i.Mx6 EGL",
- "type": "compile",
- "test": {
- "include": [ "EGL/egl.h", "EGL/eglvivante.h" ],
- "main": [
- "#ifdef __INTEGRITY",
- "fbGetDisplay();",
- "#else",
- "// Do not rely on fbGetDisplay(), since the signature has changed over time.",
- "// Stick to fbGetDisplayByIndex().",
- "fbGetDisplayByIndex(0);",
- "#endif"
- ],
- "qmake": [
- "DEFINES += EGL_API_FB=1",
- "!integrity: DEFINES += LINUX=1"
- ]
- },
- "use": "egl"
- },
- "egl-openwfd": {
- "label": "OpenWFD EGL",
- "type": "compile",
- "test": {
- "include": [ "wfd.h" ],
- "main": [
- "wfdEnumerateDevices(nullptr, 0, nullptr);"
- ]
- },
- "use": "egl"
- },
- "egl-rcar": {
- "label": "RCAR EGL",
- "type": "compile",
- "test": {
- "include": [ "EGL/egl.h" ],
- "tail": [
- "extern \"C\" {",
- "extern unsigned long PVRGrfxServerInit(void);",
- "}"
- ],
- "main": [
- "PVRGrfxServerInit();"
- ]
- },
- "use": "egl opengl_es2"
- },
- "evdev": {
- "label": "evdev",
- "type": "compile",
- "test": {
- "head": [
- "#if defined(__FreeBSD__)",
- "# include <dev/evdev/input.h>",
- "#else",
- "# include <linux/input.h>",
- "# include <linux/kd.h>",
- "#endif",
- "enum {",
- " e1 = ABS_PRESSURE,",
- " e2 = ABS_X,",
- " e3 = REL_X,",
- " e4 = SYN_REPORT,",
- "};"
- ],
- "main": [
- "input_event buf[32];",
- "(void) buf;"
- ]
- }
- },
- "integrityfb": {
- "label": "INTEGRITY framebuffer",
- "type": "compile",
- "test": {
- "include": "device/fbdriver.h",
- "main": "FBDriver *driver = 0;"
- }
- },
- "libinput_axis_api": {
- "label": "axis API in libinput",
- "type": "compile",
- "test": {
- "include": "libinput.h",
- "main": "libinput_event_pointer_has_axis(nullptr, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);"
- },
- "use": "libinput"
- },
- "linuxfb": {
- "label": "LinuxFB",
- "type": "compile",
- "test": {
- "include": [ "linux/fb.h", "sys/kd.h", "sys/ioctl.h" ],
- "main": [
- "fb_fix_screeninfo finfo;",
- "fb_var_screeninfo vinfo;",
- "int fd = 3;",
- "ioctl(fd, FBIOGET_FSCREENINFO, &finfo);",
- "ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);"
- ]
- }
- },
- "opengles3": {
- "label": "OpenGL ES 3.0",
- "type": "compile",
- "test": {
- "head": [
- "#ifdef __APPLE__",
- "# include <OpenGLES/ES3/gl.h>",
- "#else",
- "# define GL_GLEXT_PROTOTYPES",
- "# include <GLES3/gl3.h>",
- "#endif"
- ],
- "main": [
- "static GLfloat f[6];",
- "glGetStringi(GL_EXTENSIONS, 0);",
- "glReadBuffer(GL_COLOR_ATTACHMENT1);",
- "glUniformMatrix2x3fv(0, 0, GL_FALSE, f);",
- "glMapBufferRange(GL_ARRAY_BUFFER, 0, 0, GL_MAP_READ_BIT);"
- ]
- },
- "comment": [
- "The library is expected to be the same as in ES 2.0 (libGLESv2).",
- "The difference is the header and the presence of the functions in",
- "the library."
- ],
- "use": "opengl_es2"
- },
- "opengles31": {
- "label": "OpenGL ES 3.1",
- "type": "compile",
- "test": {
- "include": "GLES3/gl31.h",
- "main": [
- "glDispatchCompute(1, 1, 1);",
- "glProgramUniform1i(0, 0, 0);"
- ]
- },
- "use": "opengl_es2"
- },
- "opengles32": {
- "label": "OpenGL ES 3.2",
- "type": "compile",
- "test": {
- "include": "GLES3/gl32.h",
- "main": "glFramebufferTexture(GL_TEXTURE_2D, GL_DEPTH_STENCIL_ATTACHMENT, 1, 0);"
- },
- "use": "opengl_es2"
- },
- "qpa_default_platform": {
- "label": "default QPA platform",
- "type": "qpaDefaultPlatform",
- "log": "value"
- },
- "xcb_syslibs": {
- "label": "XCB (extensions)",
- "type": "compile",
- "test": {
- "head": [
- "// xkb.h is using a variable called 'explicit', which is a reserved keyword in C++",
- "#define explicit dont_use_cxx_explicit"
- ],
- "tail": "#undef explicit",
- "include": [
- "xcb/xcb.h",
- "xcb/xcb_image.h",
- "xcb/xcb_keysyms.h",
- "xcb/randr.h",
- "xcb/render.h",
- "xcb/shape.h",
- "xcb/shm.h",
- "xcb/sync.h",
- "xcb/xfixes.h",
- "xcb/xcb_icccm.h",
- "xcb/xcb_renderutil.h",
- "xcb/xkb.h"
- ],
- "main": [
- "int primaryScreen = 0;",
- "xcb_connection_t *c = xcb_connect(\"\", &primaryScreen);",
-
- "/* RENDER */",
- "xcb_generic_error_t *error = nullptr;",
- "xcb_render_query_pict_formats_cookie_t formatsCookie =",
- " xcb_render_query_pict_formats(c);",
- "xcb_render_query_pict_formats_reply_t *formatsReply =",
- " xcb_render_query_pict_formats_reply(c, formatsCookie, &error);",
-
- "/* RENDERUTIL: xcb_renderutil.h include won't compile unless version >= 0.3.9 */",
- "xcb_render_util_find_standard_format(nullptr, XCB_PICT_STANDARD_ARGB_32);",
-
- "/* XKB: This takes more arguments in xcb-xkb < 1.11 */",
- "xcb_xkb_get_kbd_by_name_replies_key_names_value_list_sizeof(nullptr, 0, 0, 0, 0, 0, 0, 0, 0);"
- ]
- },
- "use": "xcb_icccm xcb_image xcb_keysyms xcb_randr xcb_render xcb_renderutil xcb_shape xcb_shm xcb_sync xcb_xfixes xcb_xkb xcb"
- },
- "x11prefix": {
- "label": "X11 prefix",
- "type": "getPkgConfigVariable",
- "pkg-config-args": "x11",
- "pkg-config-variable": "prefix",
- "value": "/usr",
- "log": "value"
- }
- },
-
- "features": {
- "accessibility-atspi-bridge": {
- "label": "ATSPI Bridge",
- "condition": "features.accessibility && features.xcb && features.dbus && libs.atspi",
- "output": [ "privateFeature", "feature" ]
- },
- "directfb": {
- "label": "DirectFB",
- "section": "Platform plugins",
- "autoDetect": false,
- "condition": "libs.directfb",
- "output": [ "privateFeature" ]
- },
- "directwrite": {
- "label": "DirectWrite",
- "emitIf": "config.win32",
- "condition": "libs.dwrite_2",
- "output": [ "privateFeature" ]
- },
- "directwrite3": {
- "label": "DirectWrite 3",
- "emitIf": "config.win32",
- "condition": "features.directwrite && libs.dwrite_3",
- "output": [ "privateFeature" ]
- },
- "direct2d": {
- "label": "Direct 2D",
- "condition": "config.win32 && libs.d2d1",
- "output": [ "privateFeature" ]
- },
- "direct2d1_1": {
- "label": "Direct 2D 1.1",
- "condition": "features.direct2d && libs.d2d1_1",
- "output": [ "privateFeature" ]
- },
- "evdev": {
- "label": "evdev",
- "condition": "features.thread && tests.evdev",
- "output": [ "privateFeature" ]
- },
- "freetype": {
- "label": "FreeType",
- "purpose": "Supports the FreeType 2 font engine (and its supported font formats).",
- "section": "Fonts",
- "output": [ "privateFeature", "feature" ]
- },
- "system-freetype": {
- "label": " Using system FreeType",
- "enable": "input.freetype == 'system'",
- "disable": "input.freetype == 'qt'",
- "autoDetect": "!config.msvc",
- "condition": "features.freetype && libs.freetype",
- "output": [ "privateFeature" ]
- },
- "fontconfig": {
- "label": "Fontconfig",
- "autoDetect": "!config.darwin",
- "condition": "!config.win32 && features.system-freetype && libs.fontconfig",
- "output": [ "privateFeature", "feature" ]
- },
- "gbm": {
- "label": "GBM",
- "condition": "libs.gbm",
- "output": [ "publicQtConfig" ]
- },
- "harfbuzz": {
- "label": "HarfBuzz",
- "output": [ "privateFeature", "feature" ]
- },
- "system-harfbuzz": {
- "label": " Using system HarfBuzz",
- "enable": "input.harfbuzz == 'system'",
- "disable": "input.harfbuzz == 'qt'",
- "autoDetect": "!config.darwin && !config.win32",
- "condition": "features.harfbuzz && libs.harfbuzz",
- "output": [ "privateFeature" ]
- },
- "qqnx_imf": {
- "label": "IMF",
- "emitIf": "config.qnx",
- "condition": "libs.imf",
- "output": [ "privateFeature" ]
- },
- "integrityfb": {
- "label": "INTEGRITY framebuffer",
- "section": "Platform plugins",
- "condition": "config.integrity && tests.integrityfb",
- "output": [ "privateFeature" ]
- },
- "kms": {
- "label": "KMS",
- "condition": "libs.drm",
- "output": [ "publicQtConfig", "privateFeature" ]
- },
- "drm_atomic": {
- "label": "DRM Atomic API",
- "condition": "libs.drm && tests.drm_atomic",
- "output": [ "privateFeature" ]
- },
- "libinput": {
- "label": "libinput",
- "condition": "features.libudev && libs.libinput",
- "output": [ "privateFeature" ]
- },
- "integrityhid": {
- "label": "INTEGRITY HID",
- "condition": "config.integrity && libs.integrityhid",
- "output": [ "privateFeature" ]
- },
- "libinput-axis-api": {
- "label": "axis API in libinput",
- "condition": "features.libinput && tests.libinput_axis_api",
- "output": [ "privateFeature" ]
- },
- "lgmon": {
- "label": "lgmon",
- "emitIf": "config.qnx",
- "condition": "libs.lgmon",
- "output": [ "privateConfig" ]
- },
- "linuxfb": {
- "label": "LinuxFB",
- "section": "Platform plugins",
- "condition": "tests.linuxfb && features.regularexpression",
- "output": [ "privateFeature" ]
- },
- "vsp2": {
- "label": "VSP2",
- "condition": "libs.v4l2",
- "autoDetect": false,
- "output": [ "privateFeature" ]
- },
- "vnc": {
- "label": "VNC",
- "section": "Platform plugins",
- "condition": [
- "config.unix && !config.android && !config.darwin && !config.wasm",
- "features.regularexpression && features.network"
- ],
- "output": [ "privateFeature" ]
- },
- "mtdev": {
- "label": "mtdev",
- "condition": "libs.mtdev",
- "output": [ "privateFeature" ]
- },
- "opengles2": {
- "label": "OpenGL ES 2.0",
- "enable": "input.opengl == 'es2'",
- "disable": "input.opengl == 'desktop' || input.opengl == 'dynamic' || input.opengl == 'no'",
- "condition": "!config.win32 && !config.watchos && !features.opengl-desktop && libs.opengl_es2",
- "output": [
- "publicFeature",
- "publicQtConfig"
- ]
- },
- "opengles3": {
- "label": "OpenGL ES 3.0",
- "condition": "features.opengles2 && tests.opengles3",
- "output": [
- "publicFeature"
- ]
- },
- "opengles31": {
- "label": "OpenGL ES 3.1",
- "condition": "features.opengles3 && tests.opengles31",
- "output": [
- "publicFeature"
- ]
- },
- "opengles32": {
- "label": "OpenGL ES 3.2",
- "condition": "features.opengles31 && tests.opengles32",
- "output": [
- "publicFeature"
- ]
- },
- "opengl-desktop": {
- "label": "Desktop OpenGL",
- "autoDetect": "!config.win32",
- "enable": "input.opengl == 'desktop'",
- "disable": "input.opengl == 'es2' || input.opengl == 'dynamic' || input.opengl == 'no'",
- "condition": "(config.win32 && (config.msvc || libs.opengl)) || (!config.watchos && !config.win32 && !config.wasm && libs.opengl)"
- },
- "opengl-dynamic": {
- "label": "Dynamic OpenGL",
- "disable": "input.opengl == 'no' || input.opengl == 'desktop'",
- "condition": "config.win32",
- "output": [
- { "type": "publicFeature", "name": "dynamicgl" },
- { "type": "define", "name": "QT_OPENGL_DYNAMIC" }
- ]
- },
- "opengl": {
- "label": "OpenGL",
- "condition": "features.opengl-desktop || features.opengl-dynamic || features.opengles2",
- "output": [ "publicFeature", "feature" ]
- },
- "vkgen": {
- "label": "vkgen",
- "condition": "features.xmlstreamreader",
- "output": [ "privateFeature" ]
- },
- "vulkan": {
- "label": "Vulkan",
- "condition": "features.vkgen && libs.vulkan",
- "output": [ "publicFeature" ]
- },
- "openvg": {
- "label": "OpenVG",
- "condition": "libs.openvg",
- "output": [ "publicFeature" ]
- },
- "egl": {
- "label": "EGL",
- "condition": "(features.opengl || features.openvg) && libs.egl && (features.dlopen || !config.unix || config.integrity)",
- "output": [ "publicFeature", "feature" ]
- },
- "egl_x11": {
- "label": "EGL on X11",
- "condition": "features.thread && features.egl && tests.egl-x11",
- "output": [ "privateFeature" ]
- },
- "eglfs": {
- "label": "EGLFS",
- "section": "Platform plugins",
- "condition": "!config.android && !config.darwin && !config.win32 && !config.wasm && features.egl",
- "output": [ "privateFeature" ]
- },
- "eglfs_brcm": {
- "label": "EGLFS Raspberry Pi",
- "condition": "features.eglfs && tests.egl-brcm",
- "output": [ "privateFeature" ]
- },
- "eglfs_egldevice": {
- "label": "EGLFS EGLDevice",
- "condition": "features.eglfs && tests.egl-egldevice && features.kms",
- "output": [ "privateFeature" ]
- },
- "eglfs_gbm": {
- "label": "EGLFS GBM",
- "condition": "features.eglfs && features.gbm && features.kms",
- "output": [ "privateFeature" ]
- },
- "eglfs_vsp2": {
- "label": "EGLFS VSP2",
- "condition": "features.eglfs && features.gbm && features.kms && features.vsp2",
- "output": [ "privateFeature" ]
- },
- "eglfs_mali": {
- "label": "EGLFS Mali",
- "condition": "features.eglfs && (tests.egl-mali || tests.egl-mali-2)",
- "output": [ "privateFeature" ]
- },
- "eglfs_viv": {
- "label": "EGLFS i.Mx6",
- "condition": "features.eglfs && tests.egl-viv",
- "output": [ "privateFeature" ]
- },
- "eglfs_rcar": {
- "label": "EGLFS RCAR",
- "condition": "config.integrity && features.eglfs && tests.egl-rcar",
- "output": [ "privateFeature" ]
- },
- "eglfs_viv_wl": {
- "label": "EGLFS i.Mx6 Wayland",
- "condition": "features.eglfs_viv && libs.wayland_server",
- "output": [ "privateFeature" ]
- },
- "eglfs_openwfd": {
- "label": "EGLFS OpenWFD",
- "condition": "config.integrity && features.eglfs && tests.egl-openwfd",
- "output": [ "privateFeature" ]
- },
- "eglfs_x11": {
- "label": "EGLFS X11",
- "condition": "features.eglfs && features.xcb-xlib && features.egl_x11",
- "output": [ "privateFeature" ]
- },
- "gif": {
- "label": "GIF",
- "condition": "features.imageformatplugin",
- "output": [
- "privateFeature",
- { "type": "define", "negative": true, "name": "QT_NO_IMAGEFORMAT_GIF" }
- ]
- },
- "ico": {
- "label": "ICO",
- "condition": "features.imageformatplugin",
- "output": [ "privateFeature", "feature" ]
- },
- "jpeg": {
- "label": "JPEG",
- "disable": "input.libjpeg == 'no'",
- "condition": "features.imageformatplugin",
- "output": [
- "privateFeature",
- { "type": "define", "negative": true, "name": "QT_NO_IMAGEFORMAT_JPEG" }
- ]
- },
- "system-jpeg": {
- "label": " Using system libjpeg",
- "disable": "input.libjpeg == 'qt'",
- "enable": "input.libjpeg == 'system'",
- "condition": "features.jpeg && libs.libjpeg",
- "output": [ "privateFeature" ]
- },
- "png": {
- "label": "PNG",
- "disable": "input.libpng == 'no'",
- "output": [
- "privateFeature",
- { "type": "define", "negative": true, "name": "QT_NO_IMAGEFORMAT_PNG" }
- ]
- },
- "system-png": {
- "label": " Using system libpng",
- "disable": "input.libpng == 'qt'",
- "enable": "input.libpng == 'system'",
- "autoDetect": "features.system-zlib",
- "condition": "features.png && libs.libpng",
- "output": [ "privateFeature" ]
- },
- "imageio-text-loading": {
- "label": "Image Text section loading",
- "output": [
- "privateFeature",
- { "type": "define", "negative": true, "name": "QT_NO_IMAGEIO_TEXT_LOADING" }
- ]
- },
- "qpa_default_platform": {
- "label": "QPA default platform",
- "condition": "features.gui",
- "output": [
- { "type": "define", "name": "QT_QPA_DEFAULT_PLATFORM_NAME", "value": "tests.qpa_default_platform.name" },
- { "type": "varAssign", "public": true, "name": "QT_DEFAULT_QPA_PLUGIN", "value": "tests.qpa_default_platform.plugin",
- "condition": "!features.shared" }
- ]
- },
- "sessionmanager": {
- "label": "Session Management",
- "purpose": "Provides an interface to the windowing system's session management.",
- "section": "Kernel",
- "output": [ "publicFeature", "feature" ]
- },
- "tslib": {
- "label": "tslib",
- "condition": "libs.tslib",
- "output": [ "privateFeature" ]
- },
- "tuiotouch": {
- "label": "TuioTouch",
- "purpose": "Provides the TuioTouch input plugin.",
- "condition": "features.network && features.udpsocket",
- "output": [ "privateFeature" ]
- },
- "xcb": {
- "label": "XCB",
- "section": "Platform plugins",
- "autoDetect": "!config.darwin",
- "condition": "features.thread && libs.xcb && tests.xcb_syslibs && features.xkbcommon-x11",
- "output": [ "privateFeature" ]
- },
- "x11-prefix": {
- "label": "X11 prefix",
- "emitIf": "features.xcb",
- "output": [ { "type": "varAssign", "name": "QMAKE_X11_PREFIX", "value": "tests.x11prefix.value" } ]
- },
- "xcb-glx-plugin": {
- "label": "GLX Plugin",
- "emitIf": "features.xcb",
- "condition": "features.xcb-xlib && features.opengl && !features.opengles2",
- "output": [ "publicFeature" ]
- },
- "xcb-glx": {
- "label": " XCB GLX",
- "emitIf": "features.xcb && features.xcb-glx-plugin",
- "condition": "libs.xcb_glx",
- "output": [ "privateFeature" ]
- },
- "xcb-egl-plugin": {
- "label": "EGL-X11 Plugin",
- "emitIf": "features.xcb",
- "condition": "features.egl_x11 && features.opengl",
- "output": [ "privateFeature" ]
- },
- "xcb-native-painting": {
- "label": "Native painting (experimental)",
- "autoDetect": false,
- "emitIf": "features.xcb",
- "condition": "features.xcb-xlib && features.fontconfig && libs.xrender",
- "output": [ "privateFeature" ]
- },
- "xrender": {
- "label": "XRender for native painting",
- "emitIf": "features.xcb && features.xcb-native-painting",
- "condition": "features.xcb-native-painting",
- "output": [ "privateFeature" ]
- },
- "xcb-xlib": {
- "label": "XCB Xlib",
- "condition": "features.xlib && libs.xcb_xlib",
- "output": [ "privateFeature" ]
- },
- "xcb-sm": {
- "label": "xcb-sm",
- "emitIf": "features.xcb",
- "condition": "features.sessionmanager && libs.x11sm",
- "output": [ "privateFeature" ]
- },
- "system-xcb-xinput": {
- "label": "Using system-provided xcb-xinput",
- "emitIf": "features.xcb",
- "disable": "input.bundled-xcb-xinput == 'yes'",
- "enable": "input.bundled-xcb-xinput == 'no'",
- "condition": "libs.xcb_xinput",
- "output": [ "privateFeature" ]
- },
- "xkbcommon": {
- "label": "xkbcommon",
- "condition": "libs.xkbcommon",
- "output": [ "privateFeature" ]
- },
- "xkbcommon-x11": {
- "label": "xkbcommon-x11",
- "condition": "features.xkbcommon && libs.xkbcommon_x11",
- "output": [ "privateFeature" ]
- },
- "xlib": {
- "label": "XLib",
- "autoDetect": "!config.darwin || features.xcb",
- "condition": "libs.xlib",
- "output": [ "privateFeature" ]
- },
- "texthtmlparser": {
- "label": "HtmlParser",
- "purpose": "Provides a parser for HTML.",
- "section": "Kernel",
- "output": [ "publicFeature", "feature" ]
- },
- "textmarkdownreader": {
- "label": "MarkdownReader",
- "disable": "input.libmd4c == 'no'",
- "enable": "input.libmd4c == 'system' || input.libmd4c == 'qt' || input.libmd4c == 'yes'",
- "purpose": "Provides a Markdown (CommonMark and GitHub) reader",
- "section": "Kernel",
- "output": [ "publicFeature" ]
- },
- "system-textmarkdownreader": {
- "label": " Using system libmd4c",
- "disable": "input.libmd4c == 'qt'",
- "enable": "input.libmd4c == 'system'",
- "section": "Kernel",
- "condition": "libs.libmd4c",
- "output": [ "publicFeature" ]
- },
- "textmarkdownwriter": {
- "label": "MarkdownWriter",
- "purpose": "Provides a Markdown (CommonMark) writer",
- "section": "Kernel",
- "output": [ "publicFeature" ]
- },
- "textodfwriter": {
- "label": "OdfWriter",
- "purpose": "Provides an ODF writer.",
- "section": "Kernel",
- "condition": "features.xmlstreamwriter",
- "output": [ "publicFeature", "feature" ]
- },
- "cssparser": {
- "label": "CssParser",
- "purpose": "Provides a parser for Cascading Style Sheets.",
- "section": "Kernel",
- "output": [ "publicFeature", "feature" ]
- },
- "draganddrop": {
- "label": "Drag and Drop",
- "purpose": "Supports the drag and drop mechansim.",
- "section": "Kernel",
- "condition": "features.imageformat_xpm",
- "output": [ "publicFeature", "feature" ]
- },
- "action": {
- "label": "Q(Gui)Action(Group)",
- "purpose": "Provides abstract user interface actions.",
- "section": "Kernel",
- "output": [ "publicFeature", "feature" ]
- },
- "cursor": {
- "label": "QCursor",
- "purpose": "Provides mouse cursors.",
- "section": "Kernel",
- "output": [ "publicFeature", "feature" ]
- },
- "clipboard": {
- "label": "QClipboard",
- "purpose": "Provides cut and paste operations.",
- "section": "Kernel",
- "condition": "!config.integrity && !config.qnx && !config.rtems",
- "output": [ "publicFeature", "feature" ]
- },
- "wheelevent": {
- "label": "QWheelEvent",
- "purpose": "Supports wheel events.",
- "section": "Kernel",
- "output": [ "publicFeature", "feature" ]
- },
- "tabletevent": {
- "label": "QTabletEvent",
- "purpose": "Supports tablet events.",
- "section": "Kernel",
- "output": [ "publicFeature", "feature" ]
- },
- "im": {
- "label": "QInputContext",
- "purpose": "Provides complex input methods.",
- "section": "Kernel",
- "condition": "features.library",
- "output": [ "publicFeature", "feature" ]
- },
- "highdpiscaling": {
- "label": "High DPI Scaling",
- "purpose": "Provides automatic scaling of DPI-unaware applications on high-DPI displays.",
- "section": "Kernel",
- "output": [ "publicFeature", "feature" ]
- },
- "validator": {
- "label": "QValidator",
- "purpose": "Supports validation of input text.",
- "section": "Widgets",
- "output": [ "publicFeature", "feature" ]
- },
- "standarditemmodel": {
- "label": "QStandardItemModel",
- "purpose": "Provides a generic model for storing custom data.",
- "section": "ItemViews",
- "condition": "features.itemmodel",
- "output": [ "publicFeature", "feature" ]
- },
- "filesystemmodel": {
- "label": "QFileSystemModel",
- "purpose": "Provides a data model for the local filesystem.",
- "section": "File I/O",
- "condition": "features.itemmodel",
- "output": [ "publicFeature", "feature" ]
- },
- "imageformatplugin": {
- "label": "QImageIOPlugin",
- "purpose": "Provides a base for writing a image format plugins.",
- "section": "Images",
- "output": [ "publicFeature", "feature" ]
- },
- "movie": {
- "label": "QMovie",
- "purpose": "Supports animated images.",
- "section": "Images",
- "output": [ "publicFeature", "feature" ]
- },
- "imageformat_bmp": {
- "label": "BMP Image Format",
- "purpose": "Supports Microsoft's Bitmap image file format.",
- "section": "Images",
- "output": [ "publicFeature", "feature" ]
- },
- "imageformat_ppm": {
- "label": "PPM Image Format",
- "purpose": "Supports the Portable Pixmap image file format.",
- "section": "Images",
- "output": [ "publicFeature", "feature" ]
- },
- "imageformat_xbm": {
- "label": "XBM Image Format",
- "purpose": "Supports the X11 Bitmap image file format.",
- "section": "Images",
- "output": [ "publicFeature", "feature" ]
- },
- "imageformat_xpm": {
- "label": "XPM Image Format",
- "purpose": "Supports the X11 Pixmap image file format.",
- "section": "Images",
- "output": [ "publicFeature", "feature" ]
- },
- "imageformat_png": {
- "label": "PNG Image Format",
- "purpose": "Supports the Portable Network Graphics image file format.",
- "section": "Images",
- "output": [ "publicFeature", "feature" ]
- },
- "imageformat_jpeg": {
- "label": "JPEG Image Format",
- "purpose": "Supports the Joint Photographic Experts Group image file format.",
- "section": "Images",
- "output": [ "publicFeature", "feature" ]
- },
- "image_heuristic_mask": {
- "label": "QImage::createHeuristicMask()",
- "purpose": "Supports creating a 1-bpp heuristic mask for images.",
- "section": "Images",
- "output": [ "publicFeature", "feature" ]
- },
- "image_text": {
- "label": "Image Text",
- "purpose": "Supports image file text strings.",
- "section": "Images",
- "output": [ "publicFeature", "feature" ]
- },
- "picture": {
- "label": "QPicture",
- "purpose": "Supports recording and replaying QPainter commands.",
- "section": "Painting",
- "output": [ "publicFeature", "feature" ]
- },
- "colornames": {
- "label": "Color Names",
- "purpose": "Supports color names such as \"red\", used by QColor and by some HTML documents.",
- "section": "Painting",
- "output": [ "publicFeature", "feature" ]
- },
- "pdf": {
- "label": "QPdf",
- "purpose": "Provides a PDF backend for QPainter.",
- "section": "Painting",
- "condition": "features.temporaryfile",
- "output": [ "publicFeature", "feature" ]
- },
- "desktopservices": {
- "label": "QDesktopServices",
- "purpose": "Provides methods for accessing common desktop services.",
- "section": "Utilities",
- "output": [ "publicFeature", "feature" ]
- },
- "systemtrayicon": {
- "label": "QSystemTrayIcon",
- "purpose": "Provides an icon for an application in the system tray.",
- "section": "Utilities",
- "condition": "features.temporaryfile",
- "output": [ "publicFeature", "feature" ]
- },
- "accessibility": {
- "label": "Accessibility",
- "purpose": "Provides accessibility support.",
- "section": "Utilities",
- "condition": "features.properties",
- "output": [ "publicFeature", "feature" ]
- },
- "multiprocess": {
- "label": "Multi process",
- "purpose": "Provides support for detecting the desktop environment, launching external processes and opening URLs.",
- "section": "Utilities",
- "condition": "!config.integrity && !config.rtems",
- "output": [ "privateFeature" ]
- },
- "whatsthis": {
- "label": "QWhatsThis",
- "purpose": "Supports displaying \"What's this\" help.",
- "section": "Widget Support",
- "output": [ "publicFeature", "feature" ]
- },
- "raster-64bit": {
- "label": "QPainter - 64 bit raster",
- "purpose": "Internal painting support for 64 bit (16 bpc) rasterization.",
- "section": "Painting",
- "output": [ "privateFeature" ]
- },
- "undocommand": {
- "label": "QUndoCommand",
- "purpose": "Applies (redo or) undo of a single change in a document.",
- "section": "Utilities",
- "output": [ "publicFeature", "feature" ]
- },
- "undostack": {
- "label": "QUndoStack",
- "purpose": "Provides the ability to (redo or) undo a list of changes in a document.",
- "section": "Utilities",
- "condition": "features.undocommand",
- "output": [ "publicFeature", "feature" ]
- },
- "undogroup": {
- "label": "QUndoGroup",
- "purpose": "Provides the ability to cluster QUndoCommands.",
- "section": "Utilities",
- "condition": "features.undostack",
- "output": [ "publicFeature", "feature" ]
- }
- },
-
- "earlyReport": [
- {
- "type": "error",
- "condition": "input.xcb != '' && input.xcb != 'no' && input.xkbcommon == 'no'",
- "message": "XCB plugin requires xkbcommon and xkbcommon-x11, but -no-xkbcommon was provided."
- }
- ],
-
- "report": [
- {
- "type": "note",
- "condition": "features.xcb && config.darwin",
- "message": "XCB support on macOS is minimal and untested. Some features will not work properly or at all (e.g. OpenGL, desktop services or accessibility), or may depend on your system and XQuartz setup."
- },
- {
- "type": "note",
- "condition": "features.accessibility && features.xcb && !features.accessibility-atspi-bridge",
- "message": "Disabling X11 Accessibility Bridge: D-Bus or AT-SPI is missing."
- },
- {
- "type": "warning",
- "condition": "features.gui && config.linux && !config.android && !features.xcb && !features.eglfs && !features.directfb && !features.linuxfb",
- "message": "No QPA platform plugin enabled! This will produce a Qt that cannot run GUI applications. See \"Platform backends\" in the output of --help."
- },
- {
- "type": "warning",
- "condition": "config.darwin && features.system-harfbuzz",
- "message": "On OS X, AAT is supported only with -qt-harfbuzz."
- },
- {
- "type": "error",
- "condition": "features.gui && !config.watchos && input.opengl != 'no' && !features.opengl-desktop && !features.opengles2 && !features.opengl-dynamic",
- "message": "The OpenGL functionality tests failed! You might need to modify the include and library search paths by editing QMAKE_INCDIR_OPENGL[_ES2], QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your platform."
- },
- {
- "type": "warning",
- "condition": "!features.accessibility",
- "message": "Accessibility disabled. This configuration of Qt is unsupported."
- }
- ],
-
- "summary": [
- {
- "section": "Qt Gui",
- "entries": [
- "accessibility",
- "freetype",
- "system-freetype",
- "harfbuzz",
- "system-harfbuzz",
- "fontconfig",
- {
- "section": "Image formats",
- "entries": [
- "gif", "ico", "jpeg", "system-jpeg", "png", "system-png"
- ]
- },
- {
- "section": "Text formats",
- "entries": [
- "texthtmlparser", "cssparser", "textodfwriter", "textmarkdownreader", "system-textmarkdownreader", "textmarkdownwriter"
- ]
- },
- "egl",
- "openvg",
- {
- "section": "OpenGL",
- "entries": [
- "opengl-desktop",
- {
- "type": "feature",
- "args": "opengl-dynamic",
- "condition": "config.win32"
- },
- "opengles2",
- "opengles3",
- "opengles31",
- "opengles32"
- ]
- },
- "vulkan",
- "sessionmanager"
- ]
- },
- {
- "section": "Features used by QPA backends",
- "entries": [
- "evdev",
- "libinput",
- "integrityhid",
- "mtdev",
- "tslib",
- "xkbcommon",
- {
- "section": "X11 specific",
- "entries": [
- "xlib",
- "xcb-xlib",
- "egl_x11",
- "xkbcommon-x11"
- ]
- }
- ]
- },
- {
- "section": "QPA backends",
- "entries": [
- "directfb", "eglfs",
- {
- "section": "EGLFS details",
- "condition": "features.eglfs",
- "entries": [
- "eglfs_openwfd", "eglfs_viv", "eglfs_viv_wl", "eglfs_rcar", "eglfs_egldevice", "eglfs_gbm", "eglfs_vsp2", "eglfs_mali", "eglfs_brcm", "eglfs_x11"
- ]
- },
- "linuxfb", "vnc",
- {
- "type": "feature",
- "condition": "config.integrity",
- "args": "integrityfb"
- },
- {
- "section": "QNX",
- "condition": "config.qnx",
- "entries": [
- "lgmon", "qqnx_imf"
- ]
- },
- {
- "section": "XCB",
- "condition": "features.xcb",
- "entries": [
- "system-xcb-xinput", "xcb-native-painting",
- {
- "section": "GL integrations",
- "entries": [
- "xcb-glx-plugin",
- "xcb-glx",
- "xcb-egl-plugin"
- ]
- }
- ]
- },
- {
- "section": "Windows",
- "condition": "config.win32",
- "entries": [
- "direct2d", "directwrite", "directwrite3"
- ]
- }
- ]
- }
- ]
-}
diff --git a/src/gui/doc/snippets/code/src_gui_vulkan_qvulkaninstance.cpp b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkaninstance.cpp
index 0ce6492b12..1dfd43ad10 100644
--- a/src/gui/doc/snippets/code/src_gui_vulkan_qvulkaninstance.cpp
+++ b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkaninstance.cpp
@@ -85,14 +85,14 @@ void wrapper0() {
QVulkanInstance inst;
// Enable validation layer, if supported. Messages go to qDebug by default.
- inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+ inst.setLayers({ "VK_LAYER_KHRONOS_validation" });
bool ok = inst.create();
if (!ok) {
// ... Vulkan not available
}
- if (!inst.layers().contains("VK_LAYER_LUNARG_standard_validation")) {
+ if (!inst.layers().contains("VK_LAYER_KHRONOS_validation")) {
// ... validation layer not available
}
//! [1]
@@ -103,7 +103,7 @@ void wrapper1() {
//! [2]
QVulkanInstance inst;
- if (inst.supportedLayers().contains("VK_LAYER_LUNARG_standard_validation")) {
+ if (inst.supportedLayers().contains("VK_LAYER_KHRONOS_validation")) {
// ...
}
bool ok = inst.create();
diff --git a/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanwindow.cpp b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanwindow.cpp
index 535b99be75..1f4988ca35 100644
--- a/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanwindow.cpp
+++ b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanwindow.cpp
@@ -98,7 +98,7 @@ int main(int argc, char *argv[])
QVulkanInstance inst;
// enable the standard validation layers, when available
- inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+ inst.setLayers({ "VK_LAYER_KHRONOS_validation" });
if (!inst.create())
qFatal("Failed to create Vulkan instance: %d", inst.errorCode());
diff --git a/src/gui/image/qbitmap.cpp b/src/gui/image/qbitmap.cpp
index 0505717fb3..45620e7181 100644
--- a/src/gui/image/qbitmap.cpp
+++ b/src/gui/image/qbitmap.cpp
@@ -277,7 +277,7 @@ QBitmap QBitmap::fromPixmap(const QPixmap &pixmap)
#if QT_DEPRECATED_SINCE(6, 0)
/*!
- \obsolete Use fromPixmap instead.
+ \deprecated Use fromPixmap instead.
Constructs a bitmap that is a copy of the given \a pixmap.
If the pixmap has a depth greater than 1, the resulting bitmap
@@ -292,7 +292,7 @@ QBitmap::QBitmap(const QPixmap &pixmap)
}
/*!
- \obsolete Use fromPixmap instead.
+ \deprecated Use fromPixmap instead.
\overload
Assigns the given \a pixmap to this bitmap and returns a reference
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 9c554dd513..af28c8a0ec 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -885,7 +885,7 @@ QPixmap QIcon::pixmap(const QSize &size, qreal devicePixelRatio, Mode mode, Stat
a high-dpi display the pixmap can be larger. In that case it will have
a devicePixelRatio larger than 1.
- \obsolete Use the overload which takes qreal devicePixelRatio instead.
+ \deprecated Use the overload which takes qreal devicePixelRatio instead.
\sa actualSize(), paint()
*/
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 95be9772c8..d6c29ec736 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -42,10 +42,12 @@
#include "qbuffer.h"
#include "qdatastream.h"
#include "qcolortransform.h"
+#include "qfloat16.h"
#include "qmap.h"
#include "qtransform.h"
#include "qimagereader.h"
#include "qimagewriter.h"
+#include "qrgbaf.h"
#include "qstringlist.h"
#include "qvariant.h"
#include "qimagepixmapcleanuphooks_p.h"
@@ -293,6 +295,24 @@ bool QImageData::checkForAlphaPixels() const
bits += bytes_per_line;
}
} break;
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied: {
+ uchar *bits = data;
+ for (int y = 0; y < height && !has_alpha_pixels; ++y) {
+ for (int x = 0; x < width; ++x)
+ has_alpha_pixels |= ((qfloat16 *)bits)[x * 4 + 3] < 1.0f;
+ bits += bytes_per_line;
+ }
+ } break;
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied: {
+ uchar *bits = data;
+ for (int y = 0; y < height && !has_alpha_pixels; ++y) {
+ for (int x = 0; x < width; ++x)
+ has_alpha_pixels |= ((float *)bits)[x * 4 + 3] < 1.0f;
+ bits += bytes_per_line;
+ }
+ } break;
case QImage::Format_RGB32:
case QImage::Format_RGB16:
@@ -307,6 +327,8 @@ bool QImageData::checkForAlphaPixels() const
case QImage::Format_Grayscale8:
case QImage::Format_Grayscale16:
case QImage::Format_RGBX64:
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBX32FPx4:
break;
case QImage::Format_Invalid:
case QImage::NImageFormats:
@@ -735,6 +757,16 @@ bool QImageData::checkForAlphaPixels() const
\value Format_RGBA64_Premultiplied The image is stored using a premultiplied 64-bit halfword-ordered
RGBA format (16-16-16-16). (added in Qt 5.12)
\value Format_BGR888 The image is stored using a 24-bit BGR format. (added in Qt 5.14)
+ \value Format_RGBX16FPx4 The image is stored using a 4 16-bit halfword floating point RGBx format (16FP-16FP-16FP-16FP).
+ This is the same as the Format_RGBA16FPx4 except alpha must always be 1.0. (added in Qt 6.2)
+ \value Format_RGBA16FPx4 The image is stored using a 4 16-bit halfword floating point RGBA format (16FP-16FP-16FP-16FP). (added in Qt 6.2)
+ \value Format_RGBA16FPx4_Premultiplied The image is stored using a premultiplied 4 16-bit halfword floating point
+ RGBA format (16FP-16FP-16FP-16FP). (added in Qt 6.2)
+ \value Format_RGBX32FPx4 The image is stored using a 4 32-bit floating point RGBx format (32FP-32FP-32FP-32FP).
+ This is the same as the Format_RGBA32FPx4 except alpha must always be 1.0. (added in Qt 6.2)
+ \value Format_RGBA32FPx4 The image is stored using a 4 32-bit floating point RGBA format (32FP-32FP-32FP-32FP). (added in Qt 6.2)
+ \value Format_RGBA32FPx4_Premultiplied The image is stored using a premultiplied 4 32-bit floating point
+ RGBA format (32FP-32FP-32FP-32FP). (added in Qt 6.2)
\note Drawing into a QImage with QImage::Format_Indexed8 is not
supported.
@@ -1741,11 +1773,29 @@ void QImage::fill(uint pixel)
qt_rectfill<quint24>(reinterpret_cast<quint24*>(d->data), pixel,
0, 0, d->width, d->height, d->bytes_per_line);
return;
- } else if (d->depth == 64) {
+ } else if (d->format >= QImage::Format_RGBX64 && d->format <= QImage::Format_RGBA64_Premultiplied) {
qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), QRgba64::fromArgb32(pixel),
0, 0, d->width, d->height, d->bytes_per_line);
return;
+ } else if (d->format >= QImage::Format_RGBX16FPx4 && d->format <= QImage::Format_RGBA16FPx4_Premultiplied) {
+ quint64 cu;
+ QRgba16F cf = QRgba16F::fromArgb32(pixel);
+ ::memcpy(&cu, &cf, sizeof(quint64));
+ qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), cu,
+ 0, 0, d->width, d->height, d->bytes_per_line);
+ return;
+ } else if (d->format >= QImage::Format_RGBX32FPx4 && d->format <= QImage::Format_RGBA32FPx4_Premultiplied) {
+ QRgba32F cf = QRgba32F::fromArgb32(pixel);
+ uchar *data = d->data;
+ for (int y = 0; y < d->height; ++y) {
+ QRgba32F *line = reinterpret_cast<QRgba32F *>(data);
+ for (int x = 0; x < d->width; ++x)
+ line[x] = cf;
+ data += d->bytes_per_line;
+ }
+ return;
}
+ Q_ASSERT(d->depth == 32);
if (d->format == Format_RGB32)
pixel |= 0xff000000;
@@ -1907,7 +1957,13 @@ void QImage::invertPixels(InvertMode mode)
QImage::Format originalFormat = d->format;
// Inverting premultiplied pixels would produce invalid image data.
if (hasAlphaChannel() && qPixelLayouts[d->format].premultiplied) {
- if (depth() > 32) {
+ if (d->format == QImage::Format_RGBA16FPx4_Premultiplied) {
+ if (!d->convertInPlace(QImage::Format_RGBA16FPx4, { }))
+ *this = convertToFormat(QImage::Format_RGBA16FPx4);
+ } else if (d->format == QImage::Format_RGBA32FPx4_Premultiplied) {
+ if (!d->convertInPlace(QImage::Format_RGBA32FPx4, { }))
+ *this = convertToFormat(QImage::Format_RGBA32FPx4);
+ } else if (depth() > 32) {
if (!d->convertInPlace(QImage::Format_RGBA64, { }))
*this = convertToFormat(QImage::Format_RGBA64);
} else {
@@ -1926,8 +1982,32 @@ void QImage::invertPixels(InvertMode mode)
*sl++ ^= 0xff;
sl += pad;
}
- }
- else if (depth() == 64) {
+ } else if (format() >= QImage::Format_RGBX16FPx4 && format() <= QImage::Format_RGBA16FPx4_Premultiplied) {
+ qfloat16 *p = reinterpret_cast<qfloat16 *>(d->data);
+ qfloat16 *end = reinterpret_cast<qfloat16 *>(d->data + d->nbytes);
+ while (p < end) {
+ p[0] = 1.0f - p[0];
+ p[1] = 1.0f - p[1];
+ p[2] = 1.0f - p[2];
+ if (mode == InvertRgba)
+ p[3] = 1.0f - p[3];
+ p += 4;
+ }
+ } else if (format() >= QImage::Format_RGBX32FPx4 && format() <= QImage::Format_RGBA32FPx4_Premultiplied) {
+ uchar *data = d->data;
+ for (int y = 0; y < d->height; ++y) {
+ float *p = reinterpret_cast<float *>(data);
+ for (int x = 0; x < d->width; ++x) {
+ p[0] = 1.0f - p[0];
+ p[1] = 1.0f - p[1];
+ p[2] = 1.0f - p[2];
+ if (mode == InvertRgba)
+ p[3] = 1.0f - p[3];
+ p += 4;
+ }
+ data += d->bytes_per_line;
+ }
+ } else if (depth() == 64) {
quint16 *p = (quint16*)d->data;
quint16 *end = (quint16*)(d->data + d->nbytes);
quint16 xorbits = 0xffff;
@@ -2085,7 +2165,12 @@ QImage QImage::convertToFormat_helper(Format format, Qt::ImageConversionFlags fl
if (!converter && format > QImage::Format_Indexed8 && d->format > QImage::Format_Indexed8) {
if (qt_highColorPrecision(d->format, !destLayout->hasAlphaChannel)
&& qt_highColorPrecision(format, !hasAlphaChannel())) {
- converter = convert_generic_over_rgb64;
+#if QT_CONFIG(raster_fp)
+ if (qt_fpColorPrecision(d->format) && qt_fpColorPrecision(format))
+ converter = convert_generic_over_rgba32f;
+ else
+#endif
+ converter = convert_generic_over_rgb64;
} else
converter = convert_generic;
}
@@ -2418,6 +2503,14 @@ QRgb QImage::pixel(int x, int y) const
case Format_RGBA64: // Match ARGB32 behavior.
case Format_RGBA64_Premultiplied:
return reinterpret_cast<const QRgba64 *>(s)[x].toArgb32();
+ case Format_RGBX16FPx4:
+ case Format_RGBA16FPx4: // Match ARGB32 behavior.
+ case Format_RGBA16FPx4_Premultiplied:
+ return reinterpret_cast<const QRgba16F *>(s)[x].toArgb32();
+ case Format_RGBX32FPx4:
+ case Format_RGBA32FPx4: // Match ARGB32 behavior.
+ case Format_RGBA32FPx4_Premultiplied:
+ return reinterpret_cast<const QRgba32F *>(s)[x].toArgb32();
default:
break;
}
@@ -2519,6 +2612,20 @@ void QImage::setPixel(int x, int y, uint index_or_rgb)
case Format_RGBA64_Premultiplied:
((QRgba64 *)s)[x] = QRgba64::fromArgb32(index_or_rgb);
return;
+ case Format_RGBX16FPx4:
+ ((QRgba16F *)s)[x] = QRgba16F::fromArgb32(index_or_rgb | 0xff000000);
+ return;
+ case Format_RGBA16FPx4:
+ case Format_RGBA16FPx4_Premultiplied:
+ ((QRgba16F *)s)[x] = QRgba16F::fromArgb32(index_or_rgb);
+ return;
+ case Format_RGBX32FPx4:
+ ((QRgba32F *)s)[x] = QRgba32F::fromArgb32(index_or_rgb | 0xff000000);
+ return;
+ case Format_RGBA32FPx4:
+ case Format_RGBA32FPx4_Premultiplied:
+ ((QRgba32F *)s)[x] = QRgba32F::fromArgb32(index_or_rgb);
+ return;
case Format_Invalid:
case NImageFormats:
Q_ASSERT(false);
@@ -2583,6 +2690,26 @@ QColor QImage::pixelColor(int x, int y) const
quint16 v = reinterpret_cast<const quint16 *>(s)[x];
return QColor(qRgba64(v, v, v, 0xffff));
}
+ case Format_RGBX16FPx4:
+ case Format_RGBA16FPx4:
+ case Format_RGBA16FPx4_Premultiplied: {
+ QRgba16F p = reinterpret_cast<const QRgba16F *>(s)[x];
+ if (d->format == Format_RGBA16FPx4_Premultiplied)
+ p = p.unpremultiplied();
+ QColor color;
+ color.setRgbF(p.red(), p.green(), p.blue(), p.alpha());
+ return color;
+ }
+ case Format_RGBX32FPx4:
+ case Format_RGBA32FPx4:
+ case Format_RGBA32FPx4_Premultiplied: {
+ QRgba32F p = reinterpret_cast<const QRgba32F *>(s)[x];
+ if (d->format == Format_RGBA32FPx4_Premultiplied)
+ p = p.unpremultiplied();
+ QColor color;
+ color.setRgbF(p.red(), p.green(), p.blue(), p.alpha());
+ return color;
+ }
default:
c = QRgba64::fromArgb32(pixel(x, y));
break;
@@ -2658,6 +2785,32 @@ void QImage::setPixelColor(int x, int y, const QColor &color)
case Format_RGBA64_Premultiplied:
((QRgba64 *)s)[x] = c;
return;
+ case Format_RGBX16FPx4:
+ case Format_RGBA16FPx4:
+ case Format_RGBA16FPx4_Premultiplied: {
+ float r, g, b, a;
+ color.getRgbF(&r, &g, &b, &a);
+ if (d->format == Format_RGBX16FPx4)
+ a = 1.0f;
+ QRgba16F c16f{r, g, b, a};
+ if (d->format == Format_RGBA16FPx4_Premultiplied)
+ c16f = c16f.premultiplied();
+ ((QRgba16F *)s)[x] = c16f;
+ return;
+ }
+ case Format_RGBX32FPx4:
+ case Format_RGBA32FPx4:
+ case Format_RGBA32FPx4_Premultiplied: {
+ float r, g, b, a;
+ color.getRgbF(&r, &g, &b, &a);
+ if (d->format == Format_RGBX32FPx4)
+ a = 1.0f;
+ QRgba32F c32f{r, g, b, a};
+ if (d->format == Format_RGBA32FPx4_Premultiplied)
+ c32f = c32f.premultiplied();
+ ((QRgba32F *)s)[x] = c32f;
+ return;
+ }
default:
setPixel(x, y, c.toArgb32());
return;
@@ -3218,6 +3371,9 @@ inline void do_mirror(QImageData *dst, QImageData *src, bool horizontal, bool ve
}
switch (depth) {
+ case 128:
+ do_mirror_data<QRgba32F>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
+ break;
case 64:
do_mirror_data<quint64>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
break;
@@ -3585,11 +3741,10 @@ bool QImage::load(QIODevice* device, const char* format)
}
/*!
- \fn bool QImage::loadFromData(const uchar *data, int len, const char *format)
+ \since 6.2
- Loads an image from the first \a len bytes of the given binary \a
- data. Returns \c true if the image was successfully loaded; otherwise
- invalidates the image and returns \c false.
+ Loads an image from the given QByteArrayView \a data. Returns \c true if the image was
+ successfully loaded; otherwise invalidates the image and returns \c false.
The loader attempts to read the image using the specified \a format, e.g.,
PNG or JPG. If \a format is not specified (which is the default), the
@@ -3598,13 +3753,26 @@ bool QImage::load(QIODevice* device, const char* format)
\sa {QImage#Reading and Writing Image Files}{Reading and Writing Image Files}
*/
-bool QImage::loadFromData(const uchar *data, int len, const char *format)
+bool QImage::loadFromData(QByteArrayView data, const char *format)
{
- *this = fromData(data, len, format);
+ *this = fromData(data, format);
return !isNull();
}
/*!
+ \fn bool QImage::loadFromData(const uchar *data, int len, const char *format)
+
+ \overload
+
+ Loads an image from the first \a len bytes of the given binary \a data.
+*/
+
+bool QImage::loadFromData(const uchar *buf, int len, const char *format)
+{
+ return loadFromData(QByteArrayView(buf, len), format);
+}
+
+/*!
\fn bool QImage::loadFromData(const QByteArray &data, const char *format)
\overload
@@ -3613,12 +3781,11 @@ bool QImage::loadFromData(const uchar *data, int len, const char *format)
*/
/*!
- \fn QImage QImage::fromData(const uchar *data, int size, const char *format)
+ \since 6.2
- Constructs a QImage from the first \a size bytes of the given
- binary \a data. The loader attempts to read the image using the
- specified \a format. If \a format is not specified (which is the default),
- the loader probes the data for a header to guess the file format.
+ Constructs an image from the given QByteArrayView \a data. The loader attempts to read the image
+ using the specified \a format. If \a format is not specified (which is the default), the loader
+ probes the data for a header to guess the file format.
If \a format is specified, it must be one of the values returned by
QImageReader::supportedImageFormats().
@@ -3628,9 +3795,9 @@ bool QImage::loadFromData(const uchar *data, int len, const char *format)
\sa load(), save(), {QImage#Reading and Writing Image Files}{Reading and Writing Image Files}
*/
-QImage QImage::fromData(const uchar *data, int size, const char *format)
+QImage QImage::fromData(QByteArrayView data, const char *format)
{
- QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(data), size);
+ QByteArray a = QByteArray::fromRawData(data.constData(), data.size());
QBuffer b;
b.setData(a);
b.open(QIODevice::ReadOnly);
@@ -3638,11 +3805,25 @@ QImage QImage::fromData(const uchar *data, int size, const char *format)
}
/*!
+ \fn QImage QImage::fromData(const uchar *data, int size, const char *format)
+
+ \overload
+
+ Constructs a QImage from the first \a size bytes of the given binary \a data.
+*/
+
+QImage QImage::fromData(const uchar *data, int size, const char *format)
+{
+ return fromData(QByteArrayView(data, size), format);
+}
+
+/*!
\fn QImage QImage::fromData(const QByteArray &data, const char *format)
\overload
- Loads an image from the given QByteArray \a data.
+ Constructs a QImage from the given QByteArray \a data.
+
*/
/*!
@@ -4409,8 +4590,12 @@ int QImage::bitPlaneCount() const
bpc = 12;
break;
case QImage::Format_RGBX64:
+ case QImage::Format_RGBX16FPx4:
bpc = 48;
break;
+ case QImage::Format_RGBX32FPx4:
+ bpc = 96;
+ break;
default:
bpc = qt_depthForFormat(d->format);
break;
@@ -4429,7 +4614,8 @@ int QImage::bitPlaneCount() const
if necessary. To avoid unnecessary conversion the result is returned in the format
internally used, and not in the original format.
*/
-QImage QImage::smoothScaled(int w, int h) const {
+QImage QImage::smoothScaled(int w, int h) const
+{
QImage src = *this;
switch (src.format()) {
case QImage::Format_RGB32:
@@ -4443,14 +4629,28 @@ QImage QImage::smoothScaled(int w, int h) const {
case QImage::Format_RGBA64_Premultiplied:
break;
case QImage::Format_RGBA64:
- src = src.convertToFormat(QImage::Format_RGBA64_Premultiplied);
+ case QImage::Format_Grayscale16:
+ src.convertTo(QImage::Format_RGBA64_Premultiplied);
+ break;
+#endif
+#if QT_CONFIG(raster_fp)
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+ break;
+ case QImage::Format_RGBX16FPx4:
+ src.convertTo(QImage::Format_RGBX32FPx4);
+ break;
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ case QImage::Format_RGBA32FPx4:
+ src.convertTo(QImage::Format_RGBA32FPx4_Premultiplied);
break;
#endif
default:
if (src.hasAlphaChannel())
- src = src.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ src.convertTo(QImage::Format_ARGB32_Premultiplied);
else
- src = src.convertToFormat(QImage::Format_RGB32);
+ src.convertTo(QImage::Format_RGB32);
}
src = qSmoothScaleImage(src, w, h);
if (!src.isNull())
@@ -4813,6 +5013,13 @@ QColorSpace QImage::colorSpace() const
*/
void QImage::applyColorTransform(const QColorTransform &transform)
{
+ if (!d)
+ return;
+ if (pixelFormat().colorModel() == QPixelFormat::Indexed) {
+ for (int i = 0; i < d->colortable.size(); ++i)
+ d->colortable[i] = transform.map(d->colortable[i]);
+ return;
+ }
QImage::Format oldFormat = format();
if (depth() > 32) {
if (format() != QImage::Format_RGBX64 && format() != QImage::Format_RGBA64
@@ -4903,6 +5110,10 @@ bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFla
// any direct ones are probably better even if not inplace.
if (qt_highColorPrecision(newFormat, !qPixelLayouts[newFormat].hasAlphaChannel)
&& qt_highColorPrecision(format, !qPixelLayouts[format].hasAlphaChannel)) {
+#if QT_CONFIG(raster_fp)
+ if (qt_fpColorPrecision(format) && qt_fpColorPrecision(newFormat))
+ return convert_generic_inplace_over_rgba32f(this, newFormat, flags);
+#endif
return convert_generic_inplace_over_rgb64(this, newFormat, flags);
}
return convert_generic_inplace(this, newFormat, flags);
@@ -5328,6 +5539,84 @@ static constexpr QPixelFormat pixelformats[] = {
/*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
/*INTERPRETATION*/ QPixelFormat::UnsignedByte,
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBX16FPx4:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 16,
+ /*GREEN*/ 16,
+ /*BLUE*/ 16,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 16,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::FloatingPoint,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBA16FPx4:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 16,
+ /*GREEN*/ 16,
+ /*BLUE*/ 16,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 16,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::FloatingPoint,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBA16FPx4_Premultiplied:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 16,
+ /*GREEN*/ 16,
+ /*BLUE*/ 16,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 16,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::FloatingPoint,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBX32FPx4:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 32,
+ /*GREEN*/ 32,
+ /*BLUE*/ 32,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 32,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::FloatingPoint,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBA32FPx4:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 32,
+ /*GREEN*/ 32,
+ /*BLUE*/ 32,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 32,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::FloatingPoint,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBA32FPx4_Premultiplied:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 32,
+ /*GREEN*/ 32,
+ /*BLUE*/ 32,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 32,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::FloatingPoint,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
};
static_assert(sizeof(pixelformats) / sizeof(*pixelformats) == QImage::NImageFormats);
diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h
index ecb38af172..6561359dae 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -47,6 +47,7 @@
#include <QtGui/qpixelformat.h>
#include <QtGui/qtransform.h>
#include <QtCore/qbytearray.h>
+#include <QtCore/qbytearrayview.h>
#include <QtCore/qrect.h>
#include <QtCore/qstring.h>
#include <QtCore/qcontainerfwd.h>
@@ -104,6 +105,12 @@ public:
Format_RGBA64_Premultiplied,
Format_Grayscale16,
Format_BGR888,
+ Format_RGBX16FPx4,
+ Format_RGBA16FPx4,
+ Format_RGBA16FPx4_Premultiplied,
+ Format_RGBX32FPx4,
+ Format_RGBA32FPx4,
+ Format_RGBA32FPx4_Premultiplied,
#ifndef Q_QDOC
NImageFormats
#endif
@@ -267,16 +274,18 @@ public:
bool load(QIODevice *device, const char *format);
bool load(const QString &fileName, const char *format = nullptr);
- bool loadFromData(const uchar *buf, int len, const char *format = nullptr);
- bool loadFromData(const QByteArray &data, const char *aformat = nullptr)
- { return loadFromData(reinterpret_cast<const uchar *>(data.constData()), data.size(), aformat); }
+ bool loadFromData(QByteArrayView data, const char *format = nullptr);
+ bool loadFromData(const uchar *buf, int len, const char *format = nullptr); // ### Qt 7: qsizetype
+ bool loadFromData(const QByteArray &data, const char *format = nullptr) // ### Qt 7: drop
+ { return loadFromData(QByteArrayView(data), format); }
bool save(const QString &fileName, const char *format = nullptr, int quality = -1) const;
bool save(QIODevice *device, const char *format = nullptr, int quality = -1) const;
- static QImage fromData(const uchar *data, int size, const char *format = nullptr);
- static QImage fromData(const QByteArray &data, const char *format = nullptr)
- { return fromData(reinterpret_cast<const uchar *>(data.constData()), data.size(), format); }
+ static QImage fromData(QByteArrayView data, const char *format = nullptr);
+ static QImage fromData(const uchar *data, int size, const char *format = nullptr); // ### Qt 7: qsizetype
+ static QImage fromData(const QByteArray &data, const char *format = nullptr) // ### Qt 7: drop
+ { return fromData(QByteArrayView(data), format); }
qint64 cacheKey() const;
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 84a5a5ab83..5825397a21 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -38,6 +38,7 @@
****************************************************************************/
#include <private/qguiapplication_p.h>
+#include <private/qcolortransform_p.h>
#include <private/qcolortrclut_p.h>
#include <private/qdrawhelper_p.h>
#include <private/qendian_p.h>
@@ -46,6 +47,7 @@
#include <private/qimage_p.h>
#include <qendian.h>
+#include <qrgbaf.h>
#if QT_CONFIG(thread)
#include <qsemaphore.h>
#include <qthreadpool.h>
@@ -312,6 +314,61 @@ void convert_generic_over_rgb64(QImageData *dest, const QImageData *src, Qt::Ima
#endif
}
+#if QT_CONFIG(raster_fp)
+void convert_generic_over_rgba32f(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(dest->format >= QImage::Format_RGBX16FPx4);
+ Q_ASSERT(src->format >= QImage::Format_RGBX16FPx4);
+
+ const FetchAndConvertPixelsFuncFP fetch = qFetchToRGBA32F[src->format];
+ const ConvertAndStorePixelsFuncFP store = qStoreFromRGBA32F[dest->format];
+
+ auto convertSegment = [=](int yStart, int yEnd) {
+ QRgba32F buf[BufferSize];
+ QRgba32F *buffer = buf;
+ const uchar *srcData = src->data + yStart * src->bytes_per_line;
+ uchar *destData = dest->data + yStart * dest->bytes_per_line;
+ for (int y = yStart; y < yEnd; ++y) {
+ int x = 0;
+ while (x < src->width) {
+ int l = src->width - x;
+ if (dest->depth == 128)
+ buffer = reinterpret_cast<QRgba32F *>(destData) + x;
+ else
+ l = qMin(l, BufferSize);
+ const QRgba32F *ptr = fetch(buffer, srcData, x, l, nullptr, nullptr);
+ store(destData, ptr, x, l, nullptr, nullptr);
+ x += l;
+ }
+ srcData += src->bytes_per_line;
+ destData += dest->bytes_per_line;
+ }
+ };
+#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
+ int segments = (qsizetype(src->width) * src->height) >> 16;
+ segments = std::min(segments, src->height);
+
+ QThreadPool *threadPool = QThreadPool::globalInstance();
+ if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
+ return convertSegment(0, src->height);
+
+ QSemaphore semaphore;
+ int y = 0;
+ for (int i = 0; i < segments; ++i) {
+ int yn = (src->height - y) / (segments - i);
+ threadPool->start([&, y, yn]() {
+ convertSegment(y, y + yn);
+ semaphore.release(1);
+ });
+ y += yn;
+ }
+ semaphore.acquire(segments);
+#else
+ convertSegment(0, src->height);
+#endif
+}
+#endif
+
bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags flags)
{
// Cannot be used with indexed formats or between formats with different pixel depths.
@@ -336,7 +393,7 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
return false;
}
- Q_ASSERT(destLayout->bpp != QPixelLayout::BPP64);
+ Q_ASSERT(destLayout->bpp < QPixelLayout::BPP64);
FetchAndConvertPixelsFunc fetch = srcLayout->fetchToARGB32PM;
ConvertAndStorePixelsFunc store = destLayout->storeFromARGB32PM;
if (!srcLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
@@ -534,6 +591,102 @@ bool convert_generic_inplace_over_rgb64(QImageData *data, QImage::Format dst_for
return true;
}
+#if QT_CONFIG(raster_fp)
+bool convert_generic_inplace_over_rgba32f(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(data->format >= QImage::Format_RGBX16FPx4);
+ Q_ASSERT(dst_format >= QImage::Format_RGBX16FPx4);
+ const int destDepth = qt_depthForFormat(dst_format);
+ if (data->depth < destDepth)
+ return false;
+
+ const QPixelLayout *srcLayout = &qPixelLayouts[data->format];
+ const QPixelLayout *destLayout = &qPixelLayouts[dst_format];
+
+ QImageData::ImageSizeParameters params = { data->bytes_per_line, data->nbytes };
+ if (data->depth != destDepth) {
+ params = QImageData::calculateImageParameters(data->width, data->height, destDepth);
+ if (!params.isValid())
+ return false;
+ }
+
+ FetchAndConvertPixelsFuncFP fetch = qFetchToRGBA32F[data->format];
+ ConvertAndStorePixelsFuncFP store = qStoreFromRGBA32F[dst_format];
+ if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
+ destLayout->hasAlphaChannel && !destLayout->premultiplied) {
+ // Avoid unnecessary premultiply and unpremultiply when converting between two unpremultiplied formats.
+ // This abuses the fact unpremultiplied formats are always before their premultiplied counterparts.
+ fetch = qFetchToRGBA32F[data->format + 1];
+ store = qStoreFromRGBA32F[dst_format + 1];
+ }
+
+ auto convertSegment = [=](int yStart, int yEnd) {
+ QRgba32F buf[BufferSize];
+ QRgba32F *buffer = buf;
+ uchar *srcData = data->data + yStart * data->bytes_per_line;
+ uchar *destData = srcData;
+ for (int y = yStart; y < yEnd; ++y) {
+ int x = 0;
+ while (x < data->width) {
+ int l = data->width - x;
+ if (srcLayout->bpp == QPixelLayout::BPP32FPx4)
+ buffer = reinterpret_cast<QRgba32F *>(srcData) + x;
+ else
+ l = qMin(l, BufferSize);
+ const QRgba32F *ptr = fetch(buffer, srcData, x, l, nullptr, nullptr);
+ store(destData, ptr, x, l, nullptr, nullptr);
+ x += l;
+ }
+ srcData += data->bytes_per_line;
+ destData += params.bytesPerLine;
+ }
+ };
+#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
+ int segments = (qsizetype(data->width) * data->height) >> 16;
+ segments = std::min(segments, data->height);
+ QThreadPool *threadPool = QThreadPool::globalInstance();
+ if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
+ QSemaphore semaphore;
+ int y = 0;
+ for (int i = 0; i < segments; ++i) {
+ int yn = (data->height - y) / (segments - i);
+ threadPool->start([&, y, yn]() {
+ convertSegment(y, y + yn);
+ semaphore.release(1);
+ });
+ y += yn;
+ }
+ semaphore.acquire(segments);
+ if (data->bytes_per_line != params.bytesPerLine) {
+ // Compress segments to a continuous block
+ y = 0;
+ for (int i = 0; i < segments; ++i) {
+ int yn = (data->height - y) / (segments - i);
+ uchar *srcData = data->data + data->bytes_per_line * y;
+ uchar *destData = data->data + params.bytesPerLine * y;
+ if (srcData != destData)
+ memmove(destData, srcData, params.bytesPerLine * yn);
+ y += yn;
+ }
+ }
+ } else
+#endif
+ convertSegment(0, data->height);
+ if (params.totalSize != data->nbytes) {
+ Q_ASSERT(params.totalSize < data->nbytes);
+ void *newData = realloc(data->data, params.totalSize);
+ if (newData) {
+ data->data = (uchar *)newData;
+ data->nbytes = params.totalSize;
+ }
+ data->bytes_per_line = params.bytesPerLine;
+ }
+ data->depth = destDepth;
+ data->format = dst_format;
+ return true;
+}
+#endif
+
static void convert_passthrough(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
Q_ASSERT(src->width == dest->width);
@@ -1284,10 +1437,120 @@ static void convert_gray16_to_RGBA64(QImageData *dest, const QImageData *src, Qt
}
}
+template<bool Premultiplied>
+static void convert_ARGB_to_gray8(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(dest->format == QImage::Format_Grayscale8);
+ Q_ASSERT(src->format == QImage::Format_RGB32 ||
+ src->format == QImage::Format_ARGB32 ||
+ src->format == QImage::Format_ARGB32_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const qsizetype sbpl = src->bytes_per_line;
+ const qsizetype dbpl = dest->bytes_per_line;
+ const uchar *src_data = src->data;
+ uchar *dest_data = dest->data;
+
+ QColorSpace fromCS = src->colorSpace.isValid() ? src->colorSpace : QColorSpace::SRgb;
+ QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
+ QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+ QColorTransformPrivate::TransformFlags flags = Premultiplied
+ ? QColorTransformPrivate::InputPremultiplied
+ : QColorTransformPrivate::Unpremultiplied;
+
+ for (int i = 0; i < src->height; ++i) {
+ const QRgb *src_line = reinterpret_cast<const QRgb *>(src_data);
+ tfd->apply(dest_data, src_line, src->width, flags);
+ src_data += sbpl;
+ dest_data += dbpl;
+ }
+}
+
+template<bool Premultiplied>
+static void convert_ARGB_to_gray16(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(dest->format == QImage::Format_Grayscale16);
+ Q_ASSERT(src->format == QImage::Format_RGB32 ||
+ src->format == QImage::Format_ARGB32 ||
+ src->format == QImage::Format_ARGB32_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const qsizetype sbpl = src->bytes_per_line;
+ const qsizetype dbpl = dest->bytes_per_line;
+ const uchar *src_data = src->data;
+ uchar *dest_data = dest->data;
+
+ QColorSpace fromCS = src->colorSpace.isValid() ? src->colorSpace : QColorSpace::SRgb;
+ QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
+ QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+ QColorTransformPrivate::TransformFlags flags = Premultiplied
+ ? QColorTransformPrivate::InputPremultiplied
+ : QColorTransformPrivate::Unpremultiplied;
+
+ QRgba64 tmp_line[BufferSize];
+ for (int i = 0; i < src->height; ++i) {
+ const QRgb *src_line = reinterpret_cast<const QRgb *>(src_data);
+ quint16 *dest_line = reinterpret_cast<quint16 *>(dest_data);
+ int j = 0;
+ while (j < src->width) {
+ const int len = std::min(src->width - j, BufferSize);
+ for (int k = 0; k < len; ++k)
+ tmp_line[k] = QRgba64::fromArgb32(src_line[j + k]);
+ tfd->apply(dest_line + j, tmp_line, len, flags);
+ j += len;
+ }
+ src_data += sbpl;
+ dest_data += dbpl;
+ }
+}
+
+template<bool Premultiplied>
+static void convert_RGBA64_to_gray8(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(dest->format == QImage::Format_Grayscale8);
+ Q_ASSERT(src->format == QImage::Format_RGBX64 ||
+ src->format == QImage::Format_RGBA64 ||
+ src->format == QImage::Format_RGBA64_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const qsizetype sbpl = src->bytes_per_line;
+ const qsizetype dbpl = dest->bytes_per_line;
+ const uchar *src_data = src->data;
+ uchar *dest_data = dest->data;
+
+ QColorSpace fromCS = src->colorSpace.isValid() ? src->colorSpace : QColorSpace::SRgb;
+ QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
+ QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+ QColorTransformPrivate::TransformFlags flags = Premultiplied
+ ? QColorTransformPrivate::InputPremultiplied
+ : QColorTransformPrivate::Unpremultiplied;
+
+ quint16 gray_line[BufferSize];
+ for (int i = 0; i < src->height; ++i) {
+ const QRgba64 *src_line = reinterpret_cast<const QRgba64 *>(src_data);
+ uchar *dest_line = dest_data;
+ int j = 0;
+ while (j < src->width) {
+ const int len = std::min(src->width - j, BufferSize);
+ tfd->apply(gray_line, src_line + j, len, flags);
+ for (int k = 0; k < len; ++k)
+ dest_line[j + k] = qt_div_257(gray_line[k]);
+ j += len;
+ }
+ src_data += sbpl;
+ dest_data += dbpl;
+ }
+}
+
+template<bool Premultiplied>
static void convert_RGBA64_to_gray16(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
Q_ASSERT(dest->format == QImage::Format_Grayscale16);
Q_ASSERT(src->format == QImage::Format_RGBX64 ||
+ src->format == QImage::Format_RGBA64 ||
src->format == QImage::Format_RGBA64_Premultiplied);
Q_ASSERT(src->width == dest->width);
Q_ASSERT(src->height == dest->height);
@@ -1297,18 +1560,71 @@ static void convert_RGBA64_to_gray16(QImageData *dest, const QImageData *src, Qt
const uchar *src_data = src->data;
uchar *dest_data = dest->data;
+ QColorSpace fromCS = src->colorSpace.isValid() ? src->colorSpace : QColorSpace::SRgb;
+ QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
+ QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+ QColorTransformPrivate::TransformFlags flags = Premultiplied
+ ? QColorTransformPrivate::InputPremultiplied
+ : QColorTransformPrivate::Unpremultiplied;
+
for (int i = 0; i < src->height; ++i) {
const QRgba64 *src_line = reinterpret_cast<const QRgba64 *>(src_data);
quint16 *dest_line = reinterpret_cast<quint16 *>(dest_data);
- for (int j = 0; j < src->width; ++j) {
- QRgba64 s = src_line[j].unpremultiplied();
- dest_line[j] = qGray(s.red(), s.green(), s.blue());
- }
+ tfd->apply(dest_line, src_line, src->width, flags);
src_data += sbpl;
dest_data += dbpl;
}
}
+template<bool MaskAlpha>
+static void convert_RGBA16FPM_to_RGBA16F(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_RGBA16FPx4_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_RGBA16FPx4 || dest->format == QImage::Format_RGBX16FPx4);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 3) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 3) - dest->width;
+ const QRgba16F *src_data = reinterpret_cast<const QRgba16F *>(src->data);
+ QRgba16F *dest_data = reinterpret_cast<QRgba16F *>(dest->data);
+
+ for (int i = 0; i < src->height; ++i) {
+ const QRgba16F *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = src_data->unpremultiplied();
+ if (MaskAlpha)
+ dest_data->setAlpha(1.0f);
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+template<bool MaskAlpha>
+static bool convert_RGBA16FPM_to_RGBA16F_inplace(QImageData *data, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(data->format == QImage::Format_RGBA16FPx4_Premultiplied);
+
+ const int pad = (data->bytes_per_line >> 3) - data->width;
+ QRgba16F *rgb_data = reinterpret_cast<QRgba16F *>(data->data);
+
+ for (int i = 0; i < data->height; ++i) {
+ const QRgba16F *end = rgb_data + data->width;
+ while (rgb_data < end) {
+ *rgb_data = rgb_data->unpremultiplied();
+ if (MaskAlpha)
+ rgb_data->setAlpha(1.0f);
+ ++rgb_data;
+ }
+ rgb_data += pad;
+ }
+ data->format = MaskAlpha ? QImage::Format_RGBX16FPx4 : QImage::Format_RGBA16FPx4;
+ return true;
+}
+
static QList<QRgb> fix_color_table(const QList<QRgb> &ctbl, QImage::Format format)
{
QList<QRgb> colorTable = ctbl;
@@ -2072,23 +2388,29 @@ static void convert_Indexed8_to_Grayscale8(QImageData *dest, const QImageData *s
uchar translate[256];
const QList<QRgb> &colors = src->colortable;
bool simpleCase = (colors.size() == 256);
+ for (int i = 0; i < colors.size() && simpleCase; ++i) {
+ if (colors[i] != qRgb(i, i, i))
+ simpleCase = false;
+ }
+ if (simpleCase) {
+ copy_8bit_pixels(dest, src);
+ return;
+ }
+
+ QColorSpace fromCS = src->colorSpace.isValid() ? src->colorSpace : QColorSpace::SRgb;
+ QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
for (int i = 0; i < colors.size(); ++i) {
- uchar gray = qGray(colors[i]);
- translate[i] = gray;
- simpleCase = simpleCase && (gray == i);
+ QRgba64 c16 = tf.map(QRgba64::fromArgb32(colors[i]));
+ translate[i] = c16.green8(); // Y from XYZ ends up in the G channel
}
- if (simpleCase)
- copy_8bit_pixels(dest, src);
- else {
- const uchar *sdata = src->data;
- uchar *ddata = dest->data;
- for (int y = 0; y < src->height; ++y) {
- for (int x = 0; x < src->width; ++x)
- ddata[x] = translate[sdata[x]];
- sdata += src->bytes_per_line;
- ddata += dest->bytes_per_line;
- }
+ const uchar *sdata = src->data;
+ uchar *ddata = dest->data;
+ for (int y = 0; y < src->height; ++y) {
+ for (int x = 0; x < src->width; ++x)
+ ddata[x] = translate[sdata[x]];
+ sdata += src->bytes_per_line;
+ ddata += dest->bytes_per_line;
}
}
@@ -2120,7 +2442,7 @@ static bool convert_Indexed8_to_Grayscale8_inplace(QImageData *data, Qt::ImageCo
if (colors.size() != 256)
return false;
for (int i = 0; i < colors.size(); ++i) {
- if (i != qGray(colors[i]))
+ if (colors[i] != qRgb(i, i, i))
return false;
}
@@ -2206,6 +2528,8 @@ static void qInitImageConversions()
qimage_converter_map[QImage::Format_RGB32][QImage::Format_Indexed8] = convert_RGB_to_Indexed8;
qimage_converter_map[QImage::Format_RGB32][QImage::Format_ARGB32] = mask_alpha_converter;
qimage_converter_map[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = mask_alpha_converter;
+ qimage_converter_map[QImage::Format_RGB32][QImage::Format_Grayscale8] = convert_ARGB_to_gray8<false>;
+ qimage_converter_map[QImage::Format_RGB32][QImage::Format_Grayscale16] = convert_ARGB_to_gray16<false>;
qimage_converter_map[QImage::Format_ARGB32][QImage::Format_Mono] = convert_X_to_Mono;
qimage_converter_map[QImage::Format_ARGB32][QImage::Format_MonoLSB] = convert_X_to_Mono;
@@ -2217,11 +2541,15 @@ static void qInitImageConversions()
qimage_converter_map[QImage::Format_ARGB32][QImage::Format_A2BGR30_Premultiplied] = convert_ARGB_to_A2RGB30<PixelOrderBGR, false>;
qimage_converter_map[QImage::Format_ARGB32][QImage::Format_A2RGB30_Premultiplied] = convert_ARGB_to_A2RGB30<PixelOrderRGB, false>;
qimage_converter_map[QImage::Format_ARGB32][QImage::Format_RGBA64] = convert_ARGB32_to_RGBA64<false>;
+ qimage_converter_map[QImage::Format_ARGB32][QImage::Format_Grayscale8] = convert_ARGB_to_gray8<false>;
+ qimage_converter_map[QImage::Format_ARGB32][QImage::Format_Grayscale16] = convert_ARGB_to_gray16<false>;
qimage_converter_map[QImage::Format_ARGB32_Premultiplied][QImage::Format_Mono] = convert_ARGB_PM_to_Mono;
qimage_converter_map[QImage::Format_ARGB32_Premultiplied][QImage::Format_MonoLSB] = convert_ARGB_PM_to_Mono;
qimage_converter_map[QImage::Format_ARGB32_Premultiplied][QImage::Format_Indexed8] = convert_ARGB_PM_to_Indexed8;
qimage_converter_map[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = convert_ARGB_to_RGBA;
+ qimage_converter_map[QImage::Format_ARGB32_Premultiplied][QImage::Format_Grayscale8] = convert_ARGB_to_gray8<true>;
+ qimage_converter_map[QImage::Format_ARGB32_Premultiplied][QImage::Format_Grayscale16] = convert_ARGB_to_gray16<true>;
qimage_converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB<false>;
qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB<false>;
@@ -2271,13 +2599,17 @@ static void qInitImageConversions()
qimage_converter_map[QImage::Format_RGBX64][QImage::Format_RGBA64] = convert_passthrough;
qimage_converter_map[QImage::Format_RGBX64][QImage::Format_RGBA64_Premultiplied] = convert_passthrough;
- qimage_converter_map[QImage::Format_RGBX64][QImage::Format_Grayscale16] = convert_RGBA64_to_gray16;
+ qimage_converter_map[QImage::Format_RGBX64][QImage::Format_Grayscale8] = convert_RGBA64_to_gray8<false>;
+ qimage_converter_map[QImage::Format_RGBX64][QImage::Format_Grayscale16] = convert_RGBA64_to_gray16<false>;
qimage_converter_map[QImage::Format_RGBA64][QImage::Format_ARGB32] = convert_RGBA64_to_ARGB32<false>;
qimage_converter_map[QImage::Format_RGBA64][QImage::Format_RGBA8888] = convert_RGBA64_to_ARGB32<true>;
qimage_converter_map[QImage::Format_RGBA64][QImage::Format_RGBX64] = convert_RGBA64_to_RGBx64;
+ qimage_converter_map[QImage::Format_RGBA64][QImage::Format_Grayscale8] = convert_RGBA64_to_gray8<false>;
+ qimage_converter_map[QImage::Format_RGBA64][QImage::Format_Grayscale16] = convert_RGBA64_to_gray16<false>;
- qimage_converter_map[QImage::Format_RGBA64_Premultiplied][QImage::Format_Grayscale16] = convert_RGBA64_to_gray16;
+ qimage_converter_map[QImage::Format_RGBA64_Premultiplied][QImage::Format_Grayscale8] = convert_RGBA64_to_gray8<true>;
+ qimage_converter_map[QImage::Format_RGBA64_Premultiplied][QImage::Format_Grayscale16] = convert_RGBA64_to_gray16<true>;
qimage_converter_map[QImage::Format_Grayscale16][QImage::Format_RGBX64] = convert_gray16_to_RGBA64;
qimage_converter_map[QImage::Format_Grayscale16][QImage::Format_RGBA64] = convert_gray16_to_RGBA64;
@@ -2290,6 +2622,12 @@ static void qInitImageConversions()
qimage_converter_map[QImage::Format_BGR888][QImage::Format_RGBA8888_Premultiplied] = convert_RGB888_to_RGB<false>;
#endif
+ qimage_converter_map[QImage::Format_RGBX16FPx4][QImage::Format_RGBA16FPx4] = convert_passthrough;
+ qimage_converter_map[QImage::Format_RGBX16FPx4][QImage::Format_RGBA16FPx4_Premultiplied] = convert_passthrough;
+
+ qimage_converter_map[QImage::Format_RGBX32FPx4][QImage::Format_RGBA32FPx4] = convert_passthrough;
+ qimage_converter_map[QImage::Format_RGBX32FPx4][QImage::Format_RGBA32FPx4_Premultiplied] = convert_passthrough;
+
// Inline converters:
qimage_inplace_converter_map[QImage::Format_Indexed8][QImage::Format_Grayscale8] =
convert_Indexed8_to_Grayscale8_inplace;
@@ -2395,6 +2733,16 @@ static void qInitImageConversions()
qimage_inplace_converter_map[QImage::Format_BGR888][QImage::Format_RGB888] =
convert_rgbswap_generic_inplace;
+ qimage_inplace_converter_map[QImage::Format_RGBX16FPx4][QImage::Format_RGBA16FPx4] =
+ convert_passthrough_inplace<QImage::Format_RGBA16FPx4>;
+ qimage_inplace_converter_map[QImage::Format_RGBX16FPx4][QImage::Format_RGBA16FPx4_Premultiplied] =
+ convert_passthrough_inplace<QImage::Format_RGBA16FPx4_Premultiplied>;
+
+ qimage_inplace_converter_map[QImage::Format_RGBX32FPx4][QImage::Format_RGBA32FPx4] =
+ convert_passthrough_inplace<QImage::Format_RGBA32FPx4>;
+ qimage_inplace_converter_map[QImage::Format_RGBX32FPx4][QImage::Format_RGBA32FPx4_Premultiplied] =
+ convert_passthrough_inplace<QImage::Format_RGBA32FPx4_Premultiplied>;
+
// Now architecture specific conversions:
#if defined(__SSE2__) && defined(QT_COMPILER_SUPPORTS_SSSE3)
if (qCpuHasFeature(SSSE3)) {
diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h
index 64f5be9e76..a2c50adc43 100644
--- a/src/gui/image/qimage_p.h
+++ b/src/gui/image/qimage_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -161,6 +161,10 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
void convert_generic_over_rgb64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags);
bool convert_generic_inplace_over_rgb64(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags);
+#if QT_CONFIG(raster_fp)
+void convert_generic_over_rgba32f(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
+bool convert_generic_inplace_over_rgba32f(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags);
+#endif
void dither_to_Mono(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags, bool fromalpha);
@@ -216,8 +220,16 @@ inline int qt_depthForFormat(QImage::Format format)
case QImage::Format_RGBX64:
case QImage::Format_RGBA64:
case QImage::Format_RGBA64_Premultiplied:
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
depth = 64;
break;
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+ depth = 128;
+ break;
}
return depth;
}
@@ -247,6 +259,12 @@ inline QImage::Format qt_opaqueVersion(QImage::Format format)
case QImage::Format_RGBA64:
case QImage::Format_RGBA64_Premultiplied:
return QImage::Format_RGBX64;
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ return QImage::Format_RGBX16FPx4;
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+ return QImage::Format_RGBX32FPx4;
case QImage::Format_ARGB32_Premultiplied:
case QImage::Format_ARGB32:
return QImage::Format_RGB32;
@@ -261,6 +279,8 @@ inline QImage::Format qt_opaqueVersion(QImage::Format format)
case QImage::Format_BGR30:
case QImage::Format_RGB30:
case QImage::Format_RGBX64:
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBX32FPx4:
case QImage::Format_Grayscale8:
case QImage::Format_Grayscale16:
return format;
@@ -300,6 +320,12 @@ inline QImage::Format qt_alphaVersion(QImage::Format format)
case QImage::Format_RGBA64:
case QImage::Format_Grayscale16:
return QImage::Format_RGBA64_Premultiplied;
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBA16FPx4:
+ return QImage::Format_RGBA16FPx4_Premultiplied;
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4:
+ return QImage::Format_RGBA32FPx4_Premultiplied;
case QImage::Format_ARGB32_Premultiplied:
case QImage::Format_ARGB8565_Premultiplied:
case QImage::Format_ARGB8555_Premultiplied:
@@ -309,6 +335,8 @@ inline QImage::Format qt_alphaVersion(QImage::Format format)
case QImage::Format_A2BGR30_Premultiplied:
case QImage::Format_A2RGB30_Premultiplied:
case QImage::Format_RGBA64_Premultiplied:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
return format;
case QImage::Format_Mono:
case QImage::Format_MonoLSB:
@@ -339,6 +367,12 @@ inline bool qt_highColorPrecision(QImage::Format format, bool opaque = false)
case QImage::Format_RGBA64:
case QImage::Format_RGBA64_Premultiplied:
case QImage::Format_Grayscale16:
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
return true;
default:
break;
@@ -346,6 +380,21 @@ inline bool qt_highColorPrecision(QImage::Format format, bool opaque = false)
return false;
}
+inline bool qt_fpColorPrecision(QImage::Format format)
+{
+ switch (format) {
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
inline QImage::Format qt_maybeAlphaVersionWithSameDepth(QImage::Format format)
{
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index 9943e7261a..c013a06813 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -627,10 +627,10 @@ bool QPngHandlerPrivate::readPngHeader()
}
if (primaries.areValid()) {
colorSpace = QColorSpace(primaries.whitePoint, primaries.redPoint, primaries.greenPoint, primaries.bluePoint,
- QColorSpace::TransferFunction::Gamma, fileGamma);
+ QColorSpace::TransferFunction::Gamma, 1.0f / fileGamma);
} else {
colorSpace = QColorSpace(QColorSpace::Primaries::SRgb,
- QColorSpace::TransferFunction::Gamma, fileGamma);
+ QColorSpace::TransferFunction::Gamma, 1.0f / fileGamma);
}
colorSpaceState = GammaChrm;
}
diff --git a/src/gui/itemmodels/qfilesystemmodel.cpp b/src/gui/itemmodels/qfilesystemmodel.cpp
index 70c274b816..e0274e5fef 100644
--- a/src/gui/itemmodels/qfilesystemmodel.cpp
+++ b/src/gui/itemmodels/qfilesystemmodel.cpp
@@ -391,8 +391,11 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
if (absolutePath.endsWith(QLatin1Char('/')))
trailingSeparator = QLatin1String("\\");
int r = 0;
- QFileSystemModelPrivate::QFileSystemNode *rootNode = const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);
- if (!root.children.contains(host.toLower())) {
+ auto rootNode = const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);
+ auto it = root.children.constFind(host);
+ if (it != root.children.cend()) {
+ host = it.key(); // Normalize case for lookup in visibleLocation()
+ } else {
if (pathElements.count() == 1 && !absolutePath.endsWith(QLatin1Char('/')))
return rootNode;
QFileInfo info(host);
diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp
index f16cf5d1b7..9c16123545 100644
--- a/src/gui/kernel/qaction.cpp
+++ b/src/gui/kernel/qaction.cpp
@@ -548,14 +548,14 @@ QList<QObject*> QAction::associatedObjects() const
/*!
\fn QWidget *QAction::parentWidget() const
- \obsolete Use parent() with qobject_cast() instead.
+ \deprecated Use parent() with qobject_cast() instead.
Returns the parent widget.
*/
/*!
\fn QList<QWidget*> QAction::associatedWidgets() const
- \obsolete Use associatedObjects() with qobject_cast() instead.
+ \deprecated Use associatedObjects() with qobject_cast() instead.
Returns a list of widgets this action has been added to.
@@ -564,7 +564,7 @@ QList<QObject*> QAction::associatedObjects() const
/*!
\fn QList<QWidget*> QAction::associatedGraphicsWidgets() const
- \obsolete Use associatedObjects() with qobject_cast() instead.
+ \deprecated Use associatedObjects() with qobject_cast() instead.
Returns a list of graphics widgets this action has been added to.
@@ -1225,7 +1225,7 @@ QAction::MenuRole QAction::menuRole() const
/*!
\fn QMenu *QAction::menu() const
- \obsolete
+ \deprecated
Returns the menu contained by this action.
@@ -1242,7 +1242,7 @@ QObject* QAction::menuObject() const
/*!
\fn void QAction::setMenu(QMenu *menu)
- \obsolete
+ \deprecated
Sets the menu contained by this action to the specified \a menu.
*/
@@ -1301,8 +1301,7 @@ bool QAction::isIconVisibleInMenu() const
shown via a context menu, when it is false, it is not shown.
The default is to follow whether the Qt::AA_DontShowShortcutsInContextMenus attribute
- is set for the application, falling back to the widget style hint.
- Explicitly setting this property overrides the presence (or abscence) of the attribute.
+ is set for the application. Explicitly setting this property overrides the attribute.
\sa shortcut, QCoreApplication::setAttribute()
*/
@@ -1323,10 +1322,8 @@ void QAction::setShortcutVisibleInContextMenu(bool visible)
bool QAction::isShortcutVisibleInContextMenu() const
{
Q_D(const QAction);
- if (d->shortcutVisibleInContextMenu == -1) {
- return !QCoreApplication::testAttribute(Qt::AA_DontShowShortcutsInContextMenus)
- && QGuiApplication::styleHints()->showShortcutsInContextMenus();
- }
+ if (d->shortcutVisibleInContextMenu == -1)
+ return !QCoreApplication::testAttribute(Qt::AA_DontShowShortcutsInContextMenus);
return d->shortcutVisibleInContextMenu;
}
diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp
index 5dcb526847..20511ef8e6 100644
--- a/src/gui/kernel/qcursor.cpp
+++ b/src/gui/kernel/qcursor.cpp
@@ -565,7 +565,7 @@ void QCursor::setShape(Qt::CursorShape shape)
/*!
\fn QBitmap QCursor::bitmap(Qt::ReturnByValueConstant) const
\since 5.15
- \obsolete Use the overload without argument instead.
+ \deprecated Use the overload without argument instead.
Returns the cursor bitmap, or a null bitmap if it is one of the
standard cursors.
@@ -592,7 +592,7 @@ QBitmap QCursor::bitmap() const
/*!
\fn QBitmap QCursor::mask(Qt::ReturnByValueConstant) const
\since 5.15
- \obsolete Use the overload without argument instead.
+ \deprecated Use the overload without argument instead.
Returns the cursor bitmap mask, or a null bitmap if it is one of the
standard cursors.
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 858a7cba2e..14daf3089b 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -474,7 +474,7 @@ void QPointerEvent::clearPassiveGrabbers(const QEventPoint &point)
Returns the button state when the event was generated.
The button state is a combination of Qt::LeftButton, Qt::RightButton,
- and Qt::MidButton using the OR operator.
+ and Qt::MiddleButton using the OR operator.
For mouse move or \l TabletMove events, this is all buttons that are
pressed down.
@@ -2770,7 +2770,7 @@ QTabletEvent::~QTabletEvent()
*/
/*!
- \obsolete
+ \deprecated
Use the other constructor, because \a intValue is no longer stored separately.
Constructs a native gesture event of type \a type originating from \a device.
@@ -4166,7 +4166,7 @@ QT_WARNING_POP
const QNativeGestureEvent *ne = static_cast<const QNativeGestureEvent *>(e);
dbg << "QNativeGestureEvent(";
QtDebugUtils::formatQEnum(dbg, ne->gestureType());
- dbg << ", localPos=";
+ dbg << ", fingerCount=" << ne->fingerCount() << ", localPos=";
QtDebugUtils::formatQPoint(dbg, ne->position());
if (!qIsNull(ne->value()))
dbg << ", value=" << ne->value();
@@ -4462,7 +4462,7 @@ QTouchEvent::QTouchEvent(QEvent::Type eventType,
}
/*!
- \obsolete
+ \deprecated
Try to use another constructor, because \a touchPointStates
can be calculated from the given \a touchPoints.
@@ -4527,7 +4527,7 @@ bool QTouchEvent::isEndEvent() const
*/
/*! \fn const QList<QEventPoint> &QTouchEvent::touchPoints() const
- \obsolete
+ \deprecated
Deprecated since Qt 6.0. Use points() instead.
Returns a reference to the list of touch points contained in the touch event.
diff --git a/src/gui/kernel/qeventpoint.cpp b/src/gui/kernel/qeventpoint.cpp
index 41f8dd90a2..0c8428286a 100644
--- a/src/gui/kernel/qeventpoint.cpp
+++ b/src/gui/kernel/qeventpoint.cpp
@@ -142,7 +142,7 @@ bool QEventPoint::operator==(const QEventPoint &other) const noexcept
QEventPoint::~QEventPoint() = default;
/*! \fn QPointF QEventPoint::pos() const
- \obsolete
+ \deprecated
Deprecated since Qt 6.0. Use position() instead.
Returns the position of this point, relative to the widget
@@ -443,7 +443,7 @@ bool QEventPoint::isAccepted() const
/*!
- \obsolete
+ \deprecated
\fn QPointF QEventPoint::normalizedPos() const
Deprecated since Qt 6.0. Use normalizedPosition() instead.
@@ -470,7 +470,7 @@ QPointF QEventPoint::normalizedPosition() const
}
/*!
- \obsolete
+ \deprecated
Deprecated since Qt 6.0. Use globalPressPosition() instead.
Returns the normalized press position of this point.
@@ -487,7 +487,7 @@ QPointF QEventPoint::startNormalizedPos() const
}
/*!
- \obsolete
+ \deprecated
Deprecated since Qt 6.0. Use globalLastPosition() instead.
Returns the normalized position of this point from the previous press or
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 966a558304..101b33f94a 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -1295,7 +1295,10 @@ static void init_platform(const QString &pluginNamesWithArguments, const QString
}
#endif
- fontSmoothingGamma = QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::FontSmoothingGamma).toReal();
+ const auto platformIntegration = QGuiApplicationPrivate::platformIntegration();
+ fontSmoothingGamma = platformIntegration->styleHint(QPlatformIntegration::FontSmoothingGamma).toReal();
+ QCoreApplication::setAttribute(Qt::AA_DontShowShortcutsInContextMenus,
+ !platformIntegration->styleHint(QPlatformIntegration::ShowShortcutsInContextMenus).toBool());
}
static void init_plugins(const QList<QByteArray> &pluginList)
@@ -2169,7 +2172,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
processMouseEvent(e); // the original mouse event
return;
}
- if (mouseMove && !positionChanged) {
+ if (type == QEvent::MouseMove && !positionChanged) {
// On Windows, and possibly other platforms, a touchpad can send a mouse move
// that does not change position, between a press and a release. This may
// confuse applications, so we always filter out these mouse events for
@@ -3285,7 +3288,7 @@ QClipboard * QGuiApplication::clipboard()
/*!
\since 5.4
\fn void QGuiApplication::paletteChanged(const QPalette &palette)
- \obsolete
+ \deprecated
This signal is emitted when the \a palette of the application changes. Use
QEvent::ApplicationPaletteChanged instead.
@@ -3396,7 +3399,7 @@ void QGuiApplicationPrivate::applyWindowGeometrySpecificationTo(QWindow *window)
/*!
\since 5.11
\fn void QGuiApplication::fontChanged(const QFont &font)
- \obsolete
+ \deprecated
This signal is emitted when the \a font of the application changes. Use
QEvent::ApplicationFontChanged instead.
@@ -3475,8 +3478,16 @@ void QGuiApplicationPrivate::notifyLayoutDirectionChange()
}
}
-void QGuiApplicationPrivate::notifyActiveWindowChange(QWindow *)
+void QGuiApplicationPrivate::notifyActiveWindowChange(QWindow *prev)
{
+ if (prev) {
+ QEvent de(QEvent::WindowDeactivate);
+ QCoreApplication::sendEvent(prev, &de);
+ }
+ if (self->focus_window) {
+ QEvent ae(QEvent::WindowActivate);
+ QCoreApplication::sendEvent(focus_window, &ae);
+ }
}
/*!
@@ -4197,7 +4208,7 @@ QInputDeviceManager *QGuiApplicationPrivate::inputDeviceManager()
}
template <>
-Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QGuiApplication *that, const std::type_info &type, int revision)
+Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QGuiApplication *that, const char *name, int revision)
{
using namespace QNativeInterface::Private;
@@ -4208,7 +4219,7 @@ Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(cons
QT_NATIVE_INTERFACE_RETURN_IF(QWindowsApplication, platformIntegration);
#endif
- return resolveInterface<QCoreApplication>(that, type, revision);
+ return resolveInterface<QCoreApplication>(that, name, revision);
}
#include "moc_qguiapplication.cpp"
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index f6c8693206..70571cf751 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -53,6 +53,7 @@
#include <QtGui/private/qtguiglobal_p.h>
#include <QtGui/qguiapplication.h>
+#include <QtGui/qicon.h>
#include <QtCore/QPointF>
#include <QtCore/QSharedPointer>
@@ -67,8 +68,6 @@
# include "private/qshortcutmap_p.h"
#endif
-#include <qicon.h>
-
QT_BEGIN_NAMESPACE
class QColorTrcLut;
diff --git a/src/gui/kernel/qkeymapper.cpp b/src/gui/kernel/qkeymapper.cpp
index 3781330073..e3d39f80dc 100644
--- a/src/gui/kernel/qkeymapper.cpp
+++ b/src/gui/kernel/qkeymapper.cpp
@@ -136,9 +136,9 @@ QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent *e)
}
template <>
-Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QKeyMapper *that, const std::type_info &type, int revision)
+Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QKeyMapper *that, const char *name, int revision)
{
- Q_UNUSED(that); Q_UNUSED(type); Q_UNUSED(revision);
+ Q_UNUSED(that); Q_UNUSED(name); Q_UNUSED(revision);
using namespace QNativeInterface::Private;
#if QT_CONFIG(evdev)
diff --git a/src/gui/kernel/qoffscreensurface.cpp b/src/gui/kernel/qoffscreensurface.cpp
index 53c60b278e..7cb8050504 100644
--- a/src/gui/kernel/qoffscreensurface.cpp
+++ b/src/gui/kernel/qoffscreensurface.cpp
@@ -372,9 +372,9 @@ QPlatformSurface *QOffscreenSurface::surfaceHandle() const
using namespace QNativeInterface;
template <>
-Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QOffscreenSurface *that, const std::type_info &type, int revision)
+Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QOffscreenSurface *that, const char *name, int revision)
{
- Q_UNUSED(that); Q_UNUSED(type); Q_UNUSED(revision);
+ Q_UNUSED(that); Q_UNUSED(name); Q_UNUSED(revision);
auto *surfacePrivate = QOffscreenSurfacePrivate::get(const_cast<QOffscreenSurface*>(that));
Q_UNUSED(surfacePrivate);
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index 4a423e7ed5..eef85bf0d0 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -709,7 +709,8 @@ bool QOpenGLContext::makeCurrent(QSurface *surface)
|| qstrcmp(rendererString, "GC800 core") == 0
|| qstrcmp(rendererString, "GC1000 core") == 0
|| strstr(rendererString, "GC2000") != nullptr
- || qstrcmp(rendererString, "Immersion.16") == 0;
+ || qstrcmp(rendererString, "Immersion.16") == 0
+ || qstrncmp(rendererString, "Apple Mx", 7) == 0;
}
needsWorkaroundSet = true;
}
@@ -1312,9 +1313,9 @@ QDebug operator<<(QDebug debug, const QOpenGLContextGroup *cg)
using namespace QNativeInterface;
template <>
-Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QOpenGLContext *that, const std::type_info &type, int revision)
+Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QOpenGLContext *that, const char *name, int revision)
{
- Q_UNUSED(that); Q_UNUSED(type); Q_UNUSED(revision);
+ Q_UNUSED(that); Q_UNUSED(name); Q_UNUSED(revision);
auto *platformContext = that->handle();
Q_UNUSED(platformContext);
diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp
index 2cdc9fddc6..b313d545a5 100644
--- a/src/gui/kernel/qpalette.cpp
+++ b/src/gui/kernel/qpalette.cpp
@@ -52,7 +52,7 @@ static int qt_palette_count = 1;
static constexpr QPalette::ResolveMask colorRoleOffset(QPalette::ColorGroup colorGroup)
{
- return QPalette::NColorRoles * colorGroup;
+ return qToUnderlying(QPalette::NColorRoles) * qToUnderlying(colorGroup);
}
static constexpr QPalette::ResolveMask bitPosition(QPalette::ColorGroup colorGroup,
@@ -595,7 +595,8 @@ QPalette::QPalette(const QBrush &windowText, const QBrush &button,
}
-/*!\obsolete
+/*!
+ \deprecated
Constructs a palette with the specified \a windowText, \a
window, \a light, \a dark, \a mid, \a text, and \a base colors.
diff --git a/src/gui/kernel/qplatformscreen_p.h b/src/gui/kernel/qplatformscreen_p.h
index bd149ccbac..35097b5d23 100644
--- a/src/gui/kernel/qplatformscreen_p.h
+++ b/src/gui/kernel/qplatformscreen_p.h
@@ -73,7 +73,7 @@ namespace QNativeInterface::Private {
#if QT_CONFIG(xcb) || defined(Q_CLANG_QDOC)
struct Q_GUI_EXPORT QXcbScreen
{
- QT_DECLARE_NATIVE_INTERFACE(QXcbScreen)
+ QT_DECLARE_NATIVE_INTERFACE(QXcbScreen, 1, QScreen)
virtual int virtualDesktopNumber() const = 0;
};
#endif
@@ -81,7 +81,7 @@ struct Q_GUI_EXPORT QXcbScreen
#if QT_CONFIG(vsp2) || defined(Q_CLANG_QDOC)
struct Q_GUI_EXPORT QVsp2Screen
{
- QT_DECLARE_NATIVE_INTERFACE(QVsp2Screen)
+ QT_DECLARE_NATIVE_INTERFACE(QVsp2Screen, 1, QScreen)
virtual int addLayer(int dmabufFd, const QSize &size, const QPoint &position, uint drmPixelFormat, uint bytesPerLine) = 0;
virtual void setLayerBuffer(int id, int dmabufFd) = 0;
virtual void setLayerPosition(int id, const QPoint &position) = 0;
@@ -91,6 +91,19 @@ struct Q_GUI_EXPORT QVsp2Screen
};
#endif
+#if defined(Q_OS_WEBOS) || defined(Q_CLANG_QDOC)
+struct Q_GUI_EXPORT QWebOSScreen
+{
+ QT_DECLARE_NATIVE_INTERFACE(QWebOSScreen, 1, QScreen)
+ virtual int addLayer(void *gbm_bo, const QRectF &geometry) = 0;
+ virtual void setLayerBuffer(int id, void *gbm_bo) = 0;
+ virtual void setLayerGeometry(int id, const QRectF &geometry) = 0;
+ virtual void setLayerAlpha(int id, qreal alpha) = 0;
+ virtual bool removeLayer(int id) = 0;
+ virtual void addFlipListener(void (*callback)()) = 0;
+};
+#endif
+
} // QNativeInterface::Private
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformwindow_p.h b/src/gui/kernel/qplatformwindow_p.h
index 22431e8d79..e35f527921 100644
--- a/src/gui/kernel/qplatformwindow_p.h
+++ b/src/gui/kernel/qplatformwindow_p.h
@@ -74,7 +74,7 @@ namespace QNativeInterface::Private {
#if defined(Q_OS_MACOS) || defined(Q_CLANG_QDOC)
struct Q_GUI_EXPORT QCocoaWindow
{
- QT_DECLARE_NATIVE_INTERFACE(QCocoaWindow)
+ QT_DECLARE_NATIVE_INTERFACE(QCocoaWindow, 1, QWindow)
virtual void setContentBorderEnabled(bool enable) = 0;
virtual QPoint bottomLeftClippedByNSWindowOffset() const = 0;
};
@@ -83,7 +83,7 @@ struct Q_GUI_EXPORT QCocoaWindow
#if QT_CONFIG(xcb) || defined(Q_CLANG_QDOC)
struct Q_GUI_EXPORT QXcbWindow
{
- QT_DECLARE_NATIVE_INTERFACE(QXcbWindow)
+ QT_DECLARE_NATIVE_INTERFACE(QXcbWindow, 1, QWindow)
enum WindowType {
None = 0x000000,
@@ -115,7 +115,7 @@ struct Q_GUI_EXPORT QXcbWindow
#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
struct Q_GUI_EXPORT QWindowsWindow
{
- QT_DECLARE_NATIVE_INTERFACE(QWindowsWindow)
+ QT_DECLARE_NATIVE_INTERFACE(QWindowsWindow, 1, QWindow)
virtual void setHasBorderInFullScreen(bool border) = 0;
virtual bool hasBorderInFullScreen() const = 0;
diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp
index b978638782..6f9f48d6c4 100644
--- a/src/gui/kernel/qscreen.cpp
+++ b/src/gui/kernel/qscreen.cpp
@@ -786,6 +786,31 @@ QPixmap QScreen::grabWindow(WId window, int x, int y, int width, int height)
return result;
}
+template <>
+Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QScreen *that, const char *name, int revision)
+{
+ using namespace QNativeInterface::Private;
+
+ auto *platformScreen = that->handle();
+ Q_UNUSED(platformScreen);
+ Q_UNUSED(name);
+ Q_UNUSED(revision);
+
+#if QT_CONFIG(xcb)
+ QT_NATIVE_INTERFACE_RETURN_IF(QXcbScreen, platformScreen);
+#endif
+
+#if QT_CONFIG(vsp2)
+ QT_NATIVE_INTERFACE_RETURN_IF(QVsp2Screen, platformScreen);
+#endif
+
+#if defined(Q_OS_WEBOS)
+ QT_NATIVE_INTERFACE_RETURN_IF(QWebOSScreen, platformScreen);
+#endif
+
+ return nullptr;
+}
+
#ifndef QT_NO_DEBUG_STREAM
static inline void formatRect(QDebug &debug, const QRect r)
diff --git a/src/gui/kernel/qscreen.h b/src/gui/kernel/qscreen.h
index 1bff3f4ec1..98271c0aa0 100644
--- a/src/gui/kernel/qscreen.h
+++ b/src/gui/kernel/qscreen.h
@@ -50,6 +50,7 @@
#include <QtGui/QTransform>
#include <QtCore/qnamespace.h>
+#include <QtCore/qnativeinterface.h>
QT_BEGIN_NAMESPACE
@@ -148,6 +149,8 @@ public:
qreal refreshRate() const;
+ QT_DECLARE_NATIVE_INTERFACE_ACCESSOR
+
Q_SIGNALS:
void geometryChanged(const QRect &geometry);
void availableGeometryChanged(const QRect &geometry);
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index bacc49a98e..61c201559a 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -69,6 +69,7 @@
#include <QStyleHints>
#include <qpa/qplatformcursor.h>
+#include <qpa/qplatformwindow_p.h>
QT_BEGIN_NAMESPACE
@@ -3003,6 +3004,31 @@ bool QWindowPrivate::applyCursor()
}
#endif // QT_NO_CURSOR
+template <>
+Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QWindow *that, const char *name, int revision)
+{
+ using namespace QNativeInterface::Private;
+
+ auto *platformWindow = that->handle();
+ Q_UNUSED(platformWindow);
+ Q_UNUSED(name);
+ Q_UNUSED(revision);
+
+#if defined(Q_OS_WIN)
+ QT_NATIVE_INTERFACE_RETURN_IF(QWindowsWindow, platformWindow);
+#endif
+
+#if QT_CONFIG(xcb)
+ QT_NATIVE_INTERFACE_RETURN_IF(QXcbWindow, platformWindow);
+#endif
+
+#if defined(Q_OS_MACOS)
+ QT_NATIVE_INTERFACE_RETURN_IF(QCocoaWindow, platformWindow);
+#endif
+
+ return nullptr;
+}
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QWindow *window)
{
diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h
index 14d8ba1810..6200727789 100644
--- a/src/gui/kernel/qwindow.h
+++ b/src/gui/kernel/qwindow.h
@@ -47,6 +47,7 @@
#include <QtCore/QRect>
#include <QtCore/qnamespace.h>
+#include <QtCore/qnativeinterface.h>
#include <QtGui/qsurface.h>
#include <QtGui/qsurfaceformat.h>
@@ -283,6 +284,8 @@ public:
QVulkanInstance *vulkanInstance() const;
#endif
+ QT_DECLARE_NATIVE_INTERFACE_ACCESSOR
+
public Q_SLOTS:
Q_REVISION(2, 1) void requestActivate();
diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp
index 76348144ff..752b4944d0 100644
--- a/src/gui/math3d/qmatrix4x4.cpp
+++ b/src/gui/math3d/qmatrix4x4.cpp
@@ -633,7 +633,7 @@ QMatrix4x4& QMatrix4x4::operator/=(float divisor)
\fn QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix)
\relates QMatrix4x4
- \obsolete Convert the QVector3D to a QVector4D first, then multiply.
+ \deprecated Convert the QVector3D to a QVector4D first, then multiply.
Returns the result of transforming \a vector according to \a matrix,
with the matrix applied post-vector. The vector is transformed as a point.
@@ -643,7 +643,7 @@ QMatrix4x4& QMatrix4x4::operator/=(float divisor)
\fn QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector)
\relates QMatrix4x4
- \obsolete Use QMatrix4x4::map() or QMatrix4x4::mapVector() instead.
+ \deprecated Use QMatrix4x4::map() or QMatrix4x4::mapVector() instead.
Returns the result of transforming \a vector according to \a matrix,
with the matrix applied pre-vector. The vector is transformed as a
@@ -696,7 +696,7 @@ QMatrix4x4& QMatrix4x4::operator/=(float divisor)
\fn QPoint operator*(const QMatrix4x4& matrix, const QPoint& point)
\relates QMatrix4x4
- \obsolete Use QMatrix4x4::map() instead.
+ \deprecated Use QMatrix4x4::map() instead.
Returns the result of transforming \a point according to \a matrix,
with the matrix applied pre-point.
@@ -706,7 +706,7 @@ QMatrix4x4& QMatrix4x4::operator/=(float divisor)
\fn QPointF operator*(const QMatrix4x4& matrix, const QPointF& point)
\relates QMatrix4x4
- \obsolete Use QMatrix4x4::map() instead.
+ \deprecated Use QMatrix4x4::map() instead.
Returns the result of transforming \a point according to \a matrix,
with the matrix applied pre-point.
diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp
index 48e12f12fe..ba82aaa737 100644
--- a/src/gui/math3d/qquaternion.cpp
+++ b/src/gui/math3d/qquaternion.cpp
@@ -511,7 +511,11 @@ void QQuaternion::getEulerAngles(float *pitch, float *yaw, float *roll) const
const float zz = zps * zps;
const float zw = zps * wps;
- *pitch = std::asin(-2.0f * (yz - xw));
+ const float sinp = -2.0f * (yz - xw);
+ if (std::abs(sinp) >= 1.0f)
+ *pitch = std::copysign(M_PI_2, sinp);
+ else
+ *pitch = std::asin(sinp);
if (*pitch < M_PI_2) {
if (*pitch > -M_PI_2) {
*yaw = std::atan2(2.0f * (xz + yw), 1.0f - 2.0f * (xx + yy));
diff --git a/src/gui/painting/qcolorspace.cpp b/src/gui/painting/qcolorspace.cpp
index e770d929d3..9007b66601 100644
--- a/src/gui/painting/qcolorspace.cpp
+++ b/src/gui/painting/qcolorspace.cpp
@@ -454,6 +454,17 @@ QColorTransform QColorSpacePrivate::transformationToColorSpace(const QColorSpace
return combined;
}
+QColorTransform QColorSpacePrivate::transformationToXYZ() const
+{
+ QColorTransform transform;
+ auto ptr = new QColorTransformPrivate;
+ transform.d = ptr;
+ ptr->colorSpaceIn = this;
+ ptr->colorSpaceOut = this;
+ ptr->colorMatrix = toXyz;
+ return transform;
+}
+
/*!
\class QColorSpace
\brief The QColorSpace class provides a color space abstraction.
diff --git a/src/gui/painting/qcolorspace_p.h b/src/gui/painting/qcolorspace_p.h
index b5e5263cae..79b1774d0b 100644
--- a/src/gui/painting/qcolorspace_p.h
+++ b/src/gui/painting/qcolorspace_p.h
@@ -120,6 +120,7 @@ public:
const QList<uint16_t> &greenTransferFunctionTable,
const QList<uint16_t> &blueTransferFunctionTable);
QColorTransform transformationToColorSpace(const QColorSpacePrivate *out) const;
+ QColorTransform transformationToXYZ() const;
static constexpr QColorSpace::NamedColorSpace Unknown = QColorSpace::NamedColorSpace(0);
QColorSpace::NamedColorSpace namedColorSpace = Unknown;
diff --git a/src/gui/painting/qcolortransform.cpp b/src/gui/painting/qcolortransform.cpp
index 013abf769a..f1f8019a15 100644
--- a/src/gui/painting/qcolortransform.cpp
+++ b/src/gui/painting/qcolortransform.cpp
@@ -271,6 +271,24 @@ static void applyMatrix(QColorVector *buffer, const qsizetype len, const QColorM
cx = _mm_max_ps(cx, minV);
_mm_storeu_ps(&buffer[j].x, cx);
}
+#elif defined(__ARM_NEON__)
+ const float32x4_t minV = vdupq_n_f32(0.0f);
+ const float32x4_t maxV = vdupq_n_f32(1.0f);
+ const float32x4_t xMat = vld1q_f32(&colorMatrix.r.x);
+ const float32x4_t yMat = vld1q_f32(&colorMatrix.g.x);
+ const float32x4_t zMat = vld1q_f32(&colorMatrix.b.x);
+ for (qsizetype j = 0; j < len; ++j) {
+ float32x4_t c = vld1q_f32(&buffer[j].x);
+ float32x4_t cx = vmulq_n_f32(xMat, vgetq_lane_f32(c, 0));
+ float32x4_t cy = vmulq_n_f32(yMat, vgetq_lane_f32(c, 1));
+ float32x4_t cz = vmulq_n_f32(zMat, vgetq_lane_f32(c, 2));
+ cx = vaddq_f32(cx, cy);
+ cx = vaddq_f32(cx, cz);
+ // Clamp:
+ cx = vminq_f32(cx, maxV);
+ cx = vmaxq_f32(cx, minV);
+ vst1q_f32(&buffer[j].x, cx);
+ }
#else
for (int j = 0; j < len; ++j) {
const QColorVector cv = colorMatrix.map(buffer[j]);
@@ -281,6 +299,24 @@ static void applyMatrix(QColorVector *buffer, const qsizetype len, const QColorM
#endif
}
+#if defined(__SSE2__) || defined(__ARM_NEON__)
+template<typename T>
+static constexpr inline bool isArgb();
+template<>
+constexpr inline bool isArgb<QRgb>() { return true; }
+template<>
+constexpr inline bool isArgb<QRgba64>() { return false; }
+
+template<typename T>
+static inline int getAlpha(const T &p);
+template<>
+inline int getAlpha<QRgb>(const QRgb &p)
+{ return qAlpha(p); }
+template<>
+inline int getAlpha<QRgba64>(const QRgba64 &p)
+{ return p.alpha(); }
+#endif
+
template<typename T>
static void loadPremultiplied(QColorVector *buffer, const T *src, const qsizetype len, const QColorTransformPrivate *d_ptr);
template<typename T>
@@ -312,8 +348,6 @@ inline void loadP<QRgba64>(const QRgba64 &p, __m128i &v)
#else
v = _mm_unpacklo_epi16(v, _mm_setzero_si128());
#endif
- // Shuffle to ARGB as the template below expects it
- v = _mm_shuffle_epi32(v, _MM_SHUFFLE(3, 0, 1, 2));
}
template<typename T>
@@ -321,6 +355,7 @@ static void loadPremultiplied(QColorVector *buffer, const T *src, const qsizetyp
{
const __m128 v4080 = _mm_set1_ps(4080.f);
const __m128 iFF00 = _mm_set1_ps(1.0f / (255 * 256));
+ constexpr bool isARGB = isArgb<T>();
for (qsizetype i = 0; i < len; ++i) {
__m128i v;
loadP<T>(src[i], v);
@@ -338,9 +373,9 @@ static void loadPremultiplied(QColorVector *buffer, const T *src, const qsizetyp
// LUT
v = _mm_cvtps_epi32(_mm_mul_ps(vf, v4080));
- const int ridx = _mm_extract_epi16(v, 4);
+ const int ridx = isARGB ? _mm_extract_epi16(v, 4) : _mm_extract_epi16(v, 0);
const int gidx = _mm_extract_epi16(v, 2);
- const int bidx = _mm_extract_epi16(v, 0);
+ const int bidx = isARGB ? _mm_extract_epi16(v, 0) : _mm_extract_epi16(v, 4);
v = _mm_insert_epi16(v, d_ptr->colorSpaceIn->lut[0]->m_toLinear[ridx], 0);
v = _mm_insert_epi16(v, d_ptr->colorSpaceIn->lut[1]->m_toLinear[gidx], 2);
v = _mm_insert_epi16(v, d_ptr->colorSpaceIn->lut[2]->m_toLinear[bidx], 4);
@@ -378,20 +413,19 @@ inline void loadPU<QRgba64>(const QRgba64 &p, __m128i &v)
v = _mm_unpacklo_epi16(v, _mm_setzero_si128());
#endif
v = _mm_srli_epi32(v, 4);
- // Shuffle to ARGB as the template below expects it
- v = _mm_shuffle_epi32(v, _MM_SHUFFLE(3, 0, 1, 2));
}
template<typename T>
void loadUnpremultiplied(QColorVector *buffer, const T *src, const qsizetype len, const QColorTransformPrivate *d_ptr)
{
+ constexpr bool isARGB = isArgb<T>();
const __m128 iFF00 = _mm_set1_ps(1.0f / (255 * 256));
for (qsizetype i = 0; i < len; ++i) {
__m128i v;
loadPU<T>(src[i], v);
- const int ridx = _mm_extract_epi16(v, 4);
+ const int ridx = isARGB ? _mm_extract_epi16(v, 4) : _mm_extract_epi16(v, 0);
const int gidx = _mm_extract_epi16(v, 2);
- const int bidx = _mm_extract_epi16(v, 0);
+ const int bidx = isARGB ? _mm_extract_epi16(v, 0) : _mm_extract_epi16(v, 4);
v = _mm_insert_epi16(v, d_ptr->colorSpaceIn->lut[0]->m_toLinear[ridx], 0);
v = _mm_insert_epi16(v, d_ptr->colorSpaceIn->lut[1]->m_toLinear[gidx], 2);
v = _mm_insert_epi16(v, d_ptr->colorSpaceIn->lut[2]->m_toLinear[bidx], 4);
@@ -400,6 +434,100 @@ void loadUnpremultiplied(QColorVector *buffer, const T *src, const qsizetype len
}
}
+#elif defined(__ARM_NEON__)
+// Load to [0-alpha] in 4x32 SIMD
+template<typename T>
+static inline void loadP(const T &p, uint32x4_t &v);
+
+template<>
+inline void loadP<QRgb>(const QRgb &p, uint32x4_t &v)
+{
+ v = vmovl_u16(vget_low_u16(vmovl_u8(vreinterpret_u8_u32(vmov_n_u32(p)))));
+}
+
+template<>
+inline void loadP<QRgba64>(const QRgba64 &p, uint32x4_t &v)
+{
+ v = vmovl_u16(vreinterpret_u16_u64(vld1_u64(reinterpret_cast<const uint64_t *>(&p))));
+}
+
+template<typename T>
+static void loadPremultiplied(QColorVector *buffer, const T *src, const qsizetype len, const QColorTransformPrivate *d_ptr)
+{
+ constexpr bool isARGB = isArgb<T>();
+ const float iFF00 = 1.0f / (255 * 256);
+ for (qsizetype i = 0; i < len; ++i) {
+ uint32x4_t v;
+ loadP<T>(src[i], v);
+ float32x4_t vf = vcvtq_f32_u32(v);
+ // Approximate 1/a:
+ float32x4_t va = vdupq_n_f32(vgetq_lane_f32(vf, 3));
+ float32x4_t via = vrecpeq_f32(va); // estimate 1/a
+ via = vmulq_f32(vrecpsq_f32(va, via), via);
+
+ // v * (1/a)
+ vf = vmulq_f32(vf, via);
+
+ // Handle zero alpha
+#if defined(Q_PROCESSOR_ARM_64)
+ uint32x4_t vAlphaMask = vceqzq_f32(va);
+#else
+ uint32x4_t vAlphaMask = vceqq_f32(va, vdupq_n_f32(0.0));
+#endif
+ vf = vreinterpretq_f32_u32(vbicq_u32(vreinterpretq_u32_f32(vf), vAlphaMask));
+
+ // LUT
+ v = vcvtq_u32_f32(vaddq_f32(vmulq_n_f32(vf, 4080.f), vdupq_n_f32(0.5f)));
+ const int ridx = isARGB ? vgetq_lane_u32(v, 2) : vgetq_lane_u32(v, 0);
+ const int gidx = vgetq_lane_u32(v, 1);
+ const int bidx = isARGB ? vgetq_lane_u32(v, 0) : vgetq_lane_u32(v, 2);
+ v = vsetq_lane_u32(d_ptr->colorSpaceIn->lut[0]->m_toLinear[ridx], v, 0);
+ v = vsetq_lane_u32(d_ptr->colorSpaceIn->lut[1]->m_toLinear[gidx], v, 1);
+ v = vsetq_lane_u32(d_ptr->colorSpaceIn->lut[2]->m_toLinear[bidx], v, 2);
+ vf = vmulq_n_f32(vcvtq_f32_u32(v), iFF00);
+
+ vst1q_f32(&buffer[i].x, vf);
+ }
+}
+
+// Load to [0-4080] in 4x32 SIMD
+template<typename T>
+static inline void loadPU(const T &p, uint32x4_t &v);
+
+template<>
+inline void loadPU<QRgb>(const QRgb &p, uint32x4_t &v)
+{
+ v = vmovl_u16(vget_low_u16(vmovl_u8(vreinterpret_u8_u32(vmov_n_u32(p)))));
+ v = vshlq_n_u32(v, 4);
+}
+
+template<>
+inline void loadPU<QRgba64>(const QRgba64 &p, uint32x4_t &v)
+{
+ uint16x4_t v16 = vreinterpret_u16_u64(vld1_u64(reinterpret_cast<const uint64_t *>(&p)));
+ v16 = vsub_u16(v16, vshr_n_u16(v16, 8));
+ v = vmovl_u16(v16);
+ v = vshrq_n_u32(v, 4);
+}
+
+template<typename T>
+void loadUnpremultiplied(QColorVector *buffer, const T *src, const qsizetype len, const QColorTransformPrivate *d_ptr)
+{
+ constexpr bool isARGB = isArgb<T>();
+ const float iFF00 = 1.0f / (255 * 256);
+ for (qsizetype i = 0; i < len; ++i) {
+ uint32x4_t v;
+ loadPU<T>(src[i], v);
+ const int ridx = isARGB ? vgetq_lane_u32(v, 2) : vgetq_lane_u32(v, 0);
+ const int gidx = vgetq_lane_u32(v, 1);
+ const int bidx = isARGB ? vgetq_lane_u32(v, 0) : vgetq_lane_u32(v, 2);
+ v = vsetq_lane_u32(d_ptr->colorSpaceIn->lut[0]->m_toLinear[ridx], v, 0);
+ v = vsetq_lane_u32(d_ptr->colorSpaceIn->lut[1]->m_toLinear[gidx], v, 1);
+ v = vsetq_lane_u32(d_ptr->colorSpaceIn->lut[2]->m_toLinear[bidx], v, 2);
+ float32x4_t vf = vmulq_n_f32(vcvtq_f32_u32(v), iFF00);
+ vst1q_f32(&buffer[i].x, vf);
+ }
+}
#else
template<>
void loadPremultiplied<QRgb>(QColorVector *buffer, const QRgb *src, const qsizetype len, const QColorTransformPrivate *d_ptr)
@@ -464,82 +592,102 @@ void loadUnpremultiplied<QRgba64>(QColorVector *buffer, const QRgba64 *src, cons
}
#endif
-static void storePremultiplied(QRgb *dst, const QRgb *src, const QColorVector *buffer, const qsizetype len,
+#if defined(__SSE2__)
+template<typename T>
+static inline void storeP(T &p, __m128i &v, int a);
+template<>
+inline void storeP<QRgb>(QRgb &p, __m128i &v, int a)
+{
+ v = _mm_packs_epi32(v, v);
+ v = _mm_insert_epi16(v, a, 3);
+ p = _mm_cvtsi128_si32(_mm_packus_epi16(v, v));
+}
+template<>
+inline void storeP<QRgba64>(QRgba64 &p, __m128i &v, int a)
+{
+#if defined(__SSE4_1__)
+ v = _mm_packus_epi32(v, v);
+ v = _mm_insert_epi16(v, a, 3);
+ _mm_storel_epi64((__m128i *)&p, v);
+#else
+ const int r = _mm_extract_epi16(v, 0);
+ const int g = _mm_extract_epi16(v, 2);
+ const int b = _mm_extract_epi16(v, 4);
+ p = qRgba64(r, g, b, a);
+#endif
+}
+
+template<typename T>
+static void storePremultiplied(T *dst, const T *src, const QColorVector *buffer, const qsizetype len,
const QColorTransformPrivate *d_ptr)
{
-#if defined(__SSE2__)
const __m128 v4080 = _mm_set1_ps(4080.f);
const __m128 iFF00 = _mm_set1_ps(1.0f / (255 * 256));
+ constexpr bool isARGB = isArgb<T>();
for (qsizetype i = 0; i < len; ++i) {
- const int a = qAlpha(src[i]);
+ const int a = getAlpha<T>(src[i]);
__m128 vf = _mm_loadu_ps(&buffer[i].x);
__m128i v = _mm_cvtps_epi32(_mm_mul_ps(vf, v4080));
- __m128 va = _mm_set1_ps(a);
- va = _mm_mul_ps(va, iFF00);
+ __m128 va = _mm_mul_ps(_mm_set1_ps(a), iFF00);
const int ridx = _mm_extract_epi16(v, 0);
const int gidx = _mm_extract_epi16(v, 2);
const int bidx = _mm_extract_epi16(v, 4);
- v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[0]->m_fromLinear[ridx], 4);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[0]->m_fromLinear[ridx], isARGB ? 4 : 0);
v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[1]->m_fromLinear[gidx], 2);
- v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[2]->m_fromLinear[bidx], 0);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[2]->m_fromLinear[bidx], isARGB ? 0 : 4);
vf = _mm_cvtepi32_ps(v);
vf = _mm_mul_ps(vf, va);
v = _mm_cvtps_epi32(vf);
- v = _mm_packs_epi32(v, v);
- v = _mm_insert_epi16(v, a, 3);
- v = _mm_packus_epi16(v, v);
- dst[i] = _mm_cvtsi128_si32(v);
- }
-#else
- for (qsizetype i = 0; i < len; ++i) {
- const int a = qAlpha(src[i]);
- const float fa = a / (255.0f * 256.0f);
- const float r = d_ptr->colorSpaceOut->lut[0]->m_fromLinear[int(buffer[i].x * 4080.0f + 0.5f)];
- const float g = d_ptr->colorSpaceOut->lut[1]->m_fromLinear[int(buffer[i].y * 4080.0f + 0.5f)];
- const float b = d_ptr->colorSpaceOut->lut[2]->m_fromLinear[int(buffer[i].z * 4080.0f + 0.5f)];
- dst[i] = qRgba(r * fa + 0.5f, g * fa + 0.5f, b * fa + 0.5f, a);
+ storeP<T>(dst[i], v, a);
}
-#endif
}
-static void storeUnpremultiplied(QRgb *dst, const QRgb *src, const QColorVector *buffer, const qsizetype len,
+template<typename T>
+static inline void storePU(T &p, __m128i &v, int a);
+template<>
+inline void storePU<QRgb>(QRgb &p, __m128i &v, int a)
+{
+ v = _mm_add_epi16(v, _mm_set1_epi16(0x80));
+ v = _mm_srli_epi16(v, 8);
+ v = _mm_insert_epi16(v, a, 3);
+ p = _mm_cvtsi128_si32(_mm_packus_epi16(v, v));
+}
+template<>
+inline void storePU<QRgba64>(QRgba64 &p, __m128i &v, int a)
+{
+ v = _mm_add_epi16(v, _mm_srli_epi16(v, 8));
+ v = _mm_insert_epi16(v, a, 3);
+ _mm_storel_epi64((__m128i *)&p, v);
+}
+
+template<typename T>
+static void storeUnpremultiplied(T *dst, const T *src, const QColorVector *buffer, const qsizetype len,
const QColorTransformPrivate *d_ptr)
{
-#if defined(__SSE2__)
const __m128 v4080 = _mm_set1_ps(4080.f);
+ constexpr bool isARGB = isArgb<T>();
for (qsizetype i = 0; i < len; ++i) {
- const int a = qAlpha(src[i]);
+ const int a = getAlpha<T>(src[i]);
__m128 vf = _mm_loadu_ps(&buffer[i].x);
__m128i v = _mm_cvtps_epi32(_mm_mul_ps(vf, v4080));
const int ridx = _mm_extract_epi16(v, 0);
const int gidx = _mm_extract_epi16(v, 2);
const int bidx = _mm_extract_epi16(v, 4);
v = _mm_setzero_si128();
- v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[0]->m_fromLinear[ridx], 2);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[0]->m_fromLinear[ridx], isARGB ? 2 : 0);
v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[1]->m_fromLinear[gidx], 1);
- v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[2]->m_fromLinear[bidx], 0);
- v = _mm_add_epi16(v, _mm_set1_epi16(0x80));
- v = _mm_srli_epi16(v, 8);
- v = _mm_insert_epi16(v, a, 3);
- v = _mm_packus_epi16(v, v);
- dst[i] = _mm_cvtsi128_si32(v);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[2]->m_fromLinear[bidx], isARGB ? 0 : 2);
+ storePU<T>(dst[i], v, a);
}
-#else
- for (qsizetype i = 0; i < len; ++i) {
- const int r = d_ptr->colorSpaceOut->lut[0]->u8FromLinearF32(buffer[i].x);
- const int g = d_ptr->colorSpaceOut->lut[1]->u8FromLinearF32(buffer[i].y);
- const int b = d_ptr->colorSpaceOut->lut[2]->u8FromLinearF32(buffer[i].z);
- dst[i] = (src[i] & 0xff000000) | (r << 16) | (g << 8) | (b << 0);
- }
-#endif
}
-static void storeOpaque(QRgb *dst, const QRgb *src, const QColorVector *buffer, const qsizetype len,
+template<typename T>
+static void storeOpaque(T *dst, const T *src, const QColorVector *buffer, const qsizetype len,
const QColorTransformPrivate *d_ptr)
{
Q_UNUSED(src);
-#if defined(__SSE2__)
const __m128 v4080 = _mm_set1_ps(4080.f);
+ constexpr bool isARGB = isArgb<T>();
for (qsizetype i = 0; i < len; ++i) {
__m128 vf = _mm_loadu_ps(&buffer[i].x);
__m128i v = _mm_cvtps_epi32(_mm_mul_ps(vf, v4080));
@@ -547,23 +695,142 @@ static void storeOpaque(QRgb *dst, const QRgb *src, const QColorVector *buffer,
const int gidx = _mm_extract_epi16(v, 2);
const int bidx = _mm_extract_epi16(v, 4);
v = _mm_setzero_si128();
- v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[0]->m_fromLinear[ridx], 2);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[0]->m_fromLinear[ridx], isARGB ? 2 : 0);
v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[1]->m_fromLinear[gidx], 1);
- v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[2]->m_fromLinear[bidx], 0);
- v = _mm_add_epi16(v, _mm_set1_epi16(0x80));
- v = _mm_srli_epi16(v, 8);
- v = _mm_insert_epi16(v, 255, 3);
- v = _mm_packus_epi16(v, v);
- dst[i] = _mm_cvtsi128_si32(v);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[2]->m_fromLinear[bidx], isARGB ? 0 : 2);
+ storePU<T>(dst[i], v, isARGB ? 255 : 0xffff);
+ }
+}
+#elif defined(__ARM_NEON__)
+template<typename T>
+static inline void storeP(T &p, const uint16x4_t &v);
+template<>
+inline void storeP<QRgb>(QRgb &p, const uint16x4_t &v)
+{
+ p = vget_lane_u32(vreinterpret_u32_u8(vmovn_u16(vcombine_u16(v, v))), 0);
+}
+template<>
+inline void storeP<QRgba64>(QRgba64 &p, const uint16x4_t &v)
+{
+ vst1_u16((uint16_t *)&p, v);
+}
+
+template<typename T>
+static void storePremultiplied(T *dst, const T *src, const QColorVector *buffer, const qsizetype len,
+ const QColorTransformPrivate *d_ptr)
+{
+ const float iFF00 = 1.0f / (255 * 256);
+ constexpr bool isARGB = isArgb<T>();
+ for (qsizetype i = 0; i < len; ++i) {
+ const int a = getAlpha<T>(src[i]);
+ float32x4_t vf = vld1q_f32(&buffer[i].x);
+ uint32x4_t v = vcvtq_u32_f32(vaddq_f32(vmulq_n_f32(vf, 4080.f), vdupq_n_f32(0.5f)));
+ const int ridx = vgetq_lane_u32(v, 0);
+ const int gidx = vgetq_lane_u32(v, 1);
+ const int bidx = vgetq_lane_u32(v, 2);
+ v = vsetq_lane_u32(d_ptr->colorSpaceOut->lut[0]->m_fromLinear[ridx], v, isARGB ? 2 : 0);
+ v = vsetq_lane_u32(d_ptr->colorSpaceOut->lut[1]->m_fromLinear[gidx], v, 1);
+ v = vsetq_lane_u32(d_ptr->colorSpaceOut->lut[2]->m_fromLinear[bidx], v, isARGB ? 0 : 2);
+ vf = vcvtq_f32_u32(v);
+ vf = vmulq_n_f32(vf, a * iFF00);
+ vf = vaddq_f32(vf, vdupq_n_f32(0.5f));
+ v = vcvtq_u32_f32(vf);
+ uint16x4_t v16 = vmovn_u32(v);
+ v16 = vset_lane_u16(a, v16, 3);
+ storeP<T>(dst[i], v16);
+ }
+}
+
+template<typename T>
+static inline void storePU(T &p, uint16x4_t &v, int a);
+template<>
+inline void storePU<QRgb>(QRgb &p, uint16x4_t &v, int a)
+{
+ v = vadd_u16(v, vdup_n_u16(0x80));
+ v = vshr_n_u16(v, 8);
+ v = vset_lane_u16(a, v, 3);
+ p = vget_lane_u32(vreinterpret_u32_u8(vmovn_u16(vcombine_u16(v, v))), 0);
+}
+template<>
+inline void storePU<QRgba64>(QRgba64 &p, uint16x4_t &v, int a)
+{
+ v = vadd_u16(v, vshr_n_u16(v, 8));
+ v = vset_lane_u16(a, v, 3);
+ vst1_u16((uint16_t *)&p, v);
+}
+
+template<typename T>
+static void storeUnpremultiplied(T *dst, const T *src, const QColorVector *buffer, const qsizetype len,
+ const QColorTransformPrivate *d_ptr)
+{
+ constexpr bool isARGB = isArgb<T>();
+ for (qsizetype i = 0; i < len; ++i) {
+ const int a = getAlpha<T>(src[i]);
+ float32x4_t vf = vld1q_f32(&buffer[i].x);
+ uint16x4_t v = vmovn_u32(vcvtq_u32_f32(vaddq_f32(vmulq_n_f32(vf, 4080.f), vdupq_n_f32(0.5f))));
+ const int ridx = vget_lane_u16(v, 0);
+ const int gidx = vget_lane_u16(v, 1);
+ const int bidx = vget_lane_u16(v, 2);
+ v = vset_lane_u16(d_ptr->colorSpaceOut->lut[0]->m_fromLinear[ridx], v, isARGB ? 2 : 0);
+ v = vset_lane_u16(d_ptr->colorSpaceOut->lut[1]->m_fromLinear[gidx], v, 1);
+ v = vset_lane_u16(d_ptr->colorSpaceOut->lut[2]->m_fromLinear[bidx], v, isARGB ? 0 : 2);
+ storePU<T>(dst[i], v, a);
}
+}
+
+template<typename T>
+static void storeOpaque(T *dst, const T *src, const QColorVector *buffer, const qsizetype len,
+ const QColorTransformPrivate *d_ptr)
+{
+ Q_UNUSED(src);
+ constexpr bool isARGB = isArgb<T>();
+ for (qsizetype i = 0; i < len; ++i) {
+ float32x4_t vf = vld1q_f32(&buffer[i].x);
+ uint16x4_t v = vmovn_u32(vcvtq_u32_f32(vaddq_f32(vmulq_n_f32(vf, 4080.f), vdupq_n_f32(0.5f))));
+ const int ridx = vget_lane_u16(v, 0);
+ const int gidx = vget_lane_u16(v, 1);
+ const int bidx = vget_lane_u16(v, 2);
+ v = vset_lane_u16(d_ptr->colorSpaceOut->lut[0]->m_fromLinear[ridx], v, isARGB ? 2 : 0);
+ v = vset_lane_u16(d_ptr->colorSpaceOut->lut[1]->m_fromLinear[gidx], v, 1);
+ v = vset_lane_u16(d_ptr->colorSpaceOut->lut[2]->m_fromLinear[bidx], v, isARGB ? 0 : 2);
+ storePU<T>(dst[i], v, isARGB ? 255 : 0xffff);
+ }
+}
#else
+static void storePremultiplied(QRgb *dst, const QRgb *src, const QColorVector *buffer, const qsizetype len,
+ const QColorTransformPrivate *d_ptr)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const int a = qAlpha(src[i]);
+ const float fa = a / (255.0f * 256.0f);
+ const float r = d_ptr->colorSpaceOut->lut[0]->m_fromLinear[int(buffer[i].x * 4080.0f + 0.5f)];
+ const float g = d_ptr->colorSpaceOut->lut[1]->m_fromLinear[int(buffer[i].y * 4080.0f + 0.5f)];
+ const float b = d_ptr->colorSpaceOut->lut[2]->m_fromLinear[int(buffer[i].z * 4080.0f + 0.5f)];
+ dst[i] = qRgba(r * fa + 0.5f, g * fa + 0.5f, b * fa + 0.5f, a);
+ }
+}
+
+static void storeUnpremultiplied(QRgb *dst, const QRgb *src, const QColorVector *buffer, const qsizetype len,
+ const QColorTransformPrivate *d_ptr)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const int r = d_ptr->colorSpaceOut->lut[0]->u8FromLinearF32(buffer[i].x);
+ const int g = d_ptr->colorSpaceOut->lut[1]->u8FromLinearF32(buffer[i].y);
+ const int b = d_ptr->colorSpaceOut->lut[2]->u8FromLinearF32(buffer[i].z);
+ dst[i] = (src[i] & 0xff000000) | (r << 16) | (g << 8) | (b << 0);
+ }
+}
+
+static void storeOpaque(QRgb *dst, const QRgb *src, const QColorVector *buffer, const qsizetype len,
+ const QColorTransformPrivate *d_ptr)
+{
+ Q_UNUSED(src);
for (qsizetype i = 0; i < len; ++i) {
const int r = d_ptr->colorSpaceOut->lut[0]->u8FromLinearF32(buffer[i].x);
const int g = d_ptr->colorSpaceOut->lut[1]->u8FromLinearF32(buffer[i].y);
const int b = d_ptr->colorSpaceOut->lut[2]->u8FromLinearF32(buffer[i].z);
dst[i] = 0xff000000 | (r << 16) | (g << 8) | (b << 0);
}
-#endif
}
static void storePremultiplied(QRgba64 *dst, const QRgba64 *src, const QColorVector *buffer, const qsizetype len,
@@ -601,6 +868,23 @@ static void storeOpaque(QRgba64 *dst, const QRgba64 *src, const QColorVector *bu
dst[i] = qRgba64(r, g, b, 0xFFFF);
}
}
+#endif
+
+static void storeGray(quint8 *dst, const QRgb *src, const QColorVector *buffer, const qsizetype len,
+ const QColorTransformPrivate *d_ptr)
+{
+ Q_UNUSED(src);
+ for (qsizetype i = 0; i < len; ++i)
+ dst[i] = d_ptr->colorSpaceOut->lut[1]->u8FromLinearF32(buffer[i].y);
+}
+
+static void storeGray(quint16 *dst, const QRgba64 *src, const QColorVector *buffer, const qsizetype len,
+ const QColorTransformPrivate *d_ptr)
+{
+ Q_UNUSED(src);
+ for (qsizetype i = 0; i < len; ++i)
+ dst[i] = d_ptr->colorSpaceOut->lut[1]->u16FromLinearF32(buffer[i].y);
+}
static constexpr qsizetype WorkBlockSize = 256;
@@ -648,6 +932,33 @@ void QColorTransformPrivate::apply(T *dst, const T *src, qsizetype count, Transf
}
}
+template<typename D, typename S>
+void QColorTransformPrivate::applyReturnGray(D *dst, const S *src, qsizetype count, TransformFlags flags) const
+{
+ if (!colorMatrix.isValid())
+ return;
+
+ updateLutsIn();
+ updateLutsOut();
+
+ QUninitialized<QColorVector, WorkBlockSize> buffer;
+
+ qsizetype i = 0;
+ while (i < count) {
+ const qsizetype len = qMin(count - i, WorkBlockSize);
+ if (flags & InputPremultiplied)
+ loadPremultiplied(buffer, src + i, len, this);
+ else
+ loadUnpremultiplied(buffer, src + i, len, this);
+
+ applyMatrix(buffer, len, colorMatrix);
+
+ storeGray(dst + i, src + i, buffer, len, this);
+
+ i += len;
+ }
+}
+
/*!
\internal
\enum QColorTransformPrivate::TransformFlag
@@ -708,5 +1019,25 @@ void QColorTransformPrivate::apply(QRgba64 *dst, const QRgba64 *src, qsizetype c
apply<QRgba64>(dst, src, count, flags);
}
+/*!
+ \internal
+ Is to be called on a color-transform to XYZ, returns only luminance values.
+
+*/
+void QColorTransformPrivate::apply(quint8 *dst, const QRgb *src, qsizetype count, TransformFlags flags) const
+{
+ applyReturnGray<quint8, QRgb>(dst, src, count, flags);
+}
+
+/*!
+ \internal
+ Is to be called on a color-transform to XYZ, returns only luminance values.
+
+*/
+void QColorTransformPrivate::apply(quint16 *dst, const QRgba64 *src, qsizetype count, TransformFlags flags) const
+{
+ applyReturnGray<quint16, QRgba64>(dst, src, count, flags);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/painting/qcolortransform.h b/src/gui/painting/qcolortransform.h
index 30aceebda3..7ec58c5617 100644
--- a/src/gui/painting/qcolortransform.h
+++ b/src/gui/painting/qcolortransform.h
@@ -75,6 +75,7 @@ public:
private:
friend class QColorSpace;
friend class QColorSpacePrivate;
+ friend class QColorTransformPrivate;
friend class QImage;
QExplicitlySharedDataPointer<QColorTransformPrivate> d;
diff --git a/src/gui/painting/qcolortransform_p.h b/src/gui/painting/qcolortransform_p.h
index 5d7116248d..b9099fa399 100644
--- a/src/gui/painting/qcolortransform_p.h
+++ b/src/gui/painting/qcolortransform_p.h
@@ -65,6 +65,9 @@ public:
QExplicitlySharedDataPointer<const QColorSpacePrivate> colorSpaceIn;
QExplicitlySharedDataPointer<const QColorSpacePrivate> colorSpaceOut;
+ static QColorTransformPrivate *get(const QColorTransform &q)
+ { return q.d.data(); }
+
void updateLutsIn() const;
void updateLutsOut() const;
bool simpleGammaCorrection() const;
@@ -81,9 +84,15 @@ public:
void apply(QRgb *dst, const QRgb *src, qsizetype count, TransformFlags flags = Unpremultiplied) const;
void apply(QRgba64 *dst, const QRgba64 *src, qsizetype count, TransformFlags flags = Unpremultiplied) const;
+ void apply(quint8 *dst, const QRgb *src, qsizetype count, TransformFlags flags = Unpremultiplied) const;
+ void apply(quint16 *dst, const QRgba64 *src, qsizetype count, TransformFlags flags = Unpremultiplied) const;
template<typename T>
void apply(T *dst, const T *src, qsizetype count, TransformFlags flags) const;
+
+ template<typename D, typename S>
+ void applyReturnGray(D *dst, const S *src, qsizetype count, TransformFlags flags) const;
+
};
QT_END_NAMESPACE
diff --git a/src/gui/painting/qcompositionfunctions.cpp b/src/gui/painting/qcompositionfunctions.cpp
index 65b03a1e12..3fc9aa3e4e 100644
--- a/src/gui/painting/qcompositionfunctions.cpp
+++ b/src/gui/painting/qcompositionfunctions.cpp
@@ -38,8 +38,10 @@
****************************************************************************/
#include <qglobal.h>
+
#include "qdrawhelper_p.h"
#include "qrgba64_p.h"
+#include "qrgbaf.h"
QT_BEGIN_NAMESPACE
@@ -117,6 +119,8 @@ struct Argb32OperationsC
const Argb32OperationsC::Type Argb32OperationsC::clear = 0;
+typedef Argb32OperationsC Argb32Operations;
+
struct Rgba64OperationsBase
{
typedef QRgba64 Type;
@@ -319,9 +323,188 @@ typedef Rgba64OperationsNEON Rgba64Operations;
#else
typedef Rgba64OperationsC Rgba64Operations;
#endif
+
#endif // QT_CONFIG(raster_64bit)
-typedef Argb32OperationsC Argb32Operations;
+#if QT_CONFIG(raster_fp)
+
+static inline QRgba32F qRgba32f(float r, float g, float b, float a)
+{
+ return QRgba32F{r, g, b, a};
+}
+
+struct RgbaFPOperationsBase
+{
+ typedef QRgba32F Type;
+ typedef float Scalar;
+
+ static inline constexpr Type clear = { 0, 0, 0, 0 };
+
+ static bool isOpaque(Type val)
+ { return val.a >= 1.0f; }
+ static bool isTransparent(Type val)
+ { return val.a <= 0.0f; }
+ static Scalar scalarFrom8bit(uint8_t a)
+ { return a * (1.0f / 255.0f); }
+
+ static void memfill(Type *ptr, Type value, qsizetype len)
+ {
+ for (qsizetype i = 0; i < len; ++i)
+ ptr[i] = value;
+ }
+ static void memcpy(Type *Q_DECL_RESTRICT dest, const Type *Q_DECL_RESTRICT src, qsizetype len)
+ { ::memcpy(dest, src, len * sizeof(Type)); }
+};
+
+struct RgbaFPOperationsC : RgbaFPOperationsBase
+{
+ typedef QRgba32F OptimalType;
+ typedef float OptimalScalar;
+
+ static OptimalType load(const Type *ptr)
+ {
+ return QRgba32F { ptr->r, ptr->g, ptr->b, ptr->a };
+ }
+ static OptimalType convert(const Type &val)
+ {
+ return QRgba32F { val.r, val.g, val.b, val.a };
+ }
+ static void store(Type *ptr, OptimalType value)
+ {
+ ptr->r = value.r;
+ ptr->g = value.g;
+ ptr->b = value.b;
+ ptr->a = value.a;
+ }
+ static OptimalType add(OptimalType a, OptimalType b)
+ {
+ a.r += b.r;
+ a.g += b.g;
+ a.b += b.b;
+ a.a += b.a;
+ return a;
+ }
+ static OptimalScalar add(OptimalScalar a, OptimalScalar b)
+ { return a + b; }
+ static OptimalType plus(OptimalType a, OptimalType b)
+ {
+ a = add(a, b); // no saturation on color values
+ if (a.a < 0.0f) a.a = 0.0f;
+ else if (a.a > 1.0f) a.a = 1.0f;
+ return a;
+ }
+ static OptimalScalar alpha(OptimalType val)
+ { return val.a; }
+ static OptimalScalar invAlpha(OptimalScalar c)
+ { return 1.0f - c; }
+ static OptimalScalar invAlpha(OptimalType val)
+ { return 1.0f - val.a; }
+ static OptimalScalar scalar(Scalar v)
+ { return v; }
+ static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
+ {
+ val.r *= a;
+ val.g *= a;
+ val.b *= a;
+ val.a *= a;
+ return val;
+ }
+ static OptimalScalar multiplyAlpha8bit(OptimalScalar val, uint8_t a)
+ {
+ return val * a * (1.0f / 255.0f);
+ }
+ static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2)
+ {
+ return add(multiplyAlpha(x, a1), multiplyAlpha(y, a2));
+ }
+ static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
+ {
+ return multiplyAlpha(val, a * (1.0f / 255.0f));
+ }
+ static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
+ {
+ return add(multiplyAlpha8bit(x, a1), multiplyAlpha8bit(y, a2));
+ }
+};
+
+#if defined(__SSE2__)
+struct RgbaFPOperationsSSE2 : public RgbaFPOperationsBase
+{
+ typedef __m128 OptimalType;
+ typedef __m128 OptimalScalar;
+
+ static OptimalType load(const Type *ptr)
+ {
+ return _mm_load_ps(reinterpret_cast<const float *>(ptr));
+ }
+ static OptimalType convert(const Type &value)
+ {
+ return load(&value);
+ }
+ static void store(Type *ptr, OptimalType value)
+ {
+ _mm_store_ps(reinterpret_cast<float *>(ptr), value);
+ }
+ static OptimalType add(OptimalType a, OptimalType b)
+ {
+ return _mm_add_ps(a, b);
+ }
+// same as above:
+// static OptimalScalar add(OptimalScalar a, OptimalScalar b)
+ static OptimalType plus(OptimalType a, OptimalType b)
+ {
+ a = _mm_add_ps(a, b);
+ __m128 aa = _mm_min_ps(a, _mm_set1_ps(1.0f));
+ aa = _mm_max_ps(aa, _mm_set1_ps(0.0f));
+ // An indirect insert using only SSE2:
+ aa = _mm_shuffle_ps(aa, a, _MM_SHUFFLE(2, 2, 3, 3));
+ a = _mm_shuffle_ps(a, aa, _MM_SHUFFLE(0, 2, 1, 0));
+ return a;
+ }
+ static OptimalScalar alpha(OptimalType c)
+ {
+ return _mm_shuffle_ps(c, c, _MM_SHUFFLE(3, 3, 3, 3));
+ }
+ static OptimalScalar invAlpha(Scalar c)
+ {
+ return _mm_set1_ps(1.0f - float(c));
+ }
+ static OptimalScalar invAlpha(OptimalType c)
+ {
+ return _mm_sub_ps(_mm_set1_ps(1.0f), alpha(c));
+ }
+ static OptimalScalar scalar(Scalar n)
+ {
+ return _mm_set1_ps(float(n));
+ }
+ static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
+ {
+ return _mm_mul_ps(val, a);
+ }
+ static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2)
+ {
+ return add(multiplyAlpha(x, a1), multiplyAlpha(y, a2));
+ }
+ static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
+ {
+ return multiplyAlpha(val, _mm_set1_ps(a * (1.0f / 255.0f)));
+ }
+// same as above:
+// static OptimalScalar multiplyAlpha8bit(OptimalScalar a, uint8_t a)
+ static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
+ {
+ return add(multiplyAlpha8bit(x, a1), multiplyAlpha8bit(y, a2));
+ }
+};
+#endif
+
+#if defined(__SSE2__)
+typedef RgbaFPOperationsSSE2 RgbaFPOperations;
+#else
+typedef RgbaFPOperationsC RgbaFPOperations;
+#endif
+
+#endif // QT_CONFIG(raster_fp)
/*
result = 0
@@ -362,6 +545,17 @@ void QT_FASTCALL comp_func_Clear_rgb64(QRgba64 *dest, const QRgba64 *, int lengt
}
#endif
+#if QT_CONFIG(raster_fp)
+void QT_FASTCALL comp_func_solid_Clear_rgbafp(QRgba32F *dest, int length, QRgba32F, uint const_alpha)
+{
+ comp_func_Clear_template<RgbaFPOperations>(dest, length, const_alpha);
+}
+
+void QT_FASTCALL comp_func_Clear_rgbafp(QRgba32F *dest, const QRgba32F *, int length, uint const_alpha)
+{
+ comp_func_Clear_template<RgbaFPOperations>(dest, length, const_alpha);
+}
+#endif
/*
result = s
@@ -421,6 +615,18 @@ void QT_FASTCALL comp_func_Source_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRg
}
#endif
+#if QT_CONFIG(raster_fp)
+void QT_FASTCALL comp_func_solid_Source_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ comp_func_solid_Source_template<RgbaFPOperations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_Source_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_Source_template<RgbaFPOperations>(dest, src, length, const_alpha);
+}
+#endif
+
void QT_FASTCALL comp_func_solid_Destination(uint *, int, uint, uint)
{
}
@@ -439,6 +645,16 @@ void QT_FASTCALL comp_func_Destination_rgb64(QRgba64 *, const QRgba64 *, int, ui
}
#endif
+#if QT_CONFIG(raster_fp)
+void QT_FASTCALL comp_func_solid_Destination_rgbafp(QRgba32F *, int, QRgba32F, uint)
+{
+}
+
+void QT_FASTCALL comp_func_Destination_rgbafp(QRgba32F *, const QRgba32F *, int, uint)
+{
+}
+#endif
+
/*
result = s + d * sia
dest = (s + d * sia) * ca + d * cia
@@ -509,6 +725,19 @@ void QT_FASTCALL comp_func_SourceOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
}
#endif
+#if QT_CONFIG(raster_fp)
+void QT_FASTCALL comp_func_solid_SourceOver_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ comp_func_solid_SourceOver_template<RgbaFPOperations>(dest, length, color, const_alpha);
+}
+
+
+void QT_FASTCALL comp_func_SourceOver_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_SourceOver_template<RgbaFPOperations>(dest, src, length, const_alpha);
+}
+#endif
+
/*
result = d + s * dia
dest = (d + s * dia) * ca + d * cia
@@ -570,6 +799,18 @@ void QT_FASTCALL comp_func_DestinationOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest,
}
#endif
+#if QT_CONFIG(raster_fp)
+void QT_FASTCALL comp_func_solid_DestinationOver_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ comp_func_solid_DestinationOver_template<RgbaFPOperations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_DestinationOver_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_DestinationOver_template<RgbaFPOperations>(dest, src, length, const_alpha);
+}
+#endif
+
/*
result = s * da
dest = s * da * ca + d * cia
@@ -636,6 +877,18 @@ void QT_FASTCALL comp_func_SourceIn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const Q
}
#endif
+#if QT_CONFIG(raster_fp)
+void QT_FASTCALL comp_func_solid_SourceIn_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ comp_func_solid_SourceIn_template<RgbaFPOperations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_SourceIn_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_SourceIn_template<RgbaFPOperations>(dest, src, length, const_alpha);
+}
+#endif
+
/*
result = d * sa
dest = d * sa * ca + d * cia
@@ -697,6 +950,18 @@ void QT_FASTCALL comp_func_DestinationIn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, co
}
#endif
+#if QT_CONFIG(raster_fp)
+void QT_FASTCALL comp_func_solid_DestinationIn_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ comp_func_solid_DestinationIn_template<RgbaFPOperations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_DestinationIn_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_DestinationIn_template<RgbaFPOperations>(dest, src, length, const_alpha);
+}
+#endif
+
/*
result = s * dia
dest = s * dia * ca + d * cia
@@ -761,6 +1026,18 @@ void QT_FASTCALL comp_func_SourceOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
}
#endif
+#if QT_CONFIG(raster_fp)
+void QT_FASTCALL comp_func_solid_SourceOut_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ comp_func_solid_SourceOut_template<RgbaFPOperations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_SourceOut_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_SourceOut_template<RgbaFPOperations>(dest, src, length, const_alpha);
+}
+#endif
+
/*
result = d * sia
dest = d * sia * ca + d * cia
@@ -822,6 +1099,18 @@ void QT_FASTCALL comp_func_DestinationOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, c
}
#endif
+#if QT_CONFIG(raster_fp)
+void QT_FASTCALL comp_func_solid_DestinationOut_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ comp_func_solid_DestinationOut_template<RgbaFPOperations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_DestinationOut_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_DestinationOut_template<RgbaFPOperations>(dest, src, length, const_alpha);
+}
+#endif
+
/*
result = s*da + d*sia
dest = s*da*ca + d*sia*ca + d *cia
@@ -883,6 +1172,18 @@ void QT_FASTCALL comp_func_SourceAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
}
#endif
+#if QT_CONFIG(raster_fp)
+void QT_FASTCALL comp_func_solid_SourceAtop_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ comp_func_solid_SourceAtop_template<RgbaFPOperations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_SourceAtop_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_SourceAtop_template<RgbaFPOperations>(dest, src, length, const_alpha);
+}
+#endif
+
/*
result = d*sa + s*dia
dest = d*sa*ca + s*dia*ca + d *cia
@@ -949,6 +1250,18 @@ void QT_FASTCALL comp_func_DestinationAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest,
}
#endif
+#if QT_CONFIG(raster_fp)
+void QT_FASTCALL comp_func_solid_DestinationAtop_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ comp_func_solid_DestinationAtop_template<RgbaFPOperations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_DestinationAtop_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_DestinationAtop_template<RgbaFPOperations>(dest, src, length, const_alpha);
+}
+#endif
+
/*
result = d*sia + s*dia
dest = d*sia*ca + s*dia*ca + d *cia
@@ -1011,15 +1324,35 @@ void QT_FASTCALL comp_func_XOR_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba6
}
#endif
+#if QT_CONFIG(raster_fp)
+void QT_FASTCALL comp_func_solid_XOR_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ comp_func_solid_XOR_template<RgbaFPOperations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_XOR_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_XOR_template<RgbaFPOperations>(dest, src, length, const_alpha);
+}
+#endif
+
struct QFullCoverage {
inline void store(uint *dest, const uint src) const
{
*dest = src;
}
+#if QT_CONFIG(raster_64bit)
inline void store(QRgba64 *dest, const QRgba64 src) const
{
*dest = src;
}
+#endif
+#if QT_CONFIG(raster_fp)
+ inline void store(QRgba32F *dest, const QRgba32F src) const
+ {
+ *dest = src;
+ }
+#endif
};
struct QPartialCoverage {
@@ -1029,14 +1362,27 @@ struct QPartialCoverage {
{
}
+ template<typename Op>
+ inline void store_template(typename Op::Type *dest, const typename Op::Type src) const
+ {
+ Op::store(dest, Op::interpolate8bit(Op::convert(src), ca, Op::load(dest), ica));
+ }
inline void store(uint *dest, const uint src) const
{
- *dest = INTERPOLATE_PIXEL_255(src, ca, *dest, ica);
+ store_template<Argb32Operations>(dest, src);
}
+#if QT_CONFIG(raster_64bit)
inline void store(QRgba64 *dest, const QRgba64 src) const
{
- *dest = interpolate255(src, ca, *dest, ica);
+ store_template<Rgba64Operations>(dest, src);
}
+#endif
+#if QT_CONFIG(raster_fp)
+ inline void store(QRgba32F *dest, const QRgba32F src) const
+ {
+ store_template<RgbaFPOperations>(dest, src);
+ }
+#endif
private:
const uint ca;
@@ -1048,10 +1394,19 @@ static inline int mix_alpha(int da, int sa)
return 255 - ((255 - sa) * (255 - da) >> 8);
}
+#if QT_CONFIG(raster_64bit)
static inline uint mix_alpha_rgb64(uint da, uint sa)
{
return 65535U - ((65535U - sa) * (65535U - da) >> 16);
}
+#endif
+
+#if QT_CONFIG(raster_fp)
+static inline float mix_alpha_rgbafp(float da, float sa)
+{
+ return 1.0f - (1.0f - sa) * (1.0f - da);
+}
+#endif
/*
Dca' = Sca.Da + Dca.Sa + Sca.(1 - Da) + Dca.(1 - Sa)
@@ -1122,6 +1477,18 @@ void QT_FASTCALL comp_func_Plus_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba
}
#endif
+#if QT_CONFIG(raster_fp)
+void QT_FASTCALL comp_func_solid_Plus_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ comp_func_solid_Plus_template<RgbaFPOperations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_Plus_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_Plus_template<RgbaFPOperations>(dest, src, length, const_alpha);
+}
+#endif
+
/*
Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
*/
@@ -1199,6 +1566,45 @@ void QT_FASTCALL comp_func_solid_Multiply_rgb64(QRgba64 *dest, int length, QRgba
}
#endif
+#if QT_CONFIG(raster_fp)
+static inline float multiply_op_rgbafp(float dst, float src, float da, float sa)
+{
+ return src * dst + src * (1.0f - da) + dst * (1.0f - sa);
+}
+
+template <typename T>
+static inline void comp_func_solid_Multiply_impl(QRgba32F *dest, int length, QRgba32F color, const T &coverage)
+{
+ float sa = color.alpha();
+ float sr = color.red();
+ float sg = color.green();
+ float sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ float da = d.alpha();
+
+#define OP(a, b) multiply_op_rgbafp(a, b, da, sa)
+ float r = OP( d.red(), sr);
+ float b = OP( d.blue(), sb);
+ float g = OP(d.green(), sg);
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_Multiply_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Multiply_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Multiply_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+#endif
+
+
template <typename T>
static inline void comp_func_Multiply_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -1259,6 +1665,37 @@ void QT_FASTCALL comp_func_Multiply_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const Q
}
#endif
+#if QT_CONFIG(raster_fp)
+template <typename T>
+static inline void comp_func_Multiply_impl(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ QRgba32F s = src[i];
+
+ float da = d.alpha();
+ float sa = s.alpha();
+
+#define OP(a, b) multiply_op_rgbafp(a, b, da, sa)
+ float r = OP( d.red(), s.red());
+ float b = OP( d.blue(), s.blue());
+ float g = OP(d.green(), s.green());
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_Multiply_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Multiply_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Multiply_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+#endif
+
/*
Dca' = (Sca.Da + Dca.Sa - Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
= Sca + Dca - Sca.Dca
@@ -1327,6 +1764,39 @@ void QT_FASTCALL comp_func_solid_Screen_rgb64(QRgba64 *dest, int length, QRgba64
}
#endif
+#if QT_CONFIG(raster_fp)
+template <typename T>
+static inline void comp_func_solid_Screen_impl(QRgba32F *dest, int length, QRgba32F color, const T &coverage)
+{
+ float sa = color.alpha();
+ float sr = color.red();
+ float sg = color.green();
+ float sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ float da = d.alpha();
+
+#define OP(a, b) (1.0f - ((1.0f - a) * (1.0f - b)))
+ float r = OP( d.red(), sr);
+ float b = OP( d.blue(), sb);
+ float g = OP(d.green(), sg);
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_Screen_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Screen_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Screen_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+#endif
+
template <typename T>
static inline void comp_func_Screen_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -1387,6 +1857,37 @@ void QT_FASTCALL comp_func_Screen_rgb64(QRgba64 *dest, const QRgba64 *src, int l
}
#endif
+#if QT_CONFIG(raster_fp)
+template <typename T>
+static inline void comp_func_Screen_impl(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ QRgba32F s = src[i];
+
+ float da = d.alpha();
+ float sa = s.alpha();
+
+#define OP(a, b) (1.0f - ((1.0f - a) * (1.0f - b)))
+ float r = OP( d.red(), s.red());
+ float b = OP( d.blue(), s.blue());
+ float g = OP(d.green(), s.green());
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_Screen_rgbafp(QRgba32F *dest, const QRgba32F *src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Screen_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Screen_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+#endif
+
/*
if 2.Dca < Da
Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
@@ -1475,6 +1976,48 @@ void QT_FASTCALL comp_func_solid_Overlay_rgb64(QRgba64 *dest, int length, QRgba6
}
#endif
+#if QT_CONFIG(raster_fp)
+static inline float overlay_op_rgbafp(float dst, float src, float da, float sa)
+{
+ const float temp = src * (1.0f - da) + dst * (1.0f - sa);
+ if (2 * dst < da)
+ return 2 * src * dst + temp;
+ else
+ return sa * da - 2 * (da - dst) * (sa - src) + temp;
+}
+
+template <typename T>
+static inline void comp_func_solid_Overlay_impl(QRgba32F *dest, int length, QRgba32F color, const T &coverage)
+{
+ float sa = color.alpha();
+ float sr = color.red();
+ float sg = color.green();
+ float sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ float da = d.alpha();
+
+#define OP(a, b) overlay_op_rgbafp(a, b, da, sa)
+ float r = OP( d.red(), sr);
+ float b = OP( d.blue(), sb);
+ float g = OP(d.green(), sg);
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_Overlay_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Overlay_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Overlay_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+#endif
+
template <typename T>
static inline void comp_func_Overlay_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -1535,6 +2078,37 @@ void QT_FASTCALL comp_func_Overlay_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QR
}
#endif
+#if QT_CONFIG(raster_fp)
+template <typename T>
+static inline void comp_func_Overlay_impl(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ QRgba32F s = src[i];
+
+ float da = d.alpha();
+ float sa = s.alpha();
+
+#define OP(a, b) overlay_op_rgbafp(a, b, da, sa)
+ float r = OP( d.red(), s.red());
+ float b = OP( d.blue(), s.blue());
+ float g = OP(d.green(), s.green());
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_Overlay_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Overlay_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Overlay_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+#endif
+
/*
Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
Da' = Sa + Da - Sa.Da
@@ -1613,6 +2187,44 @@ void QT_FASTCALL comp_func_solid_Darken_rgb64(QRgba64 *dest, int length, QRgba64
}
#endif
+#if QT_CONFIG(raster_fp)
+static inline float darken_op_rgbafp(float dst, float src, float da, float sa)
+{
+ return qMin(src * da, dst * sa) + src * (1.0f - da) + dst * (1.0f - sa);
+}
+
+template <typename T>
+static inline void comp_func_solid_Darken_impl(QRgba32F *dest, int length, QRgba32F color, const T &coverage)
+{
+ float sa = color.alpha();
+ float sr = color.red();
+ float sg = color.green();
+ float sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ float da = d.alpha();
+
+#define OP(a, b) darken_op_rgbafp(a, b, da, sa)
+ float r = OP( d.red(), sr);
+ float b = OP( d.blue(), sb);
+ float g = OP(d.green(), sg);
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_Darken_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Darken_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Darken_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+#endif
+
template <typename T>
static inline void comp_func_Darken_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -1673,6 +2285,37 @@ void QT_FASTCALL comp_func_Darken_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRg
}
#endif
+#if QT_CONFIG(raster_fp)
+template <typename T>
+static inline void comp_func_Darken_impl(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ QRgba32F s = src[i];
+
+ float da = d.alpha();
+ float sa = s.alpha();
+
+#define OP(a, b) darken_op_rgbafp(a, b, da, sa)
+ float r = OP( d.red(), s.red());
+ float b = OP( d.blue(), s.blue());
+ float g = OP(d.green(), s.green());
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_Darken_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Darken_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Darken_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+#endif
+
/*
Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
Da' = Sa + Da - Sa.Da
@@ -1752,6 +2395,44 @@ void QT_FASTCALL comp_func_solid_Lighten_rgb64(QRgba64 *dest, int length, QRgba6
}
#endif
+#if QT_CONFIG(raster_fp)
+static inline float lighten_op_rgbafp(float dst, float src, float da, float sa)
+{
+ return qMax(src * da, dst * sa) + src * (1.0f - da) + dst * (1.0f - sa);
+}
+
+template <typename T>
+static inline void comp_func_solid_Lighten_impl(QRgba32F *dest, int length, QRgba32F color, const T &coverage)
+{
+ float sa = color.alpha();
+ float sr = color.red();
+ float sg = color.green();
+ float sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ float da = d.alpha();
+
+#define OP(a, b) lighten_op_rgbafp(a, b, da, sa)
+ float r = OP( d.red(), sr);
+ float b = OP( d.blue(), sb);
+ float g = OP(d.green(), sg);
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_Lighten_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Lighten_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Lighten_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+#endif
+
template <typename T>
static inline void comp_func_Lighten_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -1812,6 +2493,37 @@ void QT_FASTCALL comp_func_Lighten_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QR
}
#endif
+#if QT_CONFIG(raster_fp)
+template <typename T>
+static inline void comp_func_Lighten_impl(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ QRgba32F s = src[i];
+
+ float da = d.alpha();
+ float sa = s.alpha();
+
+#define OP(a, b) lighten_op_rgbafp(a, b, da, sa)
+ float r = OP( d.red(), s.red());
+ float b = OP( d.blue(), s.blue());
+ float g = OP(d.green(), s.green());
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_Lighten_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Lighten_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Lighten_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+#endif
+
/*
if Sca.Da + Dca.Sa > Sa.Da
Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa)
@@ -1914,6 +2626,54 @@ void QT_FASTCALL comp_func_solid_ColorDodge_rgb64(QRgba64 *dest, int length, QRg
}
#endif
+#if QT_CONFIG(raster_fp)
+static inline float color_dodge_op_rgbafp(float dst, float src, float da, float sa)
+{
+ const float sa_da = sa * da;
+ const float dst_sa = dst * sa;
+ const float src_da = src * da;
+
+ const float temp = src * (1.0f - da) + dst * (1.0f - sa);
+ if (src_da + dst_sa > sa_da)
+ return sa_da + temp;
+ else if (src == sa || sa == 0.0f)
+ return temp;
+ else
+ return dst_sa / (1.0f - src / sa) + temp;
+}
+
+template <typename T>
+static inline void comp_func_solid_ColorDodge_impl(QRgba32F *dest, int length, QRgba32F color, const T &coverage)
+{
+ float sa = color.alpha();
+ float sr = color.red();
+ float sg = color.green();
+ float sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ float da = d.alpha();
+
+#define OP(a,b) color_dodge_op_rgbafp(a, b, da, sa)
+ float r = OP( d.red(), sr);
+ float b = OP( d.blue(), sb);
+ float g = OP(d.green(), sg);
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_ColorDodge_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_ColorDodge_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_ColorDodge_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+#endif
+
template <typename T>
static inline void comp_func_ColorDodge_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -1974,6 +2734,37 @@ void QT_FASTCALL comp_func_ColorDodge_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
}
#endif
+#if QT_CONFIG(raster_fp)
+template <typename T>
+static inline void comp_func_ColorDodge_impl(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ QRgba32F s = src[i];
+
+ float da = d.alpha();
+ float sa = s.alpha();
+
+#define OP(a, b) color_dodge_op_rgbafp(a, b, da, sa)
+ float r = OP( d.red(), s.red());
+ float b = OP( d.blue(), s.blue());
+ float g = OP(d.green(), s.green());
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_ColorDodge_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_ColorDodge_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_ColorDodge_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+#endif
+
/*
if Sca.Da + Dca.Sa < Sa.Da
Dca' = Sca.(1 - Da) + Dca.(1 - Sa)
@@ -2076,6 +2867,54 @@ void QT_FASTCALL comp_func_solid_ColorBurn_rgb64(QRgba64 *dest, int length, QRgb
}
#endif
+#if QT_CONFIG(raster_fp)
+static inline float color_burn_op_rgbafp(float dst, float src, float da, float sa)
+{
+ const float src_da = src * da;
+ const float dst_sa = dst * sa;
+ const float sa_da = sa * da;
+
+ const float temp = src * (1.0f - da) + dst * (1.0f - sa);
+
+ if (src_da + dst_sa < sa_da)
+ return temp;
+ else if (src == 0)
+ return dst_sa + temp;
+ return sa * (src_da + dst_sa - sa_da) / src + temp;
+}
+
+template <typename T>
+static inline void comp_func_solid_ColorBurn_impl(QRgba32F *dest, int length, QRgba32F color, const T &coverage)
+{
+ float sa = color.alpha();
+ float sr = color.red();
+ float sg = color.green();
+ float sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ float da = d.alpha();
+
+#define OP(a, b) color_burn_op_rgbafp(a, b, da, sa)
+ float r = OP( d.red(), sr);
+ float b = OP( d.blue(), sb);
+ float g = OP(d.green(), sg);
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_ColorBurn_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_ColorBurn_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_ColorBurn_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+#endif
+
template <typename T>
static inline void comp_func_ColorBurn_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -2136,6 +2975,37 @@ void QT_FASTCALL comp_func_ColorBurn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
}
#endif
+#if QT_CONFIG(raster_fp)
+template <typename T>
+static inline void comp_func_ColorBurn_impl(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ QRgba32F s = src[i];
+
+ float da = d.alpha();
+ float sa = s.alpha();
+
+#define OP(a, b) color_burn_op_rgbafp(a, b, da, sa)
+ float r = OP( d.red(), s.red());
+ float b = OP( d.blue(), s.blue());
+ float g = OP(d.green(), s.green());
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_ColorBurn_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_ColorBurn_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_ColorBurn_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+#endif
+
/*
if 2.Sca < Sa
Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
@@ -2226,6 +3096,49 @@ void QT_FASTCALL comp_func_solid_HardLight_rgb64(QRgba64 *dest, int length, QRgb
}
#endif
+#if QT_CONFIG(raster_fp)
+static inline float hardlight_op_rgbafp(float dst, float src, float da, float sa)
+{
+ const float temp = src * (1.0f - da) + dst * (1.0f - sa);
+
+ if (2 * src < sa)
+ return 2 * src * dst + temp;
+ else
+ return sa * da - 2 * (da - dst) * (sa - src) + temp;
+}
+
+template <typename T>
+static inline void comp_func_solid_HardLight_impl(QRgba32F *dest, int length, QRgba32F color, const T &coverage)
+{
+ float sa = color.alpha();
+ float sr = color.red();
+ float sg = color.green();
+ float sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ float da = d.alpha();
+
+#define OP(a, b) hardlight_op_rgbafp(a, b, da, sa)
+ float r = OP( d.red(), sr);
+ float b = OP( d.blue(), sb);
+ float g = OP(d.green(), sg);
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_HardLight_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_HardLight_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_HardLight_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+#endif
+
template <typename T>
static inline void comp_func_HardLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -2286,6 +3199,37 @@ void QT_FASTCALL comp_func_HardLight_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
}
#endif
+#if QT_CONFIG(raster_fp)
+template <typename T>
+static inline void comp_func_HardLight_impl(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ QRgba32F s = src[i];
+
+ float da = d.alpha();
+ float sa = s.alpha();
+
+#define OP(a, b) hardlight_op_rgbafp(a, b, da, sa)
+ float r = OP( d.red(), s.red());
+ float b = OP( d.blue(), s.blue());
+ float g = OP(d.green(), s.green());
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_HardLight_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_HardLight_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_HardLight_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+#endif
+
/*
if 2.Sca <= Sa
Dca' = Dca.(Sa + (2.Sca - Sa).(1 - Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa)
@@ -2332,6 +3276,14 @@ static inline void comp_func_solid_SoftLight_impl(uint *dest, int length, uint c
}
}
+void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_SoftLight_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_SoftLight_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
#if QT_CONFIG(raster_64bit)
static inline uint soft_light_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
{
@@ -2371,15 +3323,64 @@ static inline void comp_func_solid_SoftLight_impl(QRgba64 *dest, int length, QRg
coverage.store(&dest[i], qRgba64(r, g, b, a));
}
}
+
+void QT_FASTCALL comp_func_solid_SoftLight_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_SoftLight_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_SoftLight_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
#endif
-void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, uint const_alpha)
+#if QT_CONFIG(raster_fp)
+static inline float soft_light_op_rgbafp(float dst, float src, float da, float sa)
+{
+ const float src2 = src * 2;
+ const float dst_np = da != 0.0f ? (dst / da) : 0.0f;
+ const float temp = src * (1.0f - da) + dst * (1.0f - sa);
+
+ if (src2 < sa)
+ return dst * (sa + (src2 - sa) * (1.0f - dst_np)) + temp;
+ else if (4 * dst <= da)
+ return dst * sa + da * (src2 - sa) * (((16 * dst_np - 12) * dst_np + 3) * dst_np) + temp;
+ else {
+ return dst * sa + da * (src2 - sa) * (qSqrt(qreal(dst_np)) - dst_np) + temp;
+ }
+}
+
+template <typename T>
+static inline void comp_func_solid_SoftLight_impl(QRgba32F *dest, int length, QRgba32F color, const T &coverage)
+{
+ float sa = color.alpha();
+ float sr = color.red();
+ float sg = color.green();
+ float sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ float da = d.alpha();
+
+#define OP(a, b) soft_light_op_rgbafp(a, b, da, sa)
+ float r = OP( d.red(), sr);
+ float b = OP( d.blue(), sb);
+ float g = OP(d.green(), sg);
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_SoftLight_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
{
if (const_alpha == 255)
comp_func_solid_SoftLight_impl(dest, length, color, QFullCoverage());
else
comp_func_solid_SoftLight_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+#endif
template <typename T>
static inline void comp_func_SoftLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
@@ -2411,14 +3412,6 @@ void QT_FASTCALL comp_func_SoftLight(uint *Q_DECL_RESTRICT dest, const uint *Q_D
}
#if QT_CONFIG(raster_64bit)
-void QT_FASTCALL comp_func_solid_SoftLight_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_solid_SoftLight_impl(dest, length, color, QFullCoverage());
- else
- comp_func_solid_SoftLight_impl(dest, length, color, QPartialCoverage(const_alpha));
-}
-
template <typename T>
static inline void comp_func_SoftLight_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -2449,6 +3442,37 @@ void QT_FASTCALL comp_func_SoftLight_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
}
#endif
+#if QT_CONFIG(raster_fp)
+template <typename T>
+static inline void comp_func_SoftLight_impl(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ QRgba32F s = src[i];
+
+ float da = d.alpha();
+ float sa = s.alpha();
+
+#define OP(a, b) soft_light_op_rgbafp(a, b, da, sa)
+ float r = OP( d.red(), s.red());
+ float b = OP( d.blue(), s.blue());
+ float g = OP(d.green(), s.green());
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_SoftLight_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_SoftLight_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_SoftLight_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+#endif
+
/*
Dca' = abs(Dca.Sa - Sca.Da) + Sca.(1 - Da) + Dca.(1 - Sa)
= Sca + Dca - 2.min(Sca.Da, Dca.Sa)
@@ -2527,6 +3551,44 @@ void QT_FASTCALL comp_func_solid_Difference_rgb64(QRgba64 *dest, int length, QRg
}
#endif
+#if QT_CONFIG(raster_fp)
+static inline float difference_op_rgbafp(float dst, float src, float da, float sa)
+{
+ return src + dst - (2 * qMin(src * da, dst * sa));
+}
+
+template <typename T>
+static inline void comp_func_solid_Difference_impl(QRgba32F *dest, int length, QRgba32F color, const T &coverage)
+{
+ float sa = color.alpha();
+ float sr = color.red();
+ float sg = color.green();
+ float sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ float da = d.alpha();
+
+#define OP(a, b) difference_op_rgbafp(a, b, da, sa)
+ float r = OP( d.red(), sr);
+ float b = OP( d.blue(), sb);
+ float g = OP(d.green(), sg);
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_Difference_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Difference_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Difference_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+#endif
+
template <typename T>
static inline void comp_func_Difference_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -2587,6 +3649,37 @@ void QT_FASTCALL comp_func_Difference_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
}
#endif
+#if QT_CONFIG(raster_fp)
+template <typename T>
+static inline void comp_func_Difference_impl(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ QRgba32F s = src[i];
+
+ float da = d.alpha();
+ float sa = s.alpha();
+
+#define OP(a, b) difference_op_rgbafp(a, b, da, sa)
+ float r = OP( d.red(), s.red());
+ float b = OP( d.blue(), s.blue());
+ float g = OP(d.green(), s.green());
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_Difference_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Difference_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Difference_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+#endif
+
/*
Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
*/
@@ -2645,7 +3738,6 @@ static inline void QT_FASTCALL comp_func_solid_Exclusion_impl(QRgba64 *dest, int
}
}
-
void QT_FASTCALL comp_func_solid_Exclusion_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
if (const_alpha == 255)
@@ -2655,6 +3747,39 @@ void QT_FASTCALL comp_func_solid_Exclusion_rgb64(QRgba64 *dest, int length, QRgb
}
#endif
+#if QT_CONFIG(raster_fp)
+template <typename T>
+static inline void QT_FASTCALL comp_func_solid_Exclusion_impl(QRgba32F *dest, int length, QRgba32F color, const T &coverage)
+{
+ float sa = color.alpha();
+ float sr = color.red();
+ float sg = color.green();
+ float sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ float da = d.alpha();
+
+#define OP(a, b) (a + b - (2.0f * a * b))
+ float r = OP( d.red(), sr);
+ float b = OP( d.blue(), sb);
+ float g = OP(d.green(), sg);
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_Exclusion_rgbafp(QRgba32F *dest, int length, QRgba32F color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Exclusion_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Exclusion_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+#endif
+
template <typename T>
static inline void comp_func_Exclusion_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -2715,6 +3840,37 @@ void QT_FASTCALL comp_func_Exclusion_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
}
#endif
+#if QT_CONFIG(raster_fp)
+template <typename T>
+static inline void comp_func_Exclusion_impl(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba32F d = dest[i];
+ QRgba32F s = src[i];
+
+ float da = d.alpha();
+ float sa = s.alpha();
+
+#define OP(a, b) (a + b - (2.0f * a * b))
+ float r = OP( d.red(), s.red());
+ float b = OP( d.blue(), s.blue());
+ float g = OP(d.green(), s.green());
+ float a = mix_alpha_rgbafp(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba32f(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_Exclusion_rgbafp(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Exclusion_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Exclusion_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+#endif
+
void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest,
int length,
uint color,
@@ -3097,6 +4253,40 @@ CompositionFunctionSolid64 qt_functionForModeSolid64_C[] = {
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
};
+CompositionFunctionSolidFP qt_functionForModeSolidFP_C[] = {
+#if QT_CONFIG(raster_fp)
+ comp_func_solid_SourceOver_rgbafp,
+ comp_func_solid_DestinationOver_rgbafp,
+ comp_func_solid_Clear_rgbafp,
+ comp_func_solid_Source_rgbafp,
+ comp_func_solid_Destination_rgbafp,
+ comp_func_solid_SourceIn_rgbafp,
+ comp_func_solid_DestinationIn_rgbafp,
+ comp_func_solid_SourceOut_rgbafp,
+ comp_func_solid_DestinationOut_rgbafp,
+ comp_func_solid_SourceAtop_rgbafp,
+ comp_func_solid_DestinationAtop_rgbafp,
+ comp_func_solid_XOR_rgbafp,
+ comp_func_solid_Plus_rgbafp,
+ comp_func_solid_Multiply_rgbafp,
+ comp_func_solid_Screen_rgbafp,
+ comp_func_solid_Overlay_rgbafp,
+ comp_func_solid_Darken_rgbafp,
+ comp_func_solid_Lighten_rgbafp,
+ comp_func_solid_ColorDodge_rgbafp,
+ comp_func_solid_ColorBurn_rgbafp,
+ comp_func_solid_HardLight_rgbafp,
+ comp_func_solid_SoftLight_rgbafp,
+ comp_func_solid_Difference_rgbafp,
+ comp_func_solid_Exclusion_rgbafp,
+#else
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+#endif
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
CompositionFunction qt_functionForMode_C[] = {
comp_func_SourceOver,
comp_func_DestinationOver,
@@ -3173,4 +4363,38 @@ CompositionFunction64 qt_functionForMode64_C[] = {
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
};
+CompositionFunctionFP qt_functionForModeFP_C[] = {
+#if QT_CONFIG(raster_fp)
+ comp_func_SourceOver_rgbafp,
+ comp_func_DestinationOver_rgbafp,
+ comp_func_Clear_rgbafp,
+ comp_func_Source_rgbafp,
+ comp_func_Destination_rgbafp,
+ comp_func_SourceIn_rgbafp,
+ comp_func_DestinationIn_rgbafp,
+ comp_func_SourceOut_rgbafp,
+ comp_func_DestinationOut_rgbafp,
+ comp_func_SourceAtop_rgbafp,
+ comp_func_DestinationAtop_rgbafp,
+ comp_func_XOR_rgbafp,
+ comp_func_Plus_rgbafp,
+ comp_func_Multiply_rgbafp,
+ comp_func_Screen_rgbafp,
+ comp_func_Overlay_rgbafp,
+ comp_func_Darken_rgbafp,
+ comp_func_Lighten_rgbafp,
+ comp_func_ColorDodge_rgbafp,
+ comp_func_ColorBurn_rgbafp,
+ comp_func_HardLight_rgbafp,
+ comp_func_SoftLight_rgbafp,
+ comp_func_Difference_rgbafp,
+ comp_func_Exclusion_rgbafp,
+#else
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+#endif
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index c66268c5f3..06eb08ea9c 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -38,11 +38,12 @@
**
****************************************************************************/
-#include <qglobal.h>
+#include "qdrawhelper_p.h"
#include <qstylehints.h>
#include <qguiapplication.h>
#include <qatomic.h>
+#include <private/qcolortransform_p.h>
#include <private/qcolortrclut_p.h>
#include <private/qdrawhelper_p.h>
#include <private/qdrawhelper_x86_p.h>
@@ -70,21 +71,258 @@ Q_LOGGING_CATEGORY(lcQtGuiDrawHelper, "qt.gui.drawhelper")
constants and structures
*/
-enum {
- fixed_scale = 1 << 16,
- half_point = 1 << 15
+constexpr int fixed_scale = 1 << 16;
+constexpr int half_point = 1 << 15;
+
+template <QPixelLayout::BPP bpp> static
+inline uint QT_FASTCALL fetch1Pixel(const uchar *, int)
+{
+ Q_UNREACHABLE();
+ return 0;
+}
+
+template <>
+inline uint QT_FASTCALL fetch1Pixel<QPixelLayout::BPP1LSB>(const uchar *src, int index)
+{
+ return (src[index >> 3] >> (index & 7)) & 1;
+}
+
+template <>
+inline uint QT_FASTCALL fetch1Pixel<QPixelLayout::BPP1MSB>(const uchar *src, int index)
+{
+ return (src[index >> 3] >> (~index & 7)) & 1;
+}
+
+template <>
+inline uint QT_FASTCALL fetch1Pixel<QPixelLayout::BPP8>(const uchar *src, int index)
+{
+ return src[index];
+}
+
+template <>
+inline uint QT_FASTCALL fetch1Pixel<QPixelLayout::BPP16>(const uchar *src, int index)
+{
+ return reinterpret_cast<const quint16 *>(src)[index];
+}
+
+template <>
+inline uint QT_FASTCALL fetch1Pixel<QPixelLayout::BPP24>(const uchar *src, int index)
+{
+ return reinterpret_cast<const quint24 *>(src)[index];
+}
+
+template <>
+inline uint QT_FASTCALL fetch1Pixel<QPixelLayout::BPP32>(const uchar *src, int index)
+{
+ return reinterpret_cast<const uint *>(src)[index];
+}
+
+template <>
+inline uint QT_FASTCALL fetch1Pixel<QPixelLayout::BPP64>(const uchar *src, int index)
+{
+ // We have to do the conversion in fetch to fit into a 32bit uint
+ QRgba64 c = reinterpret_cast<const QRgba64 *>(src)[index];
+ return c.toArgb32();
+}
+
+template <>
+inline uint QT_FASTCALL fetch1Pixel<QPixelLayout::BPP16FPx4>(const uchar *src, int index)
+{
+ // We have to do the conversion in fetch to fit into a 32bit uint
+ QRgba16F c = reinterpret_cast<const QRgba16F *>(src)[index];
+ return c.toArgb32();
+}
+
+template <>
+inline uint QT_FASTCALL fetch1Pixel<QPixelLayout::BPP32FPx4>(const uchar *src, int index)
+{
+ // We have to do the conversion in fetch to fit into a 32bit uint
+ QRgba32F c = reinterpret_cast<const QRgba32F *>(src)[index];
+ return c.toArgb32();
+}
+
+typedef uint (QT_FASTCALL *Fetch1PixelFunc)(const uchar *src, int index);
+
+constexpr Fetch1PixelFunc fetch1PixelTable[QPixelLayout::BPPCount] = {
+ nullptr, // BPPNone
+ fetch1Pixel<QPixelLayout::BPP1MSB>,
+ fetch1Pixel<QPixelLayout::BPP1LSB>,
+ fetch1Pixel<QPixelLayout::BPP8>,
+ fetch1Pixel<QPixelLayout::BPP16>,
+ fetch1Pixel<QPixelLayout::BPP24>,
+ fetch1Pixel<QPixelLayout::BPP32>,
+ fetch1Pixel<QPixelLayout::BPP64>,
+ fetch1Pixel<QPixelLayout::BPP16FPx4>,
+ fetch1Pixel<QPixelLayout::BPP32FPx4>,
};
#if QT_CONFIG(raster_64bit)
-static void convertRGBA64ToRGBA64PM(QRgba64 *buffer, int count)
+static void QT_FASTCALL convertRGBA64ToRGBA64PM(QRgba64 *buffer, int count)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = buffer[i].premultiplied();
+}
+
+static void QT_FASTCALL convertRGBA64PMToRGBA64PM(QRgba64 *, int)
+{
+}
+
+static void QT_FASTCALL convertRGBA16FToRGBA64PM(QRgba64 *buffer, int count)
+{
+ const QRgba16F *in = reinterpret_cast<const QRgba16F *>(buffer);
+ for (int i = 0; i < count; ++i) {
+ QRgba16F c = in[i];
+ buffer[i] = QRgba64::fromRgba64(c.red16(), c.green16(), c.blue16(), c.alpha16()).premultiplied();
+ }
+}
+
+static void QT_FASTCALL convertRGBA16FPMToRGBA64PM(QRgba64 *buffer, int count)
+{
+ const QRgba16F *in = reinterpret_cast<const QRgba16F *>(buffer);
+ for (int i = 0; i < count; ++i) {
+ QRgba16F c = in[i];
+ buffer[i] = QRgba64::fromRgba64(c.red16(), c.green16(), c.blue16(), c.alpha16());
+ }
+}
+
+static void QT_FASTCALL convertRGBA32FToRGBA64PM(QRgba64 *buffer, int count)
+{
+ const QRgba32F *in = reinterpret_cast<const QRgba32F *>(buffer);
+ for (int i = 0; i < count; ++i) {
+ QRgba32F c = in[i];
+ buffer[i] = QRgba64::fromRgba64(c.red16(), c.green16(), c.blue16(), c.alpha16()).premultiplied();
+ }
+}
+
+static void QT_FASTCALL convertRGBA32FPMToRGBA64PM(QRgba64 *buffer, int count)
+{
+ const QRgba32F *in = reinterpret_cast<const QRgba32F *>(buffer);
+ for (int i = 0; i < count; ++i) {
+ QRgba32F c = in[i];
+ buffer[i] = QRgba64::fromRgba64(c.red16(), c.green16(), c.blue16(), c.alpha16());
+ }
+}
+
+static Convert64Func convert64ToRGBA64PM[QImage::NImageFormats] = {
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ convertRGBA64PMToRGBA64PM,
+ convertRGBA64ToRGBA64PM,
+ convertRGBA64PMToRGBA64PM,
+ nullptr,
+ nullptr,
+ convertRGBA16FPMToRGBA64PM,
+ convertRGBA16FToRGBA64PM,
+ convertRGBA16FPMToRGBA64PM,
+ convertRGBA32FPMToRGBA64PM,
+ convertRGBA32FToRGBA64PM,
+ convertRGBA32FPMToRGBA64PM,
+};
+#endif
+
+#if QT_CONFIG(raster_fp)
+static void QT_FASTCALL convertRGBA64PMToRGBA32F(QRgba32F *buffer, const quint64 *src, int count)
{
+ const auto *in = reinterpret_cast<const QRgba64 *>(src);
+ for (int i = 0; i < count; ++i) {
+ auto c = in[i];
+ buffer[i] = QRgba32F::fromRgba64(c.red(), c.green(), c.blue(), c.alpha()).premultiplied();
+ }
+}
+
+static void QT_FASTCALL convertRGBA64ToRGBA32F(QRgba32F *buffer, const quint64 *src, int count)
+{
+ const auto *in = reinterpret_cast<const QRgba64 *>(src);
+ for (int i = 0; i < count; ++i) {
+ auto c = in[i];
+ buffer[i] = QRgba32F::fromRgba64(c.red(), c.green(), c.blue(), c.alpha());
+ }
+}
+
+static void QT_FASTCALL convertRGBA16FPMToRGBA32F(QRgba32F *buffer, const quint64 *src, int count)
+{
+ qFloatFromFloat16((float *)buffer, (const qfloat16 *)src, count * 4);
for (int i = 0; i < count; ++i)
buffer[i] = buffer[i].premultiplied();
}
-static void convertRGBA64PMToRGBA64PM(QRgba64 *, int)
+static void QT_FASTCALL convertRGBA16FToRGBA32F(QRgba32F *buffer, const quint64 *src, int count)
{
+ qFloatFromFloat16((float *)buffer, (const qfloat16 *)src, count * 4);
}
+
+static Convert64ToFPFunc convert64ToRGBA32F[QImage::NImageFormats] = {
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ convertRGBA64ToRGBA32F,
+ convertRGBA64PMToRGBA32F,
+ convertRGBA64ToRGBA32F,
+ nullptr,
+ nullptr,
+ convertRGBA16FToRGBA32F,
+ convertRGBA16FPMToRGBA32F,
+ convertRGBA16FToRGBA32F,
+ nullptr,
+ nullptr,
+ nullptr,
+};
+
+static void convertRGBA32FToRGBA32FPM(QRgba32F *buffer, int count)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = buffer[i].premultiplied();
+}
+
+static void convertRGBA32FToRGBA32F(QRgba32F *, int)
+{
+}
+
#endif
/*
@@ -174,6 +412,12 @@ static DestFetchProc destFetchProc[QImage::NImageFormats] =
destFetch, // Format_RGBA64_Premultiplied
destFetch, // Format_Grayscale16
destFetch, // Format_BGR888
+ destFetch, // Format_RGBX16FPx4
+ destFetch, // Format_RGBA16FPx4
+ destFetch, // Format_RGBA16FPx4_Premultiplied
+ destFetch, // Format_RGBX32FPx4
+ destFetch, // Format_RGBA32FPx4
+ destFetch, // Format_RGBA32FPx4_Premultiplied
};
#if QT_CONFIG(raster_64bit)
@@ -225,9 +469,27 @@ static DestFetchProc64 destFetchProc64[QImage::NImageFormats] =
destFetchRGB64, // Format_RGBA64_Premultiplied
destFetch64, // Format_Grayscale16
destFetch64, // Format_BGR888
+ destFetch64, // Format_RGBX16FPx4
+ destFetch64, // Format_RGBA16FPx4
+ destFetch64, // Format_RGBA16FPx4_Premultiplied
+ destFetch64, // Format_RGBX32FPx4
+ destFetch64, // Format_RGBA32FPx4
+ destFetch64, // Format_RGBA32FPx4_Premultiplied
};
#endif
+#if QT_CONFIG(raster_fp)
+static QRgba32F *QT_FASTCALL destFetchFP(QRgba32F *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
+{
+ return const_cast<QRgba32F *>(qFetchToRGBA32F[rasterBuffer->format](buffer, rasterBuffer->scanLine(y), x, length, nullptr, nullptr));
+}
+
+static QRgba32F *QT_FASTCALL destFetchFPUndefined(QRgba32F *buffer, QRasterBuffer *, int, int, int)
+{
+ return buffer;
+}
+#endif
+
/*
Returns the color in the mono destination color table
that is the "nearest" to /color/.
@@ -334,6 +596,51 @@ static void QT_FASTCALL destStore(QRasterBuffer *rasterBuffer, int x, int y, con
store(dest, buffer, x, length, nullptr, nullptr);
}
+static void QT_FASTCALL destStoreGray8(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length)
+{
+ uchar *data = rasterBuffer->scanLine(y) + x;
+
+ bool failed = false;
+ for (int k = 0; k < length; ++k) {
+ if (!qIsGray(buffer[k])) {
+ failed = true;
+ break;
+ }
+ data[k] = qRed(buffer[k]);
+ }
+ if (failed) { // Non-gray colors
+ QColorSpace fromCS = rasterBuffer->colorSpace.isValid() ? rasterBuffer->colorSpace : QColorSpace::SRgb;
+ QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
+ QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+
+ tfd->apply(data, buffer, length, QColorTransformPrivate::InputPremultiplied);
+ }
+}
+
+static void QT_FASTCALL destStoreGray16(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length)
+{
+ quint16 *data = reinterpret_cast<quint16 *>(rasterBuffer->scanLine(y)) + x;
+
+ bool failed = false;
+ for (int k = 0; k < length; ++k) {
+ if (!qIsGray(buffer[k])) {
+ failed = true;
+ break;
+ }
+ data[k] = qRed(buffer[k]) * 257;
+ }
+ if (failed) { // Non-gray colors
+ QColorSpace fromCS = rasterBuffer->colorSpace.isValid() ? rasterBuffer->colorSpace : QColorSpace::SRgb;
+ QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
+ QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+
+ QRgba64 tmp_line[BufferSize];
+ for (int k = 0; k < length; ++k)
+ tmp_line[k] = QRgba64::fromArgb32(buffer[k]);
+ tfd->apply(data, tmp_line, length, QColorTransformPrivate::InputPremultiplied);
+ }
+}
+
static DestStoreProc destStoreProc[QImage::NImageFormats] =
{
nullptr, // Format_Invalid
@@ -360,12 +667,18 @@ static DestStoreProc destStoreProc[QImage::NImageFormats] =
destStore, // Format_RGB30
destStore, // Format_A2RGB30_Premultiplied
destStore, // Format_Alpha8
- destStore, // Format_Grayscale8
+ destStoreGray8, // Format_Grayscale8
destStore, // Format_RGBX64
destStore, // Format_RGBA64
destStore, // Format_RGBA64_Premultiplied
- destStore, // Format_Grayscale16
+ destStoreGray16, // Format_Grayscale16
destStore, // Format_BGR888
+ destStore, // Format_RGBX16FPx4
+ destStore, // Format_RGBA16FPx4
+ destStore, // Format_RGBA16FPx4_Premultiplied
+ destStore, // Format_RGBX32FPx4
+ destStore, // Format_RGBA32FPx4
+ destStore, // Format_RGBA32FPx4_Premultiplied
};
#if QT_CONFIG(raster_64bit)
@@ -384,6 +697,50 @@ static void QT_FASTCALL destStore64RGBA64(QRasterBuffer *rasterBuffer, int x, in
}
}
+static void QT_FASTCALL destStore64Gray8(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
+{
+ uchar *data = rasterBuffer->scanLine(y) + x;
+
+ bool failed = false;
+ for (int k = 0; k < length; ++k) {
+ if (buffer[k].red() != buffer[k].green() || buffer[k].red() != buffer[k].blue()) {
+ failed = true;
+ break;
+ }
+ data[k] = buffer[k].red8();
+ }
+ if (failed) { // Non-gray colors
+ QColorSpace fromCS = rasterBuffer->colorSpace.isValid() ? rasterBuffer->colorSpace : QColorSpace::SRgb;
+ QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
+ QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+
+ quint16 gray_line[BufferSize];
+ tfd->apply(gray_line, buffer, length, QColorTransformPrivate::InputPremultiplied);
+ for (int k = 0; k < length; ++k)
+ data[k] = qt_div_257(gray_line[k]);
+ }
+}
+
+static void QT_FASTCALL destStore64Gray16(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
+{
+ quint16 *data = reinterpret_cast<quint16 *>(rasterBuffer->scanLine(y)) + x;
+
+ bool failed = false;
+ for (int k = 0; k < length; ++k) {
+ if (buffer[k].red() != buffer[k].green() || buffer[k].red() != buffer[k].blue()) {
+ failed = true;
+ break;
+ }
+ data[k] = buffer[k].red();
+ }
+ if (failed) { // Non-gray colors
+ QColorSpace fromCS = rasterBuffer->colorSpace.isValid() ? rasterBuffer->colorSpace : QColorSpace::SRgb;
+ QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
+ QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+ tfd->apply(data, buffer, length, QColorTransformPrivate::InputPremultiplied);
+ }
+}
+
static DestStoreProc64 destStoreProc64[QImage::NImageFormats] =
{
nullptr, // Format_Invalid
@@ -410,15 +767,30 @@ static DestStoreProc64 destStoreProc64[QImage::NImageFormats] =
destStore64, // Format_RGB30
destStore64, // Format_A2RGB30_Premultiplied
destStore64, // Format_Alpha8
- destStore64, // Format_Grayscale8
+ destStore64Gray8, // Format_Grayscale8
nullptr, // Format_RGBX64
destStore64RGBA64, // Format_RGBA64
nullptr, // Format_RGBA64_Premultiplied
- destStore64, // Format_Grayscale16
+ destStore64Gray16, // Format_Grayscale16
destStore64, // Format_BGR888
+ destStore64, // Format_RGBX16FPx4
+ destStore64, // Format_RGBA16FPx4
+ destStore64, // Format_RGBA16FPx4_Premultiplied
+ destStore64, // Format_RGBX32FPx4
+ destStore64, // Format_RGBA32FPx4
+ destStore64, // Format_RGBA32FPx4_Premultiplied
};
#endif
+#if QT_CONFIG(raster_fp)
+static void QT_FASTCALL destStoreFP(QRasterBuffer *rasterBuffer, int x, int y, const QRgba32F *buffer, int length)
+{
+ auto store = qStoreFromRGBA32F[rasterBuffer->format];
+ uchar *dest = rasterBuffer->scanLine(y);
+ store(dest, buffer, x, length, nullptr, nullptr);
+}
+#endif
+
/*
Source fetches
@@ -484,6 +856,15 @@ static const QRgba64 *QT_FASTCALL fetchUntransformedRGBA64PM(QRgba64 *, const Op
}
#endif
+#if QT_CONFIG(raster_fp)
+static const QRgba32F *QT_FASTCALL fetchUntransformedFP(QRgba32F *buffer, const Operator *,
+ const QSpanData *data, int y, int x, int length)
+{
+ const auto fetch = qFetchToRGBA32F[data->texture.format];
+ return fetch(buffer, data->texture.scanLine(y), x, length, data->texture.colorTable, nullptr);
+}
+#endif
+
template<TextureBlendType blendType>
inline void fetchTransformed_pixelBounds(int max, int l1, int l2, int &v)
{
@@ -528,9 +909,9 @@ static void QT_FASTCALL fetchTransformed_fetcher(T *buffer, const QSpanData *dat
constexpr bool useFetch = (bpp < QPixelLayout::BPP32) && sizeof(T) == sizeof(uint);
const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
if (!useFetch)
- Q_ASSERT(layout->bpp == bpp);
+ Q_ASSERT(layout->bpp == bpp || (layout->bpp == QPixelLayout::BPP16FPx4 && bpp == QPixelLayout::BPP64));
// When templated 'fetch' should be inlined at compile time:
- const FetchPixelFunc fetch = (bpp == QPixelLayout::BPPNone) ? qFetchPixelTable[layout->bpp] : FetchPixelFunc(qFetchPixel<bpp>);
+ const Fetch1PixelFunc fetch1 = (bpp == QPixelLayout::BPPNone) ? fetch1PixelTable[layout->bpp] : Fetch1PixelFunc(fetch1Pixel<bpp>);
if (canUseFastMatrixPath(cx, cy, length, data)) {
// The increment pr x in the scanline
@@ -561,8 +942,8 @@ static void QT_FASTCALL fetchTransformed_fetcher(T *buffer, const QSpanData *dat
fetchTransformed_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, x1);
if (x1 == x2)
break;
- if (useFetch)
- buffer[i] = fetch(src, x1);
+ if constexpr (useFetch)
+ buffer[i] = fetch1(src, x1);
else
buffer[i] = reinterpret_cast<const T*>(src)[x1];
fx += fdx;
@@ -570,8 +951,8 @@ static void QT_FASTCALL fetchTransformed_fetcher(T *buffer, const QSpanData *dat
for (; i < fastLen; ++i) {
int px = (fx >> 16);
- if (useFetch)
- buffer[i] = fetch(src, px);
+ if constexpr (useFetch)
+ buffer[i] = fetch1(src, px);
else
buffer[i] = reinterpret_cast<const T*>(src)[px];
fx += fdx;
@@ -581,8 +962,8 @@ static void QT_FASTCALL fetchTransformed_fetcher(T *buffer, const QSpanData *dat
for (; i < length; ++i) {
int px = (fx >> 16);
fetchTransformed_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, px);
- if (useFetch)
- buffer[i] = fetch(src, px);
+ if constexpr (useFetch)
+ buffer[i] = fetch1(src, px);
else
buffer[i] = reinterpret_cast<const T*>(src)[px];
fx += fdx;
@@ -609,8 +990,8 @@ static void QT_FASTCALL fetchTransformed_fetcher(T *buffer, const QSpanData *dat
fetchTransformed_pixelBounds<blendType>(image.height, image.y1, image.y2 - 1, y1);
if (x1 == x2 && y1 == y2)
break;
- if (useFetch)
- buffer[i] = fetch(image.scanLine(y1), x1);
+ if constexpr (useFetch)
+ buffer[i] = fetch1(image.scanLine(y1), x1);
else
buffer[i] = reinterpret_cast<const T*>(image.scanLine(y1))[x1];
fx += fdx;
@@ -620,8 +1001,8 @@ static void QT_FASTCALL fetchTransformed_fetcher(T *buffer, const QSpanData *dat
for (; i < fastLen; ++i) {
int px = (fx >> 16);
int py = (fy >> 16);
- if (useFetch)
- buffer[i] = fetch(image.scanLine(py), px);
+ if constexpr (useFetch)
+ buffer[i] = fetch1(image.scanLine(py), px);
else
buffer[i] = reinterpret_cast<const T*>(image.scanLine(py))[px];
fx += fdx;
@@ -634,8 +1015,8 @@ static void QT_FASTCALL fetchTransformed_fetcher(T *buffer, const QSpanData *dat
int py = (fy >> 16);
fetchTransformed_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, px);
fetchTransformed_pixelBounds<blendType>(image.height, image.y1, image.y2 - 1, py);
- if (useFetch)
- buffer[i] = fetch(image.scanLine(py), px);
+ if constexpr (useFetch)
+ buffer[i] = fetch1(image.scanLine(py), px);
else
buffer[i] = reinterpret_cast<const T*>(image.scanLine(py))[px];
fx += fdx;
@@ -662,8 +1043,8 @@ static void QT_FASTCALL fetchTransformed_fetcher(T *buffer, const QSpanData *dat
fetchTransformed_pixelBounds<blendType>(image.height, image.y1, image.y2 - 1, py);
fetchTransformed_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, px);
- if (useFetch)
- *b = fetch(image.scanLine(py), px);
+ if constexpr (useFetch)
+ *b = fetch1(image.scanLine(py), px);
else
*b = reinterpret_cast<const T*>(image.scanLine(py))[px];
@@ -696,7 +1077,7 @@ static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Oper
int y, int x, int length)
{
const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
- if (layout->bpp != QPixelLayout::BPP64) {
+ if (layout->bpp < QPixelLayout::BPP64) {
uint buffer32[BufferSize];
Q_ASSERT(length <= BufferSize);
if (layout->bpp == QPixelLayout::BPP32)
@@ -706,9 +1087,37 @@ static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Oper
return layout->convertToRGBA64PM(buffer, buffer32, length, data->texture.colorTable, nullptr);
}
- fetchTransformed_fetcher<blendType, QPixelLayout::BPP64, QRgba64>(buffer, data, y, x, length);
- if (data->texture.format == QImage::Format_RGBA64)
- convertRGBA64ToRGBA64PM(buffer, length);
+ fetchTransformed_fetcher<blendType, QPixelLayout::BPP64, quint64>(reinterpret_cast<quint64*>(buffer), data, y, x, length);
+ if (auto convert = convert64ToRGBA64PM[data->texture.format])
+ convert(buffer, length);
+ return buffer;
+}
+#endif
+
+#if QT_CONFIG(raster_fp)
+template<TextureBlendType blendType> /* either BlendTransformed or BlendTransformedTiled */
+static const QRgba32F *QT_FASTCALL fetchTransformedFP(QRgba32F *buffer, const Operator *, const QSpanData *data,
+ int y, int x, int length)
+{
+ const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
+ if (layout->bpp < QPixelLayout::BPP64) {
+ uint buffer32[BufferSize];
+ Q_ASSERT(length <= BufferSize);
+ if (layout->bpp == QPixelLayout::BPP32)
+ fetchTransformed_fetcher<blendType, QPixelLayout::BPP32, uint>(buffer32, data, y, x, length);
+ else
+ fetchTransformed_fetcher<blendType, QPixelLayout::BPPNone, uint>(buffer32, data, y, x, length);
+ qConvertToRGBA32F[data->texture.format](buffer, buffer32, length, data->texture.colorTable, nullptr);
+ } else if (layout->bpp < QPixelLayout::BPP32FPx4) {
+ quint64 buffer64[BufferSize];
+ fetchTransformed_fetcher<blendType, QPixelLayout::BPP64, quint64>(buffer64, data, y, x, length);
+ convert64ToRGBA32F[data->texture.format](buffer, buffer64, length);
+ } else {
+ fetchTransformed_fetcher<blendType, QPixelLayout::BPP32FPx4, QRgba32F>(buffer, data, y, x, length);
+ if (data->texture.format == QImage::Format_RGBA32FPx4)
+ convertRGBA32FToRGBA32FPM(buffer, length);
+ return buffer;
+ }
return buffer;
}
#endif
@@ -1681,8 +2090,8 @@ static void QT_FASTCALL fetchTransformedBilinear_fetcher(T *buf1, T *buf2, const
if (useFetch)
Q_ASSERT(sizeof(T) == sizeof(uint));
else
- Q_ASSERT(layout.bpp == bpp);
- const FetchPixelFunc fetch1 = (bpp == QPixelLayout::BPPNone) ? qFetchPixelTable[layout.bpp] : qFetchPixel<bpp>;
+ Q_ASSERT(layout.bpp == bpp || (layout.bpp == QPixelLayout::BPP16FPx4 && bpp == QPixelLayout::BPP64));
+ const Fetch1PixelFunc fetch1 = (bpp == QPixelLayout::BPPNone) ? fetch1PixelTable[layout.bpp] : fetch1Pixel<bpp>;
if (fdy == 0) {
int y1 = (fy >> 16);
int y2;
@@ -1698,7 +2107,7 @@ static void QT_FASTCALL fetchTransformedBilinear_fetcher(T *buf1, T *buf2, const
fetchTransformedBilinear_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, x1, x2);
if (x1 != x2)
break;
- if (useFetch) {
+ if constexpr (useFetch) {
buf1[i * 2 + 0] = buf1[i * 2 + 1] = fetch1(s1, x1);
buf2[i * 2 + 0] = buf2[i * 2 + 1] = fetch1(s2, x1);
} else {
@@ -1715,7 +2124,7 @@ static void QT_FASTCALL fetchTransformedBilinear_fetcher(T *buf1, T *buf2, const
for (; i < fastLen; ++i) {
int x = (fx >> 16);
- if (useFetch) {
+ if constexpr (useFetch) {
buf1[i * 2 + 0] = fetch1(s1, x);
buf1[i * 2 + 1] = fetch1(s1, x + 1);
buf2[i * 2 + 0] = fetch1(s2, x);
@@ -1734,7 +2143,7 @@ static void QT_FASTCALL fetchTransformedBilinear_fetcher(T *buf1, T *buf2, const
int x1 = (fx >> 16);
int x2;
fetchTransformedBilinear_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, x1, x2);
- if (useFetch) {
+ if constexpr (useFetch) {
buf1[i * 2 + 0] = fetch1(s1, x1);
buf1[i * 2 + 1] = fetch1(s1, x2);
buf2[i * 2 + 0] = fetch1(s2, x1);
@@ -1761,7 +2170,7 @@ static void QT_FASTCALL fetchTransformedBilinear_fetcher(T *buf1, T *buf2, const
break;
const uchar *s1 = image.scanLine(y1);
const uchar *s2 = image.scanLine(y2);
- if (useFetch) {
+ if constexpr (useFetch) {
buf1[i * 2 + 0] = fetch1(s1, x1);
buf1[i * 2 + 1] = fetch1(s1, x2);
buf2[i * 2 + 0] = fetch1(s2, x1);
@@ -1790,7 +2199,7 @@ static void QT_FASTCALL fetchTransformedBilinear_fetcher(T *buf1, T *buf2, const
int y = (fy >> 16);
const uchar *s1 = image.scanLine(y);
const uchar *s2 = s1 + image.bytesPerLine;
- if (useFetch) {
+ if constexpr (useFetch) {
buf1[i * 2 + 0] = fetch1(s1, x);
buf1[i * 2 + 1] = fetch1(s1, x + 1);
buf2[i * 2 + 0] = fetch1(s2, x);
@@ -1816,7 +2225,7 @@ static void QT_FASTCALL fetchTransformedBilinear_fetcher(T *buf1, T *buf2, const
const uchar *s1 = image.scanLine(y1);
const uchar *s2 = image.scanLine(y2);
- if (useFetch) {
+ if constexpr (useFetch) {
buf1[i * 2 + 0] = fetch1(s1, x1);
buf1[i * 2 + 1] = fetch1(s1, x2);
buf2[i * 2 + 0] = fetch1(s2, x1);
@@ -1846,7 +2255,7 @@ static void QT_FASTCALL fetchTransformedBilinear_slow_fetcher(T *buf1, T *buf2,
else
Q_ASSERT(layout.bpp == bpp);
- const FetchPixelFunc fetch1 = (bpp == QPixelLayout::BPPNone) ? qFetchPixelTable[layout.bpp] : qFetchPixel<bpp>;
+ const Fetch1PixelFunc fetch1 = (bpp == QPixelLayout::BPPNone) ? fetch1PixelTable[layout.bpp] : fetch1Pixel<bpp>;
for (int i = 0; i < len; ++i) {
const qreal iw = fw == 0 ? 16384 : 1 / fw;
@@ -1866,7 +2275,7 @@ static void QT_FASTCALL fetchTransformedBilinear_slow_fetcher(T *buf1, T *buf2,
const uchar *s1 = image.scanLine(y1);
const uchar *s2 = image.scanLine(y2);
- if (useFetch) {
+ if constexpr (useFetch) {
buf1[i * 2 + 0] = fetch1(s1, x1);
buf1[i * 2 + 1] = fetch1(s1, x2);
buf2[i * 2 + 0] = fetch1(s2, x1);
@@ -2038,7 +2447,8 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64_uint32(QRgba64 *buf
int y, int x, int length)
{
const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
- const QList<QRgb> *clut = data->texture.colorTable;
+ const auto *clut = data->texture.colorTable;
+ const auto convert = layout->convertToRGBA64PM;
const qreal cx = x + qreal(0.5);
const qreal cy = y + qreal(0.5);
@@ -2047,7 +2457,6 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64_uint32(QRgba64 *buf
uint sbuf2[BufferSize];
alignas(8) QRgba64 buf1[BufferSize];
alignas(8) QRgba64 buf2[BufferSize];
- QRgba64 *end = buffer + length;
QRgba64 *b = buffer;
if (canUseFastMatrixPath(cx, cy, length, data)) {
@@ -2068,20 +2477,20 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64_uint32(QRgba64 *buf
if (fdy == 0) { //simple scale, no rotation
while (length) {
- int len = qMin(length, BufferSize / 2);
- int disty = (fy & 0x0000ffff);
+ const int len = qMin(length, BufferSize / 2);
+ const int disty = (fy & 0x0000ffff);
#if defined(__SSE2__)
const __m128i vdy = _mm_set1_epi16(disty);
const __m128i vidy = _mm_set1_epi16(0x10000 - disty);
#endif
fetcher(sbuf1, sbuf2, len, data->texture, fx, fy, fdx, fdy);
- layout->convertToRGBA64PM(buf1, sbuf1, len * 2, clut, nullptr);
+ convert(buf1, sbuf1, len * 2, clut, nullptr);
if (disty)
- layout->convertToRGBA64PM(buf2, sbuf2, len * 2, clut, nullptr);
+ convert(buf2, sbuf2, len * 2, clut, nullptr);
for (int i = 0; i < len; ++i) {
- int distx = (fx & 0x0000ffff);
+ const int distx = (fx & 0x0000ffff);
#if defined(__SSE2__)
__m128i vt = _mm_loadu_si128((const __m128i*)(buf1 + i*2));
if (disty) {
@@ -2106,17 +2515,17 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64_uint32(QRgba64 *buf
b += len;
}
} else { // rotation or shear
- while (b < end) {
- int len = qMin(length, BufferSize / 2);
+ while (length) {
+ const int len = qMin(length, BufferSize / 2);
fetcher(sbuf1, sbuf2, len, data->texture, fx, fy, fdx, fdy);
- layout->convertToRGBA64PM(buf1, sbuf1, len * 2, clut, nullptr);
- layout->convertToRGBA64PM(buf2, sbuf2, len * 2, clut, nullptr);
+ convert(buf1, sbuf1, len * 2, clut, nullptr);
+ convert(buf2, sbuf2, len * 2, clut, nullptr);
for (int i = 0; i < len; ++i) {
- int distx = (fx & 0x0000ffff);
- int disty = (fy & 0x0000ffff);
+ const int distx = (fx & 0x0000ffff);
+ const int disty = (fy & 0x0000ffff);
b[i] = interpolate_4_pixels_rgb64(buf1 + i*2, buf2 + i*2, distx, disty);
fx += fdx;
fy += fdy;
@@ -2147,8 +2556,8 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64_uint32(QRgba64 *buf
const int len = qMin(length, BufferSize / 2);
fetcher(sbuf1, sbuf2, distxs, distys, len, data->texture, fx, fy, fw, fdx, fdy, fdw);
- layout->convertToRGBA64PM(buf1, sbuf1, len * 2, clut, nullptr);
- layout->convertToRGBA64PM(buf2, sbuf2, len * 2, clut, nullptr);
+ convert(buf1, sbuf1, len * 2, clut, nullptr);
+ convert(buf2, sbuf2, len * 2, clut, nullptr);
for (int i = 0; i < len; ++i) {
const int distx = distxs[i];
@@ -2167,8 +2576,7 @@ template<TextureBlendType blendType>
static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64_uint64(QRgba64 *buffer, const QSpanData *data,
int y, int x, int length)
{
- Q_ASSERT(qPixelLayouts[data->texture.format].bpp == QPixelLayout::BPP64);
- const auto convert = (data->texture.format == QImage::Format_RGBA64) ? convertRGBA64ToRGBA64PM : convertRGBA64PMToRGBA64PM;
+ const auto convert = convert64ToRGBA64PM[data->texture.format];
const qreal cx = x + qreal(0.5);
const qreal cy = y + qreal(0.5);
@@ -2285,15 +2693,366 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64_uint64(QRgba64 *buf
}
template<TextureBlendType blendType>
+static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64_f32x4(QRgba64 *buffer, const QSpanData *data,
+ int y, int x, int length)
+{
+ const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
+ const auto *clut = data->texture.colorTable;
+ const auto convert = layout->fetchToRGBA64PM;
+
+ const qreal cx = x + qreal(0.5);
+ const qreal cy = y + qreal(0.5);
+
+ QRgba32F sbuf1[BufferSize];
+ QRgba32F sbuf2[BufferSize];
+ alignas(8) QRgba64 buf1[BufferSize];
+ alignas(8) QRgba64 buf2[BufferSize];
+ QRgba64 *b = buffer;
+
+ if (canUseFastMatrixPath(cx, cy, length, data)) {
+ // The increment pr x in the scanline
+ const int fdx = (int)(data->m11 * fixed_scale);
+ const int fdy = (int)(data->m12 * fixed_scale);
+
+ int fx = int((data->m21 * cy + data->m11 * cx + data->dx) * fixed_scale);
+ int fy = int((data->m22 * cy + data->m12 * cx + data->dy) * fixed_scale);
+
+ fx -= half_point;
+ fy -= half_point;
+
+ const auto fetcher = fetchTransformedBilinear_fetcher<blendType, QPixelLayout::BPP32FPx4, QRgba32F>;
+
+ const bool skipsecond = (fdy == 0) && ((fy & 0x0000ffff) == 0);
+ while (length) {
+ const int len = qMin(length, BufferSize / 2);
+
+ fetcher(sbuf1, sbuf2, len, data->texture, fx, fy, fdx, fdy);
+
+ convert(buf1, (const uchar *)sbuf1, 0, len * 2, clut, nullptr);
+ if (!skipsecond)
+ convert(buf2, (const uchar *)sbuf2, 0, len * 2, clut, nullptr);
+
+ for (int i = 0; i < len; ++i) {
+ const int distx = (fx & 0x0000ffff);
+ const int disty = (fy & 0x0000ffff);
+ b[i] = interpolate_4_pixels_rgb64(buf1 + i*2, buf2 + i*2, distx, disty);
+ fx += fdx;
+ fy += fdy;
+ }
+
+ length -= len;
+ b += len;
+ }
+ } else { // !(data->fast_matrix)
+ const auto fetcher = fetchTransformedBilinear_slow_fetcher<blendType, QPixelLayout::BPP32FPx4, QRgba32F>;
+
+ const qreal fdx = data->m11;
+ const qreal fdy = data->m12;
+ const qreal fdw = data->m13;
+
+ qreal fx = data->m21 * cy + data->m11 * cx + data->dx;
+ qreal fy = data->m22 * cy + data->m12 * cx + data->dy;
+ qreal fw = data->m23 * cy + data->m13 * cx + data->m33;
+
+ ushort distxs[BufferSize / 2];
+ ushort distys[BufferSize / 2];
+
+ while (length) {
+ const int len = qMin(length, BufferSize / 2);
+ fetcher(sbuf1, sbuf2, distxs, distys, len, data->texture, fx, fy, fw, fdx, fdy, fdw);
+
+ convert(buf1, (const uchar *)sbuf1, 0, len * 2, clut, nullptr);
+ convert(buf2, (const uchar *)sbuf2, 0, len * 2, clut, nullptr);
+
+ for (int i = 0; i < len; ++i) {
+ const int distx = distxs[i];
+ const int disty = distys[i];
+ b[i] = interpolate_4_pixels_rgb64(buf1 + i*2, buf2 + i*2, distx, disty);
+ }
+
+ length -= len;
+ b += len;
+ }
+ }
+ return buffer;
+}
+
+template<TextureBlendType blendType>
static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, const Operator *,
const QSpanData *data, int y, int x, int length)
{
- if (qPixelLayouts[data->texture.format].bpp == QPixelLayout::BPP64)
+ switch (qPixelLayouts[data->texture.format].bpp) {
+ case QPixelLayout::BPP64:
+ case QPixelLayout::BPP16FPx4:
return fetchTransformedBilinear64_uint64<blendType>(buffer, data, y, x, length);
- return fetchTransformedBilinear64_uint32<blendType>(buffer, data, y, x, length);
+ case QPixelLayout::BPP32FPx4:
+ return fetchTransformedBilinear64_f32x4<blendType>(buffer, data, y, x, length);
+ default:
+ return fetchTransformedBilinear64_uint32<blendType>(buffer, data, y, x, length);
+ }
}
#endif
+#if QT_CONFIG(raster_fp)
+static void interpolate_simple_rgba32f(QRgba32F *b, const QRgba32F *buf1, const QRgba32F *buf2, int len,
+ int &fx, int fdx,
+ int &fy, int fdy)
+{
+ for (int i = 0; i < len; ++i) {
+ const int distx = (fx & 0x0000ffff);
+ const int disty = (fy & 0x0000ffff);
+ b[i] = interpolate_4_pixels_rgba32f(buf1 + i*2, buf2 + i*2, distx, disty);
+ fx += fdx;
+ fy += fdy;
+ }
+}
+
+static void interpolate_perspective_rgba32f(QRgba32F *b, const QRgba32F *buf1, const QRgba32F *buf2, int len,
+ unsigned short *distxs,
+ unsigned short *distys)
+{
+ for (int i = 0; i < len; ++i) {
+ const int dx = distxs[i];
+ const int dy = distys[i];
+ b[i] = interpolate_4_pixels_rgba32f(buf1 + i*2, buf2 + i*2, dx, dy);
+ }
+}
+
+template<TextureBlendType blendType>
+static const QRgba32F *QT_FASTCALL fetchTransformedBilinearFP_uint32(QRgba32F *buffer, const QSpanData *data,
+ int y, int x, int length)
+{
+ const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
+ const auto *clut = data->texture.colorTable;
+ const auto convert = qConvertToRGBA32F[data->texture.format];
+
+ const qreal cx = x + qreal(0.5);
+ const qreal cy = y + qreal(0.5);
+
+ uint sbuf1[BufferSize];
+ uint sbuf2[BufferSize];
+ QRgba32F buf1[BufferSize];
+ QRgba32F buf2[BufferSize];
+ QRgba32F *b = buffer;
+
+ if (canUseFastMatrixPath(cx, cy, length, data)) {
+ // The increment pr x in the scanline
+ const int fdx = (int)(data->m11 * fixed_scale);
+ const int fdy = (int)(data->m12 * fixed_scale);
+
+ int fx = int((data->m21 * cy + data->m11 * cx + data->dx) * fixed_scale);
+ int fy = int((data->m22 * cy + data->m12 * cx + data->dy) * fixed_scale);
+
+ fx -= half_point;
+ fy -= half_point;
+
+ const auto fetcher =
+ (layout->bpp == QPixelLayout::BPP32)
+ ? fetchTransformedBilinear_fetcher<blendType, QPixelLayout::BPP32, uint>
+ : fetchTransformedBilinear_fetcher<blendType, QPixelLayout::BPPNone, uint>;
+
+ const bool skipsecond = (fdy == 0) && ((fy & 0x0000ffff) == 0);
+ while (length) {
+ const int len = qMin(length, BufferSize / 2);
+ fetcher(sbuf1, sbuf2, len, data->texture, fx, fy, fdx, fdy);
+
+ convert(buf1, sbuf1, len * 2, clut, nullptr);
+ if (!skipsecond)
+ convert(buf2, sbuf2, len * 2, clut, nullptr);
+
+ interpolate_simple_rgba32f(b, buf1, buf2, len, fx, fdx, fy, fdy);
+
+ length -= len;
+ b += len;
+ }
+ } else { // !(data->fast_matrix)
+ const auto fetcher =
+ (layout->bpp == QPixelLayout::BPP32)
+ ? fetchTransformedBilinear_slow_fetcher<blendType, QPixelLayout::BPP32, uint>
+ : fetchTransformedBilinear_slow_fetcher<blendType, QPixelLayout::BPPNone, uint>;
+
+ const qreal fdx = data->m11;
+ const qreal fdy = data->m12;
+ const qreal fdw = data->m13;
+ qreal fx = data->m21 * cy + data->m11 * cx + data->dx;
+ qreal fy = data->m22 * cy + data->m12 * cx + data->dy;
+ qreal fw = data->m23 * cy + data->m13 * cx + data->m33;
+ ushort distxs[BufferSize / 2];
+ ushort distys[BufferSize / 2];
+
+ while (length) {
+ const int len = qMin(length, BufferSize / 2);
+ fetcher(sbuf1, sbuf2, distxs, distys, len, data->texture, fx, fy, fw, fdx, fdy, fdw);
+
+ convert(buf1, sbuf1, len * 2, clut, nullptr);
+ convert(buf2, sbuf2, len * 2, clut, nullptr);
+
+ interpolate_perspective_rgba32f(b, buf1, buf2, len, distxs, distys);
+
+ length -= len;
+ b += len;
+ }
+ }
+ return buffer;
+}
+
+template<TextureBlendType blendType>
+static const QRgba32F *QT_FASTCALL fetchTransformedBilinearFP_uint64(QRgba32F *buffer, const QSpanData *data,
+ int y, int x, int length)
+{
+ const auto convert = convert64ToRGBA32F[data->texture.format];
+
+ const qreal cx = x + qreal(0.5);
+ const qreal cy = y + qreal(0.5);
+
+ quint64 sbuf1[BufferSize];
+ quint64 sbuf2[BufferSize];
+ QRgba32F buf1[BufferSize];
+ QRgba32F buf2[BufferSize];
+ QRgba32F *b = buffer;
+
+ if (canUseFastMatrixPath(cx, cy, length, data)) {
+ // The increment pr x in the scanline
+ const int fdx = (int)(data->m11 * fixed_scale);
+ const int fdy = (int)(data->m12 * fixed_scale);
+
+ int fx = int((data->m21 * cy + data->m11 * cx + data->dx) * fixed_scale);
+ int fy = int((data->m22 * cy + data->m12 * cx + data->dy) * fixed_scale);
+
+ fx -= half_point;
+ fy -= half_point;
+ const auto fetcher = fetchTransformedBilinear_fetcher<blendType, QPixelLayout::BPP64, quint64>;
+
+ const bool skipsecond = (fdy == 0) && ((fy & 0x0000ffff) == 0);
+ while (length) {
+ const int len = qMin(length, BufferSize / 2);
+ fetcher(sbuf1, sbuf2, len, data->texture, fx, fy, fdx, fdy);
+
+ convert(buf1, sbuf1, len * 2);
+ if (!skipsecond)
+ convert(buf2, sbuf2, len * 2);
+
+ interpolate_simple_rgba32f(b, buf1, buf2, len, fx, fdx, fy, fdy);
+
+ length -= len;
+ b += len;
+ }
+ } else { // !(data->fast_matrix)
+ const auto fetcher = fetchTransformedBilinear_slow_fetcher<blendType, QPixelLayout::BPP64, quint64>;
+
+ const qreal fdx = data->m11;
+ const qreal fdy = data->m12;
+ const qreal fdw = data->m13;
+
+ qreal fx = data->m21 * cy + data->m11 * cx + data->dx;
+ qreal fy = data->m22 * cy + data->m12 * cx + data->dy;
+ qreal fw = data->m23 * cy + data->m13 * cx + data->m33;
+
+ ushort distxs[BufferSize / 2];
+ ushort distys[BufferSize / 2];
+
+ while (length) {
+ const int len = qMin(length, BufferSize / 2);
+ fetcher(sbuf1, sbuf2, distxs, distys, len, data->texture, fx, fy, fw, fdx, fdy, fdw);
+
+ convert(buf1, sbuf1, len * 2);
+ convert(buf2, sbuf2, len * 2);
+
+ interpolate_perspective_rgba32f(b, buf1, buf2, len, distxs, distys);
+
+ length -= len;
+ b += len;
+ }
+ }
+ return buffer;
+}
+
+template<TextureBlendType blendType>
+static const QRgba32F *QT_FASTCALL fetchTransformedBilinearFP(QRgba32F *buffer, const QSpanData *data,
+ int y, int x, int length)
+{
+ const auto convert = data->rasterBuffer->format == QImage::Format_RGBA32FPx4 ? convertRGBA32FToRGBA32FPM
+ : convertRGBA32FToRGBA32F;
+
+ const qreal cx = x + qreal(0.5);
+ const qreal cy = y + qreal(0.5);
+
+ QRgba32F buf1[BufferSize];
+ QRgba32F buf2[BufferSize];
+ QRgba32F *b = buffer;
+
+ if (canUseFastMatrixPath(cx, cy, length, data)) {
+ // The increment pr x in the scanline
+ const int fdx = (int)(data->m11 * fixed_scale);
+ const int fdy = (int)(data->m12 * fixed_scale);
+
+ int fx = int((data->m21 * cy + data->m11 * cx + data->dx) * fixed_scale);
+ int fy = int((data->m22 * cy + data->m12 * cx + data->dy) * fixed_scale);
+
+ fx -= half_point;
+ fy -= half_point;
+ const auto fetcher = fetchTransformedBilinear_fetcher<blendType, QPixelLayout::BPP32FPx4, QRgba32F>;
+
+ const bool skipsecond = (fdy == 0) && ((fy & 0x0000ffff) == 0);
+ while (length) {
+ const int len = qMin(length, BufferSize / 2);
+ fetcher(buf1, buf2, len, data->texture, fx, fy, fdx, fdy);
+
+ convert(buf1, len * 2);
+ if (!skipsecond)
+ convert(buf2, len * 2);
+
+ interpolate_simple_rgba32f(b, buf1, buf2, len, fx, fdx, fy, fdy);
+
+ length -= len;
+ b += len;
+ }
+ } else { // !(data->fast_matrix)
+ const auto fetcher = fetchTransformedBilinear_slow_fetcher<blendType, QPixelLayout::BPP32FPx4, QRgba32F>;
+
+ const qreal fdx = data->m11;
+ const qreal fdy = data->m12;
+ const qreal fdw = data->m13;
+
+ qreal fx = data->m21 * cy + data->m11 * cx + data->dx;
+ qreal fy = data->m22 * cy + data->m12 * cx + data->dy;
+ qreal fw = data->m23 * cy + data->m13 * cx + data->m33;
+
+ ushort distxs[BufferSize / 2];
+ ushort distys[BufferSize / 2];
+
+ while (length) {
+ const int len = qMin(length, BufferSize / 2);
+ fetcher(buf1, buf2, distxs, distys, len, data->texture, fx, fy, fw, fdx, fdy, fdw);
+
+ convert(buf1, len * 2);
+ convert(buf2, len * 2);
+
+ interpolate_perspective_rgba32f(b, buf1, buf2, len, distxs, distys);
+
+ length -= len;
+ b += len;
+ }
+ }
+ return buffer;
+}
+
+template<TextureBlendType blendType>
+static const QRgba32F *QT_FASTCALL fetchTransformedBilinearFP(QRgba32F *buffer, const Operator *,
+ const QSpanData *data, int y, int x, int length)
+{
+ switch (qPixelLayouts[data->texture.format].bpp) {
+ case QPixelLayout::BPP64:
+ case QPixelLayout::BPP16FPx4:
+ return fetchTransformedBilinearFP_uint64<blendType>(buffer, data, y, x, length);
+ case QPixelLayout::BPP32FPx4:
+ return fetchTransformedBilinearFP<blendType>(buffer, data, y, x, length);
+ default:
+ return fetchTransformedBilinearFP_uint32<blendType>(buffer, data, y, x, length);
+ }
+}
+#endif // QT_CONFIG(raster_fp)
+
// FetchUntransformed can have more specialized methods added depending on SIMD features.
static SourceFetchProc sourceFetchUntransformed[QImage::NImageFormats] = {
nullptr, // Invalid
@@ -2326,6 +3085,12 @@ static SourceFetchProc sourceFetchUntransformed[QImage::NImageFormats] = {
fetchUntransformed, // RGBA64_Premultiplied
fetchUntransformed, // Grayscale16
fetchUntransformed, // BGR888
+ fetchUntransformed, // RGBX16FPx4
+ fetchUntransformed, // RGBA16FPx4
+ fetchUntransformed, // RGBA16FPx4_Premultiplied
+ fetchUntransformed, // RGBX32Px4
+ fetchUntransformed, // RGBA32FPx4
+ fetchUntransformed, // RGBA32FPx4_Premultiplied
};
static const SourceFetchProc sourceFetchGeneric[NBlendTypes] = {
@@ -2404,6 +3169,21 @@ static inline SourceFetchProc64 getSourceFetch64(TextureBlendType blendType, QIm
}
#endif
+#if QT_CONFIG(raster_fp)
+static const SourceFetchProcFP sourceFetchGenericFP[NBlendTypes] = {
+ fetchUntransformedFP, // Untransformed
+ fetchUntransformedFP, // Tiled
+ fetchTransformedFP<BlendTransformed>, // Transformed
+ fetchTransformedFP<BlendTransformedTiled>, // TransformedTiled
+ fetchTransformedBilinearFP<BlendTransformedBilinear>, // Bilinear
+ fetchTransformedBilinearFP<BlendTransformedBilinearTiled> // BilinearTiled
+};
+
+static inline SourceFetchProcFP getSourceFetchFP(TextureBlendType blendType, QImage::Format /*format*/)
+{
+ return sourceFetchGenericFP[blendType];
+}
+#endif
#define FIXPT_BITS 8
#define FIXPT_SIZE (1<<FIXPT_BITS)
@@ -2423,6 +3203,22 @@ static const QRgba64& qt_gradient_pixel64_fixed(const QGradientData *data, int f
}
#endif
+#if QT_CONFIG(raster_fp)
+static inline QRgba32F qt_gradient_pixelFP(const QGradientData *data, qreal pos)
+{
+ int ipos = int(pos * (GRADIENT_STOPTABLE_SIZE - 1) + qreal(0.5));
+ QRgba64 rgb64 = data->colorTable64[qt_gradient_clamp(data, ipos)];
+ return QRgba32F::fromRgba64(rgb64.red(),rgb64.green(), rgb64.blue(), rgb64.alpha());
+}
+
+static inline QRgba32F qt_gradient_pixelFP_fixed(const QGradientData *data, int fixed_pos)
+{
+ int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS;
+ QRgba64 rgb64 = data->colorTable64[qt_gradient_clamp(data, ipos)];
+ return QRgba32F::fromRgba64(rgb64.red(), rgb64.green(), rgb64.blue(), rgb64.alpha());
+}
+#endif
+
static void QT_FASTCALL getLinearGradientValues(LinearGradientValues *v, const QSpanData *data)
{
v->dx = data->gradient.linear.end.x - data->gradient.linear.origin.x;
@@ -2476,6 +3272,29 @@ public:
};
#endif
+#if QT_CONFIG(raster_fp)
+class GradientBaseFP
+{
+public:
+ typedef QRgba32F Type;
+ static Type null() { return QRgba32F::fromRgba64(0,0,0,0); }
+ static Type fetchSingle(const QGradientData& gradient, qreal v)
+ {
+ return qt_gradient_pixelFP(&gradient, v);
+ }
+ static Type fetchSingle(const QGradientData& gradient, int v)
+ {
+ return qt_gradient_pixelFP_fixed(&gradient, v);
+ }
+ static void memfill(Type *buffer, Type fill, int length)
+ {
+ quint64 fillCopy;
+ memcpy(&fillCopy, &fill, sizeof(quint64));
+ qt_memfill64((quint64*)buffer, fillCopy, length);
+ }
+};
+#endif
+
template<class GradientBase, typename BlendType>
static inline const BlendType * QT_FASTCALL qt_fetch_linear_gradient_template(
BlendType *buffer, const Operator *op, const QSpanData *data,
@@ -2561,6 +3380,13 @@ static const QRgba64 * QT_FASTCALL qt_fetch_linear_gradient_rgb64(QRgba64 *buffe
return qt_fetch_linear_gradient_template<GradientBase64, QRgba64>(buffer, op, data, y, x, length);
}
#endif
+#if QT_CONFIG(raster_fp)
+static const QRgba32F * QT_FASTCALL qt_fetch_linear_gradient_rgbfp(QRgba32F *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length)
+{
+ return qt_fetch_linear_gradient_template<GradientBaseFP, QRgba32F>(buffer, op, data, y, x, length);
+}
+#endif
static void QT_FASTCALL getRadialGradientValues(RadialGradientValues *v, const QSpanData *data)
{
@@ -2630,6 +3456,14 @@ const QRgba64 * QT_FASTCALL qt_fetch_radial_gradient_rgb64(QRgba64 *buffer, cons
}
#endif
+#if QT_CONFIG(raster_fp)
+static const QRgba32F * QT_FASTCALL qt_fetch_radial_gradient_rgbfp(QRgba32F *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length)
+{
+ return qt_fetch_radial_gradient_template<RadialFetchPlain<GradientBaseFP>, QRgba32F>(buffer, op, data, y, x, length);
+}
+#endif
+
template <class GradientBase, typename BlendType>
static inline const BlendType * QT_FASTCALL qt_fetch_conical_gradient_template(
BlendType *buffer, const QSpanData *data,
@@ -2695,21 +3529,37 @@ static const QRgba64 * QT_FASTCALL qt_fetch_conical_gradient_rgb64(QRgba64 *buff
}
#endif
+#if QT_CONFIG(raster_fp)
+static const QRgba32F * QT_FASTCALL qt_fetch_conical_gradient_rgbfp(QRgba32F *buffer, const Operator *, const QSpanData *data,
+ int y, int x, int length)
+{
+ return qt_fetch_conical_gradient_template<GradientBaseFP, QRgba32F>(buffer, data, y, x, length);
+}
+#endif
+
extern CompositionFunctionSolid qt_functionForModeSolid_C[];
extern CompositionFunctionSolid64 qt_functionForModeSolid64_C[];
+extern CompositionFunctionSolidFP qt_functionForModeSolidFP_C[];
static const CompositionFunctionSolid *functionForModeSolid = qt_functionForModeSolid_C;
#if QT_CONFIG(raster_64bit)
static const CompositionFunctionSolid64 *functionForModeSolid64 = qt_functionForModeSolid64_C;
#endif
+#if QT_CONFIG(raster_fp)
+static const CompositionFunctionSolidFP *functionForModeSolidFP = qt_functionForModeSolidFP_C;
+#endif
extern CompositionFunction qt_functionForMode_C[];
extern CompositionFunction64 qt_functionForMode64_C[];
+extern CompositionFunctionFP qt_functionForModeFP_C[];
static const CompositionFunction *functionForMode = qt_functionForMode_C;
#if QT_CONFIG(raster_64bit)
static const CompositionFunction64 *functionForMode64 = qt_functionForMode64_C;
#endif
+#if QT_CONFIG(raster_fp)
+static const CompositionFunctionFP *functionForModeFP = qt_functionForModeFP_C;
+#endif
static TextureBlendType getBlendType(const QSpanData *data)
{
@@ -2743,9 +3593,8 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
case QSpanData::Solid:
solidSource = data->solidColor.isOpaque();
op.srcFetch = nullptr;
-#if QT_CONFIG(raster_64bit)
op.srcFetch64 = nullptr;
-#endif
+ op.srcFetchFP = nullptr;
break;
case QSpanData::LinearGradient:
solidSource = !data->gradient.alphaColor;
@@ -2754,6 +3603,9 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
#if QT_CONFIG(raster_64bit)
op.srcFetch64 = qt_fetch_linear_gradient_rgb64;
#endif
+#if QT_CONFIG(raster_fp)
+ op.srcFetchFP = qt_fetch_linear_gradient_rgbfp;
+#endif
break;
case QSpanData::RadialGradient:
solidSource = !data->gradient.alphaColor;
@@ -2762,6 +3614,9 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
#if QT_CONFIG(raster_64bit)
op.srcFetch64 = qt_fetch_radial_gradient_rgb64;
#endif
+#if QT_CONFIG(raster_fp)
+ op.srcFetchFP = qt_fetch_radial_gradient_rgbfp;
+#endif
break;
case QSpanData::ConicalGradient:
solidSource = !data->gradient.alphaColor;
@@ -2769,6 +3624,9 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
#if QT_CONFIG(raster_64bit)
op.srcFetch64 = qt_fetch_conical_gradient_rgb64;
#endif
+#if QT_CONFIG(raster_fp)
+ op.srcFetchFP = qt_fetch_conical_gradient_rgbfp;
+#endif
break;
case QSpanData::Texture:
solidSource = !data->texture.hasAlpha;
@@ -2776,13 +3634,19 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
#if QT_CONFIG(raster_64bit)
op.srcFetch64 = getSourceFetch64(getBlendType(data), data->texture.format);;
#endif
+#if QT_CONFIG(raster_fp)
+ op.srcFetchFP = getSourceFetchFP(getBlendType(data), data->texture.format);
+#endif
break;
default:
Q_UNREACHABLE();
break;
}
#if !QT_CONFIG(raster_64bit)
- op.srcFetch64 = 0;
+ op.srcFetch64 = nullptr;
+#endif
+#if !QT_CONFIG(raster_fp)
+ op.srcFetchFP = nullptr;
#endif
op.mode = data->rasterBuffer->compositionMode;
@@ -2793,8 +3657,14 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
#if QT_CONFIG(raster_64bit)
op.destFetch64 = destFetchProc64[data->rasterBuffer->format];
#else
- op.destFetch64 = 0;
+ op.destFetch64 = nullptr;
+#endif
+#if QT_CONFIG(raster_fp)
+ if (data->rasterBuffer->format > QImage::Format_Indexed8)
+ op.destFetchFP = destFetchFP;
+ else
#endif
+ op.destFetchFP = nullptr;
if (op.mode == QPainter::CompositionMode_Source &&
(data->type != QSpanData::Texture || data->texture.const_alpha == 256)) {
const QSpan *lastSpan = spans + spanCount;
@@ -2815,6 +3685,9 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
if (op.destFetch64 != destFetchRGB64)
op.destFetch64 = destFetch64Undefined;
#endif
+#if QT_CONFIG(raster_fp)
+ op.destFetchFP = destFetchFPUndefined;
+#endif
}
}
@@ -2826,9 +3699,18 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
op.funcSolid64 = functionForModeSolid64[op.mode];
op.func64 = functionForMode64[op.mode];
#else
- op.destStore64 = 0;
- op.funcSolid64 = 0;
- op.func64 = 0;
+ op.destStore64 = nullptr;
+ op.funcSolid64 = nullptr;
+ op.func64 = nullptr;
+#endif
+#if QT_CONFIG(raster_fp)
+ op.destStoreFP = destStoreFP;
+ op.funcSolidFP = functionForModeSolidFP[op.mode];
+ op.funcFP = functionForModeFP[op.mode];
+#else
+ op.destStoreFP = nullptr;
+ op.funcSolidFP = nullptr;
+ op.funcFP = nullptr;
#endif
return op;
@@ -2837,6 +3719,12 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
static void spanfill_from_first(QRasterBuffer *rasterBuffer, QPixelLayout::BPP bpp, int x, int y, int length)
{
switch (bpp) {
+ case QPixelLayout::BPP32FPx4: {
+ QRgba32F *dest = reinterpret_cast<QRgba32F *>(rasterBuffer->scanLine(y)) + x;
+ qt_memfill_template(dest + 1, dest[0], length - 1);
+ break;
+ }
+ case QPixelLayout::BPP16FPx4:
case QPixelLayout::BPP64: {
quint64 *dest = reinterpret_cast<quint64 *>(rasterBuffer->scanLine(y)) + x;
qt_memfill_template(dest + 1, dest[0], length - 1);
@@ -2937,7 +3825,7 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData)
}
}
-void blend_color_generic_rgb64(int count, const QSpan *spans, void *userData)
+static void blend_color_generic_rgb64(int count, const QSpan *spans, void *userData)
{
#if QT_CONFIG(raster_64bit)
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
@@ -2978,6 +3866,47 @@ void blend_color_generic_rgb64(int count, const QSpan *spans, void *userData)
#endif
}
+static void blend_color_generic_fp(int count, const QSpan *spans, void *userData)
+{
+#if QT_CONFIG(raster_fp)
+ QSpanData *data = reinterpret_cast<QSpanData *>(userData);
+ Operator op = getOperator(data, nullptr, 0);
+ if (!op.funcSolidFP || !op.destFetchFP) {
+ qCDebug(lcQtGuiDrawHelper, "blend_color_generic_fp: unsupported 4xF16 blend attempted, falling back to 32-bit");
+ return blend_color_generic(count, spans, userData);
+ }
+
+ QRgba32F buffer[BufferSize];
+ const QRgba32F color = qConvertRgb64ToRgbaF32(data->solidColor);
+ const bool solidFill = op.mode == QPainter::CompositionMode_Source;
+ QPixelLayout::BPP bpp = qPixelLayouts[data->rasterBuffer->format].bpp;
+
+ while (count--) {
+ int x = spans->x;
+ int length = spans->len;
+ if (solidFill && bpp >= QPixelLayout::BPP8 && spans->coverage == 255 && length && op.destStoreFP) {
+ // If dest doesn't matter we don't need to bother with blending or converting all the identical pixels
+ op.destStoreFP(data->rasterBuffer, x, spans->y, &color, 1);
+ spanfill_from_first(data->rasterBuffer, bpp, x, spans->y, length);
+ length = 0;
+ }
+
+ while (length) {
+ int l = qMin(BufferSize, length);
+ QRgba32F *dest = op.destFetchFP(buffer, data->rasterBuffer, x, spans->y, l);
+ op.funcSolidFP(dest, l, color, spans->coverage);
+ if (op.destStoreFP)
+ op.destStoreFP(data->rasterBuffer, x, spans->y, dest, l);
+ length -= l;
+ x += l;
+ }
+ ++spans;
+ }
+#else
+ blend_color_generic(count, spans, userData);
+#endif
+}
+
template <typename T>
void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handler)
{
@@ -3008,7 +3937,7 @@ void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handle
int process_length = l;
int process_x = x;
- const typename T::BlendType *src = handler.fetch(process_x, y, process_length);
+ const auto *src = handler.fetch(process_x, y, process_length);
int offset = 0;
while (l > 0) {
if (x == spans->x) // new span?
@@ -3033,31 +3962,20 @@ void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handle
}
}
-template<typename T>
struct QBlendBase
{
- typedef T BlendType;
- QBlendBase(QSpanData *d, const Operator &o)
- : data(d)
- , op(o)
- , dest(nullptr)
- {
- }
-
QSpanData *data;
Operator op;
-
- BlendType *dest;
-
- alignas(8) BlendType buffer[BufferSize];
- alignas(8) BlendType src_buffer[BufferSize];
};
-class BlendSrcGeneric : public QBlendBase<uint>
+class BlendSrcGeneric : public QBlendBase
{
public:
+ uint *dest = nullptr;
+ alignas(16) uint buffer[BufferSize];
+ alignas(16) uint src_buffer[BufferSize];
BlendSrcGeneric(QSpanData *d, const Operator &o)
- : QBlendBase<uint>(d, o)
+ : QBlendBase{d, o}
{
}
@@ -3080,11 +3998,14 @@ public:
};
#if QT_CONFIG(raster_64bit)
-class BlendSrcGenericRGB64 : public QBlendBase<QRgba64>
+class BlendSrcGenericRGB64 : public QBlendBase
{
public:
+ QRgba64 *dest = nullptr;
+ alignas(16) QRgba64 buffer[BufferSize];
+ alignas(16) QRgba64 src_buffer[BufferSize];
BlendSrcGenericRGB64(QSpanData *d, const Operator &o)
- : QBlendBase<QRgba64>(d, o)
+ : QBlendBase{d, o}
{
}
@@ -3112,6 +4033,42 @@ public:
};
#endif
+#if QT_CONFIG(raster_fp)
+class BlendSrcGenericRGBFP : public QBlendBase
+{
+public:
+ QRgba32F *dest = nullptr;
+ alignas(16) QRgba32F buffer[BufferSize];
+ alignas(16) QRgba32F src_buffer[BufferSize];
+ BlendSrcGenericRGBFP(QSpanData *d, const Operator &o)
+ : QBlendBase{d, o}
+ {
+ }
+
+ bool isSupported() const
+ {
+ return op.funcFP && op.destFetchFP && op.srcFetchFP;
+ }
+
+ const QRgba32F *fetch(int x, int y, int len)
+ {
+ dest = op.destFetchFP(buffer, data->rasterBuffer, x, y, len);
+ return op.srcFetchFP(src_buffer, &op, data, y, x, len);
+ }
+
+ void process(int, int, int len, int coverage, const QRgba32F *src, int offset)
+ {
+ op.funcFP(dest + offset, src + offset, len, coverage);
+ }
+
+ void store(int x, int y, int len)
+ {
+ if (op.destStoreFP)
+ op.destStoreFP(data->rasterBuffer, x, y, dest, len);
+ }
+};
+#endif
+
static void blend_src_generic(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
@@ -3135,6 +4092,22 @@ static void blend_src_generic_rgb64(int count, const QSpan *spans, void *userDat
}
#endif
+#if QT_CONFIG(raster_fp)
+static void blend_src_generic_fp(int count, const QSpan *spans, void *userData)
+{
+ QSpanData *data = reinterpret_cast<QSpanData *>(userData);
+ Operator op = getOperator(data, spans, count);
+ BlendSrcGenericRGBFP blendFP(data, op);
+ if (blendFP.isSupported())
+ handleSpans(count, spans, data, blendFP);
+ else {
+ qCDebug(lcQtGuiDrawHelper, "blend_src_generic_fp: unsupported 4xFP blend attempted, falling back to 32-bit");
+ BlendSrcGeneric blend32(data, op);
+ handleSpans(count, spans, data, blend32);
+ }
+}
+#endif
+
static void blend_untransformed_generic(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
@@ -3233,6 +4206,58 @@ static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, voi
}
#endif
+#if QT_CONFIG(raster_fp)
+static void blend_untransformed_generic_fp(int count, const QSpan *spans, void *userData)
+{
+ QSpanData *data = reinterpret_cast<QSpanData *>(userData);
+
+ Operator op = getOperator(data, spans, count);
+ if (!op.funcFP) {
+ qCDebug(lcQtGuiDrawHelper, "blend_untransformed_generic_rgbaf16: unsupported 4xFP16 blend attempted, falling back to 32-bit");
+ return blend_untransformed_generic(count, spans, userData);
+ }
+ QRgba32F buffer[BufferSize];
+ QRgba32F src_buffer[BufferSize];
+
+ const int image_width = data->texture.width;
+ const int image_height = data->texture.height;
+ int xoff = -qRound(-data->dx);
+ int yoff = -qRound(-data->dy);
+
+ for (; count--; spans++) {
+ if (!spans->len)
+ continue;
+ int x = spans->x;
+ int length = spans->len;
+ int sx = xoff + x;
+ int sy = yoff + spans->y;
+ if (sy >= 0 && sy < image_height && sx < image_width) {
+ if (sx < 0) {
+ x -= sx;
+ length += sx;
+ sx = 0;
+ }
+ if (sx + length > image_width)
+ length = image_width - sx;
+ if (length > 0) {
+ const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
+ while (length) {
+ int l = qMin(BufferSize, length);
+ const QRgba32F *src = op.srcFetchFP(src_buffer, &op, data, sy, sx, l);
+ QRgba32F *dest = op.destFetchFP(buffer, data->rasterBuffer, x, spans->y, l);
+ op.funcFP(dest, src, l, coverage);
+ if (op.destStoreFP)
+ op.destStoreFP(data->rasterBuffer, x, spans->y, dest, l);
+ x += l;
+ sx += l;
+ length -= l;
+ }
+ }
+ }
+ }
+}
+#endif
+
static void blend_untransformed_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
@@ -3536,6 +4561,62 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD
}
#endif
+#if QT_CONFIG(raster_fp)
+static void blend_tiled_generic_fp(int count, const QSpan *spans, void *userData)
+{
+ QSpanData *data = reinterpret_cast<QSpanData *>(userData);
+
+ Operator op = getOperator(data, spans, count);
+ if (!op.funcFP) {
+ qCDebug(lcQtGuiDrawHelper, "blend_tiled_generic_fp: unsupported 4xFP blend attempted, falling back to 32-bit");
+ return blend_tiled_generic(count, spans, userData);
+ }
+ QRgba32F buffer[BufferSize];
+ QRgba32F src_buffer[BufferSize];
+
+ const int image_width = data->texture.width;
+ const int image_height = data->texture.height;
+ int xoff = -qRound(-data->dx) % image_width;
+ int yoff = -qRound(-data->dy) % image_height;
+
+ if (xoff < 0)
+ xoff += image_width;
+ if (yoff < 0)
+ yoff += image_height;
+
+ // Consider tiling optimizing like the other versions.
+
+ while (count--) {
+ int x = spans->x;
+ int length = spans->len;
+ int sx = (xoff + spans->x) % image_width;
+ int sy = (spans->y + yoff) % image_height;
+ if (sx < 0)
+ sx += image_width;
+ if (sy < 0)
+ sy += image_height;
+
+ const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
+ while (length) {
+ int l = qMin(image_width - sx, length);
+ if (BufferSize < l)
+ l = BufferSize;
+ const QRgba32F *src = op.srcFetchFP(src_buffer, &op, data, sy, sx, l);
+ QRgba32F *dest = op.destFetchFP(buffer, data->rasterBuffer, x, spans->y, l);
+ op.funcFP(dest, src, l, coverage);
+ if (op.destStoreFP)
+ op.destStoreFP(data->rasterBuffer, x, spans->y, dest, l);
+ x += l;
+ sx += l;
+ length -= l;
+ if (sx >= image_width)
+ sx = 0;
+ }
+ ++spans;
+ }
+}
+#endif
+
static void blend_tiled_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
@@ -3722,19 +4803,31 @@ static const ProcessSpans processTextureSpansGeneric64[NBlendTypes] = {
};
#endif
+#if QT_CONFIG(raster_fp)
+static const ProcessSpans processTextureSpansGenericFP[NBlendTypes] = {
+ blend_untransformed_generic_fp, // Untransformed
+ blend_tiled_generic_fp, // Tiled
+ blend_src_generic_fp, // Transformed
+ blend_src_generic_fp, // TransformedTiled
+ blend_src_generic_fp, // TransformedBilinear
+ blend_src_generic_fp // TransformedBilinearTiled
+};
+#endif
void qBlendTexture(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
TextureBlendType blendType = getBlendType(data);
ProcessSpans proc;
switch (data->rasterBuffer->format) {
+ case QImage::Format_Invalid:
+ Q_UNREACHABLE();
+ return;
case QImage::Format_ARGB32_Premultiplied:
proc = processTextureSpansARGB32PM[blendType];
break;
case QImage::Format_RGB16:
proc = processTextureSpansRGB16[blendType];
break;
-#if QT_CONFIG(raster_64bit)
#if defined(__SSE2__) || defined(__ARM_NEON__) || (Q_PROCESSOR_WORDSIZE == 8)
case QImage::Format_ARGB32:
case QImage::Format_RGBA8888:
@@ -3747,12 +4840,28 @@ void qBlendTexture(int count, const QSpan *spans, void *userData)
case QImage::Format_RGBA64:
case QImage::Format_RGBA64_Premultiplied:
case QImage::Format_Grayscale16:
+#if !QT_CONFIG(raster_fp)
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+#endif
+#if QT_CONFIG(raster_64bit)
proc = processTextureSpansGeneric64[blendType];
break;
#endif // QT_CONFIG(raster_64bit)
- case QImage::Format_Invalid:
- Q_UNREACHABLE();
- return;
+#if QT_CONFIG(raster_fp)
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+ proc = processTextureSpansGenericFP[blendType];
+ break;
+#endif
default:
proc = processTextureSpansGeneric[blendType];
break;
@@ -3835,12 +4944,13 @@ void qBlendGradient(int count, const QSpan *spans, void *userData)
data->type == QSpanData::LinearGradient &&
data->gradient.linear.end.x == data->gradient.linear.origin.x;
switch (data->rasterBuffer->format) {
+ case QImage::Format_Invalid:
+ break;
case QImage::Format_RGB32:
case QImage::Format_ARGB32_Premultiplied:
if (isVerticalGradient)
return blend_vertical_gradient_argb(count, spans, userData);
return blend_src_generic(count, spans, userData);
-#if QT_CONFIG(raster_64bit)
#if defined(__SSE2__) || defined(__ARM_NEON__) || (Q_PROCESSOR_WORDSIZE == 8)
case QImage::Format_ARGB32:
case QImage::Format_RGBA8888:
@@ -3852,12 +4962,30 @@ void qBlendGradient(int count, const QSpan *spans, void *userData)
case QImage::Format_RGBX64:
case QImage::Format_RGBA64:
case QImage::Format_RGBA64_Premultiplied:
+#if !QT_CONFIG(raster_fp)
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+#endif
+#if QT_CONFIG(raster_64bit)
if (isVerticalGradient)
return blend_vertical_gradient<blend_color_generic_rgb64>(count, spans, userData);
return blend_src_generic_rgb64(count, spans, userData);
#endif // QT_CONFIG(raster_64bit)
- case QImage::Format_Invalid:
- break;
+#if QT_CONFIG(raster_fp)
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+ if (isVerticalGradient)
+ return blend_vertical_gradient<blend_color_generic_fp>(count, spans, userData);
+ return blend_src_generic_fp(count, spans, userData);
+#endif
default:
if (isVerticalGradient)
return blend_vertical_gradient<blend_color_generic>(count, spans, userData);
@@ -4716,6 +5844,17 @@ static void qt_rectfill_quint64(QRasterBuffer *rasterBuffer,
c64, x, y, width, height, rasterBuffer->bytesPerLine());
}
+static void qt_rectfill_fp32x4(QRasterBuffer *rasterBuffer,
+ int x, int y, int width, int height,
+ const QRgba64 &color)
+{
+ const auto store = qStoreFromRGBA64PM[rasterBuffer->format];
+ QRgba32F c;
+ store(reinterpret_cast<uchar *>(&c), &color, 0, 1, nullptr, nullptr);
+ qt_rectfill<QRgba32F>(reinterpret_cast<QRgba32F *>(rasterBuffer->buffer()),
+ c, x, y, width, height, rasterBuffer->bytesPerLine());
+}
+
// Map table for destination image format. Contains function pointers
// for blends of various types unto the destination
@@ -4946,6 +6085,54 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
qt_alphargbblit_generic,
qt_rectfill_quint24
},
+ // Format_RGBX16FPx4
+ {
+ blend_color_generic_fp,
+ nullptr,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
+ qt_rectfill_quint64
+ },
+ // Format_RGBA16FPx4
+ {
+ blend_color_generic_fp,
+ nullptr,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
+ qt_rectfill_quint64
+ },
+ // Format_RGBA16FPx4_Premultiplied
+ {
+ blend_color_generic_fp,
+ nullptr,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
+ qt_rectfill_quint64
+ },
+ // Format_RGBX32FPx4
+ {
+ blend_color_generic_fp,
+ nullptr,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
+ qt_rectfill_fp32x4
+ },
+ // Format_RGBA32FPx4
+ {
+ blend_color_generic_fp,
+ nullptr,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
+ qt_rectfill_fp32x4
+ },
+ // Format_RGBA32FPx4_Premultiplied
+ {
+ blend_color_generic_fp,
+ nullptr,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
+ qt_rectfill_fp32x4
+ },
};
#if !defined(__SSE2__)
@@ -5170,6 +6357,14 @@ static void qInitDrawhelperFunctions()
destStoreProc64[QImage::Format_ARGB32] = destStore64ARGB32_sse4;
destStoreProc64[QImage::Format_RGBA8888] = destStore64RGBA8888_sse4;
#endif
+#if QT_CONFIG(raster_fp)
+ extern const QRgba32F *QT_FASTCALL fetchRGBA32FToRGBA32F_sse4(QRgba32F *buffer, const uchar *src, int index, int count, const QList<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL storeRGBX32FFromRGBA32F_sse4(uchar *dest, const QRgba32F *src, int index, int count, const QList<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL storeRGBA32FFromRGBA32F_sse4(uchar *dest, const QRgba32F *src, int index, int count, const QList<QRgb> *, QDitherInfo *);
+ qFetchToRGBA32F[QImage::Format_RGBA32FPx4] = fetchRGBA32FToRGBA32F_sse4;
+ qStoreFromRGBA32F[QImage::Format_RGBX32FPx4] = storeRGBX32FFromRGBA32F_sse4;
+ qStoreFromRGBA32F[QImage::Format_RGBA32FPx4] = storeRGBA32FFromRGBA32F_sse4;
+#endif // QT_CONFIG(raster_fp)
}
#endif
@@ -5206,6 +6401,16 @@ static void qInitDrawhelperFunctions()
qt_functionForMode64_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_rgb64_avx2;
qt_functionForModeSolid64_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_rgb64_avx2;
#endif
+#if QT_CONFIG(raster_fp)
+ extern void QT_FASTCALL comp_func_Source_rgbafp_avx2(QRgba32F *destPixels, const QRgba32F *srcPixels, int length, uint const_alpha);
+ extern void QT_FASTCALL comp_func_SourceOver_rgbafp_avx2(QRgba32F *destPixels, const QRgba32F *srcPixels, int length, uint const_alpha);
+ extern void QT_FASTCALL comp_func_solid_Source_rgbafp_avx2(QRgba32F *destPixels, int length, QRgba32F color, uint const_alpha);
+ extern void QT_FASTCALL comp_func_solid_SourceOver_rgbafp_avx2(QRgba32F *destPixels, int length, QRgba32F color, uint const_alpha);
+ qt_functionForModeFP_C[QPainter::CompositionMode_Source] = comp_func_Source_rgbafp_avx2;
+ qt_functionForModeFP_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_rgbafp_avx2;
+ qt_functionForModeSolidFP_C[QPainter::CompositionMode_Source] = comp_func_solid_Source_rgbafp_avx2;
+ qt_functionForModeSolidFP_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_rgbafp_avx2;
+#endif
extern void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_scale_helper_avx2(uint *b, uint *end, const QTextureData &image,
int &fx, int &fy, int fdx, int /*fdy*/);
@@ -5239,7 +6444,35 @@ static void qInitDrawhelperFunctions()
qPixelLayouts[QImage::Format_ARGB32].fetchToRGBA64PM = fetchARGB32ToRGBA64PM_avx2;
qPixelLayouts[QImage::Format_RGBX8888].fetchToRGBA64PM = fetchRGBA8888ToRGBA64PM_avx2;
qPixelLayouts[QImage::Format_RGBA64].fetchToRGBA64PM = fetchRGBA64ToRGBA64PM_avx2;
+
+ extern const uint *QT_FASTCALL fetchRGB16FToRGB32_avx2(uint *buffer, const uchar *src, int index, int count, const QList<QRgb> *, QDitherInfo *);
+ extern const uint *QT_FASTCALL fetchRGBA16FToARGB32PM_avx2(uint *buffer, const uchar *src, int index, int count, const QList<QRgb> *, QDitherInfo *);
+ extern const QRgba64 *QT_FASTCALL fetchRGBA16FPMToRGBA64PM_avx2(QRgba64 *buffer, const uchar *src, int index, int count, const QList<QRgb> *, QDitherInfo *);
+ extern const QRgba64 *QT_FASTCALL fetchRGBA16FToRGBA64PM_avx2(QRgba64 *buffer, const uchar *src, int index, int count, const QList<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL storeRGB16FFromRGB32_avx2(uchar *dest, const uint *src, int index, int count, const QList<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL storeRGBA16FFromARGB32PM_avx2(uchar *dest, const uint *src, int index, int count, const QList<QRgb> *, QDitherInfo *);
+ qPixelLayouts[QImage::Format_RGBX16FPx4].fetchToARGB32PM = fetchRGB16FToRGB32_avx2;
+ qPixelLayouts[QImage::Format_RGBX16FPx4].fetchToRGBA64PM = fetchRGBA16FPMToRGBA64PM_avx2;
+ qPixelLayouts[QImage::Format_RGBX16FPx4].storeFromARGB32PM = storeRGB16FFromRGB32_avx2;
+ qPixelLayouts[QImage::Format_RGBX16FPx4].storeFromRGB32 = storeRGB16FFromRGB32_avx2;
+ qPixelLayouts[QImage::Format_RGBA16FPx4].fetchToARGB32PM = fetchRGBA16FToARGB32PM_avx2;
+ qPixelLayouts[QImage::Format_RGBA16FPx4].fetchToRGBA64PM = fetchRGBA16FToRGBA64PM_avx2;
+ qPixelLayouts[QImage::Format_RGBA16FPx4].storeFromARGB32PM = storeRGBA16FFromARGB32PM_avx2;
+ qPixelLayouts[QImage::Format_RGBA16FPx4].storeFromRGB32 = storeRGB16FFromRGB32_avx2;
+ qPixelLayouts[QImage::Format_RGBA16FPx4_Premultiplied].fetchToARGB32PM = fetchRGB16FToRGB32_avx2;
+ qPixelLayouts[QImage::Format_RGBA16FPx4_Premultiplied].fetchToRGBA64PM = fetchRGBA16FPMToRGBA64PM_avx2;
+ qPixelLayouts[QImage::Format_RGBA16FPx4_Premultiplied].storeFromARGB32PM = storeRGB16FFromRGB32_avx2;
+ qPixelLayouts[QImage::Format_RGBA16FPx4_Premultiplied].storeFromRGB32 = storeRGB16FFromRGB32_avx2;
+#if QT_CONFIG(raster_fp)
+ extern const QRgba32F *QT_FASTCALL fetchRGBA16FToRGBA32F_avx2(QRgba32F *buffer, const uchar *src, int index, int count, const QList<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL storeRGBX16FFromRGBA32F_avx2(uchar *dest, const QRgba32F *src, int index, int count, const QList<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL storeRGBA16FFromRGBA32F_avx2(uchar *dest, const QRgba32F *src, int index, int count, const QList<QRgb> *, QDitherInfo *);
+ qFetchToRGBA32F[QImage::Format_RGBA16FPx4] = fetchRGBA16FToRGBA32F_avx2;
+ qStoreFromRGBA32F[QImage::Format_RGBX16FPx4] = storeRGBX16FFromRGBA32F_avx2;
+ qStoreFromRGBA32F[QImage::Format_RGBA16FPx4] = storeRGBA16FFromRGBA32F_avx2;
+#endif // QT_CONFIG(raster_fp)
}
+
#endif
#endif // SSE2
diff --git a/src/gui/painting/qdrawhelper_avx2.cpp b/src/gui/painting/qdrawhelper_avx2.cpp
index e401a1463f..3e7743e980 100644
--- a/src/gui/painting/qdrawhelper_avx2.cpp
+++ b/src/gui/painting/qdrawhelper_avx2.cpp
@@ -143,7 +143,6 @@ INTERPOLATE_PIXEL_RGB64_AVX2(__m256i srcVector, __m256i &dstVector, __m256i alph
dstVector = _mm256_or_si256(finalAG, finalRB);
}
-
// See BLEND_SOURCE_OVER_ARGB32_SSE2 for details.
inline static void Q_DECL_VECTORCALL BLEND_SOURCE_OVER_ARGB32_AVX2(quint32 *dst, const quint32 *src, const int length)
{
@@ -457,6 +456,40 @@ void QT_FASTCALL comp_func_SourceOver_rgb64_avx2(QRgba64 *dst, const QRgba64 *sr
}
#endif
+#if QT_CONFIG(raster_fp)
+void QT_FASTCALL comp_func_SourceOver_rgbafp_avx2(QRgba32F *dst, const QRgba32F *src, int length, uint const_alpha)
+{
+ Q_ASSERT(const_alpha < 256); // const_alpha is in [0-255]
+
+ const float a = const_alpha / 255.0f;
+ const __m128 one = _mm_set1_ps(1.0f);
+ const __m128 constAlphaVector = _mm_set1_ps(a);
+ const __m256 one256 = _mm256_set1_ps(1.0f);
+ const __m256 constAlphaVector256 = _mm256_set1_ps(a);
+ int x = 0;
+ for (; x < length - 1; x += 2) {
+ __m256 srcVector = _mm256_loadu_ps((const float *)&src[x]);
+ __m256 dstVector = _mm256_loadu_ps((const float *)&dst[x]);
+ srcVector = _mm256_mul_ps(srcVector, constAlphaVector256);
+ __m256 alphaChannel = _mm256_permute_ps(srcVector, _MM_SHUFFLE(3, 3, 3, 3));
+ alphaChannel = _mm256_sub_ps(one256, alphaChannel);
+ dstVector = _mm256_mul_ps(dstVector, alphaChannel);
+ dstVector = _mm256_add_ps(dstVector, srcVector);
+ _mm256_storeu_ps((float *)(dst + x), dstVector);
+ }
+ if (x < length) {
+ __m128 srcVector = _mm_load_ps((float *)(src + x));
+ __m128 dstVector = _mm_load_ps((const float *)(dst + x));
+ srcVector = _mm_mul_ps(srcVector, constAlphaVector);
+ __m128 alphaChannel = _mm_permute_ps(srcVector, _MM_SHUFFLE(3, 3, 3, 3));
+ alphaChannel = _mm_sub_ps(one, alphaChannel);
+ dstVector = _mm_mul_ps(dstVector, alphaChannel);
+ dstVector = _mm_add_ps(dstVector, srcVector);
+ _mm_store_ps((float *)(dst + x), dstVector);
+ }
+}
+#endif
+
void QT_FASTCALL comp_func_Source_avx2(uint *dst, const uint *src, int length, uint const_alpha)
{
if (const_alpha == 255) {
@@ -523,6 +556,41 @@ void QT_FASTCALL comp_func_Source_rgb64_avx2(QRgba64 *dst, const QRgba64 *src, i
}
#endif
+#if QT_CONFIG(raster_fp)
+void QT_FASTCALL comp_func_Source_rgbafp_avx2(QRgba32F *dst, const QRgba32F *src, int length, uint const_alpha)
+{
+ Q_ASSERT(const_alpha < 256); // const_alpha is in [0-255]
+ if (const_alpha == 255) {
+ ::memcpy(dst, src, length * sizeof(QRgba32F));
+ } else {
+ const float ca = const_alpha / 255.f;
+ const float cia = 1.0f - ca;
+
+ const __m128 constAlphaVector = _mm_set1_ps(ca);
+ const __m128 oneMinusConstAlpha = _mm_set1_ps(cia);
+ const __m256 constAlphaVector256 = _mm256_set1_ps(ca);
+ const __m256 oneMinusConstAlpha256 = _mm256_set1_ps(cia);
+ int x = 0;
+ for (; x < length - 1; x += 2) {
+ __m256 srcVector = _mm256_loadu_ps((const float *)&src[x]);
+ __m256 dstVector = _mm256_loadu_ps((const float *)&dst[x]);
+ srcVector = _mm256_mul_ps(srcVector, constAlphaVector256);
+ dstVector = _mm256_mul_ps(dstVector, oneMinusConstAlpha256);
+ dstVector = _mm256_add_ps(dstVector, srcVector);
+ _mm256_storeu_ps((float *)&dst[x], dstVector);
+ }
+ if (x < length) {
+ __m128 srcVector = _mm_load_ps((const float *)&src[x]);
+ __m128 dstVector = _mm_load_ps((const float *)&dst[x]);
+ srcVector = _mm_mul_ps(srcVector, constAlphaVector);
+ dstVector = _mm_mul_ps(dstVector, oneMinusConstAlpha);
+ dstVector = _mm_add_ps(dstVector, srcVector);
+ _mm_store_ps((float *)&dst[x], dstVector);
+ }
+ }
+}
+#endif
+
void QT_FASTCALL comp_func_solid_SourceOver_avx2(uint *destPixels, int length, uint color, uint const_alpha)
{
if ((const_alpha & qAlpha(color)) == 255) {
@@ -587,6 +655,69 @@ void QT_FASTCALL comp_func_solid_SourceOver_rgb64_avx2(QRgba64 *destPixels, int
}
#endif
+#if QT_CONFIG(raster_fp)
+void QT_FASTCALL comp_func_solid_Source_rgbafp_avx2(QRgba32F *dst, int length, QRgba32F color, uint const_alpha)
+{
+ Q_ASSERT(const_alpha < 256); // const_alpha is in [0-255]
+ if (const_alpha == 255) {
+ for (int i = 0; i < length; ++i)
+ dst[i] = color;
+ } else {
+ const float a = const_alpha / 255.0f;
+ const __m128 alphaVector = _mm_set1_ps(a);
+ const __m128 minusAlphaVector = _mm_set1_ps(1.0f - a);
+ __m128 colorVector = _mm_load_ps((const float *)&color);
+ colorVector = _mm_mul_ps(colorVector, alphaVector);
+ const __m256 colorVector256 = _mm256_insertf128_ps(_mm256_castps128_ps256(colorVector), colorVector, 1);
+ const __m256 minusAlphaVector256 = _mm256_set1_ps(1.0f - a);
+ int x = 0;
+ for (; x < length - 1; x += 2) {
+ __m256 dstVector = _mm256_loadu_ps((const float *)&dst[x]);
+ dstVector = _mm256_mul_ps(dstVector, minusAlphaVector256);
+ dstVector = _mm256_add_ps(dstVector, colorVector256);
+ _mm256_storeu_ps((float *)&dst[x], dstVector);
+ }
+ if (x < length) {
+ __m128 dstVector = _mm_load_ps((const float *)&dst[x]);
+ dstVector = _mm_mul_ps(dstVector, minusAlphaVector);
+ dstVector = _mm_add_ps(dstVector, colorVector);
+ _mm_store_ps((float *)&dst[x], dstVector);
+ }
+ }
+}
+
+void QT_FASTCALL comp_func_solid_SourceOver_rgbafp_avx2(QRgba32F *dst, int length, QRgba32F color, uint const_alpha)
+{
+ Q_ASSERT(const_alpha < 256); // const_alpha is in [0-255]
+ if (const_alpha == 255 && color.a >= 1.0f) {
+ for (int i = 0; i < length; ++i)
+ dst[i] = color;
+ } else {
+ __m128 colorVector = _mm_load_ps((const float *)&color);
+ if (const_alpha != 255)
+ colorVector = _mm_mul_ps(colorVector, _mm_set1_ps(const_alpha / 255.f));
+ __m128 minusAlphaOfColorVector =
+ _mm_sub_ps(_mm_set1_ps(1.0f), _mm_permute_ps(colorVector, _MM_SHUFFLE(3, 3, 3, 3)));
+ const __m256 colorVector256 = _mm256_insertf128_ps(_mm256_castps128_ps256(colorVector), colorVector, 1);
+ const __m256 minusAlphaVector256 = _mm256_insertf128_ps(_mm256_castps128_ps256(minusAlphaOfColorVector),
+ minusAlphaOfColorVector, 1);
+ int x = 0;
+ for (; x < length - 1; x += 2) {
+ __m256 dstVector = _mm256_loadu_ps((const float *)&dst[x]);
+ dstVector = _mm256_mul_ps(dstVector, minusAlphaVector256);
+ dstVector = _mm256_add_ps(dstVector, colorVector256);
+ _mm256_storeu_ps((float *)&dst[x], dstVector);
+ }
+ if (x < length) {
+ __m128 dstVector = _mm_load_ps((const float *)&dst[x]);
+ dstVector = _mm_mul_ps(dstVector, minusAlphaOfColorVector);
+ dstVector = _mm_add_ps(dstVector, colorVector);
+ _mm_store_ps((float *)&dst[x], dstVector);
+ }
+ }
+}
+#endif
+
#define interpolate_4_pixels_16_avx2(tlr1, tlr2, blr1, blr2, distx, disty, colorMask, v_256, b) \
{ \
/* Correct for later unpack */ \
@@ -1261,6 +1392,258 @@ const QRgba64 *QT_FASTCALL fetchRGBA64ToRGBA64PM_avx2(QRgba64 *buffer, const uch
return buffer;
}
+const uint *QT_FASTCALL fetchRGB16FToRGB32_avx2(uint *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const quint64 *s = reinterpret_cast<const quint64 *>(src) + index;
+ const __m256 vf = _mm256_set1_ps(255.0f);
+ const __m256 vh = _mm256_set1_ps(0.5f);
+ int i = 0;
+ for (; i + 1 < count; i += 2) {
+ __m256 vsf = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *)(s + i)));
+ vsf = _mm256_mul_ps(vsf, vf);
+ vsf = _mm256_add_ps(vsf, vh);
+ __m256i vsi = _mm256_cvttps_epi32(vsf);
+ vsi = _mm256_packs_epi32(vsi, vsi);
+ vsi = _mm256_shufflelo_epi16(vsi, _MM_SHUFFLE(3, 0, 1, 2));
+ vsi = _mm256_permute4x64_epi64(vsi, _MM_SHUFFLE(3, 1, 2, 0));
+ __m128i vsi128 = _mm256_castsi256_si128(vsi);
+ vsi128 = _mm_packus_epi16(vsi128, vsi128);
+ _mm_storel_epi64((__m128i *)(buffer + i), vsi128);
+ }
+ if (i < count) {
+ __m128 vsf = _mm_cvtph_ps(_mm_loadl_epi64((const __m128i *)(s + i)));
+ vsf = _mm_mul_ps(vsf, _mm_set1_ps(255.0f));
+ vsf = _mm_add_ps(vsf, _mm_set1_ps(0.5f));
+ __m128i vsi = _mm_cvttps_epi32(vsf);
+ vsi = _mm_packs_epi32(vsi, vsi);
+ vsi = _mm_shufflelo_epi16(vsi, _MM_SHUFFLE(3, 0, 1, 2));
+ vsi = _mm_packus_epi16(vsi, vsi);
+ buffer[i] = _mm_cvtsi128_si32(vsi);
+ }
+ return buffer;
+}
+
+const uint *QT_FASTCALL fetchRGBA16FToARGB32PM_avx2(uint *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const quint64 *s = reinterpret_cast<const quint64 *>(src) + index;
+ const __m256 vf = _mm256_set1_ps(255.0f);
+ const __m256 vh = _mm256_set1_ps(0.5f);
+ int i = 0;
+ for (; i + 1 < count; i += 2) {
+ __m256 vsf = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *)(s + i)));
+ __m256 vsa = _mm256_permute_ps(vsf, _MM_SHUFFLE(3, 3, 3, 3));
+ vsf = _mm256_mul_ps(vsf, vsa);
+ vsf = _mm256_blend_ps(vsf, vsa, 0x88);
+ vsf = _mm256_mul_ps(vsf, vf);
+ vsf = _mm256_add_ps(vsf, vh);
+ __m256i vsi = _mm256_cvttps_epi32(vsf);
+ vsi = _mm256_packus_epi32(vsi, vsi);
+ vsi = _mm256_shufflelo_epi16(vsi, _MM_SHUFFLE(3, 0, 1, 2));
+ vsi = _mm256_permute4x64_epi64(vsi, _MM_SHUFFLE(3, 1, 2, 0));
+ __m128i vsi128 = _mm256_castsi256_si128(vsi);
+ vsi128 = _mm_packus_epi16(vsi128, vsi128);
+ _mm_storel_epi64((__m128i *)(buffer + i), vsi128);
+ }
+ if (i < count) {
+ __m128 vsf = _mm_cvtph_ps(_mm_loadl_epi64((const __m128i *)(s + i)));
+ __m128 vsa = _mm_permute_ps(vsf, _MM_SHUFFLE(3, 3, 3, 3));
+ vsf = _mm_mul_ps(vsf, vsa);
+ vsf = _mm_insert_ps(vsf, vsa, 0x30);
+ vsf = _mm_mul_ps(vsf, _mm_set1_ps(255.0f));
+ vsf = _mm_add_ps(vsf, _mm_set1_ps(0.5f));
+ __m128i vsi = _mm_cvttps_epi32(vsf);
+ vsi = _mm_packus_epi32(vsi, vsi);
+ vsi = _mm_shufflelo_epi16(vsi, _MM_SHUFFLE(3, 0, 1, 2));
+ vsi = _mm_packus_epi16(vsi, vsi);
+ buffer[i] = _mm_cvtsi128_si32(vsi);
+ }
+ return buffer;
+}
+
+const QRgba64 *QT_FASTCALL fetchRGBA16FPMToRGBA64PM_avx2(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const quint64 *s = reinterpret_cast<const quint64 *>(src) + index;
+ const __m256 vf = _mm256_set1_ps(65535.0f);
+ const __m256 vh = _mm256_set1_ps(0.5f);
+ int i = 0;
+ for (; i + 1 < count; i += 2) {
+ __m256 vsf = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *)(s + i)));
+ vsf = _mm256_mul_ps(vsf, vf);
+ vsf = _mm256_add_ps(vsf, vh);
+ __m256i vsi = _mm256_cvttps_epi32(vsf);
+ vsi = _mm256_packus_epi32(vsi, vsi);
+ vsi = _mm256_permute4x64_epi64(vsi, _MM_SHUFFLE(3, 1, 2, 0));
+ _mm_storeu_si128((__m128i *)(buffer + i), _mm256_castsi256_si128(vsi));
+ }
+ if (i < count) {
+ __m128 vsf = _mm_cvtph_ps(_mm_loadl_epi64((const __m128i *)(s + i)));
+ vsf = _mm_mul_ps(vsf, _mm_set1_ps(65535.0f));
+ vsf = _mm_add_ps(vsf, _mm_set1_ps(0.5f));
+ __m128i vsi = _mm_cvttps_epi32(vsf);
+ vsi = _mm_packus_epi32(vsi, vsi);
+ _mm_storel_epi64((__m128i *)(buffer + i), vsi);
+ }
+ return buffer;
+}
+
+const QRgba64 *QT_FASTCALL fetchRGBA16FToRGBA64PM_avx2(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const quint64 *s = reinterpret_cast<const quint64 *>(src) + index;
+ const __m256 vf = _mm256_set1_ps(65535.0f);
+ const __m256 vh = _mm256_set1_ps(0.5f);
+ int i = 0;
+ for (; i + 1 < count; i += 2) {
+ __m256 vsf = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *)(s + i)));
+ __m256 vsa = _mm256_shuffle_ps(vsf, vsf, _MM_SHUFFLE(3, 3, 3, 3));
+ vsf = _mm256_mul_ps(vsf, vsa);
+ vsf = _mm256_blend_ps(vsf, vsa, 0x88);
+ vsf = _mm256_mul_ps(vsf, vf);
+ vsf = _mm256_add_ps(vsf, vh);
+ __m256i vsi = _mm256_cvttps_epi32(vsf);
+ vsi = _mm256_packus_epi32(vsi, vsi);
+ vsi = _mm256_permute4x64_epi64(vsi, _MM_SHUFFLE(3, 1, 2, 0));
+ _mm_storeu_si128((__m128i *)(buffer + i), _mm256_castsi256_si128(vsi));
+ }
+ if (i < count) {
+ __m128 vsf = _mm_cvtph_ps(_mm_loadl_epi64((const __m128i *)(s + i)));
+ __m128 vsa = _mm_shuffle_ps(vsf, vsf, _MM_SHUFFLE(3, 3, 3, 3));
+ vsf = _mm_mul_ps(vsf, vsa);
+ vsf = _mm_insert_ps(vsf, vsa, 0x30);
+ vsf = _mm_mul_ps(vsf, _mm_set1_ps(65535.0f));
+ vsf = _mm_add_ps(vsf, _mm_set1_ps(0.5f));
+ __m128i vsi = _mm_cvttps_epi32(vsf);
+ vsi = _mm_packus_epi32(vsi, vsi);
+ _mm_storel_epi64((__m128i *)(buffer + i), vsi);
+ }
+ return buffer;
+}
+
+void QT_FASTCALL storeRGB16FFromRGB32_avx2(uchar *dest, const uint *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ quint64 *d = reinterpret_cast<quint64 *>(dest) + index;
+ const __m256 vf = _mm256_set1_ps(1.0f / 255.0f);
+ int i = 0;
+ for (; i + 1 < count; i += 2) {
+ __m256i vsi = _mm256_cvtepu8_epi32(_mm_loadl_epi64((const __m128i *)(src + i)));
+ vsi = _mm256_shuffle_epi32(vsi, _MM_SHUFFLE(3, 0, 1, 2));
+ __m256 vsf = _mm256_cvtepi32_ps(vsi);
+ vsf = _mm256_mul_ps(vsf, vf);
+ _mm_storeu_si128((__m128i *)(d + i), _mm256_cvtps_ph(vsf, 0));
+ }
+ if (i < count) {
+ __m128i vsi = _mm_cvtsi32_si128(src[i]);
+ vsi = _mm_cvtepu8_epi32(vsi);
+ vsi = _mm_shuffle_epi32(vsi, _MM_SHUFFLE(3, 0, 1, 2));
+ __m128 vsf = _mm_cvtepi32_ps(vsi);
+ vsf = _mm_mul_ps(vsf, _mm_set1_ps(1.0f / 255.0f));
+ _mm_storel_epi64((__m128i *)(d + i), _mm_cvtps_ph(vsf, 0));
+ }
+}
+
+void QT_FASTCALL storeRGBA16FFromARGB32PM_avx2(uchar *dest, const uint *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ quint64 *d = reinterpret_cast<quint64 *>(dest) + index;
+ const __m128 vf = _mm_set1_ps(1.0f / 255.0f);
+ for (int i = 0; i < count; ++i) {
+ const uint s = src[i];
+ __m128i vsi = _mm_cvtsi32_si128(s);
+ vsi = _mm_cvtepu8_epi32(vsi);
+ vsi = _mm_shuffle_epi32(vsi, _MM_SHUFFLE(3, 0, 1, 2));
+ __m128 vsf = _mm_cvtepi32_ps(vsi);
+ const uint8_t a = (s >> 24);
+ if (a == 255)
+ vsf = _mm_mul_ps(vsf, vf);
+ else if (a == 0)
+ vsf = _mm_set1_ps(0.0f);
+ else {
+ const __m128 vsa = _mm_permute_ps(vsf, _MM_SHUFFLE(3, 3, 3, 3));
+ __m128 vsr = _mm_rcp_ps(vsa);
+ vsr = _mm_sub_ps(_mm_add_ps(vsr, vsr), _mm_mul_ps(vsr, _mm_mul_ps(vsr, vsa)));
+ vsr = _mm_insert_ps(vsr, _mm_set_ss(1.0f), 0x30);
+ vsf = _mm_mul_ps(vsf, vsr);
+ }
+ _mm_storel_epi64((__m128i *)(d + i), _mm_cvtps_ph(vsf, 0));
+ }
+}
+
+#if QT_CONFIG(raster_fp)
+const QRgba32F *QT_FASTCALL fetchRGBA16FToRGBA32F_avx2(QRgba32F *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const quint64 *s = reinterpret_cast<const quint64 *>(src) + index;
+ int i = 0;
+ for (; i + 1 < count; i += 2) {
+ __m256 vsf = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *)(s + i)));
+ __m256 vsa = _mm256_permute_ps(vsf, _MM_SHUFFLE(3, 3, 3, 3));
+ vsf = _mm256_mul_ps(vsf, vsa);
+ vsf = _mm256_blend_ps(vsf, vsa, 0x88);
+ _mm256_storeu_ps((float *)(buffer + i), vsf);
+ }
+ if (i < count) {
+ __m128 vsf = _mm_cvtph_ps(_mm_loadl_epi64((const __m128i *)(s + i)));
+ __m128 vsa = _mm_permute_ps(vsf, _MM_SHUFFLE(3, 3, 3, 3));
+ vsf = _mm_mul_ps(vsf, vsa);
+ vsf = _mm_insert_ps(vsf, vsa, 0x30);
+ _mm_store_ps((float *)(buffer + i), vsf);
+ }
+ return buffer;
+}
+
+void QT_FASTCALL storeRGBX16FFromRGBA32F_avx2(uchar *dest, const QRgba32F *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ quint64 *d = reinterpret_cast<quint64 *>(dest) + index;
+ const __m128 *s = reinterpret_cast<const __m128 *>(src);
+ const __m128 zero = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f);
+ for (int i = 0; i < count; ++i) {
+ __m128 vsf = _mm_load_ps(reinterpret_cast<const float *>(s + i));
+ const __m128 vsa = _mm_permute_ps(vsf, _MM_SHUFFLE(3, 3, 3, 3));
+ const float a = _mm_cvtss_f32(vsa);
+ if (a == 1.0f)
+ { }
+ else if (a == 0.0f)
+ vsf = zero;
+ else {
+ __m128 vsr = _mm_rcp_ps(vsa);
+ vsr = _mm_sub_ps(_mm_add_ps(vsr, vsr), _mm_mul_ps(vsr, _mm_mul_ps(vsr, vsa)));
+ vsf = _mm_mul_ps(vsf, vsr);
+ vsf = _mm_insert_ps(vsf, _mm_set_ss(1.0f), 0x30);
+ }
+ _mm_storel_epi64((__m128i *)(d + i), _mm_cvtps_ph(vsf, 0));
+ }
+}
+
+void QT_FASTCALL storeRGBA16FFromRGBA32F_avx2(uchar *dest, const QRgba32F *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ quint64 *d = reinterpret_cast<quint64 *>(dest) + index;
+ const __m128 *s = reinterpret_cast<const __m128 *>(src);
+ const __m128 zero = _mm_set1_ps(0.0f);
+ for (int i = 0; i < count; ++i) {
+ __m128 vsf = _mm_load_ps(reinterpret_cast<const float *>(s + i));
+ const __m128 vsa = _mm_permute_ps(vsf, _MM_SHUFFLE(3, 3, 3, 3));
+ const float a = _mm_cvtss_f32(vsa);
+ if (a == 1.0f)
+ { }
+ else if (a == 0.0f)
+ vsf = zero;
+ else {
+ __m128 vsr = _mm_rcp_ps(vsa);
+ vsr = _mm_sub_ps(_mm_add_ps(vsr, vsr), _mm_mul_ps(vsr, _mm_mul_ps(vsr, vsa)));
+ vsr = _mm_insert_ps(vsr, _mm_set_ss(1.0f), 0x30);
+ vsf = _mm_mul_ps(vsf, vsr);
+ }
+ _mm_storel_epi64((__m128i *)(d + i), _mm_cvtps_ph(vsf, 0));
+ }
+}
+#endif
+
QT_END_NAMESPACE
#endif
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index 08826bca2f..89db63725f 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -108,6 +108,9 @@ class QRasterBuffer;
class QClipData;
class QRasterPaintEngineState;
+template<typename F> class QRgbaF;
+typedef QRgbaF<float> QRgba32F;
+
typedef QT_FT_SpanFunc ProcessSpans;
typedef void (*BitmapBlitFunc)(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
@@ -194,8 +197,10 @@ extern void qt_memfill16(quint16 *dest, quint16 value, qsizetype count);
typedef void (QT_FASTCALL *CompositionFunction)(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha);
typedef void (QT_FASTCALL *CompositionFunction64)(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha);
+typedef void (QT_FASTCALL *CompositionFunctionFP)(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha);
typedef void (QT_FASTCALL *CompositionFunctionSolid)(uint *dest, int length, uint color, uint const_alpha);
typedef void (QT_FASTCALL *CompositionFunctionSolid64)(QRgba64 *dest, int length, QRgba64 color, uint const_alpha);
+typedef void (QT_FASTCALL *CompositionFunctionSolidFP)(QRgba32F *dest, int length, QRgba32F color, uint const_alpha);
struct LinearGradientValues
{
@@ -219,10 +224,13 @@ struct RadialGradientValues
struct Operator;
typedef uint* (QT_FASTCALL *DestFetchProc)(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length);
typedef QRgba64* (QT_FASTCALL *DestFetchProc64)(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length);
+typedef QRgba32F* (QT_FASTCALL *DestFetchProcFP)(QRgba32F *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length);
typedef void (QT_FASTCALL *DestStoreProc)(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length);
typedef void (QT_FASTCALL *DestStoreProc64)(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length);
+typedef void (QT_FASTCALL *DestStoreProcFP)(QRasterBuffer *rasterBuffer, int x, int y, const QRgba32F *buffer, int length);
typedef const uint* (QT_FASTCALL *SourceFetchProc)(uint *buffer, const Operator *o, const QSpanData *data, int y, int x, int length);
typedef const QRgba64* (QT_FASTCALL *SourceFetchProc64)(QRgba64 *buffer, const Operator *o, const QSpanData *data, int y, int x, int length);
+typedef const QRgba32F* (QT_FASTCALL *SourceFetchProcFP)(QRgba32F *buffer, const Operator *o, const QSpanData *data, int y, int x, int length);
struct Operator
{
@@ -239,6 +247,12 @@ struct Operator
CompositionFunctionSolid64 funcSolid64;
CompositionFunction64 func64;
+ DestFetchProcFP destFetchFP;
+ DestStoreProcFP destStoreFP;
+ SourceFetchProcFP srcFetchFP;
+ CompositionFunctionSolidFP funcSolidFP;
+ CompositionFunctionFP funcFP;
+
union {
LinearGradientValues linear;
RadialGradientValues radial;
@@ -295,7 +309,7 @@ struct QGradientData
#define GRADIENT_STOPTABLE_SIZE 1024
#define GRADIENT_STOPTABLE_SIZE_SHIFT 10
-#if QT_CONFIG(raster_64bit)
+#if QT_CONFIG(raster_64bit) || QT_CONFIG(raster_fp)
const QRgba64 *colorTable64; //[GRADIENT_STOPTABLE_SIZE];
#endif
const QRgb *colorTable32; //[GRADIENT_STOPTABLE_SIZE];
@@ -473,7 +487,7 @@ const BlendType * QT_FASTCALL qt_fetch_radial_gradient_template(BlendType *buffe
while (buffer < end) {
if (rw == 0) {
- *buffer = 0;
+ *buffer = RadialFetchFunc::null();
} else {
qreal invRw = 1 / rw;
qreal gx = rx * invRw - data->gradient.radial.focal.x;
@@ -845,6 +859,57 @@ static inline QRgba64 interpolate_4_pixels_rgb64(const QRgba64 t[], const QRgba6
}
#endif // __SSE2__
+#if QT_CONFIG(raster_fp)
+static inline QRgba32F multiplyAlpha_rgba32f(QRgba32F c, float a)
+{
+ return QRgba32F { c.r * a, c.g * a, c.b * a, c.a * a };
+}
+
+static inline QRgba32F interpolate_rgba32f(QRgba32F x, float alpha1, QRgba32F y, float alpha2)
+{
+ x = multiplyAlpha_rgba32f(x, alpha1);
+ y = multiplyAlpha_rgba32f(y, alpha2);
+ return QRgba32F { x.r + y.r, x.g + y.g, x.b + y.b, x.a + y.a };
+}
+#ifdef __SSE2__
+static inline __m128 Q_DECL_VECTORCALL interpolate_rgba32f(__m128 x, __m128 alpha1, __m128 y, __m128 alpha2)
+{
+ return _mm_add_ps(_mm_mul_ps(x, alpha1), _mm_mul_ps(y, alpha2));
+}
+#endif
+
+static inline QRgba32F interpolate_4_pixels_rgba32f(const QRgba32F t[], const QRgba32F b[], uint distx, uint disty)
+{
+ constexpr float f = 1.0f / 65536.0f;
+ const float dx = distx * f;
+ const float dy = disty * f;
+ const float idx = 1.0f - dx;
+ const float idy = 1.0f - dy;
+#ifdef __SSE2__
+ const __m128 vtl = _mm_load_ps((const float *)&t[0]);
+ const __m128 vtr = _mm_load_ps((const float *)&t[1]);
+ const __m128 vbl = _mm_load_ps((const float *)&b[0]);
+ const __m128 vbr = _mm_load_ps((const float *)&b[1]);
+
+ const __m128 vdx = _mm_set1_ps(dx);
+ const __m128 vidx = _mm_set1_ps(idx);
+ __m128 vt = interpolate_rgba32f(vtl, vidx, vtr, vdx);
+ __m128 vb = interpolate_rgba32f(vbl, vidx, vbr, vdx);
+ const __m128 vdy = _mm_set1_ps(dy);
+ const __m128 vidy = _mm_set1_ps(idy);
+ vt = interpolate_rgba32f(vt, vidy, vb, vdy);
+ QRgba32F res;
+ _mm_store_ps((float*)&res, vt);
+ return res;
+#else
+ QRgba32F xtop = interpolate_rgba32f(t[0], idx, t[1], dx);
+ QRgba32F xbot = interpolate_rgba32f(b[0], idx, b[1], dx);
+ xtop = interpolate_rgba32f(xtop, idy, xbot, dy);
+ return xtop;
+#endif
+}
+#endif // QT_CONFIG(raster_fp)
+
static inline uint BYTE_MUL_RGB16(uint x, uint a) {
a += 1;
uint t = (((x & 0x07e0)*a) >> 8) & 0x07e0;
@@ -1024,70 +1089,6 @@ struct IntermediateBuffer
quint32 buffer_ag[BufferSize+2];
};
-template <QPixelLayout::BPP bpp>
-inline uint QT_FASTCALL qFetchPixel(const uchar *, int)
-{
- Q_UNREACHABLE();
- return 0;
-}
-
-template <>
-inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP1LSB>(const uchar *src, int index)
-{
- return (src[index >> 3] >> (index & 7)) & 1;
-}
-
-template <>
-inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP1MSB>(const uchar *src, int index)
-{
- return (src[index >> 3] >> (~index & 7)) & 1;
-}
-
-template <>
-inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP8>(const uchar *src, int index)
-{
- return src[index];
-}
-
-template <>
-inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP16>(const uchar *src, int index)
-{
- return reinterpret_cast<const quint16 *>(src)[index];
-}
-
-template <>
-inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP24>(const uchar *src, int index)
-{
- return reinterpret_cast<const quint24 *>(src)[index];
-}
-
-template <>
-inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP32>(const uchar *src, int index)
-{
- return reinterpret_cast<const uint *>(src)[index];
-}
-
-template <>
-inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP64>(const uchar *src, int index)
-{
- // We have to do the conversion in fetch to fit into a 32bit uint
- QRgba64 c = reinterpret_cast<const QRgba64 *>(src)[index];
- return c.toArgb32();
-}
-
-typedef uint (QT_FASTCALL *FetchPixelFunc)(const uchar *src, int index);
-
-constexpr FetchPixelFunc qFetchPixelTable[QPixelLayout::BPPCount] = {
- nullptr, // BPPNone
- qFetchPixel<QPixelLayout::BPP1MSB>,
- qFetchPixel<QPixelLayout::BPP1LSB>,
- qFetchPixel<QPixelLayout::BPP8>,
- qFetchPixel<QPixelLayout::BPP16>,
- qFetchPixel<QPixelLayout::BPP24>,
- qFetchPixel<QPixelLayout::BPP32>,
- qFetchPixel<QPixelLayout::BPP64>,
-};
-
QT_END_NAMESPACE
#endif // QDRAWHELPER_P_H
diff --git a/src/gui/painting/qdrawhelper_sse4.cpp b/src/gui/painting/qdrawhelper_sse4.cpp
index dc9755e414..f6ec19c718 100644
--- a/src/gui/painting/qdrawhelper_sse4.cpp
+++ b/src/gui/painting/qdrawhelper_sse4.cpp
@@ -502,6 +502,13 @@ void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4(uchar *dest, const uint *src, i
d[i] = qConvertArgb32ToA2rgb30_sse4<PixelOrder>(src[i]);
}
+template
+void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4<PixelOrderBGR>(uchar *dest, const uint *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *);
+template
+void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4<PixelOrderRGB>(uchar *dest, const uint *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *);
+
#if QT_CONFIG(raster_64bit)
void QT_FASTCALL destStore64ARGB32_sse4(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
{
@@ -544,12 +551,68 @@ void QT_FASTCALL storeRGBx64FromRGBA64PM_sse4(uchar *dest, const QRgba64 *src, i
convertRGBA64FromRGBA64PM_sse4<true>(d, src, count);
}
-template
-void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4<PixelOrderBGR>(uchar *dest, const uint *src, int index, int count,
- const QList<QRgb> *, QDitherInfo *);
-template
-void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4<PixelOrderRGB>(uchar *dest, const uint *src, int index, int count,
- const QList<QRgb> *, QDitherInfo *);
+#if QT_CONFIG(raster_fp)
+const QRgba32F *QT_FASTCALL fetchRGBA32FToRGBA32F_sse4(QRgba32F *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const QRgba32F *s = reinterpret_cast<const QRgba32F *>(src) + index;
+ for (int i = 0; i < count; ++i) {
+ __m128 vsf = _mm_load_ps(reinterpret_cast<const float *>(s + i));
+ __m128 vsa = _mm_shuffle_ps(vsf, vsf, _MM_SHUFFLE(3, 3, 3, 3));
+ vsf = _mm_mul_ps(vsf, vsa);
+ vsf = _mm_insert_ps(vsf, vsa, 0x30);
+ _mm_store_ps(reinterpret_cast<float *>(buffer + i), vsf);
+ }
+ return buffer;
+}
+
+void QT_FASTCALL storeRGBX32FFromRGBA32F_sse4(uchar *dest, const QRgba32F *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba32F *d = reinterpret_cast<QRgba32F *>(dest) + index;
+ const __m128 zero = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f);
+ for (int i = 0; i < count; ++i) {
+ __m128 vsf = _mm_load_ps(reinterpret_cast<const float *>(src + i));
+ const __m128 vsa = _mm_shuffle_ps(vsf, vsf, _MM_SHUFFLE(3, 3, 3, 3));
+ const float a = _mm_cvtss_f32(vsa);
+ if (a == 1.0f)
+ { }
+ else if (a == 0.0f)
+ vsf = zero;
+ else {
+ __m128 vsr = _mm_rcp_ps(vsa);
+ vsr = _mm_sub_ps(_mm_add_ps(vsr, vsr), _mm_mul_ps(vsr, _mm_mul_ps(vsr, vsa)));
+ vsf = _mm_mul_ps(vsf, vsr);
+ vsf = _mm_insert_ps(vsf, _mm_set_ss(1.0f), 0x30);
+ }
+ _mm_store_ps(reinterpret_cast<float *>(d + i), vsf);
+ }
+}
+
+void QT_FASTCALL storeRGBA32FFromRGBA32F_sse4(uchar *dest, const QRgba32F *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba32F *d = reinterpret_cast<QRgba32F *>(dest) + index;
+ const __m128 zero = _mm_set1_ps(0.0f);
+ for (int i = 0; i < count; ++i) {
+ __m128 vsf = _mm_load_ps(reinterpret_cast<const float *>(src + i));
+ const __m128 vsa = _mm_shuffle_ps(vsf, vsf, _MM_SHUFFLE(3, 3, 3, 3));
+ const float a = _mm_cvtss_f32(vsa);
+ if (a == 1.0f)
+ { }
+ else if (a == 0.0f)
+ vsf = zero;
+ else {
+ __m128 vsr = _mm_rcp_ps(vsa);
+ vsr = _mm_sub_ps(_mm_add_ps(vsr, vsr), _mm_mul_ps(vsr, _mm_mul_ps(vsr, vsa)));
+ vsr = _mm_insert_ps(vsr, _mm_set_ss(1.0f), 0x30);
+ vsf = _mm_mul_ps(vsf, vsr);
+ }
+ _mm_store_ps(reinterpret_cast<float *>(d + i), vsf);
+ }
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/gui/painting/qicc.cpp b/src/gui/painting/qicc.cpp
index 8196ccc595..8f6a204caa 100644
--- a/src/gui/painting/qicc.cpp
+++ b/src/gui/painting/qicc.cpp
@@ -742,7 +742,7 @@ bool fromIccProfile(const QByteArray &data, QColorSpace *colorSpace)
QColorVector whitePoint;
if (!parseXyzData(data, tagIndex[Tag::wtpt], whitePoint))
return false;
- if (!qFuzzyCompare(whitePoint.y, 1.0f) || (1.0f + whitePoint.z - whitePoint.x) == 0.0f) {
+ if (!qFuzzyCompare(whitePoint.y, 1.0f) || (1.0f + whitePoint.z + whitePoint.x) == 0.0f) {
qCWarning(lcIcc) << "fromIccProfile: Invalid ICC profile - gray white-point not normalized";
return false;
}
diff --git a/src/gui/painting/qimagescale.cpp b/src/gui/painting/qimagescale.cpp
index 28691fa89b..ae44ca6297 100644
--- a/src/gui/painting/qimagescale.cpp
+++ b/src/gui/painting/qimagescale.cpp
@@ -38,10 +38,12 @@
****************************************************************************/
#include <private/qimagescale_p.h>
#include <private/qdrawhelper_p.h>
+#include <private/qimage_p.h>
#include "qimage.h"
#include "qcolor.h"
#include "qrgba64_p.h"
+#include "qrgbaf.h"
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
#include "qsemaphore.h"
@@ -789,6 +791,221 @@ static void qt_qimageScaleRgba64_down_xy(QImageScaleInfo *isi, QRgba64 *dest,
}
#endif
+#if QT_CONFIG(raster_fp)
+static void qt_qimageScaleRgbaFP_up_x_down_y(QImageScaleInfo *isi, QRgba32F *dest,
+ int dw, int dh, int dow, int sow);
+
+static void qt_qimageScaleRgbaFP_down_x_up_y(QImageScaleInfo *isi, QRgba32F *dest,
+ int dw, int dh, int dow, int sow);
+
+static void qt_qimageScaleRgbaFP_down_xy(QImageScaleInfo *isi, QRgba32F *dest,
+ int dw, int dh, int dow, int sow);
+
+static void qt_qimageScaleRgbaFP_up_xy(QImageScaleInfo *isi, QRgba32F *dest,
+ int dw, int dh, int dow, int sow)
+{
+ const QRgba32F **ypoints = (const QRgba32F **)isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ auto scaleSection = [&] (int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QRgba32F *sptr = ypoints[y];
+ QRgba32F *dptr = dest + (y * dow);
+ const int yap = yapoints[y];
+ if (yap > 0) {
+ for (int x = 0; x < dw; x++) {
+ const QRgba32F *pix = sptr + xpoints[x];
+ const int xap = xapoints[x];
+ if (xap > 0)
+ *dptr = interpolate_4_pixels_rgba32f(pix, pix + sow, xap * 256, yap * 256);
+ else
+ *dptr = interpolate_rgba32f(pix[0], 256 - yap, pix[sow], yap);
+ dptr++;
+ }
+ } else {
+ for (int x = 0; x < dw; x++) {
+ const QRgba32F *pix = sptr + xpoints[x];
+ const int xap = xapoints[x];
+ if (xap > 0)
+ *dptr = interpolate_rgba32f(pix[0], 256 - xap, pix[1], xap);
+ else
+ *dptr = pix[0];
+ dptr++;
+ }
+ }
+ }
+ };
+ multithread_pixels_function(isi, dh, scaleSection);
+}
+
+void qt_qimageScaleRgbaFP(QImageScaleInfo *isi, QRgba32F *dest,
+ int dw, int dh, int dow, int sow)
+{
+ if (isi->xup_yup == 3)
+ qt_qimageScaleRgbaFP_up_xy(isi, dest, dw, dh, dow, sow);
+ else if (isi->xup_yup == 1)
+ qt_qimageScaleRgbaFP_up_x_down_y(isi, dest, dw, dh, dow, sow);
+ else if (isi->xup_yup == 2)
+ qt_qimageScaleRgbaFP_down_x_up_y(isi, dest, dw, dh, dow, sow);
+ else
+ qt_qimageScaleRgbaFP_down_xy(isi, dest, dw, dh, dow, sow);
+}
+
+inline static void qt_qimageScaleRgbaFP_helper(const QRgba32F *pix, int xyap, int Cxy, int step, float &r, float &g, float &b, float &a)
+{
+ constexpr float f = (1.0f / float(1<<14));
+ const float xyapf = xyap * f;
+ const float Cxyf = Cxy * f;
+ r = pix->red() * xyapf;
+ g = pix->green() * xyapf;
+ b = pix->blue() * xyapf;
+ a = pix->alpha() * xyapf;
+ int j;
+ for (j = (1 << 14) - xyap; j > Cxy; j -= Cxy ){
+ pix += step;
+ r += pix->red() * Cxyf;
+ g += pix->green() * Cxyf;
+ b += pix->blue() * Cxyf;
+ a += pix->alpha() * Cxyf;
+ }
+ pix += step;
+ const float jf = j * f;
+ r += pix->red() * jf;
+ g += pix->green() * jf;
+ b += pix->blue() * jf;
+ a += pix->alpha() * jf;
+}
+
+static void qt_qimageScaleRgbaFP_up_x_down_y(QImageScaleInfo *isi, QRgba32F *dest,
+ int dw, int dh, int dow, int sow)
+{
+ const QRgba32F **ypoints = (const QRgba32F **)isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ auto scaleSection = [&] (int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ int Cy = (yapoints[y]) >> 16;
+ int yap = (yapoints[y]) & 0xffff;
+
+ QRgba32F *dptr = dest + (y * dow);
+ for (int x = 0; x < dw; x++) {
+ const QRgba32F *sptr = ypoints[y] + xpoints[x];
+ float r, g, b, a;
+ qt_qimageScaleRgbaFP_helper(sptr, yap, Cy, sow, r, g, b, a);
+
+ int xap = xapoints[x];
+ float xapf = xap * (1.f / 256.f);
+ if (xap > 0) {
+ float rr, gg, bb, aa;
+ qt_qimageScaleRgbaFP_helper(sptr + 1, yap, Cy, sow, rr, gg, bb, aa);
+
+ r = (r * (1.0f - xapf) + (rr * xapf));
+ g = (g * (1.0f - xapf) + (gg * xapf));
+ b = (b * (1.0f - xapf) + (bb * xapf));
+ a = (a * (1.0f - xapf) + (aa * xapf));
+ }
+ *dptr++ = QRgba32F{r, g, b, a};
+ }
+ }
+ };
+ multithread_pixels_function(isi, dh, scaleSection);
+}
+
+static void qt_qimageScaleRgbaFP_down_x_up_y(QImageScaleInfo *isi, QRgba32F *dest,
+ int dw, int dh, int dow, int sow)
+{
+ const QRgba32F **ypoints = (const QRgba32F **)isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ auto scaleSection = [&] (int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ QRgba32F *dptr = dest + (y * dow);
+ for (int x = 0; x < dw; x++) {
+ int Cx = xapoints[x] >> 16;
+ int xap = xapoints[x] & 0xffff;
+
+ const QRgba32F *sptr = ypoints[y] + xpoints[x];
+ float r, g, b, a;
+ qt_qimageScaleRgbaFP_helper(sptr, xap, Cx, 1, r, g, b, a);
+
+ int yap = yapoints[y];
+ float yapf = yap * (1.f / 256.f);
+ if (yap > 0) {
+ float rr, gg, bb, aa;
+ qt_qimageScaleRgbaFP_helper(sptr + sow, xap, Cx, 1, rr, gg, bb, aa);
+
+ r = (r * (1.0f - yapf) + (rr * yapf));
+ g = (g * (1.0f - yapf) + (gg * yapf));
+ b = (b * (1.0f - yapf) + (bb * yapf));
+ a = (a * (1.0f - yapf) + (aa * yapf));
+ }
+ *dptr++ = QRgba32F{r, g, b, a};
+ }
+ }
+ };
+ multithread_pixels_function(isi, dh, scaleSection);
+}
+
+static void qt_qimageScaleRgbaFP_down_xy(QImageScaleInfo *isi, QRgba32F *dest,
+ int dw, int dh, int dow, int sow)
+{
+ const QRgba32F **ypoints = (const QRgba32F **)isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ auto scaleSection = [&] (int yStart, int yEnd) {
+ constexpr float f = 1.f / float(1 << 14);
+ for (int y = yStart; y < yEnd; ++y) {
+ int Cy = (yapoints[y]) >> 16;
+ int yap = (yapoints[y]) & 0xffff;
+
+ QRgba32F *dptr = dest + (y * dow);
+ for (int x = 0; x < dw; x++) {
+ int Cx = xapoints[x] >> 16;
+ int xap = xapoints[x] & 0xffff;
+
+ const QRgba32F *sptr = ypoints[y] + xpoints[x];
+ float rx, gx, bx, ax;
+ qt_qimageScaleRgbaFP_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
+
+ const float yapf = yap * f;
+ const float Cyf = Cy * f;
+ float r = rx * yapf;
+ float g = gx * yapf;
+ float b = bx * yapf;
+ float a = ax * yapf;
+ int j;
+ for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
+ sptr += sow;
+ qt_qimageScaleRgbaFP_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
+ r += rx * Cyf;
+ g += gx * Cyf;
+ b += bx * Cyf;
+ a += ax * Cyf;
+ }
+ sptr += sow;
+ qt_qimageScaleRgbaFP_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
+ const float jf = j * f;
+ r += rx * jf;
+ g += gx * jf;
+ b += bx * jf;
+ a += ax * jf;
+
+ *dptr++ = QRgba32F{r, g, b, a};
+ }
+ }
+ };
+ multithread_pixels_function(isi, dh, scaleSection);
+}
+#endif
+
static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
int dw, int dh, int dow, int sow);
@@ -1014,6 +1231,12 @@ QImage qSmoothScaleImage(const QImage &src, int dw, int dh)
return QImage();
}
+#if QT_CONFIG(raster_fp)
+ if (qt_fpColorPrecision(src.format()))
+ qt_qimageScaleRgbaFP(scaleinfo, (QRgba32F *)buffer.scanLine(0),
+ dw, dh, dw, src.bytesPerLine() / 16);
+ else
+#endif
#if QT_CONFIG(raster_64bit)
if (src.depth() > 32)
qt_qimageScaleRgba64(scaleinfo, (QRgba64 *)buffer.scanLine(0),
diff --git a/src/gui/painting/qmemrotate.cpp b/src/gui/painting/qmemrotate.cpp
index b3bee9e5e7..c58ead6b84 100644
--- a/src/gui/painting/qmemrotate.cpp
+++ b/src/gui/painting/qmemrotate.cpp
@@ -224,24 +224,11 @@ inline void qt_memrotate90_template(const T *src, int srcWidth, int srcHeight, i
{
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
// packed algorithm assumes little endian and that sizeof(quint32)/sizeof(T) is an integer
- if (sizeof(quint32) % sizeof(T) == 0)
- qt_memrotate90_tiled<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
- else
-#endif
+ static_assert(sizeof(quint32) % sizeof(T) == 0);
+ qt_memrotate90_tiled<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
+#else
qt_memrotate90_tiled_unpacked<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
-}
-
-template <>
-inline void qt_memrotate90_template<quint32>(const quint32 *src, int w, int h, int sstride, quint32 *dest, int dstride)
-{
- // packed algorithm doesn't have any benefit for quint32
- qt_memrotate90_tiled_unpacked(src, w, h, sstride, dest, dstride);
-}
-
-template <>
-inline void qt_memrotate90_template<quint64>(const quint64 *src, int w, int h, int sstride, quint64 *dest, int dstride)
-{
- qt_memrotate90_tiled_unpacked(src, w, h, sstride, dest, dstride);
+#endif
}
template<class T>
@@ -268,24 +255,11 @@ inline void qt_memrotate270_template(const T *src, int srcWidth, int srcHeight,
{
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
// packed algorithm assumes little endian and that sizeof(quint32)/sizeof(T) is an integer
- if (sizeof(quint32) % sizeof(T) == 0)
- qt_memrotate270_tiled<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
- else
-#endif
+ static_assert(sizeof(quint32) % sizeof(T) == 0);
+ qt_memrotate270_tiled<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
+#else
qt_memrotate270_tiled_unpacked<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
-}
-
-template <>
-inline void qt_memrotate270_template<quint32>(const quint32 *src, int w, int h, int sstride, quint32 *dest, int dstride)
-{
- // packed algorithm doesn't have any benefit for quint32
- qt_memrotate270_tiled_unpacked(src, w, h, sstride, dest, dstride);
-}
-
-template <>
-inline void qt_memrotate270_template<quint64>(const quint64 *src, int w, int h, int sstride, quint64 *dest, int dstride)
-{
- qt_memrotate270_tiled_unpacked(src, w, h, sstride, dest, dstride);
+#endif
}
#define QT_IMPL_MEMROTATE(type) \
@@ -322,10 +296,11 @@ Q_GUI_EXPORT void qt_memrotate270(const type *src, int w, int h, int sstride, \
qt_memrotate270_tiled_unpacked(src, w, h, sstride, dest, dstride); \
}
-QT_IMPL_MEMROTATE(quint64)
-QT_IMPL_MEMROTATE(quint32)
+QT_IMPL_SIMPLE_MEMROTATE(QRgba32F)
+QT_IMPL_SIMPLE_MEMROTATE(quint64)
+QT_IMPL_SIMPLE_MEMROTATE(quint32)
+QT_IMPL_SIMPLE_MEMROTATE(quint24)
QT_IMPL_MEMROTATE(quint16)
-QT_IMPL_MEMROTATE(quint24)
QT_IMPL_MEMROTATE(quint8)
void qt_memrotate90_8(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
@@ -404,6 +379,21 @@ void qt_memrotate270_64(const uchar *srcPixels, int w, int h, int sbpl, uchar *d
qt_memrotate270((const quint64 *)srcPixels, w, h, sbpl, (quint64 *)destPixels, dbpl);
}
+void qt_memrotate90_128(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
+{
+ qt_memrotate90((const QRgba32F *)srcPixels, w, h, sbpl, (QRgba32F *)destPixels, dbpl);
+}
+
+void qt_memrotate180_128(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
+{
+ qt_memrotate180((const QRgba32F *)srcPixels, w, h, sbpl, (QRgba32F *)destPixels, dbpl);
+}
+
+void qt_memrotate270_128(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
+{
+ qt_memrotate270((const QRgba32F *)srcPixels, w, h, sbpl, (QRgba32F *)destPixels, dbpl);
+}
+
MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3] =
// 90, 180, 270
{
@@ -415,6 +405,8 @@ MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3] =
{ qt_memrotate90_24, qt_memrotate180_24, qt_memrotate270_24 }, // BPP24
{ qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // BPP32
{ qt_memrotate90_64, qt_memrotate180_64, qt_memrotate270_64 }, // BPP64
+ { qt_memrotate90_64, qt_memrotate180_64, qt_memrotate270_64 }, // BPP16FPx4
+ { qt_memrotate90_128, qt_memrotate180_128, qt_memrotate270_128 }, // BPP32FPx4
};
QT_END_NAMESPACE
diff --git a/src/gui/painting/qpagesize.h b/src/gui/painting/qpagesize.h
index 72d24ed938..f4e7af0f6c 100644
--- a/src/gui/painting/qpagesize.h
+++ b/src/gui/painting/qpagesize.h
@@ -224,7 +224,7 @@ public:
};
QPageSize();
- explicit QPageSize(PageSizeId pageSizeId);
+ Q_IMPLICIT QPageSize(PageSizeId pageSizeId);
explicit QPageSize(const QSize &pointSize,
const QString &name = QString(),
SizeMatchPolicy matchPolicy = FuzzyMatch);
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index de17bff844..5ac1f748e5 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -1649,17 +1649,18 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
const QLineF *lines = reinterpret_cast<const QLineF *>(path.points());
for (int i = 0; i < lineCount; ++i) {
- if (lines[i].p1() == lines[i].p2()) {
+ const QLineF line = s->matrix.map(lines[i]);
+ if (line.p1() == line.p2()) {
if (s->lastPen.capStyle() != Qt::FlatCap) {
QPointF p = lines[i].p1();
- QLineF line = s->matrix.map(QLineF(QPointF(p.x() - width*0.5, p.y()),
+ QLineF mappedline = s->matrix.map(QLineF(QPointF(p.x() - width*0.5, p.y()),
QPointF(p.x() + width*0.5, p.y())));
- d->rasterizer->rasterizeLine(line.p1(), line.p2(), width / line.length());
+ d->rasterizer->rasterizeLine(mappedline.p1(), mappedline.p2(),
+ width / mappedline.length());
}
continue;
}
- const QLineF line = s->matrix.map(lines[i]);
if (qpen_style(s->lastPen) == Qt::SolidLine) {
d->rasterizer->rasterizeLine(line.p1(), line.p2(),
width / line.length(),
@@ -2595,6 +2596,8 @@ void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx
return;
QRasterBuffer *rb = d->rasterBuffer.data();
+ if (rb->colorSpace.transferFunction() == QColorSpace::TransferFunction::Linear)
+ useGammaCorrection = false;
const QRect rect(rx, ry, w, h);
const QClipData *clip = d->clip();
@@ -3788,6 +3791,7 @@ QImage::Format QRasterBuffer::prepare(QImage *image)
bytes_per_line = image->bytesPerLine();
format = image->format();
+ colorSpace = image->colorSpace();
if (image->depth() == 1 && image->colorTable().size() == 2) {
monoDestinationWithClut = true;
const QList<QRgb> colorTable = image->colorTable();
@@ -4516,7 +4520,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode
auto cacheInfo = qt_gradient_cache()->getBuffer(*g, alpha);
gradient.colorTable32 = cacheInfo->buffer32;
-#if QT_CONFIG(raster_64bit)
+#if QT_CONFIG(raster_64bit) || QT_CONFIG(raster_fp)
gradient.colorTable64 = cacheInfo->buffer64;
#endif
cachedGradient = std::move(cacheInfo);
@@ -4540,7 +4544,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode
auto cacheInfo = qt_gradient_cache()->getBuffer(*g, alpha);
gradient.colorTable32 = cacheInfo->buffer32;
-#if QT_CONFIG(raster_64bit)
+#if QT_CONFIG(raster_64bit) || QT_CONFIG(raster_fp)
gradient.colorTable64 = cacheInfo->buffer64;
#endif
cachedGradient = std::move(cacheInfo);
@@ -4568,7 +4572,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode
auto cacheInfo = qt_gradient_cache()->getBuffer(*g, alpha);
gradient.colorTable32 = cacheInfo->buffer32;
-#if QT_CONFIG(raster_64bit)
+#if QT_CONFIG(raster_64bit) || QT_CONFIG(raster_fp)
gradient.colorTable64 = cacheInfo->buffer64;
#endif
cachedGradient = std::move(cacheInfo);
diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h
index 62cef10d32..d25fe4c3b3 100644
--- a/src/gui/painting/qpaintengine_raster_p.h
+++ b/src/gui/painting/qpaintengine_raster_p.h
@@ -450,6 +450,7 @@ public:
QPainter::CompositionMode compositionMode;
QImage::Format format;
+ QColorSpace colorSpace;
QImage colorizeBitmap(const QImage &image, const QColor &color);
private:
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index 8d471e938d..4c854e0026 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -502,52 +502,52 @@ inline void QPainter::drawLine(const QPointF &p1, const QPointF &p2)
inline void QPainter::drawLines(const QList<QLineF> &lines)
{
- drawLines(lines.constData(), lines.size());
+ drawLines(lines.constData(), int(lines.size()));
}
inline void QPainter::drawLines(const QList<QLine> &lines)
{
- drawLines(lines.constData(), lines.size());
+ drawLines(lines.constData(), int(lines.size()));
}
inline void QPainter::drawLines(const QList<QPointF> &pointPairs)
{
- drawLines(pointPairs.constData(), pointPairs.size() / 2);
+ drawLines(pointPairs.constData(), int(pointPairs.size() / 2));
}
inline void QPainter::drawLines(const QList<QPoint> &pointPairs)
{
- drawLines(pointPairs.constData(), pointPairs.size() / 2);
+ drawLines(pointPairs.constData(), int(pointPairs.size() / 2));
}
inline void QPainter::drawPolyline(const QPolygonF &polyline)
{
- drawPolyline(polyline.constData(), polyline.size());
+ drawPolyline(polyline.constData(), int(polyline.size()));
}
inline void QPainter::drawPolyline(const QPolygon &polyline)
{
- drawPolyline(polyline.constData(), polyline.size());
+ drawPolyline(polyline.constData(), int(polyline.size()));
}
inline void QPainter::drawPolygon(const QPolygonF &polygon, Qt::FillRule fillRule)
{
- drawPolygon(polygon.constData(), polygon.size(), fillRule);
+ drawPolygon(polygon.constData(), int(polygon.size()), fillRule);
}
inline void QPainter::drawPolygon(const QPolygon &polygon, Qt::FillRule fillRule)
{
- drawPolygon(polygon.constData(), polygon.size(), fillRule);
+ drawPolygon(polygon.constData(), int(polygon.size()), fillRule);
}
inline void QPainter::drawConvexPolygon(const QPolygonF &poly)
{
- drawConvexPolygon(poly.constData(), poly.size());
+ drawConvexPolygon(poly.constData(), int(poly.size()));
}
inline void QPainter::drawConvexPolygon(const QPolygon &poly)
{
- drawConvexPolygon(poly.constData(), poly.size());
+ drawConvexPolygon(poly.constData(), int(poly.size()));
}
inline void QPainter::drawRect(const QRectF &rect)
@@ -568,12 +568,12 @@ inline void QPainter::drawRect(const QRect &r)
inline void QPainter::drawRects(const QList<QRectF> &rects)
{
- drawRects(rects.constData(), rects.size());
+ drawRects(rects.constData(), int(rects.size()));
}
inline void QPainter::drawRects(const QList<QRect> &rects)
{
- drawRects(rects.constData(), rects.size());
+ drawRects(rects.constData(), int(rects.size()));
}
inline void QPainter::drawPoint(const QPointF &p)
@@ -594,12 +594,12 @@ inline void QPainter::drawPoint(const QPoint &p)
inline void QPainter::drawPoints(const QPolygonF &points)
{
- drawPoints(points.constData(), points.size());
+ drawPoints(points.constData(), int(points.size()));
}
inline void QPainter::drawPoints(const QPolygon &points)
{
- drawPoints(points.constData(), points.size());
+ drawPoints(points.constData(), int(points.size()));
}
inline void QPainter::drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius,
diff --git a/src/gui/painting/qpixellayout.cpp b/src/gui/painting/qpixellayout.cpp
index ca6bca344f..f181d78a10 100644
--- a/src/gui/painting/qpixellayout.cpp
+++ b/src/gui/painting/qpixellayout.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -55,6 +55,9 @@ template<QImage::Format> constexpr uint blueShift();
template<QImage::Format> constexpr uint alphaWidth();
template<QImage::Format> constexpr uint alphaShift();
+template<> constexpr uint redWidth<QImage::Format_RGB32>() { return 8; }
+template<> constexpr uint redWidth<QImage::Format_ARGB32>() { return 8; }
+template<> constexpr uint redWidth<QImage::Format_ARGB32_Premultiplied>() { return 8; }
template<> constexpr uint redWidth<QImage::Format_RGB16>() { return 5; }
template<> constexpr uint redWidth<QImage::Format_RGB444>() { return 4; }
template<> constexpr uint redWidth<QImage::Format_RGB555>() { return 5; }
@@ -69,6 +72,9 @@ template<> constexpr uint redWidth<QImage::Format_RGBX8888>() { return 8; }
template<> constexpr uint redWidth<QImage::Format_RGBA8888>() { return 8; }
template<> constexpr uint redWidth<QImage::Format_RGBA8888_Premultiplied>() { return 8; }
+template<> constexpr uint redShift<QImage::Format_RGB32>() { return 16; }
+template<> constexpr uint redShift<QImage::Format_ARGB32>() { return 16; }
+template<> constexpr uint redShift<QImage::Format_ARGB32_Premultiplied>() { return 16; }
template<> constexpr uint redShift<QImage::Format_RGB16>() { return 11; }
template<> constexpr uint redShift<QImage::Format_RGB444>() { return 8; }
template<> constexpr uint redShift<QImage::Format_RGB555>() { return 10; }
@@ -88,6 +94,9 @@ template<> constexpr uint redShift<QImage::Format_RGBX8888>() { return 0; }
template<> constexpr uint redShift<QImage::Format_RGBA8888>() { return 0; }
template<> constexpr uint redShift<QImage::Format_RGBA8888_Premultiplied>() { return 0; }
#endif
+template<> constexpr uint greenWidth<QImage::Format_RGB32>() { return 8; }
+template<> constexpr uint greenWidth<QImage::Format_ARGB32>() { return 8; }
+template<> constexpr uint greenWidth<QImage::Format_ARGB32_Premultiplied>() { return 8; }
template<> constexpr uint greenWidth<QImage::Format_RGB16>() { return 6; }
template<> constexpr uint greenWidth<QImage::Format_RGB444>() { return 4; }
template<> constexpr uint greenWidth<QImage::Format_RGB555>() { return 5; }
@@ -102,6 +111,9 @@ template<> constexpr uint greenWidth<QImage::Format_RGBX8888>() { return 8; }
template<> constexpr uint greenWidth<QImage::Format_RGBA8888>() { return 8; }
template<> constexpr uint greenWidth<QImage::Format_RGBA8888_Premultiplied>() { return 8; }
+template<> constexpr uint greenShift<QImage::Format_RGB32>() { return 8; }
+template<> constexpr uint greenShift<QImage::Format_ARGB32>() { return 8; }
+template<> constexpr uint greenShift<QImage::Format_ARGB32_Premultiplied>() { return 8; }
template<> constexpr uint greenShift<QImage::Format_RGB16>() { return 5; }
template<> constexpr uint greenShift<QImage::Format_RGB444>() { return 4; }
template<> constexpr uint greenShift<QImage::Format_RGB555>() { return 5; }
@@ -121,6 +133,9 @@ template<> constexpr uint greenShift<QImage::Format_RGBX8888>() { return 8; }
template<> constexpr uint greenShift<QImage::Format_RGBA8888>() { return 8; }
template<> constexpr uint greenShift<QImage::Format_RGBA8888_Premultiplied>() { return 8; }
#endif
+template<> constexpr uint blueWidth<QImage::Format_RGB32>() { return 8; }
+template<> constexpr uint blueWidth<QImage::Format_ARGB32>() { return 8; }
+template<> constexpr uint blueWidth<QImage::Format_ARGB32_Premultiplied>() { return 8; }
template<> constexpr uint blueWidth<QImage::Format_RGB16>() { return 5; }
template<> constexpr uint blueWidth<QImage::Format_RGB444>() { return 4; }
template<> constexpr uint blueWidth<QImage::Format_RGB555>() { return 5; }
@@ -135,6 +150,9 @@ template<> constexpr uint blueWidth<QImage::Format_RGBX8888>() { return 8; }
template<> constexpr uint blueWidth<QImage::Format_RGBA8888>() { return 8; }
template<> constexpr uint blueWidth<QImage::Format_RGBA8888_Premultiplied>() { return 8; }
+template<> constexpr uint blueShift<QImage::Format_RGB32>() { return 0; }
+template<> constexpr uint blueShift<QImage::Format_ARGB32>() { return 0; }
+template<> constexpr uint blueShift<QImage::Format_ARGB32_Premultiplied>() { return 0; }
template<> constexpr uint blueShift<QImage::Format_RGB16>() { return 0; }
template<> constexpr uint blueShift<QImage::Format_RGB444>() { return 0; }
template<> constexpr uint blueShift<QImage::Format_RGB555>() { return 0; }
@@ -154,6 +172,9 @@ template<> constexpr uint blueShift<QImage::Format_RGBX8888>() { return 16; }
template<> constexpr uint blueShift<QImage::Format_RGBA8888>() { return 16; }
template<> constexpr uint blueShift<QImage::Format_RGBA8888_Premultiplied>() { return 16; }
#endif
+template<> constexpr uint alphaWidth<QImage::Format_RGB32>() { return 0; }
+template<> constexpr uint alphaWidth<QImage::Format_ARGB32>() { return 8; }
+template<> constexpr uint alphaWidth<QImage::Format_ARGB32_Premultiplied>() { return 8; }
template<> constexpr uint alphaWidth<QImage::Format_RGB16>() { return 0; }
template<> constexpr uint alphaWidth<QImage::Format_RGB444>() { return 0; }
template<> constexpr uint alphaWidth<QImage::Format_RGB555>() { return 0; }
@@ -168,6 +189,9 @@ template<> constexpr uint alphaWidth<QImage::Format_RGBX8888>() { return 0; }
template<> constexpr uint alphaWidth<QImage::Format_RGBA8888>() { return 8; }
template<> constexpr uint alphaWidth<QImage::Format_RGBA8888_Premultiplied>() { return 8; }
+template<> constexpr uint alphaShift<QImage::Format_RGB32>() { return 24; }
+template<> constexpr uint alphaShift<QImage::Format_ARGB32>() { return 24; }
+template<> constexpr uint alphaShift<QImage::Format_ARGB32_Premultiplied>() { return 24; }
template<> constexpr uint alphaShift<QImage::Format_RGB16>() { return 0; }
template<> constexpr uint alphaShift<QImage::Format_RGB444>() { return 0; }
template<> constexpr uint alphaShift<QImage::Format_RGB555>() { return 0; }
@@ -189,6 +213,9 @@ template<> constexpr uint alphaShift<QImage::Format_RGBA8888_Premultiplied>() {
#endif
template<QImage::Format> constexpr QPixelLayout::BPP bitsPerPixel();
+template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB32>() { return QPixelLayout::BPP32; }
+template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB32>() { return QPixelLayout::BPP32; }
+template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB32_Premultiplied>() { return QPixelLayout::BPP32; }
template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB16>() { return QPixelLayout::BPP16; }
template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB444>() { return QPixelLayout::BPP16; }
template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB555>() { return QPixelLayout::BPP16; }
@@ -218,6 +245,76 @@ inline void QT_FASTCALL storePixel<QPixelLayout::BPP24>(uchar *dest, int index,
reinterpret_cast<quint24 *>(dest)[index] = quint24(pixel);
}
+template <QPixelLayout::BPP bpp> static
+inline uint QT_FASTCALL fetchPixel(const uchar *, int)
+{
+ Q_UNREACHABLE();
+ return 0;
+}
+
+template <>
+inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP1LSB>(const uchar *src, int index)
+{
+ return (src[index >> 3] >> (index & 7)) & 1;
+}
+
+template <>
+inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP1MSB>(const uchar *src, int index)
+{
+ return (src[index >> 3] >> (~index & 7)) & 1;
+}
+
+template <>
+inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP8>(const uchar *src, int index)
+{
+ return src[index];
+}
+
+template <>
+inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP16>(const uchar *src, int index)
+{
+ return reinterpret_cast<const quint16 *>(src)[index];
+}
+
+template <>
+inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP24>(const uchar *src, int index)
+{
+ return reinterpret_cast<const quint24 *>(src)[index];
+}
+
+template <>
+inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP32>(const uchar *src, int index)
+{
+ return reinterpret_cast<const uint *>(src)[index];
+}
+
+template <>
+[[maybe_unused]]
+inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP64>(const uchar *src, int index)
+{
+ // We have to do the conversion in fetch to fit into a 32bit uint
+ QRgba64 c = reinterpret_cast<const QRgba64 *>(src)[index];
+ return c.toArgb32();
+}
+
+template <>
+[[maybe_unused]]
+inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP16FPx4>(const uchar *src, int index)
+{
+ // We have to do the conversion in fetch to fit into a 32bit uint
+ QRgba16F c = reinterpret_cast<const QRgba16F *>(src)[index];
+ return c.toArgb32();
+}
+
+template <>
+[[maybe_unused]]
+inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP32FPx4>(const uchar *src, int index)
+{
+ // We have to do the conversion in fetch to fit into a 32bit uint
+ QRgba32F c = reinterpret_cast<const QRgba32F *>(src)[index];
+ return c.toArgb32();
+}
+
template<QImage::Format Format>
static inline uint convertPixelToRGB32(uint s)
{
@@ -269,7 +366,7 @@ static const uint *QT_FASTCALL fetchRGBToRGB32(uint *buffer, const uchar *src, i
}
#endif
for (int i = 0; i < count; ++i)
- buffer[i] = convertPixelToRGB32<Format>(qFetchPixel<BPP>(src, index + i));
+ buffer[i] = convertPixelToRGB32<Format>(fetchPixel<BPP>(src, index + i));
return buffer;
}
@@ -293,7 +390,22 @@ static const QRgba64 *QT_FASTCALL fetchRGBToRGB64(QRgba64 *buffer, const uchar *
const QList<QRgb> *, QDitherInfo *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = convertPixelToRGB64<Format>(qFetchPixel<bitsPerPixel<Format>()>(src, index + i));
+ buffer[i] = convertPixelToRGB64<Format>(fetchPixel<bitsPerPixel<Format>()>(src, index + i));
+ return buffer;
+}
+
+template<QImage::Format Format>
+static Q_ALWAYS_INLINE QRgba32F convertPixelToRGB32F(uint s)
+{
+ return QRgba32F::fromArgb32(convertPixelToRGB32<Format>(s));
+}
+
+template<QImage::Format Format>
+static const QRgba32F *QT_FASTCALL fetchRGBToRGB32F(QRgba32F *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = convertPixelToRGB32F<Format>(fetchPixel<bitsPerPixel<Format>()>(src, index + i));
return buffer;
}
@@ -360,7 +472,7 @@ static const uint *QT_FASTCALL fetchARGBPMToARGB32PM(uint *buffer, const uchar *
}
#endif
for (int i = 0; i < count; ++i)
- buffer[i] = convertPixelToARGB32PM<Format>(qFetchPixel<BPP>(src, index + i));
+ buffer[i] = convertPixelToARGB32PM<Format>(fetchPixel<BPP>(src, index + i));
return buffer;
}
@@ -385,7 +497,33 @@ static const QRgba64 *QT_FASTCALL fetchARGBPMToRGBA64PM(QRgba64 *buffer, const u
{
constexpr QPixelLayout::BPP bpp = bitsPerPixel<Format>();
for (int i = 0; i < count; ++i)
- buffer[i] = convertPixelToRGBA64PM<Format>(qFetchPixel<bpp>(src, index + i));
+ buffer[i] = convertPixelToRGBA64PM<Format>(fetchPixel<bpp>(src, index + i));
+ return buffer;
+}
+
+template<QImage::Format Format>
+static Q_ALWAYS_INLINE QRgba32F convertPixelToRGBA32F(uint s)
+{
+ return QRgba32F::fromArgb32(convertPixelToARGB32PM<Format>(s));
+}
+
+template<QImage::Format Format>
+static const QRgba32F *QT_FASTCALL fetchARGBPMToRGBA32F(QRgba32F *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ constexpr QPixelLayout::BPP bpp = bitsPerPixel<Format>();
+ for (int i = 0; i < count; ++i)
+ buffer[i] = convertPixelToRGBA32F<Format>(fetchPixel<bpp>(src, index + i));
+ return buffer;
+}
+
+template<QImage::Format Format>
+static const QRgba32F *QT_FASTCALL fetchARGBToRGBA32F(QRgba32F *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ constexpr QPixelLayout::BPP bpp = bitsPerPixel<Format>();
+ for (int i = 0; i < count; ++i)
+ buffer[i] = convertPixelToRGBA32F<Format>(fetchPixel<bpp>(src, index + i)).premultiplied();
return buffer;
}
@@ -518,7 +656,7 @@ static void QT_FASTCALL rbSwap(uchar *dst, const uchar *src, int count)
constexpr QPixelLayout::BPP bpp = bitsPerPixel<Format>();
for (int i = 0; i < count; ++i) {
- const uint c = qFetchPixel<bpp>(src, i);
+ const uint c = fetchPixel<bpp>(src, i);
const uint r = (c >> rShift) & redBlueMask;
const uint b = (c >> bShift) & redBlueMask;
const uint t = (c & alphaGreenMask)
@@ -589,6 +727,27 @@ static void QT_FASTCALL rbSwap_4x16(uchar *d, const uchar *s, int count)
}
}
+static void QT_FASTCALL rbSwap_4x32(uchar *d, const uchar *s, int count)
+{
+ const uint *src = reinterpret_cast<const uint *>(s);
+ uint *dest = reinterpret_cast<uint *>(d);
+ if (src != dest) {
+ for (int i = 0; i < count; ++i) {
+ dest[i * 4 + 0] = src[i * 4 + 2];
+ dest[i * 4 + 1] = src[i * 4 + 1];
+ dest[i * 4 + 2] = src[i * 4 + 0];
+ dest[i * 4 + 3] = src[i * 4 + 3];
+ }
+ } else {
+ for (int i = 0; i < count; ++i) {
+ const uint r = src[i * 4 + 0];
+ const uint b = src[i * 4 + 2];
+ dest[i * 4 + 0] = b;
+ dest[i * 4 + 2] = r;
+ }
+ }
+}
+
template<QImage::Format Format> constexpr static inline QPixelLayout pixelLayoutRGB()
{
return QPixelLayout{
@@ -632,7 +791,7 @@ static const uint *QT_FASTCALL fetchIndexedToARGB32PM(uint *buffer, const uchar
const QList<QRgb> *clut, QDitherInfo *)
{
for (int i = 0; i < count; ++i) {
- const uint s = qFetchPixel<BPP>(src, index + i);
+ const uint s = fetchPixel<BPP>(src, index + i);
buffer[i] = qPremultiply(clut->at(s));
}
return buffer;
@@ -643,17 +802,29 @@ static const QRgba64 *QT_FASTCALL fetchIndexedToRGBA64PM(QRgba64 *buffer, const
const QList<QRgb> *clut, QDitherInfo *)
{
for (int i = 0; i < count; ++i) {
- const uint s = qFetchPixel<BPP>(src, index + i);
+ const uint s = fetchPixel<BPP>(src, index + i);
buffer[i] = QRgba64::fromArgb32(clut->at(s)).premultiplied();
}
return buffer;
}
-static const QRgba64 *QT_FASTCALL convertIndexedToRGBA64PM(QRgba64 *buffer, const uint *src, int count,
- const QList<QRgb> *clut, QDitherInfo *)
+template<QPixelLayout::BPP BPP>
+static const QRgba32F *QT_FASTCALL fetchIndexedToRGBA32F(QRgba32F *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *clut, QDitherInfo *)
+{
+ for (int i = 0; i < count; ++i) {
+ const uint s = fetchPixel<BPP>(src, index + i);
+ buffer[i] = QRgba32F::fromArgb32(clut->at(s)).premultiplied();
+ }
+ return buffer;
+}
+
+template<typename QRgba>
+static const QRgba *QT_FASTCALL convertIndexedTo(QRgba *buffer, const uint *src, int count,
+ const QList<QRgb> *clut, QDitherInfo *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = QRgba64::fromArgb32(clut->at(src[i])).premultiplied();
+ buffer[i] = QRgba::fromArgb32(clut->at(src[i])).premultiplied();
return buffer;
}
@@ -731,18 +902,21 @@ static const uint *QT_FASTCALL fetchAlpha8ToRGB32(uint *buffer, const uchar *src
return buffer;
}
-static const QRgba64 *QT_FASTCALL convertAlpha8ToRGB64(QRgba64 *buffer, const uint *src, int count,
- const QList<QRgb> *, QDitherInfo *)
+template<typename QRgba>
+static const QRgba *QT_FASTCALL convertAlpha8To(QRgba *buffer, const uint *src, int count,
+ const QList<QRgb> *, QDitherInfo *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = QRgba64::fromRgba(0, 0, 0, src[i]);
+ buffer[i] = QRgba::fromRgba(0, 0, 0, src[i]);
return buffer;
}
-static const QRgba64 *QT_FASTCALL fetchAlpha8ToRGB64(QRgba64 *buffer, const uchar *src, int index, int count,
- const QList<QRgb> *, QDitherInfo *)
+
+template<typename QRgba>
+static const QRgba *QT_FASTCALL fetchAlpha8To(QRgba *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = QRgba64::fromRgba(0, 0, 0, src[index + i]);
+ buffer[i] = QRgba::fromRgba(0, 0, 0, src[index + i]);
return buffer;
}
@@ -764,20 +938,22 @@ static const uint *QT_FASTCALL fetchGrayscale8ToRGB32(uint *buffer, const uchar
return buffer;
}
-static const QRgba64 *QT_FASTCALL convertGrayscale8ToRGB64(QRgba64 *buffer, const uint *src, int count,
- const QList<QRgb> *, QDitherInfo *)
+template<typename QRgba>
+static const QRgba *QT_FASTCALL convertGrayscale8To(QRgba *buffer, const uint *src, int count,
+ const QList<QRgb> *, QDitherInfo *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = QRgba64::fromRgba(src[i], src[i], src[i], 255);
+ buffer[i] = QRgba::fromRgba(src[i], src[i], src[i], 255);
return buffer;
}
-static const QRgba64 *QT_FASTCALL fetchGrayscale8ToRGB64(QRgba64 *buffer, const uchar *src, int index, int count,
- const QList<QRgb> *, QDitherInfo *)
+template<typename QRgba>
+static const QRgba *QT_FASTCALL fetchGrayscale8To(QRgba *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
{
for (int i = 0; i < count; ++i) {
const uint s = src[index + i];
- buffer[i] = QRgba64::fromRgba(s, s, s, 255);
+ buffer[i] = QRgba::fromRgba(s, s, s, 255);
}
return buffer;
}
@@ -789,7 +965,6 @@ static void QT_FASTCALL convertGrayscale16ToRGB32(uint *buffer, int count, const
buffer[i] = qRgb(x, x, x);
}
}
-
static const uint *QT_FASTCALL fetchGrayscale16ToRGB32(uint *buffer, const uchar *src, int index, int count,
const QList<QRgb> *, QDitherInfo *)
{
@@ -801,20 +976,22 @@ static const uint *QT_FASTCALL fetchGrayscale16ToRGB32(uint *buffer, const uchar
return buffer;
}
-static const QRgba64 *QT_FASTCALL convertGrayscale16ToRGBA64(QRgba64 *buffer, const uint *src, int count,
- const QList<QRgb> *, QDitherInfo *)
+template<typename QRgba>
+static const QRgba *QT_FASTCALL convertGrayscale16To(QRgba *buffer, const uint *src, int count,
+ const QList<QRgb> *, QDitherInfo *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = QRgba64::fromRgba64(src[i], src[i], src[i], 65535);
+ buffer[i] = QRgba::fromRgba64(src[i], src[i], src[i], 65535);
return buffer;
}
-static const QRgba64 *QT_FASTCALL fetchGrayscale16ToRGBA64(QRgba64 *buffer, const uchar *src, int index, int count,
- const QList<QRgb> *, QDitherInfo *)
+template<typename QRgba>
+static const QRgba *QT_FASTCALL fetchGrayscale16To(QRgba *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
{
const unsigned short *s = reinterpret_cast<const unsigned short *>(src) + index;
for (int i = 0; i < count; ++i) {
- buffer[i] = QRgba64::fromRgba64(s[i], s[i], s[i], 65535);
+ buffer[i] = QRgba::fromRgba64(s[i], s[i], s[i], 65535);
}
return buffer;
}
@@ -1212,6 +1389,44 @@ static const QRgba64 *QT_FASTCALL fetchA2RGB30PMToRGBA64PM(QRgba64 *buffer, cons
return convertA2RGB30PMToRGBA64PM<PixelOrder>(buffer, reinterpret_cast<const uint *>(src) + index, count, nullptr, nullptr);
}
+template<enum QtPixelOrder> inline QRgba32F qConvertA2rgb30ToRgbaFP(uint rgb);
+
+template<>
+inline QRgba32F qConvertA2rgb30ToRgbaFP<PixelOrderBGR>(uint rgb)
+{
+ float alpha = (rgb >> 30) * (1.f/3.f);
+ float blue = ((rgb >> 20) & 0x3ff) * (1.f/1023.f);
+ float green = ((rgb >> 10) & 0x3ff) * (1.f/1023.f);
+ float red = (rgb & 0x3ff) * (1.f/1023.f);
+ return QRgba32F{ red, green, blue, alpha };
+}
+
+template<>
+inline QRgba32F qConvertA2rgb30ToRgbaFP<PixelOrderRGB>(uint rgb)
+{
+ float alpha = (rgb >> 30) * (1.f/3.f);
+ float red = ((rgb >> 20) & 0x3ff) * (1.f/1023.f);
+ float green = ((rgb >> 10) & 0x3ff) * (1.f/1023.f);
+ float blue = (rgb & 0x3ff) * (1.f/1023.f);
+ return QRgba32F{ red, green, blue, alpha };
+}
+
+template<QtPixelOrder PixelOrder>
+static const QRgba32F *QT_FASTCALL convertA2RGB30PMToRGBA32F(QRgba32F *buffer, const uint *src, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = qConvertA2rgb30ToRgbaFP<PixelOrder>(src[i]);
+ return buffer;
+}
+
+template<QtPixelOrder PixelOrder>
+static const QRgba32F *QT_FASTCALL fetchRGB30ToRGBA32F(QRgba32F *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ return convertA2RGB30PMToRGBA32F<PixelOrder>(buffer, reinterpret_cast<const uint *>(src) + index, count, nullptr, nullptr);
+}
+
template<QtPixelOrder PixelOrder>
static void QT_FASTCALL storeA2RGB30PMFromARGB32PM(uchar *dest, const uint *src, int index, int count,
const QList<QRgb> *, QDitherInfo *)
@@ -1365,6 +1580,118 @@ static void QT_FASTCALL storeRGBA64FromARGB32(uchar *dest, const uint *src, int
d[i] = QRgba64::fromArgb32(src[i]);
}
+static const uint *QT_FASTCALL fetchRGB16FToRGB32(uint *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const QRgba16F *s = reinterpret_cast<const QRgba16F *>(src) + index;
+ for (int i = 0; i < count; ++i)
+ buffer[i] = s[i].toArgb32();
+ return buffer;
+}
+
+static void QT_FASTCALL storeRGB16FFromRGB32(uchar *dest, const uint *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba16F *d = reinterpret_cast<QRgba16F *>(dest) + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = QRgba16F::fromArgb32(src[i]);
+}
+
+static const uint *QT_FASTCALL fetchRGBA16FToARGB32PM(uint *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const QRgba16F *s = reinterpret_cast<const QRgba16F *>(src) + index;
+ for (int i = 0; i < count; ++i)
+ buffer[i] = s[i].premultiplied().toArgb32();
+ return buffer;
+}
+
+static const QRgba64 *QT_FASTCALL fetchRGBA16FToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const QRgba16F *s = reinterpret_cast<const QRgba16F *>(src) + index;
+ for (int i = 0; i < count; ++i) {
+ QRgba16F c = s[i].premultiplied();
+ buffer[i] = QRgba64::fromRgba64(c.red16(), c.green16(), c.blue16(), c.alpha16());
+ }
+ return buffer;
+}
+
+static void QT_FASTCALL storeRGBA16FFromARGB32PM(uchar *dest, const uint *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba16F *d = reinterpret_cast<QRgba16F *>(dest) + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = QRgba16F::fromArgb32(src[i]).unpremultiplied();
+}
+
+static const QRgba64 *QT_FASTCALL fetchRGBA16FPMToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const QRgba16F *s = reinterpret_cast<const QRgba16F *>(src) + index;
+ for (int i = 0; i < count; ++i) {
+ QRgba16F c = s[i];
+ buffer[i] = QRgba64::fromRgba64(c.red16(), c.green16(), c.blue16(), c.alpha16());
+ }
+ return buffer;
+}
+
+static const uint *QT_FASTCALL fetchRGB32FToRGB32(uint *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const QRgba32F *s = reinterpret_cast<const QRgba32F *>(src) + index;
+ for (int i = 0; i < count; ++i)
+ buffer[i] = s[i].toArgb32();
+ return buffer;
+}
+
+static void QT_FASTCALL storeRGB32FFromRGB32(uchar *dest, const uint *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba32F *d = reinterpret_cast<QRgba32F *>(dest) + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = QRgba32F::fromArgb32(src[i]);
+}
+
+static const uint *QT_FASTCALL fetchRGBA32FToARGB32PM(uint *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const QRgba32F *s = reinterpret_cast<const QRgba32F *>(src) + index;
+ for (int i = 0; i < count; ++i)
+ buffer[i] = s[i].premultiplied().toArgb32();
+ return buffer;
+}
+
+static const QRgba64 *QT_FASTCALL fetchRGBA32FToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const QRgba32F *s = reinterpret_cast<const QRgba32F *>(src) + index;
+ for (int i = 0; i < count; ++i) {
+ QRgba32F c = s[i].premultiplied();
+ buffer[i] = QRgba64::fromRgba64(c.red16(), c.green16(), c.blue16(), c.alpha16());
+ }
+ return buffer;
+}
+
+static void QT_FASTCALL storeRGBA32FFromARGB32PM(uchar *dest, const uint *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba32F *d = reinterpret_cast<QRgba32F *>(dest) + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = QRgba32F::fromArgb32(src[i]).unpremultiplied();
+}
+
+static const QRgba64 *QT_FASTCALL fetchRGBA32FPMToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const QRgba32F *s = reinterpret_cast<const QRgba32F *>(src) + index;
+ for (int i = 0; i < count; ++i) {
+ QRgba32F c = s[i];
+ buffer[i] = QRgba64::fromRgba64(c.red16(), c.green16(), c.blue16(), c.alpha16());
+ }
+ return buffer;
+}
+
// Note:
// convertToArgb32() assumes that no color channel is less than 4 bits.
// storeRGBFromARGB32PM() assumes that no color channel is more than 8 bits.
@@ -1372,15 +1699,15 @@ static void QT_FASTCALL storeRGBA64FromARGB32(uchar *dest, const uint *src, int
QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
{ false, false, QPixelLayout::BPPNone, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }, // Format_Invalid
{ false, false, QPixelLayout::BPP1MSB, nullptr,
- convertIndexedToARGB32PM, convertIndexedToRGBA64PM,
+ convertIndexedToARGB32PM, convertIndexedTo<QRgba64>,
fetchIndexedToARGB32PM<QPixelLayout::BPP1MSB>, fetchIndexedToRGBA64PM<QPixelLayout::BPP1MSB>,
nullptr, nullptr }, // Format_Mono
{ false, false, QPixelLayout::BPP1LSB, nullptr,
- convertIndexedToARGB32PM, convertIndexedToRGBA64PM,
+ convertIndexedToARGB32PM, convertIndexedTo<QRgba64>,
fetchIndexedToARGB32PM<QPixelLayout::BPP1LSB>, fetchIndexedToRGBA64PM<QPixelLayout::BPP1LSB>,
nullptr, nullptr }, // Format_MonoLSB
{ false, false, QPixelLayout::BPP8, nullptr,
- convertIndexedToARGB32PM, convertIndexedToRGBA64PM,
+ convertIndexedToARGB32PM, convertIndexedTo<QRgba64>,
fetchIndexedToARGB32PM<QPixelLayout::BPP8>, fetchIndexedToRGBA64PM<QPixelLayout::BPP8>,
nullptr, nullptr }, // Format_Indexed8
// Technically using convertPassThrough to convert from ARGB32PM to RGB32 is wrong,
@@ -1439,12 +1766,12 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
storeRGB30FromRGB32<PixelOrderRGB>
}, // Format_A2RGB30_Premultiplied
{ true, true, QPixelLayout::BPP8, nullptr,
- convertAlpha8ToRGB32, convertAlpha8ToRGB64,
- fetchAlpha8ToRGB32, fetchAlpha8ToRGB64,
+ convertAlpha8ToRGB32, convertAlpha8To<QRgba64>,
+ fetchAlpha8ToRGB32, fetchAlpha8To<QRgba64>,
storeAlpha8FromARGB32PM, nullptr }, // Format_Alpha8
{ false, false, QPixelLayout::BPP8, nullptr,
- convertGrayscale8ToRGB32, convertGrayscale8ToRGB64,
- fetchGrayscale8ToRGB32, fetchGrayscale8ToRGB64,
+ convertGrayscale8ToRGB32, convertGrayscale8To<QRgba64>,
+ fetchGrayscale8ToRGB32, fetchGrayscale8To<QRgba64>,
storeGrayscale8FromARGB32PM, storeGrayscale8FromRGB32 }, // Format_Grayscale8
{ false, false, QPixelLayout::BPP64, rbSwap_4x16,
convertPassThrough, nullptr,
@@ -1459,10 +1786,34 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
fetchRGB64ToRGB32, fetchPassThrough64,
storeRGBA64FromARGB32, storeRGB64FromRGB32 }, // Format_RGBA64_Premultiplied
{ false, false, QPixelLayout::BPP16, nullptr,
- convertGrayscale16ToRGB32, convertGrayscale16ToRGBA64,
- fetchGrayscale16ToRGB32, fetchGrayscale16ToRGBA64,
+ convertGrayscale16ToRGB32, convertGrayscale16To<QRgba64>,
+ fetchGrayscale16ToRGB32, fetchGrayscale16To<QRgba64>,
storeGrayscale16FromARGB32PM, storeGrayscale16FromRGB32 }, // Format_Grayscale16
pixelLayoutRGB<QImage::Format_BGR888>(),
+ { false, false, QPixelLayout::BPP16FPx4, rbSwap_4x16,
+ convertPassThrough, nullptr,
+ fetchRGB16FToRGB32, fetchRGBA16FPMToRGBA64PM,
+ storeRGB16FFromRGB32, storeRGB16FFromRGB32 }, // Format_RGBX16FPx4
+ { true, false, QPixelLayout::BPP16FPx4, rbSwap_4x16,
+ convertARGB32ToARGB32PM, nullptr,
+ fetchRGBA16FToARGB32PM, fetchRGBA16FToRGBA64PM,
+ storeRGBA16FFromARGB32PM, storeRGB16FFromRGB32 }, // Format_RGBA16FPx4
+ { true, true, QPixelLayout::BPP16FPx4, rbSwap_4x16,
+ convertPassThrough, nullptr,
+ fetchRGB16FToRGB32, fetchRGBA16FPMToRGBA64PM,
+ storeRGB16FFromRGB32, storeRGB16FFromRGB32 }, // Format_RGBA16FPx4_Premultiplied
+ { false, false, QPixelLayout::BPP32FPx4, rbSwap_4x32,
+ convertPassThrough, nullptr,
+ fetchRGB32FToRGB32, fetchRGBA32FPMToRGBA64PM,
+ storeRGB32FFromRGB32, storeRGB32FFromRGB32 }, // Format_RGBX32FPx4
+ { true, false, QPixelLayout::BPP32FPx4, rbSwap_4x32,
+ convertARGB32ToARGB32PM, nullptr,
+ fetchRGBA32FToARGB32PM, fetchRGBA32FToRGBA64PM,
+ storeRGBA32FFromARGB32PM, storeRGB32FFromRGB32 }, // Format_RGBA32FPx4
+ { true, true, QPixelLayout::BPP32FPx4, rbSwap_4x32,
+ convertPassThrough, nullptr,
+ fetchRGB32FToRGB32, fetchRGBA32FPMToRGBA64PM,
+ storeRGB32FFromRGB32, storeRGB32FFromRGB32 }, // Format_RGBA32FPx4_Premultiplied
};
static_assert(sizeof(qPixelLayouts) / sizeof(*qPixelLayouts) == QImage::NImageFormats);
@@ -1548,6 +1899,58 @@ static void QT_FASTCALL storeGray16FromRGBA64PM(uchar *dest, const QRgba64 *src,
}
}
+static void QT_FASTCALL storeRGBX16FFromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba16F *d = reinterpret_cast<QRgba16F *>(dest) + index;
+ for (int i = 0; i < count; ++i) {
+ d[i] = qConvertRgb64ToRgbaF16(src[i]).unpremultiplied();
+ d[i].setAlpha(1.0);
+ }
+}
+
+static void QT_FASTCALL storeRGBA16FFromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba16F *d = reinterpret_cast<QRgba16F *>(dest) + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = qConvertRgb64ToRgbaF16(src[i]).unpremultiplied();
+}
+
+static void QT_FASTCALL storeRGBA16FPMFromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba16F *d = reinterpret_cast<QRgba16F *>(dest) + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = qConvertRgb64ToRgbaF16(src[i]);
+}
+
+static void QT_FASTCALL storeRGBX32FFromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba32F *d = reinterpret_cast<QRgba32F *>(dest) + index;
+ for (int i = 0; i < count; ++i) {
+ d[i] = qConvertRgb64ToRgbaF32(src[i]).unpremultiplied();
+ d[i].setAlpha(1.0);
+ }
+}
+
+static void QT_FASTCALL storeRGBA32FFromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba32F *d = reinterpret_cast<QRgba32F *>(dest) + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = qConvertRgb64ToRgbaF32(src[i]).unpremultiplied();
+}
+
+static void QT_FASTCALL storeRGBA32FPMFromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba32F *d = reinterpret_cast<QRgba32F *>(dest) + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = qConvertRgb64ToRgbaF32(src[i]);
+}
+
ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats] = {
nullptr,
nullptr,
@@ -1579,6 +1982,375 @@ ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats] = {
storeRGBA64PMFromRGBA64PM,
storeGray16FromRGBA64PM,
storeGenericFromRGBA64PM<QImage::Format_BGR888>,
+ storeRGBX16FFromRGBA64PM,
+ storeRGBA16FFromRGBA64PM,
+ storeRGBA16FPMFromRGBA64PM,
+ storeRGBX32FFromRGBA64PM,
+ storeRGBA32FFromRGBA64PM,
+ storeRGBA32FPMFromRGBA64PM,
+};
+
+#if QT_CONFIG(raster_fp)
+static void QT_FASTCALL convertToRgbaF32(QRgba32F *dest, const uint *src, int length)
+{
+ for (int i = 0; i < length; ++i)
+ dest[i] = QRgba32F::fromArgb32(src[i]);
+}
+
+template<QImage::Format format>
+static const QRgba32F * QT_FASTCALL convertGenericToRGBA32F(QRgba32F *buffer, const uint *src, int count,
+ const QList<QRgb> *clut, QDitherInfo *)
+{
+ uint buffer32[BufferSize];
+ memcpy(buffer32, src, count * sizeof(uint));
+ qPixelLayouts[format].convertToARGB32PM(buffer32, count, clut);
+ convertToRgbaF32(buffer, buffer32, count);
+ return buffer;
+}
+
+static const QRgba32F * QT_FASTCALL convertARGB32ToRGBA32F(QRgba32F *buffer, const uint *src, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = QRgba32F::fromArgb32(src[i]).premultiplied();
+ return buffer;
+}
+
+static const QRgba32F * QT_FASTCALL convertRGBA8888ToRGBA32F(QRgba32F *buffer, const uint *src, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = QRgba32F::fromArgb32(RGBA2ARGB(src[i])).premultiplied();
+ return buffer;
+}
+
+template<QtPixelOrder PixelOrder>
+static const QRgba32F * QT_FASTCALL convertRGB30ToRGBA32F(QRgba32F *buffer, const uint *src, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ for (int i = 0; i < count; ++i) {
+ QRgba64 s = qConvertA2rgb30ToRgb64<PixelOrder>(src[i]);
+ buffer[i] = QRgba32F::fromRgba64(s.red(), s.green(), s.blue(), s.alpha());
+ }
+ return buffer;
+}
+
+ConvertToFPFunc qConvertToRGBA32F[QImage::NImageFormats] = {
+ nullptr,
+ convertIndexedTo<QRgba32F>,
+ convertIndexedTo<QRgba32F>,
+ convertIndexedTo<QRgba32F>,
+ convertGenericToRGBA32F<QImage::Format_RGB32>,
+ convertARGB32ToRGBA32F,
+ convertGenericToRGBA32F<QImage::Format_ARGB32_Premultiplied>,
+ convertGenericToRGBA32F<QImage::Format_RGB16>,
+ convertGenericToRGBA32F<QImage::Format_ARGB8565_Premultiplied>,
+ convertGenericToRGBA32F<QImage::Format_RGB666>,
+ convertGenericToRGBA32F<QImage::Format_ARGB6666_Premultiplied>,
+ convertGenericToRGBA32F<QImage::Format_RGB555>,
+ convertGenericToRGBA32F<QImage::Format_ARGB8555_Premultiplied>,
+ convertGenericToRGBA32F<QImage::Format_RGB888>,
+ convertGenericToRGBA32F<QImage::Format_RGB444>,
+ convertGenericToRGBA32F<QImage::Format_ARGB4444_Premultiplied>,
+ convertGenericToRGBA32F<QImage::Format_RGBX8888>,
+ convertRGBA8888ToRGBA32F,
+ convertGenericToRGBA32F<QImage::Format_RGBA8888_Premultiplied>,
+ convertRGB30ToRGBA32F<PixelOrderBGR>,
+ convertRGB30ToRGBA32F<PixelOrderBGR>,
+ convertRGB30ToRGBA32F<PixelOrderRGB>,
+ convertRGB30ToRGBA32F<PixelOrderRGB>,
+ convertAlpha8To<QRgba32F>,
+ convertGrayscale8To<QRgba32F>,
+ nullptr,
+ nullptr,
+ nullptr,
+ convertGrayscale16To<QRgba32F>,
+ convertGenericToRGBA32F<QImage::Format_BGR888>,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+};
+
+static const QRgba32F *QT_FASTCALL fetchRGBX64ToRGBA32F(QRgba32F *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const QRgba64 *s = reinterpret_cast<const QRgba64 *>(src) + index;
+ for (int i = 0; i < count; ++i) {
+ QRgba64 c = s[i];
+ buffer[i] = QRgba32F::fromRgba64(c.red(), c.green(), c.blue(), 65535);
+ }
+ return buffer;
+}
+
+static const QRgba32F *QT_FASTCALL fetchRGBA64ToRGBA32F(QRgba32F *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const QRgba64 *s = reinterpret_cast<const QRgba64 *>(src) + index;
+ for (int i = 0; i < count; ++i)
+ buffer[i] = qConvertRgb64ToRgbaF32(s[i]).premultiplied();
+ return buffer;
+}
+
+static const QRgba32F *QT_FASTCALL fetchRGBA64PMToRGBA32F(QRgba32F *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const QRgba64 *s = reinterpret_cast<const QRgba64 *>(src) + index;
+ for (int i = 0; i < count; ++i)
+ buffer[i] = qConvertRgb64ToRgbaF32(s[i]);
+ return buffer;
+}
+
+static const QRgba32F *QT_FASTCALL fetchRGBA16FToRGBA32F(QRgba32F *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const QRgba16F *s = reinterpret_cast<const QRgba16F *>(src) + index;
+ for (int i = 0; i < count; ++i) {
+ auto c = s[i].premultiplied();
+ buffer[i] = QRgba32F { c.r, c.g, c.b, c.a};
+ }
+ return buffer;
+}
+
+static const QRgba32F *QT_FASTCALL fetchRGBA16F(QRgba32F *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const QRgba16F *s = reinterpret_cast<const QRgba16F *>(src) + index;
+ qFloatFromFloat16((float *)buffer, (const qfloat16 *)s, count * 4);
+ return buffer;
+}
+
+static const QRgba32F *QT_FASTCALL fetchRGBA32FToRGBA32F(QRgba32F *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const QRgba32F *s = reinterpret_cast<const QRgba32F *>(src) + index;
+ for (int i = 0; i < count; ++i)
+ buffer[i] = s[i].premultiplied();
+ return buffer;
+}
+
+static const QRgba32F *QT_FASTCALL fetchRGBA32F(QRgba32F *, const uchar *src, int index, int,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const QRgba32F *s = reinterpret_cast<const QRgba32F *>(src) + index;
+ return s;
+}
+
+FetchAndConvertPixelsFuncFP qFetchToRGBA32F[QImage::NImageFormats] = {
+ nullptr,
+ fetchIndexedToRGBA32F<QPixelLayout::BPP1MSB>,
+ fetchIndexedToRGBA32F<QPixelLayout::BPP1LSB>,
+ fetchIndexedToRGBA32F<QPixelLayout::BPP8>,
+ fetchRGBToRGB32F<QImage::Format_RGB32>,
+ fetchARGBToRGBA32F<QImage::Format_ARGB32>,
+ fetchARGBPMToRGBA32F<QImage::Format_ARGB32_Premultiplied>,
+ fetchRGBToRGB32F<QImage::Format_RGB16>,
+ fetchARGBToRGBA32F<QImage::Format_ARGB8565_Premultiplied>,
+ fetchRGBToRGB32F<QImage::Format_RGB666>,
+ fetchARGBToRGBA32F<QImage::Format_ARGB6666_Premultiplied>,
+ fetchRGBToRGB32F<QImage::Format_RGB555>,
+ fetchARGBToRGBA32F<QImage::Format_ARGB8555_Premultiplied>,
+ fetchRGBToRGB32F<QImage::Format_RGB888>,
+ fetchRGBToRGB32F<QImage::Format_RGB444>,
+ fetchARGBToRGBA32F<QImage::Format_ARGB4444_Premultiplied>,
+ fetchRGBToRGB32F<QImage::Format_RGBX8888>,
+ fetchARGBToRGBA32F<QImage::Format_RGBA8888>,
+ fetchARGBPMToRGBA32F<QImage::Format_RGBA8888_Premultiplied>,
+ fetchRGB30ToRGBA32F<PixelOrderBGR>,
+ fetchRGB30ToRGBA32F<PixelOrderBGR>,
+ fetchRGB30ToRGBA32F<PixelOrderRGB>,
+ fetchRGB30ToRGBA32F<PixelOrderRGB>,
+ fetchAlpha8To<QRgba32F>,
+ fetchGrayscale8To<QRgba32F>,
+ fetchRGBX64ToRGBA32F,
+ fetchRGBA64ToRGBA32F,
+ fetchRGBA64PMToRGBA32F,
+ fetchGrayscale16To<QRgba32F>,
+ fetchRGBToRGB32F<QImage::Format_BGR888>,
+ fetchRGBA16F,
+ fetchRGBA16FToRGBA32F,
+ fetchRGBA16F,
+ fetchRGBA32F,
+ fetchRGBA32FToRGBA32F,
+ fetchRGBA32F,
+};
+
+static void QT_FASTCALL convertFromRgba32f(uint *dest, const QRgba32F *src, int length)
+{
+ for (int i = 0; i < length; ++i)
+ dest[i] = src[i].toArgb32();
+}
+
+template<QImage::Format format>
+static void QT_FASTCALL storeGenericFromRGBA32F(uchar *dest, const QRgba32F *src, int index, int count,
+ const QList<QRgb> *clut, QDitherInfo *dither)
+{
+ uint buffer[BufferSize];
+ convertFromRgba32f(buffer, src, count);
+ qPixelLayouts[format].storeFromARGB32PM(dest, buffer, index, count, clut, dither);
+}
+
+static void QT_FASTCALL storeARGB32FromRGBA32F(uchar *dest, const QRgba32F *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ uint *d = (uint*)dest + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = src[i].unpremultiplied().toArgb32();
+}
+
+static void QT_FASTCALL storeRGBA8888FromRGBA32F(uchar *dest, const QRgba32F *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ uint *d = (uint*)dest + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = ARGB2RGBA(src[i].unpremultiplied().toArgb32());
+}
+
+template<QtPixelOrder PixelOrder>
+static void QT_FASTCALL storeRGB30FromRGBA32F(uchar *dest, const QRgba32F *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ uint *d = (uint*)dest + index;
+ for (int i = 0; i < count; ++i) {
+ const auto s = src[i];
+ d[i] = qConvertRgb64ToRgb30<PixelOrder>(QRgba64::fromRgba64(s.red16(), s.green16(), s.blue16(), s.alpha16()));
+ }
+}
+
+static void QT_FASTCALL storeRGBX64FromRGBA32F(uchar *dest, const QRgba32F *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba64 *d = reinterpret_cast<QRgba64 *>(dest) + index;
+ for (int i = 0; i < count; ++i) {
+ const auto s = src[i].unpremultiplied();
+ d[i] = QRgba64::fromRgba64(s.red16(), s.green16(), s.blue16(), 65535);
+ }
+}
+
+static void QT_FASTCALL storeRGBA64FromRGBA32F(uchar *dest, const QRgba32F *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba64 *d = reinterpret_cast<QRgba64 *>(dest) + index;
+ for (int i = 0; i < count; ++i) {
+ const auto s = src[i].unpremultiplied();
+ d[i] = QRgba64::fromRgba64(s.red16(), s.green16(), s.blue16(), s.alpha16());
+ }
+}
+
+static void QT_FASTCALL storeRGBA64PMFromRGBA32F(uchar *dest, const QRgba32F *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba64 *d = reinterpret_cast<QRgba64 *>(dest) + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = QRgba64::fromRgba64(src[i].red16(), src[i].green16(), src[i].blue16(), src[i].alpha16());
+}
+
+static void QT_FASTCALL storeGray16FromRGBA32F(uchar *dest, const QRgba32F *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ quint16 *d = reinterpret_cast<quint16 *>(dest) + index;
+ for (int i = 0; i < count; ++i) {
+ auto s = src[i].unpremultiplied();
+ d[i] = qGray(s.red16(), s.green16(), s.blue16());
+ }
+}
+
+static void QT_FASTCALL storeRGBX16FFromRGBA32F(uchar *dest, const QRgba32F *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba16F *d = reinterpret_cast<QRgba16F *>(dest) + index;
+ for (int i = 0; i < count; ++i) {
+ auto s = src[i].unpremultiplied();
+ d[i] = QRgba16F{ s.r, s.g, s.b, 1.0f };
+ }
+}
+
+static void QT_FASTCALL storeRGBA16FFromRGBA32F(uchar *dest, const QRgba32F *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba16F *d = reinterpret_cast<QRgba16F *>(dest) + index;
+ for (int i = 0; i < count; ++i) {
+ auto s = src[i].unpremultiplied();
+ d[i] = QRgba16F{ s.r, s.g, s.b, s.a };
+ }
+}
+
+static void QT_FASTCALL storeRGBA16FPMFromRGBA32F(uchar *dest, const QRgba32F *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba16F *d = reinterpret_cast<QRgba16F *>(dest) + index;
+ qFloatToFloat16((qfloat16 *)d, (const float *)src, count * 4);
+}
+
+static void QT_FASTCALL storeRGBX32FFromRGBA32F(uchar *dest, const QRgba32F *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba32F *d = reinterpret_cast<QRgba32F *>(dest) + index;
+ for (int i = 0; i < count; ++i) {
+ auto s = src[i].unpremultiplied();
+ s.a = 1.0f;
+ d[i] = s;
+ }
+}
+
+static void QT_FASTCALL storeRGBA32FFromRGBA32F(uchar *dest, const QRgba32F *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba32F *d = reinterpret_cast<QRgba32F *>(dest) + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = src[i].unpremultiplied();
+}
+
+static void QT_FASTCALL storeRGBA32FPMFromRGBA32F(uchar *dest, const QRgba32F *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ QRgba32F *d = reinterpret_cast<QRgba32F *>(dest) + index;
+ if (d != src) {
+ for (int i = 0; i < count; ++i)
+ d[i] = src[i];
+ }
+}
+
+ConvertAndStorePixelsFuncFP qStoreFromRGBA32F[QImage::NImageFormats] = {
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ storeGenericFromRGBA32F<QImage::Format_RGB32>,
+ storeARGB32FromRGBA32F,
+ storeGenericFromRGBA32F<QImage::Format_ARGB32_Premultiplied>,
+ storeGenericFromRGBA32F<QImage::Format_RGB16>,
+ storeGenericFromRGBA32F<QImage::Format_ARGB8565_Premultiplied>,
+ storeGenericFromRGBA32F<QImage::Format_RGB666>,
+ storeGenericFromRGBA32F<QImage::Format_ARGB6666_Premultiplied>,
+ storeGenericFromRGBA32F<QImage::Format_RGB555>,
+ storeGenericFromRGBA32F<QImage::Format_ARGB8555_Premultiplied>,
+ storeGenericFromRGBA32F<QImage::Format_RGB888>,
+ storeGenericFromRGBA32F<QImage::Format_RGB444>,
+ storeGenericFromRGBA32F<QImage::Format_ARGB4444_Premultiplied>,
+ storeGenericFromRGBA32F<QImage::Format_RGBX8888>,
+ storeRGBA8888FromRGBA32F,
+ storeGenericFromRGBA32F<QImage::Format_RGBA8888_Premultiplied>,
+ storeRGB30FromRGBA32F<PixelOrderBGR>,
+ storeRGB30FromRGBA32F<PixelOrderBGR>,
+ storeRGB30FromRGBA32F<PixelOrderRGB>,
+ storeRGB30FromRGBA32F<PixelOrderRGB>,
+ storeGenericFromRGBA32F<QImage::Format_Alpha8>,
+ storeGenericFromRGBA32F<QImage::Format_Grayscale8>,
+ storeRGBX64FromRGBA32F,
+ storeRGBA64FromRGBA32F,
+ storeRGBA64PMFromRGBA32F,
+ storeGray16FromRGBA32F,
+ storeGenericFromRGBA32F<QImage::Format_BGR888>,
+ storeRGBX16FFromRGBA32F,
+ storeRGBA16FFromRGBA32F,
+ storeRGBA16FPMFromRGBA32F,
+ storeRGBX32FFromRGBA32F,
+ storeRGBA32FFromRGBA32F,
+ storeRGBA32FPMFromRGBA32F,
};
+#endif // QT_CONFIG(raster_fp)
QT_END_NAMESPACE
diff --git a/src/gui/painting/qpixellayout_p.h b/src/gui/painting/qpixellayout_p.h
index 6d20131efe..bf0bac3b09 100644
--- a/src/gui/painting/qpixellayout_p.h
+++ b/src/gui/painting/qpixellayout_p.h
@@ -54,6 +54,7 @@
#include <QtCore/qlist.h>
#include <QtGui/qimage.h>
#include <QtGui/qrgba64.h>
+#include <QtGui/qrgbaf.h>
QT_BEGIN_NAMESPACE
@@ -217,6 +218,16 @@ inline unsigned int qConvertRgb64ToRgb30<PixelOrderRGB>(QRgba64 c)
return (a << 30) | (r << 20) | (g << 10) | b;
}
+inline constexpr QRgba16F qConvertRgb64ToRgbaF16(QRgba64 c)
+{
+ return QRgba16F::fromRgba64(c.red(), c.green(), c.blue(), c.alpha());
+}
+
+inline constexpr QRgba32F qConvertRgb64ToRgbaF32(QRgba64 c)
+{
+ return QRgba32F::fromRgba64(c.red(), c.green(), c.blue(), c.alpha());
+}
+
inline uint qRgbSwapRgb30(uint c)
{
const uint ag = c & 0xc00ffc00;
@@ -296,10 +307,19 @@ typedef void(QT_FASTCALL *ConvertAndStorePixelsFunc64)(uchar *dest, const QRgba6
int count, const QList<QRgb> *clut,
QDitherInfo *dither);
-typedef void(QT_FASTCALL *ConvertFunc)(uint *buffer, int count, const QList<QRgb> *clut);
-typedef void(QT_FASTCALL *Convert64Func)(quint64 *buffer, int count, const QList<QRgb> *clut);
+typedef const QRgba32F *(QT_FASTCALL *FetchAndConvertPixelsFuncFP)(QRgba32F *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *clut, QDitherInfo *dither);
+typedef void (QT_FASTCALL *ConvertAndStorePixelsFuncFP)(uchar *dest, const QRgba32F *src, int index, int count,
+ const QList<QRgb> *clut, QDitherInfo *dither);
+typedef void (QT_FASTCALL *ConvertFunc)(uint *buffer, int count, const QList<QRgb> *clut);
+typedef void (QT_FASTCALL *Convert64Func)(QRgba64 *buffer, int count);
+typedef void (QT_FASTCALL *ConvertFPFunc)(QRgba32F *buffer, int count);
+typedef void (QT_FASTCALL *Convert64ToFPFunc)(QRgba32F *buffer, const quint64 *src, int count);
+
typedef const QRgba64 *(QT_FASTCALL *ConvertTo64Func)(QRgba64 *buffer, const uint *src, int count,
const QList<QRgb> *clut, QDitherInfo *dither);
+typedef const QRgba32F *(QT_FASTCALL *ConvertToFPFunc)(QRgba32F *buffer, const uint *src, int count,
+ const QList<QRgb> *clut, QDitherInfo *dither);
typedef void (QT_FASTCALL *RbSwapFunc)(uchar *dst, const uchar *src, int count);
typedef void (*MemRotateFunc)(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl);
@@ -316,6 +336,8 @@ struct QPixelLayout
BPP24,
BPP32,
BPP64,
+ BPP16FPx4,
+ BPP32FPx4,
BPPCount
};
@@ -333,6 +355,12 @@ struct QPixelLayout
extern ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats];
+#if QT_CONFIG(raster_fp)
+extern ConvertToFPFunc qConvertToRGBA32F[QImage::NImageFormats];
+extern FetchAndConvertPixelsFuncFP qFetchToRGBA32F[QImage::NImageFormats];
+extern ConvertAndStorePixelsFuncFP qStoreFromRGBA32F[QImage::NImageFormats];
+#endif
+
extern QPixelLayout qPixelLayouts[QImage::NImageFormats];
extern MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3];
diff --git a/src/gui/painting/qrgbaf.h b/src/gui/painting/qrgbaf.h
new file mode 100644
index 0000000000..da6d0a3646
--- /dev/null
+++ b/src/gui/painting/qrgbaf.h
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRGBAF_H
+#define QRGBAF_H
+
+#include <QtGui/qtguiglobal.h>
+#include <QtCore/qfloat16.h>
+
+#include <algorithm>
+#include <cmath>
+
+QT_BEGIN_NAMESPACE
+
+template<typename F>
+class alignas(sizeof(F) * 4) QRgbaF {
+public:
+ F r;
+ F g;
+ F b;
+ F a;
+
+ static constexpr
+ QRgbaF fromRgba64(quint16 red, quint16 green, quint16 blue, quint16 alpha)
+ {
+ return QRgbaF{
+ red * (1.0f / 65535.0f),
+ green * (1.0f / 65535.0f),
+ blue * (1.0f / 65535.0f),
+ alpha * (1.0f / 65535.0f) };
+ }
+
+ static constexpr
+ QRgbaF fromRgba(quint8 red, quint8 green, quint8 blue, quint8 alpha)
+ {
+ return QRgbaF{
+ red * (1.0f / 255.0f),
+ green * (1.0f / 255.0f),
+ blue * (1.0f / 255.0f),
+ alpha * (1.0f / 255.0f) };
+ }
+ static constexpr
+ QRgbaF fromArgb32(uint rgb)
+ {
+ return fromRgba(quint8(rgb >> 16), quint8(rgb >> 8), quint8(rgb), quint8(rgb >> 24));
+ }
+
+ constexpr bool isOpaque() const { return a >= 1.0f; }
+ constexpr bool isTransparent() const { return a <= 0.0f; }
+
+ constexpr float red() const { return r; }
+ constexpr float green() const { return g; }
+ constexpr float blue() const { return b; }
+ constexpr float alpha() const { return a; }
+ void setRed(float _red) { r = _red; }
+ void setGreen(float _green) { g = _green; }
+ void setBlue(float _blue) { b = _blue; }
+ void setAlpha(float _alpha) { a = _alpha; }
+
+ constexpr float redNormalized() const { return std::clamp(static_cast<float>(r), 0.0f, 1.0f); }
+ constexpr float greenNormalized() const { return std::clamp(static_cast<float>(g), 0.0f, 1.0f); }
+ constexpr float blueNormalized() const { return std::clamp(static_cast<float>(b), 0.0f, 1.0f); }
+ constexpr float alphaNormalized() const { return std::clamp(static_cast<float>(a), 0.0f, 1.0f); }
+
+ constexpr quint8 red8() const { return std::lround(redNormalized() * 255.0f); }
+ constexpr quint8 green8() const { return std::lround(greenNormalized() * 255.0f); }
+ constexpr quint8 blue8() const { return std::lround(blueNormalized() * 255.0f); }
+ constexpr quint8 alpha8() const { return std::lround(alphaNormalized() * 255.0f); }
+ constexpr uint toArgb32() const
+ {
+ return uint((alpha8() << 24) | (red8() << 16) | (green8() << 8) | blue8());
+ }
+
+ constexpr quint16 red16() const { return std::lround(redNormalized() * 65535.0f); }
+ constexpr quint16 green16() const { return std::lround(greenNormalized() * 65535.0f); }
+ constexpr quint16 blue16() const { return std::lround(blueNormalized() * 65535.0f); }
+ constexpr quint16 alpha16() const { return std::lround(alphaNormalized() * 65535.0f); }
+
+ constexpr Q_ALWAYS_INLINE QRgbaF premultiplied() const
+ {
+ return QRgbaF{r * a, g * a, b * a, a};
+ }
+ constexpr Q_ALWAYS_INLINE QRgbaF unpremultiplied() const
+ {
+ if (a <= 0.0f)
+ return QRgbaF{0.0f, 0.0f, 0.0f, 0.0f};
+ if (a >= 1.0f)
+ return *this;
+ const float ia = 1.0f / a;
+ return QRgbaF{r * ia, g * ia, b * ia, a};
+ }
+};
+
+typedef QRgbaF<float> QRgba32F;
+typedef QRgbaF<qfloat16> QRgba16F;
+
+QT_END_NAMESPACE
+
+#endif // QRGBAF_H
diff --git a/src/gui/painting/qrgbaf.qdoc b/src/gui/painting/qrgbaf.qdoc
new file mode 100644
index 0000000000..3e9760ce22
--- /dev/null
+++ b/src/gui/painting/qrgbaf.qdoc
@@ -0,0 +1,248 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QRgbaF
+ \brief The QRgbaF struct contains a four part RGBA floating-point color.
+ \since 6.2
+
+ \ingroup painting
+ \inmodule QtGui
+
+ QRgba16F is a 64-bit data-structure containing four 16-bit floating point color channels: Red, green, blue and alpha.
+ QRgba32F is a 128-bit data-structure containing four 32-bit floating point color channels: Red, green, blue and alpha.
+
+ \sa QRgb, QRgba64, QColor
+*/
+
+/*!
+ \fn template<typename F> QRgbaF<F>::fromRgba64(quint16 r, quint16 g, quint16 b, quint16 a)
+
+ Constructs a QRgbaF value from the four 16-bit integer color channels \a red, \a green, \a blue and \a alpha.
+
+ \sa fromRgba()
+*/
+
+/*!
+ \fn template<typename F> QRgbaF<F>::fromRgba(quint8 red, quint8 green, quint8 blue, quint8 alpha)
+
+ Constructs a QRgbaF value from the four 8-bit color channels \a red, \a green, \a blue and \a alpha.
+
+ \sa fromArgb32()
+*/
+
+/*!
+ \fn template<typename F> QRgbaF<F>::fromArgb32(uint rgb)
+
+ Constructs a QRgbaF value from the 32bit ARGB value \a rgb.
+
+ \sa fromRgba(), toArgb32()
+*/
+
+/*!
+ \fn template<typename F> bool QRgbaF<F>::isOpaque() const
+
+ Returns whether the color is fully opaque.
+
+ \sa isTransparent(), alpha()
+*/
+
+/*!
+ \fn template<typename F> bool QRgbaF<F>::isTransparent() const
+
+ Returns whether the color is fully transparent.
+
+ \sa isOpaque(), alpha()
+*/
+
+/*!
+ \fn template<typename F> float QRgbaF<F>::red() const
+
+ Returns the red color component.
+
+ \sa setRed()
+*/
+
+/*!
+ \fn template<typename F> void QRgbaF<F>::setRed(float red)
+
+ Sets the red color component of this color to \a red.
+
+ \sa red()
+*/
+
+/*!
+ \fn template<typename F> float QRgbaF<F>::green() const
+
+ Returns the green color component.
+
+ \sa setGreen()
+*/
+
+/*!
+ \fn template<typename F> void QRgbaF<F>::setGreen(float green)
+
+ Sets the green color component of this color to \a green.
+
+ \sa green()
+*/
+
+/*!
+ \fn template<typename F> float QRgbaF<F>::blue() const
+
+ Returns the blue color component.
+
+ \sa setBlue()
+*/
+
+/*!
+ \fn template<typename F> void QRgbaF<F>::setBlue(float blue)
+
+ Sets the blue color component of this color to \a blue.
+
+ \sa blue()
+*/
+
+/*!
+ \fn template<typename F> float QRgbaF<F>::alpha() const
+
+ Returns the alpha channel.
+
+ \sa setAlpha()
+*/
+
+/*!
+ \fn template<typename F> void QRgbaF<F>::setAlpha(float alpha)
+
+ Sets the alpha of this color to \a alpha.
+
+ \sa alpha()
+*/
+
+/*!
+ \fn template<typename F> float QRgbaF<F>::redNormalized() const
+
+ Returns the red color component normalized to values between \c 0.0f and \c 1.0f.
+
+ \sa setRed()
+*/
+
+/*!
+ \fn template<typename F> float QRgbaF<F>::greenNormalized() const
+
+ Returns the green color component normalized to values between \c 0.0f and \c 1.0f.
+
+ \sa setGreen()
+*/
+
+/*!
+ \fn template<typename F> float QRgbaF<F>::blueNormalized() const
+
+ Returns the blue color component normalized to values between \c 0.0f and \c 1.0f.
+
+ \sa setBlue()
+*/
+
+/*!
+ \fn template<typename F> float QRgbaF<F>::alphaNormalized() const
+
+ Returns the alpha channel normalized to values between \c 0.0f and \c 1.0f.
+
+ \sa alpha()
+*/
+
+/*!
+ \fn template<typename F> quint8 QRgbaF<F>::red8() const
+
+ Returns the red color component as an 8-bit.
+*/
+
+/*!
+ \fn template<typename F> quint8 QRgbaF<F>::green8() const
+
+ Returns the green color component as an 8-bit.
+*/
+
+/*!
+ \fn template<typename F> quint8 QRgbaF<F>::blue8() const
+
+ Returns the blue color component as an 8-bit.
+*/
+
+/*!
+ \fn template<typename F> quint8 QRgbaF<F>::alpha8() const
+
+ Returns the alpha channel as an 8-bit.
+*/
+
+/*!
+ \fn template<typename F> uint QRgbaF<F>::toArgb32() const
+
+ Returns the color as a 32-bit ARGB value.
+
+ \sa fromArgb32()
+*/
+
+/*!
+ \fn template<typename F> quint16 QRgbaF<F>::red16() const
+
+ Returns the red color component as a 16-bit integer.
+*/
+
+/*!
+ \fn template<typename F> quint16 QRgbaF<F>::green16() const
+
+ Returns the green color component as a 16-bit integer.
+*/
+
+/*!
+ \fn template<typename F> quint16 QRgbaF<F>::blue16() const
+
+ Returns the blue color component as a 16-bit integer.
+*/
+
+/*!
+ \fn template<typename F> quint16 QRgbaF<F>::alpha16() const
+
+ Returns the alpha channel as a 16-bit integer.
+*/
+
+/*!
+ \fn template<typename F> QRgbaF QRgbaF<F>::premultiplied() const
+
+ Returns the color with the alpha premultiplied.
+
+ \sa unpremultiplied()
+*/
+
+/*!
+ \fn template<typename F> QRgbaF QRgbaF<F>::unpremultiplied() const
+
+ Returns the color with the alpha unpremultiplied.
+
+ \sa premultiplied()
+*/
diff --git a/src/gui/platform/unix/qtx11extras_p.h b/src/gui/platform/unix/qtx11extras_p.h
index 85b26b1462..aed46a82b4 100644
--- a/src/gui/platform/unix/qtx11extras_p.h
+++ b/src/gui/platform/unix/qtx11extras_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <qtguiglobal.h>
+#include <QtGui/qtguiglobal.h>
#include <xcb/xcb.h>
diff --git a/src/gui/platform/unix/qunixnativeinterface.cpp b/src/gui/platform/unix/qunixnativeinterface.cpp
index 9fde98f76a..4febe69d91 100644
--- a/src/gui/platform/unix/qunixnativeinterface.cpp
+++ b/src/gui/platform/unix/qunixnativeinterface.cpp
@@ -185,6 +185,10 @@ QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QXcbWindow);
QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QVsp2Screen);
#endif
+#ifdef Q_OS_WEBOS
+QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QWebOSScreen);
+#endif
+
#if QT_CONFIG(evdev)
/*!
diff --git a/src/gui/platform/unix/qxkbcommon.cpp b/src/gui/platform/unix/qxkbcommon.cpp
index 3db84097c7..e4d93ceb55 100644
--- a/src/gui/platform/unix/qxkbcommon.cpp
+++ b/src/gui/platform/unix/qxkbcommon.cpp
@@ -545,13 +545,27 @@ static int keysymToQtKey_internal(xkb_keysym_t keysym, Qt::KeyboardModifiers mod
// numeric keypad keys
qtKey = Qt::Key_0 + (keysym - XKB_KEY_KP_0);
} else if (QXkbCommon::isLatin1(keysym)) {
+ // Upper-case first, since Qt::Keys are defined in terms of their
+ // upper-case versions.
qtKey = QXkbCommon::qxkbcommon_xkb_keysym_to_upper(keysym);
+ // Upper-casing a Latin1 character might move it out of Latin1 range,
+ // for example U+00B5 MICRO SIGN, which upper-case equivalent is
+ // U+039C GREEK CAPITAL LETTER MU. If that's the case, then map the
+ // original lower-case character.
+ if (!QXkbCommon::isLatin1(qtKey))
+ qtKey = keysym;
} else {
// check if we have a direct mapping
xkb2qt_t searchKey{keysym, 0};
auto it = std::lower_bound(KeyTbl.cbegin(), KeyTbl.cend(), searchKey);
if (it != KeyTbl.end() && !(searchKey < *it))
qtKey = it->qt;
+
+ // translate Super/Hyper keys to Meta if we're using them as the MetaModifier
+ if (superAsMeta && (qtKey == Qt::Key_Super_L || qtKey == Qt::Key_Super_R))
+ qtKey = Qt::Key_Meta;
+ if (hyperAsMeta && (qtKey == Qt::Key_Hyper_L || qtKey == Qt::Key_Hyper_R))
+ qtKey = Qt::Key_Meta;
}
if (qtKey)
@@ -578,12 +592,6 @@ static int keysymToQtKey_internal(xkb_keysym_t keysym, Qt::KeyboardModifiers mod
}
}
- // translate Super/Hyper keys to Meta if we're using them as the MetaModifier
- if (superAsMeta && (qtKey == Qt::Key_Super_L || qtKey == Qt::Key_Super_R))
- qtKey = Qt::Key_Meta;
- if (hyperAsMeta && (qtKey == Qt::Key_Hyper_L || qtKey == Qt::Key_Hyper_R))
- qtKey = Qt::Key_Meta;
-
return qtKey;
}
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp
index 8c24f11079..4ae75b5df5 100644
--- a/src/gui/rhi/qrhi.cpp
+++ b/src/gui/rhi/qrhi.cpp
@@ -642,6 +642,24 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
supported (which can happen when the underlying API is OpenGL ES 2.0 without
support for GL_UNPACK_ROW_LENGTH),
QRhiTextureSubresourceUploadDescription::setDataStride() must not be used.
+
+ \value RenderBufferImport Indicates that QRhiRenderBuffer::createFrom() is
+ supported. For most graphics APIs this is not sensible because
+ QRhiRenderBuffer encapsulates texture objects internally, just like
+ QRhiTexture. With OpenGL however, renderbuffer object exist as a separate
+ object type in the API, and in certain environments (for example, where one
+ may want to associated a renderbuffer object with an EGLImage object) it is
+ important to allow wrapping an existing OpenGL renderbuffer object with a
+ QRhiRenderBuffer.
+
+ \value ThreeDimensionalTextures Indicates that 3D textures are supported.
+ In practice this feature will be unsupported with OpenGL and OpenGL ES
+ versions lower than 3.0.
+
+ \value RenderTo3DTextureSlice Indicates that rendering to a slice in a 3D
+ texture is supported. This can be unsupported with Vulkan 1.0 due to
+ relying on VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT which is a Vulkan 1.1
+ feature.
*/
/*!
@@ -1348,12 +1366,6 @@ size_t qHash(const QRhiVertexInputLayout &v, size_t seed) noexcept
}
#ifndef QT_NO_DEBUG_STREAM
-template<typename T, qsizetype N>
-QDebug operator<<(QDebug dbg, const QVarLengthArray<T, N> &vla)
-{
- return QtPrivate::printSequentialContainer(dbg, "VLA", vla);
-}
-
QDebug operator<<(QDebug dbg, const QRhiVertexInputLayout &v)
{
QDebugStateSaver saver(dbg);
@@ -1468,9 +1480,10 @@ QDebug operator<<(QDebug dbg, const QRhiShaderStage &s)
support for multisample textures, but does support multisample
renderbuffers).
- When targeting a non-multisample texture, the layer() and level()
- indicate the targeted layer (face index \c{0-5} for cubemaps) and mip
- level.
+ When targeting a non-multisample texture, the layer() and level() indicate
+ the targeted layer (face index \c{0-5} for cubemaps) and mip level. For 3D
+ textures layer() specifies the slice (one 2D image within the 3D texture)
+ to render to.
When texture() or renderBuffer() is multisample, resolveTexture() can be
set optionally. When set, samples are resolved automatically into that
@@ -1806,6 +1819,13 @@ QRhiTextureUploadDescription::QRhiTextureUploadDescription(std::initializer_list
\note The source and destination rectangles defined by pixelSize(),
sourceTopLeft(), and destinationTopLeft() must fit the source and
destination textures, respectively. The behavior is undefined otherwise.
+
+ With cubemap and 3D textures one face or slice can be copied at a time. The
+ face or slice is specified by the source and destination layer indices.
+ With mipmapped textures one mip level can be copied at a time. The source
+ and destination layer and mip level indices can differ, but the size and
+ position must be carefully controlled to avoid out of bounds copies, in
+ which case the behavior is undefined.
*/
/*!
@@ -2306,6 +2326,44 @@ QRhiResource::Type QRhiRenderBuffer::resourceType() const
*/
/*!
+ Similar to create() except that no new native renderbuffer objects are
+ created. Instead, the native renderbuffer object specified by \a src is
+ used.
+
+ This allows importing an existing renderbuffer object (which must belong to
+ the same device or sharing context, depending on the graphics API) from an
+ external graphics engine.
+
+ \note This is currently applicable to OpenGL only. This function exists
+ solely to allow importing a renderbuffer object that is bound to some
+ special, external object, such as an EGLImageKHR. Once the application
+ performed the glEGLImageTargetRenderbufferStorageOES call, the renderbuffer
+ object can be passed to this function to create a wrapping
+ QRhiRenderBuffer, which in turn can be passed in as a color attachment to
+ a QRhiTextureRenderTarget to enable rendering to the EGLImage.
+
+ \note pixelSize(), sampleCount(), and flags() must still be set correctly.
+ Passing incorrect sizes and other values to QRhi::newRenderBuffer() and
+ then following it with a createFrom() expecting that the native
+ renderbuffer object alone is sufficient to deduce such values is \b wrong
+ and will lead to problems.
+
+ \note QRhiRenderBuffer does not take ownership of the native object, and
+ destroy() will not release that object.
+
+ \note This function is only implemented when the QRhi::RenderBufferImport
+ feature is reported as \l{QRhi::isFeatureSupported()}{supported}. Otherwise,
+ the function does nothing and the return value is \c false.
+
+ \return \c true when successful, \c false when not supported.
+ */
+bool QRhiRenderBuffer::createFrom(NativeRenderBuffer src)
+{
+ Q_UNUSED(src);
+ return false;
+}
+
+/*!
\fn QRhiTexture::Format QRhiRenderBuffer::backingFormat() const
\internal
@@ -2358,6 +2416,14 @@ QRhiResource::Type QRhiRenderBuffer::resourceType() const
\value ExternalOES The texture should use the GL_TEXTURE_EXTERNAL_OES
target with OpenGL. This flag is ignored with other graphics APIs.
+
+ \value ThreeDimensional The texture is a 3D texture. Such textures should
+ be created with the QRhi::newTexture() overload taking a depth in addition
+ to width and height. A 3D texture can have mipmaps but cannot be
+ multisample. When rendering into a 3D texture, the layer specified in the
+ render target's color attachment refers to a slice in range [0..depth-1].
+ The underlying graphics API may not support 3D textures at run time.
+ Support is indicated by the QRhi::ThreeDimensionalTextures feature.
*/
/*!
@@ -2448,10 +2514,10 @@ QRhiResource::Type QRhiRenderBuffer::resourceType() const
/*!
\internal
*/
-QRhiTexture::QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_,
+QRhiTexture::QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_, int depth_,
int sampleCount_, Flags flags_)
: QRhiResource(rhi),
- m_format(format_), m_pixelSize(pixelSize_), m_sampleCount(sampleCount_), m_flags(flags_)
+ m_format(format_), m_pixelSize(pixelSize_), m_depth(depth_), m_sampleCount(sampleCount_), m_flags(flags_)
{
}
@@ -4578,7 +4644,7 @@ void QRhiImplementation::textureFormatInfo(QRhiTexture::Format format, const QSi
}
// Approximate because it excludes subresource alignment or multisampling.
-quint32 QRhiImplementation::approxByteSizeForTexture(QRhiTexture::Format format, const QSize &baseSize,
+quint32 QRhiImplementation::approxByteSizeForTexture(QRhiTexture::Format format, const QSize &baseSize, int depth,
int mipCount, int layerCount)
{
quint32 approxSize = 0;
@@ -4589,7 +4655,8 @@ quint32 QRhiImplementation::approxByteSizeForTexture(QRhiTexture::Format format,
textureFormatInfo(format, size, nullptr, &byteSize, nullptr);
approxSize += byteSize;
}
- approxSize *= uint(layerCount);
+ approxSize *= depth; // 3D texture depth or 1 otherwise
+ approxSize *= uint(layerCount); // 6 for cubemaps or 1 otherwise
return approxSize;
}
@@ -5266,6 +5333,10 @@ void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, co
N is the \l{QRhi::resourceLimit()}{resource limit value} returned for
QRhi::MaxAsyncReadbackFrames.
+ A single readback operation copies one mip level of one layer (cubemap face
+ or 3D slice) at a time. The level and layer are specified by the respective
+ fields in \a rb.
+
\sa readBackBuffer(), QRhi::resourceLimit()
*/
void QRhiResourceUpdateBatch::readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
@@ -6330,7 +6401,30 @@ QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
int sampleCount,
QRhiTexture::Flags flags)
{
- return d->createTexture(format, pixelSize, sampleCount, flags);
+ return d->createTexture(format, pixelSize, 1, sampleCount, flags);
+}
+
+/*!
+ \return a new texture with the specified \a format, \a width, \a height, \a
+ depth, \a sampleCount, and \a flags.
+
+ This overload is suitable for 3D textures because it allows specifying \a
+ depth. A 3D texture must have QRhiTexture::ThreeDimensional set in \a
+ flags, but using this overload that can be omitted because the flag is set
+ implicitly whenever \a depth is greater than 0. For 2D and cube textures \a
+ depth should be set to 0.
+
+ \overload
+ */
+QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
+ int width, int height, int depth,
+ int sampleCount,
+ QRhiTexture::Flags flags)
+{
+ if (depth > 0)
+ flags |= QRhiTexture::ThreeDimensional;
+
+ return d->createTexture(format, QSize(width, height), depth, sampleCount, flags);
}
/*!
diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h
index b43d490ea9..c2a09b7edf 100644
--- a/src/gui/rhi/qrhi_p.h
+++ b/src/gui/rhi/qrhi_p.h
@@ -753,7 +753,8 @@ public:
UsedWithGenerateMips = 1 << 6,
UsedWithLoadStore = 1 << 7,
UsedAsCompressedAtlas = 1 << 8,
- ExternalOES = 1 << 9
+ ExternalOES = 1 << 9,
+ ThreeDimensional = 1 << 10
};
Q_DECLARE_FLAGS(Flags, Flag)
@@ -819,6 +820,9 @@ public:
QSize pixelSize() const { return m_pixelSize; }
void setPixelSize(const QSize &sz) { m_pixelSize = sz; }
+ int depth() const { return m_depth; }
+ void setDepth(int depth) { m_depth = depth; }
+
Flags flags() const { return m_flags; }
void setFlags(Flags f) { m_flags = f; }
@@ -831,10 +835,11 @@ public:
virtual void setNativeLayout(int layout);
protected:
- QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_,
+ QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_, int depth_,
int sampleCount_, Flags flags_);
Format m_format;
QSize m_pixelSize;
+ int m_depth;
int m_sampleCount;
Flags m_flags;
};
@@ -918,6 +923,10 @@ public:
};
Q_DECLARE_FLAGS(Flags, Flag)
+ struct NativeRenderBuffer {
+ quint64 object;
+ };
+
QRhiResource::Type resourceType() const override;
Type type() const { return m_type; }
@@ -933,6 +942,7 @@ public:
void setFlags(Flags h) { m_flags = h; }
virtual bool create() = 0;
+ virtual bool createFrom(NativeRenderBuffer src);
virtual QRhiTexture::Format backingFormat() const = 0;
@@ -1534,7 +1544,10 @@ public:
ScreenSpaceDerivatives,
ReadBackAnyTextureFormat,
PipelineCacheDataLoadSave,
- ImageDataStride
+ ImageDataStride,
+ RenderBufferImport,
+ ThreeDimensionalTextures,
+ RenderTo3DTextureSlice
};
enum BeginFrameFlag {
@@ -1594,6 +1607,11 @@ public:
int sampleCount = 1,
QRhiTexture::Flags flags = {});
+ QRhiTexture *newTexture(QRhiTexture::Format format,
+ int width, int height, int depth,
+ int sampleCount = 1,
+ QRhiTexture::Flags flags = {});
+
QRhiSampler *newSampler(QRhiSampler::Filter magFilter,
QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
@@ -1640,8 +1658,7 @@ public:
QRhiProfiler *profiler();
- static const int MAX_LAYERS = 6; // cubemaps only
- static const int MAX_LEVELS = 16; // a width and/or height of 65536 should be enough for everyone
+ static const int MAX_MIP_LEVELS = 16; // a width and/or height of 65536 should be enough for everyone
void releaseCachedResources();
diff --git a/src/gui/rhi/qrhi_p_p.h b/src/gui/rhi/qrhi_p_p.h
index f33626ae1d..89dd7b8e44 100644
--- a/src/gui/rhi/qrhi_p_p.h
+++ b/src/gui/rhi/qrhi_p_p.h
@@ -87,6 +87,7 @@ public:
QRhiTexture::Format backingFormatHint) = 0;
virtual QRhiTexture *createTexture(QRhiTexture::Format format,
const QSize &pixelSize,
+ int depth,
int sampleCount,
QRhiTexture::Flags flags) = 0;
virtual QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
@@ -180,7 +181,7 @@ public:
QSize *blockDim) const;
void textureFormatInfo(QRhiTexture::Format format, const QSize &size,
quint32 *bpl, quint32 *byteSize, quint32 *bytesPerPixel) const;
- quint32 approxByteSizeForTexture(QRhiTexture::Format format, const QSize &baseSize,
+ quint32 approxByteSizeForTexture(QRhiTexture::Format format, const QSize &baseSize, int depth,
int mipCount, int layerCount);
QRhiProfilerPrivate *profilerPrivateOrNull()
@@ -447,7 +448,8 @@ public:
// In the backend this can then end up, where applicable, as a
// single, batched copy operation with only one set of barriers.
// This helps when doing for example glyph cache fills.
- QList<QRhiTextureSubresourceUploadDescription> subresDesc[QRhi::MAX_LAYERS][QRhi::MAX_LEVELS];
+ using MipLevelUploadList = std::array<QVector<QRhiTextureSubresourceUploadDescription>, QRhi::MAX_MIP_LEVELS>;
+ QVarLengthArray<MipLevelUploadList, 6> subresDesc;
QRhiTexture *src;
QRhiTextureCopyDescription desc;
QRhiReadbackDescription rb;
@@ -458,6 +460,12 @@ public:
TextureOp op = {};
op.type = Upload;
op.dst = tex;
+ int maxLayer = -1;
+ for (auto it = desc.cbeginEntries(), itEnd = desc.cendEntries(); it != itEnd; ++it) {
+ if (it->layer() > maxLayer)
+ maxLayer = it->layer();
+ }
+ op.subresDesc.resize(maxLayer + 1);
for (auto it = desc.cbeginEntries(), itEnd = desc.cendEntries(); it != itEnd; ++it)
op.subresDesc[it->layer()][it->level()].append(it->description());
return op;
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index 46851ad612..6b4be76fef 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -544,6 +544,12 @@ bool QRhiD3D11::isFeatureSupported(QRhi::Feature feature) const
return false;
case QRhi::ImageDataStride:
return true;
+ case QRhi::RenderBufferImport:
+ return false;
+ case QRhi::ThreeDimensionalTextures:
+ return true;
+ case QRhi::RenderTo3DTextureSlice:
+ return true;
default:
Q_UNREACHABLE();
return false;
@@ -631,10 +637,11 @@ QRhiRenderBuffer *QRhiD3D11::createRenderBuffer(QRhiRenderBuffer::Type type, con
return new QD3D11RenderBuffer(this, type, pixelSize, sampleCount, flags, backingFormatHint);
}
-QRhiTexture *QRhiD3D11::createTexture(QRhiTexture::Format format, const QSize &pixelSize,
+QRhiTexture *QRhiD3D11::createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize, int depth,
int sampleCount, QRhiTexture::Flags flags)
{
- return new QD3D11Texture(this, format, pixelSize, sampleCount, flags);
+ return new QD3D11Texture(this, format, pixelSize, depth, sampleCount, flags);
}
QRhiSampler *QRhiD3D11::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
@@ -1349,17 +1356,18 @@ QRhi::FrameOpResult QRhiD3D11::finish()
void QRhiD3D11::enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD,
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc)
{
- UINT subres = D3D11CalcSubresource(UINT(level), UINT(layer), texD->mipLevelCount);
- const QPoint dp = subresDesc.destinationTopLeft();
+ const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
+ UINT subres = D3D11CalcSubresource(UINT(level), is3D ? 0u : UINT(layer), texD->mipLevelCount);
D3D11_BOX box;
- box.front = 0;
+ box.front = is3D ? UINT(layer) : 0u;
// back, right, bottom are exclusive
- box.back = 1;
+ box.back = box.front + 1;
QD3D11CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QD3D11CommandBuffer::Command::UpdateSubRes;
- cmd.args.updateSubRes.dst = texD->tex;
+ cmd.args.updateSubRes.dst = texD->textureResource();
cmd.args.updateSubRes.dstSubRes = subres;
+ const QPoint dp = subresDesc.destinationTopLeft();
if (!subresDesc.image().isNull()) {
QImage img = subresDesc.image();
QSize size = img.size();
@@ -1486,6 +1494,7 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
cmd.args.copySubRes.dstSubRes = 0;
cmd.args.copySubRes.dstX = 0;
cmd.args.copySubRes.dstY = 0;
+ cmd.args.copySubRes.dstZ = 0;
cmd.args.copySubRes.src = bufD->buffer;
cmd.args.copySubRes.srcSubRes = 0;
cmd.args.copySubRes.hasSrcBox = true;
@@ -1506,8 +1515,8 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
const QRhiResourceUpdateBatchPrivate::TextureOp &u(ud->textureOps[opIdx]);
if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Upload) {
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, u.dst);
- for (int layer = 0; layer < QRhi::MAX_LAYERS; ++layer) {
- for (int level = 0; level < QRhi::MAX_LEVELS; ++level) {
+ for (int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
+ for (int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(u.subresDesc[layer][level]))
enqueueSubresUpload(texD, cbD, layer, level, subresDesc);
}
@@ -1516,8 +1525,10 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
Q_ASSERT(u.src && u.dst);
QD3D11Texture *srcD = QRHI_RES(QD3D11Texture, u.src);
QD3D11Texture *dstD = QRHI_RES(QD3D11Texture, u.dst);
- UINT srcSubRes = D3D11CalcSubresource(UINT(u.desc.sourceLevel()), UINT(u.desc.sourceLayer()), srcD->mipLevelCount);
- UINT dstSubRes = D3D11CalcSubresource(UINT(u.desc.destinationLevel()), UINT(u.desc.destinationLayer()), dstD->mipLevelCount);
+ const bool srcIs3D = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
+ const bool dstIs3D = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
+ UINT srcSubRes = D3D11CalcSubresource(UINT(u.desc.sourceLevel()), srcIs3D ? 0u : UINT(u.desc.sourceLayer()), srcD->mipLevelCount);
+ UINT dstSubRes = D3D11CalcSubresource(UINT(u.desc.destinationLevel()), dstIs3D ? 0u : UINT(u.desc.destinationLayer()), dstD->mipLevelCount);
const QPoint dp = u.desc.destinationTopLeft();
const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
@@ -1525,18 +1536,19 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
D3D11_BOX srcBox;
srcBox.left = UINT(sp.x());
srcBox.top = UINT(sp.y());
- srcBox.front = 0;
+ srcBox.front = srcIs3D ? UINT(u.desc.sourceLayer()) : 0u;
// back, right, bottom are exclusive
srcBox.right = srcBox.left + UINT(copySize.width());
srcBox.bottom = srcBox.top + UINT(copySize.height());
- srcBox.back = 1;
+ srcBox.back = srcBox.front + 1;
QD3D11CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QD3D11CommandBuffer::Command::CopySubRes;
- cmd.args.copySubRes.dst = dstD->tex;
+ cmd.args.copySubRes.dst = dstD->textureResource();
cmd.args.copySubRes.dstSubRes = dstSubRes;
cmd.args.copySubRes.dstX = UINT(dp.x());
cmd.args.copySubRes.dstY = UINT(dp.y());
- cmd.args.copySubRes.src = srcD->tex;
+ cmd.args.copySubRes.dstZ = dstIs3D ? UINT(u.desc.destinationLayer()) : 0u;
+ cmd.args.copySubRes.src = srcD->textureResource();
cmd.args.copySubRes.srcSubRes = srcSubRes;
cmd.args.copySubRes.hasSrcBox = true;
cmd.args.copySubRes.srcBox = srcBox;
@@ -1552,17 +1564,19 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
UINT subres = 0;
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, u.rb.texture());
QD3D11SwapChain *swapChainD = nullptr;
+ bool is3D = false;
if (texD) {
if (texD->sampleDesc.Count > 1) {
qWarning("Multisample texture cannot be read back");
continue;
}
- src = texD->tex;
+ src = texD->textureResource();
dxgiFormat = texD->dxgiFormat;
pixelSize = q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize);
format = texD->m_format;
- subres = D3D11CalcSubresource(UINT(u.rb.level()), UINT(u.rb.layer()), texD->mipLevelCount);
+ is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
+ subres = D3D11CalcSubresource(UINT(u.rb.level()), UINT(is3D ? 0 : u.rb.layer()), texD->mipLevelCount);
} else {
Q_ASSERT(contextState.currentSwapChain);
swapChainD = QRHI_RES(QD3D11SwapChain, contextState.currentSwapChain);
@@ -1614,9 +1628,21 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
cmd.args.copySubRes.dstSubRes = 0;
cmd.args.copySubRes.dstX = 0;
cmd.args.copySubRes.dstY = 0;
+ cmd.args.copySubRes.dstZ = 0;
cmd.args.copySubRes.src = src;
cmd.args.copySubRes.srcSubRes = subres;
- cmd.args.copySubRes.hasSrcBox = false;
+ if (is3D) {
+ D3D11_BOX srcBox;
+ memset(&srcBox, 0, sizeof(srcBox));
+ srcBox.front = UINT(u.rb.layer());
+ srcBox.right = desc.Width; // exclusive
+ srcBox.bottom = desc.Height;
+ srcBox.back = srcBox.front + 1;
+ cmd.args.copySubRes.hasSrcBox = true;
+ cmd.args.copySubRes.srcBox = srcBox;
+ } else {
+ cmd.args.copySubRes.hasSrcBox = false;
+ }
readback.stagingTex = stagingTex;
readback.byteSize = byteSize;
@@ -1789,12 +1815,12 @@ void QRhiD3D11::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource
Q_ASSERT(srcTexD || srcRbD);
QD3D11CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QD3D11CommandBuffer::Command::ResolveSubRes;
- cmd.args.resolveSubRes.dst = dstTexD->tex;
+ cmd.args.resolveSubRes.dst = dstTexD->textureResource();
cmd.args.resolveSubRes.dstSubRes = D3D11CalcSubresource(UINT(colorAtt.resolveLevel()),
UINT(colorAtt.resolveLayer()),
dstTexD->mipLevelCount);
if (srcTexD) {
- cmd.args.resolveSubRes.src = srcTexD->tex;
+ cmd.args.resolveSubRes.src = srcTexD->textureResource();
if (srcTexD->dxgiFormat != dstTexD->dxgiFormat) {
qWarning("Resolve source (%d) and destination (%d) formats do not match",
int(srcTexD->dxgiFormat), int(dstTexD->dxgiFormat));
@@ -2529,7 +2555,7 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
context->VSSetShader(psD->vs.shader, nullptr, 0);
context->PSSetShader(psD->fs.shader, nullptr, 0);
context->IASetPrimitiveTopology(psD->d3dTopology);
- context->IASetInputLayout(psD->inputLayout);
+ context->IASetInputLayout(psD->inputLayout); // may be null, that's ok
context->OMSetDepthStencilState(psD->dsState, stencilRef);
context->OMSetBlendState(psD->blendState, blendConstants, 0xffffffff);
context->RSSetState(psD->rastState);
@@ -2580,7 +2606,7 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
break;
case QD3D11CommandBuffer::Command::CopySubRes:
context->CopySubresourceRegion(cmd.args.copySubRes.dst, cmd.args.copySubRes.dstSubRes,
- cmd.args.copySubRes.dstX, cmd.args.copySubRes.dstY, 0,
+ cmd.args.copySubRes.dstX, cmd.args.copySubRes.dstY, cmd.args.copySubRes.dstZ,
cmd.args.copySubRes.src, cmd.args.copySubRes.srcSubRes,
cmd.args.copySubRes.hasSrcBox ? &cmd.args.copySubRes.srcBox : nullptr);
break;
@@ -2883,11 +2909,11 @@ QRhiTexture::Format QD3D11RenderBuffer::backingFormat() const
return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
}
-QD3D11Texture::QD3D11Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+QD3D11Texture::QD3D11Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
int sampleCount, Flags flags)
- : QRhiTexture(rhi, format, pixelSize, sampleCount, flags)
+ : QRhiTexture(rhi, format, pixelSize, depth, sampleCount, flags)
{
- for (int i = 0; i < QRhi::MAX_LEVELS; ++i)
+ for (int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i)
perLevelViews[i] = nullptr;
}
@@ -2898,7 +2924,7 @@ QD3D11Texture::~QD3D11Texture()
void QD3D11Texture::destroy()
{
- if (!tex)
+ if (!tex && !tex3D)
return;
if (srv) {
@@ -2906,17 +2932,22 @@ void QD3D11Texture::destroy()
srv = nullptr;
}
- for (int i = 0; i < QRhi::MAX_LEVELS; ++i) {
+ for (int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i) {
if (perLevelViews[i]) {
perLevelViews[i]->Release();
perLevelViews[i] = nullptr;
}
}
- if (owns)
- tex->Release();
+ if (owns) {
+ if (tex)
+ tex->Release();
+ if (tex3D)
+ tex3D->Release();
+ }
tex = nullptr;
+ tex3D = nullptr;
QRHI_RES_RHI(QRhiD3D11);
QRHI_PROF;
@@ -2960,12 +2991,13 @@ static inline DXGI_FORMAT toD3DDepthTextureDSVFormat(QRhiTexture::Format format)
bool QD3D11Texture::prepareCreate(QSize *adjustedSize)
{
- if (tex)
+ if (tex || tex3D)
destroy();
const QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
const bool isDepth = isDepthTextureFormat(m_format);
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool is3D = m_flags.testFlag(ThreeDimensional);
const bool hasMipMaps = m_flags.testFlag(MipMapped);
QRHI_RES_RHI(QRhiD3D11);
@@ -2977,6 +3009,10 @@ bool QD3D11Texture::prepareCreate(QSize *adjustedSize)
qWarning("Cubemap texture cannot be multisample");
return false;
}
+ if (is3D) {
+ qWarning("3D texture cannot be multisample");
+ return false;
+ }
if (hasMipMaps) {
qWarning("Multisample texture cannot have mipmaps");
return false;
@@ -2986,6 +3022,15 @@ bool QD3D11Texture::prepareCreate(QSize *adjustedSize)
qWarning("Depth texture cannot have mipmaps");
return false;
}
+ if (isCube && is3D) {
+ qWarning("Texture cannot be both cube and 3D");
+ return false;
+ }
+ m_depth = qMax(1, m_depth);
+ if (m_depth > 1 && !is3D) {
+ qWarning("Texture cannot have a depth of %d when it is not 3D", m_depth);
+ return false;
+ }
if (adjustedSize)
*adjustedSize = size;
@@ -2998,6 +3043,7 @@ bool QD3D11Texture::finishCreate()
QRHI_RES_RHI(QRhiD3D11);
const bool isDepth = isDepthTextureFormat(m_format);
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool is3D = m_flags.testFlag(ThreeDimensional);
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
memset(&srvDesc, 0, sizeof(srvDesc));
@@ -3008,13 +3054,16 @@ bool QD3D11Texture::finishCreate()
} else {
if (sampleDesc.Count > 1) {
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
+ } else if (is3D) {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
+ srvDesc.Texture3D.MipLevels = mipLevelCount;
} else {
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = mipLevelCount;
}
}
- HRESULT hr = rhiD->dev->CreateShaderResourceView(tex, &srvDesc, &srv);
+ HRESULT hr = rhiD->dev->CreateShaderResourceView(textureResource(), &srvDesc, &srv);
if (FAILED(hr)) {
qWarning("Failed to create srv: %s", qPrintable(comErrorMessage(hr)));
return false;
@@ -3032,6 +3081,7 @@ bool QD3D11Texture::create()
const bool isDepth = isDepthTextureFormat(m_format);
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool is3D = m_flags.testFlag(ThreeDimensional);
uint bindFlags = D3D11_BIND_SHADER_RESOURCE;
uint miscFlags = isCube ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
@@ -3052,31 +3102,51 @@ bool QD3D11Texture::create()
if (m_flags.testFlag(UsedWithLoadStore))
bindFlags |= D3D11_BIND_UNORDERED_ACCESS;
- D3D11_TEXTURE2D_DESC desc;
- memset(&desc, 0, sizeof(desc));
- desc.Width = UINT(size.width());
- desc.Height = UINT(size.height());
- desc.MipLevels = mipLevelCount;
- desc.ArraySize = isCube ? 6 : 1;
- desc.Format = dxgiFormat;
- desc.SampleDesc = sampleDesc;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = bindFlags;
- desc.MiscFlags = miscFlags;
-
QRHI_RES_RHI(QRhiD3D11);
- HRESULT hr = rhiD->dev->CreateTexture2D(&desc, nullptr, &tex);
- if (FAILED(hr)) {
- qWarning("Failed to create texture: %s", qPrintable(comErrorMessage(hr)));
- return false;
+ if (!is3D) {
+ D3D11_TEXTURE2D_DESC desc;
+ memset(&desc, 0, sizeof(desc));
+ desc.Width = UINT(size.width());
+ desc.Height = UINT(size.height());
+ desc.MipLevels = mipLevelCount;
+ desc.ArraySize = isCube ? 6 : 1;
+ desc.Format = dxgiFormat;
+ desc.SampleDesc = sampleDesc;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = bindFlags;
+ desc.MiscFlags = miscFlags;
+
+ HRESULT hr = rhiD->dev->CreateTexture2D(&desc, nullptr, &tex);
+ if (FAILED(hr)) {
+ qWarning("Failed to create 2D texture: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ if (!m_objectName.isEmpty())
+ tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
+ } else {
+ D3D11_TEXTURE3D_DESC desc;
+ memset(&desc, 0, sizeof(desc));
+ desc.Width = UINT(size.width());
+ desc.Height = UINT(size.height());
+ desc.Depth = UINT(m_depth);
+ desc.MipLevels = mipLevelCount;
+ desc.Format = dxgiFormat;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = bindFlags;
+ desc.MiscFlags = miscFlags;
+
+ HRESULT hr = rhiD->dev->CreateTexture3D(&desc, nullptr, &tex3D);
+ if (FAILED(hr)) {
+ qWarning("Failed to create 3D texture: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ if (!m_objectName.isEmpty())
+ tex3D->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
}
if (!finishCreate())
return false;
- if (!m_objectName.isEmpty())
- tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
-
QRHI_PROF;
QRHI_PROF_F(newTexture(this, true, int(mipLevelCount), isCube ? 6 : 1, int(sampleDesc.Count)));
@@ -3087,14 +3157,16 @@ bool QD3D11Texture::create()
bool QD3D11Texture::createFrom(QRhiTexture::NativeTexture src)
{
- ID3D11Texture2D *srcTex = reinterpret_cast<ID3D11Texture2D *>(src.object);
- if (srcTex == nullptr)
+ if (!src.object)
return false;
if (!prepareCreate())
return false;
- tex = srcTex;
+ if (m_flags.testFlag(ThreeDimensional))
+ tex3D = reinterpret_cast<ID3D11Texture3D *>(src.object);
+ else
+ tex = reinterpret_cast<ID3D11Texture2D *>(src.object);
if (!finishCreate())
return false;
@@ -3110,7 +3182,7 @@ bool QD3D11Texture::createFrom(QRhiTexture::NativeTexture src)
QRhiTexture::NativeTexture QD3D11Texture::nativeTexture()
{
- return {quint64(tex), 0};
+ return { quint64(textureResource()), 0 };
}
ID3D11UnorderedAccessView *QD3D11Texture::unorderedAccessViewForLevel(int level)
@@ -3119,6 +3191,7 @@ ID3D11UnorderedAccessView *QD3D11Texture::unorderedAccessViewForLevel(int level)
return perLevelViews[level];
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool is3D = m_flags.testFlag(ThreeDimensional);
D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
memset(&desc, 0, sizeof(desc));
desc.Format = dxgiFormat;
@@ -3127,6 +3200,9 @@ ID3D11UnorderedAccessView *QD3D11Texture::unorderedAccessViewForLevel(int level)
desc.Texture2DArray.MipSlice = UINT(level);
desc.Texture2DArray.FirstArraySlice = 0;
desc.Texture2DArray.ArraySize = 6;
+ } else if (is3D) {
+ desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
+ desc.Texture3D.MipSlice = UINT(level);
} else {
desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
desc.Texture2D.MipSlice = UINT(level);
@@ -3134,7 +3210,7 @@ ID3D11UnorderedAccessView *QD3D11Texture::unorderedAccessViewForLevel(int level)
QRHI_RES_RHI(QRhiD3D11);
ID3D11UnorderedAccessView *uav = nullptr;
- HRESULT hr = rhiD->dev->CreateUnorderedAccessView(tex, &desc, &uav);
+ HRESULT hr = rhiD->dev->CreateUnorderedAccessView(textureResource(), &desc, &uav);
if (FAILED(hr)) {
qWarning("Failed to create UAV: %s", qPrintable(comErrorMessage(hr)));
return nullptr;
@@ -3402,6 +3478,11 @@ bool QD3D11TextureRenderTarget::create()
rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
rtvDesc.Texture2DArray.ArraySize = 1;
+ } else if (texD->flags().testFlag(QRhiTexture::ThreeDimensional)) {
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
+ rtvDesc.Texture3D.MipSlice = UINT(colorAtt.level());
+ rtvDesc.Texture3D.FirstWSlice = UINT(colorAtt.layer());
+ rtvDesc.Texture3D.WSize = 1;
} else {
if (texD->sampleDesc.Count > 1) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
@@ -3410,7 +3491,7 @@ bool QD3D11TextureRenderTarget::create()
rtvDesc.Texture2D.MipSlice = UINT(colorAtt.level());
}
}
- HRESULT hr = rhiD->dev->CreateRenderTargetView(texD->tex, &rtvDesc, &rtv[attIndex]);
+ HRESULT hr = rhiD->dev->CreateRenderTargetView(texD->textureResource(), &rtvDesc, &rtv[attIndex]);
if (FAILED(hr)) {
qWarning("Failed to create rtv: %s", qPrintable(comErrorMessage(hr)));
return false;
@@ -4068,12 +4149,14 @@ bool QD3D11GraphicsPipeline::create()
}
inputDescs.append(desc);
}
- hr = rhiD->dev->CreateInputLayout(inputDescs.constData(), UINT(inputDescs.count()),
- vsByteCode, SIZE_T(vsByteCode.size()), &inputLayout);
- if (FAILED(hr)) {
- qWarning("Failed to create input layout: %s", qPrintable(comErrorMessage(hr)));
- return false;
- }
+ if (!inputDescs.isEmpty()) {
+ hr = rhiD->dev->CreateInputLayout(inputDescs.constData(), UINT(inputDescs.count()),
+ vsByteCode, SIZE_T(vsByteCode.size()), &inputLayout);
+ if (FAILED(hr)) {
+ qWarning("Failed to create input layout: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ } // else leave inputLayout set to nullptr; that's valid and it avoids a debug layer warning about an input layout with 0 elements
}
generation += 1;
diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h
index 82cbe5114c..0695259612 100644
--- a/src/gui/rhi/qrhid3d11_p_p.h
+++ b/src/gui/rhi/qrhid3d11_p_p.h
@@ -101,7 +101,7 @@ struct QD3D11RenderBuffer : public QRhiRenderBuffer
struct QD3D11Texture : public QRhiTexture
{
- QD3D11Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+ QD3D11Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
int sampleCount, Flags flags);
~QD3D11Texture();
void destroy() override;
@@ -112,14 +112,21 @@ struct QD3D11Texture : public QRhiTexture
bool prepareCreate(QSize *adjustedSize = nullptr);
bool finishCreate();
ID3D11UnorderedAccessView *unorderedAccessViewForLevel(int level);
+ ID3D11Resource *textureResource() const
+ {
+ if (tex)
+ return tex;
+ return tex3D;
+ }
ID3D11Texture2D *tex = nullptr;
+ ID3D11Texture3D *tex3D = nullptr;
bool owns = true;
ID3D11ShaderResourceView *srv = nullptr;
DXGI_FORMAT dxgiFormat;
uint mipLevelCount = 0;
DXGI_SAMPLE_DESC sampleDesc;
- ID3D11UnorderedAccessView *perLevelViews[QRhi::MAX_LEVELS];
+ ID3D11UnorderedAccessView *perLevelViews[QRhi::MAX_MIP_LEVELS];
uint generation = 0;
friend class QRhiD3D11;
};
@@ -439,6 +446,7 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
UINT dstSubRes;
UINT dstX;
UINT dstY;
+ UINT dstZ;
ID3D11Resource *src;
UINT srcSubRes;
bool hasSrcBox;
@@ -596,6 +604,7 @@ public:
QRhiTexture::Format backingFormatHint) override;
QRhiTexture *createTexture(QRhiTexture::Format format,
const QSize &pixelSize,
+ int depth,
int sampleCount,
QRhiTexture::Flags flags) override;
QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp
index 43569d3752..05465e40cc 100644
--- a/src/gui/rhi/qrhigles2.cpp
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -348,6 +348,14 @@ QT_BEGIN_NAMESPACE
#define GL_UNPACK_ROW_LENGTH 0x0CF2
#endif
+#ifndef GL_TEXTURE_3D
+#define GL_TEXTURE_3D 0x806F
+#endif
+
+#ifndef GL_TEXTURE_WRAP_R
+#define GL_TEXTURE_WRAP_R 0x8072
+#endif
+
/*!
Constructs a new QRhiGles2InitParams.
@@ -621,6 +629,8 @@ bool QRhiGles2::create(QRhi::Flags flags)
caps.programBinary = false;
}
+ caps.texture3D = caps.ctxMajor >= 3; // 3.0
+
if (!caps.gles) {
f->glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
f->glEnable(GL_POINT_SPRITE);
@@ -1011,6 +1021,12 @@ bool QRhiGles2::isFeatureSupported(QRhi::Feature feature) const
return caps.programBinary;
case QRhi::ImageDataStride:
return !caps.gles || caps.ctxMajor >= 3;
+ case QRhi::RenderBufferImport:
+ return true;
+ case QRhi::ThreeDimensionalTextures:
+ return caps.texture3D;
+ case QRhi::RenderTo3DTextureSlice:
+ return caps.texture3D;
default:
Q_UNREACHABLE();
return false;
@@ -1227,10 +1243,11 @@ QRhiRenderBuffer *QRhiGles2::createRenderBuffer(QRhiRenderBuffer::Type type, con
return new QGles2RenderBuffer(this, type, pixelSize, sampleCount, flags, backingFormatHint);
}
-QRhiTexture *QRhiGles2::createTexture(QRhiTexture::Format format, const QSize &pixelSize,
+QRhiTexture *QRhiGles2::createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize, int depth,
int sampleCount, QRhiTexture::Flags flags)
{
- return new QGles2Texture(this, format, pixelSize, sampleCount, flags);
+ return new QGles2Texture(this, format, pixelSize, depth, sampleCount, flags);
}
QRhiSampler *QRhiGles2::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
@@ -1810,6 +1827,7 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
cmd.args.subImage.level = level;
cmd.args.subImage.dx = dp.x();
cmd.args.subImage.dy = dp.y();
+ cmd.args.subImage.dz = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional) ? layer : 0;
cmd.args.subImage.w = size.width();
cmd.args.subImage.h = size.height();
cmd.args.subImage.glformat = texD->glformat;
@@ -1818,10 +1836,19 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
cmd.args.subImage.rowLength = 0;
cmd.args.subImage.data = cbD->retainImage(img);
} else if (!rawData.isEmpty() && isCompressed) {
- if (!texD->compressedAtlasBuilt && (texD->flags() & QRhiTexture::UsedAsCompressedAtlas)) {
- // Create on first upload since glCompressedTexImage2D cannot take nullptr data
+ const bool is3D = texD->flags().testFlag(QRhiTexture::ThreeDimensional);
+ if ((texD->flags().testFlag(QRhiTexture::UsedAsCompressedAtlas) || is3D)
+ && !texD->zeroInitialized)
+ {
+ // Create on first upload since glCompressedTexImage2D cannot take
+ // nullptr data. We have a rule in the QRhi docs that the first
+ // upload for a compressed texture must cover the entire image, but
+ // that is clearly not ideal when building a texture atlas, or when
+ // having a 3D texture with per-slice data.
quint32 byteSize = 0;
compressedFormatInfo(texD->m_format, texD->m_pixelSize, nullptr, &byteSize, nullptr);
+ if (is3D)
+ byteSize *= texD->m_depth;
QByteArray zeroBuf(byteSize, 0);
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QGles2CommandBuffer::Command::CompressedImage;
@@ -1832,14 +1859,15 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
cmd.args.compressedImage.glintformat = texD->glintformat;
cmd.args.compressedImage.w = texD->m_pixelSize.width();
cmd.args.compressedImage.h = texD->m_pixelSize.height();
+ cmd.args.compressedImage.depth = is3D ? texD->m_depth : 0;
cmd.args.compressedImage.size = byteSize;
cmd.args.compressedImage.data = cbD->retainData(zeroBuf);
- texD->compressedAtlasBuilt = true;
+ texD->zeroInitialized = true;
}
const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
: subresDesc.sourceSize();
- if (texD->specified || texD->compressedAtlasBuilt) {
+ if (texD->specified || texD->zeroInitialized) {
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QGles2CommandBuffer::Command::CompressedSubImage;
cmd.args.compressedSubImage.target = texD->target;
@@ -1848,6 +1876,7 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
cmd.args.compressedSubImage.level = level;
cmd.args.compressedSubImage.dx = dp.x();
cmd.args.compressedSubImage.dy = dp.y();
+ cmd.args.compressedSubImage.dz = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional) ? layer : 0;
cmd.args.compressedSubImage.w = size.width();
cmd.args.compressedSubImage.h = size.height();
cmd.args.compressedSubImage.glintformat = texD->glintformat;
@@ -1863,6 +1892,7 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
cmd.args.compressedImage.glintformat = texD->glintformat;
cmd.args.compressedImage.w = size.width();
cmd.args.compressedImage.h = size.height();
+ cmd.args.compressedImage.depth = is3D ? texD->m_depth : 0;
cmd.args.compressedImage.size = rawData.size();
cmd.args.compressedImage.data = cbD->retainData(rawData);
}
@@ -1880,6 +1910,7 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
cmd.args.subImage.level = level;
cmd.args.subImage.dx = dp.x();
cmd.args.subImage.dy = dp.y();
+ cmd.args.subImage.dz = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional) ? layer : 0;
cmd.args.subImage.w = size.width();
cmd.args.subImage.h = size.height();
cmd.args.subImage.glformat = texD->glformat;
@@ -1909,7 +1940,7 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, u.buf);
Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
if (bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer)) {
- memcpy(bufD->data + u.offset, u.data.constData(), size_t(u.data.size()));
+ memcpy(bufD->data.data() + u.offset, u.data.constData(), size_t(u.data.size()));
} else {
trackedBufferBarrier(cbD, bufD, QGles2Buffer::AccessUpdate);
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
@@ -1925,7 +1956,7 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
Q_ASSERT(u.offset + u.data.size() <= bufD->m_size);
if (bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer)) {
- memcpy(bufD->data + u.offset, u.data.constData(), size_t(u.data.size()));
+ memcpy(bufD->data.data() + u.offset, u.data.constData(), size_t(u.data.size()));
} else {
trackedBufferBarrier(cbD, bufD, QGles2Buffer::AccessUpdate);
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
@@ -1940,7 +1971,7 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, u.buf);
if (bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer)) {
u.result->data.resize(u.readSize);
- memcpy(u.result->data.data(), bufD->data + u.offset, size_t(u.readSize));
+ memcpy(u.result->data.data(), bufD->data.constData() + u.offset, size_t(u.readSize));
if (u.result->completed)
u.result->completed();
} else {
@@ -1959,8 +1990,8 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
const QRhiResourceUpdateBatchPrivate::TextureOp &u(ud->textureOps[opIdx]);
if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Upload) {
QGles2Texture *texD = QRHI_RES(QGles2Texture, u.dst);
- for (int layer = 0; layer < QRhi::MAX_LAYERS; ++layer) {
- for (int level = 0; level < QRhi::MAX_LEVELS; ++level) {
+ for (int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
+ for (int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(u.subresDesc[layer][level]))
enqueueSubresUpload(texD, cbD, layer, level, subresDesc);
}
@@ -1988,18 +2019,21 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QGles2CommandBuffer::Command::CopyTex;
+ cmd.args.copyTex.srcTarget = srcD->target;
cmd.args.copyTex.srcFaceTarget = srcFaceTargetBase + uint(u.desc.sourceLayer());
cmd.args.copyTex.srcTexture = srcD->texture;
cmd.args.copyTex.srcLevel = u.desc.sourceLevel();
cmd.args.copyTex.srcX = sp.x();
cmd.args.copyTex.srcY = sp.y();
+ cmd.args.copyTex.srcZ = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional) ? u.desc.sourceLayer() : 0;
cmd.args.copyTex.dstTarget = dstD->target;
- cmd.args.copyTex.dstTexture = dstD->texture;
cmd.args.copyTex.dstFaceTarget = dstFaceTargetBase + uint(u.desc.destinationLayer());
+ cmd.args.copyTex.dstTexture = dstD->texture;
cmd.args.copyTex.dstLevel = u.desc.destinationLevel();
cmd.args.copyTex.dstX = dp.x();
cmd.args.copyTex.dstY = dp.y();
+ cmd.args.copyTex.dstZ = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional) ? u.desc.destinationLayer() : 0;
cmd.args.copyTex.w = copySize.width();
cmd.args.copyTex.h = copySize.height();
@@ -2011,14 +2045,20 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
if (texD)
trackedImageBarrier(cbD, texD, QGles2Texture::AccessRead);
cmd.args.readPixels.texture = texD ? texD->texture : 0;
+ cmd.args.readPixels.slice3D = -1;
if (texD) {
const QSize readImageSize = q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize);
cmd.args.readPixels.w = readImageSize.width();
cmd.args.readPixels.h = readImageSize.height();
cmd.args.readPixels.format = texD->m_format;
- const GLenum faceTargetBase = texD->m_flags.testFlag(QRhiTexture::CubeMap)
- ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : texD->target;
- cmd.args.readPixels.readTarget = faceTargetBase + uint(u.rb.layer());
+ if (texD->m_flags.testFlag(QRhiTexture::ThreeDimensional)) {
+ cmd.args.readPixels.readTarget = texD->target;
+ cmd.args.readPixels.slice3D = u.rb.layer();
+ } else {
+ const GLenum faceTargetBase = texD->m_flags.testFlag(QRhiTexture::CubeMap)
+ ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : texD->target;
+ cmd.args.readPixels.readTarget = faceTargetBase + uint(u.rb.layer());
+ }
cmd.args.readPixels.level = u.rb.level();
}
} else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::GenMips) {
@@ -2732,13 +2772,25 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
GLuint fbo;
f->glGenFramebuffers(1, &fbo);
f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
- f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- cmd.args.copyTex.srcFaceTarget, cmd.args.copyTex.srcTexture, cmd.args.copyTex.srcLevel);
+ if (cmd.args.copyTex.srcTarget == GL_TEXTURE_3D) {
+ f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.copyTex.srcTexture,
+ cmd.args.copyTex.srcLevel, cmd.args.copyTex.srcZ);
+ } else {
+ f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ cmd.args.copyTex.srcFaceTarget, cmd.args.copyTex.srcTexture, cmd.args.copyTex.srcLevel);
+ }
f->glBindTexture(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstTexture);
- f->glCopyTexSubImage2D(cmd.args.copyTex.dstFaceTarget, cmd.args.copyTex.dstLevel,
- cmd.args.copyTex.dstX, cmd.args.copyTex.dstY,
- cmd.args.copyTex.srcX, cmd.args.copyTex.srcY,
- cmd.args.copyTex.w, cmd.args.copyTex.h);
+ if (cmd.args.copyTex.dstTarget == GL_TEXTURE_3D) {
+ f->glCopyTexSubImage3D(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstLevel,
+ cmd.args.copyTex.dstX, cmd.args.copyTex.dstY, cmd.args.copyTex.dstZ,
+ cmd.args.copyTex.srcX, cmd.args.copyTex.srcY,
+ cmd.args.copyTex.w, cmd.args.copyTex.h);
+ } else {
+ f->glCopyTexSubImage2D(cmd.args.copyTex.dstFaceTarget, cmd.args.copyTex.dstLevel,
+ cmd.args.copyTex.dstX, cmd.args.copyTex.dstY,
+ cmd.args.copyTex.srcX, cmd.args.copyTex.srcY,
+ cmd.args.copyTex.w, cmd.args.copyTex.h);
+ }
f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
f->glDeleteFramebuffers(1, &fbo);
}
@@ -2756,8 +2808,13 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
if (mipLevel == 0 || caps.nonBaseLevelFramebufferTexture) {
f->glGenFramebuffers(1, &fbo);
f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
- f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- cmd.args.readPixels.readTarget, cmd.args.readPixels.texture, mipLevel);
+ if (cmd.args.readPixels.slice3D >= 0) {
+ f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ tex, mipLevel, cmd.args.readPixels.slice3D);
+ } else {
+ f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ cmd.args.readPixels.readTarget, tex, mipLevel);
+ }
}
} else {
result->pixelSize = currentSwapChain->pixelSize;
@@ -2823,11 +2880,19 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
f->glPixelStorei(GL_UNPACK_ALIGNMENT, cmd.args.subImage.rowStartAlign);
if (cmd.args.subImage.rowLength != 0)
f->glPixelStorei(GL_UNPACK_ROW_LENGTH, cmd.args.subImage.rowLength);
- f->glTexSubImage2D(cmd.args.subImage.faceTarget, cmd.args.subImage.level,
- cmd.args.subImage.dx, cmd.args.subImage.dy,
- cmd.args.subImage.w, cmd.args.subImage.h,
- cmd.args.subImage.glformat, cmd.args.subImage.gltype,
- cmd.args.subImage.data);
+ if (cmd.args.subImage.target == GL_TEXTURE_3D) {
+ f->glTexSubImage3D(cmd.args.subImage.target, cmd.args.subImage.level,
+ cmd.args.subImage.dx, cmd.args.subImage.dy, cmd.args.subImage.dz,
+ cmd.args.subImage.w, cmd.args.subImage.h, 1,
+ cmd.args.subImage.glformat, cmd.args.subImage.gltype,
+ cmd.args.subImage.data);
+ } else {
+ f->glTexSubImage2D(cmd.args.subImage.faceTarget, cmd.args.subImage.level,
+ cmd.args.subImage.dx, cmd.args.subImage.dy,
+ cmd.args.subImage.w, cmd.args.subImage.h,
+ cmd.args.subImage.glformat, cmd.args.subImage.gltype,
+ cmd.args.subImage.data);
+ }
if (cmd.args.subImage.rowStartAlign != 4)
f->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
if (cmd.args.subImage.rowLength != 0)
@@ -2835,18 +2900,33 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
break;
case QGles2CommandBuffer::Command::CompressedImage:
f->glBindTexture(cmd.args.compressedImage.target, cmd.args.compressedImage.texture);
- f->glCompressedTexImage2D(cmd.args.compressedImage.faceTarget, cmd.args.compressedImage.level,
- cmd.args.compressedImage.glintformat,
- cmd.args.compressedImage.w, cmd.args.compressedImage.h, 0,
- cmd.args.compressedImage.size, cmd.args.compressedImage.data);
+ if (cmd.args.compressedImage.target == GL_TEXTURE_3D) {
+ f->glCompressedTexImage3D(cmd.args.compressedImage.target, cmd.args.compressedImage.level,
+ cmd.args.compressedImage.glintformat,
+ cmd.args.compressedImage.w, cmd.args.compressedImage.h, cmd.args.compressedImage.depth,
+ 0, cmd.args.compressedImage.size, cmd.args.compressedImage.data);
+ } else {
+ f->glCompressedTexImage2D(cmd.args.compressedImage.faceTarget, cmd.args.compressedImage.level,
+ cmd.args.compressedImage.glintformat,
+ cmd.args.compressedImage.w, cmd.args.compressedImage.h,
+ 0, cmd.args.compressedImage.size, cmd.args.compressedImage.data);
+ }
break;
case QGles2CommandBuffer::Command::CompressedSubImage:
f->glBindTexture(cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.texture);
- f->glCompressedTexSubImage2D(cmd.args.compressedSubImage.faceTarget, cmd.args.compressedSubImage.level,
- cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy,
- cmd.args.compressedSubImage.w, cmd.args.compressedSubImage.h,
- cmd.args.compressedSubImage.glintformat,
- cmd.args.compressedSubImage.size, cmd.args.compressedSubImage.data);
+ if (cmd.args.compressedSubImage.target == GL_TEXTURE_3D) {
+ f->glCompressedTexSubImage3D(cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.level,
+ cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy, cmd.args.compressedSubImage.dz,
+ cmd.args.compressedSubImage.w, cmd.args.compressedSubImage.h, 1,
+ cmd.args.compressedSubImage.glintformat,
+ cmd.args.compressedSubImage.size, cmd.args.compressedSubImage.data);
+ } else {
+ f->glCompressedTexSubImage2D(cmd.args.compressedSubImage.faceTarget, cmd.args.compressedSubImage.level,
+ cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy,
+ cmd.args.compressedSubImage.w, cmd.args.compressedSubImage.h,
+ cmd.args.compressedSubImage.glintformat,
+ cmd.args.compressedSubImage.size, cmd.args.compressedSubImage.data);
+ }
break;
case QGles2CommandBuffer::Command::BlitFromRenderbuffer:
{
@@ -3140,7 +3220,7 @@ void QRhiGles2::bindShaderResources(QGles2CommandBuffer *cbD,
}
}
QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, b->u.ubuf.buf);
- const char *bufView = bufD->data + viewOffset;
+ const char *bufView = bufD->data.constData() + viewOffset;
for (const QGles2UniformDescription &uniform : qAsConst(uniforms)) {
if (uniform.binding == b->binding) {
// in a uniform buffer everything is at least 4 byte aligned
@@ -3397,6 +3477,8 @@ void QRhiGles2::bindShaderResources(QGles2CommandBuffer *cbD,
f->glTexParameteri(texD->target, GL_TEXTURE_MAG_FILTER, GLint(samplerD->d.glmagfilter));
f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_S, GLint(samplerD->d.glwraps));
f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_T, GLint(samplerD->d.glwrapt));
+ if (caps.texture3D)
+ f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_R, GLint(samplerD->d.glwrapr));
if (caps.textureCompareMode) {
if (samplerD->d.gltexcomparefunc != GL_NEVER) {
f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
@@ -4163,9 +4245,7 @@ QGles2Buffer::~QGles2Buffer()
void QGles2Buffer::destroy()
{
- delete[] data;
- data = nullptr;
-
+ data.clear();
if (!buffer)
return;
@@ -4197,8 +4277,7 @@ bool QGles2Buffer::create()
qWarning("Uniform buffer: multiple usages specified, this is not supported by the OpenGL backend");
return false;
}
- delete[] data;
- data = new char[nonZeroSize];
+ data.resize(nonZeroSize);
QRHI_PROF_F(newBuffer(this, uint(nonZeroSize), 0, 1));
return true;
}
@@ -4242,11 +4321,11 @@ char *QGles2Buffer::beginFullDynamicBufferUpdateForCurrentFrame()
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
} else {
// Need some storage for the data, use the otherwise unused 'data' member.
- if (!data)
- data = new char[nonZeroSize];
+ if (data.isEmpty())
+ data.resize(nonZeroSize);
}
}
- return data;
+ return data.data();
}
void QGles2Buffer::endFullDynamicBufferUpdateForCurrentFrame()
@@ -4256,7 +4335,7 @@ void QGles2Buffer::endFullDynamicBufferUpdateForCurrentFrame()
if (rhiD->caps.properMapBuffer)
rhiD->f->glUnmapBuffer(targetForDataOps);
else
- rhiD->f->glBufferSubData(targetForDataOps, 0, nonZeroSize, data);
+ rhiD->f->glBufferSubData(targetForDataOps, 0, nonZeroSize, data.data());
}
}
@@ -4287,7 +4366,8 @@ void QGles2RenderBuffer::destroy()
stencilRenderbuffer = 0;
QRHI_RES_RHI(QRhiGles2);
- rhiD->releaseQueue.append(e);
+ if (owns)
+ rhiD->releaseQueue.append(e);
QRHI_PROF;
QRHI_PROF_F(releaseRenderBuffer(this));
rhiD->unregisterResource(this);
@@ -4375,6 +4455,34 @@ bool QGles2RenderBuffer::create()
break;
}
+ owns = true;
+ rhiD->registerResource(this);
+ return true;
+}
+
+bool QGles2RenderBuffer::createFrom(NativeRenderBuffer src)
+{
+ if (!src.object)
+ return false;
+
+ if (renderbuffer)
+ destroy();
+
+ QRHI_RES_RHI(QRhiGles2);
+ samples = rhiD->effectiveSampleCount(m_sampleCount);
+
+ if (m_flags.testFlag(UsedWithSwapChainOnly))
+ qWarning("RenderBuffer: UsedWithSwapChainOnly is meaningless when importing an existing native object");
+
+ if (!rhiD->ensureContext())
+ return false;
+
+ renderbuffer = src.object;
+
+ QRHI_PROF;
+ QRHI_PROF_F(newRenderBuffer(this, false, false, samples));
+
+ owns = false;
rhiD->registerResource(this);
return true;
}
@@ -4387,9 +4495,9 @@ QRhiTexture::Format QGles2RenderBuffer::backingFormat() const
return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
}
-QGles2Texture::QGles2Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+QGles2Texture::QGles2Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
int sampleCount, Flags flags)
- : QRhiTexture(rhi, format, pixelSize, sampleCount, flags)
+ : QRhiTexture(rhi, format, pixelSize, depth, sampleCount, flags)
{
}
@@ -4410,7 +4518,7 @@ void QGles2Texture::destroy()
texture = 0;
specified = false;
- compressedAtlasBuilt = false;
+ zeroInitialized = false;
QRHI_RES_RHI(QRhiGles2);
if (owns)
@@ -4432,11 +4540,26 @@ bool QGles2Texture::prepareCreate(QSize *adjustedSize)
const QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool is3D = m_flags.testFlag(ThreeDimensional);
const bool hasMipMaps = m_flags.testFlag(MipMapped);
const bool isCompressed = rhiD->isCompressedFormat(m_format);
+ if (is3D && !rhiD->caps.texture3D) {
+ qWarning("3D textures are not supported");
+ return false;
+ }
+ if (isCube && is3D) {
+ qWarning("Texture cannot be both cube and 3D");
+ return false;
+ }
+ m_depth = qMax(1, m_depth);
+ if (m_depth > 1 && !is3D) {
+ qWarning("Texture cannot have a depth of %d when it is not 3D", m_depth);
+ return false;
+ }
+
target = isCube ? GL_TEXTURE_CUBE_MAP
- : m_sampleCount > 1 ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
+ : m_sampleCount > 1 ? GL_TEXTURE_2D_MULTISAMPLE : (is3D ? GL_TEXTURE_3D : GL_TEXTURE_2D);
if (m_flags.testFlag(ExternalOES))
target = GL_TEXTURE_EXTERNAL_OES;
@@ -4480,12 +4603,24 @@ bool QGles2Texture::create()
rhiD->f->glGenTextures(1, &texture);
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool is3D = m_flags.testFlag(ThreeDimensional);
const bool hasMipMaps = m_flags.testFlag(MipMapped);
const bool isCompressed = rhiD->isCompressedFormat(m_format);
if (!isCompressed) {
rhiD->f->glBindTexture(target, texture);
if (!m_flags.testFlag(UsedWithLoadStore)) {
- if (hasMipMaps || isCube) {
+ if (is3D) {
+ if (hasMipMaps) {
+ for (int level = 0; level != mipLevelCount; ++level) {
+ const QSize mipSize = rhiD->q->sizeForMipLevel(level, size);
+ rhiD->f->glTexImage3D(target, level, GLint(glintformat), mipSize.width(), mipSize.height(), m_depth,
+ 0, glformat, gltype, nullptr);
+ }
+ } else {
+ rhiD->f->glTexImage3D(target, 0, GLint(glintformat), size.width(), size.height(), m_depth,
+ 0, glformat, gltype, nullptr);
+ }
+ } else if (hasMipMaps || isCube) {
const GLenum faceTargetBase = isCube ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
for (int layer = 0, layerCount = isCube ? 6 : 1; layer != layerCount; ++layer) {
for (int level = 0; level != mipLevelCount; ++level) {
@@ -4503,7 +4638,10 @@ bool QGles2Texture::create()
// Must be specified with immutable storage functions otherwise
// bindImageTexture may fail. Also, the internal format must be a
// sized format here.
- rhiD->f->glTexStorage2D(target, mipLevelCount, glsizedintformat, size.width(), size.height());
+ if (is3D)
+ rhiD->f->glTexStorage3D(target, mipLevelCount, glsizedintformat, size.width(), size.height(), m_depth);
+ else
+ rhiD->f->glTexStorage2D(target, mipLevelCount, glsizedintformat, size.width(), size.height());
}
specified = true;
} else {
@@ -4534,7 +4672,7 @@ bool QGles2Texture::createFrom(QRhiTexture::NativeTexture src)
texture = textureId;
specified = true;
- compressedAtlasBuilt = true;
+ zeroInitialized = true;
QRHI_RES_RHI(QRhiGles2);
QRHI_PROF;
@@ -4574,6 +4712,7 @@ bool QGles2Sampler::create()
d.glmagfilter = toGlMagFilter(m_magFilter);
d.glwraps = toGlWrapMode(m_addressU);
d.glwrapt = toGlWrapMode(m_addressV);
+ d.glwrapr = toGlWrapMode(m_addressW);
d.gltexcomparefunc = toGlTextureCompareFunc(m_compareOp);
generation += 1;
@@ -4713,9 +4852,14 @@ bool QGles2TextureRenderTarget::create()
if (texture) {
QGles2Texture *texD = QRHI_RES(QGles2Texture, texture);
Q_ASSERT(texD->texture && texD->specified);
- const GLenum faceTargetBase = texD->flags().testFlag(QRhiTexture::CubeMap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : texD->target;
- rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.layer()),
- texD->texture, colorAtt.level());
+ if (texD->flags().testFlag(QRhiTexture::ThreeDimensional)) {
+ rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), texD->texture,
+ colorAtt.level(), colorAtt.layer());
+ } else {
+ const GLenum faceTargetBase = texD->flags().testFlag(QRhiTexture::CubeMap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : texD->target;
+ rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.layer()),
+ texD->texture, colorAtt.level());
+ }
if (attIndex == 0) {
d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
d.sampleCount = 1;
diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h
index 3d9fba80dc..8a0e0ec2a1 100644
--- a/src/gui/rhi/qrhigles2_p_p.h
+++ b/src/gui/rhi/qrhigles2_p_p.h
@@ -55,6 +55,7 @@
#include "qrhi_p_p.h"
#include "qshaderdescription_p.h"
#include <qopengl.h>
+#include <QByteArray>
#include <QSurface>
QT_BEGIN_NAMESPACE
@@ -74,7 +75,7 @@ struct QGles2Buffer : public QRhiBuffer
int nonZeroSize = 0;
GLuint buffer = 0;
GLenum targetForDataOps;
- char *data = nullptr;
+ QByteArray data;
enum Access {
AccessNone,
AccessVertex,
@@ -100,11 +101,13 @@ struct QGles2RenderBuffer : public QRhiRenderBuffer
~QGles2RenderBuffer();
void destroy() override;
bool create() override;
+ bool createFrom(NativeRenderBuffer src) override;
QRhiTexture::Format backingFormat() const override;
GLuint renderbuffer = 0;
GLuint stencilRenderbuffer = 0; // when packed depth-stencil not supported
int samples;
+ bool owns = true;
friend class QRhiGles2;
};
@@ -114,6 +117,7 @@ struct QGles2SamplerData
GLenum glmagfilter = 0;
GLenum glwraps = 0;
GLenum glwrapt = 0;
+ GLenum glwrapr = 0;
GLenum gltexcomparefunc = 0;
};
@@ -123,6 +127,7 @@ inline bool operator==(const QGles2SamplerData &a, const QGles2SamplerData &b)
&& a.glmagfilter == b.glmagfilter
&& a.glwraps == b.glwraps
&& a.glwrapt == b.glwrapt
+ && a.glwrapr == b.glwrapr
&& a.gltexcomparefunc == b.gltexcomparefunc;
}
@@ -133,7 +138,7 @@ inline bool operator!=(const QGles2SamplerData &a, const QGles2SamplerData &b)
struct QGles2Texture : public QRhiTexture
{
- QGles2Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+ QGles2Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
int sampleCount, Flags flags);
~QGles2Texture();
void destroy() override;
@@ -152,7 +157,7 @@ struct QGles2Texture : public QRhiTexture
GLenum gltype;
QGles2SamplerData samplerState;
bool specified = false;
- bool compressedAtlasBuilt = false;
+ bool zeroInitialized = false;
int mipLevelCount = 0;
enum Access {
@@ -438,17 +443,20 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer
int size;
} getBufferSubData;
struct {
+ GLenum srcTarget;
GLenum srcFaceTarget;
GLuint srcTexture;
int srcLevel;
int srcX;
int srcY;
+ int srcZ;
GLenum dstTarget;
GLuint dstTexture;
GLenum dstFaceTarget;
int dstLevel;
int dstX;
int dstY;
+ int dstZ;
int w;
int h;
} copyTex;
@@ -460,6 +468,7 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer
QRhiTexture::Format format;
GLenum readTarget;
int level;
+ int slice3D;
} readPixels;
struct {
GLenum target;
@@ -468,6 +477,7 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer
int level;
int dx;
int dy;
+ int dz;
int w;
int h;
GLenum glformat;
@@ -484,6 +494,7 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer
GLenum glintformat;
int w;
int h;
+ int depth;
int size;
const void *data; // must come from retainData()
} compressedImage;
@@ -494,6 +505,7 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer
int level;
int dx;
int dy;
+ int dz;
int w;
int h;
GLenum glintformat;
@@ -737,6 +749,7 @@ public:
QRhiTexture::Format backingFormatHint) override;
QRhiTexture *createTexture(QRhiTexture::Format format,
const QSize &pixelSize,
+ int depth,
int sampleCount,
QRhiTexture::Flags flags) override;
QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
@@ -927,7 +940,8 @@ public:
texelFetch(false),
intAttributes(true),
screenSpaceDerivatives(false),
- programBinary(false)
+ programBinary(false),
+ texture3D(false)
{ }
int ctxMajor;
int ctxMinor;
@@ -970,6 +984,7 @@ public:
uint intAttributes : 1;
uint screenSpaceDerivatives : 1;
uint programBinary : 1;
+ uint texture3D : 1;
} caps;
QGles2SwapChain *currentSwapChain = nullptr;
QList<GLint> supportedCompressedFormats;
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index 850b3a91aa..cf11f12ead 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -182,7 +182,7 @@ struct QRhiMetalData
struct {
id<MTLTexture> texture;
id<MTLBuffer> stagingBuffers[QMTL_FRAMES_IN_FLIGHT];
- id<MTLTexture> views[QRhi::MAX_LEVELS];
+ id<MTLTexture> views[QRhi::MAX_MIP_LEVELS];
} texture;
struct {
id<MTLSamplerState> samplerState;
@@ -249,7 +249,7 @@ struct QMetalTextureData
id<MTLTexture> tex = nil;
id<MTLBuffer> stagingBuf[QMTL_FRAMES_IN_FLIGHT];
bool owns = true;
- id<MTLTexture> perLevelViews[QRhi::MAX_LEVELS];
+ id<MTLTexture> perLevelViews[QRhi::MAX_MIP_LEVELS];
id<MTLTexture> viewForLevel(int level);
};
@@ -281,7 +281,8 @@ struct QMetalRenderTargetData
struct ColorAtt {
bool needsDrawableForTex = false;
id<MTLTexture> tex = nil;
- int layer = 0;
+ int arrayLayer = 0;
+ int slice = 0;
int level = 0;
bool needsDrawableForResolveTex = false;
id<MTLTexture> resolveTex = nil;
@@ -595,6 +596,12 @@ bool QRhiMetal::isFeatureSupported(QRhi::Feature feature) const
return false;
case QRhi::ImageDataStride:
return true;
+ case QRhi::RenderBufferImport:
+ return false;
+ case QRhi::ThreeDimensionalTextures:
+ return true;
+ case QRhi::RenderTo3DTextureSlice:
+ return true;
default:
Q_UNREACHABLE();
return false;
@@ -685,10 +692,11 @@ QRhiRenderBuffer *QRhiMetal::createRenderBuffer(QRhiRenderBuffer::Type type, con
return new QMetalRenderBuffer(this, type, pixelSize, sampleCount, flags, backingFormatHint);
}
-QRhiTexture *QRhiMetal::createTexture(QRhiTexture::Format format, const QSize &pixelSize,
+QRhiTexture *QRhiMetal::createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize, int depth,
int sampleCount, QRhiTexture::Flags flags)
{
- return new QMetalTexture(this, format, pixelSize, sampleCount, flags);
+ return new QMetalTexture(this, format, pixelSize, depth, sampleCount, flags);
}
QRhiSampler *QRhiMetal::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
@@ -1611,6 +1619,7 @@ void QRhiMetal::enqueueSubresUpload(QMetalTexture *texD, void *mp, void *blitEnc
const QPoint dp = subresDesc.destinationTopLeft();
const QByteArray rawData = subresDesc.data();
QImage img = subresDesc.image();
+ const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
id<MTLBlitCommandEncoder> blitEnc = (id<MTLBlitCommandEncoder>) blitEncPtr;
if (!img.isNull()) {
@@ -1647,9 +1656,9 @@ void QRhiMetal::enqueueSubresUpload(QMetalTexture *texD, void *mp, void *blitEnc
sourceBytesPerImage: 0
sourceSize: MTLSizeMake(NSUInteger(w), NSUInteger(h), 1)
toTexture: texD->d->tex
- destinationSlice: NSUInteger(layer)
+ destinationSlice: NSUInteger(is3D ? 0 : layer)
destinationLevel: NSUInteger(level)
- destinationOrigin: MTLOriginMake(NSUInteger(dp.x()), NSUInteger(dp.y()), 0)
+ destinationOrigin: MTLOriginMake(NSUInteger(dp.x()), NSUInteger(dp.y()), NSUInteger(is3D ? layer : 0))
options: MTLBlitOptionNone];
*curOfs += aligned<qsizetype>(fullImageSizeBytes, QRhiMetalData::TEXBUF_ALIGN);
@@ -1685,9 +1694,9 @@ void QRhiMetal::enqueueSubresUpload(QMetalTexture *texD, void *mp, void *blitEnc
sourceBytesPerImage: 0
sourceSize: MTLSizeMake(NSUInteger(w), NSUInteger(h), 1)
toTexture: texD->d->tex
- destinationSlice: NSUInteger(layer)
+ destinationSlice: NSUInteger(is3D ? 0 : layer)
destinationLevel: NSUInteger(level)
- destinationOrigin: MTLOriginMake(NSUInteger(dx), NSUInteger(dy), 0)
+ destinationOrigin: MTLOriginMake(NSUInteger(dx), NSUInteger(dy), NSUInteger(is3D ? layer : 0))
options: MTLBlitOptionNone];
*curOfs += aligned<qsizetype>(rawData.size(), QRhiMetalData::TEXBUF_ALIGN);
@@ -1718,9 +1727,9 @@ void QRhiMetal::enqueueSubresUpload(QMetalTexture *texD, void *mp, void *blitEnc
sourceBytesPerImage: 0
sourceSize: MTLSizeMake(NSUInteger(w), NSUInteger(h), 1)
toTexture: texD->d->tex
- destinationSlice: NSUInteger(layer)
+ destinationSlice: NSUInteger(is3D ? 0 : layer)
destinationLevel: NSUInteger(level)
- destinationOrigin: MTLOriginMake(NSUInteger(dp.x()), NSUInteger(dp.y()), 0)
+ destinationOrigin: MTLOriginMake(NSUInteger(dp.x()), NSUInteger(dp.y()), NSUInteger(is3D ? layer : 0))
options: MTLBlitOptionNone];
*curOfs += aligned<qsizetype>(rawData.size(), QRhiMetalData::TEXBUF_ALIGN);
@@ -1781,8 +1790,8 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Upload) {
QMetalTexture *utexD = QRHI_RES(QMetalTexture, u.dst);
qsizetype stagingSize = 0;
- for (int layer = 0; layer < QRhi::MAX_LAYERS; ++layer) {
- for (int level = 0; level < QRhi::MAX_LEVELS; ++level) {
+ for (int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
+ for (int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(u.subresDesc[layer][level]))
stagingSize += subresUploadByteSize(subresDesc);
}
@@ -1796,8 +1805,8 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
void *mp = [utexD->d->stagingBuf[currentFrameSlot] contents];
qsizetype curOfs = 0;
- for (int layer = 0; layer < QRhi::MAX_LAYERS; ++layer) {
- for (int level = 0; level < QRhi::MAX_LEVELS; ++level) {
+ for (int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
+ for (int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(u.subresDesc[layer][level]))
enqueueSubresUpload(utexD, mp, blitEnc, layer, level, subresDesc, &curOfs);
}
@@ -1816,6 +1825,8 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
Q_ASSERT(u.src && u.dst);
QMetalTexture *srcD = QRHI_RES(QMetalTexture, u.src);
QMetalTexture *dstD = QRHI_RES(QMetalTexture, u.dst);
+ const bool srcIs3D = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
+ const bool dstIs3D = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
const QPoint dp = u.desc.destinationTopLeft();
const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
@@ -1823,14 +1834,14 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
ensureBlit();
[blitEnc copyFromTexture: srcD->d->tex
- sourceSlice: NSUInteger(u.desc.sourceLayer())
+ sourceSlice: NSUInteger(srcIs3D ? 0 : u.desc.sourceLayer())
sourceLevel: NSUInteger(u.desc.sourceLevel())
- sourceOrigin: MTLOriginMake(NSUInteger(sp.x()), NSUInteger(sp.y()), 0)
+ sourceOrigin: MTLOriginMake(NSUInteger(sp.x()), NSUInteger(sp.y()), NSUInteger(srcIs3D ? u.desc.sourceLayer() : 0))
sourceSize: MTLSizeMake(NSUInteger(copySize.width()), NSUInteger(copySize.height()), 1)
toTexture: dstD->d->tex
- destinationSlice: NSUInteger(u.desc.destinationLayer())
+ destinationSlice: NSUInteger(dstIs3D ? 0 : u.desc.destinationLayer())
destinationLevel: NSUInteger(u.desc.destinationLevel())
- destinationOrigin: MTLOriginMake(NSUInteger(dp.x()), NSUInteger(dp.y()), 0)];
+ destinationOrigin: MTLOriginMake(NSUInteger(dp.x()), NSUInteger(dp.y()), NSUInteger(dstIs3D ? u.desc.destinationLayer() : 0))];
srcD->lastActiveFrameSlot = dstD->lastActiveFrameSlot = currentFrameSlot;
} else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Read) {
@@ -1843,11 +1854,13 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
QMetalSwapChain *swapChainD = nullptr;
id<MTLTexture> src;
QSize srcSize;
+ bool is3D = false;
if (texD) {
if (texD->samples > 1) {
qWarning("Multisample texture cannot be read back");
continue;
}
+ is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
readback.pixelSize = q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize);
readback.format = texD->m_format;
src = texD->d->tex;
@@ -1875,9 +1888,9 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
ensureBlit();
[blitEnc copyFromTexture: src
- sourceSlice: NSUInteger(u.rb.layer())
+ sourceSlice: NSUInteger(is3D ? 0 : u.rb.layer())
sourceLevel: NSUInteger(u.rb.level())
- sourceOrigin: MTLOriginMake(0, 0, 0)
+ sourceOrigin: MTLOriginMake(0, 0, is3D ? u.rb.layer() : 0)
sourceSize: MTLSizeMake(NSUInteger(srcSize.width()), NSUInteger(srcSize.height()), 1)
toBuffer: readback.buf
destinationOffset: 0
@@ -2017,7 +2030,8 @@ void QRhiMetal::beginPass(QRhiCommandBuffer *cb,
for (uint i = 0; i < uint(rtD->colorAttCount); ++i) {
cbD->d->currentPassRpDesc.colorAttachments[i].texture = rtD->fb.colorAtt[i].tex;
- cbD->d->currentPassRpDesc.colorAttachments[i].slice = NSUInteger(rtD->fb.colorAtt[i].layer);
+ cbD->d->currentPassRpDesc.colorAttachments[i].slice = NSUInteger(rtD->fb.colorAtt[i].arrayLayer);
+ cbD->d->currentPassRpDesc.colorAttachments[i].depthPlane = NSUInteger(rtD->fb.colorAtt[i].slice);
cbD->d->currentPassRpDesc.colorAttachments[i].level = NSUInteger(rtD->fb.colorAtt[i].level);
if (rtD->fb.colorAtt[i].resolveTex) {
cbD->d->currentPassRpDesc.colorAttachments[i].storeAction = MTLStoreActionMultisampleResolve;
@@ -2127,7 +2141,7 @@ static void qrhimtl_releaseTexture(const QRhiMetalData::DeferredReleaseEntry &e)
[e.texture.texture release];
for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i)
[e.texture.stagingBuffers[i] release];
- for (int i = 0; i < QRhi::MAX_LEVELS; ++i)
+ for (int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i)
[e.texture.views[i] release];
}
@@ -2578,15 +2592,15 @@ QRhiTexture::Format QMetalRenderBuffer::backingFormat() const
return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
}
-QMetalTexture::QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+QMetalTexture::QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
int sampleCount, Flags flags)
- : QRhiTexture(rhi, format, pixelSize, sampleCount, flags),
+ : QRhiTexture(rhi, format, pixelSize, depth, sampleCount, flags),
d(new QMetalTextureData(this))
{
for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i)
d->stagingBuf[i] = nil;
- for (int i = 0; i < QRhi::MAX_LEVELS; ++i)
+ for (int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i)
d->perLevelViews[i] = nil;
}
@@ -2613,7 +2627,7 @@ void QMetalTexture::destroy()
d->stagingBuf[i] = nil;
}
- for (int i = 0; i < QRhi::MAX_LEVELS; ++i) {
+ for (int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i) {
e.texture.views[i] = d->perLevelViews[i];
d->perLevelViews[i] = nil;
}
@@ -2632,6 +2646,7 @@ bool QMetalTexture::prepareCreate(QSize *adjustedSize)
const QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool is3D = m_flags.testFlag(ThreeDimensional);
const bool hasMipMaps = m_flags.testFlag(MipMapped);
QRHI_RES_RHI(QRhiMetal);
@@ -2643,11 +2658,24 @@ bool QMetalTexture::prepareCreate(QSize *adjustedSize)
qWarning("Cubemap texture cannot be multisample");
return false;
}
+ if (is3D) {
+ qWarning("3D texture cannot be multisample");
+ return false;
+ }
if (hasMipMaps) {
qWarning("Multisample texture cannot have mipmaps");
return false;
}
}
+ if (isCube && is3D) {
+ qWarning("Texture cannot be both cube and 3D");
+ return false;
+ }
+ m_depth = qMax(1, m_depth);
+ if (m_depth > 1 && !is3D) {
+ qWarning("Texture cannot have a depth of %d when it is not 3D", m_depth);
+ return false;
+ }
if (adjustedSize)
*adjustedSize = size;
@@ -2664,13 +2692,17 @@ bool QMetalTexture::create()
MTLTextureDescriptor *desc = [[MTLTextureDescriptor alloc] init];
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool is3D = m_flags.testFlag(ThreeDimensional);
if (isCube)
desc.textureType = MTLTextureTypeCube;
+ else if (is3D)
+ desc.textureType = MTLTextureType3D;
else
desc.textureType = samples > 1 ? MTLTextureType2DMultisample : MTLTextureType2D;
desc.pixelFormat = d->format;
desc.width = NSUInteger(size.width());
desc.height = NSUInteger(size.height());
+ desc.depth = is3D ? m_depth : 1;
desc.mipmapLevelCount = NSUInteger(mipLevelCount);
if (samples > 1)
desc.sampleCount = NSUInteger(samples);
@@ -3007,12 +3039,14 @@ bool QMetalTextureRenderTarget::create()
QMetalRenderBuffer *rbD = QRHI_RES(QMetalRenderBuffer, it->renderBuffer());
Q_ASSERT(texD || rbD);
id<MTLTexture> dst = nil;
+ bool is3D = false;
if (texD) {
dst = texD->d->tex;
if (attIndex == 0) {
d->pixelSize = rhiD->q->sizeForMipLevel(it->level(), texD->pixelSize());
d->sampleCount = texD->samples;
}
+ is3D = texD->flags().testFlag(QRhiTexture::ThreeDimensional);
} else if (rbD) {
dst = rbD->d->tex;
if (attIndex == 0) {
@@ -3022,7 +3056,8 @@ bool QMetalTextureRenderTarget::create()
}
QMetalRenderTargetData::ColorAtt colorAtt;
colorAtt.tex = dst;
- colorAtt.layer = it->layer();
+ colorAtt.arrayLayer = is3D ? 0 : it->layer();
+ colorAtt.slice = is3D ? it->layer() : 0;
colorAtt.level = it->level();
QMetalTexture *resTexD = QRHI_RES(QMetalTexture, it->resolveTexture());
colorAtt.resolveTex = resTexD ? resTexD->d->tex : nil;
diff --git a/src/gui/rhi/qrhimetal_p_p.h b/src/gui/rhi/qrhimetal_p_p.h
index c8ba5940a8..3a22b76b22 100644
--- a/src/gui/rhi/qrhimetal_p_p.h
+++ b/src/gui/rhi/qrhimetal_p_p.h
@@ -102,7 +102,7 @@ struct QMetalTextureData;
struct QMetalTexture : public QRhiTexture
{
- QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+ QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
int sampleCount, Flags flags);
~QMetalTexture();
void destroy() override;
@@ -360,6 +360,7 @@ public:
QRhiTexture::Format backingFormatHint) override;
QRhiTexture *createTexture(QRhiTexture::Format format,
const QSize &pixelSize,
+ int depth,
int sampleCount,
QRhiTexture::Flags flags) override;
QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
diff --git a/src/gui/rhi/qrhinull.cpp b/src/gui/rhi/qrhinull.cpp
index 0a25b58b91..d8dd77a790 100644
--- a/src/gui/rhi/qrhinull.cpp
+++ b/src/gui/rhi/qrhinull.cpp
@@ -218,10 +218,11 @@ QRhiRenderBuffer *QRhiNull::createRenderBuffer(QRhiRenderBuffer::Type type, cons
return new QNullRenderBuffer(this, type, pixelSize, sampleCount, flags, backingFormatHint);
}
-QRhiTexture *QRhiNull::createTexture(QRhiTexture::Format format, const QSize &pixelSize,
+QRhiTexture *QRhiNull::createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize, int depth,
int sampleCount, QRhiTexture::Flags flags)
{
- return new QNullTexture(this, format, pixelSize, sampleCount, flags);
+ return new QNullTexture(this, format, pixelSize, depth, sampleCount, flags);
}
QRhiSampler *QRhiNull::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
@@ -415,8 +416,8 @@ QRhi::FrameOpResult QRhiNull::finish()
void QRhiNull::simulateTextureUpload(const QRhiResourceUpdateBatchPrivate::TextureOp &u)
{
QNullTexture *texD = QRHI_RES(QNullTexture, u.dst);
- for (int layer = 0; layer < QRhi::MAX_LAYERS; ++layer) {
- for (int level = 0; level < QRhi::MAX_LEVELS; ++level) {
+ for (int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
+ for (int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(u.subresDesc[layer][level])) {
if (!subresDesc.image().isNull()) {
const QImage src = subresDesc.image();
@@ -642,9 +643,9 @@ QRhiTexture::Format QNullRenderBuffer::backingFormat() const
return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
}
-QNullTexture::QNullTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+QNullTexture::QNullTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
int sampleCount, Flags flags)
- : QRhiTexture(rhi, format, pixelSize, sampleCount, flags)
+ : QRhiTexture(rhi, format, pixelSize, depth, sampleCount, flags)
{
}
@@ -663,12 +664,15 @@ bool QNullTexture::create()
{
QRHI_RES_RHI(QRhiNull);
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool is3D = m_flags.testFlag(ThreeDimensional);
const bool hasMipMaps = m_flags.testFlag(MipMapped);
QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
+ m_depth = qMax(1, m_depth);
const int mipLevelCount = hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1;
- const int layerCount = isCube ? 6 : 1;
+ const int layerCount = is3D ? m_depth : (isCube ? 6 : 1);
if (m_format == RGBA8) {
+ image.resize(layerCount);
for (int layer = 0; layer < layerCount; ++layer) {
for (int level = 0; level < mipLevelCount; ++level) {
image[layer][level] = QImage(rhiD->q->sizeForMipLevel(level, size),
diff --git a/src/gui/rhi/qrhinull_p_p.h b/src/gui/rhi/qrhinull_p_p.h
index d296c0bbf0..b064e7ad37 100644
--- a/src/gui/rhi/qrhinull_p_p.h
+++ b/src/gui/rhi/qrhinull_p_p.h
@@ -80,14 +80,14 @@ struct QNullRenderBuffer : public QRhiRenderBuffer
struct QNullTexture : public QRhiTexture
{
- QNullTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+ QNullTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
int sampleCount, Flags flags);
~QNullTexture();
void destroy() override;
bool create() override;
bool createFrom(NativeTexture src) override;
- QImage image[QRhi::MAX_LAYERS][QRhi::MAX_LEVELS];
+ QVarLengthArray<std::array<QImage, QRhi::MAX_MIP_LEVELS>, 6> image;
};
struct QNullSampler : public QRhiSampler
@@ -217,6 +217,7 @@ public:
QRhiTexture::Format backingFormatHint) override;
QRhiTexture *createTexture(QRhiTexture::Format format,
const QSize &pixelSize,
+ int depth,
int sampleCount,
QRhiTexture::Flags flags) override;
QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
diff --git a/src/gui/rhi/qrhiprofiler.cpp b/src/gui/rhi/qrhiprofiler.cpp
index 364a247ea1..76798dc396 100644
--- a/src/gui/rhi/qrhiprofiler.cpp
+++ b/src/gui/rhi/qrhiprofiler.cpp
@@ -387,7 +387,7 @@ void QRhiProfilerPrivate::newRenderBuffer(QRhiRenderBuffer *rb, bool transientBa
const QSize sz = rb->pixelSize();
// just make up something, ds is likely D24S8 while color is RGBA8 or similar
const QRhiTexture::Format assumedFormat = type == QRhiRenderBuffer::DepthStencil ? QRhiTexture::D32F : QRhiTexture::RGBA8;
- quint32 byteSize = rhiDWhenEnabled->approxByteSizeForTexture(assumedFormat, sz, 1, 1);
+ quint32 byteSize = rhiDWhenEnabled->approxByteSizeForTexture(assumedFormat, sz, 1, 1, 1);
if (sampleCount > 1)
byteSize *= uint(sampleCount);
@@ -418,7 +418,8 @@ void QRhiProfilerPrivate::newTexture(QRhiTexture *tex, bool owns, int mipCount,
const QRhiTexture::Format format = tex->format();
const QSize sz = tex->pixelSize();
- quint32 byteSize = rhiDWhenEnabled->approxByteSizeForTexture(format, sz, mipCount, layerCount);
+ const int depth = tex->depth();
+ quint32 byteSize = rhiDWhenEnabled->approxByteSizeForTexture(format, sz, depth, mipCount, layerCount);
if (sampleCount > 1)
byteSize *= uint(sampleCount);
@@ -470,7 +471,7 @@ void QRhiProfilerPrivate::resizeSwapChain(QRhiSwapChain *sc, int bufferCount, in
return;
const QSize sz = sc->currentPixelSize();
- quint32 byteSize = rhiDWhenEnabled->approxByteSizeForTexture(QRhiTexture::BGRA8, sz, 1, 1);
+ quint32 byteSize = rhiDWhenEnabled->approxByteSizeForTexture(QRhiTexture::BGRA8, sz, 1, 1, 1);
byteSize = byteSize * uint(bufferCount) + byteSize * uint(msaaBufferCount) * uint(sampleCount);
startEntry(QRhiProfiler::ResizeSwapChain, ts.elapsed(), sc);
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index e7e31b1b2d..64b979b8c7 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -104,18 +104,7 @@ QT_BEGIN_NAMESPACE
...
QVulkanInstance inst;
- #ifndef Q_OS_ANDROID
- inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
- #else
- inst.setLayers(QByteArrayList()
- << "VK_LAYER_GOOGLE_threading"
- << "VK_LAYER_LUNARG_parameter_validation"
- << "VK_LAYER_LUNARG_object_tracker"
- << "VK_LAYER_LUNARG_core_validation"
- << "VK_LAYER_LUNARG_image"
- << "VK_LAYER_LUNARG_swapchain"
- << "VK_LAYER_GOOGLE_unique_objects");
- #endif
+ inst.setLayers({ "VK_LAYER_KHRONOS_validation" }); // for debugging only, not for release builds
inst.setExtensions(QRhiVulkanInitParams::preferredInstanceExtensions());
if (!inst.create())
qFatal("Vulkan not available");
@@ -160,11 +149,21 @@ QT_BEGIN_NAMESPACE
in deviceExtensions. This can be relevant when integrating with native Vulkan
rendering code.
- It is expected that the desired list of instance extensions will be queried
- by calling the static function preferredInstanceExtensions() before
- initializing a QVulkanInstance. The returned list can be passed to
- QVulkanInstance::setExtensions() as-is, because unsupported extensions are
- filtered out automatically.
+ It is expected that the backend's desired list of instance extensions will
+ be queried by calling the static function preferredInstanceExtensions()
+ before initializing a QVulkanInstance. The returned list can be safely
+ passed to QVulkanInstance::setExtensions() as-is, because unsupported
+ extensions are filtered out automatically. If this is not done, certain
+ features, such as QRhi::CustomInstanceStepRate may be reported as
+ unsupported even when the Vulkan implementation on the system has support
+ for the relevant functionality.
+
+ For full functionality the QVulkanInstance needs to have API 1.1 enabled,
+ when available. This means calling QVulkanInstance::setApiVersion() with
+ 1.1 or higher whenever QVulkanInstance::supportedApiVersion() reports that
+ at least Vulkan 1.1 is supported. If this is not done, certain features,
+ such as QRhi::RenderTo3DTextureSlice may be reported as unsupported even
+ when the Vulkan implementation on the system supports Vulkan 1.1 or newer.
\section2 Working with existing Vulkan devices
@@ -549,8 +548,8 @@ bool QRhiVulkan::create(QRhi::Flags flags)
queueInfo[0].pQueuePriorities = prio;
QList<const char *> devLayers;
- if (inst->layers().contains("VK_LAYER_LUNARG_standard_validation"))
- devLayers.append("VK_LAYER_LUNARG_standard_validation");
+ if (inst->layers().contains("VK_LAYER_KHRONOS_validation"))
+ devLayers.append("VK_LAYER_KHRONOS_validation");
QVulkanInfoVector<QVulkanExtension> devExts;
uint32_t devExtCount = 0;
@@ -566,17 +565,17 @@ bool QRhiVulkan::create(QRhi::Flags flags)
QList<const char *> requestedDevExts;
requestedDevExts.append("VK_KHR_swapchain");
- debugMarkersAvailable = false;
+ caps.debugMarkers = false;
if (devExts.contains(VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) {
requestedDevExts.append(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
- debugMarkersAvailable = true;
+ caps.debugMarkers = true;
}
- vertexAttribDivisorAvailable = false;
+ caps.vertexAttribDivisor = false;
if (devExts.contains(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) {
if (inst->extensions().contains(QByteArrayLiteral("VK_KHR_get_physical_device_properties2"))) {
requestedDevExts.append(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
- vertexAttribDivisorAvailable = true;
+ caps.vertexAttribDivisor = true;
}
}
@@ -663,7 +662,7 @@ bool QRhiVulkan::create(QRhi::Flags flags)
if (queueFamilyProps.isEmpty())
queryQueueFamilyProps();
- hasCompute = (queueFamilyProps[gfxQueueFamilyIdx].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0;
+ caps.compute = (queueFamilyProps[gfxQueueFamilyIdx].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0;
timestampValidBits = queueFamilyProps[gfxQueueFamilyIdx].timestampValidBits;
ubufAlign = physDevProperties.limits.minUniformBufferOffsetAlignment;
@@ -671,7 +670,9 @@ bool QRhiVulkan::create(QRhi::Flags flags)
// elsewhere states that the minimum bufferOffset is 4...
texbufAlign = qMax<VkDeviceSize>(4, physDevProperties.limits.optimalBufferCopyOffsetAlignment);
- hasWideLines = physDevFeatures.wideLines;
+ caps.wideLines = physDevFeatures.wideLines;
+
+ caps.texture3DSliceAs2D = inst->apiVersion() >= QVersionNumber(1, 1);
if (!importedAllocator) {
VmaVulkanFunctions afuncs;
@@ -731,7 +732,7 @@ bool QRhiVulkan::create(QRhi::Flags flags)
timestampQueryPoolMap.resize(QVK_MAX_ACTIVE_TIMESTAMP_PAIRS); // 1 bit per pair
timestampQueryPoolMap.fill(false);
- if (debugMarkersAvailable) {
+ if (caps.debugMarkers) {
vkCmdDebugMarkerBegin = reinterpret_cast<PFN_vkCmdDebugMarkerBeginEXT>(f->vkGetDeviceProcAddr(dev, "vkCmdDebugMarkerBeginEXT"));
vkCmdDebugMarkerEnd = reinterpret_cast<PFN_vkCmdDebugMarkerEndEXT>(f->vkGetDeviceProcAddr(dev, "vkCmdDebugMarkerEndEXT"));
vkCmdDebugMarkerInsert = reinterpret_cast<PFN_vkCmdDebugMarkerInsertEXT>(f->vkGetDeviceProcAddr(dev, "vkCmdDebugMarkerInsertEXT"));
@@ -2944,15 +2945,18 @@ void QRhiVulkan::prepareUploadSubres(QVkTexture *texD, int layer, int level,
qsizetype copySizeBytes = 0;
qsizetype imageSizeBytes = 0;
const void *src = nullptr;
+ const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
VkBufferImageCopy copyInfo;
memset(&copyInfo, 0, sizeof(copyInfo));
copyInfo.bufferOffset = *curOfs;
copyInfo.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copyInfo.imageSubresource.mipLevel = uint32_t(level);
- copyInfo.imageSubresource.baseArrayLayer = uint32_t(layer);
+ copyInfo.imageSubresource.baseArrayLayer = is3D ? 0 : uint32_t(layer);
copyInfo.imageSubresource.layerCount = 1;
copyInfo.imageExtent.depth = 1;
+ if (is3D)
+ copyInfo.imageOffset.z = uint32_t(layer);
const QByteArray rawData = subresDesc.data();
const QPoint dp = subresDesc.destinationTopLeft();
@@ -3202,8 +3206,8 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
QVkTexture *utexD = QRHI_RES(QVkTexture, u.dst);
// batch into a single staging buffer and a single CopyBufferToImage with multiple copyInfos
VkDeviceSize stagingSize = 0;
- for (int layer = 0; layer < QRhi::MAX_LAYERS; ++layer) {
- for (int level = 0; level < QRhi::MAX_LEVELS; ++level) {
+ for (int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
+ for (int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(u.subresDesc[layer][level]))
stagingSize += subresUploadByteSize(subresDesc);
}
@@ -3240,8 +3244,8 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
continue;
}
- for (int layer = 0; layer < QRhi::MAX_LAYERS; ++layer) {
- for (int level = 0; level < QRhi::MAX_LEVELS; ++level) {
+ for (int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
+ for (int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
const QList<QRhiTextureSubresourceUploadDescription> &srd(u.subresDesc[layer][level]);
if (srd.isEmpty())
continue;
@@ -3289,25 +3293,31 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
}
QVkTexture *srcD = QRHI_RES(QVkTexture, u.src);
QVkTexture *dstD = QRHI_RES(QVkTexture, u.dst);
+ const bool srcIs3D = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
+ const bool dstIs3D = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
VkImageCopy region;
memset(&region, 0, sizeof(region));
region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.srcSubresource.mipLevel = uint32_t(u.desc.sourceLevel());
- region.srcSubresource.baseArrayLayer = uint32_t(u.desc.sourceLayer());
+ region.srcSubresource.baseArrayLayer = srcIs3D ? 0 : uint32_t(u.desc.sourceLayer());
region.srcSubresource.layerCount = 1;
region.srcOffset.x = u.desc.sourceTopLeft().x();
region.srcOffset.y = u.desc.sourceTopLeft().y();
+ if (srcIs3D)
+ region.srcOffset.z = uint32_t(u.desc.sourceLayer());
region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.dstSubresource.mipLevel = uint32_t(u.desc.destinationLevel());
- region.dstSubresource.baseArrayLayer = uint32_t(u.desc.destinationLayer());
+ region.dstSubresource.baseArrayLayer = dstIs3D ? 0 : uint32_t(u.desc.destinationLayer());
region.dstSubresource.layerCount = 1;
region.dstOffset.x = u.desc.destinationTopLeft().x();
region.dstOffset.y = u.desc.destinationTopLeft().y();
+ if (dstIs3D)
+ region.dstOffset.z = uint32_t(u.desc.destinationLayer());
const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
@@ -3337,11 +3347,13 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
QVkTexture *texD = QRHI_RES(QVkTexture, u.rb.texture());
QVkSwapChain *swapChainD = nullptr;
+ bool is3D = false;
if (texD) {
if (texD->samples > VK_SAMPLE_COUNT_1_BIT) {
qWarning("Multisample texture cannot be read back");
continue;
}
+ is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
readback.pixelSize = q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize);
readback.format = texD->m_format;
texD->lastActiveFrameSlot = currentFrameSlot;
@@ -3391,8 +3403,10 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
copyDesc.bufferOffset = 0;
copyDesc.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copyDesc.imageSubresource.mipLevel = uint32_t(u.rb.level());
- copyDesc.imageSubresource.baseArrayLayer = uint32_t(u.rb.layer());
+ copyDesc.imageSubresource.baseArrayLayer = is3D ? 0 : uint32_t(u.rb.layer());
copyDesc.imageSubresource.layerCount = 1;
+ if (is3D)
+ copyDesc.imageOffset.z = u.rb.layer();
copyDesc.imageExtent.width = uint32_t(readback.pixelSize.width());
copyDesc.imageExtent.height = uint32_t(readback.pixelSize.height());
copyDesc.imageExtent.depth = 1;
@@ -3437,6 +3451,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
QVkTexture *utexD = QRHI_RES(QVkTexture, u.dst);
Q_ASSERT(utexD->m_flags.testFlag(QRhiTexture::UsedWithGenerateMips));
const bool isCube = utexD->m_flags.testFlag(QRhiTexture::CubeMap);
+ const bool is3D = utexD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
VkImageLayout origLayout = utexD->usageState.layout;
VkAccessFlags origAccess = utexD->usageState.access;
@@ -3447,6 +3462,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
for (int layer = 0; layer < (isCube ? 6 : 1); ++layer) {
int w = utexD->m_pixelSize.width();
int h = utexD->m_pixelSize.height();
+ int depth = is3D ? utexD->m_depth : 1;
for (int level = 1; level < int(utexD->mipLevelCount); ++level) {
if (level == 1) {
subresourceBarrier(cbD, utexD->image,
@@ -3481,7 +3497,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
region.srcOffsets[1].x = qMax(1, w);
region.srcOffsets[1].y = qMax(1, h);
- region.srcOffsets[1].z = 1;
+ region.srcOffsets[1].z = qMax(1, depth);
region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.dstSubresource.mipLevel = uint32_t(level);
@@ -3490,7 +3506,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
region.dstOffsets[1].x = qMax(1, w >> 1);
region.dstOffsets[1].y = qMax(1, h >> 1);
- region.dstOffsets[1].z = 1;
+ region.dstOffsets[1].z = qMax(1, depth >> 1);
QVkCommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QVkCommandBuffer::Command::BlitImage;
@@ -3503,6 +3519,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
w >>= 1;
h >>= 1;
+ depth >>= 1;
}
if (utexD->mipLevelCount > 1) {
@@ -3580,7 +3597,7 @@ static void qrhivk_releaseTexture(const QRhiVulkan::DeferredReleaseEntry &e, VkD
vmaDestroyImage(toVmaAllocator(allocator), e.texture.image, toVmaAllocation(e.texture.allocation));
for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i)
vmaDestroyBuffer(toVmaAllocator(allocator), e.texture.stagingBuffers[i], toVmaAllocation(e.texture.stagingAllocations[i]));
- for (int i = 0; i < QRhi::MAX_LEVELS; ++i) {
+ for (int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i) {
if (e.texture.extraImageViews[i])
df->vkDestroyImageView(dev, e.texture.extraImageViews[i], nullptr);
}
@@ -4194,13 +4211,13 @@ bool QRhiVulkan::isFeatureSupported(QRhi::Feature feature) const
case QRhi::MultisampleRenderBuffer:
return true;
case QRhi::DebugMarkers:
- return debugMarkersAvailable;
+ return caps.debugMarkers;
case QRhi::Timestamps:
return timestampValidBits != 0;
case QRhi::Instancing:
return true;
case QRhi::CustomInstanceStepRate:
- return vertexAttribDivisorAvailable;
+ return caps.vertexAttribDivisor;
case QRhi::PrimitiveRestart:
return true;
case QRhi::NonDynamicUniformBuffers:
@@ -4214,9 +4231,9 @@ bool QRhiVulkan::isFeatureSupported(QRhi::Feature feature) const
case QRhi::ElementIndexUint:
return true;
case QRhi::Compute:
- return hasCompute;
+ return caps.compute;
case QRhi::WideLines:
- return hasWideLines;
+ return caps.wideLines;
case QRhi::VertexShaderPointSize:
return true;
case QRhi::BaseVertex:
@@ -4243,6 +4260,12 @@ bool QRhiVulkan::isFeatureSupported(QRhi::Feature feature) const
return true;
case QRhi::ImageDataStride:
return true;
+ case QRhi::RenderBufferImport:
+ return false;
+ case QRhi::ThreeDimensionalTextures:
+ return true;
+ case QRhi::RenderTo3DTextureSlice:
+ return caps.texture3DSliceAs2D;
default:
Q_UNREACHABLE();
return false;
@@ -4448,10 +4471,11 @@ QRhiRenderBuffer *QRhiVulkan::createRenderBuffer(QRhiRenderBuffer::Type type, co
return new QVkRenderBuffer(this, type, pixelSize, sampleCount, flags, backingFormatHint);
}
-QRhiTexture *QRhiVulkan::createTexture(QRhiTexture::Format format, const QSize &pixelSize,
+QRhiTexture *QRhiVulkan::createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize, int depth,
int sampleCount, QRhiTexture::Flags flags)
{
- return new QVkTexture(this, format, pixelSize, sampleCount, flags);
+ return new QVkTexture(this, format, pixelSize, depth, sampleCount, flags);
}
QRhiSampler *QRhiVulkan::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
@@ -4948,7 +4972,7 @@ void QRhiVulkan::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
void QRhiVulkan::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name)
{
- if (!debugMarkers || !debugMarkersAvailable)
+ if (!debugMarkers || !caps.debugMarkers)
return;
VkDebugMarkerMarkerInfoEXT marker;
@@ -4970,7 +4994,7 @@ void QRhiVulkan::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name)
void QRhiVulkan::debugMarkEnd(QRhiCommandBuffer *cb)
{
- if (!debugMarkers || !debugMarkersAvailable)
+ if (!debugMarkers || !caps.debugMarkers)
return;
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
@@ -4984,7 +5008,7 @@ void QRhiVulkan::debugMarkEnd(QRhiCommandBuffer *cb)
void QRhiVulkan::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg)
{
- if (!debugMarkers || !debugMarkersAvailable)
+ if (!debugMarkers || !caps.debugMarkers)
return;
VkDebugMarkerMarkerInfoEXT marker;
@@ -5084,7 +5108,7 @@ void QRhiVulkan::endExternal(QRhiCommandBuffer *cb)
void QRhiVulkan::setObjectName(uint64_t object, VkDebugReportObjectTypeEXT type, const QByteArray &name, int slot)
{
- if (!debugMarkers || !debugMarkersAvailable || name.isEmpty())
+ if (!debugMarkers || !caps.debugMarkers || name.isEmpty())
return;
VkDebugMarkerObjectNameInfoEXT nameInfo;
@@ -5682,6 +5706,7 @@ bool QVkRenderBuffer::create()
if (!backingTexture) {
backingTexture = QRHI_RES(QVkTexture, rhiD->createTexture(backingFormat(),
m_pixelSize,
+ 1,
m_sampleCount,
QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource));
} else {
@@ -5730,15 +5755,15 @@ QRhiTexture::Format QVkRenderBuffer::backingFormat() const
return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
}
-QVkTexture::QVkTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+QVkTexture::QVkTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
int sampleCount, Flags flags)
- : QRhiTexture(rhi, format, pixelSize, sampleCount, flags)
+ : QRhiTexture(rhi, format, pixelSize, depth, sampleCount, flags)
{
for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
stagingBuffers[i] = VK_NULL_HANDLE;
stagingAllocations[i] = nullptr;
}
- for (int i = 0; i < QRhi::MAX_LEVELS; ++i)
+ for (int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i)
perLevelImageViews[i] = VK_NULL_HANDLE;
}
@@ -5768,7 +5793,7 @@ void QVkTexture::destroy()
stagingAllocations[i] = nullptr;
}
- for (int i = 0; i < QRhi::MAX_LEVELS; ++i) {
+ for (int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i) {
e.texture.extraImageViews[i] = perLevelImageViews[i];
perLevelImageViews[i] = VK_NULL_HANDLE;
}
@@ -5803,10 +5828,11 @@ bool QVkTexture::prepareCreate(QSize *adjustedSize)
const QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool is3D = m_flags.testFlag(ThreeDimensional);
const bool hasMipMaps = m_flags.testFlag(MipMapped);
mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
- const int maxLevels = QRhi::MAX_LEVELS;
+ const int maxLevels = QRhi::MAX_MIP_LEVELS;
if (mipLevelCount > maxLevels) {
qWarning("Too many mip levels (%d, max is %d), truncating mip chain", mipLevelCount, maxLevels);
mipLevelCount = maxLevels;
@@ -5817,11 +5843,24 @@ bool QVkTexture::prepareCreate(QSize *adjustedSize)
qWarning("Cubemap texture cannot be multisample");
return false;
}
+ if (is3D) {
+ qWarning("3D texture cannot be multisample");
+ return false;
+ }
if (hasMipMaps) {
qWarning("Multisample texture cannot have mipmaps");
return false;
}
}
+ if (isCube && is3D) {
+ qWarning("Texture cannot be both cube and 3D");
+ return false;
+ }
+ m_depth = qMax(1, m_depth);
+ if (m_depth > 1 && !is3D) {
+ qWarning("Texture cannot have a depth of %d when it is not 3D", m_depth);
+ return false;
+ }
usageState.layout = VK_IMAGE_LAYOUT_PREINITIALIZED;
usageState.access = 0;
@@ -5839,12 +5878,13 @@ bool QVkTexture::finishCreate()
const auto aspectMask = aspectMaskForTextureFormat(m_format);
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool is3D = m_flags.testFlag(ThreeDimensional);
VkImageViewCreateInfo viewInfo;
memset(&viewInfo, 0, sizeof(viewInfo));
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = image;
- viewInfo.viewType = isCube ? VK_IMAGE_VIEW_TYPE_CUBE : VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.viewType = isCube ? VK_IMAGE_VIEW_TYPE_CUBE : (is3D ? VK_IMAGE_VIEW_TYPE_3D : VK_IMAGE_VIEW_TYPE_2D);
viewInfo.format = vkformat;
viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
@@ -5872,19 +5912,39 @@ bool QVkTexture::create()
if (!prepareCreate(&size))
return false;
+ QRHI_RES_RHI(QRhiVulkan);
const bool isRenderTarget = m_flags.testFlag(QRhiTexture::RenderTarget);
const bool isDepth = isDepthTextureFormat(m_format);
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool is3D = m_flags.testFlag(ThreeDimensional);
VkImageCreateInfo imageInfo;
memset(&imageInfo, 0, sizeof(imageInfo));
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
- imageInfo.flags = isCube ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
- imageInfo.imageType = VK_IMAGE_TYPE_2D;
+ imageInfo.flags = 0;
+ if (isCube)
+ imageInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
+
+ if (is3D && isRenderTarget) {
+ // This relies on a Vulkan 1.1 constant. For guaranteed proper behavior
+ // this also requires that at run time the VkInstance has at least API 1.1
+ // enabled. (though it works as expected with some Vulkan (1.2)
+ // implementations regardless of the requested API version, but f.ex. the
+ // validation layer complains when using this without enabling >=1.1)
+ if (!rhiD->caps.texture3DSliceAs2D)
+ qWarning("QRhiVulkan: Rendering to 3D texture slice may not be functional without API 1.1 on the VkInstance");
+#ifdef VK_VERSION_1_1
+ imageInfo.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
+#else
+ imageInfo.flags |= 0x00000020;
+#endif
+ }
+
+ imageInfo.imageType = is3D ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D;
imageInfo.format = vkformat;
imageInfo.extent.width = uint32_t(size.width());
imageInfo.extent.height = uint32_t(size.height());
- imageInfo.extent.depth = 1;
+ imageInfo.extent.depth = is3D ? m_depth : 1;
imageInfo.mipLevels = mipLevelCount;
imageInfo.arrayLayers = isCube ? 6 : 1;
imageInfo.samples = samples;
@@ -5909,7 +5969,6 @@ bool QVkTexture::create()
memset(&allocInfo, 0, sizeof(allocInfo));
allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
- QRHI_RES_RHI(QRhiVulkan);
VmaAllocation allocation;
VkResult err = vmaCreateImage(toVmaAllocator(rhiD->allocator), &imageInfo, &allocInfo, &image, &allocation, nullptr);
if (err != VK_SUCCESS) {
@@ -5974,12 +6033,13 @@ VkImageView QVkTexture::imageViewForLevel(int level)
const VkImageAspectFlags aspectMask = aspectMaskForTextureFormat(m_format);
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool is3D = m_flags.testFlag(ThreeDimensional);
VkImageViewCreateInfo viewInfo;
memset(&viewInfo, 0, sizeof(viewInfo));
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = image;
- viewInfo.viewType = isCube ? VK_IMAGE_VIEW_TYPE_CUBE : VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.viewType = isCube ? VK_IMAGE_VIEW_TYPE_CUBE : (is3D ? VK_IMAGE_VIEW_TYPE_3D : VK_IMAGE_VIEW_TYPE_2D);
viewInfo.format = vkformat;
viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
@@ -6654,7 +6714,7 @@ bool QVkGraphicsPipeline::create()
? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE
};
if (it->classification() == QRhiVertexInputBinding::PerInstance && it->instanceStepRate() != 1) {
- if (rhiD->vertexAttribDivisorAvailable) {
+ if (rhiD->caps.vertexAttribDivisor) {
nonOneStepRates.append({ uint32_t(bindingIndex), uint32_t(it->instanceStepRate()) });
} else {
qWarning("QRhiVulkan: Instance step rates other than 1 not supported without "
@@ -6731,7 +6791,7 @@ bool QVkGraphicsPipeline::create()
rastInfo.depthBiasConstantFactor = float(m_depthBias);
rastInfo.depthBiasSlopeFactor = m_slopeScaledDepthBias;
}
- rastInfo.lineWidth = rhiD->hasWideLines ? m_lineWidth : 1.0f;
+ rastInfo.lineWidth = rhiD->caps.wideLines ? m_lineWidth : 1.0f;
pipelineInfo.pRasterizationState = &rastInfo;
VkPipelineMultisampleStateCreateInfo msInfo;
diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h
index bb60fca42a..af647bb508 100644
--- a/src/gui/rhi/qrhivulkan_p_p.h
+++ b/src/gui/rhi/qrhivulkan_p_p.h
@@ -128,7 +128,7 @@ struct QVkRenderBuffer : public QRhiRenderBuffer
struct QVkTexture : public QRhiTexture
{
- QVkTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+ QVkTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
int sampleCount, Flags flags);
~QVkTexture();
void destroy() override;
@@ -146,7 +146,7 @@ struct QVkTexture : public QRhiTexture
QVkAlloc imageAlloc = nullptr;
VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT];
- VkImageView perLevelImageViews[QRhi::MAX_LEVELS];
+ VkImageView perLevelImageViews[QRhi::MAX_MIP_LEVELS];
bool owns = true;
struct UsageState {
// no tracking of subresource layouts (some operations can keep
@@ -676,6 +676,7 @@ public:
QRhiTexture::Format backingFormatHint) override;
QRhiTexture *createTexture(QRhiTexture::Format format,
const QSize &pixelSize,
+ int depth,
int sampleCount,
QRhiTexture::Flags flags) override;
QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
@@ -846,7 +847,6 @@ public:
int gfxQueueFamilyIdx = -1;
int gfxQueueIdx = 0;
VkQueue gfxQueue = VK_NULL_HANDLE;
- bool hasCompute = false;
quint32 timestampValidBits = 0;
bool importedAllocator = false;
QVkAllocator allocator = nullptr;
@@ -857,12 +857,9 @@ public:
VkPhysicalDeviceProperties physDevProperties;
VkDeviceSize ubufAlign;
VkDeviceSize texbufAlign;
- bool hasWideLines = false;
bool deviceLost = false;
bool releaseCachedResourcesCalledBeforeFrameStart = false;
- bool debugMarkersAvailable = false;
- bool vertexAttribDivisorAvailable = false;
PFN_vkCmdDebugMarkerBeginEXT vkCmdDebugMarkerBegin = nullptr;
PFN_vkCmdDebugMarkerEndEXT vkCmdDebugMarkerEnd = nullptr;
PFN_vkCmdDebugMarkerInsertEXT vkCmdDebugMarkerInsert = nullptr;
@@ -877,6 +874,14 @@ public:
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR;
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR;
+ struct {
+ bool compute = false;
+ bool wideLines = false;
+ bool debugMarkers = false;
+ bool vertexAttribDivisor = false;
+ bool texture3DSliceAs2D = false;
+ } caps;
+
VkPipelineCache pipelineCache = VK_NULL_HANDLE;
struct DescriptorPoolData {
DescriptorPoolData() { }
@@ -978,7 +983,7 @@ public:
QVkAlloc allocation;
VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT];
- VkImageView extraImageViews[QRhi::MAX_LEVELS];
+ VkImageView extraImageViews[QRhi::MAX_MIP_LEVELS];
} texture;
struct {
VkSampler sampler;
diff --git a/src/gui/rhi/qshader.cpp b/src/gui/rhi/qshader.cpp
index 85cb5fade7..74255dcf5c 100644
--- a/src/gui/rhi/qshader.cpp
+++ b/src/gui/rhi/qshader.cpp
@@ -558,6 +558,13 @@ bool operator==(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept
return lhs.version() == rhs.version() && lhs.flags() == rhs.flags();
}
+#ifdef Q_OS_INTEGRITY
+size_t qHash(const QShaderVersion &s, size_t seed) noexcept
+{
+ return qHashMulti(seed, s.version(), s.flags());
+}
+#endif
+
/*!
\internal
\fn bool operator!=(const QShaderVersion &lhs, const QShaderVersion &rhs)
diff --git a/src/gui/rhi/qshader_p.h b/src/gui/rhi/qshader_p.h
index d7b9892b8f..b320340229 100644
--- a/src/gui/rhi/qshader_p.h
+++ b/src/gui/rhi/qshader_p.h
@@ -59,6 +59,11 @@ QT_BEGIN_NAMESPACE
struct QShaderPrivate;
class QShaderKey;
+#ifdef Q_OS_INTEGRITY
+ class QShaderVersion;
+ size_t qHash(const QShaderVersion &, size_t = 0) noexcept;
+#endif
+
class Q_GUI_EXPORT QShaderVersion
{
public:
diff --git a/src/gui/text/freetype/qfontengine_ft.cpp b/src/gui/text/freetype/qfontengine_ft.cpp
index ae1e139251..12ba46b7ed 100644
--- a/src/gui/text/freetype/qfontengine_ft.cpp
+++ b/src/gui/text/freetype/qfontengine_ft.cpp
@@ -903,7 +903,7 @@ int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags,
static inline bool areMetricsTooLarge(const QFontEngineFT::GlyphInfo &info)
{
// false if exceeds QFontEngineFT::Glyph metrics
- return info.width > 0xFF || info.height > 0xFF;
+ return info.width > 0xFF || info.height > 0xFF || info.linearAdvance > 0x7FFF;
}
static inline void transformBoundingBox(int *left, int *top, int *right, int *bottom, FT_Matrix *matrix)
@@ -1052,7 +1052,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
// If any of the metrics are too large to fit, don't cache them
// Also, avoid integer overflow when linearAdvance is to large to fit in a signed short
- if (areMetricsTooLarge(info) || info.linearAdvance > 0x7FFF)
+ if (areMetricsTooLarge(info))
return nullptr;
g = new Glyph;
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index 4b2e257231..b6d7160cd4 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -258,8 +258,10 @@ QFontPrivate::~QFontPrivate()
if (engineData && !engineData->ref.deref())
delete engineData;
engineData = nullptr;
- if (scFont && scFont != this)
- scFont->ref.deref();
+ if (scFont && scFont != this) {
+ if (!scFont->ref.deref())
+ delete scFont;
+ }
scFont = nullptr;
}
@@ -650,8 +652,10 @@ void QFont::detach()
if (d->engineData && !d->engineData->ref.deref())
delete d->engineData;
d->engineData = nullptr;
- if (d->scFont && d->scFont != d.data())
- d->scFont->ref.deref();
+ if (d->scFont && d->scFont != d.data()) {
+ if (!d->scFont->ref.deref())
+ delete d->scFont;
+ }
d->scFont = nullptr;
return;
}
@@ -688,7 +692,7 @@ QFont::QFont()
}
/*!
- \obsolete
+ \deprecated
Constructs a font object with the specified \a family, \a
pointSize, \a weight and \a italic settings.
@@ -1179,7 +1183,7 @@ QFont::Weight QFont::weight() const
#if QT_DEPRECATED_SINCE(6, 0)
/*!
- \obsolete Use setWeight() instead.
+ \deprecated Use setWeight() instead.
Sets the weight of the font to \a legacyWeight using the legacy font
weight scale of Qt 5 and previous versions.
@@ -1199,7 +1203,7 @@ void QFont::setLegacyWeight(int legacyWeight)
}
/*!
- \obsolete Use weight() instead.
+ \deprecated Use weight() instead.
Returns the weight of the font converted to the non-standard font
weight scale used in Qt 5 and earlier versions.
@@ -2694,7 +2698,7 @@ QFont::Style QFontInfo::style() const
#if QT_DEPRECATED_SINCE(6, 0)
/*!
- \obsolete Use weight() instead.
+ \deprecated Use weight() instead.
Returns the weight of the font converted to the non-standard font
weight scale used in Qt 5 and earlier versions.
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index b7d834bc4a..3eb59e0f04 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -1239,7 +1239,7 @@ QString QFontDatabase::styleString(const QFontInfo &fontInfo)
/*!
\fn QFontDatabase::QFontDatabase()
- \obsolete Call the class methods as static functions instead.
+ \deprecated Call the class methods as static functions instead.
Creates a font database object.
*/
diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp
index 2d1f9ec161..24f2198d4e 100644
--- a/src/gui/text/qtextdocumentfragment.cpp
+++ b/src/gui/text/qtextdocumentfragment.cpp
@@ -1281,5 +1281,6 @@ QTextDocumentFragment QTextDocumentFragment::fromHtml(const QString &html, const
return res;
}
-QT_END_NAMESPACE
#endif // QT_NO_TEXTHTMLPARSER
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index 509cc7e521..f8b4474e09 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -2186,9 +2186,11 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p
painter->setRenderHint(QPainter::Antialiasing);
+ const bool marker = bl.blockFormat().marker() != QTextBlockFormat::MarkerType::NoMarker;
if (selectionFormat) {
painter->setPen(QPen(selectionFormat->foreground(), 0));
- painter->fillRect(r, selectionFormat->background());
+ if (!marker)
+ painter->fillRect(r, selectionFormat->background());
} else {
QBrush fg = charFormat.foreground();
if (fg == Qt::NoBrush)
@@ -2198,19 +2200,21 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p
QBrush brush = context.palette.brush(QPalette::Text);
- bool marker = bl.blockFormat().marker() != QTextBlockFormat::MarkerType::NoMarker;
if (marker) {
int adj = fontMetrics.lineSpacing() / 6;
r.adjust(-adj, 0, -adj, 0);
+ const QRectF outer = r.adjusted(-adj, -adj, adj, adj);
+ if (selectionFormat)
+ painter->fillRect(outer, selectionFormat->background());
if (bl.blockFormat().marker() == QTextBlockFormat::MarkerType::Checked) {
- // ### Qt6: render with QStyle / PE_IndicatorCheckBox. We don't currently
+ // ### Qt7: render with QStyle / PE_IndicatorCheckBox. We don't currently
// have access to that here, because it would be a widget dependency.
painter->setPen(QPen(painter->pen().color(), 2));
painter->drawLine(r.topLeft(), r.bottomRight());
painter->drawLine(r.topRight(), r.bottomLeft());
painter->setPen(QPen(painter->pen().color(), 0));
}
- painter->drawRect(r.adjusted(-adj, -adj, adj, adj));
+ painter->drawRect(outer);
}
switch (style) {
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index bada332316..74967aeac9 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -2011,10 +2011,15 @@ void QTextEngine::itemize() const
: formatCollection()->defaultFont().capitalization();
if (s) {
for (const auto &range : qAsConst(s->formats)) {
- if (range.start >= prevPosition && range.start < position && range.format.hasProperty(QTextFormat::FontCapitalization)) {
- itemizer.generate(prevPosition, range.start - prevPosition, capitalization);
- itemizer.generate(range.start, range.length, range.format.fontCapitalization());
- prevPosition = range.start + range.length;
+ if (range.start + range.length <= prevPosition || range.start >= position)
+ continue;
+ if (range.format.hasProperty(QTextFormat::FontCapitalization)) {
+ if (range.start > prevPosition)
+ itemizer.generate(prevPosition, range.start - prevPosition, capitalization);
+ int newStart = std::max(prevPosition, range.start);
+ int newEnd = std::min(position, range.start + range.length);
+ itemizer.generate(newStart, newEnd - newStart, range.format.fontCapitalization());
+ prevPosition = newEnd;
}
}
}
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index 80c7845410..d31e17efc3 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -1457,7 +1457,7 @@ QTextCharFormat::QTextCharFormat(const QTextFormat &fmt)
/*!
\fn void QTextCharFormat::setFontFamily(const QString &family)
- \obsolete Use setFontFamilies() instead.
+ \deprecated Use setFontFamilies() instead.
Sets the text format's font \a family.
@@ -1467,7 +1467,7 @@ QTextCharFormat::QTextCharFormat(const QTextFormat &fmt)
/*!
\fn QString QTextCharFormat::fontFamily() const
- \obsolete Use fontFamilies() instead.
+ \deprecated Use fontFamilies() instead.
Returns the text format's font family.
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index 77299f7f9c..6a9f7d3a96 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -800,12 +800,38 @@ void QTextHtmlParser::parseExclamationTag()
}
}
+QString QTextHtmlParser::parseEntity(QStringView entity)
+{
+ QChar resolved = resolveEntity(entity);
+ if (!resolved.isNull())
+ return QString(resolved);
+
+ if (entity.length() > 1 && entity.at(0) == QLatin1Char('#')) {
+ entity = entity.mid(1); // removing leading #
+
+ int base = 10;
+ bool ok = false;
+
+ if (entity.at(0).toLower() == QLatin1Char('x')) { // hex entity?
+ entity = entity.mid(1);
+ base = 16;
+ }
+
+ uint uc = entity.toUInt(&ok, base);
+ if (ok) {
+ if (uc >= 0x80 && uc < 0x80 + (sizeof(windowsLatin1ExtendedCharacters)/sizeof(windowsLatin1ExtendedCharacters[0])))
+ uc = windowsLatin1ExtendedCharacters[uc - 0x80];
+ return QStringView{QChar::fromUcs4(uc)}.toString();
+ }
+ }
+ return {};
+}
+
// parses an entity after "&", and returns it
QString QTextHtmlParser::parseEntity()
{
const int recover = pos;
int entityLen = 0;
- QStringView entity;
while (pos < len) {
QChar c = txt.at(pos++);
if (c.isSpace() || pos - recover > 9) {
@@ -816,28 +842,10 @@ QString QTextHtmlParser::parseEntity()
++entityLen;
}
if (entityLen) {
- entity = QStringView(txt).mid(recover, entityLen);
- QChar resolved = resolveEntity(entity);
- if (!resolved.isNull())
- return QString(resolved);
-
- if (entityLen > 1 && entity.at(0) == QLatin1Char('#')) {
- entity = entity.mid(1); // removing leading #
-
- int base = 10;
- bool ok = false;
-
- if (entity.at(0).toLower() == QLatin1Char('x')) { // hex entity?
- entity = entity.mid(1);
- base = 16;
- }
-
- uint uc = entity.toUInt(&ok, base);
- if (ok) {
- if (uc >= 0x80 && uc < 0x80 + (sizeof(windowsLatin1ExtendedCharacters)/sizeof(windowsLatin1ExtendedCharacters[0])))
- uc = windowsLatin1ExtendedCharacters[uc - 0x80];
- return QStringView{QChar::fromUcs4(uc)}.toString();
- }
+ const QStringView entity = QStringView(txt).mid(recover, entityLen);
+ QString parsedEntity = parseEntity(entity);
+ if (!parsedEntity.isNull()) {
+ return parsedEntity;
}
}
error:
@@ -1168,6 +1176,44 @@ void QTextHtmlParserNode::setListStyle(const QList<QCss::Value> &cssValues)
blockFormat.setProperty(QTextFormat::ListStyle, listStyle);
}
+static QTextFrameFormat::BorderStyle toQTextFrameFormat(QCss::BorderStyle cssStyle)
+{
+ switch (cssStyle) {
+ case QCss::BorderStyle::BorderStyle_Dotted:
+ return QTextFrameFormat::BorderStyle::BorderStyle_Dotted;
+ case QCss::BorderStyle::BorderStyle_Dashed:
+ return QTextFrameFormat::BorderStyle::BorderStyle_Dashed;
+ case QCss::BorderStyle::BorderStyle_Solid:
+ return QTextFrameFormat::BorderStyle::BorderStyle_Solid;
+ case QCss::BorderStyle::BorderStyle_Double:
+ return QTextFrameFormat::BorderStyle::BorderStyle_Double;
+ case QCss::BorderStyle::BorderStyle_DotDash:
+ return QTextFrameFormat::BorderStyle::BorderStyle_DotDash;
+ case QCss::BorderStyle::BorderStyle_DotDotDash:
+ return QTextFrameFormat::BorderStyle::BorderStyle_DotDotDash;
+ case QCss::BorderStyle::BorderStyle_Groove:
+ return QTextFrameFormat::BorderStyle::BorderStyle_Groove;
+ case QCss::BorderStyle::BorderStyle_Ridge:
+ return QTextFrameFormat::BorderStyle::BorderStyle_Ridge;
+ case QCss::BorderStyle::BorderStyle_Inset:
+ return QTextFrameFormat::BorderStyle::BorderStyle_Inset;
+ case QCss::BorderStyle::BorderStyle_Outset:
+ return QTextFrameFormat::BorderStyle::BorderStyle_Outset;
+ case QCss::BorderStyle::BorderStyle_Unknown:
+ case QCss::BorderStyle::BorderStyle_None:
+ case QCss::BorderStyle::BorderStyle_Native:
+ return QTextFrameFormat::BorderStyle::BorderStyle_None;
+ case QCss::BorderStyle::NumKnownBorderStyles:
+ break;
+ // Intentionally no "default" to allow a compiler warning when extending the enum
+ // without updating this here. clang gives such a warning.
+ }
+ // Must not happen, intentionally trigger undefined behavior which sanitizers will detect.
+ // Having all cases covered in switch is not sufficient:
+ // MSVC would warn when there is no "default".
+ return static_cast<QTextFrameFormat::BorderStyle>(-1);
+}
+
void QTextHtmlParserNode::applyCssDeclarations(const QList<QCss::Declaration> &declarations, const QTextDocument *resourceProvider)
{
QCss::ValueExtractor extractor(declarations);
@@ -1187,7 +1233,7 @@ void QTextHtmlParserNode::applyCssDeclarations(const QList<QCss::Declaration> &d
// because tableBorder is not relevant for cells.
extractor.extractBorder(cssBorder, tableCellBorderBrush, cssStyles, cssRadii);
for (int i = 0; i < 4; ++i) {
- tableCellBorderStyle[i] = static_cast<QTextFrameFormat::BorderStyle>(cssStyles[i] - 1);
+ tableCellBorderStyle[i] = toQTextFrameFormat(cssStyles[i]);
tableCellBorder[i] = static_cast<qreal>(cssBorder[i]);
}
}
diff --git a/src/gui/text/qtexthtmlparser_p.h b/src/gui/text/qtexthtmlparser_p.h
index b99f73fafb..06bbc032a8 100644
--- a/src/gui/text/qtexthtmlparser_p.h
+++ b/src/gui/text/qtexthtmlparser_p.h
@@ -310,6 +310,9 @@ public:
void parse(const QString &text, const QTextDocument *resourceProvider);
static int lookupElement(const QString &element);
+
+ Q_GUI_EXPORT static QString parseEntity(QStringView entity);
+
protected:
QTextHtmlParserNode *newNode(int parent);
QList<QTextHtmlParserNode *> nodes;
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 48f26f8665..1ce35c2ff2 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -1937,7 +1937,8 @@ void QTextLine::layout_helper(int maxGlyphs)
if (lbh.currentPosition >= eng->layoutData->string.length()
|| isBreakableSpace
- || attributes[lbh.currentPosition].lineBreak) {
+ || attributes[lbh.currentPosition].lineBreak
+ || lbh.tmpData.textWidth >= QFIXED_MAX) {