diff options
-rw-r--r-- | vcl/inc/opengl/AccumulatedTextures.hxx | 112 | ||||
-rw-r--r-- | vcl/inc/opengl/texture.hxx | 4 | ||||
-rw-r--r-- | vcl/inc/openglgdiimpl.hxx | 5 | ||||
-rw-r--r-- | vcl/opengl/gdiimpl.cxx | 96 | ||||
-rw-r--r-- | vcl/opengl/texture.cxx | 46 | ||||
-rw-r--r-- | vcl/win/gdi/winlayout.cxx | 16 |
6 files changed, 268 insertions, 11 deletions
diff --git a/vcl/inc/opengl/AccumulatedTextures.hxx b/vcl/inc/opengl/AccumulatedTextures.hxx new file mode 100644 index 000000000000..9ce170c2a0af --- /dev/null +++ b/vcl/inc/opengl/AccumulatedTextures.hxx @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INCLUDED_VCL_INC_OPENGL_ACCUMULATEDTEXTURES_H +#define INCLUDED_VCL_INC_OPENGL_ACCUMULATEDTEXTURES_H + +#include <o3tl/make_unique.hxx> +#include "opengl/texture.hxx" +#include <memory> + +struct TextureDrawParameters +{ + std::vector<GLfloat> maVertices; + std::vector<GLfloat> maTextureCoords; + GLint getNumberOfVertices() + { + return maVertices.size() / 2; + } +}; + +struct AccumulatedTexturesEntry +{ + OpenGLTexture maTexture; + std::unordered_map<SalColor, TextureDrawParameters> maColorTextureDrawParametersMap; + + AccumulatedTexturesEntry(const OpenGLTexture& rTexture) + : maTexture(rTexture) + {} + + void insert(const SalColor& aColor, const SalTwoRect& r2Rect) + { + TextureDrawParameters& aDrawParameters = maColorTextureDrawParametersMap[aColor]; + maTexture.FillCoords<GL_TRIANGLES>(aDrawParameters.maTextureCoords, r2Rect, false); + + GLfloat nX1 = r2Rect.mnDestX; + GLfloat nY1 = r2Rect.mnDestY; + GLfloat nX2 = r2Rect.mnDestX + r2Rect.mnDestWidth; + GLfloat nY2 = r2Rect.mnDestY + r2Rect.mnDestHeight; + + auto& rVertices = aDrawParameters.maVertices; + rVertices.push_back(nX1); + rVertices.push_back(nY1); + + rVertices.push_back(nX2); + rVertices.push_back(nY1); + + rVertices.push_back(nX1); + rVertices.push_back(nY2); + + rVertices.push_back(nX1); + rVertices.push_back(nY2); + + rVertices.push_back(nX2); + rVertices.push_back(nY1); + + rVertices.push_back(nX2); + rVertices.push_back(nY2); + } +}; + +class AccumulatedTextures +{ +private: + typedef std::unordered_map<GLuint, std::unique_ptr<AccumulatedTexturesEntry>> AccumulatedTexturesMap; + + AccumulatedTexturesMap maEntries; + +public: + AccumulatedTextures() + {} + + bool empty() + { + return maEntries.empty(); + } + + void clear() + { + maEntries.clear(); + } + + void insert(const OpenGLTexture& rTexture, const SalColor& aColor, const SalTwoRect& r2Rect) + { + GLuint nTextureId = rTexture.Id(); + + auto iterator = maEntries.find(nTextureId); + + if (iterator == maEntries.end()) + { + maEntries[nTextureId] = o3tl::make_unique<AccumulatedTexturesEntry>(rTexture); + } + + std::unique_ptr<AccumulatedTexturesEntry>& rEntry = maEntries[nTextureId]; + rEntry->insert(aColor, r2Rect); + } + + AccumulatedTexturesMap& getAccumulatedTexturesMap() + { + return maEntries; + } +}; + +#endif // INCLUDED_VCL_INC_OPENGL_TEXTURE_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/opengl/texture.hxx b/vcl/inc/opengl/texture.hxx index 113c65b79e34..f48a1a166b03 100644 --- a/vcl/inc/opengl/texture.hxx +++ b/vcl/inc/opengl/texture.hxx @@ -110,6 +110,7 @@ public: GLuint Id() const; int GetWidth() const; int GetHeight() const; + void GetCoord( GLfloat* pCoord, const SalTwoRect& rPosAry, bool bInverted=false ) const; void GetWholeCoord( GLfloat* pCoord ) const; @@ -128,6 +129,9 @@ public: OpenGLTexture& operator=( const OpenGLTexture& rTexture ); bool operator==( const OpenGLTexture& rTexture ) const; bool operator!=( const OpenGLTexture& rTexture ) const; + + template<GLenum type> + void FillCoords(std::vector<GLfloat>& aCoordVector, const SalTwoRect& rPosAry, bool bInverted) const; }; #endif // INCLUDED_VCL_INC_OPENGL_TEXTURE_H diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx index 8dd063902075..0fb2941ace9c 100644 --- a/vcl/inc/openglgdiimpl.hxx +++ b/vcl/inc/openglgdiimpl.hxx @@ -29,6 +29,7 @@ #include "opengl/framebuffer.hxx" #include "opengl/program.hxx" #include "opengl/texture.hxx" +#include "opengl/AccumulatedTextures.hxx" #include <memory> @@ -99,6 +100,8 @@ protected: SalColor mProgramSolidColor; double mProgramSolidTransparency; + std::unique_ptr<AccumulatedTextures> mpAccumulatedTextures; + void ImplInitClipRegion(); void ImplSetClipBit( const vcl::Region& rClip, GLuint nMask ); void ImplDrawLineAA( double nX1, double nY1, double nX2, double nY2, bool edge = false ); @@ -144,6 +147,8 @@ public: void DrawLinearGradient( const Gradient& rGradient, const Rectangle& rRect ); void DrawAxialGradient( const Gradient& rGradient, const Rectangle& rRect ); void DrawRadialGradient( const Gradient& rGradient, const Rectangle& rRect ); + void DeferredTextDraw(const OpenGLTexture& rTexture, const SalColor nMaskColor, const SalTwoRect& rPosAry); + void FlushDeferredDrawing(bool bInDraw = false); public: // get the width of the device diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx index 355fe21fc6ea..bfa48b48402a 100644 --- a/vcl/opengl/gdiimpl.cxx +++ b/vcl/opengl/gdiimpl.cxx @@ -82,6 +82,7 @@ OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl(SalGraphics& rParent, SalGeometryPr , mnDrawCountAtFlush(0) , mProgramSolidColor(SALCOLOR_NONE) , mProgramSolidTransparency(0.0) + , mpAccumulatedTextures(new AccumulatedTextures) { } @@ -205,6 +206,8 @@ void OpenGLSalGraphicsImpl::PreDraw(XOROption eOpt) glViewport( 0, 0, GetWidth(), GetHeight() ); CHECK_GL_ERROR(); + FlushDeferredDrawing(true); + ImplInitClipRegion(); CHECK_GL_ERROR(); @@ -355,6 +358,11 @@ const vcl::Region& OpenGLSalGraphicsImpl::getClipRegion() const bool OpenGLSalGraphicsImpl::setClipRegion( const vcl::Region& rClip ) { VCL_GL_INFO( "::setClipRegion " << rClip ); + if (maClipRegion == rClip) + return true; + + FlushDeferredDrawing(); + maClipRegion = rClip; mbUseStencil = false; @@ -371,6 +379,11 @@ bool OpenGLSalGraphicsImpl::setClipRegion( const vcl::Region& rClip ) void OpenGLSalGraphicsImpl::ResetClipRegion() { VCL_GL_INFO( "::ResetClipRegion" ); + if (maClipRegion.IsEmpty()) + return; + + FlushDeferredDrawing(); + maClipRegion.SetEmpty(); mbUseScissor = false; mbUseStencil = false; @@ -1656,6 +1669,81 @@ void OpenGLSalGraphicsImpl::DrawMask( OpenGLTexture& rMask, SalColor nMaskColor, mpProgram->Clean(); } +void OpenGLSalGraphicsImpl::DeferredTextDraw(const OpenGLTexture& rTexture, SalColor aMaskColor, const SalTwoRect& rPosAry) +{ + mpAccumulatedTextures->insert(rTexture, aMaskColor, rPosAry); +} + +void OpenGLSalGraphicsImpl::FlushDeferredDrawing(bool bIsInDraw) +{ + if (mpAccumulatedTextures->empty()) + return; + + if (!bIsInDraw) + PreDraw(); + + OpenGLZone aZone; + +#if 0 // Draw a background rect under text for debugging - same color shows text from the same texture + static sal_uInt8 r = 0xBE; + static sal_uInt8 g = 0xF0; + static sal_uInt8 b = 0xFF; + static std::unordered_map<GLuint, Color> aColorForTextureMap; + + + for (auto& rPair : mpAccumulatedTextures->getAccumulatedTexturesMap()) + { + OpenGLTexture& rTexture = rPair.second->maTexture; + Color aUseColor; + if (aColorForTextureMap.find(rTexture.Id()) == aColorForTextureMap.end()) + { + Color aColor(r, g, b); + sal_uInt16 h,s,br; + aColor.RGBtoHSB(h, s, br); + aColor = Color::HSBtoRGB((h + 40) % 360, s, br); + r = aColor.GetRed(); + g = aColor.GetGreen(); + b = aColor.GetBlue(); + aColorForTextureMap[rTexture.Id()] = aColor; + } + aUseColor = aColorForTextureMap[rTexture.Id()]; + + if (!UseSolid(MAKE_SALCOLOR(aUseColor.GetRed(), aUseColor.GetGreen(), aUseColor.GetBlue()))) + return; + for (auto rColorTwoRectPair: rPair.second->maColorTextureDrawParametersMap) + { + TextureDrawParameters& rParameters = rColorTwoRectPair.second; + ApplyProgramMatrices(); + mpProgram->SetTextureCoord(rParameters.maTextureCoords.data()); + mpProgram->SetVertices(rParameters.maVertices.data()); + glDrawArrays(GL_TRIANGLES, 0, rParameters.getNumberOfVertices()); + } + } +#endif + + if( !UseProgram( "textureVertexShader", "maskFragmentShader" ) ) + return; + mpProgram->SetBlendMode(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + for (auto& rPair : mpAccumulatedTextures->getAccumulatedTexturesMap()) + { + OpenGLTexture& rTexture = rPair.second->maTexture; + mpProgram->SetTexture("sampler", rTexture); + for (auto& rColorTwoRectPair: rPair.second->maColorTextureDrawParametersMap) + { + mpProgram->SetColor("color", rColorTwoRectPair.first, 0); + TextureDrawParameters& rParameters = rColorTwoRectPair.second; + ApplyProgramMatrices(); + mpProgram->SetTextureCoord(rParameters.maTextureCoords.data()); + mpProgram->SetVertices(rParameters.maVertices.data()); + glDrawArrays(GL_TRIANGLES, 0, rParameters.getNumberOfVertices()); + } + } + mpProgram->Clean(); + mpAccumulatedTextures->clear(); + if (!bIsInDraw) + PostDraw(); +} + void OpenGLSalGraphicsImpl::DrawLinearGradient( const Gradient& rGradient, const Rectangle& rRect ) { OpenGLZone aZone; @@ -2019,6 +2107,8 @@ void OpenGLSalGraphicsImpl::DoCopyBits( const SalTwoRect& rPosAry, OpenGLSalGrap { VCL_GL_INFO( "::copyBits" ); + rImpl.FlushDeferredDrawing(); + if( !rImpl.maOffscreenTex ) { VCL_GL_INFO( "::copyBits - skipping copy of un-initialized framebuffer contents of size " @@ -2120,6 +2210,8 @@ SalBitmap* OpenGLSalGraphicsImpl::getBitmap( long nX, long nY, long nWidth, long SalColor OpenGLSalGraphicsImpl::getPixel( long nX, long nY ) { + FlushDeferredDrawing(); + char pixel[3] = { 0, 0, 0 }; PreDraw( XOROption::IMPLEMENT_XOR ); @@ -2388,6 +2480,8 @@ bool OpenGLSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPoly, void OpenGLSalGraphicsImpl::flush() { + FlushDeferredDrawing(); + if( IsOffscreen() ) return; @@ -2402,6 +2496,8 @@ void OpenGLSalGraphicsImpl::flush() void OpenGLSalGraphicsImpl::doFlush() { + FlushDeferredDrawing(); + if( IsOffscreen() ) return; diff --git a/vcl/opengl/texture.cxx b/vcl/opengl/texture.cxx index 1b2e5a7caec6..fd6d11f04a5a 100644 --- a/vcl/opengl/texture.cxx +++ b/vcl/opengl/texture.cxx @@ -369,6 +369,52 @@ void OpenGLTexture::GetCoord( GLfloat* pCoord, const SalTwoRect& rPosAry, bool b } } +template <> +void OpenGLTexture::FillCoords<GL_TRIANGLES>(std::vector<GLfloat>& aCoord, const SalTwoRect& rPosAry, bool bInverted) const +{ + VCL_GL_INFO("Add coord " << Id() << " [" << maRect.Left() << "," << maRect.Top() << "] " << GetWidth() << "x" << GetHeight() ); + + GLfloat x1 = 0.0f; + GLfloat x2 = 0.0f; + GLfloat y1 = 0.0f; + GLfloat y2 = 0.0f; + + if (mpImpl) + { + x1 = (maRect.Left() + rPosAry.mnSrcX) / (double) mpImpl->mnWidth; + x2 = (maRect.Left() + rPosAry.mnSrcX + rPosAry.mnSrcWidth) / (double) mpImpl->mnWidth; + + if (bInverted) + { + y2 = 1.0f - (maRect.Top() + rPosAry.mnSrcY) / (double) mpImpl->mnHeight; + y1 = 1.0f - (maRect.Top() + rPosAry.mnSrcY + rPosAry.mnSrcHeight) / (double) mpImpl->mnHeight; + } + else + { + y1 = 1.0f - (maRect.Top() + rPosAry.mnSrcY) / (double) mpImpl->mnHeight; + y2 = 1.0f - (maRect.Top() + rPosAry.mnSrcY + rPosAry.mnSrcHeight) / (double) mpImpl->mnHeight; + } + } + + aCoord.push_back(x1); + aCoord.push_back(y1); + + aCoord.push_back(x2); + aCoord.push_back(y1); + + aCoord.push_back(x1); + aCoord.push_back(y2); + + aCoord.push_back(x1); + aCoord.push_back(y2); + + aCoord.push_back(x2); + aCoord.push_back(y1); + + aCoord.push_back(x2); + aCoord.push_back(y2); +} + void OpenGLTexture::GetWholeCoord( GLfloat* pCoord ) const { if( GetWidth() != mpImpl->mnWidth || GetHeight() != mpImpl->mnHeight ) diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx index 1ee9d0246235..293bfa247fb8 100644 --- a/vcl/win/gdi/winlayout.cxx +++ b/vcl/win/gdi/winlayout.cxx @@ -364,7 +364,7 @@ bool WinFontInstance::GlyphIsCached(int nGlyphIndex) const bool WinFontInstance::AddChunkOfGlyphs(bool bRealGlyphIndices, int nGlyphIndex, const WinLayout& rLayout, SalGraphics& rGraphics) { - const int DEFAULT_CHUNK_SIZE = 20; + const int DEFAULT_CHUNK_SIZE = 40; if (nGlyphIndex == DROPPED_OUTGLYPH) return true; @@ -1556,8 +1556,6 @@ bool SimpleWinLayout::DrawCachedGlyphs(SalGraphics& rGraphics) const if (!pImpl) return false; - pImpl->PreDraw(); - HFONT hOrigFont = DisableFontScaling(); Point aPos = GetDrawPosition( Point( mnBaseAdv, 0 ) ); @@ -1589,7 +1587,8 @@ bool SimpleWinLayout::DrawCachedGlyphs(SalGraphics& rGraphics) const nAdvance + aPos.X() - rChunk.getExtraOffset() + rChunk.maLeftOverhangs[n], aPos.Y() - rChunk.mnBaselineOffset - rChunk.getExtraOffset(), rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight()); // ??? - pImpl->DrawMask(*rChunk.mpTexture, salColor, a2Rects); + + pImpl->DeferredTextDraw(*rChunk.mpTexture, salColor, a2Rects); nAdvance += mpGlyphAdvances[i]; } @@ -1597,8 +1596,6 @@ bool SimpleWinLayout::DrawCachedGlyphs(SalGraphics& rGraphics) const if( hOrigFont ) DeleteFont(SelectFont(hDC, hOrigFont)); - pImpl->PostDraw(); - return true; } @@ -3049,8 +3046,6 @@ bool UniscribeLayout::DrawCachedGlyphsUsingTextures(SalGraphics& rGraphics) cons if (!pImpl) return false; - pImpl->PreDraw(); - // FIXME: This code snippet is mostly copied from the one in // UniscribeLayout::DrawTextImpl. Should be factored out. int nBaseClusterOffset = 0; @@ -3109,7 +3104,7 @@ bool UniscribeLayout::DrawCachedGlyphsUsingTextures(SalGraphics& rGraphics) cons rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight(), aPos.X() + rChunk.maLeftOverhangs[n], nAdvance + aPos.Y(), rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight()); // ??? - pImpl->DrawMask(*rChunk.mpTexture, salColor, a2Rects); + pImpl->DeferredTextDraw(*rChunk.mpTexture, salColor, a2Rects); } else { @@ -3118,12 +3113,11 @@ bool UniscribeLayout::DrawCachedGlyphsUsingTextures(SalGraphics& rGraphics) cons nAdvance + aPos.X() + mpGlyphOffsets[i].du - rChunk.getExtraOffset() + rChunk.maLeftOverhangs[n], aPos.Y() + mpGlyphOffsets[i].dv - rChunk.mnBaselineOffset - rChunk.getExtraOffset(), rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight()); // ??? - pImpl->DrawMask(*rChunk.mpTexture, salColor, a2Rects); + pImpl->DeferredTextDraw(*rChunk.mpTexture, salColor, a2Rects); } nAdvance += pGlyphWidths[i]; } } - pImpl->PostDraw(); return true; } |