diff options
Diffstat (limited to 'src/plugins/graphicssystems/meego')
10 files changed, 826 insertions, 239 deletions
diff --git a/src/plugins/graphicssystems/meego/dithering.cpp b/src/plugins/graphicssystems/meego/dithering.cpp new file mode 100644 index 0000000..b50826c --- /dev/null +++ b/src/plugins/graphicssystems/meego/dithering.cpp @@ -0,0 +1,277 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +// This is an implementation of the 32bit => 16bit Floyd-Steinberg dithering. +// The alghorithm used here is not the fastest possible but it's prolly fast enough: +// uses look-up tables, integer-only arthmetics and works in one pass on two lines +// at a time. It's a high-quality dithering using 1/8 diffusion precission. +// Two functions here to look at: +// +// * convertRGBA32_to_RGB565 +// * convertRGBA32_to_RGBA4444 +// +// Each channel (RGBA) is diffused independently and alpha is dithered too. + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <QVarLengthArray> + +// Gets a component (red = 1, green = 2...) from a RGBA data structure. +// data is unsigned char. stride is the number of bytes per line. +#define GET_RGBA_COMPONENT(data, x, y, stride, c) (data[(y * stride) + (x << 2) + c]) + +// Writes a new pixel with r, g, b to data in 565 16bit format. Data is a short. +#define PUT_565(data, x, y, width, r, g, b) (data[(y * width) + x] = (r << 11) | (g << 5) | b) + +// Writes a new pixel with r, g, b, a to data in 4444 RGBA 16bit format. Data is a short. +#define PUT_4444(data, x, y, width, r, g, b, a) (data[(y * width) + x] = (r << 12) | (g << 8) | (b << 4) | a) + +// Writes(ads) a new value to the diffusion accumulator. accumulator is a short. +// x, y is a position in the accumulation buffer. y can be 0 or 1 -- we operate on two lines at time. +#define ACCUMULATE(accumulator, x, y, width, v) if (x < width && x > 0) accumulator[(y * width) + x] += v + +// Clamps a value to be in 0..255 range. +#define CLAMP_256(v) if (v > 255) v = 255; if (v < 0) v = 0; + +// Converts incoming RGB32 (QImage::Format_RGB32) to RGB565. Returns the newly allocated data. +unsigned short* convertRGB32_to_RGB565(const unsigned char *in, int width, int height, int stride) +{ + // Will store output + unsigned short *out = (unsigned short *) malloc(width * height * 2); + + // Lookup tables for the 8bit => 6bit and 8bit => 5bit conversion + unsigned char lookup_8bit_to_5bit[256]; + short lookup_8bit_to_5bit_diff[256]; + unsigned char lookup_8bit_to_6bit[256]; + short lookup_8bit_to_6bit_diff[256]; + + // Macros for the conversion using the lookup table. + #define CONVERT_8BIT_TO_5BIT(v) (lookup_8bit_to_5bit[v]) + #define DIFF_8BIT_TO_5BIT(v) (lookup_8bit_to_5bit_diff[v]) + + #define CONVERT_8BIT_TO_6BIT(v) (lookup_8bit_to_6bit[v]) + #define DIFF_8BIT_TO_6BIT(v) (lookup_8bit_to_6bit_diff[v]) + + int i; + int x, y, c; // Pixel we're processing. c is component number (0, 1, 2 for r, b, b) + short component[3]; // Stores the new components (r, g, b) for pixel produced during conversion + short diff; // The difference between the converted value and the original one. To be accumulated. + QVarLengthArray <short> accumulatorData(3 * width * 2); // Data for three acumulators for r, g, b. Each accumulator is two lines. + short *accumulator[3]; // Helper for accessing the accumulator on a per-channel basis more easily. + accumulator[0] = accumulatorData.data(); + accumulator[1] = accumulatorData.data() + width; + accumulator[2] = accumulatorData.data() + (width * 2); + + // Produce the conversion lookup tables. + for (i = 0; i < 256; i++) { + lookup_8bit_to_5bit[i] = round(i / 8.0); + if (lookup_8bit_to_5bit[i] > 31) + lookup_8bit_to_5bit[i] -= 1; + + // Before bitshifts: (i * 8) - (... * 8 * 8) + lookup_8bit_to_5bit_diff[i] = (i << 3) - (lookup_8bit_to_5bit[i] << 6); + + lookup_8bit_to_6bit[i] = round(i / 4.0); + if (lookup_8bit_to_6bit[i] > 63) + lookup_8bit_to_6bit[i] -= 1; + + // Before bitshifts: (i * 8) - (... * 4 * 8) + lookup_8bit_to_6bit_diff[i] = (i << 3) - (lookup_8bit_to_6bit[i] << 5); + } + + // Clear the accumulators + memset(accumulator[0], 0, width * 4); + memset(accumulator[1], 0, width * 4); + memset(accumulator[2], 0, width * 4); + + // For each line... + for (y = 0; y < height; y++) { + + // For each accumulator, move the second line (index 1) to replace the first line (index 0). + // Clear the second line (index 1) + memcpy(accumulator[0], accumulator[0] + width, width * 2); + memset(accumulator[0] + width, 0, width * 2); + + memcpy(accumulator[1], accumulator[1] + width, width * 2); + memset(accumulator[1] + width, 0, width * 2); + + memcpy(accumulator[2], accumulator[2] + width, width * 2); + memset(accumulator[2] + width, 0, width * 2); + + // For each column.... + for (x = 0; x < width; x++) { + + // For each component (r, g, b)... + for (c = 0; c < 3; c++) { + + // Get the 8bit value from the original image + component[c] = GET_RGBA_COMPONENT(in, x, y, stride, c); + + // Add the diffusion for this pixel we stored in the accumulator. + // >> 7 because the values in accumulator are stored * 128 + component[c] += accumulator[c][x] >> 7; + + // Make sure we're not over the boundaries. + CLAMP_256(component[c]); + + // For green component we use 6 bits. Otherwise 5 bits. + // Store the difference from converting 8bit => 6 bit and the orig pixel. + // Convert 8bit => 6(5) bit. + if (c == 1) { + diff = DIFF_8BIT_TO_6BIT(component[c]); + component[c] = CONVERT_8BIT_TO_6BIT(component[c]); + } else { + diff = DIFF_8BIT_TO_5BIT(component[c]); + component[c] = CONVERT_8BIT_TO_5BIT(component[c]); + } + + // Distribute the difference according to the matrix in the + // accumulation bufffer. + ACCUMULATE(accumulator[c], x + 1, 0, width, diff * 7); + ACCUMULATE(accumulator[c], x - 1, 1, width, diff * 3); + ACCUMULATE(accumulator[c], x, 1, width, diff * 5); + ACCUMULATE(accumulator[c], x + 1, 1, width, diff * 1); + } + + // Write the newly produced pixel + PUT_565(out, x, y, width, component[2], component[1], component[0]); + } + } + + return out; +} + +// Converts incoming RGBA32 (QImage::Format_ARGB32_Premultiplied) to RGB565. Returns the newly allocated data. +// This function is similar (yet different) to the _565 variant but it makes sense to duplicate it here for simplicity. +unsigned short* convertARGB32_to_RGBA4444(const unsigned char *in, int width, int height, int stride) +{ + // Will store output + unsigned short *out = (unsigned short *) malloc(width * height * 2); + + // Lookup tables for the 8bit => 4bit conversion + unsigned char lookup_8bit_to_4bit[256]; + short lookup_8bit_to_4bit_diff[256]; + + // Macros for the conversion using the lookup table. + #define CONVERT_8BIT_TO_4BIT(v) (lookup_8bit_to_4bit[v]) + #define DIFF_8BIT_TO_4BIT(v) (lookup_8bit_to_4bit_diff[v]) + + int i; + int x, y, c; // Pixel we're processing. c is component number (0, 1, 2, 3 for r, b, b, a) + short component[4]; // Stores the new components (r, g, b, a) for pixel produced during conversion + short diff; // The difference between the converted value and the original one. To be accumulated. + QVarLengthArray <short> accumulatorData(4 * width * 2); // Data for three acumulators for r, g, b. Each accumulator is two lines. + short *accumulator[4]; // Helper for accessing the accumulator on a per-channel basis more easily. + accumulator[0] = accumulatorData.data(); + accumulator[1] = accumulatorData.data() + width; + accumulator[2] = accumulatorData.data() + (width * 2); + accumulator[3] = accumulatorData.data() + (width * 3); + + // Produce the conversion lookup tables. + for (i = 0; i < 256; i++) { + lookup_8bit_to_4bit[i] = round(i / 16.0); + if (lookup_8bit_to_4bit[i] > 15) + lookup_8bit_to_4bit[i] -= 1; + + // Before bitshifts: (i * 8) - (... * 16 * 8) + lookup_8bit_to_4bit_diff[i] = (i << 3) - (lookup_8bit_to_4bit[i] << 7); + } + + // Clear the accumulators + memset(accumulator[0], 0, width * 4); + memset(accumulator[1], 0, width * 4); + memset(accumulator[2], 0, width * 4); + memset(accumulator[3], 0, width * 4); + + // For each line... + for (y = 0; y < height; y++) { + + // For each component (r, g, b, a)... + memcpy(accumulator[0], accumulator[0] + width, width * 2); + memset(accumulator[0] + width, 0, width * 2); + + memcpy(accumulator[1], accumulator[1] + width, width * 2); + memset(accumulator[1] + width, 0, width * 2); + + memcpy(accumulator[2], accumulator[2] + width, width * 2); + memset(accumulator[2] + width, 0, width * 2); + + memcpy(accumulator[3], accumulator[3] + width, width * 2); + memset(accumulator[3] + width, 0, width * 2); + + // For each column.... + for (x = 0; x < width; x++) { + + // For each component (r, g, b, a)... + for (c = 0; c < 4; c++) { + + // Get the 8bit value from the original image + component[c] = GET_RGBA_COMPONENT(in, x, y, stride, c); + + // Add the diffusion for this pixel we stored in the accumulator. + // >> 7 because the values in accumulator are stored * 128 + component[c] += accumulator[c][x] >> 7; + + // Make sure we're not over the boundaries. + CLAMP_256(component[c]); + + // Store the difference from converting 8bit => 4bit and the orig pixel. + // Convert 8bit => 4bit. + diff = DIFF_8BIT_TO_4BIT(component[c]); + component[c] = CONVERT_8BIT_TO_4BIT(component[c]); + + // Distribute the difference according to the matrix in the + // accumulation bufffer. + ACCUMULATE(accumulator[c], x + 1, 0, width, diff * 7); + ACCUMULATE(accumulator[c], x - 1, 1, width, diff * 3); + ACCUMULATE(accumulator[c], x, 1, width, diff * 5); + ACCUMULATE(accumulator[c], x + 1, 1, width, diff * 1); + } + + // Write the newly produced pixel + PUT_4444(out, x, y, width, component[0], component[1], component[2], component[3]); + } + } + + return out; +} diff --git a/src/plugins/graphicssystems/meego/meego.pro b/src/plugins/graphicssystems/meego/meego.pro index d750d34..0d3cce6 100644 --- a/src/plugins/graphicssystems/meego/meego.pro +++ b/src/plugins/graphicssystems/meego/meego.pro @@ -5,8 +5,8 @@ QT += gui opengl QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/graphicssystems -HEADERS = qmeegographicssystem.h qmeegopixmapdata.h qmeegoextensions.h -SOURCES = qmeegographicssystem.cpp qmeegographicssystem.h qmeegographicssystemplugin.h qmeegographicssystemplugin.cpp qmeegopixmapdata.h qmeegopixmapdata.cpp qmeegoextensions.h qmeegoextensions.cpp +HEADERS = qmeegographicssystem.h qmeegopixmapdata.h qmeegoextensions.h qmeegorasterpixmapdata.h qmeegolivepixmapdata.h +SOURCES = qmeegographicssystem.cpp qmeegographicssystem.h qmeegographicssystemplugin.h qmeegographicssystemplugin.cpp qmeegopixmapdata.h qmeegopixmapdata.cpp qmeegoextensions.h qmeegoextensions.cpp qmeegorasterpixmapdata.h qmeegorasterpixmapdata.cpp qmeegolivepixmapdata.cpp qmeegolivepixmapdata.h dithering.cpp target.path += $$[QT_INSTALL_PLUGINS]/graphicssystems INSTALLS += target diff --git a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp index f8b228c..a633e2f 100644 --- a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp +++ b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp @@ -54,6 +54,7 @@ #include <private/qpixmap_x11_p.h> #include "qmeegopixmapdata.h" +#include "qmeegolivepixmapdata.h" #include "qmeegographicssystem.h" #include "qmeegoextensions.h" @@ -150,8 +151,8 @@ void QMeeGoGraphicsSystem::setTranslucent(bool translucent) QPixmapData *QMeeGoGraphicsSystem::pixmapDataFromEGLSharedImage(Qt::HANDLE handle, const QImage &softImage) { if (softImage.format() != QImage::Format_ARGB32_Premultiplied && - softImage.format() != QImage::Format_ARGB32) { - qFatal("For egl shared images, the soft image has to be ARGB32 or ARGB32_Premultiplied"); + softImage.format() != QImage::Format_RGB32) { + qFatal("For egl shared images, the soft image has to be ARGB32_Premultiplied or RGB32"); return NULL; } @@ -173,22 +174,6 @@ QPixmapData *QMeeGoGraphicsSystem::pixmapDataFromEGLSharedImage(Qt::HANDLE handl } } -QPixmapData *QMeeGoGraphicsSystem::pixmapDataFromEGLImage(Qt::HANDLE handle) -{ - if (QMeeGoGraphicsSystem::meeGoRunning()) { - QMeeGoPixmapData *pmd = new QMeeGoPixmapData; - pmd->fromEGLImage(handle); - - // FIXME Ok. This is a bit BAD BAD BAD. We're abusing here the fact that we KNOW - // that this function is used for the live pixmap... - pmd->texture()->options &= ~QGLContext::InvertedYBindOption; - return QMeeGoGraphicsSystem::wrapPixmapData(pmd); - } else { - qFatal("Can't create from EGL image when not running meego graphics system!"); - return NULL; - } -} - void QMeeGoGraphicsSystem::updateEGLSharedImagePixmap(QPixmap *pixmap) { QMeeGoPixmapData *pmd = (QMeeGoPixmapData *) pixmap->pixmapData(); @@ -207,109 +192,6 @@ QPixmapData *QMeeGoGraphicsSystem::pixmapDataWithGLTexture(int w, int h) return QMeeGoGraphicsSystem::wrapPixmapData(pmd); } -Qt::HANDLE QMeeGoGraphicsSystem::createLiveTexture(int w, int h, QImage::Format format) -{ - // No need to wrap the QPixmapData here. This QPixmap(Data) is a - // internal implementation and we don't migrate it between - // graphics system switching. - - // We use a bit ugly way of enforcing a color format on the X pixmap -- we create - // a local QImage and fromImage from there. This is quite redundant (extra overhead of creating - // the useless image only to delete it) but shouldn't be too bad for now... you're not expected - // to call createLiveTexture too often anyways. Would be great if QX11PixmapData had a way to - // force the X format upon creation or resize. - - QImage image(w, h, format); - QX11PixmapData *pmd = new QX11PixmapData(QPixmapData::PixmapType); - pmd->fromImage(image, Qt::NoOpaqueDetection); - QPixmap *p = new QPixmap(pmd); - - liveTexturePixmaps.insert(p->handle(), p); - return p->handle(); -} - -void QMeeGoGraphicsSystem::destroyLiveTexture(Qt::HANDLE h) -{ - if (liveTexturePixmaps.contains(h)) { - QPixmap *p = liveTexturePixmaps.value(h); - delete p; - liveTexturePixmaps.remove(h); - } else - qWarning("Trying to destroy live texture %ld which was not found!", h); -} - -bool QMeeGoGraphicsSystem::lockLiveTexture(Qt::HANDLE h) -{ - if (! liveTexturePixmaps.contains(h)) { - qWarning("Trying to lock live texture %ld which was not found!", h); - return false; - } - - EGLint attribs[] = { - EGL_MAP_PRESERVE_PIXELS_KHR, EGL_TRUE, - EGL_LOCK_USAGE_HINT_KHR, EGL_READ_SURFACE_BIT_KHR | EGL_WRITE_SURFACE_BIT_KHR, - EGL_NONE - }; - - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - EGLSurface surface = getSurfaceForLiveTexturePixmap(liveTexturePixmaps.value(h)); - return QMeeGoExtensions::eglLockSurfaceKHR(QEgl::display(), surface, attribs); -} - -bool QMeeGoGraphicsSystem::unlockLiveTexture(Qt::HANDLE h) -{ - if (! liveTexturePixmaps.contains(h)) { - qWarning("Trying to lock live texture %ld which was not found!", h); - return false; - } - - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - QMeeGoExtensions::ensureInitialized(); - - EGLSurface surface = getSurfaceForLiveTexturePixmap(liveTexturePixmaps.value(h)); - if (QMeeGoExtensions::eglUnlockSurfaceKHR(QEgl::display(), surface)) { - glFinish(); - return true; - } else { - return false; - } -} - -void QMeeGoGraphicsSystem::queryLiveTexture(Qt::HANDLE h, void **data, int *pitch) -{ - // FIXME Only allow this on locked surfaces - if (! liveTexturePixmaps.contains(h)) { - qWarning("Trying to query live texture %ld which was not found!", h); - return; - } - - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - QMeeGoExtensions::ensureInitialized(); - - EGLSurface surface = getSurfaceForLiveTexturePixmap(liveTexturePixmaps.value(h)); - eglQuerySurface(QEgl::display(), surface, EGL_BITMAP_POINTER_KHR, (EGLint*) data); - eglQuerySurface(QEgl::display(), surface, EGL_BITMAP_PITCH_KHR, (EGLint*) pitch); -} - -Qt::HANDLE QMeeGoGraphicsSystem::liveTextureToEGLImage(Qt::HANDLE h) -{ - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - QMeeGoExtensions::ensureInitialized(); - - EGLint attribs[] = { - EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, - EGL_NONE - }; - - EGLImageKHR eglImage = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, - (EGLClientBuffer) h, attribs); - - if (eglImage == EGL_NO_IMAGE_KHR) - qWarning("eglCreateImageKHR failed!"); - - return (Qt::HANDLE) eglImage; -} - bool QMeeGoGraphicsSystem::meeGoRunning() { if (! QApplicationPrivate::instance()) { @@ -326,50 +208,32 @@ bool QMeeGoGraphicsSystem::meeGoRunning() return (name == "meego"); } -void QMeeGoGraphicsSystem::destroySurfaceForLiveTexturePixmap(QPixmapData* pmd) +QPixmapData* QMeeGoGraphicsSystem::pixmapDataWithNewLiveTexture(int w, int h, QImage::Format format) { - Q_ASSERT(pmd->classId() == QPixmapData::X11Class); - QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd); - if (pixmapData->gl_surface) { - eglDestroySurface(QEgl::display(), (EGLSurface)pixmapData->gl_surface); - pixmapData->gl_surface = 0; - } + return new QMeeGoLivePixmapData(w, h, format); } -EGLSurface QMeeGoGraphicsSystem::getSurfaceForLiveTexturePixmap(QPixmap *pixmap) +QPixmapData* QMeeGoGraphicsSystem::pixmapDataFromLiveTextureHandle(Qt::HANDLE handle) { - // This code is a crative remix of the stuff that can be found in the - // Qt's TFP implementation in /src/opengl/qgl_x11egl.cpp ::bindiTextureFromNativePixmap - QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pixmap->data_ptr().data()); - Q_ASSERT(pixmapData->classId() == QPixmapData::X11Class); - bool hasAlpha = pixmapData->hasAlphaChannel(); - - if (pixmapData->gl_surface && - hasAlpha == (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha)) - return pixmapData->gl_surface; - - // Check to see if the surface is still valid - if (pixmapData->gl_surface && - hasAlpha != ((pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha) > 0)) { - // Surface is invalid! - QMeeGoGraphicsSystem::destroySurfaceForLiveTexturePixmap(pixmapData); - } + return new QMeeGoLivePixmapData(handle); +} - if (pixmapData->gl_surface == 0) { - EGLConfig config = QEgl::defaultConfig(QInternal::Pixmap, - QEgl::OpenGL, - hasAlpha ? QEgl::Translucent : QEgl::NoOptions); +QImage* QMeeGoGraphicsSystem::lockLiveTexture(QPixmap* pixmap) +{ + QMeeGoLivePixmapData *pixmapData = static_cast<QMeeGoLivePixmapData*>(pixmap->data_ptr().data()); + return pixmapData->lock(); +} - pixmapData->gl_surface = (void*)QEgl::createSurface(pixmap, config); - - if (hasAlpha) - pixmapData->flags = pixmapData->flags | QX11PixmapData::GlSurfaceCreatedWithAlpha; - - if (pixmapData->gl_surface == (void*)EGL_NO_SURFACE) - return NULL; - } +bool QMeeGoGraphicsSystem::releaseLiveTexture(QPixmap *pixmap, QImage *image) +{ + QMeeGoLivePixmapData *pixmapData = static_cast<QMeeGoLivePixmapData*>(pixmap->data_ptr().data()); + return pixmapData->release(image); +} - return pixmapData->gl_surface; +Qt::HANDLE QMeeGoGraphicsSystem::getLiveTextureHandle(QPixmap *pixmap) +{ + QMeeGoLivePixmapData *pixmapData = static_cast<QMeeGoLivePixmapData*>(pixmap->data_ptr().data()); + return pixmapData->handle(); } /* C API */ @@ -384,11 +248,6 @@ QPixmapData* qt_meego_pixmapdata_from_egl_shared_image(Qt::HANDLE handle, const return QMeeGoGraphicsSystem::pixmapDataFromEGLSharedImage(handle, softImage); } -QPixmapData* qt_meego_pixmapdata_from_egl_image(Qt::HANDLE handle) -{ - return QMeeGoGraphicsSystem::pixmapDataFromEGLImage(handle); -} - QPixmapData* qt_meego_pixmapdata_with_gl_texture(int w, int h) { return QMeeGoGraphicsSystem::pixmapDataWithGLTexture(w, h); @@ -419,32 +278,27 @@ void qt_meego_update_egl_shared_image_pixmap(QPixmap *pixmap) QMeeGoGraphicsSystem::updateEGLSharedImagePixmap(pixmap); } -Qt::HANDLE qt_meego_live_texture_create(int w, int h, QImage::Format format) +QPixmapData* qt_meego_pixmapdata_with_new_live_texture(int w, int h, QImage::Format format) { - return QMeeGoGraphicsSystem::createLiveTexture(w, h, format); + return QMeeGoGraphicsSystem::pixmapDataWithNewLiveTexture(w, h, format); } -void qt_meego_live_texture_destroy(Qt::HANDLE h) +QPixmapData* qt_meego_pixmapdata_from_live_texture_handle(Qt::HANDLE handle) { - QMeeGoGraphicsSystem::destroyLiveTexture(h); + return QMeeGoGraphicsSystem::pixmapDataFromLiveTextureHandle(handle); } -bool qt_meego_live_texture_lock(Qt::HANDLE h) +QImage* qt_meego_live_texture_lock(QPixmap *pixmap) { - return QMeeGoGraphicsSystem::lockLiveTexture(h); + return QMeeGoGraphicsSystem::lockLiveTexture(pixmap); } -bool qt_meego_live_texture_unlock(Qt::HANDLE h) +bool qt_meego_live_texture_release(QPixmap *pixmap, QImage *image) { - return QMeeGoGraphicsSystem::unlockLiveTexture(h); + return QMeeGoGraphicsSystem::releaseLiveTexture(pixmap, image); } -void qt_meego_live_texture_query(Qt::HANDLE h, void **data, int *pitch) +Qt::HANDLE qt_meego_live_texture_get_handle(QPixmap *pixmap) { - return QMeeGoGraphicsSystem::queryLiveTexture(h, data, pitch); -} - -Qt::HANDLE qt_meego_live_texture_to_egl_image(Qt::HANDLE h) -{ - return QMeeGoGraphicsSystem::liveTextureToEGLImage(h); -} + return QMeeGoGraphicsSystem::getLiveTextureHandle(pixmap); +}
\ No newline at end of file diff --git a/src/plugins/graphicssystems/meego/qmeegographicssystem.h b/src/plugins/graphicssystems/meego/qmeegographicssystem.h index 934d32d..2697f0f 100644 --- a/src/plugins/graphicssystems/meego/qmeegographicssystem.h +++ b/src/plugins/graphicssystems/meego/qmeegographicssystem.h @@ -67,12 +67,11 @@ public: static QPixmapData *pixmapDataWithGLTexture(int w, int h); static void updateEGLSharedImagePixmap(QPixmap *pixmap); - static Qt::HANDLE createLiveTexture(int w, int h, QImage::Format format); - static void destroyLiveTexture(Qt::HANDLE h); - static bool lockLiveTexture(Qt::HANDLE h); - static bool unlockLiveTexture(Qt::HANDLE h); - static void queryLiveTexture(Qt::HANDLE h, void **data, int *pitch); - static Qt::HANDLE liveTextureToEGLImage(Qt::HANDLE h); + static QPixmapData *pixmapDataWithNewLiveTexture(int w, int h, QImage::Format format); + static QPixmapData *pixmapDataFromLiveTextureHandle(Qt::HANDLE handle); + static QImage *lockLiveTexture(QPixmap* pixmap); + static bool releaseLiveTexture(QPixmap *pixmap, QImage *image); + static Qt::HANDLE getLiveTextureHandle(QPixmap *pixmap); private: static bool meeGoRunning(); @@ -88,19 +87,17 @@ private: extern "C" { Q_DECL_EXPORT int qt_meego_image_to_egl_shared_image(const QImage &image); Q_DECL_EXPORT QPixmapData* qt_meego_pixmapdata_from_egl_shared_image(Qt::HANDLE handle, const QImage &softImage); - Q_DECL_EXPORT QPixmapData* qt_meego_pixmapdata_from_egl_image(Qt::HANDLE handle); Q_DECL_EXPORT QPixmapData* qt_meego_pixmapdata_with_gl_texture(int w, int h); Q_DECL_EXPORT void qt_meego_update_egl_shared_image_pixmap(QPixmap *pixmap); Q_DECL_EXPORT bool qt_meego_destroy_egl_shared_image(Qt::HANDLE handle); Q_DECL_EXPORT void qt_meego_set_surface_fixed_size(int width, int height); Q_DECL_EXPORT void qt_meego_set_surface_scaling(int x, int y, int width, int height); - Q_DECL_EXPORT void qt_meego_set_translucent(bool translucent); - Q_DECL_EXPORT Qt::HANDLE m_live_texture_create(int w, int h, QImage::Format format); - Q_DECL_EXPORT void m_live_texture_destroy(Qt::HANDLE h); - Q_DECL_EXPORT bool m_live_texture_lock(Qt::HANDLE h); - Q_DECL_EXPORT bool m_live_texture_unlock(Qt::HANDLE h); - Q_DECL_EXPORT void m_live_texture_query(Qt::HANDLE h, void **data, int *pitch); - Q_DECL_EXPORT Qt::HANDLE m_live_texture_to_egl_image(Qt::HANDLE h); + Q_DECL_EXPORT void qt_meego_set_translucent(bool translucent); + Q_DECL_EXPORT QPixmapData* qt_meego_pixmapdata_with_new_live_texture(int w, int h, QImage::Format format); + Q_DECL_EXPORT QPixmapData* qt_meego_pixmapdata_from_live_texture_handle(Qt::HANDLE handle); + Q_DECL_EXPORT QImage* qt_meego_live_texture_lock(QPixmap *pixmap); + Q_DECL_EXPORT bool qt_meego_live_texture_release(QPixmap *pixmap, QImage *image); + Q_DECL_EXPORT Qt::HANDLE qt_meego_live_texture_get_handle(QPixmap *pixmap); } #endif diff --git a/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.cpp b/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.cpp new file mode 100644 index 0000000..405b765 --- /dev/null +++ b/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.cpp @@ -0,0 +1,287 @@ +/**************************************************************************** +** +** 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 plugins 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 "qmeegolivepixmapdata.h" +#include "qmeegoextensions.h" +#include "qmeegorasterpixmapdata.h" +#include <private/qimage_p.h> +#include <private/qwindowsurface_gl_p.h> +#include <private/qeglcontext_p.h> +#include <private/qapplication_p.h> +#include <private/qgraphicssystem_runtime_p.h> +#include <private/qpixmap_x11_p.h> +#include <stdio.h> + +static EGLint lock_attribs[] = { + EGL_MAP_PRESERVE_PIXELS_KHR, EGL_TRUE, + EGL_LOCK_USAGE_HINT_KHR, EGL_READ_SURFACE_BIT_KHR | EGL_WRITE_SURFACE_BIT_KHR, + EGL_NONE +}; + +static EGLint preserved_attribs[] = { + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, + EGL_NONE +}; + +// as copied from qwindowsurface.cpp +void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset) +{ + // make sure we don't detach + uchar *mem = const_cast<uchar*>(const_cast<const QImage &>(img).bits()); + + int lineskip = img.bytesPerLine(); + int depth = img.depth() >> 3; + + const QRect imageRect(0, 0, img.width(), img.height()); + const QRect r = rect & imageRect & imageRect.translated(-offset); + const QPoint p = rect.topLeft() + offset; + + if (r.isEmpty()) + return; + + const uchar *src; + uchar *dest; + + if (r.top() < p.y()) { + src = mem + r.bottom() * lineskip + r.left() * depth; + dest = mem + (p.y() + r.height() - 1) * lineskip + p.x() * depth; + lineskip = -lineskip; + } else { + src = mem + r.top() * lineskip + r.left() * depth; + dest = mem + p.y() * lineskip + p.x() * depth; + } + + const int w = r.width(); + int h = r.height(); + const int bytes = w * depth; + + // overlapping segments? + if (offset.y() == 0 && qAbs(offset.x()) < w) { + do { + ::memmove(dest, src, bytes); + dest += lineskip; + src += lineskip; + } while (--h); + } else { + do { + ::memcpy(dest, src, bytes); + dest += lineskip; + src += lineskip; + } while (--h); + } +} + +/* Public */ + +QMeeGoLivePixmapData::QMeeGoLivePixmapData(int w, int h, QImage::Format format) : QGLPixmapData(QPixmapData::PixmapType) +{ + QImage image(w, h, format); + QX11PixmapData *pmd = new QX11PixmapData(QPixmapData::PixmapType); + pmd->fromImage(image, Qt::NoOpaqueDetection); + backingX11Pixmap = new QPixmap(pmd); + + initializeThroughEGLImage(); +} + +QMeeGoLivePixmapData::QMeeGoLivePixmapData(Qt::HANDLE h) : QGLPixmapData(QPixmapData::PixmapType) +{ + backingX11Pixmap = new QPixmap(QPixmap::fromX11Pixmap(h)); + initializeThroughEGLImage(); +} + +QMeeGoLivePixmapData::~QMeeGoLivePixmapData() +{ + delete backingX11Pixmap; +} + +void QMeeGoLivePixmapData::initializeThroughEGLImage() +{ + QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QMeeGoExtensions::ensureInitialized(); + + EGLImageKHR eglImage = EGL_NO_IMAGE_KHR; + GLuint newTextureId = 0; + + eglImage = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, + (EGLClientBuffer) backingX11Pixmap->handle(), preserved_attribs); + + if (eglImage == EGL_NO_IMAGE_KHR) { + qWarning("eglCreateImageKHR failed (live texture)!"); + return; + } + + glGenTextures(1, &newTextureId); + glBindTexture(GL_TEXTURE_2D, newTextureId); + + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (EGLImageKHR) eglImage); + if (glGetError() == GL_NO_ERROR) { + resize(backingX11Pixmap->width(), backingX11Pixmap->height()); + texture()->id = newTextureId; + texture()->options &= ~QGLContext::InvertedYBindOption; + m_hasAlpha = backingX11Pixmap->hasAlphaChannel(); + } else { + qWarning("Failed to create a texture from an egl image (live texture)!"); + glDeleteTextures(1, &newTextureId); + } + + QEgl::eglDestroyImageKHR(QEgl::display(), eglImage); +} + +QPixmapData *QMeeGoLivePixmapData::createCompatiblePixmapData() const +{ + qWarning("Create compatible called on live pixmap! Expect fail soon..."); + return new QMeeGoRasterPixmapData(pixelType()); +} + +QImage* QMeeGoLivePixmapData::lock() +{ + QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QMeeGoExtensions::ensureInitialized(); + + void *data = 0; + int pitch = 0; + EGLSurface surface = 0; + QImage::Format format; + lockedImage = QImage(); + + surface = getSurfaceForBackingPixmap(); + if (! QMeeGoExtensions::eglLockSurfaceKHR(QEgl::display(), surface, lock_attribs)) { + qWarning("Failed to lock surface (live texture)!"); + return &lockedImage; + } + + eglQuerySurface(QEgl::display(), surface, EGL_BITMAP_POINTER_KHR, (EGLint*) &data); + eglQuerySurface(QEgl::display(), surface, EGL_BITMAP_PITCH_KHR, (EGLint*) &pitch); + + // Ok, here we know we just support those two formats. Real solution would be: + // uqery also the format. + if (backingX11Pixmap->depth() > 16) + format = QImage::Format_ARGB32_Premultiplied; + else + format = QImage::Format_RGB16; + + if (data == NULL || pitch == 0) { + qWarning("Failed to query the live texture!"); + return &lockedImage; + } + + lockedImage = QImage((uchar *) data, width(), height(), format); + return &lockedImage; +} + +bool QMeeGoLivePixmapData::release(QImage* /*img*/) +{ + QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QMeeGoExtensions::ensureInitialized(); + + if (QMeeGoExtensions::eglUnlockSurfaceKHR(QEgl::display(), getSurfaceForBackingPixmap())) { + lockedImage = QImage(); + glFinish(); + return true; + } else { + lockedImage = QImage(); + return false; + } +} + +Qt::HANDLE QMeeGoLivePixmapData::handle() +{ + return backingX11Pixmap->handle(); +} + +bool QMeeGoLivePixmapData::scroll(int dx, int dy, const QRect &rect) +{ + lock(); + + if (!lockedImage.isNull()) + qt_scrollRectInImage(lockedImage, rect, QPoint(dx, dy)); + + release(&lockedImage); + return true; +} + +EGLSurface QMeeGoLivePixmapData::getSurfaceForBackingPixmap() +{ + // This code is a crative remix of the stuff that can be found in the + // Qt's TFP implementation in /src/opengl/qgl_x11egl.cpp ::bindiTextureFromNativePixmap + QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(backingX11Pixmap->data_ptr().data()); + Q_ASSERT(pixmapData->classId() == QPixmapData::X11Class); + bool hasAlpha = pixmapData->hasAlphaChannel(); + + if (pixmapData->gl_surface && + hasAlpha == (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha)) + return pixmapData->gl_surface; + + // Check to see if the surface is still valid + if (pixmapData->gl_surface && + hasAlpha != ((pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha) > 0)) { + // Surface is invalid! + destroySurfaceForPixmapData(pixmapData); + } + + if (pixmapData->gl_surface == 0) { + EGLConfig config = QEgl::defaultConfig(QInternal::Pixmap, + QEgl::OpenGL, + hasAlpha ? QEgl::Translucent : QEgl::NoOptions); + + pixmapData->gl_surface = (void*)QEgl::createSurface(backingX11Pixmap, config); + + if (hasAlpha) + pixmapData->flags |= QX11PixmapData::GlSurfaceCreatedWithAlpha; + else + pixmapData->flags &= ~QX11PixmapData::GlSurfaceCreatedWithAlpha; + + if (pixmapData->gl_surface == (void*)EGL_NO_SURFACE) + return NULL; + } + + return pixmapData->gl_surface; +} + +void QMeeGoLivePixmapData::destroySurfaceForPixmapData(QPixmapData* pmd) +{ + Q_ASSERT(pmd->classId() == QPixmapData::X11Class); + QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd); + if (pixmapData->gl_surface) { + eglDestroySurface(QEgl::display(), (EGLSurface)pixmapData->gl_surface); + pixmapData->gl_surface = 0; + } +} diff --git a/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.h b/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.h new file mode 100644 index 0000000..1d647f0 --- /dev/null +++ b/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** 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 plugins 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 MLIVEPIXMAPDATA_H +#define MLIVEPIXMAPDATA_H + +#include <private/qpixmapdata_gl_p.h> + +class QMeeGoLivePixmapData : public QGLPixmapData +{ +public: + QMeeGoLivePixmapData(int w, int h, QImage::Format format); + QMeeGoLivePixmapData(Qt::HANDLE h); + ~QMeeGoLivePixmapData(); + + QPixmapData *createCompatiblePixmapData() const; + bool scroll(int dx, int dy, const QRect &rect); + + void initializeThroughEGLImage(); + + QImage* lock(); + bool release(QImage *img); + Qt::HANDLE handle(); + + EGLSurface getSurfaceForBackingPixmap(); + void destroySurfaceForPixmapData(QPixmapData* pmd); + + QPixmap *backingX11Pixmap; + QImage lockedImage; +}; + +#endif diff --git a/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp b/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp index 84fc593..02a4273 100644 --- a/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp +++ b/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp @@ -41,12 +41,17 @@ #include "qmeegopixmapdata.h" #include "qmeegoextensions.h" +#include "qmeegorasterpixmapdata.h" #include <private/qimage_p.h> #include <private/qwindowsurface_gl_p.h> #include <private/qeglcontext_p.h> #include <private/qapplication_p.h> #include <private/qgraphicssystem_runtime_p.h> +// from dithering.cpp +extern unsigned short* convertRGB32_to_RGB565(const unsigned char *in, int width, int height, int stride); +extern unsigned short* convertARGB32_to_RGBA4444(const unsigned char *in, int width, int height, int stride); + static EGLint preserved_image_attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE }; QHash <void*, QMeeGoImageInfo*> QMeeGoPixmapData::sharedImagesMap; @@ -87,36 +92,6 @@ void QMeeGoPixmapData::fromImage(const QImage &image, } } -void QMeeGoPixmapData::fromEGLImage(Qt::HANDLE handle) -{ - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - QMeeGoExtensions::ensureInitialized(); - - bool textureIsBound = false; - GLuint newTextureId; - GLint newWidth, newHeight; - - glGenTextures(1, &newTextureId); - glBindTexture(GL_TEXTURE_2D, newTextureId); - - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (EGLImageKHR) handle); - GLint err = glGetError(); - if (err == GL_NO_ERROR) - textureIsBound = true; - - QMeeGoExtensions::eglQueryImageNOK(QEgl::display(), (EGLImageKHR) handle, EGL_WIDTH, &newWidth); - QMeeGoExtensions::eglQueryImageNOK(QEgl::display(), (EGLImageKHR) handle, EGL_HEIGHT, &newHeight); - - if (textureIsBound) { - // FIXME Remove this ugly hasAlphaChannel check when Qt lands the NoOpaqueCheck flag fix - // for QGLPixmapData. - fromTexture(newTextureId, newWidth, newHeight, true); - } else { - qWarning("Failed to create a texture from an egl image!"); - glDeleteTextures(1, &newTextureId); - } -} - void QMeeGoPixmapData::fromEGLSharedImage(Qt::HANDLE handle, const QImage &si) { if (si.isNull()) @@ -133,12 +108,10 @@ void QMeeGoPixmapData::fromEGLSharedImage(Qt::HANDLE handle, const QImage &si) glGenTextures(1, &newTextureId); glBindTexture(GL_TEXTURE_2D, newTextureId); - glFinish(); EGLImageKHR image = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_SHARED_IMAGE_NOK, (EGLClientBuffer)handle, preserved_image_attribs); if (image != EGL_NO_IMAGE_KHR) { - glFinish(); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); GLint err = glGetError(); if (err == GL_NO_ERROR) @@ -148,14 +121,12 @@ void QMeeGoPixmapData::fromEGLSharedImage(Qt::HANDLE handle, const QImage &si) QMeeGoExtensions::eglQueryImageNOK(QEgl::display(), image, EGL_HEIGHT, &newHeight); QEgl::eglDestroyImageKHR(QEgl::display(), image); - glFinish(); } if (textureIsBound) { - // FIXME Remove this ugly hasAlphaChannel check when Qt lands the NoOpaqueCheck flag fix - // for QGLPixmapData. fromTexture(newTextureId, newWidth, newHeight, (si.hasAlphaChannel() && const_cast<QImage &>(si).data_ptr()->checkForAlphaPixels())); + texture()->options &= ~QGLContext::InvertedYBindOption; softImage = si; QMeeGoPixmapData::registerSharedImage(handle, softImage); } else { @@ -170,22 +141,32 @@ Qt::HANDLE QMeeGoPixmapData::imageToEGLSharedImage(const QImage &image) QMeeGoExtensions::ensureInitialized(); - glFinish(); - QGLPixmapData pixmapData(QPixmapData::PixmapType); - pixmapData.fromImage(image, 0); - GLuint textureId = pixmapData.bind(); + GLuint textureId; + + glGenTextures(1, &textureId); + glBindTexture(GL_TEXTURE_2D, textureId); + if (image.hasAlphaChannel() && const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels()) { + void *converted = convertARGB32_to_RGBA4444(image.bits(), image.width(), image.height(), image.bytesPerLine()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, converted); + free(converted); + } else { + void *converted = convertRGB32_to_RGB565(image.bits(), image.width(), image.height(), image.bytesPerLine()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, converted); + free(converted); + } - glFinish(); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + glBindTexture(GL_TEXTURE_2D, textureId); EGLImageKHR eglimage = QEgl::eglCreateImageKHR(QEgl::display(), QEglContext::currentContext(QEgl::OpenGL)->context(), EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer) textureId, preserved_image_attribs); - glFinish(); - + glDeleteTextures(1, &textureId); if (eglimage) { EGLNativeSharedImageTypeNOK handle = QMeeGoExtensions::eglCreateSharedImageNOK(QEgl::display(), eglimage, NULL); QEgl::eglDestroyImageKHR(QEgl::display(), eglimage); - glFinish(); return (Qt::HANDLE) handle; } else { qWarning("Failed to create shared image from pixmap/texture!"); @@ -195,6 +176,7 @@ Qt::HANDLE QMeeGoPixmapData::imageToEGLSharedImage(const QImage &image) void QMeeGoPixmapData::updateFromSoftImage() { + // FIXME That's broken with recent 16bit textures changes. m_dirty = true; m_source = softImage; ensureCreated(); @@ -234,3 +216,8 @@ void QMeeGoPixmapData::registerSharedImage(Qt::HANDLE handle, const QImage &si) qWarning("Inconsistency detected: overwriting entry in sharedImagesMap but handle/format different"); } } + +QPixmapData *QMeeGoPixmapData::createCompatiblePixmapData() const +{ + return new QMeeGoRasterPixmapData(pixelType()); +} diff --git a/src/plugins/graphicssystems/meego/qmeegopixmapdata.h b/src/plugins/graphicssystems/meego/qmeegopixmapdata.h index 8b1ae14..c66e719 100644 --- a/src/plugins/graphicssystems/meego/qmeegopixmapdata.h +++ b/src/plugins/graphicssystems/meego/qmeegopixmapdata.h @@ -55,8 +55,8 @@ class QMeeGoPixmapData : public QGLPixmapData public: QMeeGoPixmapData(); void fromTexture(GLuint textureId, int w, int h, bool alpha); + QPixmapData *createCompatiblePixmapData() const; - virtual void fromEGLImage(Qt::HANDLE handle); virtual void fromEGLSharedImage(Qt::HANDLE handle, const QImage &softImage); virtual void fromImage (const QImage &image, Qt::ImageConversionFlags flags); virtual QImage toImage() const; diff --git a/src/plugins/graphicssystems/meego/qmeegorasterpixmapdata.cpp b/src/plugins/graphicssystems/meego/qmeegorasterpixmapdata.cpp new file mode 100644 index 0000000..b6a3727 --- /dev/null +++ b/src/plugins/graphicssystems/meego/qmeegorasterpixmapdata.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** 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 plugins 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 "qmeegorasterpixmapdata.h" + +/* Public */ + +QMeeGoRasterPixmapData::QMeeGoRasterPixmapData() : QRasterPixmapData(QPixmapData::PixmapType) +{ +} + +QMeeGoRasterPixmapData::QMeeGoRasterPixmapData(QPixmapData::PixelType t) : QRasterPixmapData(t) +{ +} + +void QMeeGoRasterPixmapData::copy(const QPixmapData *data, const QRect &rect) +{ + if (data->classId() == QPixmapData::OpenGLClass) + fromImage(data->toImage(rect).copy(), Qt::NoOpaqueDetection); + else + QRasterPixmapData::copy(data, rect); +} diff --git a/src/plugins/graphicssystems/meego/qmeegorasterpixmapdata.h b/src/plugins/graphicssystems/meego/qmeegorasterpixmapdata.h new file mode 100644 index 0000000..636b0e6 --- /dev/null +++ b/src/plugins/graphicssystems/meego/qmeegorasterpixmapdata.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** 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 plugins 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 MRASTERPIXMAPDATA_H +#define MRASTERPIXMAPDATA_H + +#include <private/qpixmap_raster_p.h> + +class QMeeGoRasterPixmapData : public QRasterPixmapData +{ +public: + QMeeGoRasterPixmapData(); + QMeeGoRasterPixmapData(QPixmapData::PixelType t); + void copy(const QPixmapData *data, const QRect &rect); +}; + +#endif |