Fix repaint of transparent images.

Remove the native bitmap and paint directly on the surface instead.

Change-Id: Ie7010d97aa934a170c079de549903fc3391df4d9
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
bb10
BogDan Vatra 2014-01-30 14:57:19 +02:00 committed by The Qt Project
parent 5096355f0a
commit 37355965c2
2 changed files with 47 additions and 65 deletions

View File

@ -53,6 +53,7 @@
#include "qandroidplatformrasterwindow.h"
#include <android/bitmap.h>
#include <android/native_window_jni.h>
QT_BEGIN_NAMESPACE
@ -85,7 +86,7 @@ QAndroidPlatformScreen::QAndroidPlatformScreen():QObject(),QPlatformScreen()
m_format = QImage::Format_RGB16;
m_depth = 16;
} else {
m_format = QImage::Format_RGBA8888;
m_format = QImage::Format_ARGB32_Premultiplied;
m_depth = 32;
}
m_physicalSize.setHeight(QAndroidPlatformIntegration::m_defaultPhysicalSizeHeight);
@ -100,8 +101,8 @@ QAndroidPlatformScreen::~QAndroidPlatformScreen()
if (m_id != -1) {
QtAndroid::destroySurface(m_id);
m_surfaceWaitCondition.wakeOne();
if (m_bitmap)
QtAndroid::AttachedJNIEnv().jniEnv->DeleteGlobalRef(m_bitmap);
if (m_nativeSurface)
ANativeWindow_release(m_nativeSurface);
}
}
@ -181,8 +182,7 @@ void QAndroidPlatformScreen::scheduleUpdate()
void QAndroidPlatformScreen::setDirty(const QRect &rect)
{
QRect intersection = rect.intersected(m_geometry);
QPoint screenOffset = m_geometry.topLeft();
m_repaintRegion += intersection.translated(-screenOffset); // global to local translation
m_repaintRegion += intersection;
scheduleUpdate();
}
@ -203,9 +203,9 @@ void QAndroidPlatformScreen::setGeometry(const QRect &rect)
resizeMaximizedWindows();
if (m_id != -1) {
if (m_bitmap) {
QtAndroid::AttachedJNIEnv().jniEnv->DeleteGlobalRef(m_bitmap);
m_bitmap = 0;
if (m_nativeSurface) {
ANativeWindow_release(m_nativeSurface);
m_nativeSurface = 0;
}
QtAndroid::setSurfaceGeometry(m_id, rect);
}
@ -237,23 +237,36 @@ void QAndroidPlatformScreen::doRedraw()
m_surfaceWaitCondition.wait(&m_surfaceMutex);
}
if (!m_bitmap || !m_surface.isValid())
if (!m_nativeSurface)
return;
QJNIEnvironmentPrivate env;
if (!env)
return;
ANativeWindow_Buffer nativeWindowBuffer;
ARect nativeWindowRect;
QRect br = m_repaintRegion.boundingRect();
nativeWindowRect.top = br.top();
nativeWindowRect.left = br.left();
nativeWindowRect.bottom = br.bottom() + 1; // for some reason that I don't understand the QRect bottom needs to +1 to be the same with ARect bottom
nativeWindowRect.right = br.right() + 1; // same for the right
int ret;
void *pixels;
if ((ret = AndroidBitmap_lockPixels(env, m_bitmap, &pixels)) < 0) {
qWarning() << "AndroidBitmap_lockPixels() failed! error=" << ret;
if ((ret = ANativeWindow_lock(m_nativeSurface, &nativeWindowBuffer, &nativeWindowRect)) < 0) {
qWarning() << "ANativeWindow_lock() failed! error=" << ret;
return;
}
QImage mScreenImage(reinterpret_cast<uchar *>(pixels), m_bitmapWidth, m_bitmapHeight, m_bitmapStride, m_format);
QPainter mCompositePainter(&mScreenImage);
int bpp = 4;
QImage::Format format = QImage::Format_RGBA8888_Premultiplied;
if (nativeWindowBuffer.format == WINDOW_FORMAT_RGB_565) {
bpp = 2;
format = QImage::Format_RGB16;
}
QImage screenImage(reinterpret_cast<uchar *>(nativeWindowBuffer.bits)
, nativeWindowBuffer.width, nativeWindowBuffer.height
, nativeWindowBuffer.stride * bpp , format);
QPainter compositePainter(&screenImage);
compositePainter.setCompositionMode(QPainter::CompositionMode_Source);
for (int rectIndex = 0; rectIndex < rects.size(); rectIndex++) {
QRegion visibleRegion = rects[rectIndex];
@ -273,37 +286,18 @@ void QAndroidPlatformScreen::doRedraw()
QRect windowRect = targetRect.translated(-window->geometry().topLeft());
QAndroidPlatformBackingStore *backingStore = static_cast<QAndroidPlatformRasterWindow *>(window)->backingStore();
if (backingStore)
mCompositePainter.drawImage(targetRect, backingStore->image(), windowRect);
compositePainter.drawImage(targetRect.topLeft(), backingStore->image(), windowRect);
}
}
foreach (const QRect &rect, visibleRegion.rects())
mCompositePainter.fillRect(rect, Qt::transparent);
foreach (const QRect &rect, visibleRegion.rects()) {
compositePainter.fillRect(rect, QColor(Qt::transparent));
}
}
QRect br = m_repaintRegion.boundingRect();
m_repaintRegion = QRegion();
AndroidBitmap_unlockPixels(env, m_bitmap);
QJNIObjectPrivate jrect("android.graphics.Rect", "(IIII)V",
jint(br.left()),
jint(br.top()),
jint(br.right() + 1),
jint(br.bottom() + 1));
QJNIObjectPrivate canvas = m_surface.callObjectMethod("lockCanvas",
"(Landroid/graphics/Rect;)Landroid/graphics/Canvas;",
jrect.object());
if (!canvas.isValid()) {
qWarning() << "Can't lockCanvas";
return;
}
canvas.callMethod<void>("drawBitmap",
"(Landroid/graphics/Bitmap;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Paint;)V",
m_bitmap, jrect.object(), jrect.object(), jobject(0));
m_surface.callMethod<void>("unlockCanvasAndPost", "(Landroid/graphics/Canvas;)V", canvas.object());
ret = ANativeWindow_unlockAndPost(m_nativeSurface);
if (ret >= 0)
m_repaintRegion = QRegion();
}
QDpi QAndroidPlatformScreen::logicalDpi() const
@ -325,24 +319,14 @@ Qt::ScreenOrientation QAndroidPlatformScreen::nativeOrientation() const
void QAndroidPlatformScreen::surfaceChanged(JNIEnv *env, jobject surface, int w, int h)
{
lockSurface();
m_surface = surface;
if (surface && w && h) {
if (w != m_bitmapWidth || h != m_bitmapHeight) {
if (m_bitmap)
env->DeleteGlobalRef(m_bitmap);
m_bitmap = env->NewGlobalRef(QtAndroid::createBitmap(w, h, m_format, env));
AndroidBitmapInfo info;
int res = AndroidBitmap_getInfo(env, m_bitmap, &info);
Q_ASSERT(res > -1);
m_bitmapStride = info.stride;
m_bitmapWidth = info.width;
m_bitmapHeight = info.height;
}
if (m_nativeSurface)
ANativeWindow_release(m_nativeSurface);
m_nativeSurface = ANativeWindow_fromSurface(env, surface);
} else {
if (m_bitmap) {
env->DeleteGlobalRef(m_bitmap);
m_bitmap = 0;
if (m_nativeSurface) {
ANativeWindow_release(m_nativeSurface);
m_nativeSurface = 0;
}
}
unlockSurface();

View File

@ -52,6 +52,8 @@
#include "androidsurfaceclient.h"
#include <android/native_window.h>
QT_BEGIN_NAMESPACE
class QAndroidPlatformWindow;
@ -108,12 +110,8 @@ private slots:
private:
int m_id = -1;
QJNIObjectPrivate m_surface;
jobject m_bitmap = nullptr;
ANativeWindow* m_nativeSurface = nullptr;
QWaitCondition m_surfaceWaitCondition;
int m_bitmapStride = -1;
int m_bitmapWidth = -1;
int m_bitmapHeight = -1;
};
QT_END_NAMESPACE