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/effects/slide_animation.h
|
||||||
ui/gl/gl_detection.cpp
|
ui/gl/gl_detection.cpp
|
||||||
ui/gl/gl_detection.h
|
ui/gl/gl_detection.h
|
||||||
|
ui/gl/gl_image.cpp
|
||||||
|
ui/gl/gl_image.h
|
||||||
ui/gl/gl_surface.cpp
|
ui/gl/gl_surface.cpp
|
||||||
ui/gl/gl_surface.h
|
ui/gl/gl_surface.h
|
||||||
ui/image/image_prepare.cpp
|
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,
|
context,
|
||||||
&QOpenGLContext::aboutToBeDestroyed,
|
&QOpenGLContext::aboutToBeDestroyed,
|
||||||
[=] { callDeInit(); });
|
[=] { callDeInit(); });
|
||||||
_renderer->init(this, context->functions());
|
_renderer->init(this, *context->functions());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceOpenGL::resizeGL(int w, int h) {
|
void SurfaceOpenGL::resizeGL(int w, int h) {
|
||||||
_renderer->resize(this, context()->functions(), w, h);
|
_renderer->resize(this, *context()->functions(), w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceOpenGL::paintGL() {
|
void SurfaceOpenGL::paintGL() {
|
||||||
_renderer->paint(this, context()->functions());
|
_renderer->paint(this, *context()->functions());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceOpenGL::callDeInit() {
|
void SurfaceOpenGL::callDeInit() {
|
||||||
|
|
@ -91,7 +91,7 @@ void SurfaceOpenGL::callDeInit() {
|
||||||
Assert(surface != nullptr);
|
Assert(surface != nullptr);
|
||||||
const auto context = this->context();
|
const auto context = this->context();
|
||||||
context->makeCurrent(surface);
|
context->makeCurrent(surface);
|
||||||
_renderer->deinit(this, context->functions());
|
_renderer->deinit(this, *context->functions());
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfaceRaster::SurfaceRaster(
|
SurfaceRaster::SurfaceRaster(
|
||||||
|
|
@ -109,7 +109,7 @@ void SurfaceRaster::paintEvent(QPaintEvent *e) {
|
||||||
|
|
||||||
void Renderer::paint(
|
void Renderer::paint(
|
||||||
not_null<QOpenGLWidget*> widget,
|
not_null<QOpenGLWidget*> widget,
|
||||||
not_null<QOpenGLFunctions*> f) {
|
QOpenGLFunctions &f) {
|
||||||
paintFallback(Painter(widget.get()), widget->rect(), Backend::OpenGL);
|
paintFallback(Painter(widget.get()), widget->rect(), Backend::OpenGL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,24 +28,24 @@ class Renderer {
|
||||||
public:
|
public:
|
||||||
virtual void init(
|
virtual void init(
|
||||||
not_null<QOpenGLWidget*> widget,
|
not_null<QOpenGLWidget*> widget,
|
||||||
not_null<QOpenGLFunctions*> f) {
|
QOpenGLFunctions &f) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void deinit(
|
virtual void deinit(
|
||||||
not_null<QOpenGLWidget*> widget,
|
not_null<QOpenGLWidget*> widget,
|
||||||
not_null<QOpenGLFunctions*> f) {
|
QOpenGLFunctions &f) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void resize(
|
virtual void resize(
|
||||||
not_null<QOpenGLWidget*> widget,
|
not_null<QOpenGLWidget*> widget,
|
||||||
not_null<QOpenGLFunctions*> f,
|
QOpenGLFunctions &f,
|
||||||
int w,
|
int w,
|
||||||
int h) {
|
int h) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void paint(
|
virtual void paint(
|
||||||
not_null<QOpenGLWidget*> widget,
|
not_null<QOpenGLWidget*> widget,
|
||||||
not_null<QOpenGLFunctions*> f);
|
QOpenGLFunctions &f);
|
||||||
|
|
||||||
virtual void paintFallback(
|
virtual void paintFallback(
|
||||||
Painter &&p,
|
Painter &&p,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue