Fill solid background in OpenGL renderer.
This commit is contained in:
		
							parent
							
								
									3e79b67032
								
							
						
					
					
						commit
						047989abcf
					
				
					 2 changed files with 209 additions and 131 deletions
				
			
		| 
						 | 
					@ -23,12 +23,95 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
				
			||||||
#include "core/application.h"
 | 
					#include "core/application.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <QtGui/QWindow>
 | 
					#include <QtGui/QWindow>
 | 
				
			||||||
 | 
					#include <QtGui/QOpenGLShader>
 | 
				
			||||||
 | 
					#include <QtGui/QOpenGLShaderProgram>
 | 
				
			||||||
 | 
					#include <QtGui/QOpenGLBuffer>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Calls::Group {
 | 
					namespace Calls::Group {
 | 
				
			||||||
namespace {
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
constexpr auto kShadowMaxAlpha = 80;
 | 
					constexpr auto kShadowMaxAlpha = 80;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *FrameVertexShader() {
 | 
				
			||||||
 | 
						return R"(
 | 
				
			||||||
 | 
					#version 130
 | 
				
			||||||
 | 
					in vec2 position;
 | 
				
			||||||
 | 
					in vec2 texcoord;
 | 
				
			||||||
 | 
					uniform vec2 viewport;
 | 
				
			||||||
 | 
					out vec2 v_texcoord;
 | 
				
			||||||
 | 
					vec4 transform(vec2 pos) {
 | 
				
			||||||
 | 
						return vec4(vec2(-1, -1) + 2 * pos / viewport, 0., 1.);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void main() {
 | 
				
			||||||
 | 
						gl_Position = transform(position);
 | 
				
			||||||
 | 
						v_texcoord = texcoord;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					)";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *FrameFragmentShader() {
 | 
				
			||||||
 | 
						return R"(
 | 
				
			||||||
 | 
					#version 130
 | 
				
			||||||
 | 
					in vec2 v_texcoord;
 | 
				
			||||||
 | 
					uniform sampler2D s_texture;
 | 
				
			||||||
 | 
					out vec4 fragColor;
 | 
				
			||||||
 | 
					void main() {
 | 
				
			||||||
 | 
						vec4 color = texture(s_texture, v_texcoord);
 | 
				
			||||||
 | 
					    fragColor = vec4(color.b, color.g, color.r, color.a);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					)";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *FillVertexShader() {
 | 
				
			||||||
 | 
						return R"(
 | 
				
			||||||
 | 
					#version 130
 | 
				
			||||||
 | 
					in vec2 position;
 | 
				
			||||||
 | 
					uniform vec2 viewport;
 | 
				
			||||||
 | 
					vec4 transform(vec2 pos) {
 | 
				
			||||||
 | 
						return vec4(vec2(-1, -1) + 2 * pos / viewport, 0., 1.);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void main() {
 | 
				
			||||||
 | 
						gl_Position = transform(position);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					)";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *FillFragmentShader() {
 | 
				
			||||||
 | 
						return R"(
 | 
				
			||||||
 | 
					#version 130
 | 
				
			||||||
 | 
					uniform vec4 s_color;
 | 
				
			||||||
 | 
					out vec4 fragColor;
 | 
				
			||||||
 | 
					void main() {
 | 
				
			||||||
 | 
					    fragColor = s_color;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					)";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					not_null<QOpenGLShader*> MakeShader(
 | 
				
			||||||
 | 
							not_null<QOpenGLShaderProgram*> program,
 | 
				
			||||||
 | 
							QOpenGLShader::ShaderType type,
 | 
				
			||||||
 | 
							const char *source) {
 | 
				
			||||||
 | 
						const auto result = new QOpenGLShader(type, program);
 | 
				
			||||||
 | 
						if (!result->compileSourceCode(source)) {
 | 
				
			||||||
 | 
							LOG(("Shader Compilation Failed: %1, error %2."
 | 
				
			||||||
 | 
								).arg(source
 | 
				
			||||||
 | 
								).arg(result->log()));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						program->addShader(result);
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LinkProgram(
 | 
				
			||||||
 | 
							not_null<QOpenGLShaderProgram*> program,
 | 
				
			||||||
 | 
							const char *vertexSource,
 | 
				
			||||||
 | 
							const char *fragmentSource) {
 | 
				
			||||||
 | 
						MakeShader(program, QOpenGLShader::Vertex, vertexSource);
 | 
				
			||||||
 | 
						MakeShader(program, QOpenGLShader::Fragment, fragmentSource);
 | 
				
			||||||
 | 
						if (!program->link()) {
 | 
				
			||||||
 | 
							LOG(("Shader Link Failed: %1.").arg(program->log()));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace
 | 
					} // namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct LargeVideo::PinButton {
 | 
					struct LargeVideo::PinButton {
 | 
				
			||||||
| 
						 | 
					@ -55,6 +138,10 @@ public:
 | 
				
			||||||
		not_null<QOpenGLWidget*> widget,
 | 
							not_null<QOpenGLWidget*> widget,
 | 
				
			||||||
		not_null<QOpenGLFunctions*> f) override;
 | 
							not_null<QOpenGLFunctions*> f) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void deinit(
 | 
				
			||||||
 | 
							not_null<QOpenGLWidget*> widget,
 | 
				
			||||||
 | 
							not_null<QOpenGLFunctions*> f) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void resize(
 | 
						void resize(
 | 
				
			||||||
		not_null<QOpenGLWidget*> widget,
 | 
							not_null<QOpenGLWidget*> widget,
 | 
				
			||||||
		not_null<QOpenGLFunctions*> f,
 | 
							not_null<QOpenGLFunctions*> f,
 | 
				
			||||||
| 
						 | 
					@ -66,17 +153,14 @@ public:
 | 
				
			||||||
		not_null<QOpenGLFunctions*> f) override;
 | 
							not_null<QOpenGLFunctions*> f) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	void deinit(not_null<QOpenGLContext*> context);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const not_null<LargeVideo*> _owner;
 | 
						const not_null<LargeVideo*> _owner;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::array<GLuint, 3> _textures = {};
 | 
						std::array<GLuint, 3> _textures = {};
 | 
				
			||||||
	GLuint _vertexBuffer = 0;
 | 
						std::optional<QOpenGLBuffer> _frameBuffer;
 | 
				
			||||||
	GLuint _vertexShader = 0;
 | 
						std::optional<QOpenGLBuffer> _fillBuffer;
 | 
				
			||||||
	GLuint _fragmentShader = 0;
 | 
						std::optional<QOpenGLShaderProgram> _frameProgram;
 | 
				
			||||||
	GLuint _shaderProgram = 0;
 | 
						std::optional<QOpenGLShaderProgram> _fillProgram;
 | 
				
			||||||
	qint64 _key = 0;
 | 
						qint64 _key = 0;
 | 
				
			||||||
	QMetaObject::Connection _connection;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -98,15 +182,6 @@ LargeVideo::RendererGL::~RendererGL() {
 | 
				
			||||||
void LargeVideo::RendererGL::init(
 | 
					void LargeVideo::RendererGL::init(
 | 
				
			||||||
		not_null<QOpenGLWidget*> widget,
 | 
							not_null<QOpenGLWidget*> widget,
 | 
				
			||||||
		not_null<QOpenGLFunctions*> f) {
 | 
							not_null<QOpenGLFunctions*> f) {
 | 
				
			||||||
	if (_connection) {
 | 
					 | 
				
			||||||
		QObject::disconnect(_connection);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	const auto context = widget->context();
 | 
					 | 
				
			||||||
	_connection = QObject::connect(
 | 
					 | 
				
			||||||
		context,
 | 
					 | 
				
			||||||
		&QOpenGLContext::aboutToBeDestroyed,
 | 
					 | 
				
			||||||
		[=] { deinit(context); });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	f->glGenTextures(3, _textures.data());
 | 
						f->glGenTextures(3, _textures.data());
 | 
				
			||||||
	for (const auto texture : _textures) {
 | 
						for (const auto texture : _textures) {
 | 
				
			||||||
		f->glBindTexture(GL_TEXTURE_2D, texture);
 | 
							f->glBindTexture(GL_TEXTURE_2D, texture);
 | 
				
			||||||
| 
						 | 
					@ -116,79 +191,32 @@ void LargeVideo::RendererGL::init(
 | 
				
			||||||
		f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 | 
							f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 | 
				
			||||||
		f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 | 
							f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	f->glGenBuffers(1, &_vertexBuffer);
 | 
						_frameBuffer.emplace();
 | 
				
			||||||
 | 
						_frameBuffer->setUsagePattern(QOpenGLBuffer::DynamicDraw);
 | 
				
			||||||
 | 
						_frameBuffer->create();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const char *vertexShaderSource = R"(
 | 
						_fillBuffer.emplace();
 | 
				
			||||||
#version 130
 | 
						_fillBuffer->setUsagePattern(QOpenGLBuffer::DynamicDraw);
 | 
				
			||||||
in vec2 position;
 | 
						_fillBuffer->create();
 | 
				
			||||||
in vec2 texcoord;
 | 
					 | 
				
			||||||
out vec2 v_texcoord;
 | 
					 | 
				
			||||||
void main() {
 | 
					 | 
				
			||||||
	gl_Position = vec4(position.x, position.y, 0.0, 1.0);
 | 
					 | 
				
			||||||
	v_texcoord = texcoord;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
)";
 | 
					 | 
				
			||||||
	_vertexShader = f->glCreateShader(GL_VERTEX_SHADER);
 | 
					 | 
				
			||||||
	f->glShaderSource(_vertexShader, 1, &vertexShaderSource, NULL);
 | 
					 | 
				
			||||||
	f->glCompileShader(_vertexShader);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	{
 | 
						_frameProgram.emplace();
 | 
				
			||||||
		int  success;
 | 
						LinkProgram(&*_frameProgram, FrameVertexShader(), FrameFragmentShader());
 | 
				
			||||||
		char infoLog[512];
 | 
					 | 
				
			||||||
		f->glGetShaderiv(_vertexShader, GL_COMPILE_STATUS, &success);
 | 
					 | 
				
			||||||
		if (!success) {
 | 
					 | 
				
			||||||
			f->glGetShaderInfoLog(_vertexShader, 512, NULL, infoLog);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		int a = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const char *fragmentShaderSource = R"(
 | 
						_fillProgram.emplace();
 | 
				
			||||||
#version 130
 | 
						LinkProgram(&*_fillProgram, FillVertexShader(), FillFragmentShader());
 | 
				
			||||||
in vec2 v_texcoord;
 | 
					 | 
				
			||||||
uniform sampler2D s_texture;
 | 
					 | 
				
			||||||
out vec4 fragColor;
 | 
					 | 
				
			||||||
void main() {
 | 
					 | 
				
			||||||
	vec4 color = texture(s_texture, v_texcoord);
 | 
					 | 
				
			||||||
    fragColor = vec4(color.b, color.g, color.r, color.a);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
)";
 | 
					 | 
				
			||||||
	// ;
 | 
					 | 
				
			||||||
	_fragmentShader = f->glCreateShader(GL_FRAGMENT_SHADER);
 | 
					 | 
				
			||||||
	f->glShaderSource(_fragmentShader, 1, &fragmentShaderSource, NULL);
 | 
					 | 
				
			||||||
	f->glCompileShader(_fragmentShader);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		int  success;
 | 
					 | 
				
			||||||
		char infoLog[512];
 | 
					 | 
				
			||||||
		f->glGetShaderiv(_fragmentShader, GL_COMPILE_STATUS, &success);
 | 
					 | 
				
			||||||
		if (!success) {
 | 
					 | 
				
			||||||
			f->glGetShaderInfoLog(_fragmentShader, 512, NULL, infoLog);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		int a = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_shaderProgram = f->glCreateProgram();
 | 
					 | 
				
			||||||
	f->glAttachShader(_shaderProgram, _vertexShader);
 | 
					 | 
				
			||||||
	f->glAttachShader(_shaderProgram, _fragmentShader);
 | 
					 | 
				
			||||||
	f->glLinkProgram(_shaderProgram);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		int  success;
 | 
					 | 
				
			||||||
		char infoLog[512];
 | 
					 | 
				
			||||||
		f->glGetProgramiv(_shaderProgram, GL_LINK_STATUS, &success);
 | 
					 | 
				
			||||||
		if (!success) {
 | 
					 | 
				
			||||||
			f->glGetProgramInfoLog(_shaderProgram, 512, NULL, infoLog);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		int a = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void LargeVideo::RendererGL::deinit(not_null<QOpenGLContext*> context) {
 | 
					void LargeVideo::RendererGL::deinit(
 | 
				
			||||||
	context->functions()->glDeleteTextures(_textures.size(), _textures.data());
 | 
							not_null<QOpenGLWidget*> widget,
 | 
				
			||||||
	context->functions()->glDeleteBuffers(1, &_vertexBuffer);
 | 
							not_null<QOpenGLFunctions*> f) {
 | 
				
			||||||
	context->functions()->glDeleteProgram(_shaderProgram);
 | 
						if (_textures.front()) {
 | 
				
			||||||
	context->functions()->glDeleteShader(_vertexShader);
 | 
							f->glDeleteTextures(_textures.size(), _textures.data());
 | 
				
			||||||
	context->functions()->glDeleteShader(_fragmentShader);
 | 
							ranges::fill(_textures, 0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_frameBuffer = std::nullopt;
 | 
				
			||||||
 | 
						_fillBuffer = std::nullopt;
 | 
				
			||||||
 | 
						_frameProgram = std::nullopt;
 | 
				
			||||||
 | 
						_fillProgram = std::nullopt;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void LargeVideo::RendererGL::resize(
 | 
					void LargeVideo::RendererGL::resize(
 | 
				
			||||||
| 
						 | 
					@ -202,23 +230,58 @@ void LargeVideo::RendererGL::resize(
 | 
				
			||||||
void LargeVideo::RendererGL::paint(
 | 
					void LargeVideo::RendererGL::paint(
 | 
				
			||||||
		not_null<QOpenGLWidget*> widget,
 | 
							not_null<QOpenGLWidget*> widget,
 | 
				
			||||||
		not_null<QOpenGLFunctions*> f) {
 | 
							not_null<QOpenGLFunctions*> f) {
 | 
				
			||||||
	const auto bg = st::groupCallMembersFg->c;
 | 
						const auto size = _owner->widget()->size();
 | 
				
			||||||
	const auto fill = [&](QRect rect) {
 | 
						if (size.isEmpty()) {
 | 
				
			||||||
		//p.fillRect(rect, st::groupCallMembersBg);
 | 
							return;
 | 
				
			||||||
	};
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const auto bg = st::groupCallMembersBg->c;
 | 
				
			||||||
 | 
						const auto bgvector = QVector4D(
 | 
				
			||||||
 | 
							bg.redF(),
 | 
				
			||||||
 | 
							bg.greenF(),
 | 
				
			||||||
 | 
							bg.blueF(),
 | 
				
			||||||
 | 
							bg.alphaF());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const auto [image, rotation] = _owner->_track
 | 
						const auto [image, rotation] = _owner->_track
 | 
				
			||||||
		? _owner->_track.track->frameOriginalWithRotation()
 | 
							? _owner->_track.track->frameOriginalWithRotation()
 | 
				
			||||||
		: std::pair<QImage, int>();
 | 
							: std::pair<QImage, int>();
 | 
				
			||||||
	if (image.isNull()) {
 | 
						if (image.isNull()) {
 | 
				
			||||||
		f->glClearColor(bg.redF(), bg.greenF(), bg.blueF(), 1.);
 | 
							f->glClearColor(bgvector[0], bgvector[1], bgvector[2], bgvector[3]);
 | 
				
			||||||
		f->glClear(GL_COLOR_BUFFER_BIT);
 | 
							f->glClear(GL_COLOR_BUFFER_BIT);
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	f->glUseProgram(_shaderProgram);
 | 
					
 | 
				
			||||||
 | 
						const auto scaled = Media::View::FlipSizeByRotation(
 | 
				
			||||||
 | 
							image.size(),
 | 
				
			||||||
 | 
							rotation
 | 
				
			||||||
 | 
						).scaled(size, Qt::KeepAspectRatio);
 | 
				
			||||||
 | 
						const auto left = (size.width() - scaled.width()) / 2;
 | 
				
			||||||
 | 
						const auto top = (size.height() - scaled.height()) / 2;
 | 
				
			||||||
 | 
						const auto right = left + scaled.width();
 | 
				
			||||||
 | 
						const auto bottom = top + scaled.height();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto texcoords = std::array<std::array<GLfloat, 2>, 4> { {
 | 
				
			||||||
 | 
							{ {0, 1}},
 | 
				
			||||||
 | 
							{ {1, 1} },
 | 
				
			||||||
 | 
							{ {1, 0} },
 | 
				
			||||||
 | 
							{ {0, 0} },
 | 
				
			||||||
 | 
						} };
 | 
				
			||||||
 | 
						if (rotation > 0) {
 | 
				
			||||||
 | 
							std::rotate(
 | 
				
			||||||
 | 
								texcoords.begin(),
 | 
				
			||||||
 | 
								texcoords.begin() + (rotation / 90),
 | 
				
			||||||
 | 
								texcoords.end());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						const GLfloat vertices[] = {
 | 
				
			||||||
 | 
							float(left), float(top), texcoords[0][0], texcoords[0][1],
 | 
				
			||||||
 | 
							float(right), float(top), texcoords[1][0], texcoords[1][1],
 | 
				
			||||||
 | 
							float(right), float(bottom), texcoords[2][0], texcoords[2][1],
 | 
				
			||||||
 | 
							float(left), float(bottom), texcoords[3][0], texcoords[3][1],
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						f->glUseProgram(_frameProgram->programId());
 | 
				
			||||||
	f->glActiveTexture(GL_TEXTURE0);
 | 
						f->glActiveTexture(GL_TEXTURE0);
 | 
				
			||||||
	f->glBindTexture(GL_TEXTURE_2D, _textures[0]);
 | 
						f->glBindTexture(GL_TEXTURE_2D, _textures[0]);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// #TODO calls check stride, upload with stride or from copy of an image.
 | 
					 | 
				
			||||||
	const auto key = image.cacheKey();
 | 
						const auto key = image.cacheKey();
 | 
				
			||||||
	if (_key != key) {
 | 
						if (_key != key) {
 | 
				
			||||||
		_key = key;
 | 
							_key = key;
 | 
				
			||||||
| 
						 | 
					@ -237,51 +300,66 @@ void LargeVideo::RendererGL::paint(
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	_owner->_track.track->markFrameShown();
 | 
						_owner->_track.track->markFrameShown();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	f->glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
 | 
						_frameBuffer->bind();
 | 
				
			||||||
	std::array<std::array<GLfloat, 2>, 4> UVCoords = { {
 | 
						_frameBuffer->allocate(vertices, sizeof(vertices));
 | 
				
			||||||
		{{0, 1}},  // Lower left.
 | 
					 | 
				
			||||||
		{{1, 1}},  // Lower right.
 | 
					 | 
				
			||||||
		{{1, 0}},  // Upper right.
 | 
					 | 
				
			||||||
		{{0, 0}},  // Upper left.
 | 
					 | 
				
			||||||
	} };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const auto rotation_offset = (rotation / 90);
 | 
						_frameProgram->setUniformValue("viewport", QSizeF(size));
 | 
				
			||||||
	std::rotate(
 | 
						_frameProgram->setUniformValue("s_texture", GLint(0));
 | 
				
			||||||
		UVCoords.begin(),
 | 
					 | 
				
			||||||
		UVCoords.begin() + rotation_offset,
 | 
					 | 
				
			||||||
		UVCoords.end());
 | 
					 | 
				
			||||||
	const GLfloat vertices[] = {
 | 
					 | 
				
			||||||
	  -1, -1, UVCoords[0][0], UVCoords[0][1],
 | 
					 | 
				
			||||||
	   1, -1, UVCoords[1][0], UVCoords[1][1],
 | 
					 | 
				
			||||||
	   1,  1, UVCoords[2][0], UVCoords[2][1],
 | 
					 | 
				
			||||||
	  -1,  1, UVCoords[3][0], UVCoords[3][1],
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	f->glBufferData(
 | 
					 | 
				
			||||||
		GL_ARRAY_BUFFER,
 | 
					 | 
				
			||||||
		sizeof(vertices),
 | 
					 | 
				
			||||||
		vertices,
 | 
					 | 
				
			||||||
		GL_DYNAMIC_DRAW);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	GLint sampler = f->glGetUniformLocation(_shaderProgram, "s_texture");
 | 
						GLint position = _frameProgram->attributeLocation("position");
 | 
				
			||||||
	GLint position = f->glGetAttribLocation(_shaderProgram, "position");
 | 
						f->glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void*)0);
 | 
				
			||||||
	GLint texcoord = f->glGetAttribLocation(_shaderProgram, "texcoord");
 | 
					 | 
				
			||||||
	if (position < 0 || texcoord < 0) {
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	f->glUniform1i(sampler, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Read position attribute with size of 2 and stride of 4 beginning at the start of the array. The
 | 
					 | 
				
			||||||
	// last argument indicates offset of data within the vertex buffer.
 | 
					 | 
				
			||||||
	f->glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void *)0);
 | 
					 | 
				
			||||||
	f->glEnableVertexAttribArray(position);
 | 
						f->glEnableVertexAttribArray(position);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Read texcoord attribute  with size of 2 and stride of 4 beginning at the first texcoord in the
 | 
						GLint texcoord = _frameProgram->attributeLocation("texcoord");
 | 
				
			||||||
	// array. The last argument indicates offset of data within the vertex buffer.
 | 
						f->glVertexAttribPointer(texcoord, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
 | 
				
			||||||
	f->glVertexAttribPointer(texcoord, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void *)(2 * sizeof(GLfloat)));
 | 
					 | 
				
			||||||
	f->glEnableVertexAttribArray(texcoord);
 | 
						f->glEnableVertexAttribArray(texcoord);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	f->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 | 
						f->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						f->glDisableVertexAttribArray(position);
 | 
				
			||||||
 | 
						f->glDisableVertexAttribArray(texcoord);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						constexpr auto kMaxTriangles = 8;
 | 
				
			||||||
 | 
						auto coordinates = std::array<GLfloat, 6 * kMaxTriangles>{ 0 };
 | 
				
			||||||
 | 
						auto triangles = 0;
 | 
				
			||||||
 | 
						const auto fill = [&](QRect rect) {
 | 
				
			||||||
 | 
							auto i = triangles * 6;
 | 
				
			||||||
 | 
							coordinates[i + 0] = coordinates[i + 10] = rect.x();
 | 
				
			||||||
 | 
							coordinates[i + 1] = coordinates[i + 11] = rect.y();
 | 
				
			||||||
 | 
							coordinates[i + 2] = rect.x() + rect.width();
 | 
				
			||||||
 | 
							coordinates[i + 3] = rect.y();
 | 
				
			||||||
 | 
							coordinates[i + 4] = coordinates[i + 6] = rect.x() + rect.width();
 | 
				
			||||||
 | 
							coordinates[i + 5] = coordinates[i + 7] = rect.y() + rect.height();
 | 
				
			||||||
 | 
							coordinates[i + 8] = rect.x();
 | 
				
			||||||
 | 
							coordinates[i + 9] = rect.y() + rect.height();
 | 
				
			||||||
 | 
							triangles += 2;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						if (left > 0) {
 | 
				
			||||||
 | 
							fill({ 0, 0, left, size.height() });
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (right < size.width()) {
 | 
				
			||||||
 | 
							fill({ right, 0, size.width() - right, size.height() });
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (top > 0) {
 | 
				
			||||||
 | 
							fill({ 0, 0, size.width(), top });
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (bottom < size.height()) {
 | 
				
			||||||
 | 
							fill({ 0, bottom, size.width(), size.height() - bottom });
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (triangles > 0) {
 | 
				
			||||||
 | 
							_fillBuffer->bind();
 | 
				
			||||||
 | 
							_fillBuffer->allocate(coordinates.data(), triangles * 6 * sizeof(GLfloat));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							f->glUseProgram(_fillProgram->programId());
 | 
				
			||||||
 | 
							_fillProgram->setUniformValue("viewport", QSizeF(size));
 | 
				
			||||||
 | 
							_fillProgram->setUniformValue("s_color", bgvector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							GLint position = _fillProgram->attributeLocation("position");
 | 
				
			||||||
 | 
							f->glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (void*)0);
 | 
				
			||||||
 | 
							f->glEnableVertexAttribArray(position);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							f->glDrawArrays(GL_TRIANGLES, 0, triangles * 3);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LargeVideo::LargeVideo(
 | 
					LargeVideo::LargeVideo(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1 +1 @@
 | 
				
			||||||
Subproject commit 5e38964fbfed38efdcf5c1628ca65d7e3469764a
 | 
					Subproject commit 8d7ced5c74328db316e2d80883ec0b12ab8c062b
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue