Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge branch 'jb43196' into 'master'
[lipstick] Reduce the number of memory allocations and copies when populating…

See merge request mer-core/lipstick!92
  • Loading branch information
adenexter committed Dec 3, 2018
2 parents eb03dea + f9756d8 commit 58e4ffa
Show file tree
Hide file tree
Showing 7 changed files with 584 additions and 217 deletions.
4 changes: 4 additions & 0 deletions src/compositor/compositor.pri
Expand Up @@ -17,6 +17,8 @@ HEADERS += \
$$PWD/lipstickrecorder.h \
$$PWD/hwcrenderstage.h \
$$PWD/hwcimage.h \
$$PWD/eglhybrisbuffer.h \
$$PWD/eglhybrisfunctions.h

SOURCES += \
$$PWD/lipstickcompositor.cpp \
Expand All @@ -31,6 +33,8 @@ SOURCES += \
$$PWD/lipstickrecorder.cpp \
$$PWD/hwcrenderstage.cpp \
$$PWD/hwcimage.cpp \
$$PWD/eglhybrisbuffer.cpp \
$$PWD/eglhybrisfunctions.cpp

DEFINES += QT_COMPOSITOR_QUICK

Expand Down
132 changes: 132 additions & 0 deletions src/compositor/eglhybrisbuffer.cpp
@@ -0,0 +1,132 @@
/***************************************************************************
**
** Copyright (C) 2018 Jolla Ltd.
** Contact: Andrew den Exter <andrew.den.exter@jolla.com>
**
** This file is part of lipstick.
**
** This library is free software; you can redistribute it and/or
** modify it 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.
**
****************************************************************************/

#include "eglhybrisbuffer.h"
#include <QImage>
#include "hwcrenderstage.h"

EglHybrisBuffer::EglHybrisBuffer(
Format format, const QSize &size, Usage usage, const EglHybrisFunctions &functions)
: EglHybrisFunctions(functions)
, m_size(size)
, m_usage(usage)
, m_format(format)
{
}

EglHybrisBuffer::~EglHybrisBuffer()
{
if (m_eglImage) {
eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), m_eglImage);
}
if (m_buffer) {
eglHybrisReleaseNativeBuffer(m_buffer);
}
}

void *EglHybrisBuffer::handle() const
{
void *handle = nullptr;
if (eglHybrisNativeBufferHandle) {
eglHybrisNativeBufferHandle(eglGetCurrentDisplay(), m_buffer, &handle);
}
return handle;
}

void EglHybrisBuffer::bindToTexture()
{
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
}

bool EglHybrisBuffer::allocate()
{
if (!eglHybrisCreateNativeBuffer(
m_size.width(), m_size.height(), m_usage, m_format, &m_bufferStride, &m_buffer)
|| !m_buffer) {
qCWarning(LIPSTICK_LOG_HWC, "EGL native buffer error");
return false;
} else if (!(m_eglImage = eglCreateImageKHR(
eglGetDisplay(EGL_DEFAULT_DISPLAY),
EGL_NO_CONTEXT,
EGL_NATIVE_BUFFER_HYBRIS,
m_buffer,
0))) {
qCWarning(LIPSTICK_LOG_HWC, "EGLImage allocation error");
return false;
} else {
return true;
}
}

uchar *EglHybrisBuffer::lock(Usage usage, int *stride)
{
uchar *bytes = nullptr;
if (eglHybrisLockNativeBuffer(
m_buffer,
usage,
0,
0,
m_size.width(),
m_size.height(),
reinterpret_cast<void **>(&bytes))) {
if (stride) {
*stride = m_bufferStride * 4;
}
return bytes;
}
return nullptr;
}

void EglHybrisBuffer::unlock()
{
eglHybrisUnlockNativeBuffer(m_buffer);
}

QImage EglHybrisBuffer::toImage()
{
QImage image;

QImage::Format format;
switch (m_format) {
case RGBA:
format = QImage::Format_RGBA8888_Premultiplied;
break;
case RGBX:
format = QImage::Format_RGBX8888;
break;
case BGRA:
format = QImage::Format_ARGB32_Premultiplied;
break;
default:
return image;
}

int stride = 0;
if (uchar *bytes = lock(Read, &stride)) {
image = QImage(bytes, m_size.width(), m_size.height(), stride, format).copy();
unlock();
}

return image;
}

void EglHybrisBuffer::destroy(void *, void *data)
{
EglHybrisBuffer * const buffer = static_cast<EglHybrisBuffer *>(data);

if (!buffer->ref.deref()) {
delete buffer;
}
}
73 changes: 73 additions & 0 deletions src/compositor/eglhybrisbuffer.h
@@ -0,0 +1,73 @@
/***************************************************************************
**
** Copyright (C) 2018 Jolla Ltd.
** Contact: Andrew den Exter <andrew.den.exter@jolla.com>
**
** This file is part of lipstick.
**
** This library is free software; you can redistribute it and/or
** modify it 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.
**
****************************************************************************/

#ifndef EGLHYBRISBUFFER_H
#define EGLHYBRISBUFFER_H

#include "eglhybrisfunctions.h"
#include <QExplicitlySharedDataPointer>
#include <QSize>

class EglHybrisBuffer : public QSharedData, protected EglHybrisFunctions
{
public:
using Pointer = QExplicitlySharedDataPointer<EglHybrisBuffer>;

enum Format {
RGBA = HYBRIS_PIXEL_FORMAT_RGBA_8888, // QImage::Format_RGBA8888_Premultiplied
RGBX = HYBRIS_PIXEL_FORMAT_RGBX_8888, // QImage::Format_RGBX8888
BGRA = HYBRIS_PIXEL_FORMAT_BGRA_8888 // QImage::Format_ARGB32_Premultiplied
};

enum UsageFlag {
Read = HYBRIS_USAGE_SW_READ_RARELY,
Write = HYBRIS_USAGE_SW_WRITE_RARELY,
Texture = HYBRIS_USAGE_HW_TEXTURE,
Render = HYBRIS_USAGE_HW_RENDER,
Composer = HYBRIS_USAGE_HW_COMPOSER
};
Q_DECLARE_FLAGS(Usage, UsageFlag)

EglHybrisBuffer(Format format, const QSize &size, Usage usage, const EglHybrisFunctions &functions);
~EglHybrisBuffer();

void *handle() const;
void bindToTexture();

Format format() const { return m_format; }
QSize size() const { return m_size; }
Usage usage() const { return m_usage; }

bool allocate();

uchar *lock(Usage usage, int *stride);
void unlock();

QImage toImage();

static void destroy(void *, void *data);

private:
const QSize m_size;
EGLClientBuffer m_buffer = nullptr;
EGLImageKHR m_eglImage = nullptr;
const Usage m_usage;
EGLint m_bufferStride = 0;
const Format m_format;
};

Q_DECLARE_OPERATORS_FOR_FLAGS(EglHybrisBuffer::Usage)

#endif
39 changes: 39 additions & 0 deletions src/compositor/eglhybrisfunctions.cpp
@@ -0,0 +1,39 @@
/***************************************************************************
**
** Copyright (C) 2018 Jolla Ltd.
** Contact: Andrew den Exter <andrew.den.exter@jolla.com>
**
** This file is part of lipstick.
**
** This library is free software; you can redistribute it and/or
** modify it 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.
**
****************************************************************************/

#include "eglhybrisfunctions.h"

#include <QGlobalStatic>

struct SupportedEglHybrisFunctions : public EglHybrisFunctions
{
const bool supported = strstr(eglQueryString(eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_EXTENSIONS), "EGL_HYBRIS_native_buffer2") != 0
&& glEGLImageTargetTexture2DOES
&& eglCreateImageKHR
&& eglDestroyImageKHR
&& eglHybrisCreateNativeBuffer
&& eglHybrisLockNativeBuffer
&& eglHybrisUnlockNativeBuffer
&& eglHybrisReleaseNativeBuffer
&& eglHybrisNativeBufferHandle;
};

Q_GLOBAL_STATIC(SupportedEglHybrisFunctions, eglFunctions)

const EglHybrisFunctions *EglHybrisFunctions::instance()
{
SupportedEglHybrisFunctions * const functions = eglFunctions();
return functions->supported ? functions : nullptr;
}
60 changes: 60 additions & 0 deletions src/compositor/eglhybrisfunctions.h
@@ -0,0 +1,60 @@
/***************************************************************************
**
** Copyright (C) 2018 Jolla Ltd.
** Contact: Andrew den Exter <andrew.den.exter@jolla.com>
**
** This file is part of lipstick.
**
** This library is free software; you can redistribute it and/or
** modify it 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.
**
****************************************************************************/

#ifndef EGLHYBRISFUNCTIONS_H
#define EGLHYBRISFUNCTIONS_H

#include <EGL/egl.h>
#include <EGL/eglext.h>

#include <QOpenGLFunctions>

// from hybris_nativebuffer.h in libhybris
#define HYBRIS_USAGE_SW_READ_RARELY 0x00000002
#define HYBRIS_USAGE_SW_WRITE_RARELY 0x00000020
#define HYBRIS_USAGE_HW_TEXTURE 0x00000100
#define HYBRIS_USAGE_HW_RENDER 0x00000200
#define HYBRIS_USAGE_HW_COMPOSER 0x00000800
#define HYBRIS_PIXEL_FORMAT_RGBA_8888 1
#define HYBRIS_PIXEL_FORMAT_RGBX_8888 2
#define HYBRIS_PIXEL_FORMAT_RGB_888 3
#define HYBRIS_PIXEL_FORMAT_BGRA_8888 5

#define EGL_NATIVE_BUFFER_HYBRIS 0x3140
struct EglHybrisFunctions
{
typedef EGLBoolean (EGLAPIENTRYP _eglHybrisCreateNativeBuffer)(EGLint width, EGLint height, EGLint usage, EGLint format, EGLint *stride, EGLClientBuffer *buffer);
typedef EGLBoolean (EGLAPIENTRYP _eglHybrisLockNativeBuffer)(EGLClientBuffer buffer, EGLint usage, EGLint l, EGLint t, EGLint w, EGLint h, void **vaddr);
typedef EGLBoolean (EGLAPIENTRYP _eglHybrisUnlockNativeBuffer)(EGLClientBuffer buffer);
typedef EGLBoolean (EGLAPIENTRYP _eglHybrisReleaseNativeBuffer)(EGLClientBuffer buffer);
typedef EGLBoolean (EGLAPIENTRYP _eglHybrisNativeBufferHandle)(EGLDisplay dpy, EGLClientBuffer buffer, void **handle);

typedef void (EGLAPIENTRYP _glEGLImageTargetTexture2DOES)(GLenum target, EGLImageKHR image);
typedef EGLImageKHR (EGLAPIENTRYP _eglCreateImageKHR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attribs);
typedef EGLBoolean (EGLAPIENTRYP _eglDestroyImageKHR)(EGLDisplay dpy, EGLImageKHR image);

const _glEGLImageTargetTexture2DOES glEGLImageTargetTexture2DOES = reinterpret_cast<_glEGLImageTargetTexture2DOES>(eglGetProcAddress("glEGLImageTargetTexture2DOES"));
const _eglCreateImageKHR eglCreateImageKHR = reinterpret_cast<_eglCreateImageKHR>(eglGetProcAddress("eglCreateImageKHR"));
const _eglDestroyImageKHR eglDestroyImageKHR = reinterpret_cast<_eglDestroyImageKHR>(eglGetProcAddress("eglDestroyImageKHR"));
const _eglHybrisCreateNativeBuffer eglHybrisCreateNativeBuffer = reinterpret_cast<_eglHybrisCreateNativeBuffer>(eglGetProcAddress("eglHybrisCreateNativeBuffer"));
const _eglHybrisLockNativeBuffer eglHybrisLockNativeBuffer = reinterpret_cast<_eglHybrisLockNativeBuffer>(eglGetProcAddress("eglHybrisLockNativeBuffer"));
const _eglHybrisUnlockNativeBuffer eglHybrisUnlockNativeBuffer = reinterpret_cast<_eglHybrisUnlockNativeBuffer>(eglGetProcAddress("eglHybrisUnlockNativeBuffer"));
const _eglHybrisReleaseNativeBuffer eglHybrisReleaseNativeBuffer = reinterpret_cast<_eglHybrisReleaseNativeBuffer>(eglGetProcAddress("eglHybrisReleaseNativeBuffer"));
const _eglHybrisNativeBufferHandle eglHybrisNativeBufferHandle = reinterpret_cast<_eglHybrisNativeBufferHandle>(eglGetProcAddress("eglHybrisNativeBufferHandle"));

static const EglHybrisFunctions *instance();
};

#endif

0 comments on commit 58e4ffa

Please sign in to comment.