summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vcl/inc/opengl/AccumulatedTextures.hxx112
-rw-r--r--vcl/inc/opengl/texture.hxx4
-rw-r--r--vcl/inc/openglgdiimpl.hxx5
-rw-r--r--vcl/opengl/gdiimpl.cxx96
-rw-r--r--vcl/opengl/texture.cxx46
-rw-r--r--vcl/win/gdi/winlayout.cxx16
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;
}