mirror of
https://github.com/hyprwm/aquamarine.git
synced 2025-12-20 04:40:12 +01:00
drm/renderer: optimize blitting and use gles3 shaders (#179)
* renderer: use gles3 shaders move over to gles3 shaders. * renderer: cleanup some code cleanup some code, use nullptr instead of void zero cast, use empty instead of .size() and cache last viewport size. dont wait on the waitFd if its already readable. * renderer: make sgltex a class make sgltex a class, cache the textureparameters to not set it twice or more, and add a bind/unbind function.
This commit is contained in:
parent
dd92142139
commit
dc45d00900
2 changed files with 106 additions and 36 deletions
|
|
@ -9,10 +9,13 @@
|
||||||
#include "Shared.hpp"
|
#include "Shared.hpp"
|
||||||
#include "FormatUtils.hpp"
|
#include "FormatUtils.hpp"
|
||||||
#include <aquamarine/allocator/GBM.hpp>
|
#include <aquamarine/allocator/GBM.hpp>
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
|
||||||
using namespace Aquamarine;
|
using namespace Aquamarine;
|
||||||
using namespace Hyprutils::Memory;
|
using namespace Hyprutils::Memory;
|
||||||
using namespace Hyprutils::Math;
|
using namespace Hyprutils::Math;
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
#define SP CSharedPointer
|
#define SP CSharedPointer
|
||||||
#define WP CWeakPointer
|
#define WP CWeakPointer
|
||||||
|
|
||||||
|
|
@ -80,10 +83,15 @@ static GLuint createProgram(const std::string& vert, const std::string& frag) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::string VERT_SRC = R"#(
|
inline const std::string VERT_SRC = R"#(
|
||||||
|
#version 300 es
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
uniform mat3 proj;
|
uniform mat3 proj;
|
||||||
attribute vec2 pos;
|
|
||||||
attribute vec2 texcoord;
|
in vec2 pos;
|
||||||
varying vec2 v_texcoord;
|
in vec2 texcoord;
|
||||||
|
|
||||||
|
out vec2 v_texcoord;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);
|
gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);
|
||||||
|
|
@ -91,22 +99,30 @@ void main() {
|
||||||
})#";
|
})#";
|
||||||
|
|
||||||
inline const std::string FRAG_SRC = R"#(
|
inline const std::string FRAG_SRC = R"#(
|
||||||
|
#version 300 es
|
||||||
precision highp float;
|
precision highp float;
|
||||||
varying vec2 v_texcoord; // is in 0-1
|
|
||||||
|
in vec2 v_texcoord;
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
uniform sampler2D tex;
|
uniform sampler2D tex;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_FragColor = texture2D(tex, v_texcoord);
|
fragColor = texture(tex, v_texcoord);
|
||||||
})#";
|
})#";
|
||||||
|
|
||||||
inline const std::string FRAG_SRC_EXT = R"#(
|
inline const std::string FRAG_SRC_EXT = R"#(
|
||||||
#extension GL_OES_EGL_image_external : require
|
#version 300 es
|
||||||
|
#extension GL_OES_EGL_image_external_essl3 : require
|
||||||
precision highp float;
|
precision highp float;
|
||||||
varying vec2 v_texcoord; // is in 0-1
|
|
||||||
|
in vec2 v_texcoord;
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
uniform samplerExternalOES texture0;
|
uniform samplerExternalOES texture0;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_FragColor = texture2D(texture0, v_texcoord);
|
fragColor = texture(texture0, v_texcoord);
|
||||||
})#";
|
})#";
|
||||||
|
|
||||||
// ------------------- egl stuff
|
// ------------------- egl stuff
|
||||||
|
|
@ -202,7 +218,7 @@ void CDRMRenderer::SShader::createVao() {
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, shaderVboPos);
|
glBindBuffer(GL_ARRAY_BUFFER, shaderVboPos);
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(fullVerts), fullVerts, GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, sizeof(fullVerts), fullVerts, GL_STATIC_DRAW);
|
||||||
glEnableVertexAttribArray(posAttrib);
|
glEnableVertexAttribArray(posAttrib);
|
||||||
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
|
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (texAttrib != -1) {
|
if (texAttrib != -1) {
|
||||||
|
|
@ -210,7 +226,7 @@ void CDRMRenderer::SShader::createVao() {
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, shaderVboUv);
|
glBindBuffer(GL_ARRAY_BUFFER, shaderVboUv);
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(fullVerts), fullVerts, GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, sizeof(fullVerts), fullVerts, GL_STATIC_DRAW);
|
||||||
glEnableVertexAttribArray(texAttrib);
|
glEnableVertexAttribArray(texAttrib);
|
||||||
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
|
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
@ -291,7 +307,7 @@ std::optional<std::vector<std::pair<uint64_t, bool>>> CDRMRenderer::getModsForFo
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the driver doesn't mark linear as external, add it. It's allowed unless the driver says otherwise. (e.g. nvidia)
|
// if the driver doesn't mark linear as external, add it. It's allowed unless the driver says otherwise. (e.g. nvidia)
|
||||||
if (!linearIsExternal && std::ranges::find(mods, DRM_FORMAT_MOD_LINEAR) == mods.end() && mods.size() == 0)
|
if (!linearIsExternal && std::ranges::find(mods, DRM_FORMAT_MOD_LINEAR) == mods.end() && mods.empty())
|
||||||
result.emplace_back(DRM_FORMAT_MOD_LINEAR, true);
|
result.emplace_back(DRM_FORMAT_MOD_LINEAR, true);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -312,7 +328,7 @@ bool CDRMRenderer::initDRMFormats() {
|
||||||
formats.resize(len);
|
formats.resize(len);
|
||||||
proc.eglQueryDmaBufFormatsEXT(egl.display, len, formats.data(), &len);
|
proc.eglQueryDmaBufFormatsEXT(egl.display, len, formats.data(), &len);
|
||||||
|
|
||||||
if (formats.size() == 0) {
|
if (formats.empty()) {
|
||||||
backend->log(AQ_LOG_ERROR, "EGL: Failed to get formats");
|
backend->log(AQ_LOG_ERROR, "EGL: Failed to get formats");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -333,7 +349,7 @@ bool CDRMRenderer::initDRMFormats() {
|
||||||
mods = *ret;
|
mods = *ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
hasModifiers = hasModifiers || mods.size() > 0;
|
hasModifiers = hasModifiers || !mods.empty();
|
||||||
|
|
||||||
// EGL can always do implicit modifiers.
|
// EGL can always do implicit modifiers.
|
||||||
mods.emplace_back(DRM_FORMAT_MOD_INVALID, true);
|
mods.emplace_back(DRM_FORMAT_MOD_INVALID, true);
|
||||||
|
|
@ -707,8 +723,8 @@ EGLImageKHR CDRMRenderer::createEGLImage(const SDMABUFAttrs& attrs) {
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
SGLTex CDRMRenderer::glTex(Hyprutils::Memory::CSharedPointer<IBuffer> buffa) {
|
CGLTex CDRMRenderer::glTex(Hyprutils::Memory::CSharedPointer<IBuffer> buffa) {
|
||||||
SGLTex tex;
|
CGLTex tex;
|
||||||
|
|
||||||
const auto& dma = buffa->dmabuf();
|
const auto& dma = buffa->dmabuf();
|
||||||
|
|
||||||
|
|
@ -732,11 +748,11 @@ SGLTex CDRMRenderer::glTex(Hyprutils::Memory::CSharedPointer<IBuffer> buffa) {
|
||||||
|
|
||||||
GLCALL(glGenTextures(1, &tex.texid));
|
GLCALL(glGenTextures(1, &tex.texid));
|
||||||
|
|
||||||
GLCALL(glBindTexture(tex.target, tex.texid));
|
GLCALL(tex.bind());
|
||||||
GLCALL(glTexParameteri(tex.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
GLCALL(tex.setTexParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||||
GLCALL(glTexParameteri(tex.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
GLCALL(tex.setTexParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||||
GLCALL(proc.glEGLImageTargetTexture2DOES(tex.target, tex.image));
|
GLCALL(proc.glEGLImageTargetTexture2DOES(tex.target, tex.image));
|
||||||
GLCALL(glBindTexture(tex.target, 0));
|
GLCALL(tex.unbind());
|
||||||
|
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
@ -747,7 +763,7 @@ void CDRMRenderer::readBuffer(Hyprutils::Memory::CSharedPointer<IBuf
|
||||||
CEglContextGuard eglContext(*this);
|
CEglContextGuard eglContext(*this);
|
||||||
auto att = buf->attachments.get<CDRMRendererBufferAttachment>();
|
auto att = buf->attachments.get<CDRMRendererBufferAttachment>();
|
||||||
if (!att) {
|
if (!att) {
|
||||||
att = makeShared<CDRMRendererBufferAttachment>(self, buf, nullptr, 0, 0, SGLTex{}, std::vector<uint8_t>());
|
att = makeShared<CDRMRendererBufferAttachment>(self, buf, nullptr, 0, 0, CGLTex{}, std::vector<uint8_t>());
|
||||||
buf->attachments.add(att);
|
buf->attachments.add(att);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -906,7 +922,7 @@ CDRMRenderer::SBlitResult CDRMRenderer::blit(SP<IBuffer> from, SP<IBuffer> to, S
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (waitFD >= 0) {
|
if (waitFD >= 0 && !CFileDescriptor::isReadable(waitFD)) {
|
||||||
// wait on a provided explicit fence
|
// wait on a provided explicit fence
|
||||||
waitOnSync(waitFD);
|
waitOnSync(waitFD);
|
||||||
}
|
}
|
||||||
|
|
@ -916,7 +932,7 @@ CDRMRenderer::SBlitResult CDRMRenderer::blit(SP<IBuffer> from, SP<IBuffer> to, S
|
||||||
// both from and to have the same AQ_ATTACHMENT_DRM_RENDERER_DATA.
|
// both from and to have the same AQ_ATTACHMENT_DRM_RENDERER_DATA.
|
||||||
// Those buffers always come from different swapchains, so it's OK.
|
// Those buffers always come from different swapchains, so it's OK.
|
||||||
|
|
||||||
WP<SGLTex> fromTex;
|
WP<CGLTex> fromTex;
|
||||||
const auto& fromDma = from->dmabuf();
|
const auto& fromDma = from->dmabuf();
|
||||||
std::span<uint8_t> intermediateBuf;
|
std::span<uint8_t> intermediateBuf;
|
||||||
{
|
{
|
||||||
|
|
@ -999,7 +1015,7 @@ CDRMRenderer::SBlitResult CDRMRenderer::blit(SP<IBuffer> from, SP<IBuffer> to, S
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
to->attachments.add(makeShared<CDRMRendererBufferAttachment>(self, to, rboImage, fboID, rboID, SGLTex{}, std::vector<uint8_t>()));
|
to->attachments.add(makeShared<CDRMRendererBufferAttachment>(self, to, rboImage, fboID, rboID, CGLTex{}, std::vector<uint8_t>()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1037,13 +1053,16 @@ CDRMRenderer::SBlitResult CDRMRenderer::blit(SP<IBuffer> from, SP<IBuffer> to, S
|
||||||
float glMtx[9];
|
float glMtx[9];
|
||||||
matrixMultiply(glMtx, monitorProj, mtx);
|
matrixMultiply(glMtx, monitorProj, mtx);
|
||||||
|
|
||||||
GLCALL(glViewport(0, 0, toDma.size.x, toDma.size.y));
|
static Vector2D lastViewportSize = {-1, -1};
|
||||||
|
if (lastViewportSize != toDma.size) {
|
||||||
|
GLCALL(glViewport(0, 0, toDma.size.x, toDma.size.y));
|
||||||
|
lastViewportSize = toDma.size;
|
||||||
|
}
|
||||||
|
|
||||||
GLCALL(glActiveTexture(GL_TEXTURE0));
|
GLCALL(glActiveTexture(GL_TEXTURE0));
|
||||||
GLCALL(glBindTexture(fromTex->target, fromTex->texid));
|
GLCALL(fromTex->bind());
|
||||||
|
GLCALL(fromTex->setTexParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
||||||
GLCALL(glTexParameteri(fromTex->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
GLCALL(fromTex->setTexParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST));
|
||||||
GLCALL(glTexParameteri(fromTex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
|
|
||||||
|
|
||||||
if (!intermediateBuf.empty())
|
if (!intermediateBuf.empty())
|
||||||
GLCALL(glTexImage2D(fromTex->target, 0, PIXEL_BUFFER_FORMAT, fromDma.size.x, fromDma.size.y, 0, PIXEL_BUFFER_FORMAT, GL_UNSIGNED_BYTE, intermediateBuf.data()));
|
GLCALL(glTexImage2D(fromTex->target, 0, PIXEL_BUFFER_FORMAT, fromDma.size.x, fromDma.size.y, 0, PIXEL_BUFFER_FORMAT, GL_UNSIGNED_BYTE, intermediateBuf.data()));
|
||||||
|
|
@ -1061,7 +1080,7 @@ CDRMRenderer::SBlitResult CDRMRenderer::blit(SP<IBuffer> from, SP<IBuffer> to, S
|
||||||
GLCALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
GLCALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||||
|
|
||||||
GLCALL(glBindVertexArray(0));
|
GLCALL(glBindVertexArray(0));
|
||||||
GLCALL(glBindTexture(fromTex->target, 0));
|
GLCALL(fromTex->unbind());
|
||||||
|
|
||||||
// get an explicit sync fd for the secondary gpu.
|
// get an explicit sync fd for the secondary gpu.
|
||||||
// when we pass buffers between gpus we should always use explicit sync,
|
// when we pass buffers between gpus we should always use explicit sync,
|
||||||
|
|
@ -1112,9 +1131,43 @@ bool CDRMRenderer::verifyDestinationDMABUF(const SDMABUFAttrs& attrs) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr std::optional<size_t> CGLTex::getCacheStateIndex(GLenum pname) {
|
||||||
|
switch (pname) {
|
||||||
|
case GL_TEXTURE_WRAP_S: return TEXTURE_PAR_WRAP_S;
|
||||||
|
case GL_TEXTURE_WRAP_T: return TEXTURE_PAR_WRAP_T;
|
||||||
|
case GL_TEXTURE_MAG_FILTER: return TEXTURE_PAR_MAG_FILTER;
|
||||||
|
case GL_TEXTURE_MIN_FILTER: return TEXTURE_PAR_MIN_FILTER;
|
||||||
|
default: return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGLTex::bind() {
|
||||||
|
glBindTexture(target, texid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGLTex::unbind() {
|
||||||
|
glBindTexture(target, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGLTex::setTexParameter(GLenum pname, GLint param) {
|
||||||
|
const auto cacheIndex = getCacheStateIndex(pname);
|
||||||
|
|
||||||
|
if (!cacheIndex) {
|
||||||
|
glTexParameteri(target, pname, param);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto idx = cacheIndex.value();
|
||||||
|
|
||||||
|
if (m_cachedStates[idx] == param)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_cachedStates[idx] = param;
|
||||||
|
glTexParameteri(target, pname, param);
|
||||||
|
}
|
||||||
|
|
||||||
CDRMRendererBufferAttachment::CDRMRendererBufferAttachment(Hyprutils::Memory::CWeakPointer<CDRMRenderer> renderer_, Hyprutils::Memory::CSharedPointer<IBuffer> buffer,
|
CDRMRendererBufferAttachment::CDRMRendererBufferAttachment(Hyprutils::Memory::CWeakPointer<CDRMRenderer> renderer_, Hyprutils::Memory::CSharedPointer<IBuffer> buffer,
|
||||||
EGLImageKHR image, GLuint fbo_, GLuint rbo_, SGLTex&& tex_, std::vector<uint8_t> intermediateBuf_) :
|
EGLImageKHR image, GLuint fbo_, GLuint rbo_, CGLTex&& tex_, std::vector<uint8_t> intermediateBuf_) :
|
||||||
eglImage(image),
|
eglImage(image), fbo(fbo_), rbo(rbo_), tex(makeUnique<CGLTex>(std::move(tex_))), intermediateBuf(intermediateBuf_), renderer(renderer_) {
|
||||||
fbo(fbo_), rbo(rbo_), tex(makeUnique<SGLTex>(std::move(tex_))), intermediateBuf(intermediateBuf_), renderer(renderer_) {
|
|
||||||
bufferDestroy = buffer->events.destroy.listen([this] { renderer->onBufferAttachmentDrop(this); });
|
bufferDestroy = buffer->events.destroy.listen([this] { renderer->onBufferAttachmentDrop(this); });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,23 +18,40 @@ namespace Aquamarine {
|
||||||
|
|
||||||
class CGBMAllocator;
|
class CGBMAllocator;
|
||||||
|
|
||||||
struct SGLTex {
|
class CGLTex {
|
||||||
|
public:
|
||||||
|
CGLTex() = default;
|
||||||
|
void bind();
|
||||||
|
void unbind();
|
||||||
|
void setTexParameter(GLenum pname, GLint param);
|
||||||
EGLImage image = nullptr;
|
EGLImage image = nullptr;
|
||||||
GLuint texid = 0;
|
GLuint texid = 0;
|
||||||
GLuint target = GL_TEXTURE_2D;
|
GLuint target = GL_TEXTURE_2D;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum eTextureParam : uint8_t {
|
||||||
|
TEXTURE_PAR_WRAP_S = 0,
|
||||||
|
TEXTURE_PAR_WRAP_T,
|
||||||
|
TEXTURE_PAR_MAG_FILTER,
|
||||||
|
TEXTURE_PAR_MIN_FILTER,
|
||||||
|
TEXTURE_PAR_LAST,
|
||||||
|
};
|
||||||
|
|
||||||
|
inline constexpr std::optional<size_t> getCacheStateIndex(GLenum pname);
|
||||||
|
std::array<std::optional<GLint>, TEXTURE_PAR_LAST> m_cachedStates;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CDRMRendererBufferAttachment : public IAttachment {
|
class CDRMRendererBufferAttachment : public IAttachment {
|
||||||
public:
|
public:
|
||||||
CDRMRendererBufferAttachment(Hyprutils::Memory::CWeakPointer<CDRMRenderer> renderer_, Hyprutils::Memory::CSharedPointer<IBuffer> buffer, EGLImageKHR image, GLuint fbo_,
|
CDRMRendererBufferAttachment(Hyprutils::Memory::CWeakPointer<CDRMRenderer> renderer_, Hyprutils::Memory::CSharedPointer<IBuffer> buffer, EGLImageKHR image, GLuint fbo_,
|
||||||
GLuint rbo_, SGLTex&& tex, std::vector<uint8_t> intermediateBuf_);
|
GLuint rbo_, CGLTex&& tex, std::vector<uint8_t> intermediateBuf_);
|
||||||
virtual ~CDRMRendererBufferAttachment() {
|
virtual ~CDRMRendererBufferAttachment() {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLImageKHR eglImage = nullptr;
|
EGLImageKHR eglImage = nullptr;
|
||||||
GLuint fbo = 0, rbo = 0;
|
GLuint fbo = 0, rbo = 0;
|
||||||
Hyprutils::Memory::CUniquePointer<SGLTex> tex;
|
Hyprutils::Memory::CUniquePointer<CGLTex> tex;
|
||||||
Hyprutils::Signal::CHyprSignalListener bufferDestroy;
|
Hyprutils::Signal::CHyprSignalListener bufferDestroy;
|
||||||
std::vector<uint8_t> intermediateBuf;
|
std::vector<uint8_t> intermediateBuf;
|
||||||
|
|
||||||
|
|
@ -132,7 +149,7 @@ namespace Aquamarine {
|
||||||
int lastBlitSyncFD = -1;
|
int lastBlitSyncFD = -1;
|
||||||
} egl;
|
} egl;
|
||||||
|
|
||||||
SGLTex glTex(Hyprutils::Memory::CSharedPointer<IBuffer> buf);
|
CGLTex glTex(Hyprutils::Memory::CSharedPointer<IBuffer> buf);
|
||||||
void readBuffer(Hyprutils::Memory::CSharedPointer<IBuffer> buf, std::span<uint8_t> out);
|
void readBuffer(Hyprutils::Memory::CSharedPointer<IBuffer> buf, std::span<uint8_t> out);
|
||||||
|
|
||||||
Hyprutils::Memory::CWeakPointer<CDRMRenderer> self;
|
Hyprutils::Memory::CWeakPointer<CDRMRenderer> self;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue