diff --git a/src/backend/drm/Renderer.cpp b/src/backend/drm/Renderer.cpp index 9040dc7..093838d 100644 --- a/src/backend/drm/Renderer.cpp +++ b/src/backend/drm/Renderer.cpp @@ -9,10 +9,13 @@ #include "Shared.hpp" #include "FormatUtils.hpp" #include +#include using namespace Aquamarine; using namespace Hyprutils::Memory; using namespace Hyprutils::Math; +using namespace Hyprutils::OS; + #define SP CSharedPointer #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"#( +#version 300 es +precision highp float; + uniform mat3 proj; -attribute vec2 pos; -attribute vec2 texcoord; -varying vec2 v_texcoord; + +in vec2 pos; +in vec2 texcoord; + +out vec2 v_texcoord; void main() { gl_Position = vec4(proj * vec3(pos, 1.0), 1.0); @@ -91,22 +99,30 @@ void main() { })#"; inline const std::string FRAG_SRC = R"#( +#version 300 es precision highp float; -varying vec2 v_texcoord; // is in 0-1 + +in vec2 v_texcoord; +out vec4 fragColor; + uniform sampler2D tex; void main() { - gl_FragColor = texture2D(tex, v_texcoord); + fragColor = texture(tex, v_texcoord); })#"; 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; -varying vec2 v_texcoord; // is in 0-1 + +in vec2 v_texcoord; +out vec4 fragColor; + uniform samplerExternalOES texture0; void main() { - gl_FragColor = texture2D(texture0, v_texcoord); + fragColor = texture(texture0, v_texcoord); })#"; // ------------------- egl stuff @@ -202,7 +218,7 @@ void CDRMRenderer::SShader::createVao() { glBindBuffer(GL_ARRAY_BUFFER, shaderVboPos); glBufferData(GL_ARRAY_BUFFER, sizeof(fullVerts), fullVerts, GL_STATIC_DRAW); glEnableVertexAttribArray(posAttrib); - glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); + glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, nullptr); } if (texAttrib != -1) { @@ -210,7 +226,7 @@ void CDRMRenderer::SShader::createVao() { glBindBuffer(GL_ARRAY_BUFFER, shaderVboUv); glBufferData(GL_ARRAY_BUFFER, sizeof(fullVerts), fullVerts, GL_STATIC_DRAW); glEnableVertexAttribArray(texAttrib); - glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); + glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 0, nullptr); } glBindVertexArray(0); @@ -291,7 +307,7 @@ std::optional>> 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 (!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); return result; @@ -312,7 +328,7 @@ bool CDRMRenderer::initDRMFormats() { formats.resize(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"); return false; } @@ -333,7 +349,7 @@ bool CDRMRenderer::initDRMFormats() { mods = *ret; } - hasModifiers = hasModifiers || mods.size() > 0; + hasModifiers = hasModifiers || !mods.empty(); // EGL can always do implicit modifiers. mods.emplace_back(DRM_FORMAT_MOD_INVALID, true); @@ -707,8 +723,8 @@ EGLImageKHR CDRMRenderer::createEGLImage(const SDMABUFAttrs& attrs) { return image; } -SGLTex CDRMRenderer::glTex(Hyprutils::Memory::CSharedPointer buffa) { - SGLTex tex; +CGLTex CDRMRenderer::glTex(Hyprutils::Memory::CSharedPointer buffa) { + CGLTex tex; const auto& dma = buffa->dmabuf(); @@ -732,11 +748,11 @@ SGLTex CDRMRenderer::glTex(Hyprutils::Memory::CSharedPointer buffa) { GLCALL(glGenTextures(1, &tex.texid)); - GLCALL(glBindTexture(tex.target, tex.texid)); - GLCALL(glTexParameteri(tex.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - GLCALL(glTexParameteri(tex.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + GLCALL(tex.bind()); + GLCALL(tex.setTexParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + GLCALL(tex.setTexParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); GLCALL(proc.glEGLImageTargetTexture2DOES(tex.target, tex.image)); - GLCALL(glBindTexture(tex.target, 0)); + GLCALL(tex.unbind()); return tex; } @@ -747,7 +763,7 @@ void CDRMRenderer::readBuffer(Hyprutils::Memory::CSharedPointerattachments.get(); if (!att) { - att = makeShared(self, buf, nullptr, 0, 0, SGLTex{}, std::vector()); + att = makeShared(self, buf, nullptr, 0, 0, CGLTex{}, std::vector()); buf->attachments.add(att); } @@ -906,7 +922,7 @@ CDRMRenderer::SBlitResult CDRMRenderer::blit(SP from, SP to, S return {}; } - if (waitFD >= 0) { + if (waitFD >= 0 && !CFileDescriptor::isReadable(waitFD)) { // wait on a provided explicit fence waitOnSync(waitFD); } @@ -916,7 +932,7 @@ CDRMRenderer::SBlitResult CDRMRenderer::blit(SP from, SP to, S // both from and to have the same AQ_ATTACHMENT_DRM_RENDERER_DATA. // Those buffers always come from different swapchains, so it's OK. - WP fromTex; + WP fromTex; const auto& fromDma = from->dmabuf(); std::span intermediateBuf; { @@ -999,7 +1015,7 @@ CDRMRenderer::SBlitResult CDRMRenderer::blit(SP from, SP to, S return {}; } - to->attachments.add(makeShared(self, to, rboImage, fboID, rboID, SGLTex{}, std::vector())); + to->attachments.add(makeShared(self, to, rboImage, fboID, rboID, CGLTex{}, std::vector())); } } @@ -1037,13 +1053,16 @@ CDRMRenderer::SBlitResult CDRMRenderer::blit(SP from, SP to, S float glMtx[9]; 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(glBindTexture(fromTex->target, fromTex->texid)); - - GLCALL(glTexParameteri(fromTex->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); - GLCALL(glTexParameteri(fromTex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); + GLCALL(fromTex->bind()); + GLCALL(fromTex->setTexParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST)); + GLCALL(fromTex->setTexParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST)); 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())); @@ -1061,7 +1080,7 @@ CDRMRenderer::SBlitResult CDRMRenderer::blit(SP from, SP to, S GLCALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); GLCALL(glBindVertexArray(0)); - GLCALL(glBindTexture(fromTex->target, 0)); + GLCALL(fromTex->unbind()); // get an explicit sync fd for the secondary gpu. // when we pass buffers between gpus we should always use explicit sync, @@ -1112,9 +1131,43 @@ bool CDRMRenderer::verifyDestinationDMABUF(const SDMABUFAttrs& attrs) { return false; } +constexpr std::optional 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 renderer_, Hyprutils::Memory::CSharedPointer buffer, - EGLImageKHR image, GLuint fbo_, GLuint rbo_, SGLTex&& tex_, std::vector intermediateBuf_) : - eglImage(image), - fbo(fbo_), rbo(rbo_), tex(makeUnique(std::move(tex_))), intermediateBuf(intermediateBuf_), renderer(renderer_) { + EGLImageKHR image, GLuint fbo_, GLuint rbo_, CGLTex&& tex_, std::vector intermediateBuf_) : + eglImage(image), fbo(fbo_), rbo(rbo_), tex(makeUnique(std::move(tex_))), intermediateBuf(intermediateBuf_), renderer(renderer_) { bufferDestroy = buffer->events.destroy.listen([this] { renderer->onBufferAttachmentDrop(this); }); } diff --git a/src/backend/drm/Renderer.hpp b/src/backend/drm/Renderer.hpp index d478949..99a15f7 100644 --- a/src/backend/drm/Renderer.hpp +++ b/src/backend/drm/Renderer.hpp @@ -18,23 +18,40 @@ namespace Aquamarine { class CGBMAllocator; - struct SGLTex { + class CGLTex { + public: + CGLTex() = default; + void bind(); + void unbind(); + void setTexParameter(GLenum pname, GLint param); EGLImage image = nullptr; GLuint texid = 0; 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 getCacheStateIndex(GLenum pname); + std::array, TEXTURE_PAR_LAST> m_cachedStates; }; class CDRMRendererBufferAttachment : public IAttachment { public: CDRMRendererBufferAttachment(Hyprutils::Memory::CWeakPointer renderer_, Hyprutils::Memory::CSharedPointer buffer, EGLImageKHR image, GLuint fbo_, - GLuint rbo_, SGLTex&& tex, std::vector intermediateBuf_); + GLuint rbo_, CGLTex&& tex, std::vector intermediateBuf_); virtual ~CDRMRendererBufferAttachment() { ; } EGLImageKHR eglImage = nullptr; GLuint fbo = 0, rbo = 0; - Hyprutils::Memory::CUniquePointer tex; + Hyprutils::Memory::CUniquePointer tex; Hyprutils::Signal::CHyprSignalListener bufferDestroy; std::vector intermediateBuf; @@ -132,7 +149,7 @@ namespace Aquamarine { int lastBlitSyncFD = -1; } egl; - SGLTex glTex(Hyprutils::Memory::CSharedPointer buf); + CGLTex glTex(Hyprutils::Memory::CSharedPointer buf); void readBuffer(Hyprutils::Memory::CSharedPointer buf, std::span out); Hyprutils::Memory::CWeakPointer self;