diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2010-06-16 20:52:29 -0700 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2010-06-16 20:52:29 -0700 |
commit | 06681f30890c10fb1acb01d8c6a3a07a4d651eae (patch) | |
tree | 5031a884bda5004c0c493b3f54447066c33cf85c | |
parent | e53e85ca0336b3e1bd309329d013cd6c161def02 (diff) |
checkpoint a bunch of random wayland work
- remove a bunch of unnecessary files
- create a wayland specific gl surface file (though not sure if we want it yet)
- add (broken) swap buffers code
Builds and ends up in the painting code now with the analogclock widget.
32 files changed, 1007 insertions, 4039 deletions
diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index e6ea198b58..13127cdef8 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -48,6 +48,10 @@ #include "qegl_p.h" #include "qeglcontext_p.h" +#ifdef Q_WS_WAYLAND +#include <private/qt_wayland_p.h> +#endif + QT_BEGIN_NAMESPACE @@ -90,7 +94,11 @@ QEglContext::QEglContext() : apiType(QEgl::OpenGL) , ctx(EGL_NO_CONTEXT) , cfg(QEGL_NO_CONFIG) +#ifndef Q_WS_WAYLAND , currentSurface(EGL_NO_SURFACE) +#else + , currentImage(EGL_NO_IMAGE_KHR) +#endif , current(false) , ownsContext(true) , sharing(false) @@ -347,11 +355,12 @@ bool QEglContext::chooseConfig(const QEglProperties& properties, QEgl::PixelForm return cfg != QEGL_NO_CONFIG; } +#ifndef Q_WS_WAYLAND EGLSurface QEglContext::createSurface(QPaintDevice* device, const QEglProperties *properties) { return QEgl::createSurface(device, cfg, properties); } - +#endif // Create the EGLContext. bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties *properties) @@ -403,6 +412,7 @@ bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties return true; } +#ifndef Q_WS_WAYLAND // Destroy an EGL surface object. If it was current on this context // then call doneCurrent() for it first. void QEglContext::destroySurface(EGLSurface surface) @@ -413,6 +423,7 @@ void QEglContext::destroySurface(EGLSurface surface) eglDestroySurface(display(), surface); } } +#endif // Destroy the context. Note: this does not destroy the surface. void QEglContext::destroyContext() @@ -423,6 +434,7 @@ void QEglContext::destroyContext() cfg = 0; } +#ifndef Q_WS_WAYLAND bool QEglContext::makeCurrent(EGLSurface surface) { if (ctx == EGL_NO_CONTEXT) { @@ -463,6 +475,7 @@ bool QEglContext::makeCurrent(EGLSurface surface) qWarning() << "QEglContext::makeCurrent(" << surface << "):" << QEgl::errorString(); return ok; } +#endif bool QEglContext::doneCurrent() { @@ -472,7 +485,11 @@ bool QEglContext::doneCurrent() return false; current = false; +#ifndef Q_WS_WAYLAND currentSurface = EGL_NO_SURFACE; +#else + currentImage = EGL_NO_IMAGE_KHR; +#endif setCurrentContext(apiType, 0); // We need to select the correct API before calling eglMakeCurrent() @@ -532,7 +549,7 @@ typedef EGLBoolean (EGLAPIENTRY *_eglDestroyImageKHR)(EGLDisplay, EGLImageKHR); static _eglCreateImageKHR qt_eglCreateImageKHR = 0; static _eglDestroyImageKHR qt_eglDestroyImageKHR = 0; - +#ifndef Q_WS_WAYLAND EGLDisplay QEgl::display() { static EGLDisplay dpy = EGL_NO_DISPLAY; @@ -564,6 +581,37 @@ EGLDisplay QEgl::display() return dpy; } +#else +EGLDisplay QEgl::display() +{ + static EGLDisplay dpy = EGL_NO_DISPLAY; + if (!QEglContextTracker::displayOpened()) { + dpy = qWayland->egl_display; + if (!dpy) + return EGL_NO_DISPLAY; + + QEglContextTracker::setDisplayOpened(); + + // Resolve the egl extension function pointers: + if (QEgl::hasExtension("EGL_KHR_image") || + QEgl::hasExtension("EGL_KHR_image_base")) { + qt_eglCreateImageKHR = (_eglCreateImageKHR) + eglGetProcAddress("eglCreateImageKHR"); + qt_eglDestroyImageKHR = (_eglDestroyImageKHR) + eglGetProcAddress("eglDestroyImageKHR"); + } + qt_eglCreateDRMImageMESA = (_eglCreateDRMImageMESA) + eglGetProcAddress("eglCreateDRMImageMESA"); + qt_glEGLImageTargetTexture2DOES = (_glEGLImageTargetTexture2DOES) + eglGetProcAddress("glEGLImageTargetTexture2DOES"); + qt_glEGLImageTargetRenderbufferStorageOES = + (_glEGLImageTargetRenderbufferStorageOES) + eglGetProcAddress("glEGLImageTargetRenderbufferStorageOES"); + } + + return dpy; +} +#endif EGLImageKHR QEgl::eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) { @@ -591,8 +639,7 @@ EGLBoolean QEgl::eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) return 0; } - -#ifndef Q_WS_X11 +#if !defined(Q_WS_X11) && !defined(Q_WS_WAYLAND) EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *properties) { // Create the native drawable for the paint device. diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h index 4fc13386ce..c1d54c739d 100644 --- a/src/gui/egl/qegl_p.h +++ b/src/gui/egl/qegl_p.h @@ -58,6 +58,7 @@ QT_BEGIN_INCLUDE_NAMESPACE #ifndef QT_NO_EGL #if defined(QT_OPENGL_ES_2) # include <GLES2/gl2.h> +typedef void* GLeglImageOES; #endif #if defined(QT_GLES_EGL) @@ -171,6 +172,18 @@ typedef void *EGLImageKHR; #define EGL_KHR_image_pixmap #endif +#ifdef Q_WS_WAYLAND +typedef EGLImageKHR (EGLAPIENTRY *_eglCreateDRMImageMESA)(EGLDisplay dpy, const EGLint *attrib_list); +typedef void (GL_APIENTRY *_glEGLImageTargetTexture2DOES)(GLenum target, GLeglImageOES image); +typedef void (GL_APIENTRY *_glEGLImageTargetRenderbufferStorageOES)(GLenum target, GLeglImageOES image); +typedef EGLBoolean (EGLAPIENTRY *_eglExportDRMImageMESA)(EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride); + +extern _eglCreateDRMImageMESA qt_eglCreateDRMImageMESA; +extern _glEGLImageTargetTexture2DOES qt_glEGLImageTargetTexture2DOES; +extern _glEGLImageTargetRenderbufferStorageOES qt_glEGLImageTargetRenderbufferStorageOES; +extern _eglExportDRMImageMESA qt_eglExportDRMImageMESA; + +#endif class QEglProperties; @@ -202,7 +215,12 @@ namespace QEgl { Q_GUI_EXPORT EGLConfig defaultConfig(int devType, API api, ConfigOptions options); Q_GUI_EXPORT EGLConfig chooseConfig(const QEglProperties* configAttribs, QEgl::PixelFormatMatch match = QEgl::ExactPixelFormat); +#ifndef Q_WS_WAYLAND Q_GUI_EXPORT EGLSurface createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *surfaceAttribs = 0); +#else + Q_GUI_EXPORT EGLImageKHR createImage(QPaintDevice *device, EGLConfig cfg, + const QEglProperties *attribs = 0); +#endif Q_GUI_EXPORT void dumpAllConfigs(); @@ -224,6 +242,15 @@ namespace QEgl { // Extension functions Q_GUI_EXPORT EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); Q_GUI_EXPORT EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img); +#ifdef Q_WS_WAYLAND + Q_GUI_EXPORT EGLImageKHR eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attrib_list); + Q_GUI_EXPORT void glEGLImageTargetTexture(GLenum target, GLeglImageOES image); + Q_GUI_EXPORT void glEGLImageTargetRenderbufferStorage(GLenum target, GLeglImageOES image); + Q_GUI_EXPORT EGLBoolean eglExportDRMImageMESA(EGLDisplay dpy, + EGLImageKHR image, + EGLint *name, EGLint *handle, + EGLint *stride); +#endif #ifdef Q_WS_X11 Q_GUI_EXPORT VisualID getCompatibleVisualId(EGLConfig config); diff --git a/src/gui/egl/qegl_wayland.cpp b/src/gui/egl/qegl_wayland.cpp index 0f3917a10f..ff0b830327 100644 --- a/src/gui/egl/qegl_wayland.cpp +++ b/src/gui/egl/qegl_wayland.cpp @@ -39,20 +39,66 @@ ** ****************************************************************************/ +#include <QDebug> #include <QtGui/qpaintdevice.h> #include <QtGui/qpixmap.h> #include <QtGui/qwidget.h> +#include <private/qpixmapdata_p.h> +#include <private/qt_wayland_p.h> #include "qegl_p.h" #include "qeglcontext_p.h" -#if !defined(QT_NO_EGL) - #include <qapplication.h> #include <qdesktopwidget.h> QT_BEGIN_NAMESPACE +_eglCreateDRMImageMESA qt_eglCreateDRMImageMESA = 0; +_glEGLImageTargetTexture2DOES qt_glEGLImageTargetTexture2DOES = 0; +_glEGLImageTargetRenderbufferStorageOES qt_glEGLImageTargetRenderbufferStorageOES = 0; +_eglExportDRMImageMESA qt_eglExportDRMImageMESA = 0; + +bool QEglContext::makeCurrent(EGLImageKHR img) +{ + if (ctx == EGL_NO_CONTEXT) { + qWarning() << "QEglContext::makeCurrent(): Cannot make invalid context current"; + return false; + } + + currentImage = img; + current = true; + setCurrentContext(apiType, this); + + // Force the right API to be bound before making the context current. + // The EGL implementation should be able to figure this out from ctx, + // but some systems require the API to be explicitly set anyway. +#ifdef EGL_OPENGL_ES_API + if (apiType == QEgl::OpenGL) + eglBindAPI(EGL_OPENGL_ES_API); +#endif +#ifdef EGL_OPENVG_API + if (apiType == QEgl::OpenVG) + eglBindAPI(EGL_OPENVG_API); +#endif + + bool ok = eglMakeCurrent(QEgl::display(), NULL, NULL, ctx); + if (!ok) + qWarning() << "QEglContext::makeCurrent(" << img << "):" << + QEgl::errorString(); + + glGenFramebuffers(1, &wl_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, wl_fbo); + + glGenRenderbuffers(1, &wl_color_rbo); + glBindRenderbuffer(GL_RENDERBUFFER, wl_color_rbo); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, wl_color_rbo); + QEgl::glEGLImageTargetRenderbufferStorage(GL_RENDERBUFFER, currentImage); + + return ok; +} + // Set pixel format and other properties based on a paint device. void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev) { @@ -64,6 +110,53 @@ void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev) setPixelFormat(static_cast<QImage *>(dev)->format()); } +void QEglProperties::setPixelFormat(QImage::Format pixelFormat) +{ + switch (pixelFormat) { + case QImage::Format_RGB32: + case QImage::Format_RGB888: + mesaFormat = EGL_IMAGE_FORMAT_ARGB8888_MESA; + break; + case QImage::Format_ARGB32: + case QImage::Format_ARGB32_Premultiplied: + mesaFormat = EGL_IMAGE_FORMAT_ARGB8888_MESA; + break; + case QImage::Format_RGB16: + mesaFormat = EGL_IMAGE_FORMAT_ARGB8888_MESA; + break; + case QImage::Format_ARGB8565_Premultiplied: + mesaFormat = EGL_IMAGE_FORMAT_ARGB8888_MESA; + break; + case QImage::Format_RGB666: + mesaFormat = EGL_IMAGE_FORMAT_ARGB8888_MESA; + break; + case QImage::Format_ARGB6666_Premultiplied: + mesaFormat = EGL_IMAGE_FORMAT_ARGB8888_MESA; + break; + case QImage::Format_RGB555: + mesaFormat = EGL_IMAGE_FORMAT_ARGB8888_MESA; + break; + case QImage::Format_ARGB8555_Premultiplied: + mesaFormat = EGL_IMAGE_FORMAT_ARGB8888_MESA; + break; + case QImage::Format_RGB444: + mesaFormat = EGL_IMAGE_FORMAT_ARGB8888_MESA; + break; + case QImage::Format_ARGB4444_Premultiplied: + mesaFormat = EGL_IMAGE_FORMAT_ARGB8888_MESA; + break; + default: + qWarning() << "QEglProperties::setPixelFormat(): Unsupported pixel format"; + mesaFormat = EGL_IMAGE_FORMAT_ARGB8888_MESA; + break; + } +} + +EGLint QEglProperties::mesaPixelFormat() const +{ + return mesaFormat; +} + EGLNativeDisplayType QEgl::nativeDisplay() { return EGLNativeDisplayType(EGL_DEFAULT_DISPLAY); @@ -71,16 +164,99 @@ EGLNativeDisplayType QEgl::nativeDisplay() EGLNativeWindowType QEgl::nativeWindow(QWidget* widget) { + qFatal("%s should not be called\n", __func__); return (EGLNativeWindowType)(widget->winId()); } EGLNativePixmapType QEgl::nativePixmap(QPixmap*) { - qWarning("QEgl: EGL pixmap surfaces not supported on QWS"); + qFatal("%s should not be called\n", __func__); return (EGLNativePixmapType)0; } +EGLImageKHR QEgl::createImage(QPaintDevice *device, EGLConfig cfg, + const QEglProperties *properties) +{ + int devType = device->devType(); + EGLImageKHR img; + const EGLint format = properties ? properties->mesaPixelFormat() : + EGL_IMAGE_FORMAT_ARGB8888_MESA; + EGLint attribs[] = { + EGL_WIDTH, 0, + EGL_HEIGHT, 0, + EGL_IMAGE_FORMAT_MESA, 0, + EGL_IMAGE_USE_MESA, EGL_IMAGE_USE_SHARE_MESA | + EGL_IMAGE_USE_SCANOUT_MESA, + EGL_NONE, + }; -QT_END_NAMESPACE + attribs[5] = format; + + if (devType == QInternal::Pixmap) { + QPixmapData *pmd = static_cast<QPixmap*>(device)->data_ptr().data(); + attribs[1] = pmd->width(); + attribs[3] = pmd->height(); + } else if (devType == QInternal::Widget) { + QWidget *widget = static_cast<QWidget*>(device); + attribs[1] = widget->width(); + attribs[3] = widget->height(); + } else { + qWarning("can only create pixmap and widget images\n"); + return EGL_NO_SURFACE; + } + + img = QEgl::eglCreateDRMImageMESA(qWayland->egl_display, attribs); + if (!img) { + qWarning("failed to create EGL image: %d\n", eglGetError()); + return NULL; + } + return img; +} -#endif // !QT_NO_EGL +EGLImageKHR QEgl::eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attrib_list) +{ + if (qt_eglCreateDRMImageMESA) + return qt_eglCreateDRMImageMESA(dpy, attrib_list); + + QEgl::display(); + + if (qt_eglCreateDRMImageMESA) + return qt_eglCreateDRMImageMESA(dpy, attrib_list); +} + +void QEgl::glEGLImageTargetTexture(GLenum target, GLeglImageOES image) +{ + if (qt_glEGLImageTargetTexture2DOES) + return qt_glEGLImageTargetTexture2DOES(target, image); + + QEgl::display(); + + if (qt_glEGLImageTargetTexture2DOES) + return qt_glEGLImageTargetTexture2DOES(target, image); +} + +void QEgl::glEGLImageTargetRenderbufferStorage(GLenum target, GLeglImageOES image) +{ + if (qt_glEGLImageTargetRenderbufferStorageOES) + return qt_glEGLImageTargetRenderbufferStorageOES(target, image); + + QEgl::display(); + + if (qt_glEGLImageTargetRenderbufferStorageOES) + return qt_glEGLImageTargetRenderbufferStorageOES(target, image); +} + +EGLBoolean QEgl::eglExportDRMImageMESA(EGLDisplay dpy, EGLImageKHR image, + EGLint *name, EGLint *handle, + EGLint *stride) +{ + if (qt_eglExportDRMImageMESA) + return qt_eglExportDRMImageMESA(dpy, image, name, handle, stride); + + QEgl::display(); + + if (qt_eglExportDRMImageMESA) + return qt_eglExportDRMImageMESA(dpy, image, name, handle, stride); +} + +QT_END_NAMESPACE diff --git a/src/gui/egl/qeglcontext_p.h b/src/gui/egl/qeglcontext_p.h index ccde00d91c..85d3982c4d 100644 --- a/src/gui/egl/qeglcontext_p.h +++ b/src/gui/egl/qeglcontext_p.h @@ -80,7 +80,11 @@ public: EGLSurface createSurface(QPaintDevice *device, const QEglProperties *properties = 0); void destroySurface(EGLSurface surface); +#ifndef Q_WS_WAYLAND bool makeCurrent(EGLSurface surface); +#else + bool makeCurrent(EGLImageKHR img); +#endif bool doneCurrent(); bool lazyDoneCurrent(); bool swapBuffers(EGLSurface surface); @@ -99,7 +103,18 @@ private: QEgl::API apiType; EGLContext ctx; EGLConfig cfg; +#ifndef Q_WS_WAYLAND EGLSurface currentSurface; +#else + EGLImageKHR currentImage; + /* + * Wayland doesn't have a "native" drawing API aside from EGL, so we + * have to use an EGL image and a framebuffer object for our rendering + * needs + */ + GLuint wl_color_rbo; + GLuint wl_fbo; +#endif bool current; bool ownsContext; bool sharing; diff --git a/src/gui/egl/qeglproperties.cpp b/src/gui/egl/qeglproperties.cpp index 3638de5b37..914e5c110c 100644 --- a/src/gui/egl/qeglproperties.cpp +++ b/src/gui/egl/qeglproperties.cpp @@ -177,6 +177,7 @@ void QEglProperties::setDeviceType(int devType) // Sets the red, green, blue, and alpha sizes based on a pixel format. // Normally used to match a configuration request to the screen format. +#ifndef Q_WS_WAYLAND void QEglProperties::setPixelFormat(QImage::Format pixelFormat) { int red, green, blue, alpha; @@ -212,6 +213,7 @@ void QEglProperties::setPixelFormat(QImage::Format pixelFormat) setValue(EGL_BLUE_SIZE, blue); setValue(EGL_ALPHA_SIZE, alpha); } +#endif void QEglProperties::setRenderableType(QEgl::API api) { diff --git a/src/gui/egl/qeglproperties_p.h b/src/gui/egl/qeglproperties_p.h index b1f9642c7b..a77441bef2 100644 --- a/src/gui/egl/qeglproperties_p.h +++ b/src/gui/egl/qeglproperties_p.h @@ -82,6 +82,9 @@ public: #ifdef Q_WS_X11 void setVisualFormat(const QX11Info *xinfo); #endif +#ifdef Q_WS_WAYLAND + EGLint mesaPixelFormat() const; +#endif void setDeviceType(int devType); void setPaintDeviceFormat(QPaintDevice *dev); void setRenderableType(QEgl::API api); @@ -92,6 +95,9 @@ public: private: QVarLengthArray<int> props; +#ifdef Q_WS_WAYLAND + EGLint mesaFormat; +#endif }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qapplication_wayland.cpp b/src/gui/kernel/qapplication_wayland.cpp index 517e87a1a1..5101d27fa9 100644 --- a/src/gui/kernel/qapplication_wayland.cpp +++ b/src/gui/kernel/qapplication_wayland.cpp @@ -74,7 +74,6 @@ #include "private/qwidget_p.h" #include "private/qbackingstore_p.h" -#include "private/qwindowsurface_wayland_p.h" #include "private/qfont_p.h" #include <unistd.h> @@ -118,76 +117,6 @@ void QApplicationPrivate::initializeWidgetPaletteHash() { } -static void -display_handle_device(void *data, - struct wl_compositor *compositor, - const char *device) -{ - struct QWaylandData *d = (struct QWaylandData *)data; - - d->device_name = strdup(device); -} - -static void -display_handle_acknowledge(void *data, - struct wl_compositor *compositor, - uint32_t key, uint32_t frame) -{ - struct QWaylandData *d = (struct QWaylandData *)data; - - return; -} - -static void -display_handle_frame(void *data, - struct wl_compositor *compositor, - uint32_t frame, uint32_t timestamp) -{ - struct QWaylandData *d = (struct QWaylandData *)data; - - return; -} - -static const struct wl_compositor_listener compositor_listener = { - display_handle_device, - display_handle_acknowledge, - display_handle_frame, -}; - -static void -display_handle_geometry(void *data, - struct wl_output *output, - int32_t width, int32_t height) -{ - struct QWaylandData *d = (struct QWaylandData *)data; - - d->x = 0; - d->y = 0; - d->width = width; - d->height = height; -} - -static const struct wl_output_listener output_listener = { - display_handle_geometry, -}; - -static void -display_handle_global(struct wl_display *display, struct wl_object *object, - void *data) -{ - struct QWaylandData *d = (struct QWaylandData *)data; - - if (wl_object_implements(object, "compositor", 1)) { - d->compositor = (struct wl_compositor *) object; - wl_compositor_add_listener(d->compositor, &compositor_listener, d); - } else if (wl_object_implements(object, "output", 1)) { - d->output = (struct wl_output *) object; - wl_output_add_listener(d->output, &output_listener, d); - } else if (wl_object_implements(object, "input_device", 1)) { - d->input_device =(struct wl_input_device *) object; - } -} - void qt_init(QApplicationPrivate *priv, int type) { PFNEGLGETTYPEDDISPLAYMESA get_typed_display_mesa; @@ -212,13 +141,11 @@ void qt_init(QApplicationPrivate *priv, int type) EGL_NONE }; - qWayland = new QWaylandData; - if (!qWayland) - qFatal("couldn't create Wayland connection, out of memory\n"); - if (!qt_is_gui_used) return; + // FIXME: share compositor connection across threads + get_typed_display_mesa = (PFNEGLGETTYPEDDISPLAYMESA)eglGetProcAddress("eglGetTypedDisplayMESA"); if (!get_typed_display_mesa) @@ -267,19 +194,13 @@ void qt_init(QApplicationPrivate *priv, int type) return; } - /* Set up listener so we'll catch all events. */ - if (!wl_display_add_global_listener(d, display_handle_global, qWayland)) { - close(fd); - wl_display_destroy(d); - qFatal("failed to add compositor listener\n"); - } - - /* Process connection events. */ - wl_display_iterate(d, WL_DISPLAY_READABLE); + qWayland = new QWaylandData; + if (!qWayland) + qFatal("couldn't create Wayland connection, out of memory\n"); qWayland->dri_fd = fd; - qWayland->display = d; - qWayland->dpy = dpy; + qWayland->wl_display = d; + qWayland->egl_display = dpy; qWayland->ctx = ctx; priv->inputContext = 0; @@ -306,7 +227,6 @@ void qt_init(QApplicationPrivate *priv, int type) } qApp->setObjectName(appName); - } /***************************************************************************** diff --git a/src/gui/kernel/qeventdispatcher_glib_wayland.cpp b/src/gui/kernel/qeventdispatcher_glib_wayland.cpp index 1ccc2e2107..bcfb9d3340 100644 --- a/src/gui/kernel/qeventdispatcher_glib_wayland.cpp +++ b/src/gui/kernel/qeventdispatcher_glib_wayland.cpp @@ -49,17 +49,370 @@ #include "qt_wayland_p.h" #include <glib.h> +#include <linux/input.h> QT_BEGIN_NAMESPACE struct GWaylandEventSource { GSource source; + GPollFD pfd; QEventLoop::ProcessEventsFlags flags; QWaylandEventDispatcherGlib *q; QWaylandEventDispatcherGlibPrivate *d; + uint32_t mask; }; +enum { + WINDOW_MODIFIER_SHIFT = 0x01, + WINDOW_MODIFIER_ALT = 0x02, + WINDOW_MODIFIER_CONTROL = 0x04, +}; + +enum window_state { + WINDOW_STABLE, + WINDOW_MOVING, + WINDOW_RESIZING_UPPER_LEFT, + WINDOW_RESIZING_UPPER_RIGHT, + WINDOW_RESIZING_LOWER_LEFT, + WINDOW_RESIZING_LOWER_RIGHT +}; + +enum location { + LOCATION_INTERIOR, + LOCATION_UPPER_LEFT, + LOCATION_UPPER_RIGHT, + LOCATION_LOWER_LEFT, + LOCATION_LOWER_RIGHT, + LOCATION_OUTSIDE +}; + +#if 0 +static void +window_handle_motion(void *data, struct wl_input_device *input_device, + int32_t x, int32_t y, int32_t sx, int32_t sy) +{ + struct QWaylandData *d = (QWaylandData *)data; + + switch (window->state) { + case WINDOW_MOVING: + if (window->fullscreen) + break; + if (window->grab_device != input_device) + break; + window->allocation.x = window->drag_x + x; + window->allocation.y = window->drag_y + y; + wl_surface_map(window->surface, + window->allocation.x - window->margin, + window->allocation.y - window->margin, + window->allocation.width, + window->allocation.height); + wl_compositor_commit(window->display->compositor, 1); + break; + case WINDOW_RESIZING_LOWER_RIGHT: + if (window->fullscreen) + break; + if (window->grab_device != input_device) + break; + window->allocation.width = window->drag_x + x; + window->allocation.height = window->drag_y + y; + + if (window->resize_handler) + (*d->resize_handler)(window, + window->user_data); + + break; + } +} + +static void window_handle_button(void *data, struct wl_input_device *input_device, + uint32_t button, uint32_t state, + int32_t x, int32_t y, int32_t sx, int32_t sy) +{ + struct QWaylandData *d = (QWaylandData *)data; + int32_t left = window->allocation.x; + int32_t right = window->allocation.x + + window->allocation.width - window->margin * 2; + int32_t top = window->allocation.y; + int32_t bottom = window->allocation.y + + window->allocation.height - window->margin * 2; + int grip_size = 16, location; + + if (right - grip_size <= x && x < right && + bottom - grip_size <= y && y < bottom) { + location = LOCATION_LOWER_RIGHT; + } else if (left <= x && x < right && top <= y && y < bottom) { + location = LOCATION_INTERIOR; + } else { + location = LOCATION_OUTSIDE; + } + + if (button == BTN_LEFT && state == 1) { + switch (location) { + case LOCATION_INTERIOR: + window->drag_x = window->allocation.x - x; + window->drag_y = window->allocation.y - y; + window->state = WINDOW_MOVING; + window->grab_device = input_device; + break; + case LOCATION_LOWER_RIGHT: + window->drag_x = window->allocation.width - x; + window->drag_y = window->allocation.height - y; + window->state = WINDOW_RESIZING_LOWER_RIGHT; + window->grab_device = input_device; + break; + default: + window->state = WINDOW_STABLE; + break; + } + } else if (button == BTN_LEFT && + state == 0 && window->grab_device == input_device) { + window->state = WINDOW_STABLE; + } +} + +struct key { + uint32_t code[4]; +} evdev_keymap[] = { + { { 0, 0 } }, /* 0 */ + { { 0x1b, 0x1b } }, + { { '1', '!' } }, + { { '2', '@' } }, + { { '3', '#' } }, + { { '4', '$' } }, + { { '5', '%' } }, + { { '6', '^' } }, + { { '7', '&' } }, + { { '8', '*' } }, + { { '9', '(' } }, + { { '0', ')' } }, + { { '-', '_' } }, + { { '=', '+' } }, + { { '\b', '\b' } }, + { { '\t', '\t' } }, + + { { 'q', 'Q', 0x11 } }, /* 16 */ + { { 'w', 'W', 0x17 } }, + { { 'e', 'E', 0x05 } }, + { { 'r', 'R', 0x12 } }, + { { 't', 'T', 0x14 } }, + { { 'y', 'Y', 0x19 } }, + { { 'u', 'U', 0x15 } }, + { { 'i', 'I', 0x09 } }, + { { 'o', 'O', 0x0f } }, + { { 'p', 'P', 0x10 } }, + { { '[', '{', 0x1b } }, + { { ']', '}', 0x1d } }, + { { '\n', '\n' } }, + { { 0, 0 } }, + { { 'a', 'A', 0x01} }, + { { 's', 'S', 0x13 } }, + + { { 'd', 'D', 0x04 } }, /* 32 */ + { { 'f', 'F', 0x06 } }, + { { 'g', 'G', 0x07 } }, + { { 'h', 'H', 0x08 } }, + { { 'j', 'J', 0x0a } }, + { { 'k', 'K', 0x0b } }, + { { 'l', 'L', 0x0c } }, + { { ';', ':' } }, + { { '\'', '"' } }, + { { '`', '~' } }, + { { 0, 0 } }, + { { '\\', '|', 0x1c } }, + { { 'z', 'Z', 0x1a } }, + { { 'x', 'X', 0x18 } }, + { { 'c', 'C', 0x03 } }, + { { 'v', 'V', 0x16 } }, + + { { 'b', 'B', 0x02 } }, /* 48 */ + { { 'n', 'N', 0x0e } }, + { { 'm', 'M', 0x0d } }, + { { ',', '<' } }, + { { '.', '>' } }, + { { '/', '?' } }, + { { 0, 0 } }, + { { '*', '*' } }, + { { 0, 0 } }, + { { ' ', ' ' } }, + { { 0, 0 } } + + /* 59 */ +}; + +#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) + +static void +window_update_modifiers(struct QWaylandData *d, uint32_t key, uint32_t state) +{ + uint32_t mod = 0; + + switch (key) { + case KEY_LEFTSHIFT: + case KEY_RIGHTSHIFT: + mod = WINDOW_MODIFIER_SHIFT; + break; + case KEY_LEFTCTRL: + case KEY_RIGHTCTRL: + mod = WINDOW_MODIFIER_CONTROL; + break; + case KEY_LEFTALT: + case KEY_RIGHTALT: + mod = WINDOW_MODIFIER_ALT; + break; + } + + if (state) + window->modifiers |= mod; + else + window->modifiers &= ~mod; +} + +static void +window_handle_key(void *data, struct wl_input_device *input_device, + uint32_t key, uint32_t state) +{ + struct QWaylandData *d = (QWaylandData *)data; + uint32_t unicode = 0; + + if (window->keyboard_device != input_device) + return; + + window_update_modifiers(window, key, state); + + if (key < ARRAY_LENGTH(evdev_keymap)) { + if (window->modifiers & WINDOW_MODIFIER_CONTROL) + unicode = evdev_keymap[key].code[2]; + else if (window->modifiers & WINDOW_MODIFIER_SHIFT) + unicode = evdev_keymap[key].code[1]; + else + unicode = evdev_keymap[key].code[0]; + } + + if (window->key_handler) + (*d->key_handler)(window, key, unicode, + state, window->modifiers, window->user_data); +} + +static void +window_handle_pointer_focus(void *data, + struct wl_input_device *input_device, + struct wl_surface *surface) +{ +} + +static void +window_handle_keyboard_focus(void *data, + struct wl_input_device *input_device, + struct wl_surface *surface, + struct wl_array *keys) +{ + struct QWaylandData *d = (QWaylandData *)data; + uint32_t *k, *end; + + if (window->keyboard_device == input_device && surface != window->surface) + window->keyboard_device = NULL; + else if (window->keyboard_device == NULL && surface == window->surface) + window->keyboard_device = input_device; + else + return; + + if (window->keyboard_device) { + end = (uint32_t *)keys->data + keys->size; + for (k = (uint32_t *)keys->data; k < end; k++) + window_update_modifiers(window, *k, 1); + } else { + window->modifiers = 0; + } + + if (window->keyboard_focus_handler) + (*d->keyboard_focus_handler)(window, + window->keyboard_device, + window->user_data); +} + +static const struct wl_input_device_listener input_device_listener = { + window_handle_motion, + window_handle_button, + window_handle_key, + window_handle_pointer_focus, + window_handle_keyboard_focus, +}; +#endif + +static void +display_handle_device(void *data, + struct wl_compositor *compositor, + const char *device) +{ + struct QWaylandData *d = (struct QWaylandData *)data; + + d->device_name = strdup(device); +} + +static void +display_handle_acknowledge(void *data, + struct wl_compositor *compositor, + uint32_t key, uint32_t frame) +{ + struct QWaylandData *d = (struct QWaylandData *)data; + + return; +} + +static void +display_handle_frame(void *data, + struct wl_compositor *compositor, + uint32_t frame, uint32_t timestamp) +{ + struct QWaylandData *d = (struct QWaylandData *)data; + + qWarning("%s\n", __func__); + + return; +} + +static const struct wl_compositor_listener compositor_listener = { + display_handle_device, + display_handle_acknowledge, + display_handle_frame, +}; + +static void +display_handle_geometry(void *data, + struct wl_output *output, + int32_t width, int32_t height) +{ + struct QWaylandData *d = (struct QWaylandData *)data; + + d->x = 0; + d->y = 0; + d->width = width; + d->height = height; +} + +static const struct wl_output_listener output_listener = { + display_handle_geometry, +}; + +static void +display_handle_global(struct wl_display *display, struct wl_object *object, + void *data) +{ + struct QWaylandData *d = (struct QWaylandData *)data; + + if (wl_object_implements(object, "compositor", 1)) { + d->compositor = (struct wl_compositor *) object; + wl_compositor_add_listener(d->compositor, &compositor_listener, d); + } else if (wl_object_implements(object, "output", 1)) { + d->output = (struct wl_output *) object; + wl_output_add_listener(d->output, &output_listener, d); + } else if (wl_object_implements(object, "input_device", 1)) { + d->input_device = (struct wl_input_device *) object; + //wl_input_device_add_listener(d->input_device, &input_device_listener, d); + } +} + class QWaylandEventDispatcherGlibPrivate : public QEventDispatcherGlibPrivate { Q_DECLARE_PUBLIC(QWaylandEventDispatcherGlib) @@ -67,7 +420,7 @@ class QWaylandEventDispatcherGlibPrivate : public QEventDispatcherGlibPrivate public: QWaylandEventDispatcherGlibPrivate(); GWaylandEventSource *waylandEventSource; - QList<struct wl_message*> queuedUserInputEvents; + QList<struct wl_message*> queuedEvents; }; static gboolean waylandEventSourcePrepare(GSource *s, gint *timeout) @@ -76,10 +429,9 @@ static gboolean waylandEventSourcePrepare(GSource *s, gint *timeout) if (timeout) *timeout = -1; -#if 0 - while (source->mask & WL_DISPLAY_WRITABLE) - wl_display_iterate(qWayland->display, WL_DISPLAY_WRITABLE); -#endif + + wl_display_iterate(qWayland->wl_display, WL_DISPLAY_WRITABLE); + return false; } @@ -87,14 +439,17 @@ static gboolean waylandEventSourceCheck(GSource *s) { GWaylandEventSource *source = reinterpret_cast<GWaylandEventSource *>(s); - return false; + return source->pfd.revents; } static gboolean waylandEventSourceDispatch(GSource *s, GSourceFunc callback, gpointer user_data) { GWaylandEventSource *source = reinterpret_cast<GWaylandEventSource *>(s); - wl_display_iterate(qWayland->display, WL_DISPLAY_READABLE); + wl_display_iterate(qWayland->wl_display, WL_DISPLAY_READABLE); + + if (callback) + callback(user_data); return true; } @@ -108,14 +463,7 @@ static GSourceFuncs waylandEventSourceFuncs = { QWaylandEventDispatcherGlibPrivate::QWaylandEventDispatcherGlibPrivate() { - waylandEventSource = reinterpret_cast<GWaylandEventSource *>(g_source_new(&waylandEventSourceFuncs, sizeof(GWaylandEventSource))); - g_source_set_can_recurse(&waylandEventSource->source, true); - - waylandEventSource->flags = QEventLoop::AllEvents; - waylandEventSource->q = 0; - waylandEventSource->d = 0; - - g_source_attach(&waylandEventSource->source, mainContext); + qDebug("wayland event dispatcher created\n"); } QWaylandEventDispatcherGlib::QWaylandEventDispatcherGlib(QObject *parent) @@ -142,11 +490,47 @@ QWaylandEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags) return returnValue; } +static int +wayland_source_update(uint32_t mask, void *data) +{ + GWaylandEventSource *source = reinterpret_cast<GWaylandEventSource *>(data); + + source->mask = mask; + + return 0; +} + void QWaylandEventDispatcherGlib::startingUp() { - Q_D(QWaylandEventDispatcherGlib); - d->waylandEventSource->q = this; - d->waylandEventSource->d = d; + Q_D(QWaylandEventDispatcherGlib); + + d->waylandEventSource = reinterpret_cast<GWaylandEventSource *>(g_source_new(&waylandEventSourceFuncs, sizeof(GWaylandEventSource))); + g_source_set_can_recurse(&d->waylandEventSource->source, true); + + d->waylandEventSource->flags = QEventLoop::AllEvents; + d->waylandEventSource->q = 0; + d->waylandEventSource->d = 0; + + g_source_attach(&d->waylandEventSource->source, d->mainContext); + + d->waylandEventSource->q = this; + d->waylandEventSource->d = d; + d->waylandEventSource->pfd.fd = + wl_display_get_fd(qWayland->wl_display, wayland_source_update, + d->waylandEventSource); + d->waylandEventSource->pfd.events = G_IO_IN | G_IO_ERR; + g_source_add_poll(&d->waylandEventSource->source, + &d->waylandEventSource->pfd); + + /* Set up listener so we'll catch all events. */ + if (!wl_display_add_global_listener(qWayland->wl_display, + display_handle_global, qWayland)) { + wl_display_destroy(qWayland->wl_display); + qFatal("failed to add compositor listener\n"); + } + + /* Process connection events. */ + wl_display_iterate(qWayland->wl_display, WL_DISPLAY_READABLE); } QT_END_NAMESPACE diff --git a/src/gui/kernel/qt_wayland_p.h b/src/gui/kernel/qt_wayland_p.h index 56f866890f..d1d26692b1 100644 --- a/src/gui/kernel/qt_wayland_p.h +++ b/src/gui/kernel/qt_wayland_p.h @@ -2,6 +2,8 @@ #define QT_WAYLAND_P_H extern "C" { +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> #include <EGL/egl.h> #include <EGL/eglext.h> #include <glib.h> @@ -14,13 +16,13 @@ extern "C" { struct QWaylandData { int dri_fd; - struct wl_display *display; + struct wl_display *wl_display; struct wl_compositor *compositor; struct wl_output *output; struct wl_input_device *input_device; char *device_name; struct wl_list window_list; - EGLDisplay dpy; + EGLDisplay egl_display; EGLContext ctx; int x; int y; diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index f23a94c554..cc266ede93 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -824,6 +824,8 @@ public: void s60UpdateIsOpaque(); void reparentChildren(); void registerTouchWindow(); +#elif defined(Q_WS_WAYLAND) + // nothing yet #endif }; diff --git a/src/gui/kernel/qwidget_wayland.cpp b/src/gui/kernel/qwidget_wayland.cpp index c5cf31d4e3..4c0d64e2e1 100644 --- a/src/gui/kernel/qwidget_wayland.cpp +++ b/src/gui/kernel/qwidget_wayland.cpp @@ -56,8 +56,12 @@ #include "qdebug.h" +#include "qt_wayland_p.h" #include "qwidget_p.h" +#include <private/qegl_p.h> +#include <private/qwindowsurface_p.h> + QT_BEGIN_NAMESPACE QT_USE_NAMESPACE @@ -67,8 +71,68 @@ QT_USE_NAMESPACE QWidget member functions *****************************************************************************/ -void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool /*destroyOldWindow*/) -{ +void QWidgetPrivate::create_sys(WId window, bool initializeWindow, + bool destroyOldWindow) +{ + Q_Q(QWidget); + Qt::WindowType type = q->windowType(); + Qt::WindowFlags &flags = data.window_flags; + QWidget *parentWidget = q->parentWidget(); + WId id; + bool topLevel = (flags & Qt::Window); + bool popup = (type == Qt::Popup); + bool dialog = (type == Qt::Dialog + || type == Qt::Sheet); + bool desktop = (type == Qt::Desktop); + bool tool = (type == Qt::Tool || type == Qt::SplashScreen + || type == Qt::ToolTip || type == Qt::Drawer); + EGLDisplay dpy = qWayland->egl_display; + EGLImageKHR image; + GLuint texture; + EGLint image_attribs[] = { + EGL_WIDTH, 0, + EGL_HEIGHT, 0, + EGL_IMAGE_FORMAT_MESA, EGL_IMAGE_FORMAT_ARGB8888_MESA, + EGL_IMAGE_USE_MESA, EGL_IMAGE_USE_SCANOUT_MESA, + EGL_NONE + }; + + qWarning("wayland widget: %s\n", __func__); + + if (type == Qt::ToolTip) + flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint; + if (type == Qt::Popup) + flags |= Qt::X11BypassWindowManagerHint; + + if (topLevel) { + if (parentWidget) { + QWidget *ptl = parentWidget->window(); + if (ptl && (ptl->windowFlags() & Qt::WindowStaysOnTopHint)) + flags |= Qt::WindowStaysOnTopHint; + } + + if (type == Qt::SplashScreen) { + // whatever... overlay in center or something? + } + if (flags & (Qt::WindowMinimizeButtonHint + | Qt::WindowMaximizeButtonHint + | Qt::WindowContextHelpButtonHint)) + flags |= Qt::WindowSystemMenuHint; + } + + if (!window) + initializeWindow = true; + + if (topLevel || q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { + image_attribs[1] = data.crect.width(); + image_attribs[3] = data.crect.height(); + image = QEgl::eglCreateDRMImageMESA(dpy, image_attribs); + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + QEgl::glEGLImageTargetTexture(GL_TEXTURE_2D, image); + + setWinId(texture); + } } @@ -90,7 +154,9 @@ QPoint QWidget::mapFromGlobal(const QPoint &pos) const { } -void QWidgetPrivate::updateSystemBackground() {} +void QWidgetPrivate::updateSystemBackground() +{ +} #ifndef QT_NO_CURSOR void QWidgetPrivate::setCursor_sys(const QCursor &cursor) @@ -149,13 +215,50 @@ QWidget *QWidget::keyboardGrabber() void QWidget::activateWindow() { + qWarning("%s\n", __func__); } void QWidgetPrivate::show_sys() { + qWarning("%s\n", __func__); + + Q_Q(QWidget); + q->setAttribute(Qt::WA_Mapped); + if (q->testAttribute(Qt::WA_DontShowOnScreen)) { + invalidateBuffer(q->rect()); + return; + } + + if (q->isWindow()) { + if (!q->testAttribute(Qt::WA_ShowWithoutActivating) + && q->windowType() != Qt::Popup + && q->windowType() != Qt::Tool + && q->windowType() != Qt::ToolTip) { + //QWidget::qwsDisplay()->requestFocus(data.winid,true); + } + + if (QWindowSurface *surface = q->windowSurface()) { + const QRect frameRect = q->frameGeometry(); + if (surface->geometry() != frameRect) + surface->setGeometry(frameRect); + } + + data.fstrut_dirty = true; + bool staysontop = + (q->windowFlags() & Qt::WindowStaysOnTopHint) + || q->windowType() == Qt::Popup; + if (!staysontop && q->parentWidget()) { // if our parent stays on top, so must we + QWidget *ptl = q->parentWidget()->window(); + if (ptl && (ptl->windowFlags() & Qt::WindowStaysOnTopHint)) + staysontop = true; + } + } + + if (!q->window()->data->in_show) { + invalidateBuffer(q->rect()); + } } - void QWidgetPrivate::hide_sys() { } @@ -170,10 +273,12 @@ void QWidgetPrivate::setFocus_sys() void QWidgetPrivate::raise_sys() { + qWarning("%s\n", __func__); } void QWidgetPrivate::lower_sys() { + qWarning("%s\n", __func__); } void QWidgetPrivate::stackUnder_sys(QWidget*) @@ -182,10 +287,12 @@ void QWidgetPrivate::stackUnder_sys(QWidget*) void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &) { + qWarning("%s\n", __func__); } void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) { + qWarning("%s\n", __func__); } void QWidgetPrivate::setConstraints_sys() @@ -235,6 +342,7 @@ void QWidgetPrivate::setMask_sys(const QRegion ®ion) void QWidgetPrivate::updateFrameStrut() { + qWarning("%s\n", __func__); } void QWidgetPrivate::setWindowOpacity_sys(qreal level) @@ -249,6 +357,7 @@ QPaintEngine *QWidget::paintEngine() const QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys() { + qWarning("%s\n", __func__); } void QWidgetPrivate::setModal_sys() diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 004f4f7a15..3a4d9f2472 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -372,11 +372,6 @@ embedded { SOURCES += painting/qwindowsurface_qws.cpp } -wayland { - HEADERS += painting/qwindowsurface_wayland_p.h - SOURCES += painting/qwindowsurface_wayland.cpp -} - symbian { HEADERS += painting/qwindowsurface_s60_p.h SOURCES += painting/qwindowsurface_s60.cpp diff --git a/src/gui/painting/qgraphicssystem_wayland.cpp b/src/gui/painting/qgraphicssystem_wayland.cpp deleted file mode 100644 index db3d4b1a76..0000000000 --- a/src/gui/painting/qgraphicssystem_wayland.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <qscreen_wayland.h> -#include "qgraphicssystem_wayland_p.h" -#include <private/qpixmap_raster_p.h> -#include <private/qwindowsurface_wayland_p.h> - -QT_BEGIN_NAMESPACE - -QPixmapData *QWSGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const -{ - if (screen->pixmapDataFactory()) - return screen->pixmapDataFactory()->create(type); //### For 4.4 compatability - else - return new QRasterPixmapData(type); -} - -QWindowSurface *QWSGraphicsSystem::createWindowSurface(QWidget *widget) const -{ - return screen->createSurface(widget); -} - -QT_END_NAMESPACE diff --git a/src/gui/painting/qgraphicssystem_wayland_p.h b/src/gui/painting/qgraphicssystem_wayland_p.h deleted file mode 100644 index d078f54a5a..0000000000 --- a/src/gui/painting/qgraphicssystem_wayland_p.h +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSSYSTEM_QWS_P_H -#define QGRAPHICSSYSTEM_QWS_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qgraphicssystem_p.h" - -QT_BEGIN_NAMESPACE - -class Q_GUI_EXPORT QWSGraphicsSystem : public QGraphicsSystem -{ -public: - - QWSGraphicsSystem() - : screen(QScreen::instance()) {} - - QWSGraphicsSystem(QScreen* s) - : screen(s) {} - - virtual QPixmapData *createPixmapData(QPixmapData::PixelType type) const; - QWindowSurface *createWindowSurface(QWidget *widget) const; - -private: - QScreen* screen; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/gui/painting/qprintengine_wayland.cpp b/src/gui/painting/qprintengine_wayland.cpp deleted file mode 100644 index 26847905f6..0000000000 --- a/src/gui/painting/qprintengine_wayland.cpp +++ /dev/null @@ -1,886 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <private/qprintengine_wayland_p.h> - -#ifndef QT_NO_PRINTER - -#include <private/qpaintengine_raster_p.h> -#include <qimage.h> -#include <qfile.h> -#include <qdebug.h> -#include <QCopChannel> - -QT_BEGIN_NAMESPACE - -#define MM(n) int((n * 720 + 127) / 254) -#define IN(n) int(n * 72) - -extern QSizeF qt_paperSizeToQSizeF(QPrinter::PaperSize size); - -QtopiaPrintEngine::QtopiaPrintEngine(QPrinter::PrinterMode mode) - : QPaintEngine(*(new QtopiaPrintEnginePrivate( mode ))) -{ - d_func()->initialize(); -} - -bool QtopiaPrintEngine::begin(QPaintDevice *) -{ - Q_D(QtopiaPrintEngine); - Q_ASSERT_X(d->printerState == QPrinter::Idle, "QtopiaPrintEngine", "printer already active"); - - // Create a new off-screen monochrome image to handle the drawing process. - QSize size = paperRect().size(); - if ( d->pageImage ) - delete d->pageImage; - d->pageImage = new QImage( size, QImage::Format_RGB32 ); - if ( !(d->pageImage) ) - return false; - - // Recreate the paint engine on the new image. - delete d->_paintEngine; - d->_paintEngine = 0; - d->paintEngine()->state = state; - - // Begin the paint process on the image. - if (!d->paintEngine()->begin(d->pageImage)) - return false; - - // Clear the first page to all-white. - clearPage(); - - // Clear the print buffer and output the image header. - d->buffer.clear(); - d->writeG3FaxHeader(); - - // The print engine is currently active. - d->printerState = QPrinter::Active; - return true; -} - -bool QtopiaPrintEngine::end() -{ - Q_D(QtopiaPrintEngine); - - d->paintEngine()->end(); - - // Flush the last page. - flushPage(); - - // Output the fax data to a file (TODO: send to the print queuing daemon). - QString filename; - if ( !d->outputFileName.isEmpty() ) - filename = QString::fromLocal8Bit(qgetenv("HOME").constData()) + QLatin1String("/Documents/") + d->outputFileName; - else - filename = QString::fromLocal8Bit(qgetenv("HOME").constData()) + QLatin1String("/tmp/qwsfax.tiff"); - - setProperty(QPrintEngine::PPK_OutputFileName, filename); - QFile file( filename ); - if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) ) { - qDebug( "Failed to open %s for printer output", - filename.toLatin1().constData() ); - } else { - file.write( d->buffer.data() ); - file.close(); - } - - // Free up the memory for the image buffer. - d->buffer.clear(); - - // Finalize the print job. - d->printerState = QPrinter::Idle; - - // call qcop service - QMap<QString, QVariant> map; - for ( int x = 0; x <= QPrintEngine::PPK_Duplex; x++ ) - map.insert( QString::number(x), property((QPrintEngine::PrintEnginePropertyKey)(x))); - QVariant variant(map); - - QByteArray data; - QDataStream out(&data, QIODevice::WriteOnly); - out << variant; - QCopChannel::send(QLatin1String("QPE/Service/Print"), QLatin1String("print(QVariant)"), data); - - return true; -} - -QPaintEngine *QtopiaPrintEngine::paintEngine() const -{ - return const_cast<QtopiaPrintEnginePrivate *>(d_func())->paintEngine(); -} - -void QtopiaPrintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) -{ - Q_D(QtopiaPrintEngine); - Q_ASSERT(d->printerState == QPrinter::Active); - d->paintEngine()->drawPixmap(r, pm, sr); -} - -void QtopiaPrintEngine::drawTextItem(const QPointF &p, const QTextItem &ti) -{ - Q_D(QtopiaPrintEngine); - Q_ASSERT(d->printerState == QPrinter::Active); - d->paintEngine()->drawTextItem(p, ti); -} - -void QtopiaPrintEngine::updateState(const QPaintEngineState &state) -{ - Q_D(QtopiaPrintEngine); - d->paintEngine()->updateState(state); -} - -QRect QtopiaPrintEngine::paperRect() const -{ - QSizeF s = qt_paperSizeToQSizeF(d_func()->paperSize); - s.rwidth() = MM(s.width()); - s.rheight() = MM(s.height()); - int w = qRound(s.width()*d_func()->resolution/72.); - int h = qRound(s.height()*d_func()->resolution/72.); - if (d_func()->orientation == QPrinter::Portrait) - return QRect(0, 0, w, h); - else - return QRect(0, 0, h, w); -} - -QRect QtopiaPrintEngine::pageRect() const -{ - QRect r = paperRect(); - if (d_func()->fullPage) - return r; - // would be nice to get better margins than this. - return QRect(d_func()->resolution/3, d_func()->resolution/3, r.width()-2*d_func()->resolution/3, r.height()-2*d_func()->resolution/3); -} - -bool QtopiaPrintEngine::newPage() -{ - flushPage(); - clearPage(); - ++(d_func()->pageNumber); - return true; -} - -bool QtopiaPrintEngine::abort() -{ - return false; -} - -QPrinter::PrinterState QtopiaPrintEngine::printerState() const -{ - return d_func()->printerState; -} - -int QtopiaPrintEngine::metric(QPaintDevice::PaintDeviceMetric metricType) const -{ - int val; - QRect r = d_func()->fullPage ? paperRect() : pageRect(); - switch (metricType) { - case QPaintDevice::PdmWidth: - val = r.width(); - break; - case QPaintDevice::PdmHeight: - val = r.height(); - break; - case QPaintDevice::PdmDpiX: - val = d_func()->resolution; - break; - case QPaintDevice::PdmDpiY: - val = d_func()->resolution; - break; - case QPaintDevice::PdmPhysicalDpiX: - case QPaintDevice::PdmPhysicalDpiY: - val = QT_QWS_PRINTER_DEFAULT_DPI; - break; - case QPaintDevice::PdmWidthMM: - val = qRound(r.width()*25.4/d_func()->resolution); - break; - case QPaintDevice::PdmHeightMM: - val = qRound(r.height()*25.4/d_func()->resolution); - break; - case QPaintDevice::PdmNumColors: - val = 2; - break; - case QPaintDevice::PdmDepth: - val = 1; - break; - default: - qWarning("QtopiaPrintEngine::metric: Invalid metric command"); - return 0; - } - return val; -} - -QVariant QtopiaPrintEngine::property(PrintEnginePropertyKey key) const -{ - Q_D(const QtopiaPrintEngine); - QVariant ret; - - switch (key) { - case PPK_CollateCopies: - ret = d->collateCopies; - break; - case PPK_ColorMode: - ret = d->colorMode; - break; - case PPK_Creator: - ret = d->creator; - break; - case PPK_DocumentName: - ret = d->docName; - break; - case PPK_FullPage: - ret = d->fullPage; - break; - case PPK_CopyCount: // fallthrough - case PPK_NumberOfCopies: - ret = d->numCopies; - break; - case PPK_SupportsMultipleCopies: - ret = false; - break; - case PPK_Orientation: - ret = d->orientation; - break; - case PPK_OutputFileName: - ret = d->outputFileName; - break; - case PPK_PageOrder: - ret = d->pageOrder; - break; - case PPK_PageRect: - ret = pageRect(); - break; - case PPK_PaperSize: - ret = d->paperSize; - break; - case PPK_PaperRect: - ret = paperRect(); - break; - case PPK_PaperSource: - ret = d->paperSource; - break; - case PPK_PrinterName: - ret = d->printerName; - break; - case PPK_PrinterProgram: - ret = d->printProgram; - break; - case PPK_Resolution: - ret = d->resolution; - break; - case PPK_SupportedResolutions: - ret = QList<QVariant>() << QT_QWS_PRINTER_DEFAULT_DPI; - break; - default: - break; - } - return ret; -} - -void QtopiaPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &value) -{ - Q_D(QtopiaPrintEngine); - switch (key) { - case PPK_CollateCopies: - d->collateCopies = value.toBool(); - break; - case PPK_ColorMode: - d->colorMode = QPrinter::ColorMode(value.toInt()); - break; - case PPK_Creator: - d->creator = value.toString(); - break; - case PPK_DocumentName: - d->docName = value.toString(); - break; - case PPK_FullPage: - d->fullPage = value.toBool(); - break; - case PPK_CopyCount: // fallthrough - case PPK_NumberOfCopies: - d->numCopies = value.toInt(); - break; - case PPK_Orientation: - d->orientation = QPrinter::Orientation(value.toInt()); - break; - case PPK_OutputFileName: - d->outputFileName = value.toString(); - break; - case PPK_PageOrder: - d->pageOrder = QPrinter::PageOrder(value.toInt()); - break; - case PPK_PaperSize: - d->paperSize = QPrinter::PaperSize(value.toInt()); - break; - case PPK_PaperSource: - d->paperSource = QPrinter::PaperSource(value.toInt()); - case PPK_PrinterName: - d->printerName = value.toString(); - break; - case PPK_PrinterProgram: - d->printProgram = value.toString(); - break; - case PPK_Resolution: - d->resolution = value.toInt(); - break; - default: - break; - } -} - -void QtopiaPrintEngine::clearPage() -{ - d_func()->pageImage->fill(QColor(255, 255, 255).rgb()); -} - -void QtopiaPrintEngine::flushPage() -{ - d_func()->writeG3FaxPage(); -} - -QtopiaPrintEnginePrivate::~QtopiaPrintEnginePrivate() -{ - if ( pageImage ) - delete pageImage; -} - -void QtopiaPrintEnginePrivate::initialize() -{ - _paintEngine = 0; -} - -QPaintEngine *QtopiaPrintEnginePrivate::paintEngine() -{ - if (!_paintEngine) - _paintEngine = new QRasterPaintEngine(pageImage); - return _paintEngine; -} - -void QtopiaPrintEnginePrivate::writeG3FaxHeader() -{ - // Write the TIFF file magic number (little-endian TIFF). - buffer.append( (char)'I' ); - buffer.append( (char)'I' ); - buffer.append( (char)42 ); - buffer.append( (char)0 ); - - // Leave a place-holder for the IFD offset of the first page. - ifdPatch = buffer.size(); - buffer.append( (int)0 ); -} - -// Tag values, from RFC 2301. -#define TIFF_IFD_NEW_SUB_FILE_TYPE 254 -#define TIFF_IFD_IMAGE_WIDTH 256 -#define TIFF_IFD_IMAGE_LENGTH 257 -#define TIFF_IFD_BITS_PER_SAMPLE 258 -#define TIFF_IFD_COMPRESSION 259 -#define TIFF_IFD_PHOTOMETRIC_INTERP 262 -#define TIFF_IFD_FILL_ORDER 266 -#define TIFF_IFD_STRIP_OFFSETS 273 -#define TIFF_IFD_ORIENTATION 274 -#define TIFF_IFD_SAMPLES_PER_PIXEL 277 -#define TIFF_IFD_ROWS_PER_STRIP 278 -#define TIFF_IFD_STRIP_BYTE_COUNTS 279 -#define TIFF_IFD_X_RESOLUTION 282 -#define TIFF_IFD_Y_RESOLUTION 283 -#define TIFF_IFD_PLANAR_CONFIG 284 -#define TIFF_IFD_T4_OPTIONS 292 -#define TIFF_IFD_RESOLUTION_UNIT 296 -#define TIFF_IFD_PAGE_NUMBER 297 -#define TIFF_IFD_CLEAN_FAX_DATA 327 - -// IFD type values. -#define TIFF_TYPE_SHORT 3 -#define TIFF_TYPE_LONG 4 -#define TIFF_TYPE_RATIONAL 5 - -// Construct a SHORT pair from two values. -#define TIFF_SHORT_PAIR(a,b) (((a) & 0xFFFF) | ((b) << 16)) - -// Width of a FAX page in pixels, in the baseline specification from RFC 2301. -// This must be hard-wired, as per the RFC. We truncate any pixels that -// are beyond this limit, or pad lines to reach this limit. -#define TIFF_FAX_WIDTH 1728 - -void QtopiaPrintEnginePrivate::writeG3FaxPage() -{ - // Pad the image file to a word boundary, just in case. - buffer.pad(); - - // Back-patch the IFD link for the previous page. - buffer.patch( ifdPatch, buffer.size() ); - - // Output the contents of the IFD for this page (these must be - // in ascending order of tag value). - buffer.append( (short)19 ); // Number of IFD entries. - writeG3IFDEntry( TIFF_IFD_NEW_SUB_FILE_TYPE, TIFF_TYPE_LONG, 1, 2 ); - writeG3IFDEntry( TIFF_IFD_IMAGE_WIDTH, TIFF_TYPE_LONG, 1, TIFF_FAX_WIDTH ); - writeG3IFDEntry - ( TIFF_IFD_IMAGE_LENGTH, TIFF_TYPE_LONG, 1, pageImage->height() ); - writeG3IFDEntry( TIFF_IFD_BITS_PER_SAMPLE, TIFF_TYPE_SHORT, 1, 1 ); - writeG3IFDEntry( TIFF_IFD_COMPRESSION, TIFF_TYPE_SHORT, 1, 3 ); - writeG3IFDEntry( TIFF_IFD_PHOTOMETRIC_INTERP, TIFF_TYPE_SHORT, 1, 0 ); - writeG3IFDEntry( TIFF_IFD_FILL_ORDER, TIFF_TYPE_SHORT, 1, 1 ); - int stripOffsets = - writeG3IFDEntry( TIFF_IFD_STRIP_OFFSETS, TIFF_TYPE_LONG, 1, 0 ); - writeG3IFDEntry( TIFF_IFD_ORIENTATION, TIFF_TYPE_SHORT, 1, 1 ); - writeG3IFDEntry( TIFF_IFD_SAMPLES_PER_PIXEL, TIFF_TYPE_SHORT, 1, 1 ); - writeG3IFDEntry - ( TIFF_IFD_ROWS_PER_STRIP, TIFF_TYPE_LONG, 1, pageImage->height() ); - int stripBytes = writeG3IFDEntry - ( TIFF_IFD_STRIP_BYTE_COUNTS, TIFF_TYPE_LONG, 1, 0 ); - int xres = - writeG3IFDEntry( TIFF_IFD_X_RESOLUTION, TIFF_TYPE_RATIONAL, 1, 0 ); - int yres = - writeG3IFDEntry( TIFF_IFD_Y_RESOLUTION, TIFF_TYPE_RATIONAL, 1, 0 ); - writeG3IFDEntry( TIFF_IFD_PLANAR_CONFIG, TIFF_TYPE_SHORT, 1, 1 ); - writeG3IFDEntry( TIFF_IFD_T4_OPTIONS, TIFF_TYPE_LONG, 1, 2 ); - writeG3IFDEntry( TIFF_IFD_RESOLUTION_UNIT, TIFF_TYPE_SHORT, 1, 2 ); - writeG3IFDEntry( TIFF_IFD_PAGE_NUMBER, TIFF_TYPE_SHORT, 2, - TIFF_SHORT_PAIR( pageNumber, 0 ) ); - writeG3IFDEntry( TIFF_IFD_CLEAN_FAX_DATA, TIFF_TYPE_SHORT, 1, 0 ); - - // Leave a place-holder for the IFD offset of the next page. - ifdPatch = buffer.size(); - buffer.append( (int)0 ); - - // Output the X and Y resolutions, as rational values (usually 200/1). - buffer.patch( xres, buffer.size() ); - buffer.append( (int)resolution ); - buffer.append( (int)1 ); - buffer.patch( yres, buffer.size() ); - buffer.append( (int)resolution ); - buffer.append( (int)1 ); - - // We are now at the start of the image data - set the strip offset. - int start = buffer.size(); - buffer.patch( stripOffsets, start ); - - // Output the image data. - int width = pageImage->width(); - QImage::Format imageFormat = pageImage->format(); - for ( int y = 0; y < pageImage->height(); ++y ) { - unsigned char *scan = pageImage->scanLine(y); - int prev, pixel, len; - writeG3EOL(); - prev = 0; - len = 0; - - uint currentColor = qRgb(255, 255, 255); // start with white - - for ( int x = 0; x < width && x < TIFF_FAX_WIDTH; ++x ) { - if ( imageFormat == QImage::Format_RGB32 ) { - // read color of the current pixel - uint *p = (uint *)scan + x; - - if ( *p == currentColor ) { // if it is the same color - len++; // imcrement length - } else { // otherwise write color into the buffer - if ( len > 0 ) { - if ( currentColor == qRgb(0, 0, 0) ) - writeG3BlackRun( len ); - else - writeG3WhiteRun( len ); - } - // initialise length and color; - len = 1; - currentColor = *p; - } - } else if ( imageFormat == QImage::Format_Mono ) { - pixel = ((scan[x >> 3] & (1 << (x & 7))) != 0); - if ( pixel != prev ) { - if ( prev ) { - writeG3BlackRun( len ); - } else { - writeG3WhiteRun( len ); - } - prev = pixel; - len = 1; - } else { - ++len; - } - } - } - - if ( imageFormat == QImage::Format_RGB32 ) { - // Output the last run on the line, and pad to TIFF_FAX_WIDTH. - if ( len != 0 ) { - if ( currentColor == qRgb(0, 0, 0) ) - writeG3BlackRun( len ); - else - writeG3WhiteRun( len ); - } - if ( width < TIFF_FAX_WIDTH ) - writeG3WhiteRun( TIFF_FAX_WIDTH - width ); - } else if ( imageFormat == QImage::Format_Mono ) { - if ( len != 0 ) { - if ( prev ) { - writeG3BlackRun( len ); - if ( width < TIFF_FAX_WIDTH ) { - writeG3WhiteRun( TIFF_FAX_WIDTH - width ); - } - } else { - if ( width < TIFF_FAX_WIDTH ) { - writeG3WhiteRun( len + ( TIFF_FAX_WIDTH - width ) ); - } else { - writeG3WhiteRun( len ); - } - } - } - } - } - - // Flush the last partial byte, which is padded with zero fill bits. - if ( partialBits > 0 ) { - buffer.append( (char)( partialByte << ( 8 - partialBits ) ) ); - partialByte = 0; - partialBits = 0; - } - - // end of page add six EOLs - for ( int i = 0; i < 6; i++ ) - writeG3EOL(); - - // Update the byte count for the image data strip. - buffer.patch( stripBytes, buffer.size() - start ); -} - -int QtopiaPrintEnginePrivate::writeG3IFDEntry - ( int tag, int type, int count, int value ) -{ - buffer.append( (short)tag ); - buffer.append( (short)type ); - buffer.append( count ); - buffer.append( value ); - return buffer.size() - 4; // Offset of the value for back-patching. -} - -void QtopiaPrintEnginePrivate::writeG3Code( int code, int bits ) -{ - partialByte = ( ( partialByte << bits ) | code ); - partialBits += bits; - while ( partialBits >= 8 ) { - partialBits -= 8; - buffer.append( (char)( partialByte >> partialBits ) ); - } -} - -void QtopiaPrintEnginePrivate::writeG3WhiteRun( int len ) -{ - static struct { - unsigned short code; - unsigned short bits; - } whiteCodes[64 + 27] = { - {0x0035, 8}, // 0 - {0x0007, 6}, - {0x0007, 4}, - {0x0008, 4}, - {0x000B, 4}, - {0x000C, 4}, - {0x000E, 4}, - {0x000F, 4}, - {0x0013, 5}, // 8 - {0x0014, 5}, - {0x0007, 5}, - {0x0008, 5}, - {0x0008, 6}, - {0x0003, 6}, - {0x0034, 6}, - {0x0035, 6}, - {0x002A, 6}, // 16 - {0x002B, 6}, - {0x0027, 7}, - {0x000C, 7}, - {0x0008, 7}, - {0x0017, 7}, - {0x0003, 7}, - {0x0004, 7}, - {0x0028, 7}, // 24 - {0x002B, 7}, - {0x0013, 7}, - {0x0024, 7}, - {0x0018, 7}, - {0x0002, 8}, - {0x0003, 8}, - {0x001A, 8}, - {0x001B, 8}, // 32 - {0x0012, 8}, - {0x0013, 8}, - {0x0014, 8}, - {0x0015, 8}, - {0x0016, 8}, - {0x0017, 8}, - {0x0028, 8}, - {0x0029, 8}, // 40 - {0x002A, 8}, - {0x002B, 8}, - {0x002C, 8}, - {0x002D, 8}, - {0x0004, 8}, - {0x0005, 8}, - {0x000A, 8}, - {0x000B, 8}, // 48 - {0x0052, 8}, - {0x0053, 8}, - {0x0054, 8}, - {0x0055, 8}, - {0x0024, 8}, - {0x0025, 8}, - {0x0058, 8}, - {0x0059, 8}, // 56 - {0x005A, 8}, - {0x005B, 8}, - {0x004A, 8}, - {0x004B, 8}, - {0x0032, 8}, - {0x0033, 8}, - {0x0034, 8}, - {0x001B, 5}, // Make up codes: 64 - {0x0012, 5}, // 128 - {0x0017, 6}, // 192 - {0x0037, 7}, // 256 - {0x0036, 8}, // 320 - {0x0037, 8}, // 384 - {0x0064, 8}, // 448 - {0x0065, 8}, // 512 - {0x0068, 8}, // 576 - {0x0067, 8}, // 640 - {0x00CC, 9}, // 704 - {0x00CD, 9}, // 768 - {0x00D2, 9}, // 832 - {0x00D3, 9}, // 896 - {0x00D4, 9}, // 960 - {0x00D5, 9}, // 1024 - {0x00D6, 9}, // 1088 - {0x00D7, 9}, // 1152 - {0x00D8, 9}, // 1216 - {0x00D9, 9}, // 1280 - {0x00DA, 9}, // 1344 - {0x00DB, 9}, // 1408 - {0x0098, 9}, // 1472 - {0x0099, 9}, // 1536 - {0x009A, 9}, // 1600 - {0x0018, 6}, // 1664 - {0x009B, 9}, // 1728 - }; - if ( len >= 64 ) { - int index = 63 + (len >> 6); - writeG3Code( whiteCodes[index].code, whiteCodes[index].bits ); - len &= 63; - } - writeG3Code( whiteCodes[len].code, whiteCodes[len].bits ); -} - -void QtopiaPrintEnginePrivate::writeG3BlackRun( int len ) -{ - static struct { - unsigned short code; - unsigned short bits; - } blackCodes[64 + 27] = { - {0x0037, 10}, // 0 - {0x0002, 3}, - {0x0003, 2}, - {0x0002, 2}, - {0x0003, 3}, - {0x0003, 4}, - {0x0002, 4}, - {0x0003, 5}, - {0x0005, 6}, // 8 - {0x0004, 6}, - {0x0004, 7}, - {0x0005, 7}, - {0x0007, 7}, - {0x0004, 8}, - {0x0007, 8}, - {0x0018, 9}, - {0x0017, 10}, // 16 - {0x0018, 10}, - {0x0008, 10}, - {0x0067, 11}, - {0x0068, 11}, - {0x006C, 11}, - {0x0037, 11}, - {0x0028, 11}, - {0x0017, 11}, // 24 - {0x0018, 11}, - {0x00CA, 12}, - {0x00CB, 12}, - {0x00CC, 12}, - {0x00CD, 12}, - {0x0068, 12}, - {0x0069, 12}, - {0x006A, 12}, // 32 - {0x006B, 12}, - {0x00D2, 12}, - {0x00D3, 12}, - {0x00D4, 12}, - {0x00D5, 12}, - {0x00D6, 12}, - {0x00D7, 12}, - {0x006C, 12}, // 40 - {0x006D, 12}, - {0x00DA, 12}, - {0x00DB, 12}, - {0x0054, 12}, - {0x0055, 12}, - {0x0056, 12}, - {0x0057, 12}, - {0x0064, 12}, // 48 - {0x0065, 12}, - {0x0052, 12}, - {0x0053, 12}, - {0x0024, 12}, - {0x0037, 12}, - {0x0038, 12}, - {0x0027, 12}, - {0x0028, 12}, // 56 - {0x0058, 12}, - {0x0059, 12}, - {0x002B, 12}, - {0x002C, 12}, - {0x005A, 12}, - {0x0066, 12}, - {0x0067, 12}, - {0x000F, 10}, // Make up codes: 64 - {0x00C8, 12}, // 128 - {0x00C9, 12}, // 192 - {0x005B, 12}, // 256 - {0x0033, 12}, // 320 - {0x0034, 12}, // 384 - {0x0035, 12}, // 448 - {0x006C, 13}, // 512 - {0x006D, 13}, // 576 - {0x004A, 13}, // 640 - {0x004B, 13}, // 704 - {0x004C, 13}, // 768 - {0x004D, 13}, // 832 - {0x0072, 13}, // 896 - {0x0073, 13}, // 960 - {0x0074, 13}, // 1024 - {0x0075, 13}, // 1088 - {0x0076, 13}, // 1152 - {0x0077, 13}, // 1216 - {0x0052, 13}, // 1280 - {0x0053, 13}, // 1344 - {0x0054, 13}, // 1408 - {0x0055, 13}, // 1472 - {0x005A, 13}, // 1536 - {0x005B, 13}, // 1600 - {0x0064, 13}, // 1664 - {0x0065, 13}, // 1728 - }; - if ( len >= 64 ) { - int index = 63 + (len >> 6); - writeG3Code( blackCodes[index].code, blackCodes[index].bits ); - len &= 63; - } - writeG3Code( blackCodes[len].code, blackCodes[len].bits ); -} - -void QtopiaPrintEnginePrivate::writeG3EOL() -{ - int bitToPad; - if ( partialBits <= 4 ) { - bitToPad = 4 - partialBits; - } else { - bitToPad = 8 - partialBits + 4; - } - - partialByte = ((partialByte << (bitToPad + 12)) | 0x0001); - partialBits += bitToPad + 12; - - while ( partialBits >= 8 ) { - partialBits -= 8; - buffer.append( (char)(partialByte >> partialBits ) ); - } -// writeG3Code( 0x0001, 12 ); -} - -void QtopiaPrintBuffer::append( short value ) -{ - if ( _bigEndian ) { - _data.append( (char)(value >> 8) ); - _data.append( (char)value ); - } else { - _data.append( (char)value ); - _data.append( (char)(value >> 8) ); - } -} - -void QtopiaPrintBuffer::append( int value ) -{ - if ( _bigEndian ) { - _data.append( (char)(value >> 24) ); - _data.append( (char)(value >> 16) ); - _data.append( (char)(value >> 8) ); - _data.append( (char)value ); - } else { - _data.append( (char)value ); - _data.append( (char)(value >> 8) ); - _data.append( (char)(value >> 16) ); - _data.append( (char)(value >> 24) ); - } -} - -void QtopiaPrintBuffer::patch( int posn, int value ) -{ - if ( _bigEndian ) { - _data[posn] = (char)(value >> 24); - _data[posn + 1] = (char)(value >> 16); - _data[posn + 2] = (char)(value >> 8); - _data[posn + 3] = (char)value; - } else { - _data[posn] = (char)value; - _data[posn + 1] = (char)(value >> 8); - _data[posn + 2] = (char)(value >> 16); - _data[posn + 3] = (char)(value >> 24); - } -} - -void QtopiaPrintBuffer::pad() -{ - while ( ( _data.size() % 4 ) != 0 ) - _data.append( (char)0 ); -} - -QT_END_NAMESPACE - -#endif // QT_NO_PRINTER diff --git a/src/gui/painting/qprintengine_wayland_p.h b/src/gui/painting/qprintengine_wayland_p.h deleted file mode 100644 index e08fbcd9e1..0000000000 --- a/src/gui/painting/qprintengine_wayland_p.h +++ /dev/null @@ -1,213 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPRINTENGINE_QWS_P_H -#define QPRINTENGINE_QWS_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "QtGui/qprinter.h" - -#ifndef QT_NO_PRINTER - -#include "QtGui/qprintengine.h" -#include "QtCore/qbytearray.h" -#include "private/qpaintengine_p.h" - -QT_BEGIN_NAMESPACE - -class QtopiaPrintEnginePrivate; -class QRasterPaintEngine; -class QPrinterPrivate; -class QImage; - -class QtopiaPrintEngine : public QPaintEngine, public QPrintEngine -{ - Q_DECLARE_PRIVATE(QtopiaPrintEngine) -public: - QtopiaPrintEngine(QPrinter::PrinterMode mode); - - // override QWSPaintEngine - bool begin(QPaintDevice *dev); - bool end(); - void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); - void drawTextItem(const QPointF &p, const QTextItem &ti); - QPaintEngine::Type type() const { return QPaintEngine::X11; } - - QPaintEngine *paintEngine() const; - - void updateState(const QPaintEngineState &state); - - QRect paperRect() const; - QRect pageRect() const; - - bool newPage(); - bool abort(); - - QPrinter::PrinterState printerState() const; - - int metric(QPaintDevice::PaintDeviceMetric metricType) const; - - QVariant property(PrintEnginePropertyKey key) const; - void setProperty(PrintEnginePropertyKey key, const QVariant &value); - -private: - friend class QPrintDialog; - friend class QPageSetupDialog; - - void clearPage(); - void flushPage(); -}; - -class QtopiaPrintBuffer -{ -public: - QtopiaPrintBuffer( bool bigEndian=FALSE ) { _bigEndian = bigEndian; } - ~QtopiaPrintBuffer() {} - - const QByteArray& data() const { return _data; } - - int size() const { return _data.size(); } - - void clear() { _data.clear(); } - - void append( char value ) { _data.append( value ); } - void append( short value ); - void append( int value ); - void append( const QByteArray& array ) { _data.append( array ); } - - void patch( int posn, int value ); - - void pad(); - -private: - QByteArray _data; - bool _bigEndian; -}; - -#define QT_QWS_PRINTER_DEFAULT_DPI 200 - -class QtopiaPrintEnginePrivate : public QPaintEnginePrivate -{ - Q_DECLARE_PUBLIC(QtopiaPrintEngine) -public: - QtopiaPrintEnginePrivate(QPrinter::PrinterMode m) : - mode(m), - printerState(QPrinter::Idle), - orientation(QPrinter::Portrait), - paperSize(QPrinter::A4), - pageOrder(QPrinter::FirstPageFirst), - colorMode(QPrinter::GrayScale), - paperSource(QPrinter::OnlyOne), - resolution(QT_QWS_PRINTER_DEFAULT_DPI), - _paintEngine(0), - numCopies(1), - outputToFile(false), - fullPage(false), - collateCopies(false), - pageNumber(0), - pageImage(0), - partialByte(0), - partialBits(0) - { - } - ~QtopiaPrintEnginePrivate(); - - void initialize(); - QPaintEngine *paintEngine(); - - QPrinter::PrinterMode mode; - - QString printerName; - QString outputFileName; - QString printProgram; - QString docName; - QString creator; - - QPrinter::PrinterState printerState; - - QPrinter::Orientation orientation; - QPrinter::PaperSize paperSize; - QPrinter::PageOrder pageOrder; - QPrinter::ColorMode colorMode; - QPrinter::PaperSource paperSource; - - int resolution; - QPaintEngine *_paintEngine; - int numCopies; - - bool outputToFile; - bool fullPage; - bool collateCopies; - - int pageNumber; - - QImage *pageImage; - - QtopiaPrintBuffer buffer; - - // Definitions that are only relevant to G3FAX output. - int ifdPatch; - int partialByte; - int partialBits; - void writeG3FaxHeader(); - void writeG3FaxPage(); - int writeG3IFDEntry( int tag, int type, int count, int value ); - void writeG3Code( int code, int bits ); - void writeG3WhiteRun( int len ); - void writeG3BlackRun( int len ); - void writeG3EOL(); -}; - -QT_END_NAMESPACE - -#endif // QT_NO_PRINTER - -#endif // QPRINTENGINE_QWS_P_H diff --git a/src/gui/painting/qwindowsurface_wayland.cpp b/src/gui/painting/qwindowsurface_wayland.cpp deleted file mode 100644 index bf2a7e2429..0000000000 --- a/src/gui/painting/qwindowsurface_wayland.cpp +++ /dev/null @@ -1,487 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwindowsurface_wayland_p.h" -#include <qwidget.h> -#include <qapplication.h> -#include <qrgb.h> -#include <qpaintengine.h> -#include <qdesktopwidget.h> -#include <private/qapplication_p.h> -#include <private/qwidget_p.h> -#include <private/qbackingstore_p.h> -#include <stdio.h> - -QT_BEGIN_NAMESPACE - -QWaylandWindowSurface* qt_findWindowSurface(int winId) -{ - return NULL; -} - -void QWaylandWindowSurface::invalidateBuffer() -{ -} - -QWaylandWindowSurfacePrivate::QWaylandWindowSurfacePrivate() - : flags(0), -#ifdef QT_QWS_CLIENTBLIT - directId(-1), -#endif - winId(0) -{ -} - -void QWaylandWindowSurfacePrivate::setWinId(int id) -{ - winId = id; -} - -int QWaylandWindowSurface::winId() const -{ - return d_ptr->winId; -} - -void QWaylandWindowSurface::setWinId(int id) -{ - d_ptr->winId = id; -} - -/*! - \class QWaylandWindowSurface - \since 4.2 - \ingroup qws - \preliminary - \internal - - \brief The QWaylandWindowSurface class provides the drawing area for top-level - windows in Qt for Embedded Linux. - - Note that this class is only available in Qt for Embedded Linux. - - In \l{Qt for Embedded Linux}, the default behavior is for each client to - render its widgets into memory while the server is responsible for - putting the contents of the memory onto the - screen. QWaylandWindowSurface is used by the window system to implement - the associated memory allocation. - - When a screen update is required, the server runs through all the - top-level windows that intersect with the region that is about to - be updated, and ensures that the associated clients have updated - their memory buffer. Then the server uses the screen driver to - copy the content of the memory to the screen. To locate the - relevant parts of memory, the driver is provided with the list of - top-level windows that intersect with the given region. Associated - with each of the top-level windows there is a window surface - representing the drawing area of the window. - - When deriving from the QWaylandWindowSurface class, e.g., when adding - an \l {Adding an Accelerated Graphics Driver to Qt for Embedded Linux} - {accelerated graphics driver}, there are several pure virtual - functions that must be implemented. In addition, QWaylandWindowSurface - provides several virtual functions that can be reimplemented to - customize the drawing process. - - \tableofcontents - - \section1 Pure Virtual Functions - - There are in fact two window surface instances for each top-level - window; one used by the application when drawing a window, and - another used by the server application to perform window - compositioning. Implement the attach() to create the server-side - representation of the surface. The data() function must be - implemented to provide the required data. - - Implement the key() function to uniquely identify the surface - class, and the isValid() function to determine is a surface - corresponds to a given widget. - - The geometry() function must be implemented to let the window - system determine the area required by the window surface - (QWaylandWindowSurface also provides a corresponding virtual - setGeometry() function that is called whenever the area necessary - for the top-level window to be drawn, changes). The image() - function is called by the window system during window - compositioning, and must be implemented to return an image of the - top-level window. - - Finally, the paintDevice() function must be implemented to return - the appropriate paint device, and the scroll() function must be - implemented to scroll the given region of the surface the given - number of pixels. - - \section1 Virtual Functions - - When painting onto the surface, the window system will always call - the beginPaint() function before any painting operations are - performed. Likewise the endPaint() function is automatically - called when the painting is done. Reimplement the painterOffset() - function to alter the offset that is applied when drawing. - - The window system uses the flush() function to put a given region - of the widget onto the screen, and the release() function to - deallocate the screen region corresponding to this window surface. - - \section1 Other Members - - QWaylandWindowSurface provides the window() function returning a - pointer to the top-level window the surface is representing. The - currently visible region of the associated widget can be retrieved - and set using the clipRegion() and setClipRegion() functions, - respectively. - - When the window system performs the window compositioning, it uses - the SurfaceFlag enum describing the surface content. The currently - set surface flags can be retrieved and altered using the - surfaceFlags() and setSurfaceFlags() functions. In addition, - QWaylandWindowSurface provides the isBuffered(), isOpaque() and - isRegionReserved() convenience functions. - - \sa {Qt for Embedded Linux Architecture#Drawing on Screen}{Qt for - Embedded Linux Architecture} -*/ - -/*! - \enum QWaylandWindowSurface::SurfaceFlag - - This enum is used to describe the window surface's contents. It - is used by the screen driver to handle region allocation and - composition. - - \value RegionReserved The surface contains a reserved area. Once - allocated, a reserved area can not not be changed by the window - system, i.e., no other widgets can be drawn on top of this. - - \value Buffered - The surface is in a memory area which is not part of a framebuffer. - (A top-level window with QWidget::windowOpacity() other than 1.0 must use - a buffered surface in order to making blending with the background work.) - - \value Opaque - The surface contains only opaque pixels. - - \sa surfaceFlags(), setSurfaceFlags() -*/ - -/*! - \fn bool QWaylandWindowSurface::isValid() const - \since 4.3 - - Implement this function to return true if the surface is a valid - surface for the given top-level \a window; otherwise return - false. - - \sa window(), key() -*/ - -/*! - \fn QString QWaylandWindowSurface::key() const - - Implement this function to return a string that uniquely - identifies the class of this surface. - - \sa window(), isValid() -*/ - -/*! - \fn QByteArray QWaylandWindowSurface::permanentState() const - \since 4.3 - - Implement this function to return the data required for creating a - server-side representation of the surface. - - \sa attach() -*/ - -/*! - \fn void QWaylandWindowSurface::setPermanentState(const QByteArray &data) - \since 4.3 - - Implement this function to attach a server-side surface instance - to the corresponding client side instance using the given \a - data. Return true if successful; otherwise return false. - - \sa data() -*/ - -/*! - \fn const QImage QWaylandWindowSurface::image() const - - Implement this function to return an image of the top-level window. - - \sa geometry() -*/ - -/*! - \fn bool QWaylandWindowSurface::isRegionReserved() const - - Returns true if the QWaylandWindowSurface::RegionReserved is set; otherwise - returns false. - - \sa surfaceFlags() -*/ - -/*! - \fn bool QWaylandWindowSurface::isBuffered() const - - Returns true if the QWaylandWindowSurface::Buffered is set; otherwise returns false. - - \sa surfaceFlags() -*/ - -/*! - \fn bool QWaylandWindowSurface::isOpaque() const - - Returns true if the QWaylandWindowSurface::Opaque is set; otherwise - returns false. - - \sa surfaceFlags() -*/ - - -/*! - Constructs an empty surface. -*/ -QWaylandWindowSurface::QWaylandWindowSurface() - : QWindowSurface(0), d_ptr(new QWaylandWindowSurfacePrivate) -{ -} - -/*! - Constructs an empty surface for the given top-level \a widget. -*/ -QWaylandWindowSurface::QWaylandWindowSurface(QWidget *widget) - : QWindowSurface(widget), d_ptr(new QWaylandWindowSurfacePrivate) -{ -} - -QWaylandWindowSurface::~QWaylandWindowSurface() -{ -#ifdef Q_BACKINGSTORE_SUBSURFACES - if (d_ptr->winId) - winIdToSurfaceMap()->remove(d_ptr->winId); -#endif - - delete d_ptr; -} - -/*! - Returns the offset to be used when painting. - - \sa paintDevice() -*/ -QPoint QWaylandWindowSurface::painterOffset() const -{ - const QWidget *w = window(); - if (!w) - return QPoint(); - return w->geometry().topLeft() - w->frameGeometry().topLeft(); -} - -void QWaylandWindowSurface::beginPaint(const QRegion &) -{ - lock(); -} - -void QWaylandWindowSurface::endPaint(const QRegion &) -{ - unlock(); -} - -// XXX: documentation!!! -QByteArray QWaylandWindowSurface::transientState() const -{ - return QByteArray(); -} - -QByteArray QWaylandWindowSurface::permanentState() const -{ - return QByteArray(); -} - -void QWaylandWindowSurface::setTransientState(const QByteArray &state) -{ - Q_UNUSED(state); -} - -void QWaylandWindowSurface::setPermanentState(const QByteArray &state) -{ - Q_UNUSED(state); -} - -bool QWaylandWindowSurface::lock(int timeout) -{ - Q_UNUSED(timeout); - return true; -} - -void QWaylandWindowSurface::unlock() -{ -} - -#ifdef QT_QWS_CLIENTBLIT -/*! \internal */ -const QRegion QWaylandWindowSurface::directRegion() const -{ - return d_ptr->direct; -} - -/*! \internal */ -int QWaylandWindowSurface::directRegionId() const -{ - return d_ptr->directId; -} - -/*! \internal */ -void QWaylandWindowSurface::setDirectRegion(const QRegion &r, int id) -{ - d_ptr->direct = r; - d_ptr->directId = id; -} -#endif - -/*! - Returns the region currently visible on the screen. - - \sa setClipRegion() -*/ -const QRegion QWaylandWindowSurface::clipRegion() const -{ - return d_ptr->clip; -} - -/*! - Sets the region currently visible on the screen to be the given \a - clip region. - - \sa clipRegion() -*/ -void QWaylandWindowSurface::setClipRegion(const QRegion &clip) -{ -} - -/*! - Returns the surface flags describing the contents of this surface. - - \sa isBuffered(), isOpaque(), isRegionReserved() -*/ -QWaylandWindowSurface::SurfaceFlags QWaylandWindowSurface::surfaceFlags() const -{ - return d_ptr->flags; -} - -/*! - Sets the surface flags describing the contents of this surface, to - be the given \a flags. - - \sa surfaceFlags() -*/ -void QWaylandWindowSurface::setSurfaceFlags(SurfaceFlags flags) -{ - d_ptr->flags = flags; -} - -void QWaylandWindowSurface::setGeometry(const QRect &rect) -{ -} - -void QWaylandWindowSurface::setGeometry(const QRect &rect, const QRegion &mask) -{ -} - -static inline void flushUpdate(QWidget *widget, const QRegion ®ion, - const QPoint &offset) -{ -} - -void QWaylandWindowSurface::flush(QWidget *widget, const QRegion ®ion, - const QPoint &offset) -{ -} - -/*! - Move the surface with the given \a offset. - - A subclass may reimplement this function to enable accelerated window move. - It must return true if the move was successful and no repaint is necessary, - false otherwise. - - The default implementation updates the QWindowSurface geometry and - returns true if the surface is buffered; false otherwise. - - This function is called by the window system on the client instance. - - \sa isBuffered() -*/ -bool QWaylandWindowSurface::move(const QPoint &offset) -{ - QWindowSurface::setGeometry(geometry().translated(offset)); - return isBuffered(); -} - -/*! - Move the surface with the given \a offset. - - The new visible region after the window move is given by \a newClip - in screen coordinates. - - A subclass may reimplement this function to enable accelerated window move. - The returned region indicates the area that still needs to be composed - on the screen. - - The default implementation updates the QWindowSurface geometry and - returns the union of the old and new geometry. - - This function is called by the window system on the server instance. -*/ -QRegion QWaylandWindowSurface::move(const QPoint &offset, const QRegion &newClip) -{ - const QRegion oldGeometry = geometry(); - QWindowSurface::setGeometry(geometry().translated(offset)); - return oldGeometry + newClip; -} - -void QWaylandWindowSurface::releaseSurface() -{ -} - -QT_END_NAMESPACE diff --git a/src/gui/painting/qwindowsurface_wayland_p.h b/src/gui/painting/qwindowsurface_wayland_p.h deleted file mode 100644 index 668796a601..0000000000 --- a/src/gui/painting/qwindowsurface_wayland_p.h +++ /dev/null @@ -1,288 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWINDOWSURFACE_QWAYLAND_P_H -#define QWINDOWSURFACE_QWAYLAND_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qwindowsurface_p.h" -#include <qregion.h> -#include <qimage.h> -#include <qmutex.h> - -QT_BEGIN_NAMESPACE - -class QScreen; -class QWaylandWindowSurfacePrivate; - -class Q_GUI_EXPORT QWaylandWindowSurface : public QWindowSurface -{ -public: - QWaylandWindowSurface(); - QWaylandWindowSurface(QWidget *widget); - ~QWaylandWindowSurface(); - - virtual bool isValid() const = 0; - - virtual void setGeometry(const QRect &rect); - virtual void setGeometry(const QRect &rect, const QRegion &mask); - virtual void flush(QWidget *widget, const QRegion ®ion, - const QPoint &offset); - - virtual bool move(const QPoint &offset); - virtual QRegion move(const QPoint &offset, const QRegion &newClip); - - virtual QPoint painterOffset() const; // remove!!! - - virtual void beginPaint(const QRegion &); - virtual void endPaint(const QRegion &); - - virtual bool lock(int timeout = -1); - virtual void unlock(); - - virtual QString key() const = 0; - - // XXX: not good enough - virtual QByteArray transientState() const; - virtual QByteArray permanentState() const; - virtual void setTransientState(const QByteArray &state); - virtual void setPermanentState(const QByteArray &state); - - virtual QImage image() const = 0; - virtual QPaintDevice *paintDevice() = 0; - - const QRegion clipRegion() const; - void setClipRegion(const QRegion &); - - enum SurfaceFlag { - RegionReserved = 0x1, - Buffered = 0x2, - Opaque = 0x4 - }; - Q_DECLARE_FLAGS(SurfaceFlags, SurfaceFlag) - - SurfaceFlags surfaceFlags() const; - - inline bool isRegionReserved() const { - return surfaceFlags() & RegionReserved; - } - inline bool isBuffered() const { return surfaceFlags() & Buffered; } - inline bool isOpaque() const { return surfaceFlags() & Opaque; } - - int winId() const; - virtual void releaseSurface(); - -protected: - void setSurfaceFlags(SurfaceFlags type); - void setWinId(int id); - -private: - friend class QWidgetPrivate; - - void invalidateBuffer(); - - QWaylandWindowSurfacePrivate *d_ptr; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(QWaylandWindowSurface::SurfaceFlags) - -class QWaylandWindowSurfacePrivate -{ -public: - QWaylandWindowSurfacePrivate(); - - void setWinId(int id); - - QWaylandWindowSurface::SurfaceFlags flags; - QRegion clip; -#ifdef QT_QWayland_CLIENTBLIT - QRegion direct; - int directId; -#endif - - int winId; -}; - -class QWaylandLock; - -class Q_GUI_EXPORT QWaylandMemorySurface : public QWaylandWindowSurface -{ -public: - QWaylandMemorySurface(); - QWaylandMemorySurface(QWidget *widget); - ~QWaylandMemorySurface(); - - bool isValid() const; - - QPaintDevice *paintDevice() { return &img; } - bool scroll(const QRegion &area, int dx, int dy); - - QImage image() const { return img; } - QPoint painterOffset() const; - - void beginPaint(const QRegion &rgn); - - bool lock(int timeout = -1); - void unlock(); - -protected: - QImage::Format preferredImageFormat(const QWidget *widget) const; - -#ifndef QT_NO_QWayland_MULTIPROCESS - void setLock(int lockId); - QWaylandLock *memlock; -#endif -#ifndef QT_NO_THREAD - QMutex threadLock; -#endif - - QImage img; -}; - -class Q_GUI_EXPORT QWaylandLocalMemSurface : public QWaylandMemorySurface -{ -public: - QWaylandLocalMemSurface(); - QWaylandLocalMemSurface(QWidget *widget); - ~QWaylandLocalMemSurface(); - - void setGeometry(const QRect &rect); - - QString key() const { return QLatin1String("mem"); } - QByteArray permanentState() const; - - void setPermanentState(const QByteArray &data); - virtual void releaseSurface(); -protected: - uchar *mem; - int memsize; -}; - -#ifndef QT_NO_QWayland_MULTIPROCESS -class Q_GUI_EXPORT QWaylandSharedMemSurface : public QWaylandMemorySurface -{ -public: - QWaylandSharedMemSurface(); - QWaylandSharedMemSurface(QWidget *widget); - ~QWaylandSharedMemSurface(); - - void setGeometry(const QRect &rect); - - QString key() const { return QLatin1String("shm"); } - QByteArray permanentState() const; - - void setPermanentState(const QByteArray &data); - -#ifdef QT_QWayland_CLIENTBLIT - virtual void setDirectRegion(const QRegion &, int); - virtual const QRegion directRegion() const; -#endif - virtual void releaseSurface(); - -private: - bool setMemory(int memId); -}; -#endif // QT_NO_QWayland_MULTIPROCESS - -#ifndef QT_NO_PAINTONSCREEN -class Q_GUI_EXPORT QWaylandOnScreenSurface : public QWaylandMemorySurface -{ -public: - QWaylandOnScreenSurface(); - QWaylandOnScreenSurface(QWidget *widget); - ~QWaylandOnScreenSurface(); - - bool isValid() const; - QPoint painterOffset() const; - - QString key() const { return QLatin1String("OnScreen"); } - QByteArray permanentState() const; - - void setPermanentState(const QByteArray &data); - -private: - void attachToScreen(const QScreen *screen); - - const QScreen *screen; -}; -#endif // QT_NO_PAINTONSCREEN - -#ifndef QT_NO_PAINT_DEBUG -class Q_GUI_EXPORT QWaylandYellowSurface : public QWaylandWindowSurface -{ -public: - QWaylandYellowSurface(bool isClient = false); - ~QWaylandYellowSurface(); - - void setDelay(int msec) { delay = msec; } - - bool isValid() const { return true; } - - void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); - - QString key() const { return QLatin1String("Yellow"); } - QByteArray permanentState() const; - - void setPermanentState(const QByteArray &data); - - QPaintDevice *paintDevice() { return &img; } - QImage image() const { return img; } - -private: - int delay; - QSize surfaceSize; // client side - QImage img; // server side -}; -#endif // QT_NO_PAINT_DEBUG - -QT_END_NAMESPACE - -#endif // QWINDOWSURFACE_QWAYLAND_P_H diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro index 90abe1e4f8..049c118a3e 100644 --- a/src/opengl/opengl.pro +++ b/src/opengl/opengl.pro @@ -112,25 +112,25 @@ x11 { } wayland { - contains(QT_CONFIG, egl) { - SOURCES += qgl_waylandegl.cpp \ - qglpixelbuffer_egl.cpp \ - qgl_egl.cpp \ - qpixmapdata_waylandgl_egl.cpp \ - qwindowsurface_waylandgl.cpp + SOURCES += qgl_waylandegl.cpp \ + qglpixelbuffer_egl.cpp \ + qgl_egl.cpp \ + qpixmapdata_waylandgl_egl.cpp \ + qwindowsurface_waylandgl.cpp - HEADERS += qgl_egl_p.h \ - qpixmapdata_waylandgl_p.h \ - qwindowsurface_waylandgl_p.h + HEADERS += qgl_egl_p.h \ + qpixmapdata_waylandgl_p.h \ + qwindowsurface_waylandgl_p.h - } contains(QT_CONFIG, system-freetype) { embedded:CONFIG += opentype # pull in the proper freetype2 include directory include($$QT_SOURCE_TREE/config.tests/unix/freetype/freetype.pri) LIBS_PRIVATE += -lfreetype } - LIBS_PRIVATE += $$QMAKE_LIBS_DYNLOAD + LIBS_PRIVATE += $$QMAKE_LIBS_DYNLOAD -lwayland + QMAKE_CXXFLAGS += $$QT_CFLAGS_GLIB + CONFIG += wayland } mac { diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index bbe0f0713c..17433cec33 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -1641,7 +1641,11 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format) #ifndef QT_NO_EGL ownsEglContext = false; eglContext = 0; +#ifndef Q_WS_WAYLAND eglSurface = EGL_NO_SURFACE; +#else + eglImage = EGL_NO_IMAGE_KHR; +#endif #endif fbo = 0; crWin = false; diff --git a/src/opengl/qgl_egl.cpp b/src/opengl/qgl_egl.cpp index 44e8ae9d29..34fa46d60a 100644 --- a/src/opengl/qgl_egl.cpp +++ b/src/opengl/qgl_egl.cpp @@ -49,6 +49,10 @@ #include <QtGui/private/qpixmap_x11_p.h> #endif +#ifdef Q_WS_WAYLAND +#include <private/qt_wayland_p.h> +#endif + QT_BEGIN_NAMESPACE void qt_eglproperties_set_glformat(QEglProperties& eglProperties, const QGLFormat& glFormat) @@ -168,7 +172,11 @@ void QGLContext::reset() } d->ownsEglContext = false; d->eglContext = 0; +#ifndef Q_WS_WAYLAND d->eglSurface = EGL_NO_SURFACE; +#else + d->eglImage = EGL_NO_IMAGE_KHR; +#endif d->crWin = false; d->sharing = false; d->valid = false; @@ -177,6 +185,7 @@ void QGLContext::reset() QGLContextGroup::removeShare(this); } +#ifndef Q_WS_WAYLAND void QGLContext::makeCurrent() { Q_D(QGLContext); @@ -206,6 +215,19 @@ void QGLContext::makeCurrent() } } } +#else +void QGLContext::makeCurrent() +{ + Q_D(QGLContext); + if (!d->valid || !d->eglContext || d->eglImage == EGL_NO_IMAGE_KHR) { + qWarning("QGLContext::makeCurrent(): Cannot make invalid context current (%d %p %p)", d->valid, d->eglContext, d->eglImage); + return; + } + + if (d->eglContext->makeCurrent(d->eglImage)) + QGLContextPrivate::setCurrentContext(this); +} +#endif void QGLContext::doneCurrent() { @@ -222,10 +244,23 @@ void QGLContext::swapBuffers() const Q_D(const QGLContext); if (!d->valid || !d->eglContext) return; - +#ifndef Q_WS_WAYLAND d->eglContext->swapBuffers(d->eglSurfaceForDevice()); +#else + struct wl_visual *visual; + EGLint name, stride; + + QEgl::eglExportDRMImageMESA(qWayland->egl_display, d->eglImage, &name, NULL, + &stride); + visual = (struct wl_visual *)wl_display_get_premultiplied_argb_visual(qWayland->wl_display); + wl_surface_attach(d->wl_surface, name, 100, 100, stride, visual); + wl_surface_map(d->wl_surface, 0, 0, 100, 100); + wl_compositor_commit(qWayland->compositor, 10); + qWarning("swap buffers\n"); +#endif } +#ifndef Q_WS_WAYLAND void QGLContextPrivate::destroyEglSurfaceForDevice() { if (eglSurface != EGL_NO_SURFACE) { @@ -245,7 +280,17 @@ void QGLContextPrivate::destroyEglSurfaceForDevice() eglSurface = EGL_NO_SURFACE; } } +#else +void QGLContextPrivate::destroyEglSurfaceForDevice() +{ + if (eglImage != EGL_NO_IMAGE_KHR) { + QEgl::eglDestroyImageKHR(eglContext->display(), eglImage); + eglImage = EGL_NO_IMAGE_KHR; + } +} +#endif +#ifndef Q_WS_WAYLAND EGLSurface QGLContextPrivate::eglSurfaceForDevice() const { // If a QPixmapData had to create the QGLContext, we don't have a paintDevice @@ -269,6 +314,7 @@ EGLSurface QGLContextPrivate::eglSurfaceForDevice() const return eglSurface; } +#endif void QGLWidget::setMouseTracking(bool enable) { diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index a64881c919..df67d65b5c 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -347,7 +347,17 @@ public: #ifndef QT_NO_EGL uint ownsEglContext : 1; QEglContext *eglContext; +#ifdef Q_WS_WAYLAND + /* + * Wayland doesn't have a "native" drawing API aside from EGL, so we + * have to use an EGL image and a framebuffer object for our rendering + * needs + */ + EGLImageKHR eglImage; + struct wl_surface *wl_surface; +#else EGLSurface eglSurface; +#endif void destroyEglSurfaceForDevice(); EGLSurface eglSurfaceForDevice() const; #elif defined(Q_WS_X11) || defined(Q_WS_MAC) diff --git a/src/opengl/qgl_wayland.cpp b/src/opengl/qgl_wayland.cpp deleted file mode 100644 index d203646803..0000000000 --- a/src/opengl/qgl_wayland.cpp +++ /dev/null @@ -1,1815 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtOpenGL module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qgl.h" -#include "qgl_p.h" - -#include "qmap.h" -#include "qapplication.h" -#include "qcolormap.h" -#include "qdesktopwidget.h" -#include "qpixmap.h" -#include "qhash.h" -#include "qlibrary.h" -#include "qdebug.h" -#include <private/qfontengine_ft_p.h> -#include <private/qt_x11_p.h> -#include <private/qpixmap_x11_p.h> -#include <private/qimagepixmapcleanuphooks_p.h> -#ifdef Q_OS_HPUX -// for GLXPBuffer -#include <private/qglpixelbuffer_p.h> -#endif - -// We always define GLX_EXT_texture_from_pixmap ourselves because -// we can't trust system headers to do it properly -#define GLX_EXT_texture_from_pixmap 1 - -#define INT8 dummy_INT8 -#define INT32 dummy_INT32 -#include <GL/glx.h> -#undef INT8 -#undef INT32 - -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xos.h> -#ifdef Q_OS_VXWORS -# ifdef open -# undef open -# endif -# ifdef getpid -# undef getpid -# endif -#endif // Q_OS_VXWORKS -#include <X11/Xatom.h> - -#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) -#include <dlfcn.h> -#endif - -QT_BEGIN_NAMESPACE - -extern Drawable qt_x11Handle(const QPaintDevice *pd); -extern const QX11Info *qt_x11Info(const QPaintDevice *pd); - -#ifndef GLX_ARB_multisample -#define GLX_SAMPLE_BUFFERS_ARB 100000 -#define GLX_SAMPLES_ARB 100001 -#endif - -#ifndef GLX_TEXTURE_2D_BIT_EXT -#define GLX_TEXTURE_2D_BIT_EXT 0x00000002 -#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004 -#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0 -#define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1 -#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2 -#define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3 -#define GLX_Y_INVERTED_EXT 0x20D4 -#define GLX_TEXTURE_FORMAT_EXT 0x20D5 -#define GLX_TEXTURE_TARGET_EXT 0x20D6 -#define GLX_MIPMAP_TEXTURE_EXT 0x20D7 -#define GLX_TEXTURE_FORMAT_NONE_EXT 0x20D8 -#define GLX_TEXTURE_FORMAT_RGB_EXT 0x20D9 -#define GLX_TEXTURE_FORMAT_RGBA_EXT 0x20DA -#define GLX_TEXTURE_2D_EXT 0x20DC -#define GLX_TEXTURE_RECTANGLE_EXT 0x20DD -#define GLX_FRONT_LEFT_EXT 0x20DE -#endif - -/* - The qt_gl_choose_cmap function is internal and used by QGLWidget::setContext() - and GLX (not Windows). If the application can't find any sharable - colormaps, it must at least create as few colormaps as possible. The - dictionary solution below ensures only one colormap is created per visual. - Colormaps are also deleted when the application terminates. -*/ - -struct QCMapEntry { - QCMapEntry(); - ~QCMapEntry(); - - Colormap cmap; - bool alloc; - XStandardColormap scmap; -}; - -QCMapEntry::QCMapEntry() -{ - cmap = 0; - alloc = false; - scmap.colormap = 0; -} - -QCMapEntry::~QCMapEntry() -{ - if (alloc) - XFreeColormap(X11->display, cmap); -} -typedef QHash<int, QCMapEntry *> CMapEntryHash; -typedef QHash<int, QMap<int, QRgb> > GLCMapHash; -static bool mesa_gl = false; -static bool first_time = true; - -static void cleanup_cmaps(); - -struct QGLCMapCleanupHandler { - QGLCMapCleanupHandler() { - cmap_hash = new CMapEntryHash; - qglcmap_hash = new GLCMapHash; - } - ~QGLCMapCleanupHandler() { - delete cmap_hash; - delete qglcmap_hash; - } - CMapEntryHash *cmap_hash; - GLCMapHash *qglcmap_hash; -}; -Q_GLOBAL_STATIC(QGLCMapCleanupHandler, cmap_handler) - -static void cleanup_cmaps() -{ - CMapEntryHash *hash = cmap_handler()->cmap_hash; - QHash<int, QCMapEntry *>::ConstIterator it = hash->constBegin(); - while (it != hash->constEnd()) { - delete it.value(); - ++it; - } - - hash->clear(); - cmap_handler()->qglcmap_hash->clear(); -} - -Colormap qt_gl_choose_cmap(Display *dpy, XVisualInfo *vi) -{ - if (first_time) { - const char *v = glXQueryServerString(dpy, vi->screen, GLX_VERSION); - if (v) - mesa_gl = (strstr(v, "Mesa") != 0); - first_time = false; - } - - CMapEntryHash *hash = cmap_handler()->cmap_hash; - CMapEntryHash::ConstIterator it = hash->constFind((long) vi->visualid + (vi->screen * 256)); - if (it != hash->constEnd()) - return it.value()->cmap; // found colormap for visual - - if (vi->visualid == - XVisualIDFromVisual((Visual *) QX11Info::appVisual(vi->screen))) { - // qDebug("Using x11AppColormap"); - return QX11Info::appColormap(vi->screen); - } - - QCMapEntry *x = new QCMapEntry(); - - XStandardColormap *c; - int n, i; - - // qDebug("Choosing cmap for vID %0x", vi->visualid); - - if (mesa_gl) { // we're using MesaGL - Atom hp_cmaps = XInternAtom(dpy, "_HP_RGB_SMOOTH_MAP_LIST", true); - if (hp_cmaps && vi->visual->c_class == TrueColor && vi->depth == 8) { - if (XGetRGBColormaps(dpy,RootWindow(dpy,vi->screen),&c,&n, - hp_cmaps)) { - i = 0; - while (i < n && x->cmap == 0) { - if (c[i].visualid == vi->visual->visualid) { - x->cmap = c[i].colormap; - x->scmap = c[i]; - //qDebug("Using HP_RGB scmap"); - - } - i++; - } - XFree((char *)c); - } - } - } - if (!x->cmap) { - if (XGetRGBColormaps(dpy,RootWindow(dpy,vi->screen),&c,&n, - XA_RGB_DEFAULT_MAP)) { - for (int i = 0; i < n && x->cmap == 0; ++i) { - if (!c[i].red_max || - !c[i].green_max || - !c[i].blue_max || - !c[i].red_mult || - !c[i].green_mult || - !c[i].blue_mult) - continue; // invalid stdcmap - if (c[i].visualid == vi->visualid) { - x->cmap = c[i].colormap; - x->scmap = c[i]; - //qDebug("Using RGB_DEFAULT scmap"); - } - } - XFree((char *)c); - } - } - if (!x->cmap) { // no shared cmap found - x->cmap = XCreateColormap(dpy, RootWindow(dpy,vi->screen), vi->visual, - AllocNone); - x->alloc = true; - // qDebug("Allocating cmap"); - } - - // colormap hash should be cleanup only when the QApplication dtor is called - if (hash->isEmpty()) - qAddPostRoutine(cleanup_cmaps); - - // associate cmap with visualid - hash->insert((long) vi->visualid + (vi->screen * 256), x); - return x->cmap; -} - -struct QTransColor -{ - VisualID vis; - int screen; - long color; -}; - -static QVector<QTransColor> trans_colors; -static int trans_colors_init = false; - -static void find_trans_colors() -{ - struct OverlayProp { - long visual; - long type; - long value; - long layer; - }; - - trans_colors_init = true; - - Display* appDisplay = X11->display; - - int scr; - int lastsize = 0; - for (scr = 0; scr < ScreenCount(appDisplay); scr++) { - QWidget* rootWin = QApplication::desktop()->screen(scr); - if (!rootWin) - return; // Should not happen - Atom overlayVisualsAtom = XInternAtom(appDisplay, - "SERVER_OVERLAY_VISUALS", True); - if (overlayVisualsAtom == XNone) - return; // Server has no overlays - - Atom actualType; - int actualFormat; - ulong nItems; - ulong bytesAfter; - unsigned char *retval = 0; - int res = XGetWindowProperty(appDisplay, rootWin->winId(), - overlayVisualsAtom, 0, 10000, False, - overlayVisualsAtom, &actualType, - &actualFormat, &nItems, &bytesAfter, - &retval); - - if (res != Success || actualType != overlayVisualsAtom - || actualFormat != 32 || nItems < 4 || !retval) - return; // Error reading property - - OverlayProp *overlayProps = (OverlayProp *)retval; - - int numProps = nItems / 4; - trans_colors.resize(lastsize + numProps); - int j = lastsize; - for (int i = 0; i < numProps; i++) { - if (overlayProps[i].type == 1) { - trans_colors[j].vis = (VisualID)overlayProps[i].visual; - trans_colors[j].screen = scr; - trans_colors[j].color = (int)overlayProps[i].value; - j++; - } - } - XFree(overlayProps); - lastsize = j; - trans_colors.resize(lastsize); - } -} - -/***************************************************************************** - QGLFormat UNIX/GLX-specific code - *****************************************************************************/ - -void* qglx_getProcAddress(const char* procName) -{ - // On systems where the GL driver is pluggable (like Mesa), we have to use - // the glXGetProcAddressARB extension to resolve other function pointers as - // the symbols wont be in the GL library, but rather in a plugin loaded by - // the GL library. - typedef void* (*qt_glXGetProcAddressARB)(const char *); - static qt_glXGetProcAddressARB glXGetProcAddressARB = 0; - static bool triedResolvingGlxGetProcAddress = false; - if (!triedResolvingGlxGetProcAddress) { - triedResolvingGlxGetProcAddress = true; - QGLExtensionMatcher extensions(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS)); - if (extensions.match("GLX_ARB_get_proc_address")) { -#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) - void *handle = dlopen(NULL, RTLD_LAZY); - if (handle) { - glXGetProcAddressARB = (qt_glXGetProcAddressARB) dlsym(handle, "glXGetProcAddressARB"); - dlclose(handle); - } - if (!glXGetProcAddressARB) -#endif - { -#if !defined(QT_NO_LIBRARY) - extern const QString qt_gl_library_name(); - QLibrary lib(qt_gl_library_name()); - glXGetProcAddressARB = (qt_glXGetProcAddressARB) lib.resolve("glXGetProcAddressARB"); -#endif - } - } - } - - void *procAddress = 0; - if (glXGetProcAddressARB) - procAddress = glXGetProcAddressARB(procName); - - // If glXGetProcAddress didn't work, try looking the symbol up in the GL library -#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) - if (!procAddress) { - void *handle = dlopen(NULL, RTLD_LAZY); - if (handle) { - procAddress = dlsym(handle, procName); - dlclose(handle); - } - } -#endif -#if !defined(QT_NO_LIBRARY) - if (!procAddress) { - extern const QString qt_gl_library_name(); - QLibrary lib(qt_gl_library_name()); - procAddress = lib.resolve(procName); - } -#endif - - return procAddress; -} - -bool QGLFormat::hasOpenGL() -{ - return glXQueryExtension(X11->display, 0, 0) != 0; -} - - -bool QGLFormat::hasOpenGLOverlays() -{ - if (!trans_colors_init) - find_trans_colors(); - return trans_colors.size() > 0; -} - -/***************************************************************************** - QGLContext UNIX/GLX-specific code - *****************************************************************************/ - -bool QGLContext::chooseContext(const QGLContext* shareContext) -{ - Q_D(QGLContext); - const QX11Info *xinfo = qt_x11Info(d->paintDevice); - - Display* disp = xinfo->display(); - d->vi = chooseVisual(); - if (!d->vi) - return false; - - if (deviceIsPixmap() && - (((XVisualInfo*)d->vi)->depth != xinfo->depth() || - ((XVisualInfo*)d->vi)->screen != xinfo->screen())) - { - XFree(d->vi); - XVisualInfo appVisInfo; - memset(&appVisInfo, 0, sizeof(XVisualInfo)); - appVisInfo.visualid = XVisualIDFromVisual((Visual *) xinfo->visual()); - appVisInfo.screen = xinfo->screen(); - int nvis; - d->vi = XGetVisualInfo(disp, VisualIDMask | VisualScreenMask, &appVisInfo, &nvis); - if (!d->vi) - return false; - - int useGL; - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_USE_GL, &useGL); - if (!useGL) - return false; //# Chickening out already... - } - int res; - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_LEVEL, &res); - d->glFormat.setPlane(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_DOUBLEBUFFER, &res); - d->glFormat.setDoubleBuffer(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_DEPTH_SIZE, &res); - d->glFormat.setDepth(res); - if (d->glFormat.depth()) - d->glFormat.setDepthBufferSize(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_RGBA, &res); - d->glFormat.setRgba(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_RED_SIZE, &res); - d->glFormat.setRedBufferSize(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_GREEN_SIZE, &res); - d->glFormat.setGreenBufferSize(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_BLUE_SIZE, &res); - d->glFormat.setBlueBufferSize(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_ALPHA_SIZE, &res); - d->glFormat.setAlpha(res); - if (d->glFormat.alpha()) - d->glFormat.setAlphaBufferSize(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_ACCUM_RED_SIZE, &res); - d->glFormat.setAccum(res); - if (d->glFormat.accum()) - d->glFormat.setAccumBufferSize(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_STENCIL_SIZE, &res); - d->glFormat.setStencil(res); - if (d->glFormat.stencil()) - d->glFormat.setStencilBufferSize(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_STEREO, &res); - d->glFormat.setStereo(res); - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_SAMPLE_BUFFERS_ARB, &res); - d->glFormat.setSampleBuffers(res); - if (d->glFormat.sampleBuffers()) { - glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_SAMPLES_ARB, &res); - d->glFormat.setSamples(res); - } - - Bool direct = format().directRendering() ? True : False; - - if (shareContext && - (!shareContext->isValid() || !shareContext->d_func()->cx)) { - qWarning("QGLContext::chooseContext(): Cannot share with invalid context"); - shareContext = 0; - } - - // 1. Sharing between rgba and color-index will give wrong colors. - // 2. Contexts cannot be shared btw. direct/non-direct renderers. - // 3. Pixmaps cannot share contexts that are set up for direct rendering. - // 4. If the contexts are not created on the same screen, they can't be shared - - if (shareContext - && (format().rgba() != shareContext->format().rgba() - || (deviceIsPixmap() && glXIsDirect(disp, (GLXContext)shareContext->d_func()->cx)) - || (shareContext->d_func()->screen != xinfo->screen()))) - { - shareContext = 0; - } - - d->cx = 0; - if (shareContext) { - d->cx = glXCreateContext(disp, (XVisualInfo *)d->vi, - (GLXContext)shareContext->d_func()->cx, direct); - d->screen = ((XVisualInfo*)d->vi)->screen; - if (d->cx) { - QGLContext *share = const_cast<QGLContext *>(shareContext); - d->sharing = true; - share->d_func()->sharing = true; - } - } - if (!d->cx) { - d->cx = glXCreateContext(disp, (XVisualInfo *)d->vi, NULL, direct); - d->screen = ((XVisualInfo*)d->vi)->screen; - } - if (!d->cx) - return false; - d->glFormat.setDirectRendering(glXIsDirect(disp, (GLXContext)d->cx)); - if (deviceIsPixmap()) { -#if defined(GLX_MESA_pixmap_colormap) && defined(QGL_USE_MESA_EXT) - d->gpm = glXCreateGLXPixmapMESA(disp, (XVisualInfo *)d->vi, - qt_x11Handle(d->paintDevice), - qt_gl_choose_cmap(disp, (XVisualInfo *)d->vi)); -#else - d->gpm = (quint32)glXCreateGLXPixmap(disp, (XVisualInfo *)d->vi, - qt_x11Handle(d->paintDevice)); -#endif - if (!d->gpm) - return false; - } - QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen())); - if (extensions.match("GLX_SGI_video_sync")) { - if (d->glFormat.swapInterval() == -1) - d->glFormat.setSwapInterval(0); - } else { - d->glFormat.setSwapInterval(-1); - } - return true; -} - -/* - See qgl.cpp for qdoc comment. - */ -void *QGLContext::chooseVisual() -{ - Q_D(QGLContext); - static const int bufDepths[] = { 8, 4, 2, 1 }; // Try 16, 12 also? - //todo: if pixmap, also make sure that vi->depth == pixmap->depth - void* vis = 0; - int i = 0; - bool fail = false; - QGLFormat fmt = format(); - bool tryDouble = !fmt.doubleBuffer(); // Some GL impl's only have double - bool triedDouble = false; - bool triedSample = false; - if (fmt.sampleBuffers()) - fmt.setSampleBuffers(QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers); - while(!fail && !(vis = tryVisual(fmt, bufDepths[i]))) { - if (!fmt.rgba() && bufDepths[i] > 1) { - i++; - continue; - } - if (tryDouble) { - fmt.setDoubleBuffer(true); - tryDouble = false; - triedDouble = true; - continue; - } else if (triedDouble) { - fmt.setDoubleBuffer(false); - triedDouble = false; - } - if (!triedSample && fmt.sampleBuffers()) { - fmt.setSampleBuffers(false); - triedSample = true; - continue; - } - if (fmt.stereo()) { - fmt.setStereo(false); - continue; - } - if (fmt.accum()) { - fmt.setAccum(false); - continue; - } - if (fmt.stencil()) { - fmt.setStencil(false); - continue; - } - if (fmt.alpha()) { - fmt.setAlpha(false); - continue; - } - if (fmt.depth()) { - fmt.setDepth(false); - continue; - } - if (fmt.doubleBuffer()) { - fmt.setDoubleBuffer(false); - continue; - } - fail = true; - } - d->glFormat = fmt; - return vis; -} - -/* - See qgl.cpp for qdoc comment. - */ -void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth) -{ - Q_D(QGLContext); - int spec[45]; - int i = 0; - spec[i++] = GLX_LEVEL; - spec[i++] = f.plane(); - const QX11Info *xinfo = qt_x11Info(d->paintDevice); - bool useFBConfig = false; - -#if defined(GLX_VERSION_1_3) && !defined(QT_NO_XRENDER) && !defined(Q_OS_HPUX) - /* - HPUX defines GLX_VERSION_1_3 but does not implement the corresponding functions. - Specifically glXChooseFBConfig and glXGetVisualFromFBConfig are not implemented. - */ - QWidget* widget = 0; - if (d->paintDevice->devType() == QInternal::Widget) - widget = static_cast<QWidget*>(d->paintDevice); - - // Only use glXChooseFBConfig for widgets if we're trying to get an ARGB visual - if (widget && widget->testAttribute(Qt::WA_TranslucentBackground) && X11->use_xrender) - useFBConfig = true; -#endif - -#if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info) - static bool useTranspExt = false; - static bool useTranspExtChecked = false; - if (f.plane() && !useTranspExtChecked && d->paintDevice) { - QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen())); - useTranspExt = extensions.match("GLX_EXT_visual_info"); - //# (A bit simplistic; that could theoretically be a substring) - if (useTranspExt) { - QByteArray cstr(glXGetClientString(xinfo->display(), GLX_VENDOR)); - useTranspExt = !cstr.contains("Xi Graphics"); // bug workaround - if (useTranspExt) { - // bug workaround - some systems (eg. FireGL) refuses to return an overlay - // visual if the GLX_TRANSPARENT_TYPE_EXT attribute is specified, even if - // the implementation supports transparent overlays - int tmpSpec[] = { GLX_LEVEL, f.plane(), GLX_TRANSPARENT_TYPE_EXT, - f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT, - XNone }; - XVisualInfo * vinf = glXChooseVisual(xinfo->display(), xinfo->screen(), tmpSpec); - if (!vinf) { - useTranspExt = false; - } - } - } - - useTranspExtChecked = true; - } - if (f.plane() && useTranspExt && !useFBConfig) { - // Required to avoid non-transparent overlay visual(!) on some systems - spec[i++] = GLX_TRANSPARENT_TYPE_EXT; - spec[i++] = f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT; - } -#endif - -#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) - // GLX_RENDER_TYPE is only in glx >=1.3 - if (useFBConfig) { - spec[i++] = GLX_RENDER_TYPE; - spec[i++] = f.rgba() ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; - } -#endif - - if (f.doubleBuffer()) - spec[i++] = GLX_DOUBLEBUFFER; - if (useFBConfig) - spec[i++] = True; - if (f.depth()) { - spec[i++] = GLX_DEPTH_SIZE; - spec[i++] = f.depthBufferSize() == -1 ? 1 : f.depthBufferSize(); - } - if (f.stereo()) { - spec[i++] = GLX_STEREO; - if (useFBConfig) - spec[i++] = True; - } - if (f.stencil()) { - spec[i++] = GLX_STENCIL_SIZE; - spec[i++] = f.stencilBufferSize() == -1 ? 1 : f.stencilBufferSize(); - } - if (f.rgba()) { - if (!useFBConfig) - spec[i++] = GLX_RGBA; - spec[i++] = GLX_RED_SIZE; - spec[i++] = f.redBufferSize() == -1 ? 1 : f.redBufferSize(); - spec[i++] = GLX_GREEN_SIZE; - spec[i++] = f.greenBufferSize() == -1 ? 1 : f.greenBufferSize(); - spec[i++] = GLX_BLUE_SIZE; - spec[i++] = f.blueBufferSize() == -1 ? 1 : f.blueBufferSize(); - if (f.alpha()) { - spec[i++] = GLX_ALPHA_SIZE; - spec[i++] = f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize(); - } - if (f.accum()) { - spec[i++] = GLX_ACCUM_RED_SIZE; - spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); - spec[i++] = GLX_ACCUM_GREEN_SIZE; - spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); - spec[i++] = GLX_ACCUM_BLUE_SIZE; - spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); - if (f.alpha()) { - spec[i++] = GLX_ACCUM_ALPHA_SIZE; - spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); - } - } - } else { - spec[i++] = GLX_BUFFER_SIZE; - spec[i++] = bufDepth; - } - - if (f.sampleBuffers()) { - spec[i++] = GLX_SAMPLE_BUFFERS_ARB; - spec[i++] = 1; - spec[i++] = GLX_SAMPLES_ARB; - spec[i++] = f.samples() == -1 ? 4 : f.samples(); - } - -#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) - if (useFBConfig) { - spec[i++] = GLX_DRAWABLE_TYPE; - switch(d->paintDevice->devType()) { - case QInternal::Pixmap: - spec[i++] = GLX_PIXMAP_BIT; - break; - case QInternal::Pbuffer: - spec[i++] = GLX_PBUFFER_BIT; - break; - default: - qWarning("QGLContext: Unknown paint device type %d", d->paintDevice->devType()); - // Fall-through & assume it's a window - case QInternal::Widget: - spec[i++] = GLX_WINDOW_BIT; - break; - }; - } -#endif - - spec[i] = XNone; - - - XVisualInfo* chosenVisualInfo = 0; - -#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) - while (useFBConfig) { - GLXFBConfig *configs; - int configCount = 0; - configs = glXChooseFBConfig(xinfo->display(), xinfo->screen(), spec, &configCount); - - if (!configs) - break; // fallback to trying glXChooseVisual - - for (i = 0; i < configCount; ++i) { - XVisualInfo* vi; - vi = glXGetVisualFromFBConfig(xinfo->display(), configs[i]); - if (!vi) - continue; - -#if !defined(QT_NO_XRENDER) - QWidget* w = 0; - if (d->paintDevice->devType() == QInternal::Widget) - w = static_cast<QWidget*>(d->paintDevice); - - if (w && w->testAttribute(Qt::WA_TranslucentBackground) && f.alpha()) { - // Attempt to find a config who's visual has a proper alpha channel - XRenderPictFormat *pictFormat; - pictFormat = XRenderFindVisualFormat(xinfo->display(), vi->visual); - - if (pictFormat && (pictFormat->type == PictTypeDirect) && pictFormat->direct.alphaMask) { - // The pict format for the visual matching the FBConfig indicates ARGB - if (chosenVisualInfo) - XFree(chosenVisualInfo); - chosenVisualInfo = vi; - break; - } - } else -#endif //QT_NO_XRENDER - if (chosenVisualInfo) { - // If we've got a visual we can use and we're not trying to find one with a - // real alpha channel, we might as well just use the one we've got - break; - } - - if (!chosenVisualInfo) - chosenVisualInfo = vi; // Have something to fall back to - else - XFree(vi); - } - - XFree(configs); - break; - } -#endif // defined(GLX_VERSION_1_3) - - if (!chosenVisualInfo) - chosenVisualInfo = glXChooseVisual(xinfo->display(), xinfo->screen(), spec); - - return chosenVisualInfo; -} - - -void QGLContext::reset() -{ - Q_D(QGLContext); - if (!d->valid) - return; - d->cleanup(); - const QX11Info *xinfo = qt_x11Info(d->paintDevice); - doneCurrent(); - if (d->gpm) - glXDestroyGLXPixmap(xinfo->display(), (GLXPixmap)d->gpm); - d->gpm = 0; - glXDestroyContext(xinfo->display(), (GLXContext)d->cx); - if (d->vi) - XFree(d->vi); - d->vi = 0; - d->cx = 0; - d->crWin = false; - d->sharing = false; - d->valid = false; - d->transpColor = QColor(); - d->initDone = false; - QGLContextGroup::removeShare(this); -} - - -void QGLContext::makeCurrent() -{ - Q_D(QGLContext); - if (!d->valid) { - qWarning("QGLContext::makeCurrent(): Cannot make invalid context current."); - return; - } - const QX11Info *xinfo = qt_x11Info(d->paintDevice); - bool ok = true; - if (d->paintDevice->devType() == QInternal::Pixmap) { - ok = glXMakeCurrent(xinfo->display(), (GLXPixmap)d->gpm, (GLXContext)d->cx); - } else if (d->paintDevice->devType() == QInternal::Pbuffer) { - ok = glXMakeCurrent(xinfo->display(), (GLXPbuffer)d->pbuf, (GLXContext)d->cx); - } else if (d->paintDevice->devType() == QInternal::Widget) { - ok = glXMakeCurrent(xinfo->display(), ((QWidget *)d->paintDevice)->winId(), (GLXContext)d->cx); - } - if (!ok) - qWarning("QGLContext::makeCurrent(): Failed."); - - if (ok) - QGLContextPrivate::setCurrentContext(this); -} - -void QGLContext::doneCurrent() -{ - Q_D(QGLContext); - glXMakeCurrent(qt_x11Info(d->paintDevice)->display(), 0, 0); - QGLContextPrivate::setCurrentContext(0); -} - - -void QGLContext::swapBuffers() const -{ - Q_D(const QGLContext); - if (!d->valid) - return; - if (!deviceIsPixmap()) { - int interval = d->glFormat.swapInterval(); - if (interval > 0) { - typedef int (*qt_glXGetVideoSyncSGI)(uint *); - typedef int (*qt_glXWaitVideoSyncSGI)(int, int, uint *); - static qt_glXGetVideoSyncSGI glXGetVideoSyncSGI = 0; - static qt_glXWaitVideoSyncSGI glXWaitVideoSyncSGI = 0; - static bool resolved = false; - if (!resolved) { - const QX11Info *xinfo = qt_x11Info(d->paintDevice); - QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen())); - if (extensions.match("GLX_SGI_video_sync")) { - glXGetVideoSyncSGI = (qt_glXGetVideoSyncSGI)qglx_getProcAddress("glXGetVideoSyncSGI"); - glXWaitVideoSyncSGI = (qt_glXWaitVideoSyncSGI)qglx_getProcAddress("glXWaitVideoSyncSGI"); - } - resolved = true; - } - if (glXGetVideoSyncSGI && glXWaitVideoSyncSGI) { - uint counter; - if (!glXGetVideoSyncSGI(&counter)) - glXWaitVideoSyncSGI(interval + 1, (counter + interval) % (interval + 1), &counter); - } - } - glXSwapBuffers(qt_x11Info(d->paintDevice)->display(), - static_cast<QWidget *>(d->paintDevice)->winId()); - } -} - -QColor QGLContext::overlayTransparentColor() const -{ - if (isValid()) - return Qt::transparent; - return QColor(); // Invalid color -} - -static uint qt_transparent_pixel(VisualID id, int screen) -{ - for (int i = 0; i < trans_colors.size(); i++) { - if (trans_colors[i].vis == id && trans_colors[i].screen == screen) - return trans_colors[i].color; - } - return 0; -} - -uint QGLContext::colorIndex(const QColor& c) const -{ - Q_D(const QGLContext); - int screen = ((XVisualInfo *)d->vi)->screen; - QColormap colmap = QColormap::instance(screen); - if (isValid()) { - if (format().plane() && c == Qt::transparent) { - return qt_transparent_pixel(((XVisualInfo *)d->vi)->visualid, - ((XVisualInfo *)d->vi)->screen); - } - if (((XVisualInfo*)d->vi)->visualid == - XVisualIDFromVisual((Visual *) QX11Info::appVisual(screen))) - return colmap.pixel(c); // We're using QColor's cmap - - XVisualInfo *info = (XVisualInfo *) d->vi; - CMapEntryHash *hash = cmap_handler()->cmap_hash; - CMapEntryHash::ConstIterator it = hash->constFind(long(info->visualid) - + (info->screen * 256)); - QCMapEntry *x = 0; - if (it != hash->constEnd()) - x = it.value(); - if (x && !x->alloc) { // It's a standard colormap - int rf = (int)(((float)c.red() * (x->scmap.red_max+1))/256.0); - int gf = (int)(((float)c.green() * (x->scmap.green_max+1))/256.0); - int bf = (int)(((float)c.blue() * (x->scmap.blue_max+1))/256.0); - uint p = x->scmap.base_pixel - + (rf * x->scmap.red_mult) - + (gf * x->scmap.green_mult) - + (bf * x->scmap.blue_mult); - return p; - } else { - QMap<int, QRgb> &cmap = (*cmap_handler()->qglcmap_hash)[(long)info->visualid]; - - // already in the map? - QRgb target = c.rgb(); - QMap<int, QRgb>::Iterator it = cmap.begin(); - for (; it != cmap.end(); ++it) { - if ((*it) == target) - return it.key(); - } - - // need to alloc color - unsigned long plane_mask[2]; - unsigned long color_map_entry; - if (!XAllocColorCells (QX11Info::display(), x->cmap, true, plane_mask, 0, - &color_map_entry, 1)) - return colmap.pixel(c); - - XColor col; - col.flags = DoRed | DoGreen | DoBlue; - col.pixel = color_map_entry; - col.red = (ushort)((qRed(c.rgb()) / 255.0) * 65535.0 + 0.5); - col.green = (ushort)((qGreen(c.rgb()) / 255.0) * 65535.0 + 0.5); - col.blue = (ushort)((qBlue(c.rgb()) / 255.0) * 65535.0 + 0.5); - XStoreColor(QX11Info::display(), x->cmap, &col); - - cmap.insert(color_map_entry, target); - return color_map_entry; - } - } - return 0; -} - -#ifndef QT_NO_FONTCONFIG -/*! \internal - This is basically a substitute for glxUseXFont() which can only - handle XLFD fonts. This version relies on freetype to render the - glyphs, but it works with all fonts that fontconfig provides - both - antialiased and aliased bitmap and outline fonts. -*/ -static void qgl_use_font(QFontEngineFT *engine, int first, int count, int listBase) -{ - GLfloat color[4]; - glGetFloatv(GL_CURRENT_COLOR, color); - - // save the pixel unpack state - GLint gl_swapbytes, gl_lsbfirst, gl_rowlength, gl_skiprows, gl_skippixels, gl_alignment; - glGetIntegerv (GL_UNPACK_SWAP_BYTES, &gl_swapbytes); - glGetIntegerv (GL_UNPACK_LSB_FIRST, &gl_lsbfirst); - glGetIntegerv (GL_UNPACK_ROW_LENGTH, &gl_rowlength); - glGetIntegerv (GL_UNPACK_SKIP_ROWS, &gl_skiprows); - glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &gl_skippixels); - glGetIntegerv (GL_UNPACK_ALIGNMENT, &gl_alignment); - - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - const bool antialiased = engine->drawAntialiased(); - FT_Face face = engine->lockFace(); - - // start generating font glyphs - for (int i = first; i < count; ++i) { - int list = listBase + i; - GLfloat x0, y0, dx, dy; - - FT_Error err; - - err = FT_Load_Glyph(face, FT_Get_Char_Index(face, i), FT_LOAD_DEFAULT); - if (err) { - qDebug("failed loading glyph %d from font", i); - Q_ASSERT(!err); - } - err = FT_Render_Glyph(face->glyph, (antialiased ? FT_RENDER_MODE_NORMAL - : FT_RENDER_MODE_MONO)); - if (err) { - qDebug("failed rendering glyph %d from font", i); - Q_ASSERT(!err); - } - - FT_Bitmap bm = face->glyph->bitmap; - x0 = face->glyph->metrics.horiBearingX >> 6; - y0 = (face->glyph->metrics.height - face->glyph->metrics.horiBearingY) >> 6; - dx = face->glyph->metrics.horiAdvance >> 6; - dy = 0; - int sz = bm.pitch * bm.rows; - uint *aa_glyph = 0; - uchar *ua_glyph = 0; - - if (antialiased) - aa_glyph = new uint[sz]; - else - ua_glyph = new uchar[sz]; - - // convert to GL format - for (int y = 0; y < bm.rows; ++y) { - for (int x = 0; x < bm.pitch; ++x) { - int c1 = y*bm.pitch + x; - int c2 = (bm.rows - y - 1) > 0 ? (bm.rows-y-1)*bm.pitch + x : x; - if (antialiased) { - aa_glyph[c1] = (int(color[0]*255) << 24) - | (int(color[1]*255) << 16) - | (int(color[2]*255) << 8) | bm.buffer[c2]; - } else { - ua_glyph[c1] = bm.buffer[c2]; - } - } - } - - glNewList(list, GL_COMPILE); - if (antialiased) { - // calling glBitmap() is just a trick to move the current - // raster pos, since glGet*() won't work in display lists - glBitmap(0, 0, 0, 0, x0, -y0, 0); - glDrawPixels(bm.pitch, bm.rows, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, aa_glyph); - glBitmap(0, 0, 0, 0, dx-x0, y0, 0); - } else { - glBitmap(bm.pitch*8, bm.rows, -x0, y0, dx, dy, ua_glyph); - } - glEndList(); - antialiased ? delete[] aa_glyph : delete[] ua_glyph; - } - - engine->unlockFace(); - - // restore pixel unpack settings - glPixelStorei(GL_UNPACK_SWAP_BYTES, gl_swapbytes); - glPixelStorei(GL_UNPACK_LSB_FIRST, gl_lsbfirst); - glPixelStorei(GL_UNPACK_ROW_LENGTH, gl_rowlength); - glPixelStorei(GL_UNPACK_SKIP_ROWS, gl_skiprows); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, gl_skippixels); - glPixelStorei(GL_UNPACK_ALIGNMENT, gl_alignment); -} -#endif - -#undef d -void QGLContext::generateFontDisplayLists(const QFont & fnt, int listBase) -{ - QFont f(fnt); - QFontEngine *engine = f.d->engineForScript(QUnicodeTables::Common); - - if (engine->type() == QFontEngine::Multi) - engine = static_cast<QFontEngineMulti *>(engine)->engine(0); -#ifndef QT_NO_FONTCONFIG - if(engine->type() == QFontEngine::Freetype) { - qgl_use_font(static_cast<QFontEngineFT *>(engine), 0, 256, listBase); - return; - } -#endif - // glXUseXFont() only works with XLFD font structures and a few GL - // drivers crash if 0 is passed as the font handle - f.setStyleStrategy(QFont::OpenGLCompatible); - if (f.handle() && engine->type() == QFontEngine::XLFD) - glXUseXFont(static_cast<Font>(f.handle()), 0, 256, listBase); -} - -void *QGLContext::getProcAddress(const QString &proc) const -{ - typedef void *(*qt_glXGetProcAddressARB)(const GLubyte *); - static qt_glXGetProcAddressARB glXGetProcAddressARB = 0; - static bool resolved = false; - - if (resolved && !glXGetProcAddressARB) - return 0; - if (!glXGetProcAddressARB) { - QGLExtensionMatcher extensions(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS)); - if (extensions.match("GLX_ARB_get_proc_address")) { -#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) - void *handle = dlopen(NULL, RTLD_LAZY); - if (handle) { - glXGetProcAddressARB = (qt_glXGetProcAddressARB) dlsym(handle, "glXGetProcAddressARB"); - dlclose(handle); - } - if (!glXGetProcAddressARB) -#endif - { -#if !defined(QT_NO_LIBRARY) - extern const QString qt_gl_library_name(); - QLibrary lib(qt_gl_library_name()); - glXGetProcAddressARB = (qt_glXGetProcAddressARB) lib.resolve("glXGetProcAddressARB"); -#endif - } - } - resolved = true; - } - if (!glXGetProcAddressARB) - return 0; - return glXGetProcAddressARB(reinterpret_cast<const GLubyte *>(proc.toLatin1().data())); -} - -/* - QGLTemporaryContext implementation -*/ - -class QGLTemporaryContextPrivate { -public: - bool initialized; - Window drawable; - GLXContext context; - GLXDrawable oldDrawable; - GLXContext oldContext; -}; - -QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) - : d(new QGLTemporaryContextPrivate) -{ - d->initialized = false; - d->oldDrawable = 0; - d->oldContext = 0; - int screen = 0; - - int attribs[] = {GLX_RGBA, XNone}; - XVisualInfo *vi = glXChooseVisual(X11->display, screen, attribs); - if (!vi) { - qWarning("QGLTempContext: No GL capable X visuals available."); - return; - } - - int useGL; - glXGetConfig(X11->display, vi, GLX_USE_GL, &useGL); - if (!useGL) { - XFree(vi); - return; - } - - d->oldDrawable = glXGetCurrentDrawable(); - d->oldContext = glXGetCurrentContext(); - - XSetWindowAttributes a; - a.colormap = qt_gl_choose_cmap(X11->display, vi); - d->drawable = XCreateWindow(X11->display, RootWindow(X11->display, screen), - 0, 0, 1, 1, 0, - vi->depth, InputOutput, vi->visual, - CWColormap, &a); - d->context = glXCreateContext(X11->display, vi, 0, True); - if (d->context && glXMakeCurrent(X11->display, d->drawable, d->context)) { - d->initialized = true; - } else { - qWarning("QGLTempContext: Unable to create GL context."); - XDestroyWindow(X11->display, d->drawable); - } - XFree(vi); -} - -QGLTemporaryContext::~QGLTemporaryContext() -{ - if (d->initialized) { - glXMakeCurrent(X11->display, 0, 0); - glXDestroyContext(X11->display, d->context); - XDestroyWindow(X11->display, d->drawable); - } - if (d->oldDrawable && d->oldContext) - glXMakeCurrent(X11->display, d->oldDrawable, d->oldContext); -} - -/***************************************************************************** - QGLOverlayWidget (Internal overlay class for X11) - *****************************************************************************/ - -class QGLOverlayWidget : public QGLWidget -{ - Q_OBJECT -public: - QGLOverlayWidget(const QGLFormat& format, QGLWidget* parent, const QGLWidget* shareWidget=0); - -protected: - void initializeGL(); - void paintGL(); - void resizeGL(int w, int h); - bool x11Event(XEvent *e) { return realWidget->x11Event(e); } - -private: - QGLWidget* realWidget; - -private: - Q_DISABLE_COPY(QGLOverlayWidget) -}; - - -QGLOverlayWidget::QGLOverlayWidget(const QGLFormat& format, QGLWidget* parent, - const QGLWidget* shareWidget) - : QGLWidget(format, parent, shareWidget ? shareWidget->d_func()->olw : 0) -{ - setAttribute(Qt::WA_X11OpenGLOverlay); - realWidget = parent; -} - - - -void QGLOverlayWidget::initializeGL() -{ - QColor transparentColor = context()->overlayTransparentColor(); - if (transparentColor.isValid()) - qglClearColor(transparentColor); - else - qWarning("QGLOverlayWidget::initializeGL(): Could not get transparent color"); - realWidget->initializeOverlayGL(); -} - - -void QGLOverlayWidget::resizeGL(int w, int h) -{ - glViewport(0, 0, w, h); - realWidget->resizeOverlayGL(w, h); -} - - -void QGLOverlayWidget::paintGL() -{ - realWidget->paintOverlayGL(); -} - -#undef Bool -QT_BEGIN_INCLUDE_NAMESPACE -#include "qgl_x11.moc" -QT_END_INCLUDE_NAMESPACE - -/***************************************************************************** - QGLWidget UNIX/GLX-specific code - *****************************************************************************/ -void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget *shareWidget) -{ - Q_Q(QGLWidget); - initContext(context, shareWidget); - olw = 0; - - if (q->isValid() && context->format().hasOverlay()) { - QString olwName = q->objectName(); - olwName += QLatin1String("-QGL_internal_overlay_widget"); - olw = new QGLOverlayWidget(QGLFormat::defaultOverlayFormat(), q, shareWidget); - olw->setObjectName(olwName); - if (olw->isValid()) { - olw->setAutoBufferSwap(false); - olw->setFocusProxy(q); - } - else { - delete olw; - olw = 0; - glcx->d_func()->glFormat.setOverlay(false); - } - } -} - -bool QGLWidgetPrivate::renderCxPm(QPixmap* pm) -{ - Q_Q(QGLWidget); - if (((XVisualInfo*)glcx->d_func()->vi)->depth != pm->depth()) - return false; - - GLXPixmap glPm; -#if defined(GLX_MESA_pixmap_colormap) && defined(QGL_USE_MESA_EXT) - glPm = glXCreateGLXPixmapMESA(X11->display, - (XVisualInfo*)glcx->vi, - (Pixmap)pm->handle(), - qt_gl_choose_cmap(pm->X11->display, - (XVisualInfo*)glcx->vi)); -#else - glPm = (quint32)glXCreateGLXPixmap(X11->display, - (XVisualInfo*)glcx->d_func()->vi, - (Pixmap)pm->handle()); -#endif - - if (!glXMakeCurrent(X11->display, glPm, (GLXContext)glcx->d_func()->cx)) { - glXDestroyGLXPixmap(X11->display, glPm); - return false; - } - - glDrawBuffer(GL_FRONT); - if (!glcx->initialized()) - q->glInit(); - q->resizeGL(pm->width(), pm->height()); - q->paintGL(); - glFlush(); - q->makeCurrent(); - glXDestroyGLXPixmap(X11->display, glPm); - q->resizeGL(q->width(), q->height()); - return true; -} - -/*! \internal - Free up any allocated colormaps. This fn is only called for - top-level widgets. -*/ -void QGLWidgetPrivate::cleanupColormaps() -{ - if (!cmap.handle()) { - return; - } else { - XFreeColormap(X11->display, (Colormap) cmap.handle()); - cmap.setHandle(0); - } -} - -void QGLWidget::setMouseTracking(bool enable) -{ - Q_D(QGLWidget); - if (d->olw) - d->olw->setMouseTracking(enable); - QWidget::setMouseTracking(enable); -} - - -void QGLWidget::resizeEvent(QResizeEvent *) -{ - Q_D(QGLWidget); - if (!isValid()) - return; - makeCurrent(); - if (!d->glcx->initialized()) - glInit(); - glXWaitX(); - resizeGL(width(), height()); - if (d->olw) - d->olw->setGeometry(rect()); -} - -const QGLContext* QGLWidget::overlayContext() const -{ - Q_D(const QGLWidget); - if (d->olw) - return d->olw->context(); - else - return 0; -} - - -void QGLWidget::makeOverlayCurrent() -{ - Q_D(QGLWidget); - if (d->olw) - d->olw->makeCurrent(); -} - - -void QGLWidget::updateOverlayGL() -{ - Q_D(QGLWidget); - if (d->olw) - d->olw->updateGL(); -} - -/*! - \internal - - Sets a new QGLContext, \a context, for this QGLWidget, using the - shared context, \a shareContext. If \a deleteOldContext is true, - the original context is deleted; otherwise it is overridden. -*/ -void QGLWidget::setContext(QGLContext *context, - const QGLContext* shareContext, - bool deleteOldContext) -{ - Q_D(QGLWidget); - if (context == 0) { - qWarning("QGLWidget::setContext: Cannot set null context"); - return; - } - if (!context->deviceIsPixmap() && context->device() != this) { - qWarning("QGLWidget::setContext: Context must refer to this widget"); - return; - } - - if (d->glcx) - d->glcx->doneCurrent(); - QGLContext* oldcx = d->glcx; - d->glcx = context; - - if (parentWidget()) { - // force creation of delay-created widgets - parentWidget()->winId(); - if (parentWidget()->x11Info().screen() != x11Info().screen()) - d_func()->xinfo = parentWidget()->d_func()->xinfo; - } - - // If the application has set WA_TranslucentBackground and not explicitly set - // the alpha buffer size to zero, modify the format so it have an alpha channel - QGLFormat& fmt = d->glcx->d_func()->glFormat; - if (testAttribute(Qt::WA_TranslucentBackground) && fmt.alphaBufferSize() == -1) - fmt.setAlphaBufferSize(1); - - bool createFailed = false; - if (!d->glcx->isValid()) { - if (!d->glcx->create(shareContext ? shareContext : oldcx)) - createFailed = true; - } - if (createFailed) { - if (deleteOldContext) - delete oldcx; - return; - } - - if (d->glcx->windowCreated() || d->glcx->deviceIsPixmap()) { - if (deleteOldContext) - delete oldcx; - return; - } - - bool visible = isVisible(); - if (visible) - hide(); - - XVisualInfo *vi = (XVisualInfo*)d->glcx->d_func()->vi; - XSetWindowAttributes a; - - QColormap colmap = QColormap::instance(vi->screen); - a.colormap = qt_gl_choose_cmap(QX11Info::display(), vi); // find best colormap - a.background_pixel = colmap.pixel(palette().color(backgroundRole())); - a.border_pixel = colmap.pixel(Qt::black); - Window p = RootWindow(X11->display, vi->screen); - if (parentWidget()) - p = parentWidget()->winId(); - - Window w = XCreateWindow(X11->display, p, x(), y(), width(), height(), - 0, vi->depth, InputOutput, vi->visual, - CWBackPixel|CWBorderPixel|CWColormap, &a); - Window *cmw; - Window *cmwret; - int count; - if (XGetWMColormapWindows(X11->display, window()->winId(), - &cmwret, &count)) { - cmw = new Window[count+1]; - memcpy((char *)cmw, (char *)cmwret, sizeof(Window)*count); - XFree((char *)cmwret); - int i; - for (i=0; i<count; i++) { - if (cmw[i] == winId()) { // replace old window - cmw[i] = w; - break; - } - } - if (i >= count) // append new window - cmw[count++] = w; - } else { - count = 1; - cmw = new Window[count]; - cmw[0] = w; - } - -#if defined(GLX_MESA_release_buffers) && defined(QGL_USE_MESA_EXT) - if (oldcx && oldcx->windowCreated()) - glXReleaseBuffersMESA(X11->display, winId()); -#endif - if (deleteOldContext) - delete oldcx; - oldcx = 0; - - if (testAttribute(Qt::WA_WState_Created)) - create(w); - else - d->createWinId(w); - XSetWMColormapWindows(X11->display, window()->winId(), cmw, count); - delete [] cmw; - - // calling QWidget::create() will always result in a new paint - // engine being created - get rid of it and replace it with our - // own - - if (visible) - show(); - XFlush(X11->display); - d->glcx->setWindowCreated(true); -} - -const QGLColormap & QGLWidget::colormap() const -{ - Q_D(const QGLWidget); - return d->cmap; -} - -/*\internal - Store color values in the given colormap. -*/ -static void qStoreColors(QWidget * tlw, Colormap cmap, - const QGLColormap & cols) -{ - Q_UNUSED(tlw); - XColor c; - QRgb color; - - for (int i = 0; i < cols.size(); i++) { - color = cols.entryRgb(i); - c.pixel = i; - c.red = (ushort)((qRed(color) / 255.0) * 65535.0 + 0.5); - c.green = (ushort)((qGreen(color) / 255.0) * 65535.0 + 0.5); - c.blue = (ushort)((qBlue(color) / 255.0) * 65535.0 + 0.5); - c.flags = DoRed | DoGreen | DoBlue; - XStoreColor(X11->display, cmap, &c); - } -} - -/*\internal - Check whether the given visual supports dynamic colormaps or not. -*/ -static bool qCanAllocColors(QWidget * w) -{ - bool validVisual = false; - int numVisuals; - long mask; - XVisualInfo templ; - XVisualInfo * visuals; - VisualID id = XVisualIDFromVisual((Visual *) w->window()->x11Info().visual()); - - mask = VisualScreenMask; - templ.screen = w->x11Info().screen(); - visuals = XGetVisualInfo(X11->display, mask, &templ, &numVisuals); - - for (int i = 0; i < numVisuals; i++) { - if (visuals[i].visualid == id) { - switch (visuals[i].c_class) { - case TrueColor: - case StaticColor: - case StaticGray: - case XGrayScale: - validVisual = false; - break; - case DirectColor: - case PseudoColor: - validVisual = true; - break; - } - break; - } - } - XFree(visuals); - - if (!validVisual) - return false; - return true; -} - - -void QGLWidget::setColormap(const QGLColormap & c) -{ - Q_D(QGLWidget); - QWidget * tlw = window(); // must return a valid widget - - d->cmap = c; - if (!d->cmap.handle()) - return; - - if (!qCanAllocColors(this)) { - qWarning("QGLWidget::setColormap: Cannot create a read/write " - "colormap for this visual"); - return; - } - - // If the child GL widget is not of the same visual class as the - // toplevel widget we will get in trouble.. - Window wid = tlw->winId(); - Visual * vis = (Visual *) tlw->x11Info().visual();; - VisualID cvId = XVisualIDFromVisual((Visual *) x11Info().visual()); - VisualID tvId = XVisualIDFromVisual((Visual *) tlw->x11Info().visual()); - if (cvId != tvId) { - wid = winId(); - vis = (Visual *) x11Info().visual(); - } - - if (!d->cmap.handle()) // allocate a cmap if necessary - d->cmap.setHandle(XCreateColormap(X11->display, wid, vis, AllocAll)); - - qStoreColors(this, (Colormap) d->cmap.handle(), c); - XSetWindowColormap(X11->display, wid, (Colormap) d->cmap.handle()); - - // tell the wm that this window has a special colormap - Window * cmw; - Window * cmwret; - int count; - if (XGetWMColormapWindows(X11->display, tlw->winId(), &cmwret, &count)) - { - cmw = new Window[count+1]; - memcpy((char *) cmw, (char *) cmwret, sizeof(Window) * count); - XFree((char *) cmwret); - int i; - for (i = 0; i < count; i++) { - if (cmw[i] == winId()) { - break; - } - } - if (i >= count) // append new window only if not in the list - cmw[count++] = winId(); - } else { - count = 1; - cmw = new Window[count]; - cmw[0] = winId(); - } - XSetWMColormapWindows(X11->display, tlw->winId(), cmw, count); - delete [] cmw; -} - -// Solaris defines glXBindTexImageEXT as part of the GL library -#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) -typedef void (*qt_glXBindTexImageEXT)(Display*, GLXDrawable, int, const int*); -typedef void (*qt_glXReleaseTexImageEXT)(Display*, GLXDrawable, int); -static qt_glXBindTexImageEXT glXBindTexImageEXT = 0; -static qt_glXReleaseTexImageEXT glXReleaseTexImageEXT = 0; - -static bool qt_resolveTextureFromPixmap(QPaintDevice *paintDevice) -{ - static bool resolvedTextureFromPixmap = false; - - if (!resolvedTextureFromPixmap) { - resolvedTextureFromPixmap = true; - - // Check to see if we have NPOT texture support - if ( !(QGLExtensions::glExtensions() & QGLExtensions::NPOTTextures) && - !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0)) - { - return false; // Can't use TFP without NPOT - } - - const QX11Info *xinfo = qt_x11Info(paintDevice); - Display *display = xinfo ? xinfo->display() : X11->display; - int screen = xinfo ? xinfo->screen() : X11->defaultScreen; - - QGLExtensionMatcher serverExtensions(glXQueryExtensionsString(display, screen)); - QGLExtensionMatcher clientExtensions(glXGetClientString(display, GLX_EXTENSIONS)); - if (serverExtensions.match("GLX_EXT_texture_from_pixmap") - && clientExtensions.match("GLX_EXT_texture_from_pixmap")) - { - glXBindTexImageEXT = (qt_glXBindTexImageEXT) qglx_getProcAddress("glXBindTexImageEXT"); - glXReleaseTexImageEXT = (qt_glXReleaseTexImageEXT) qglx_getProcAddress("glXReleaseTexImageEXT"); - } - } - - return glXBindTexImageEXT && glXReleaseTexImageEXT; -} -#endif //defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) - - -QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pixmap, const qint64 key, - QGLContext::BindOptions options) -{ -#if !defined(GLX_VERSION_1_3) || defined(Q_OS_HPUX) - return 0; -#else - - // Check we have GLX 1.3, as it is needed for glXCreatePixmap & glXDestroyPixmap - int majorVersion = 0; - int minorVersion = 0; - glXQueryVersion(X11->display, &majorVersion, &minorVersion); - if (majorVersion < 1 || (majorVersion == 1 && minorVersion < 3)) - return 0; - - Q_Q(QGLContext); - - QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pixmap->data_ptr().data()); - Q_ASSERT(pixmapData->classId() == QPixmapData::X11Class); - - if (!qt_resolveTextureFromPixmap(paintDevice)) - return 0; - - const QX11Info &x11Info = pixmapData->xinfo; - - // Store the configs (Can be static because configs aren't dependent on current context) - static GLXFBConfig glxRGBPixmapConfig = 0; - static bool RGBConfigInverted = false; - static GLXFBConfig glxRGBAPixmapConfig = 0; - static bool RGBAConfigInverted = false; - - bool hasAlpha = pixmapData->hasAlphaChannel(); - - // Check to see if we need a config - if ( (hasAlpha && !glxRGBAPixmapConfig) || (!hasAlpha && !glxRGBPixmapConfig) ) { - GLXFBConfig *configList = 0; - int configCount = 0; - - int configAttribs[] = { - hasAlpha ? GLX_BIND_TO_TEXTURE_RGBA_EXT : GLX_BIND_TO_TEXTURE_RGB_EXT, True, - GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, - GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT, - // QGLContext::bindTexture() can't return an inverted texture, but QPainter::drawPixmap() can: - GLX_Y_INVERTED_EXT, options & QGLContext::CanFlipNativePixmapBindOption ? GLX_DONT_CARE : False, - XNone - }; - configList = glXChooseFBConfig(x11Info.display(), x11Info.screen(), configAttribs, &configCount); - if (!configList) - return 0; - - int yInv; - glXGetFBConfigAttrib(x11Info.display(), configList[0], GLX_Y_INVERTED_EXT, &yInv); - - if (hasAlpha) { - glxRGBAPixmapConfig = configList[0]; - RGBAConfigInverted = yInv; - } - else { - glxRGBPixmapConfig = configList[0]; - RGBConfigInverted = yInv; - } - - XFree(configList); - } - - // Check to see if the surface is still valid - if (pixmapData->gl_surface && - hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha)) - { - // Surface is invalid! - destroyGlSurfaceForPixmap(pixmapData); - } - - // Check to see if we need a surface - if (!pixmapData->gl_surface) { - GLXPixmap glxPixmap; - int pixmapAttribs[] = { - GLX_TEXTURE_FORMAT_EXT, hasAlpha ? GLX_TEXTURE_FORMAT_RGBA_EXT : GLX_TEXTURE_FORMAT_RGB_EXT, - GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, - GLX_MIPMAP_TEXTURE_EXT, False, // Maybe needs to be don't care - XNone - }; - - // Wrap the X Pixmap into a GLXPixmap: - glxPixmap = glXCreatePixmap(x11Info.display(), - hasAlpha ? glxRGBAPixmapConfig : glxRGBPixmapConfig, - pixmapData->handle(), pixmapAttribs); - - if (!glxPixmap) - return 0; - - pixmapData->gl_surface = (void*)glxPixmap; - - // Make sure the cleanup hook gets called so we can delete the glx pixmap - QImagePixmapCleanupHooks::enableCleanupHooks(pixmapData); - } - - GLuint textureId; - glGenTextures(1, &textureId); - glBindTexture(GL_TEXTURE_2D, textureId); - glXBindTexImageEXT(x11Info.display(), (GLXPixmap)pixmapData->gl_surface, GLX_FRONT_LEFT_EXT, 0); - - glBindTexture(GL_TEXTURE_2D, textureId); - - if (!((hasAlpha && RGBAConfigInverted) || (!hasAlpha && RGBConfigInverted))) - options &= ~QGLContext::InvertedYBindOption; - - QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, options); - if (texture->options & QGLContext::InvertedYBindOption) - pixmapData->flags |= QX11PixmapData::InvertedWhenBoundToTexture; - - // We assume the cost of bound pixmaps is zero - QGLTextureCache::instance()->insert(q, key, texture, 0); - - return texture; -#endif //!defined(GLX_VERSION_1_3) || defined(Q_OS_HPUX) -} - - -void QGLContextPrivate::destroyGlSurfaceForPixmap(QPixmapData* pmd) -{ -#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) - Q_ASSERT(pmd->classId() == QPixmapData::X11Class); - QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd); - if (pixmapData->gl_surface) { - glXDestroyPixmap(QX11Info::display(), (GLXPixmap)pixmapData->gl_surface); - pixmapData->gl_surface = 0; - } -#endif -} - -void QGLContextPrivate::unbindPixmapFromTexture(QPixmapData* pmd) -{ -#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) - Q_ASSERT(pmd->classId() == QPixmapData::X11Class); - Q_ASSERT(QGLContext::currentContext()); - QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd); - if (pixmapData->gl_surface) - glXReleaseTexImageEXT(QX11Info::display(), (GLXPixmap)pixmapData->gl_surface, GLX_FRONT_LEFT_EXT); -#endif -} - -QT_END_NAMESPACE diff --git a/src/opengl/qgl_waylandegl.cpp b/src/opengl/qgl_waylandegl.cpp index d54f57581b..97e9e26bfd 100644 --- a/src/opengl/qgl_waylandegl.cpp +++ b/src/opengl/qgl_waylandegl.cpp @@ -46,6 +46,7 @@ #include <private/qpixmap_wayland_p.h> #include <private/qgl_p.h> #include <private/qpaintengine_opengl_p.h> +#include <private/qt_wayland_p.h> #include "qgl_egl_p.h" #include "qcolormap.h" @@ -62,59 +63,73 @@ class QGLTemporaryContextPrivate public: bool initialized; EGLContext context; - EGLSurface surface; + EGLImageKHR image; + GLuint wl_color_rbo; + GLuint wl_fbo; EGLDisplay display; }; QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) : d(new QGLTemporaryContextPrivate) { - d->initialized = false; - d->context = 0; - d->surface = 0; - int screen = 0; - - d->display = QEgl::display(); - EGLConfig config; int numConfigs = 0; - EGLint attribs[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, -#ifdef QT_OPENGL_ES_2 - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, -#endif + EGLint cfg_attribs[] = { + EGL_SURFACE_TYPE, 0, + EGL_NO_SURFACE_CAPABLE_MESA, EGL_OPENGL_ES2_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE }; + EGLint img_attribs[] = { + EGL_WIDTH, 1, + EGL_HEIGHT, 1, + EGL_IMAGE_FORMAT_MESA, 0, + EGL_IMAGE_USE_MESA, EGL_IMAGE_USE_SHARE_MESA | + EGL_IMAGE_USE_SCANOUT_MESA, + EGL_NONE, + }; + EGLint contextAttribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + d->initialized = false; + d->context = 0; + d->display = QEgl::display(); - eglChooseConfig(d->display, attribs, &config, 1, &numConfigs); + eglChooseConfig(d->display, cfg_attribs, &config, 1, &numConfigs); if (!numConfigs) { qWarning("QGLTemporaryContext: No EGL configurations available."); return; } - EGLint id = 0; + /* width & height will be updated at resize time */ + img_attribs[5] = EGL_IMAGE_FORMAT_ARGB8888_MESA; + d->image = QEgl::eglCreateDRMImageMESA(d->display, img_attribs); + if (!d->image) + qWarning("failed to create EGL image: %d\n", eglGetError()); - d->surface = eglCreateWindowSurface(d->display, config, (EGLNativeWindowType) 0, NULL); + glGenFramebuffers(1, &d->wl_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, d->wl_fbo); - if (d->surface == EGL_NO_SURFACE) { - qWarning("QGLTemporaryContext: Error creating EGL surface."); - return; - } + glGenRenderbuffers(1, &d->wl_color_rbo); + glBindRenderbuffer(GL_RENDERBUFFER, d->wl_color_rbo); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, d->wl_color_rbo); + QEgl::glEGLImageTargetRenderbufferStorage(GL_RENDERBUFFER, d->image); - EGLint contextAttribs[] = { -#ifdef QT_OPENGL_ES_2 - EGL_CONTEXT_CLIENT_VERSION, 2, -#endif - EGL_NONE - }; + eglBindAPI(EGL_OPENGL_ES_API); d->context = eglCreateContext(d->display, config, 0, contextAttribs); if (d->context != EGL_NO_CONTEXT - && eglMakeCurrent(d->display, d->surface, d->surface, d->context)) + && eglMakeCurrent(d->display, EGL_NO_SURFACE, EGL_NO_SURFACE, + d->context)) { d->initialized = true; } else { qWarning("QGLTemporaryContext: Error creating EGL context."); - eglDestroySurface(d->display, d->surface); + QEgl::eglDestroyImageKHR(d->display, d->image); + glDeleteRenderbuffers(1, &d->wl_color_rbo); + glDeleteFramebuffers(1, &d->wl_fbo); } } @@ -123,7 +138,9 @@ QGLTemporaryContext::~QGLTemporaryContext() if (d->initialized) { eglMakeCurrent(d->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroyContext(d->display, d->context); - eglDestroySurface(d->display, d->surface); + QEgl::eglDestroyImageKHR(d->display, d->image); + glDeleteRenderbuffers(1, &d->wl_color_rbo); + glDeleteFramebuffers(1, &d->wl_fbo); } } @@ -165,12 +182,17 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) QEglProperties configProps; configProps.setDeviceType(devType); configProps.setRenderableType(QEgl::OpenGL); - qt_eglproperties_set_glformat(configProps, d->glFormat); + configProps.setValue(EGL_SURFACE_TYPE, 0); + configProps.setValue(EGL_NO_SURFACE_CAPABLE_MESA, EGL_OPENGL_ES2_BIT); + configProps.setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT); + //qt_eglproperties_set_glformat(configProps, d->glFormat); // Set buffer preserved for regular QWidgets, QGLWidgets are ok with either preserved or destroyed: +#if 0 + // FIXME: buffer swap behavior in wayland if ((devType == QInternal::Widget) && qobject_cast<QGLWidget*>(static_cast<QWidget*>(device())) == 0) configProps.setValue(EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); - +#endif if (!d->eglContext->chooseConfig(configProps, QEgl::BestPixelFormat)) { delete d->eglContext; d->eglContext = 0; @@ -199,9 +221,14 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) // QGLPixelBuffer - no, it creates the surface itself and stores it in QGLPixelBufferPrivate::pbuf if (devType == QInternal::Widget) { - if (d->eglSurface != EGL_NO_SURFACE) - eglDestroySurface(d->eglContext->display(), d->eglSurface); - d->eglSurface = QEgl::createSurface(device(), d->eglContext->config()); + if (d->eglImage != EGL_NO_IMAGE_KHR) + QEgl::eglDestroyImageKHR(d->eglContext->display(), d->eglImage); + d->eglImage = QEgl::createImage(device(), d->eglContext->config()); + if (!d->eglImage) + qWarning("failed to create EGL image: 0x%08x\n", eglGetError()); + d->wl_surface = wl_compositor_create_surface(qWayland->compositor); + if (!d->wl_surface) + qWarning("failed to create wayland surface\n"); setWindowCreated(true); } @@ -217,7 +244,6 @@ void QGLWidget::resizeEvent(QResizeEvent *) if (!d->glcx->initialized()) glInit(); resizeGL(width(), height()); - //handle overlay } const QGLContext* QGLWidget::overlayContext() const @@ -227,12 +253,10 @@ const QGLContext* QGLWidget::overlayContext() const void QGLWidget::makeOverlayCurrent() { - //handle overlay } void QGLWidget::updateOverlayGL() { - //handle overlay } void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, bool deleteOldContext) diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp index 9a8b243659..3967a09057 100644 --- a/src/opengl/qglpixelbuffer.cpp +++ b/src/opengl/qglpixelbuffer.cpp @@ -144,6 +144,9 @@ void QGLPixelBufferPrivate::common_init(const QSize &size, const QGLFormat &form #elif defined(Q_WS_MAC) qctx->d_func()->cx = ctx; qctx->d_func()->vi = 0; +#elif defined(Q_WS_WAYLAND) + qctx->d_func()->eglContext = ctx; + qctx->d_func()->eglImage = pbuf; #elif !defined(QT_NO_EGL) qctx->d_func()->eglContext = ctx; qctx->d_func()->eglSurface = pbuf; diff --git a/src/opengl/qglpixelbuffer_p.h b/src/opengl/qglpixelbuffer_p.h index 2a1f671aea..d0f917ab29 100644 --- a/src/opengl/qglpixelbuffer_p.h +++ b/src/opengl/qglpixelbuffer_p.h @@ -194,7 +194,11 @@ public: # endif #endif #ifndef QT_NO_EGL +#ifndef Q_WS_WAYLAND EGLSurface pbuf; +#else + EGLImageKHR pbuf; +#endif QEglContext *ctx; int textureFormat; #endif diff --git a/src/opengl/qgraphicssystem_gl.cpp b/src/opengl/qgraphicssystem_gl.cpp index 58cc28ad04..afbaa7abab 100644 --- a/src/opengl/qgraphicssystem_gl.cpp +++ b/src/opengl/qgraphicssystem_gl.cpp @@ -53,6 +53,10 @@ #include "private/qwindowsurface_x11gl_p.h" #endif +#ifdef Q_WS_WAYLAND +#include "private/qwindowsurface_waylandgl_p.h" +#endif + QT_BEGIN_NAMESPACE extern QGLWidget *qt_gl_getShareWidget(); @@ -86,6 +90,10 @@ QWindowSurface *QGLGraphicsSystem::createWindowSurface(QWidget *widget) const } #endif +#ifdef Q_WS_WAYLAND +// return new QWaylandWindowSurface(widget); +#endif + return new QGLWindowSurface(widget); } diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp index 12c487d449..24fc36f593 100644 --- a/src/opengl/qpaintengine_opengl.cpp +++ b/src/opengl/qpaintengine_opengl.cpp @@ -1232,6 +1232,7 @@ inline void QOpenGLPaintEnginePrivate::setGradientOps(const QBrush &brush, const QOpenGLPaintEngine::QOpenGLPaintEngine() : QPaintEngineEx(*(new QOpenGLPaintEnginePrivate)) { + qWarning("creating new GL paint engine\n"); } QOpenGLPaintEngine::~QOpenGLPaintEngine() diff --git a/src/opengl/qpixmapdata_waylandgl_egl.cpp b/src/opengl/qpixmapdata_waylandgl_egl.cpp index 15fd075d5e..6c5efc6164 100644 --- a/src/opengl/qpixmapdata_waylandgl_egl.cpp +++ b/src/opengl/qpixmapdata_waylandgl_egl.cpp @@ -123,14 +123,7 @@ bool QWaylandGLPixmapData::scroll(int dx, int dy, const QRect &rect) return success; } -#if !defined(QT_OPENGL_ES_1) Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_pixmap_2_engine) -#endif - -#ifndef QT_OPENGL_ES_2 -Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_gl_pixmap_engine) -#endif - QPaintEngine* QWaylandGLPixmapData::paintEngine() const { @@ -148,33 +141,13 @@ QPaintEngine* QWaylandGLPixmapData::paintEngine() const QPaintEngine* engine; -#if defined(QT_OPENGL_ES_1) - engine = qt_gl_pixmap_engine(); -#elif defined(QT_OPENGL_ES_2) engine = qt_gl_pixmap_2_engine(); -#else - if (qt_gl_preferGL2Engine()) - engine = qt_gl_pixmap_2_engine(); - else - engine = qt_gl_pixmap_engine(); -#endif - - // Support multiple painters on multiple pixmaps simultaniously if (engine->isActive()) { qWarning("Pixmap paint engine already active"); -#if defined(QT_OPENGL_ES_1) - engine = new QOpenGLPaintEngine; -#elif defined(QT_OPENGL_ES_2) engine = new QGL2PaintEngineEx; -#else - if (qt_gl_preferGL2Engine()) - engine = new QGL2PaintEngineEx; - else - engine = new QOpenGLPaintEngine; -#endif return engine; } diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index 7efa9bc0c5..5c7824b5a0 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -291,6 +291,7 @@ QGLWindowSurface::QGLWindowSurface(QWidget *window) : QWindowSurface(window), d_ptr(new QGLWindowSurfacePrivate) { Q_ASSERT(window->isTopLevel()); + d_ptr->pb = 0; d_ptr->fbo = 0; d_ptr->ctx = 0; diff --git a/src/opengl/qwindowsurface_waylandgl.cpp b/src/opengl/qwindowsurface_waylandgl.cpp index f8048d800c..1fcb457b50 100644 --- a/src/opengl/qwindowsurface_waylandgl.cpp +++ b/src/opengl/qwindowsurface_waylandgl.cpp @@ -60,16 +60,30 @@ QPaintDevice *QWaylandWindowSurface::paintDevice() return &m_backBuffer; } -void QWaylandWindowSurface::flush(QWidget *widget, const QRegion &widgetRegion, const QPoint &offset) +void QWaylandWindowSurface::flush(QWidget *widget, const QRegion &widgetRegion, + const QPoint &offset) { eglWaitNative(EGL_CORE_NATIVE_ENGINE); } void QWaylandWindowSurface::setGeometry(const QRect &rect) { + if (rect.width() > m_backBuffer.size().width() || + rect.height() > m_backBuffer.size().height()) { + QWaylandGLPixmapData *pd = new QWaylandGLPixmapData; + QSize newSize = rect.size(); + pd->resize(newSize.width(), newSize.height()); + m_backBuffer = QPixmap(pd); + if (window()->testAttribute(Qt::WA_TranslucentBackground)) + m_backBuffer.fill(Qt::transparent); + } QWindowSurface::setGeometry(rect); } +void QWaylandWindowSurface::updateGeometry() +{ +} + bool QWaylandWindowSurface::scroll(const QRegion &area, int dx, int dy) { eglWaitNative(EGL_CORE_NATIVE_ENGINE); @@ -77,15 +91,30 @@ bool QWaylandWindowSurface::scroll(const QRegion &area, int dx, int dy) return true; } +void QWaylandWindowSurface::beginPaint(const QRegion ®ion) +{ +} -QPixmap QWaylandWindowSurface::grabWidget(const QWidget *widget, const QRect& rect) const +void QWaylandWindowSurface::endPaint(const QRegion ®ion) { - if (!widget || m_backBuffer.isNull()) - return QPixmap(); +#if 0 + struct wl_visual *visual; + EGLint name, stride; - eglWaitNative(EGL_CORE_NATIVE_ENGINE); + QEgl::eglExportDRMImageMESA(qWayland->egl_display, image, &name, NULL, + &stride); + visual = wl_display_get_premultiplied_argb_visual(qWayland->egl_display); + wl_surface_attach(surface, name, width, height, stride, visual); + wl_surface_map(surface, 0, 0, width, height); +#endif +} - return QPixmap(); +QImage *QWaylandWindowSurface::buffer(const QWidget *widget) +{ +} + +QGLContext *QWaylandWindowSurface::context() const +{ } QT_END_NAMESPACE diff --git a/src/opengl/qwindowsurface_waylandgl_p.h b/src/opengl/qwindowsurface_waylandgl_p.h index e5950ebacf..d287b7c9d8 100644 --- a/src/opengl/qwindowsurface_waylandgl_p.h +++ b/src/opengl/qwindowsurface_waylandgl_p.h @@ -53,7 +53,10 @@ // We mean it. // +#include <qglobal.h> +#include <qgl.h> #include <private/qwindowsurface_p.h> +#include <private/qglpaintdevice_p.h> QT_BEGIN_NAMESPACE @@ -67,12 +70,19 @@ public: QPaintDevice *paintDevice(); void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); void setGeometry(const QRect &rect); + void updateGeometry(); bool scroll(const QRegion &area, int dx, int dy); - QPixmap grabWidget(const QWidget *widget, const QRect& rectangle = QRect()) const; + + void beginPaint(const QRegion ®ion); + void endPaint(const QRegion ®ion); + + QImage *buffer(const QWidget *widget); + + QGLContext *context() const; private: - QPixmap m_backBuffer; QWidget *m_window; + QPixmap m_backBuffer; }; |