Round corners of LargeVideo.
This commit is contained in:
parent
047989abcf
commit
f40659a7b4
|
@ -32,65 +32,122 @@ namespace {
|
||||||
|
|
||||||
constexpr auto kShadowMaxAlpha = 80;
|
constexpr auto kShadowMaxAlpha = 80;
|
||||||
|
|
||||||
const char *FrameVertexShader() {
|
struct ShaderPart {
|
||||||
|
QString header;
|
||||||
|
QString body;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] QString VertexShader(const std::vector<ShaderPart> &parts) {
|
||||||
|
const auto accumulate = [&](auto proj) {
|
||||||
|
return ranges::accumulate(parts, QString(), std::plus<>(), proj);
|
||||||
|
};
|
||||||
return R"(
|
return R"(
|
||||||
#version 130
|
#version 130
|
||||||
in vec2 position;
|
in vec2 position;
|
||||||
in vec2 texcoord;
|
)" + accumulate(&ShaderPart::header) + R"(
|
||||||
uniform vec2 viewport;
|
|
||||||
out vec2 v_texcoord;
|
|
||||||
vec4 transform(vec2 pos) {
|
|
||||||
return vec4(vec2(-1, -1) + 2 * pos / viewport, 0., 1.);
|
|
||||||
}
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = transform(position);
|
vec4 result = vec4(position, 0., 1.);
|
||||||
v_texcoord = texcoord;
|
)" + accumulate(&ShaderPart::body) + R"(
|
||||||
|
gl_Position = result;
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *FrameFragmentShader() {
|
[[nodiscard]] QString FragmentShader(const std::vector<ShaderPart> &parts) {
|
||||||
|
const auto accumulate = [&](auto proj) {
|
||||||
|
return ranges::accumulate(parts, QString(), std::plus<>(), proj);
|
||||||
|
};
|
||||||
return R"(
|
return R"(
|
||||||
#version 130
|
#version 130
|
||||||
|
out vec4 fragColor;
|
||||||
|
)" + accumulate(&ShaderPart::header) + R"(
|
||||||
|
void main() {
|
||||||
|
vec4 result = vec4(0., 0., 0., 0.);
|
||||||
|
)" + accumulate(&ShaderPart::body) + R"(
|
||||||
|
fragColor = result;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] ShaderPart VertexPassTextureCoord() {
|
||||||
|
return {
|
||||||
|
.header = R"(
|
||||||
|
in vec2 texcoord;
|
||||||
|
out vec2 v_texcoord;
|
||||||
|
)",
|
||||||
|
.body = R"(
|
||||||
|
v_texcoord = texcoord;
|
||||||
|
)",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] ShaderPart FragmentSampleTexture() {
|
||||||
|
return {
|
||||||
|
.header = R"(
|
||||||
in vec2 v_texcoord;
|
in vec2 v_texcoord;
|
||||||
uniform sampler2D s_texture;
|
uniform sampler2D s_texture;
|
||||||
out vec4 fragColor;
|
)",
|
||||||
void main() {
|
.body = R"(
|
||||||
vec4 color = texture(s_texture, v_texcoord);
|
result = texture(s_texture, v_texcoord);
|
||||||
fragColor = vec4(color.b, color.g, color.r, color.a);
|
result = vec4(result.b, result.g, result.r, result.a);
|
||||||
}
|
)",
|
||||||
)";
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *FillVertexShader() {
|
[[nodiscard]] ShaderPart VertexViewportTransform() {
|
||||||
return R"(
|
return {
|
||||||
#version 130
|
.header = R"(
|
||||||
in vec2 position;
|
|
||||||
uniform vec2 viewport;
|
uniform vec2 viewport;
|
||||||
vec4 transform(vec2 pos) {
|
vec4 transform(vec4 position) {
|
||||||
return vec4(vec2(-1, -1) + 2 * pos / viewport, 0., 1.);
|
return vec4(
|
||||||
|
vec2(-1, -1) + 2 * position.xy / viewport,
|
||||||
|
position.z,
|
||||||
|
position.w);
|
||||||
}
|
}
|
||||||
void main() {
|
)",
|
||||||
gl_Position = transform(position);
|
.body = R"(
|
||||||
}
|
result = transform(result);
|
||||||
)";
|
)",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *FillFragmentShader() {
|
[[nodiscard]] ShaderPart FragmentRoundCorners() {
|
||||||
return R"(
|
return {
|
||||||
#version 130
|
.header = R"(
|
||||||
uniform vec4 s_color;
|
uniform vec2 viewport;
|
||||||
out vec4 fragColor;
|
uniform float roundRadius;
|
||||||
void main() {
|
float roundedCorner() {
|
||||||
fragColor = s_color;
|
vec2 viewportHalf = viewport / 2;
|
||||||
|
vec2 fromViewportCenter = abs(gl_FragCoord.xy - viewportHalf);
|
||||||
|
vec2 vectorRadius = vec2(roundRadius + 0.5, roundRadius + 0.5);
|
||||||
|
vec2 fromCenterWithRadius = fromViewportCenter + vectorRadius;
|
||||||
|
vec2 fromRoundingCenter = max(fromCenterWithRadius, viewportHalf)
|
||||||
|
- viewportHalf;
|
||||||
|
float d = length(fromRoundingCenter) - roundRadius;
|
||||||
|
return 1. - smoothstep(0., 1., d);
|
||||||
}
|
}
|
||||||
)";
|
)",
|
||||||
|
.body = R"(
|
||||||
|
result = vec4(result.r, result.g, result.b, result.a * roundedCorner());
|
||||||
|
)",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] ShaderPart FragmentStaticColor() {
|
||||||
|
return {
|
||||||
|
.header = R"(
|
||||||
|
uniform vec4 s_color;
|
||||||
|
)",
|
||||||
|
.body = R"(
|
||||||
|
result = s_color;
|
||||||
|
)",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
not_null<QOpenGLShader*> MakeShader(
|
not_null<QOpenGLShader*> MakeShader(
|
||||||
not_null<QOpenGLShaderProgram*> program,
|
not_null<QOpenGLShaderProgram*> program,
|
||||||
QOpenGLShader::ShaderType type,
|
QOpenGLShader::ShaderType type,
|
||||||
const char *source) {
|
const QString &source) {
|
||||||
const auto result = new QOpenGLShader(type, program);
|
const auto result = new QOpenGLShader(type, program);
|
||||||
if (!result->compileSourceCode(source)) {
|
if (!result->compileSourceCode(source)) {
|
||||||
LOG(("Shader Compilation Failed: %1, error %2."
|
LOG(("Shader Compilation Failed: %1, error %2."
|
||||||
|
@ -103,8 +160,8 @@ not_null<QOpenGLShader*> MakeShader(
|
||||||
|
|
||||||
void LinkProgram(
|
void LinkProgram(
|
||||||
not_null<QOpenGLShaderProgram*> program,
|
not_null<QOpenGLShaderProgram*> program,
|
||||||
const char *vertexSource,
|
const QString &vertexSource,
|
||||||
const char *fragmentSource) {
|
const QString &fragmentSource) {
|
||||||
MakeShader(program, QOpenGLShader::Vertex, vertexSource);
|
MakeShader(program, QOpenGLShader::Vertex, vertexSource);
|
||||||
MakeShader(program, QOpenGLShader::Fragment, fragmentSource);
|
MakeShader(program, QOpenGLShader::Fragment, fragmentSource);
|
||||||
if (!program->link()) {
|
if (!program->link()) {
|
||||||
|
@ -112,6 +169,73 @@ void LinkProgram(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Quads final {
|
||||||
|
public:
|
||||||
|
void fill(QRect rect);
|
||||||
|
void paint(
|
||||||
|
not_null<QOpenGLFunctions*> f,
|
||||||
|
not_null<QOpenGLBuffer*> buffer,
|
||||||
|
not_null<QOpenGLShaderProgram*> program,
|
||||||
|
QSize viewport,
|
||||||
|
const QColor &color,
|
||||||
|
Fn<void()> additional = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr auto kMaxTriangles = 8;
|
||||||
|
std::array<GLfloat, 6 * kMaxTriangles> coordinates{ 0 };
|
||||||
|
int triangles = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void Quads::fill(QRect rect) {
|
||||||
|
Expects(triangles + 2 <= kMaxTriangles);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Quads::paint(
|
||||||
|
not_null<QOpenGLFunctions*> f,
|
||||||
|
not_null<QOpenGLBuffer*> buffer,
|
||||||
|
not_null<QOpenGLShaderProgram*> program,
|
||||||
|
QSize viewport,
|
||||||
|
const QColor &color,
|
||||||
|
Fn<void()> additional) {
|
||||||
|
if (!triangles) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buffer->bind();
|
||||||
|
buffer->allocate(coordinates.data(), triangles * 6 * sizeof(GLfloat));
|
||||||
|
|
||||||
|
f->glUseProgram(program->programId());
|
||||||
|
program->setUniformValue("viewport", QSizeF(viewport));
|
||||||
|
program->setUniformValue("s_color", QVector4D(
|
||||||
|
color.redF(),
|
||||||
|
color.greenF(),
|
||||||
|
color.blueF(),
|
||||||
|
color.alphaF()));
|
||||||
|
|
||||||
|
GLint position = program->attributeLocation("position");
|
||||||
|
f->glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (void*)0);
|
||||||
|
f->glEnableVertexAttribArray(position);
|
||||||
|
|
||||||
|
if (additional) {
|
||||||
|
additional();
|
||||||
|
}
|
||||||
|
|
||||||
|
f->glDrawArrays(GL_TRIANGLES, 0, triangles * 3);
|
||||||
|
|
||||||
|
f->glDisableVertexAttribArray(position);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
struct LargeVideo::PinButton {
|
struct LargeVideo::PinButton {
|
||||||
|
@ -158,9 +282,11 @@ private:
|
||||||
std::array<GLuint, 3> _textures = {};
|
std::array<GLuint, 3> _textures = {};
|
||||||
std::optional<QOpenGLBuffer> _frameBuffer;
|
std::optional<QOpenGLBuffer> _frameBuffer;
|
||||||
std::optional<QOpenGLBuffer> _fillBuffer;
|
std::optional<QOpenGLBuffer> _fillBuffer;
|
||||||
|
std::optional<QOpenGLBuffer> _cornersBgBuffer;
|
||||||
std::optional<QOpenGLShaderProgram> _frameProgram;
|
std::optional<QOpenGLShaderProgram> _frameProgram;
|
||||||
std::optional<QOpenGLShaderProgram> _fillProgram;
|
std::optional<QOpenGLShaderProgram> _fillProgram;
|
||||||
qint64 _key = 0;
|
std::optional<QOpenGLShaderProgram> _cornersBgProgram;
|
||||||
|
qint64 _frameKey = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -192,18 +318,41 @@ void LargeVideo::RendererGL::init(
|
||||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
}
|
}
|
||||||
_frameBuffer.emplace();
|
_frameBuffer.emplace();
|
||||||
_frameBuffer->setUsagePattern(QOpenGLBuffer::DynamicDraw);
|
_frameBuffer->setUsagePattern(QOpenGLBuffer::StaticDraw);
|
||||||
_frameBuffer->create();
|
_frameBuffer->create();
|
||||||
|
_frameProgram.emplace();
|
||||||
|
LinkProgram(
|
||||||
|
&*_frameProgram,
|
||||||
|
VertexShader({
|
||||||
|
VertexViewportTransform(),
|
||||||
|
VertexPassTextureCoord(),
|
||||||
|
}),
|
||||||
|
FragmentShader({
|
||||||
|
FragmentSampleTexture(),
|
||||||
|
FragmentRoundCorners(),
|
||||||
|
}));
|
||||||
|
|
||||||
_fillBuffer.emplace();
|
_fillBuffer.emplace();
|
||||||
_fillBuffer->setUsagePattern(QOpenGLBuffer::DynamicDraw);
|
_fillBuffer->setUsagePattern(QOpenGLBuffer::StaticDraw);
|
||||||
_fillBuffer->create();
|
_fillBuffer->create();
|
||||||
|
|
||||||
_frameProgram.emplace();
|
|
||||||
LinkProgram(&*_frameProgram, FrameVertexShader(), FrameFragmentShader());
|
|
||||||
|
|
||||||
_fillProgram.emplace();
|
_fillProgram.emplace();
|
||||||
LinkProgram(&*_fillProgram, FillVertexShader(), FillFragmentShader());
|
LinkProgram(
|
||||||
|
&*_fillProgram,
|
||||||
|
VertexShader({ VertexViewportTransform() }),
|
||||||
|
FragmentShader({
|
||||||
|
FragmentStaticColor(),
|
||||||
|
FragmentRoundCorners(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
_cornersBgBuffer.emplace();
|
||||||
|
_cornersBgBuffer->setUsagePattern(QOpenGLBuffer::StaticDraw);
|
||||||
|
_cornersBgBuffer->create();
|
||||||
|
_cornersBgProgram.emplace();
|
||||||
|
LinkProgram(
|
||||||
|
&*_cornersBgProgram,
|
||||||
|
VertexShader({ VertexViewportTransform() }),
|
||||||
|
FragmentShader({ FragmentStaticColor() }));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LargeVideo::RendererGL::deinit(
|
void LargeVideo::RendererGL::deinit(
|
||||||
|
@ -217,6 +366,7 @@ void LargeVideo::RendererGL::deinit(
|
||||||
_fillBuffer = std::nullopt;
|
_fillBuffer = std::nullopt;
|
||||||
_frameProgram = std::nullopt;
|
_frameProgram = std::nullopt;
|
||||||
_fillProgram = std::nullopt;
|
_fillProgram = std::nullopt;
|
||||||
|
_cornersBgProgram = std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LargeVideo::RendererGL::resize(
|
void LargeVideo::RendererGL::resize(
|
||||||
|
@ -245,11 +395,9 @@ void LargeVideo::RendererGL::paint(
|
||||||
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()) {
|
|
||||||
f->glClearColor(bgvector[0], bgvector[1], bgvector[2], bgvector[3]);
|
f->glEnable(GL_BLEND);
|
||||||
f->glClear(GL_COLOR_BUFFER_BIT);
|
f->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto scaled = Media::View::FlipSizeByRotation(
|
const auto scaled = Media::View::FlipSizeByRotation(
|
||||||
image.size(),
|
image.size(),
|
||||||
|
@ -259,107 +407,108 @@ void LargeVideo::RendererGL::paint(
|
||||||
const auto top = (size.height() - scaled.height()) / 2;
|
const auto top = (size.height() - scaled.height()) / 2;
|
||||||
const auto right = left + scaled.width();
|
const auto right = left + scaled.width();
|
||||||
const auto bottom = top + scaled.height();
|
const auto bottom = top + scaled.height();
|
||||||
|
const auto radius = GLfloat(st::roundRadiusLarge * cIntRetinaFactor());
|
||||||
|
|
||||||
auto texcoords = std::array<std::array<GLfloat, 2>, 4> { {
|
auto cornersBg = Quads();
|
||||||
{ {0, 1}},
|
const auto cornerBgSize = QSize(int(radius), int(radius));
|
||||||
{ {1, 1} },
|
cornersBg.fill({ QPoint(), cornerBgSize });
|
||||||
{ {1, 0} },
|
cornersBg.fill({ QPoint(size.width() - int(radius), 0), cornerBgSize });
|
||||||
{ {0, 0} },
|
cornersBg.fill({
|
||||||
} };
|
QPoint(size.width() - int(radius), size.height() - int(radius)),
|
||||||
if (rotation > 0) {
|
cornerBgSize
|
||||||
std::rotate(
|
});
|
||||||
texcoords.begin(),
|
cornersBg.fill({ QPoint(0, size.height() - int(radius)), cornerBgSize });
|
||||||
texcoords.begin() + (rotation / 90),
|
cornersBg.paint(
|
||||||
texcoords.end());
|
f,
|
||||||
}
|
&*_cornersBgBuffer,
|
||||||
const GLfloat vertices[] = {
|
&*_cornersBgProgram,
|
||||||
float(left), float(top), texcoords[0][0], texcoords[0][1],
|
size,
|
||||||
float(right), float(top), texcoords[1][0], texcoords[1][1],
|
st::groupCallBg->c);
|
||||||
float(right), float(bottom), texcoords[2][0], texcoords[2][1],
|
|
||||||
float(left), float(bottom), texcoords[3][0], texcoords[3][1],
|
|
||||||
};
|
|
||||||
|
|
||||||
f->glUseProgram(_frameProgram->programId());
|
auto sideQuads = Quads();
|
||||||
f->glActiveTexture(GL_TEXTURE0);
|
if (!image.isNull()) {
|
||||||
f->glBindTexture(GL_TEXTURE_2D, _textures[0]);
|
auto texcoords = std::array<std::array<GLfloat, 2>, 4> { {
|
||||||
const auto key = image.cacheKey();
|
{ { 0, 1 }},
|
||||||
if (_key != key) {
|
{ { 1, 1 } },
|
||||||
_key = key;
|
{ { 1, 0 } },
|
||||||
f->glPixelStorei(GL_UNPACK_ROW_LENGTH, image.bytesPerLine() / 4);
|
{ { 0, 0 } },
|
||||||
f->glTexImage2D(
|
} };
|
||||||
GL_TEXTURE_2D,
|
if (rotation > 0) {
|
||||||
0,
|
std::rotate(
|
||||||
GL_RGB,
|
texcoords.begin(),
|
||||||
image.width(),
|
texcoords.begin() + (rotation / 90),
|
||||||
image.height(),
|
texcoords.end());
|
||||||
0,
|
}
|
||||||
GL_RGBA,
|
const GLfloat vertices[] = {
|
||||||
GL_UNSIGNED_BYTE,
|
float(left), float(top), texcoords[0][0], texcoords[0][1],
|
||||||
image.constBits());
|
float(right), float(top), texcoords[1][0], texcoords[1][1],
|
||||||
f->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
float(right), float(bottom), texcoords[2][0], texcoords[2][1],
|
||||||
}
|
float(left), float(bottom), texcoords[3][0], texcoords[3][1],
|
||||||
_owner->_track.track->markFrameShown();
|
};
|
||||||
|
|
||||||
_frameBuffer->bind();
|
f->glUseProgram(_frameProgram->programId());
|
||||||
_frameBuffer->allocate(vertices, sizeof(vertices));
|
f->glActiveTexture(GL_TEXTURE0);
|
||||||
|
f->glBindTexture(GL_TEXTURE_2D, _textures[0]);
|
||||||
|
const auto key = image.cacheKey();
|
||||||
|
if (_frameKey != key) {
|
||||||
|
_frameKey = key;
|
||||||
|
f->glPixelStorei(GL_UNPACK_ROW_LENGTH, image.bytesPerLine() / 4);
|
||||||
|
f->glTexImage2D(
|
||||||
|
GL_TEXTURE_2D,
|
||||||
|
0,
|
||||||
|
GL_RGB,
|
||||||
|
image.width(),
|
||||||
|
image.height(),
|
||||||
|
0,
|
||||||
|
GL_RGBA,
|
||||||
|
GL_UNSIGNED_BYTE,
|
||||||
|
image.constBits());
|
||||||
|
f->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||||
|
}
|
||||||
|
_owner->_track.track->markFrameShown();
|
||||||
|
|
||||||
_frameProgram->setUniformValue("viewport", QSizeF(size));
|
_frameBuffer->bind();
|
||||||
_frameProgram->setUniformValue("s_texture", GLint(0));
|
_frameBuffer->allocate(vertices, sizeof(vertices));
|
||||||
|
|
||||||
GLint position = _frameProgram->attributeLocation("position");
|
_frameProgram->setUniformValue("viewport", QSizeF(size));
|
||||||
f->glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void*)0);
|
_frameProgram->setUniformValue("s_texture", GLint(0));
|
||||||
f->glEnableVertexAttribArray(position);
|
_frameProgram->setUniformValue("roundRadius", radius);
|
||||||
|
|
||||||
GLint texcoord = _frameProgram->attributeLocation("texcoord");
|
GLint position = _frameProgram->attributeLocation("position");
|
||||||
f->glVertexAttribPointer(texcoord, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
|
f->glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void*)0);
|
||||||
f->glEnableVertexAttribArray(texcoord);
|
|
||||||
|
|
||||||
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->glEnableVertexAttribArray(position);
|
||||||
|
|
||||||
f->glDrawArrays(GL_TRIANGLES, 0, triangles * 3);
|
GLint texcoord = _frameProgram->attributeLocation("texcoord");
|
||||||
|
f->glVertexAttribPointer(texcoord, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
|
||||||
|
f->glEnableVertexAttribArray(texcoord);
|
||||||
|
|
||||||
|
f->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
|
|
||||||
|
f->glDisableVertexAttribArray(position);
|
||||||
|
f->glDisableVertexAttribArray(texcoord);
|
||||||
|
|
||||||
|
if (left > 0) {
|
||||||
|
sideQuads.fill({ 0, 0, left, size.height() });
|
||||||
|
}
|
||||||
|
if (right < size.width()) {
|
||||||
|
sideQuads.fill({ right, 0, size.width() - right, size.height() });
|
||||||
|
}
|
||||||
|
if (top > 0) {
|
||||||
|
sideQuads.fill({ 0, 0, size.width(), top });
|
||||||
|
}
|
||||||
|
if (bottom < size.height()) {
|
||||||
|
sideQuads.fill({ 0, bottom, size.width(), size.height() - bottom });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sideQuads.fill({ 0, 0, size.width(), size.height() });
|
||||||
}
|
}
|
||||||
|
sideQuads.paint(
|
||||||
|
f,
|
||||||
|
&*_fillBuffer,
|
||||||
|
&*_fillProgram,
|
||||||
|
size,
|
||||||
|
st::groupCallMembersBg->c,
|
||||||
|
[&] { _fillProgram->setUniformValue("roundRadius", radius); });
|
||||||
}
|
}
|
||||||
|
|
||||||
LargeVideo::LargeVideo(
|
LargeVideo::LargeVideo(
|
||||||
|
@ -378,6 +527,7 @@ LargeVideo::LargeVideo(
|
||||||
? std::make_unique<PinButton>(widget(), st)
|
? std::make_unique<PinButton>(widget(), st)
|
||||||
: nullptr)
|
: nullptr)
|
||||||
, _smallLayout(!_pinButton) {
|
, _smallLayout(!_pinButton) {
|
||||||
|
widget()->resize(0, 0);
|
||||||
widget()->setVisible(visible);
|
widget()->setVisible(visible);
|
||||||
if (_smallLayout) {
|
if (_smallLayout) {
|
||||||
widget()->setCursor(style::cur_pointer);
|
widget()->setCursor(style::cur_pointer);
|
||||||
|
|
Loading…
Reference in New Issue