Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
Showing
7 changed files
with
584 additions
and
217 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Oops, something went wrong.