Add texture / image OpenGL helper.
This commit is contained in:
parent
c946611689
commit
2a26d4a91a
5 changed files with 169 additions and 9 deletions
|
|
@ -59,6 +59,8 @@ PRIVATE
|
|||
ui/effects/slide_animation.h
|
||||
ui/gl/gl_detection.cpp
|
||||
ui/gl/gl_detection.h
|
||||
ui/gl/gl_image.cpp
|
||||
ui/gl/gl_image.h
|
||||
ui/gl/gl_surface.cpp
|
||||
ui/gl/gl_surface.h
|
||||
ui/image/image_prepare.cpp
|
||||
|
|
|
|||
85
ui/gl/gl_image.cpp
Normal file
85
ui/gl/gl_image.cpp
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
// This file is part of Desktop App Toolkit,
|
||||
// a set of libraries for developing nice desktop applications.
|
||||
//
|
||||
// For license and copyright information please follow this link:
|
||||
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||
//
|
||||
#include "ui/gl/gl_image.h"
|
||||
|
||||
#include <QtGui/QOpenGLFunctions>
|
||||
|
||||
namespace Ui::GL {
|
||||
namespace details {
|
||||
|
||||
void GenerateTextures(QOpenGLFunctions &f, gsl::span<GLuint> values) {
|
||||
Expects(!values.empty());
|
||||
|
||||
f.glGenTextures(values.size(), values.data());
|
||||
for (const auto texture : values) {
|
||||
f.glBindTexture(GL_TEXTURE_2D, texture);
|
||||
const auto clamp = GL_CLAMP_TO_EDGE;
|
||||
f.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp);
|
||||
f.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp);
|
||||
f.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
f.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyTextures(QOpenGLFunctions &f, gsl::span<GLuint> values) {
|
||||
Expects(!values.empty());
|
||||
|
||||
f.glDeleteTextures(values.size(), values.data());
|
||||
ranges::fill(values, 0);
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
void Image::setImage(QImage image) {
|
||||
_image = std::move(image);
|
||||
}
|
||||
|
||||
const QImage &Image::image() const {
|
||||
return _image;
|
||||
}
|
||||
|
||||
QImage Image::takeImage() {
|
||||
return _image.isNull() ? base::take(_storage) : base::take(_image);
|
||||
}
|
||||
|
||||
void Image::invalidate() {
|
||||
_storage = base::take(_image);
|
||||
}
|
||||
|
||||
void Image::bind(QOpenGLFunctions &f) {
|
||||
Expects(!_image.isNull());
|
||||
|
||||
_textures.ensureCreated(f);
|
||||
const auto cacheKey = _image.cacheKey();
|
||||
const auto upload = (_cacheKey != cacheKey);
|
||||
if (upload) {
|
||||
_cacheKey = cacheKey;
|
||||
_index = 1 - _index;
|
||||
}
|
||||
_textures.bind(f, _index);
|
||||
const auto error = f.glGetError();
|
||||
if (upload) {
|
||||
f.glPixelStorei(GL_UNPACK_ROW_LENGTH, _image.bytesPerLine() / 4);
|
||||
f.glTexImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RGBA,
|
||||
_image.width(),
|
||||
_image.height(),
|
||||
0,
|
||||
GL_RGBA,
|
||||
GL_UNSIGNED_BYTE,
|
||||
_image.constBits());
|
||||
f.glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Image::destroy(QOpenGLFunctions &f) {
|
||||
_textures.destroy(f);
|
||||
_cacheKey = 0;
|
||||
}
|
||||
|
||||
} // namespace Ui::GL
|
||||
73
ui/gl/gl_image.h
Normal file
73
ui/gl/gl_image.h
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
// This file is part of Desktop App Toolkit,
|
||||
// a set of libraries for developing nice desktop applications.
|
||||
//
|
||||
// For license and copyright information please follow this link:
|
||||
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include <QtGui/QOpenGLFunctions>
|
||||
|
||||
namespace Ui::GL {
|
||||
namespace details {
|
||||
|
||||
void GenerateTextures(QOpenGLFunctions &f, gsl::span<GLuint> values);
|
||||
void DestroyTextures(QOpenGLFunctions &f, gsl::span<GLuint> values);
|
||||
|
||||
} // namespace details
|
||||
|
||||
template <size_t Count>
|
||||
class Textures final {
|
||||
public:
|
||||
static_assert(Count > 0);
|
||||
|
||||
void ensureCreated(QOpenGLFunctions &f) {
|
||||
if (!created()) {
|
||||
details::GenerateTextures(f, gsl::make_span(_values));
|
||||
}
|
||||
}
|
||||
void destroy(QOpenGLFunctions &f) {
|
||||
if (created()) {
|
||||
details::DestroyTextures(f, gsl::make_span(_values));
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] void bind(QOpenGLFunctions &f, int index) const {
|
||||
Expects(index >= 0 && index < Count);
|
||||
|
||||
f.glBindTexture(GL_TEXTURE_2D, _values[index]);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool created() const {
|
||||
return (_values[0] != 0);
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<GLuint, Count> _values = { { 0 } };
|
||||
|
||||
};
|
||||
|
||||
class Image final {
|
||||
public:
|
||||
void setImage(QImage image);
|
||||
[[nodiscard]] const QImage &image() const;
|
||||
[[nodiscard]] QImage takeImage();
|
||||
void invalidate();
|
||||
|
||||
void bind(QOpenGLFunctions &f);
|
||||
void destroy(QOpenGLFunctions &f);
|
||||
|
||||
explicit operator bool() const {
|
||||
return !_image.isNull();
|
||||
}
|
||||
|
||||
private:
|
||||
QImage _image;
|
||||
QImage _storage;
|
||||
Textures<2> _textures;
|
||||
qint64 _cacheKey = 0;
|
||||
int _index = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Ui::GL
|
||||
|
|
@ -71,15 +71,15 @@ void SurfaceOpenGL::initializeGL() {
|
|||
context,
|
||||
&QOpenGLContext::aboutToBeDestroyed,
|
||||
[=] { callDeInit(); });
|
||||
_renderer->init(this, context->functions());
|
||||
_renderer->init(this, *context->functions());
|
||||
}
|
||||
|
||||
void SurfaceOpenGL::resizeGL(int w, int h) {
|
||||
_renderer->resize(this, context()->functions(), w, h);
|
||||
_renderer->resize(this, *context()->functions(), w, h);
|
||||
}
|
||||
|
||||
void SurfaceOpenGL::paintGL() {
|
||||
_renderer->paint(this, context()->functions());
|
||||
_renderer->paint(this, *context()->functions());
|
||||
}
|
||||
|
||||
void SurfaceOpenGL::callDeInit() {
|
||||
|
|
@ -91,7 +91,7 @@ void SurfaceOpenGL::callDeInit() {
|
|||
Assert(surface != nullptr);
|
||||
const auto context = this->context();
|
||||
context->makeCurrent(surface);
|
||||
_renderer->deinit(this, context->functions());
|
||||
_renderer->deinit(this, *context->functions());
|
||||
}
|
||||
|
||||
SurfaceRaster::SurfaceRaster(
|
||||
|
|
@ -109,7 +109,7 @@ void SurfaceRaster::paintEvent(QPaintEvent *e) {
|
|||
|
||||
void Renderer::paint(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
not_null<QOpenGLFunctions*> f) {
|
||||
QOpenGLFunctions &f) {
|
||||
paintFallback(Painter(widget.get()), widget->rect(), Backend::OpenGL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,24 +28,24 @@ class Renderer {
|
|||
public:
|
||||
virtual void init(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
not_null<QOpenGLFunctions*> f) {
|
||||
QOpenGLFunctions &f) {
|
||||
}
|
||||
|
||||
virtual void deinit(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
not_null<QOpenGLFunctions*> f) {
|
||||
QOpenGLFunctions &f) {
|
||||
}
|
||||
|
||||
virtual void resize(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
not_null<QOpenGLFunctions*> f,
|
||||
QOpenGLFunctions &f,
|
||||
int w,
|
||||
int h) {
|
||||
}
|
||||
|
||||
virtual void paint(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
not_null<QOpenGLFunctions*> f);
|
||||
QOpenGLFunctions &f);
|
||||
|
||||
virtual void paintFallback(
|
||||
Painter &&p,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue