2014-10-23 23:23:26 +02:00
|
|
|
/* -*- 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/.
|
|
|
|
*
|
|
|
|
* This file incorporates work covered by the following license notice:
|
|
|
|
*
|
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
|
|
* with this work for additional information regarding copyright
|
|
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy of
|
|
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
|
|
*/
|
|
|
|
|
2017-10-23 22:28:18 +02:00
|
|
|
#include <openglgdiimpl.hxx>
|
2019-06-10 12:30:21 +02:00
|
|
|
#include <opengl/framebuffer.hxx>
|
2014-10-23 23:23:26 +02:00
|
|
|
|
2014-10-29 17:25:55 +01:00
|
|
|
#include <vcl/gradient.hxx>
|
2017-01-04 12:06:42 +01:00
|
|
|
#include <vcl/idle.hxx>
|
2014-11-03 11:08:24 -05:00
|
|
|
#include <salframe.hxx>
|
2017-10-23 22:28:18 +02:00
|
|
|
#include <salvd.hxx>
|
2014-11-08 23:04:46 -05:00
|
|
|
#include <basegfx/matrix/b2dhommatrixtools.hxx>
|
|
|
|
#include <basegfx/polygon/b2dlinegeometry.hxx>
|
2014-10-29 13:05:02 -04:00
|
|
|
#include <basegfx/polygon/b2dpolygontools.hxx>
|
|
|
|
#include <basegfx/polygon/b2dpolygontriangulator.hxx>
|
2014-11-08 23:03:37 -05:00
|
|
|
#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
|
2014-11-08 23:04:46 -05:00
|
|
|
#include <basegfx/polygon/b2dtrapezoid.hxx>
|
2018-07-28 15:57:23 +02:00
|
|
|
#include <sal/log.hxx>
|
2014-10-29 13:05:02 -04:00
|
|
|
|
2014-10-29 22:30:55 +01:00
|
|
|
#include <vcl/opengl/OpenGLHelper.hxx>
|
2017-10-23 22:28:18 +02:00
|
|
|
#include <salgdi.hxx>
|
|
|
|
#include <svdata.hxx>
|
|
|
|
#include <opengl/zone.hxx>
|
|
|
|
#include <opengl/salbmp.hxx>
|
|
|
|
#include <opengl/RenderState.hxx>
|
|
|
|
#include <opengl/VertexUtils.hxx>
|
|
|
|
#include <opengl/BufferObject.hxx>
|
2014-10-29 22:30:55 +01:00
|
|
|
|
2018-05-16 10:16:01 +02:00
|
|
|
#include <cmath>
|
2014-11-06 03:37:47 +01:00
|
|
|
#include <vector>
|
|
|
|
|
2016-02-24 00:44:58 +01:00
|
|
|
#include <glm/gtc/type_ptr.hpp>
|
|
|
|
#include <glm/gtx/norm.hpp>
|
|
|
|
|
2015-11-13 12:00:59 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
class OpenGLFlushIdle : public Idle
|
|
|
|
{
|
|
|
|
OpenGLSalGraphicsImpl *m_pImpl;
|
|
|
|
public:
|
2015-12-29 19:27:43 +00:00
|
|
|
explicit OpenGLFlushIdle( OpenGLSalGraphicsImpl *pImpl )
|
2015-11-13 12:00:59 +00:00
|
|
|
: Idle( "gl idle swap" )
|
|
|
|
, m_pImpl( pImpl )
|
|
|
|
{
|
2016-01-12 21:02:01 +00:00
|
|
|
// We don't want to be swapping before we've painted.
|
2017-01-04 12:06:42 +01:00
|
|
|
SetPriority( TaskPriority::POST_PAINT );
|
2015-11-13 12:00:59 +00:00
|
|
|
}
|
2016-11-23 21:48:33 +01:00
|
|
|
|
2015-11-13 12:00:59 +00:00
|
|
|
virtual void Invoke() override
|
|
|
|
{
|
|
|
|
m_pImpl->doFlush();
|
|
|
|
Stop();
|
2019-03-13 01:23:36 +01:00
|
|
|
SetPriority(TaskPriority::HIGHEST);
|
2015-11-13 12:00:59 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-12-15 20:00:45 +01:00
|
|
|
OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl(SalGraphics& rParent, SalGeometryProvider *pProvider)
|
2018-09-12 15:12:39 +02:00
|
|
|
: mrParent(rParent)
|
2014-12-15 20:00:45 +01:00
|
|
|
, mpProvider(pProvider)
|
2015-11-10 10:28:29 +01:00
|
|
|
, mpProgram(nullptr)
|
2015-11-13 12:00:59 +00:00
|
|
|
, mpFlush(new OpenGLFlushIdle(this))
|
2014-11-12 15:37:11 -05:00
|
|
|
, mbUseScissor(false)
|
|
|
|
, mbUseStencil(false)
|
2016-01-08 22:33:11 +00:00
|
|
|
, mbXORMode(false)
|
2017-01-26 12:17:58 +00:00
|
|
|
, mbAcquiringOpenGLContext(false)
|
2014-11-11 10:24:37 +01:00
|
|
|
, mnLineColor(SALCOLOR_NONE)
|
|
|
|
, mnFillColor(SALCOLOR_NONE)
|
2014-12-18 11:47:58 +01:00
|
|
|
#ifdef DBG_UTIL
|
2015-01-12 13:20:54 +01:00
|
|
|
, mProgramIsSolidColor(false)
|
2014-12-18 11:47:58 +01:00
|
|
|
#endif
|
2015-11-13 12:00:59 +00:00
|
|
|
, mnDrawCount(0)
|
|
|
|
, mnDrawCountAtFlush(0)
|
2015-01-15 20:17:45 +00:00
|
|
|
, mProgramSolidColor(SALCOLOR_NONE)
|
|
|
|
, mProgramSolidTransparency(0.0)
|
2016-05-29 12:37:41 +09:00
|
|
|
, mpRenderList(new RenderList)
|
2014-11-11 10:24:37 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-10-23 23:23:26 +02:00
|
|
|
OpenGLSalGraphicsImpl::~OpenGLSalGraphicsImpl()
|
|
|
|
{
|
2015-11-13 12:00:59 +00:00
|
|
|
if( !IsOffscreen() && mnDrawCountAtFlush != mnDrawCount )
|
|
|
|
VCL_GL_INFO( "Destroying un-flushed on-screen graphics" );
|
|
|
|
|
2018-01-15 16:10:47 +02:00
|
|
|
mpFlush.reset();
|
2015-11-13 12:00:59 +00:00
|
|
|
|
2014-12-02 21:51:50 +01:00
|
|
|
ReleaseContext();
|
2014-11-22 07:58:38 -05:00
|
|
|
}
|
|
|
|
|
2015-09-07 22:21:15 +01:00
|
|
|
rtl::Reference<OpenGLContext> OpenGLSalGraphicsImpl::GetOpenGLContext()
|
2014-11-26 09:22:25 -05:00
|
|
|
{
|
2017-01-26 12:17:58 +00:00
|
|
|
if (mbAcquiringOpenGLContext)
|
|
|
|
return nullptr;
|
|
|
|
mbAcquiringOpenGLContext = true;
|
|
|
|
bool bSuccess = AcquireContext(true);
|
|
|
|
mbAcquiringOpenGLContext = false;
|
|
|
|
if (!bSuccess)
|
2015-11-10 10:28:29 +01:00
|
|
|
return nullptr;
|
2014-12-02 21:51:50 +01:00
|
|
|
return mpContext;
|
2014-11-26 09:22:25 -05:00
|
|
|
}
|
|
|
|
|
2015-12-10 18:31:04 +00:00
|
|
|
bool OpenGLSalGraphicsImpl::AcquireContext( bool bForceCreate )
|
2014-11-22 07:58:38 -05:00
|
|
|
{
|
2016-01-05 16:17:41 +00:00
|
|
|
mpContext = OpenGLContext::getVCLContext( false );
|
2015-09-16 03:25:05 +01:00
|
|
|
|
2016-01-05 16:17:41 +00:00
|
|
|
if( !mpContext.is() && mpWindowContext.is() )
|
2014-12-04 22:21:50 -05:00
|
|
|
{
|
2015-11-13 12:00:59 +00:00
|
|
|
mpContext = mpWindowContext;
|
2016-01-05 16:17:41 +00:00
|
|
|
}
|
2015-12-10 18:31:04 +00:00
|
|
|
else if( bForceCreate && !IsOffscreen() )
|
|
|
|
{
|
|
|
|
mpWindowContext = CreateWinContext();
|
|
|
|
mpContext = mpWindowContext;
|
|
|
|
}
|
2016-01-05 16:17:41 +00:00
|
|
|
|
2015-12-10 18:31:04 +00:00
|
|
|
if( !mpContext.is() )
|
2016-01-06 11:26:32 +01:00
|
|
|
mpContext = OpenGLContext::getVCLContext();
|
2014-11-22 07:58:38 -05:00
|
|
|
|
2015-09-07 22:21:15 +01:00
|
|
|
return mpContext.is();
|
2014-11-22 07:58:38 -05:00
|
|
|
}
|
|
|
|
|
2018-07-26 12:27:10 +02:00
|
|
|
void OpenGLSalGraphicsImpl::ReleaseContext()
|
2014-11-22 07:58:38 -05:00
|
|
|
{
|
2015-09-07 22:21:15 +01:00
|
|
|
mpContext.clear();
|
2014-11-22 07:58:38 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLSalGraphicsImpl::Init()
|
|
|
|
{
|
2015-11-13 12:00:59 +00:00
|
|
|
// Our init phase is strange ::Init is called twice for vdevs.
|
|
|
|
// the first time around with a NULL geometry provider.
|
|
|
|
if( !mpProvider )
|
|
|
|
return;
|
2014-11-22 07:58:38 -05:00
|
|
|
|
|
|
|
// check if we can simply re-use the same context
|
2015-09-07 22:21:15 +01:00
|
|
|
if( mpContext.is() )
|
2014-11-22 07:58:38 -05:00
|
|
|
{
|
2015-11-13 12:00:59 +00:00
|
|
|
if( !UseContext( mpContext ) )
|
2014-11-22 07:58:38 -05:00
|
|
|
ReleaseContext();
|
|
|
|
}
|
|
|
|
|
2015-11-13 12:00:59 +00:00
|
|
|
// Always create the offscreen texture
|
|
|
|
if( maOffscreenTex.GetWidth() != GetWidth() ||
|
2014-11-26 09:22:25 -05:00
|
|
|
maOffscreenTex.GetHeight() != GetHeight() )
|
2014-11-22 07:58:38 -05:00
|
|
|
{
|
2016-03-07 17:14:35 +00:00
|
|
|
// We don't want to be swapping before we've painted.
|
2017-01-04 12:06:42 +01:00
|
|
|
mpFlush->SetPriority( TaskPriority::POST_PAINT );
|
2016-03-07 17:14:35 +00:00
|
|
|
|
2015-09-15 14:07:27 +01:00
|
|
|
if( maOffscreenTex && // don't work to release empty textures
|
|
|
|
mpContext.is() ) // valid context
|
|
|
|
{
|
|
|
|
mpContext->makeCurrent();
|
2014-12-04 22:25:56 -05:00
|
|
|
mpContext->ReleaseFramebuffer( maOffscreenTex );
|
2015-09-15 14:07:27 +01:00
|
|
|
}
|
2014-11-26 09:22:25 -05:00
|
|
|
maOffscreenTex = OpenGLTexture();
|
2015-11-13 12:00:59 +00:00
|
|
|
VCL_GL_INFO("::Init - re-size offscreen texture");
|
|
|
|
}
|
|
|
|
|
2015-12-10 18:31:04 +00:00
|
|
|
if( mpWindowContext.is() )
|
2015-12-18 17:25:17 +00:00
|
|
|
{
|
2015-12-10 18:31:04 +00:00
|
|
|
mpWindowContext->reset();
|
2015-12-18 17:25:17 +00:00
|
|
|
mpWindowContext.clear();
|
|
|
|
}
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
2015-09-01 15:09:25 +01:00
|
|
|
// Currently only used to get windows ordering right.
|
|
|
|
void OpenGLSalGraphicsImpl::DeInit()
|
|
|
|
{
|
2016-05-27 19:43:12 +09:00
|
|
|
VCL_GL_INFO("::DeInit");
|
|
|
|
|
|
|
|
FlushDeferredDrawing();
|
|
|
|
|
2015-09-01 15:09:25 +01:00
|
|
|
// tdf#93839:
|
|
|
|
// Our window handles and resources are being free underneath us.
|
|
|
|
// These can be bound into a context, which relies on them. So
|
|
|
|
// let it know. Other eg. VirtualDevice contexts which have
|
|
|
|
// references on and rely on this context continuing to work will
|
|
|
|
// get a shiny new context in AcquireContext:: next PreDraw.
|
2015-12-18 17:25:17 +00:00
|
|
|
if( mpWindowContext.is() )
|
|
|
|
{
|
|
|
|
mpWindowContext->reset();
|
|
|
|
mpWindowContext.clear();
|
|
|
|
}
|
2015-11-13 12:00:59 +00:00
|
|
|
mpContext.clear();
|
2015-09-01 15:09:25 +01:00
|
|
|
}
|
|
|
|
|
2016-01-08 22:33:11 +00:00
|
|
|
void OpenGLSalGraphicsImpl::PreDraw(XOROption eOpt)
|
2016-04-08 17:41:21 +09:00
|
|
|
{
|
|
|
|
FlushDeferredDrawing();
|
|
|
|
|
|
|
|
InitializePreDrawState(eOpt);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLSalGraphicsImpl::InitializePreDrawState(XOROption eOpt)
|
2014-11-10 13:06:38 -05:00
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone::enter();
|
|
|
|
|
2015-11-13 12:00:59 +00:00
|
|
|
mnDrawCount++;
|
|
|
|
|
2014-12-04 22:21:50 -05:00
|
|
|
if( !AcquireContext() )
|
2014-11-26 09:22:25 -05:00
|
|
|
{
|
|
|
|
SAL_WARN( "vcl.opengl", "Couldn't acquire context" );
|
|
|
|
return;
|
|
|
|
}
|
2014-11-22 07:58:38 -05:00
|
|
|
|
|
|
|
mpContext->makeCurrent();
|
2014-11-26 09:22:25 -05:00
|
|
|
CHECK_GL_ERROR();
|
|
|
|
|
2015-11-13 12:00:59 +00:00
|
|
|
CheckOffscreenTexture();
|
2014-11-22 08:11:33 -05:00
|
|
|
CHECK_GL_ERROR();
|
2014-11-26 09:22:25 -05:00
|
|
|
|
2017-03-30 20:27:55 +02:00
|
|
|
mpContext->state().viewport(tools::Rectangle(Point(0, 0), Size(GetWidth(), GetHeight())));
|
2014-11-12 18:21:47 +01:00
|
|
|
|
2016-01-08 22:33:11 +00:00
|
|
|
ImplInitClipRegion();
|
2014-11-12 18:21:47 +01:00
|
|
|
CHECK_GL_ERROR();
|
2016-01-08 22:33:11 +00:00
|
|
|
|
|
|
|
if (eOpt == IMPLEMENT_XOR && mbXORMode)
|
|
|
|
{
|
|
|
|
glEnable(GL_COLOR_LOGIC_OP);
|
|
|
|
CHECK_GL_ERROR();
|
|
|
|
|
|
|
|
glLogicOp(GL_XOR);
|
2016-08-04 16:21:47 +09:00
|
|
|
CHECK_GL_ERROR();
|
|
|
|
|
|
|
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
|
|
|
|
CHECK_GL_ERROR();
|
2016-01-08 22:33:11 +00:00
|
|
|
}
|
2014-11-10 13:06:38 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLSalGraphicsImpl::PostDraw()
|
|
|
|
{
|
2016-01-08 22:33:11 +00:00
|
|
|
if (mbXORMode)
|
|
|
|
{
|
|
|
|
glDisable(GL_COLOR_LOGIC_OP);
|
|
|
|
CHECK_GL_ERROR();
|
2016-08-04 16:21:47 +09:00
|
|
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
|
|
|
CHECK_GL_ERROR();
|
2016-01-08 22:33:11 +00:00
|
|
|
}
|
|
|
|
|
2014-11-28 14:56:08 -05:00
|
|
|
if( mpProgram )
|
|
|
|
{
|
|
|
|
mpProgram->Clean();
|
2015-11-10 10:28:29 +01:00
|
|
|
mpProgram = nullptr;
|
2014-12-18 11:47:58 +01:00
|
|
|
#ifdef DBG_UTIL
|
2015-01-12 13:20:54 +01:00
|
|
|
mProgramIsSolidColor = false;
|
2014-12-18 11:47:58 +01:00
|
|
|
#endif
|
2014-11-28 14:56:08 -05:00
|
|
|
}
|
2015-11-13 12:00:59 +00:00
|
|
|
|
|
|
|
assert (maOffscreenTex);
|
|
|
|
|
|
|
|
// Always queue the flush.
|
|
|
|
if( !IsOffscreen() )
|
|
|
|
flush();
|
|
|
|
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone::leave();
|
2014-11-10 13:06:38 -05:00
|
|
|
}
|
|
|
|
|
2016-06-24 16:42:45 +08:00
|
|
|
void OpenGLSalGraphicsImpl::PostBatchDraw()
|
|
|
|
{
|
|
|
|
if (IsOffscreen())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!mpFlush->IsActive())
|
|
|
|
mpFlush->Start();
|
|
|
|
}
|
|
|
|
|
2015-07-08 18:43:32 +09:00
|
|
|
void OpenGLSalGraphicsImpl::ApplyProgramMatrices(float fPixelOffset)
|
|
|
|
{
|
|
|
|
mpProgram->ApplyMatrix(GetWidth(), GetHeight(), fPixelOffset);
|
|
|
|
}
|
|
|
|
|
2014-10-23 23:23:26 +02:00
|
|
|
void OpenGLSalGraphicsImpl::freeResources()
|
|
|
|
{
|
2014-11-10 13:46:12 -05:00
|
|
|
// TODO Delete shaders, programs and textures if not shared
|
2015-11-13 12:00:59 +00:00
|
|
|
if( mpContext.is() && mpContext->isInitialized() )
|
2014-12-04 22:25:56 -05:00
|
|
|
{
|
2015-11-13 12:00:59 +00:00
|
|
|
VCL_GL_INFO( "freeResources" );
|
2014-12-04 22:25:56 -05:00
|
|
|
mpContext->makeCurrent();
|
2016-04-08 17:41:21 +09:00
|
|
|
FlushDeferredDrawing();
|
2014-12-04 22:25:56 -05:00
|
|
|
mpContext->ReleaseFramebuffer( maOffscreenTex );
|
|
|
|
}
|
|
|
|
ReleaseContext();
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
2014-11-12 18:11:34 -05:00
|
|
|
void OpenGLSalGraphicsImpl::ImplSetClipBit( const vcl::Region& rClip, GLuint nMask )
|
|
|
|
{
|
2016-11-28 16:39:26 +01:00
|
|
|
mpContext->state().scissor().disable();
|
|
|
|
mpContext->state().stencil().enable();
|
2015-11-13 12:00:59 +00:00
|
|
|
|
|
|
|
VCL_GL_INFO( "Adding complex clip / stencil" );
|
|
|
|
GLuint nStencil = maOffscreenTex.StencilId();
|
|
|
|
if( nStencil == 0 )
|
|
|
|
{
|
|
|
|
nStencil = maOffscreenTex.AddStencil();
|
|
|
|
glFramebufferRenderbuffer(
|
|
|
|
GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
|
|
|
|
GL_RENDERBUFFER, nStencil );
|
|
|
|
CHECK_GL_ERROR();
|
|
|
|
}
|
|
|
|
// else - we associated the stencil in
|
|
|
|
// AcquireFrameBuffer / AttachTexture
|
|
|
|
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2014-11-12 18:11:34 -05:00
|
|
|
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2014-11-12 18:11:34 -05:00
|
|
|
glStencilMask( nMask );
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2014-11-12 18:11:34 -05:00
|
|
|
glStencilFunc( GL_NEVER, nMask, 0xFF );
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2014-11-12 18:11:34 -05:00
|
|
|
glStencilOp( GL_REPLACE, GL_KEEP, GL_KEEP );
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2014-11-12 18:11:34 -05:00
|
|
|
|
|
|
|
glClear( GL_STENCIL_BUFFER_BIT );
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2018-03-14 11:11:02 +02:00
|
|
|
if( UseSolid( Color( 0xFF, 0xFF, 0xFF ) ) )
|
2014-11-28 14:56:08 -05:00
|
|
|
{
|
|
|
|
if( rClip.getRegionBand() )
|
|
|
|
DrawRegionBand( *rClip.getRegionBand() );
|
|
|
|
else
|
2015-01-12 13:20:54 +01:00
|
|
|
DrawPolyPolygon( rClip.GetAsB2DPolyPolygon(), true );
|
2014-11-28 14:56:08 -05:00
|
|
|
}
|
2014-11-12 18:11:34 -05:00
|
|
|
|
|
|
|
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2014-11-12 18:11:34 -05:00
|
|
|
glStencilMask( 0x00 );
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2016-04-28 20:01:28 +09:00
|
|
|
|
2016-11-28 16:39:26 +01:00
|
|
|
mpContext->state().stencil().disable();
|
2014-11-12 18:11:34 -05:00
|
|
|
}
|
|
|
|
|
2014-11-22 08:07:47 -05:00
|
|
|
void OpenGLSalGraphicsImpl::ImplInitClipRegion()
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2014-11-22 08:07:47 -05:00
|
|
|
// make sure the context has the right clipping set
|
2016-04-28 19:34:37 +09:00
|
|
|
if (maClipRegion != mpContext->maClipRegion)
|
2014-11-12 15:37:11 -05:00
|
|
|
{
|
2014-11-22 08:07:47 -05:00
|
|
|
mpContext->maClipRegion = maClipRegion;
|
2016-04-28 19:34:37 +09:00
|
|
|
if (mbUseStencil)
|
2014-11-22 08:07:47 -05:00
|
|
|
{
|
2016-04-28 19:34:37 +09:00
|
|
|
ImplSetClipBit(maClipRegion, 0x01);
|
2014-11-22 08:07:47 -05:00
|
|
|
}
|
2014-11-12 15:37:11 -05:00
|
|
|
}
|
2014-10-29 13:05:02 -04:00
|
|
|
|
2016-04-28 19:34:37 +09:00
|
|
|
if (mbUseScissor)
|
2015-11-17 09:20:25 +02:00
|
|
|
{
|
2017-03-30 20:27:55 +02:00
|
|
|
tools::Rectangle aRect(maClipRegion.GetBoundRect());
|
2016-11-28 16:39:26 +01:00
|
|
|
mpContext->state().scissor().set(aRect.Left(), GetHeight() - aRect.Bottom() - 1, aRect.GetWidth(), aRect.GetHeight());
|
|
|
|
mpContext->state().scissor().enable();
|
2015-11-17 09:20:25 +02:00
|
|
|
}
|
2016-04-28 19:34:37 +09:00
|
|
|
else
|
|
|
|
{
|
2016-11-28 16:39:26 +01:00
|
|
|
mpContext->state().scissor().disable();
|
2016-04-28 19:34:37 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
if (mbUseStencil)
|
2014-11-12 15:37:11 -05:00
|
|
|
{
|
2014-11-22 08:07:47 -05:00
|
|
|
glStencilFunc( GL_EQUAL, 1, 0x1 );
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2016-11-28 16:39:26 +01:00
|
|
|
mpContext->state().stencil().enable();
|
2016-04-28 20:01:28 +09:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-11-28 16:39:26 +01:00
|
|
|
mpContext->state().stencil().disable();
|
2014-11-22 08:07:47 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-04 11:45:55 -05:00
|
|
|
const vcl::Region& OpenGLSalGraphicsImpl::getClipRegion() const
|
|
|
|
{
|
|
|
|
return maClipRegion;
|
|
|
|
}
|
|
|
|
|
2014-11-22 08:07:47 -05:00
|
|
|
bool OpenGLSalGraphicsImpl::setClipRegion( const vcl::Region& rClip )
|
|
|
|
{
|
2016-03-14 11:20:19 +01:00
|
|
|
if (maClipRegion == rClip)
|
2016-04-08 17:41:21 +09:00
|
|
|
{
|
|
|
|
VCL_GL_INFO("::setClipRegion (no change) " << rClip);
|
|
|
|
return true;
|
|
|
|
}
|
2016-03-14 11:20:19 +01:00
|
|
|
|
|
|
|
FlushDeferredDrawing();
|
|
|
|
|
2016-04-08 17:41:21 +09:00
|
|
|
VCL_GL_INFO("::setClipRegion " << rClip);
|
|
|
|
|
2014-11-22 08:07:47 -05:00
|
|
|
maClipRegion = rClip;
|
2014-10-29 13:05:02 -04:00
|
|
|
|
2014-11-22 08:07:47 -05:00
|
|
|
mbUseStencil = false;
|
|
|
|
mbUseScissor = false;
|
2016-04-28 19:34:37 +09:00
|
|
|
if (maClipRegion.IsRectangle())
|
2014-11-12 15:37:11 -05:00
|
|
|
mbUseScissor = true;
|
2016-04-28 19:34:37 +09:00
|
|
|
else if (!maClipRegion.IsEmpty())
|
2014-11-12 15:37:11 -05:00
|
|
|
mbUseStencil = true;
|
2014-10-29 13:05:02 -04:00
|
|
|
|
|
|
|
return true;
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
2014-11-08 22:55:58 -05:00
|
|
|
// set the clip region to empty
|
|
|
|
void OpenGLSalGraphicsImpl::ResetClipRegion()
|
|
|
|
{
|
2016-03-14 11:20:19 +01:00
|
|
|
if (maClipRegion.IsEmpty())
|
2016-04-08 17:41:21 +09:00
|
|
|
{
|
|
|
|
VCL_GL_INFO("::ResetClipRegion (no change) ");
|
2016-03-14 11:20:19 +01:00
|
|
|
return;
|
2016-04-08 17:41:21 +09:00
|
|
|
}
|
2016-03-14 11:20:19 +01:00
|
|
|
|
|
|
|
FlushDeferredDrawing();
|
|
|
|
|
2016-04-08 17:41:21 +09:00
|
|
|
VCL_GL_INFO("::ResetClipRegion");
|
|
|
|
|
2014-11-22 08:07:47 -05:00
|
|
|
maClipRegion.SetEmpty();
|
2014-11-12 15:37:11 -05:00
|
|
|
mbUseScissor = false;
|
|
|
|
mbUseStencil = false;
|
2014-11-08 22:55:58 -05:00
|
|
|
}
|
|
|
|
|
2014-10-23 23:23:26 +02:00
|
|
|
// get the depth of the device
|
|
|
|
sal_uInt16 OpenGLSalGraphicsImpl::GetBitCount() const
|
|
|
|
{
|
|
|
|
return 32;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get the width of the device
|
|
|
|
long OpenGLSalGraphicsImpl::GetGraphicsWidth() const
|
|
|
|
{
|
2014-11-03 11:08:24 -05:00
|
|
|
return GetWidth();
|
2014-10-30 21:54:22 -04:00
|
|
|
}
|
|
|
|
|
2014-10-23 23:23:26 +02:00
|
|
|
// set the line color to transparent (= don't draw lines)
|
|
|
|
void OpenGLSalGraphicsImpl::SetLineColor()
|
|
|
|
{
|
2014-10-29 13:05:02 -04:00
|
|
|
if( mnLineColor != SALCOLOR_NONE )
|
|
|
|
{
|
|
|
|
mnLineColor = SALCOLOR_NONE;
|
|
|
|
}
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// set the line color to a specific color
|
2018-03-14 11:11:02 +02:00
|
|
|
void OpenGLSalGraphicsImpl::SetLineColor( Color nColor )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2018-03-14 11:11:02 +02:00
|
|
|
if( mnLineColor != nColor )
|
2014-10-29 13:05:02 -04:00
|
|
|
{
|
2018-03-14 11:11:02 +02:00
|
|
|
mnLineColor = nColor;
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// set the fill color to transparent (= don't fill)
|
|
|
|
void OpenGLSalGraphicsImpl::SetFillColor()
|
|
|
|
{
|
2014-10-29 13:05:02 -04:00
|
|
|
if( mnFillColor != SALCOLOR_NONE )
|
|
|
|
{
|
|
|
|
mnFillColor = SALCOLOR_NONE;
|
|
|
|
}
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// set the fill color to a specific color, shapes will be
|
|
|
|
// filled accordingly
|
2018-03-14 11:11:02 +02:00
|
|
|
void OpenGLSalGraphicsImpl::SetFillColor( Color nColor )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2018-03-14 11:11:02 +02:00
|
|
|
if( mnFillColor != nColor )
|
2014-10-29 13:05:02 -04:00
|
|
|
{
|
2018-03-14 11:11:02 +02:00
|
|
|
mnFillColor = nColor;
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// enable/disable XOR drawing
|
2018-12-05 01:23:17 +01:00
|
|
|
void OpenGLSalGraphicsImpl::SetXORMode( bool bSet, bool )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2016-08-04 16:21:47 +09:00
|
|
|
if (mbXORMode != bSet)
|
|
|
|
{
|
|
|
|
FlushDeferredDrawing();
|
|
|
|
mbXORMode = bSet;
|
|
|
|
}
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
2016-08-04 16:21:47 +09:00
|
|
|
void OpenGLSalGraphicsImpl::SetROPLineColor(SalROPColor nROPColor)
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2016-08-04 16:21:47 +09:00
|
|
|
switch (nROPColor)
|
|
|
|
{
|
|
|
|
case SalROPColor::N0:
|
2018-03-14 11:11:02 +02:00
|
|
|
mnLineColor = Color(0, 0, 0);
|
2016-08-04 16:21:47 +09:00
|
|
|
break;
|
|
|
|
case SalROPColor::N1:
|
2018-03-14 11:11:02 +02:00
|
|
|
mnLineColor = Color(0xff, 0xff, 0xff);
|
2016-08-04 16:21:47 +09:00
|
|
|
break;
|
|
|
|
case SalROPColor::Invert:
|
2018-03-14 11:11:02 +02:00
|
|
|
mnLineColor = Color(0xff, 0xff, 0xff);
|
2016-08-04 16:21:47 +09:00
|
|
|
break;
|
|
|
|
}
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
2016-08-04 16:21:47 +09:00
|
|
|
void OpenGLSalGraphicsImpl::SetROPFillColor(SalROPColor nROPColor)
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2016-08-04 16:21:47 +09:00
|
|
|
switch (nROPColor)
|
|
|
|
{
|
|
|
|
case SalROPColor::N0:
|
2018-03-14 11:11:02 +02:00
|
|
|
mnFillColor = Color(0, 0, 0);
|
2016-08-04 16:21:47 +09:00
|
|
|
break;
|
|
|
|
case SalROPColor::N1:
|
2018-03-14 11:11:02 +02:00
|
|
|
mnFillColor = Color(0xff, 0xff, 0xff);
|
2016-08-04 16:21:47 +09:00
|
|
|
break;
|
|
|
|
case SalROPColor::Invert:
|
2018-03-14 11:11:02 +02:00
|
|
|
mnFillColor = Color(0xff, 0xff, 0xff);
|
2016-08-04 16:21:47 +09:00
|
|
|
break;
|
|
|
|
}
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
2018-01-22 15:52:16 +02:00
|
|
|
void OpenGLSalGraphicsImpl::CheckOffscreenTexture()
|
2014-11-13 21:38:58 -05:00
|
|
|
{
|
2015-11-13 12:00:59 +00:00
|
|
|
bool bClearTexture = false;
|
|
|
|
|
|
|
|
VCL_GL_INFO( "Check Offscreen texture" );
|
|
|
|
|
|
|
|
// Always create the offscreen texture
|
|
|
|
if( maOffscreenTex )
|
|
|
|
{
|
|
|
|
if( maOffscreenTex.GetWidth() != GetWidth() ||
|
|
|
|
maOffscreenTex.GetHeight() != GetHeight() )
|
|
|
|
{
|
2015-12-31 22:12:59 +00:00
|
|
|
VCL_GL_INFO( "re-size offscreen texture " << maOffscreenTex.Id() );
|
2017-01-04 12:06:42 +01:00
|
|
|
mpFlush->SetPriority( TaskPriority::POST_PAINT );
|
2015-11-13 12:00:59 +00:00
|
|
|
mpContext->ReleaseFramebuffer( maOffscreenTex );
|
|
|
|
maOffscreenTex = OpenGLTexture();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-26 09:22:25 -05:00
|
|
|
if( !maOffscreenTex )
|
2015-11-13 12:00:59 +00:00
|
|
|
{
|
|
|
|
VCL_GL_INFO( "create texture of size "
|
|
|
|
<< GetWidth() << " x " << GetHeight() );
|
2014-11-26 09:22:25 -05:00
|
|
|
maOffscreenTex = OpenGLTexture( GetWidth(), GetHeight() );
|
2015-11-13 12:00:59 +00:00
|
|
|
bClearTexture = true;
|
|
|
|
}
|
2014-11-13 21:38:58 -05:00
|
|
|
|
2014-11-26 09:22:25 -05:00
|
|
|
if( !maOffscreenTex.IsUnique() )
|
2014-11-22 07:58:38 -05:00
|
|
|
{
|
2014-11-26 09:22:25 -05:00
|
|
|
GLfloat fWidth = GetWidth();
|
|
|
|
GLfloat fHeight = GetHeight();
|
|
|
|
SalTwoRect aPosAry(0, 0, fWidth, fHeight, 0,0, fWidth, fHeight);
|
2014-11-13 21:38:58 -05:00
|
|
|
|
2014-11-26 09:22:25 -05:00
|
|
|
// TODO: lfrb: User GL_ARB_copy_image?
|
2019-06-21 12:14:08 +02:00
|
|
|
OpenGLTexture aNewTex( GetWidth(), GetHeight() );
|
2016-04-29 17:07:11 +09:00
|
|
|
|
2016-11-28 16:39:26 +01:00
|
|
|
mpContext->state().scissor().disable();
|
|
|
|
mpContext->state().stencil().disable();
|
2016-04-29 17:07:11 +09:00
|
|
|
|
2016-01-12 17:11:15 +02:00
|
|
|
mpContext->AcquireFramebuffer( aNewTex );
|
2014-11-26 09:22:25 -05:00
|
|
|
DrawTexture( maOffscreenTex, aPosAry );
|
|
|
|
maOffscreenTex = aNewTex;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-01-12 17:11:15 +02:00
|
|
|
mpContext->AcquireFramebuffer( maOffscreenTex );
|
2015-11-13 12:00:59 +00:00
|
|
|
CHECK_GL_ERROR();
|
|
|
|
|
|
|
|
if( bClearTexture )
|
|
|
|
{
|
|
|
|
glDrawBuffer( GL_COLOR_ATTACHMENT0 );
|
|
|
|
#if OSL_DEBUG_LEVEL > 0 // lets have some red debugging background.
|
2017-07-30 12:16:31 +02:00
|
|
|
GLfloat const clearColor[4] = { 1.0, 0, 0, 0 };
|
2015-11-13 12:00:59 +00:00
|
|
|
#else
|
2017-07-30 12:16:31 +02:00
|
|
|
GLfloat const clearColor[4] = { 1.0, 1.0, 1.0, 0 };
|
2015-11-13 12:00:59 +00:00
|
|
|
#endif
|
|
|
|
glClearBufferfv( GL_COLOR, 0, clearColor );
|
|
|
|
// FIXME: use glClearTexImage if we have it ?
|
|
|
|
}
|
2014-11-26 09:22:25 -05:00
|
|
|
}
|
2014-11-13 21:38:58 -05:00
|
|
|
|
2015-11-13 12:00:59 +00:00
|
|
|
assert( maOffscreenTex );
|
|
|
|
|
2014-11-14 15:43:44 +01:00
|
|
|
CHECK_GL_ERROR();
|
2014-11-13 21:38:58 -05:00
|
|
|
}
|
|
|
|
|
2015-01-20 14:48:48 +01:00
|
|
|
bool OpenGLSalGraphicsImpl::UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader, const OString& preamble )
|
2014-11-20 22:07:12 -05:00
|
|
|
{
|
2015-11-10 10:28:29 +01:00
|
|
|
if( mpProgram != nullptr )
|
2014-12-15 13:05:17 +01:00
|
|
|
mpProgram->Clean();
|
2015-01-20 14:48:48 +01:00
|
|
|
mpProgram = mpContext->UseProgram( rVertexShader, rFragmentShader, preamble );
|
2014-12-18 11:47:58 +01:00
|
|
|
#ifdef DBG_UTIL
|
2015-01-12 13:20:54 +01:00
|
|
|
mProgramIsSolidColor = false; // UseSolid() will set to true if needed
|
2014-12-18 11:47:58 +01:00
|
|
|
#endif
|
2015-11-10 10:28:29 +01:00
|
|
|
return ( mpProgram != nullptr );
|
2014-11-20 22:07:12 -05:00
|
|
|
}
|
|
|
|
|
2018-03-14 11:11:02 +02:00
|
|
|
bool OpenGLSalGraphicsImpl::UseSolid( Color nColor, sal_uInt8 nTransparency )
|
2014-10-29 13:05:02 -04:00
|
|
|
{
|
2014-11-28 14:56:08 -05:00
|
|
|
if( nColor == SALCOLOR_NONE )
|
2014-10-29 13:05:02 -04:00
|
|
|
return false;
|
2016-05-29 12:37:41 +09:00
|
|
|
UseSolid();
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetColor( "color", nColor, nTransparency );
|
2014-12-18 11:47:58 +01:00
|
|
|
#ifdef DBG_UTIL
|
2015-01-12 13:20:54 +01:00
|
|
|
mProgramIsSolidColor = true;
|
2014-12-18 11:47:58 +01:00
|
|
|
#endif
|
2015-01-12 13:20:54 +01:00
|
|
|
mProgramSolidColor = nColor;
|
|
|
|
mProgramSolidTransparency = nTransparency / 100.0;
|
2016-01-08 22:33:11 +00:00
|
|
|
|
2014-11-17 09:15:15 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-03-14 11:11:02 +02:00
|
|
|
bool OpenGLSalGraphicsImpl::UseSolid( Color nColor, double fTransparency )
|
2014-11-18 12:34:53 -05:00
|
|
|
{
|
2014-11-28 14:56:08 -05:00
|
|
|
if( nColor == SALCOLOR_NONE )
|
2014-11-18 12:34:53 -05:00
|
|
|
return false;
|
2016-05-29 12:37:41 +09:00
|
|
|
UseSolid();
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetColorf( "color", nColor, fTransparency );
|
2014-12-18 11:47:58 +01:00
|
|
|
#ifdef DBG_UTIL
|
2015-01-12 13:20:54 +01:00
|
|
|
mProgramIsSolidColor = true;
|
2014-12-18 11:47:58 +01:00
|
|
|
#endif
|
2015-01-12 13:20:54 +01:00
|
|
|
mProgramSolidColor = nColor;
|
|
|
|
mProgramSolidTransparency = fTransparency;
|
2014-10-29 13:05:02 -04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-01-22 15:52:16 +02:00
|
|
|
void OpenGLSalGraphicsImpl::UseSolid()
|
2016-05-29 12:37:41 +09:00
|
|
|
{
|
|
|
|
if (!UseProgram("combinedVertexShader", "combinedFragmentShader"))
|
2018-01-22 15:52:16 +02:00
|
|
|
return;
|
2016-05-29 12:37:41 +09:00
|
|
|
mpProgram->SetShaderType(DrawShaderType::Normal);
|
|
|
|
}
|
|
|
|
|
2015-12-31 21:19:48 +00:00
|
|
|
bool OpenGLSalGraphicsImpl::UseInvert50()
|
|
|
|
{
|
2017-04-25 10:33:32 +02:00
|
|
|
return UseProgram( "dumbVertexShader", "invert50FragmentShader" );
|
2015-12-31 21:19:48 +00:00
|
|
|
}
|
|
|
|
|
2018-03-14 11:11:02 +02:00
|
|
|
bool OpenGLSalGraphicsImpl::UseSolid( Color nColor )
|
2014-11-11 05:13:40 -05:00
|
|
|
{
|
2014-11-28 14:56:08 -05:00
|
|
|
return UseSolid( nColor, 0.0f );
|
2014-11-11 15:54:03 -05:00
|
|
|
}
|
|
|
|
|
2015-12-31 21:19:48 +00:00
|
|
|
bool OpenGLSalGraphicsImpl::UseInvert( SalInvert nFlags )
|
2014-11-11 15:54:03 -05:00
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2016-05-10 09:55:14 +02:00
|
|
|
if( ( nFlags & SalInvert::N50 ) ||
|
|
|
|
( nFlags & SalInvert::TrackFrame ) )
|
2015-12-31 21:19:48 +00:00
|
|
|
{
|
2016-01-09 12:13:15 +00:00
|
|
|
// FIXME: Trackframe really should be 2 pix. on/off stipple.
|
2015-12-31 21:19:48 +00:00
|
|
|
if( !UseInvert50() )
|
|
|
|
return false;
|
|
|
|
mpProgram->SetBlendMode( GL_ONE_MINUS_DST_COLOR,
|
|
|
|
GL_ONE_MINUS_SRC_COLOR );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-03-14 11:11:02 +02:00
|
|
|
if( !UseSolid( Color( 255, 255, 255 ) ) )
|
2015-12-31 21:19:48 +00:00
|
|
|
return false;
|
|
|
|
mpProgram->SetBlendMode( GL_ONE_MINUS_DST_COLOR, GL_ZERO );
|
|
|
|
}
|
2014-11-11 05:13:40 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-02-24 00:44:58 +01:00
|
|
|
void OpenGLSalGraphicsImpl::DrawLineSegment(float x1, float y1, float x2, float y2)
|
|
|
|
{
|
2016-05-27 19:43:12 +09:00
|
|
|
std::vector<GLfloat> aVertices;
|
2016-02-24 00:44:58 +01:00
|
|
|
std::vector<GLfloat> aExtrusionVectors;
|
|
|
|
|
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2016-06-07 20:45:14 +09:00
|
|
|
glm::vec2 aPoint1(x1, y1);
|
|
|
|
glm::vec2 aPoint2(x2, y2);
|
2016-02-24 00:44:58 +01:00
|
|
|
|
2016-06-07 20:45:14 +09:00
|
|
|
glm::vec2 aLineVector = vcl::vertex::normalize(aPoint2 - aPoint1);
|
2019-06-21 12:14:08 +02:00
|
|
|
glm::vec2 aNormal(-aLineVector.y, aLineVector.x);
|
2016-06-07 20:45:14 +09:00
|
|
|
|
|
|
|
vcl::vertex::addLineSegmentVertices(aVertices, aExtrusionVectors,
|
|
|
|
aPoint1, aNormal, 1.0f,
|
|
|
|
aPoint2, aNormal, 1.0f);
|
2016-02-24 00:44:58 +01:00
|
|
|
|
2016-05-19 21:35:28 +09:00
|
|
|
ApplyProgramMatrices(0.5f);
|
2016-02-24 00:44:58 +01:00
|
|
|
mpProgram->SetExtrusionVectors(aExtrusionVectors.data());
|
2016-05-27 19:43:12 +09:00
|
|
|
mpProgram->DrawArrays(GL_TRIANGLES, aVertices);
|
2016-02-24 00:44:58 +01:00
|
|
|
|
|
|
|
CHECK_GL_ERROR();
|
|
|
|
}
|
|
|
|
|
2018-03-14 11:11:02 +02:00
|
|
|
bool OpenGLSalGraphicsImpl::UseLine(Color nColor, double fTransparency, GLfloat fLineWidth, bool bUseAA)
|
2016-02-24 00:44:58 +01:00
|
|
|
{
|
|
|
|
if( nColor == SALCOLOR_NONE )
|
|
|
|
return false;
|
2016-05-29 12:37:41 +09:00
|
|
|
UseLine(fLineWidth, bUseAA);
|
|
|
|
mpProgram->SetColorf("color", nColor, fTransparency);
|
|
|
|
#ifdef DBG_UTIL
|
|
|
|
mProgramIsSolidColor = true;
|
|
|
|
#endif
|
|
|
|
mProgramSolidColor = nColor;
|
|
|
|
mProgramSolidTransparency = fTransparency;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-01-22 15:52:16 +02:00
|
|
|
void OpenGLSalGraphicsImpl::UseLine(GLfloat fLineWidth, bool bUseAA)
|
2016-05-29 12:37:41 +09:00
|
|
|
{
|
2016-05-20 14:59:24 +09:00
|
|
|
if (!UseProgram("combinedVertexShader", "combinedFragmentShader"))
|
2018-01-22 15:52:16 +02:00
|
|
|
return;
|
2016-05-20 14:59:24 +09:00
|
|
|
mpProgram->SetShaderType(DrawShaderType::Line);
|
2016-02-24 00:44:58 +01:00
|
|
|
mpProgram->SetUniform1f("line_width", fLineWidth);
|
|
|
|
// The width of the feather - area we make lineary transparent in VS.
|
2016-05-20 14:59:24 +09:00
|
|
|
// Good AA value is 0.5f, no AA if feather 0.0f
|
2016-05-19 21:35:28 +09:00
|
|
|
mpProgram->SetUniform1f("feather", bUseAA ? 0.5f : 0.0f);
|
2016-02-24 00:44:58 +01:00
|
|
|
// We need blending or AA won't work correctly
|
2016-05-29 12:37:41 +09:00
|
|
|
mpProgram->SetBlendMode(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
2016-02-24 00:44:58 +01:00
|
|
|
}
|
|
|
|
|
2015-01-18 18:58:20 +01:00
|
|
|
void OpenGLSalGraphicsImpl::DrawConvexPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry, bool blockAA )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2014-11-06 03:37:47 +01:00
|
|
|
std::vector<GLfloat> aVertices(nPoints * 2);
|
2014-10-29 13:05:02 -04:00
|
|
|
sal_uInt32 i, j;
|
|
|
|
|
|
|
|
for( i = 0, j = 0; i < nPoints; i++, j += 2 )
|
|
|
|
{
|
2015-07-08 18:43:32 +09:00
|
|
|
aVertices[j] = GLfloat(pPtAry[i].mnX);
|
|
|
|
aVertices[j+1] = GLfloat(pPtAry[i].mnY);
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
|
2015-07-08 18:43:32 +09:00
|
|
|
ApplyProgramMatrices();
|
2016-05-27 17:54:50 +09:00
|
|
|
std::vector<GLfloat> aExtrusion(nPoints * 3, 0);
|
|
|
|
mpProgram->SetExtrusionVectors(aExtrusion.data());
|
2016-05-12 13:37:11 +09:00
|
|
|
mpProgram->DrawArrays(GL_TRIANGLE_FAN, aVertices);
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2015-01-18 18:58:20 +01:00
|
|
|
|
|
|
|
if( !blockAA && mrParent.getAntiAliasB2DDraw())
|
|
|
|
{
|
|
|
|
// Make the edges antialiased by drawing the edge lines again with AA.
|
|
|
|
// TODO: If transparent drawing is set up, drawing the lines themselves twice
|
|
|
|
// may be a problem, if that is a real problem, the polygon areas itself needs to be
|
|
|
|
// masked out for this or something.
|
|
|
|
#ifdef DBG_UTIL
|
|
|
|
assert( mProgramIsSolidColor );
|
|
|
|
#endif
|
2018-03-14 11:11:02 +02:00
|
|
|
Color lastSolidColor = mProgramSolidColor;
|
2015-01-18 18:58:20 +01:00
|
|
|
double lastSolidTransparency = mProgramSolidTransparency;
|
2016-05-20 14:59:24 +09:00
|
|
|
if (UseLine(lastSolidColor, lastSolidTransparency, 1.0f, true))
|
2015-01-18 18:58:20 +01:00
|
|
|
{
|
|
|
|
for( i = 0; i < nPoints; ++i )
|
|
|
|
{
|
|
|
|
const SalPoint& rPt1 = pPtAry[ i ];
|
|
|
|
const SalPoint& rPt2 = pPtAry[ ( i + 1 ) % nPoints ];
|
2016-05-19 21:35:28 +09:00
|
|
|
DrawLineSegment(rPt1.mnX, rPt1.mnY, rPt2.mnX, rPt2.mnY);
|
2015-01-18 18:58:20 +01:00
|
|
|
}
|
|
|
|
UseSolid( lastSolidColor, lastSolidTransparency );
|
|
|
|
}
|
|
|
|
}
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
2015-08-16 16:45:12 -05:00
|
|
|
void OpenGLSalGraphicsImpl::DrawConvexPolygon( const tools::Polygon& rPolygon, bool blockAA )
|
2014-11-11 05:13:40 -05:00
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2014-11-11 05:13:40 -05:00
|
|
|
sal_uInt16 nPoints = rPolygon.GetSize() - 1;
|
|
|
|
std::vector<GLfloat> aVertices(nPoints * 2);
|
|
|
|
sal_uInt32 i, j;
|
|
|
|
|
|
|
|
for( i = 0, j = 0; i < nPoints; i++, j += 2 )
|
|
|
|
{
|
|
|
|
const Point& rPt = rPolygon.GetPoint( i );
|
2015-07-08 18:43:32 +09:00
|
|
|
aVertices[j] = GLfloat(rPt.X());
|
|
|
|
aVertices[j+1] = GLfloat(rPt.Y());
|
2014-11-11 05:13:40 -05:00
|
|
|
}
|
|
|
|
|
2015-07-08 18:43:32 +09:00
|
|
|
ApplyProgramMatrices();
|
2016-05-27 17:54:50 +09:00
|
|
|
std::vector<GLfloat> aExtrusion(nPoints * 3, 0);
|
|
|
|
mpProgram->SetExtrusionVectors(aExtrusion.data());
|
2016-05-12 13:37:11 +09:00
|
|
|
mpProgram->DrawArrays(GL_TRIANGLE_FAN, aVertices);
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2014-12-18 11:47:58 +01:00
|
|
|
|
2015-01-18 18:58:20 +01:00
|
|
|
if( !blockAA && mrParent.getAntiAliasB2DDraw())
|
2014-12-18 11:47:58 +01:00
|
|
|
{
|
|
|
|
// Make the edges antialiased by drawing the edge lines again with AA.
|
|
|
|
// TODO: If transparent drawing is set up, drawing the lines themselves twice
|
|
|
|
// may be a problem, if that is a real problem, the polygon areas itself needs to be
|
|
|
|
// masked out for this or something.
|
|
|
|
#ifdef DBG_UTIL
|
2015-01-12 13:20:54 +01:00
|
|
|
assert( mProgramIsSolidColor );
|
2014-12-18 11:47:58 +01:00
|
|
|
#endif
|
2018-03-14 11:11:02 +02:00
|
|
|
Color lastSolidColor = mProgramSolidColor;
|
2015-01-12 13:20:54 +01:00
|
|
|
double lastSolidTransparency = mProgramSolidTransparency;
|
2016-05-20 14:59:24 +09:00
|
|
|
if (UseLine(lastSolidColor, lastSolidTransparency, 1.0f, true))
|
2014-12-18 11:47:58 +01:00
|
|
|
{
|
2015-01-12 13:20:54 +01:00
|
|
|
for( i = 0; i < nPoints; ++i )
|
|
|
|
{
|
|
|
|
const Point& rPt1 = rPolygon.GetPoint( i );
|
|
|
|
const Point& rPt2 = rPolygon.GetPoint(( i + 1 ) % nPoints );
|
2016-05-19 21:35:28 +09:00
|
|
|
DrawLineSegment(rPt1.getX(), rPt1.getY(), rPt2.getX(), rPt2.getY());
|
2015-01-12 13:20:54 +01:00
|
|
|
}
|
|
|
|
UseSolid( lastSolidColor, lastSolidTransparency );
|
2014-12-18 11:47:58 +01:00
|
|
|
}
|
|
|
|
}
|
2014-11-11 05:13:40 -05:00
|
|
|
}
|
|
|
|
|
2015-01-18 22:42:06 +01:00
|
|
|
void OpenGLSalGraphicsImpl::DrawTrapezoid( const basegfx::B2DTrapezoid& trapezoid, bool blockAA )
|
2015-01-18 19:00:32 +01:00
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2015-01-18 19:00:32 +01:00
|
|
|
const basegfx::B2DPolygon& rPolygon = trapezoid.getB2DPolygon();
|
|
|
|
sal_uInt16 nPoints = rPolygon.count();
|
|
|
|
std::vector<GLfloat> aVertices(nPoints * 2);
|
|
|
|
sal_uInt32 i, j;
|
|
|
|
|
|
|
|
for( i = 0, j = 0; i < nPoints; i++, j += 2 )
|
|
|
|
{
|
|
|
|
const basegfx::B2DPoint& rPt = rPolygon.getB2DPoint( i );
|
2015-07-08 18:43:32 +09:00
|
|
|
aVertices[j] = GLfloat(rPt.getX());
|
|
|
|
aVertices[j+1] = GLfloat(rPt.getY());
|
2015-01-18 19:00:32 +01:00
|
|
|
}
|
|
|
|
|
2015-09-10 11:40:33 +02:00
|
|
|
if (!mpProgram)
|
|
|
|
{
|
|
|
|
SAL_WARN("vcl.opengl", "OpenGLSalGraphicsImpl::DrawTrapezoid: mpProgram is 0");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-07-08 18:43:32 +09:00
|
|
|
ApplyProgramMatrices();
|
2016-05-27 17:54:50 +09:00
|
|
|
std::vector<GLfloat> aExtrusion(nPoints * 3, 0);
|
|
|
|
mpProgram->SetExtrusionVectors(aExtrusion.data());
|
2016-05-12 13:37:11 +09:00
|
|
|
mpProgram->DrawArrays(GL_TRIANGLE_FAN, aVertices);
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2015-01-18 19:00:32 +01:00
|
|
|
|
2015-01-18 22:42:06 +01:00
|
|
|
if( !blockAA && mrParent.getAntiAliasB2DDraw())
|
2015-01-18 19:00:32 +01:00
|
|
|
{
|
|
|
|
// Make the edges antialiased by drawing the edge lines again with AA.
|
|
|
|
// TODO: If transparent drawing is set up, drawing the lines themselves twice
|
|
|
|
// may be a problem, if that is a real problem, the polygon areas itself needs to be
|
|
|
|
// masked out for this or something.
|
|
|
|
#ifdef DBG_UTIL
|
|
|
|
assert( mProgramIsSolidColor );
|
|
|
|
#endif
|
2018-03-14 11:11:02 +02:00
|
|
|
Color lastSolidColor = mProgramSolidColor;
|
2015-01-18 19:00:32 +01:00
|
|
|
double lastSolidTransparency = mProgramSolidTransparency;
|
2016-05-20 14:59:24 +09:00
|
|
|
if (UseLine(lastSolidColor, lastSolidTransparency, 1.0f, true))
|
2015-01-18 19:00:32 +01:00
|
|
|
{
|
|
|
|
for( i = 0; i < nPoints; ++i )
|
|
|
|
{
|
|
|
|
const basegfx::B2DPoint& rPt1 = rPolygon.getB2DPoint( i );
|
|
|
|
const basegfx::B2DPoint& rPt2 = rPolygon.getB2DPoint(( i + 1 ) % nPoints );
|
2016-05-19 21:35:28 +09:00
|
|
|
DrawLineSegment(rPt1.getX(), rPt1.getY(), rPt2.getX(), rPt2.getY());
|
2015-01-18 19:00:32 +01:00
|
|
|
}
|
|
|
|
UseSolid( lastSolidColor, lastSolidTransparency );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-29 13:05:02 -04:00
|
|
|
void OpenGLSalGraphicsImpl::DrawRect( long nX, long nY, long nWidth, long nHeight )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2018-04-07 11:45:13 +02:00
|
|
|
long nX1( nX );
|
|
|
|
long nY1( nY );
|
|
|
|
long nX2( nX + nWidth );
|
|
|
|
long nY2( nY + nHeight );
|
2014-10-29 13:05:02 -04:00
|
|
|
const SalPoint aPoints[] = { { nX1, nY2 }, { nX1, nY1 },
|
|
|
|
{ nX2, nY1 }, { nX2, nY2 }};
|
|
|
|
|
2015-01-18 18:58:20 +01:00
|
|
|
DrawConvexPolygon( 4, aPoints, true );
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
2017-03-30 20:27:55 +02:00
|
|
|
void OpenGLSalGraphicsImpl::DrawRect( const tools::Rectangle& rRect )
|
2014-11-11 15:54:03 -05:00
|
|
|
{
|
2018-04-07 11:45:13 +02:00
|
|
|
long nX1( rRect.Left() );
|
|
|
|
long nY1( rRect.Top() );
|
|
|
|
long nX2( rRect.Right() );
|
|
|
|
long nY2( rRect.Bottom() );
|
2014-11-11 15:54:03 -05:00
|
|
|
const SalPoint aPoints[] = { { nX1, nY2 }, { nX1, nY1 },
|
|
|
|
{ nX2, nY1 }, { nX2, nY2 }};
|
|
|
|
|
2015-01-18 18:58:20 +01:00
|
|
|
DrawConvexPolygon( 4, aPoints, true );
|
2014-11-11 15:54:03 -05:00
|
|
|
}
|
|
|
|
|
2014-10-29 13:05:02 -04:00
|
|
|
void OpenGLSalGraphicsImpl::DrawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2015-12-15 15:31:50 +02:00
|
|
|
basegfx::B2DPolygon aPolygon;
|
2014-10-29 13:05:02 -04:00
|
|
|
|
|
|
|
for( sal_uInt32 i = 0; i < nPoints; i++ )
|
2015-12-15 15:31:50 +02:00
|
|
|
aPolygon.append( basegfx::B2DPoint( pPtAry[i].mnX, pPtAry[i].mnY ) );
|
2014-10-29 13:05:02 -04:00
|
|
|
aPolygon.setClosed( true );
|
|
|
|
|
2017-09-22 14:12:07 +03:00
|
|
|
if( basegfx::utils::isConvex( aPolygon ) )
|
2014-10-29 13:05:02 -04:00
|
|
|
{
|
2017-08-16 16:27:55 +02:00
|
|
|
if( nPoints > 2 )
|
2014-10-29 13:05:02 -04:00
|
|
|
DrawConvexPolygon( nPoints, pPtAry );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-12-15 15:31:50 +02:00
|
|
|
const basegfx::B2DPolyPolygon aPolyPolygon( aPolygon );
|
2015-01-12 13:20:54 +01:00
|
|
|
DrawPolyPolygon( aPolyPolygon );
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
2015-01-12 13:20:54 +01:00
|
|
|
void OpenGLSalGraphicsImpl::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon, bool blockAA )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2017-09-22 14:12:07 +03:00
|
|
|
const basegfx::B2DPolyPolygon& aSimplePolyPolygon = ::basegfx::utils::solveCrossovers( rPolyPolygon );
|
2015-01-18 22:42:06 +01:00
|
|
|
basegfx::B2DTrapezoidVector aB2DTrapVector;
|
2017-09-22 14:12:07 +03:00
|
|
|
basegfx::utils::trapezoidSubdivide( aB2DTrapVector, aSimplePolyPolygon );
|
2018-01-17 19:39:12 +01:00
|
|
|
// draw tessellation result
|
2019-08-20 15:54:28 +02:00
|
|
|
for(const basegfx::B2DTrapezoid & i : aB2DTrapVector)
|
2018-11-28 15:13:42 +02:00
|
|
|
DrawTrapezoid( i, blockAA );
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
2014-11-22 08:09:29 -05:00
|
|
|
void OpenGLSalGraphicsImpl::DrawRegionBand( const RegionBand& rRegion )
|
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2014-11-22 08:09:29 -05:00
|
|
|
RectangleVector aRects;
|
|
|
|
std::vector<GLfloat> aVertices;
|
|
|
|
rRegion.GetRegionRectangles( aRects );
|
|
|
|
|
|
|
|
if( aRects.empty() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
#define ADD_VERTICE(pt) \
|
2015-07-08 18:43:32 +09:00
|
|
|
aVertices.push_back(GLfloat(pt.X())); \
|
|
|
|
aVertices.push_back(GLfloat(pt.Y()));
|
2014-11-22 08:09:29 -05:00
|
|
|
|
2017-03-30 20:27:55 +02:00
|
|
|
for(tools::Rectangle & rRect : aRects)
|
2014-11-22 08:09:29 -05:00
|
|
|
{
|
2018-02-21 15:56:58 +02:00
|
|
|
rRect.AdjustBottom(1 );
|
|
|
|
rRect.AdjustRight(1 );
|
2016-05-12 10:06:27 +02:00
|
|
|
ADD_VERTICE( rRect.TopLeft() );
|
|
|
|
ADD_VERTICE( rRect.TopRight() );
|
|
|
|
ADD_VERTICE( rRect.BottomLeft() );
|
|
|
|
ADD_VERTICE( rRect.BottomLeft() );
|
|
|
|
ADD_VERTICE( rRect.TopRight() );
|
|
|
|
ADD_VERTICE( rRect.BottomRight() );
|
2014-11-22 08:09:29 -05:00
|
|
|
}
|
|
|
|
#undef ADD_VERTICE
|
2016-05-27 17:54:50 +09:00
|
|
|
std::vector<GLfloat> aExtrusion(aRects.size() * 6 * 3, 0);
|
|
|
|
mpProgram->SetExtrusionVectors(aExtrusion.data());
|
2015-07-08 18:43:32 +09:00
|
|
|
ApplyProgramMatrices();
|
2016-05-12 13:37:11 +09:00
|
|
|
mpProgram->DrawArrays(GL_TRIANGLES, aVertices);
|
2015-03-20 13:42:56 +01:00
|
|
|
CHECK_GL_ERROR();
|
2014-11-22 08:09:29 -05:00
|
|
|
}
|
|
|
|
|
2017-04-25 15:09:53 +02:00
|
|
|
void OpenGLSalGraphicsImpl::DrawTextureRect( const SalTwoRect& rPosAry )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2015-01-27 04:31:56 +01:00
|
|
|
SAL_INFO("vcl.opengl", "draw texture rect");
|
|
|
|
|
2016-05-27 19:43:12 +09:00
|
|
|
long nX = rPosAry.mnDestX;
|
|
|
|
long nY = rPosAry.mnDestY;
|
|
|
|
long nWidth = rPosAry.mnDestWidth;
|
|
|
|
long nHeight = rPosAry.mnDestHeight;
|
|
|
|
|
|
|
|
std::vector<GLfloat> aVertices;
|
|
|
|
aVertices.reserve(8);
|
|
|
|
vcl::vertex::addRectangle<GL_TRIANGLE_FAN>(aVertices, nX, nY, nX + nWidth, nY + nHeight);
|
|
|
|
|
|
|
|
ApplyProgramMatrices();
|
|
|
|
mpProgram->DrawArrays(GL_TRIANGLE_FAN, aVertices);
|
|
|
|
CHECK_GL_ERROR();
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
2016-05-27 17:54:50 +09:00
|
|
|
void OpenGLSalGraphicsImpl::DrawTexture( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2015-01-27 04:31:56 +01:00
|
|
|
SAL_INFO("vcl.opengl", "draw texture");
|
|
|
|
|
2016-05-20 14:59:24 +09:00
|
|
|
if (!UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader"))
|
2014-11-28 14:56:08 -05:00
|
|
|
return;
|
2016-05-20 14:59:24 +09:00
|
|
|
mpProgram->SetShaderType(TextureShaderType::Normal);
|
|
|
|
mpProgram->SetIdentityTransform("transform");
|
|
|
|
mpProgram->SetTexture("texture", rTexture);
|
2016-05-27 17:54:50 +09:00
|
|
|
|
|
|
|
GLfloat aTexCoord[8];
|
|
|
|
rTexture.GetCoord(aTexCoord, rPosAry, bInverted);
|
|
|
|
mpProgram->SetTextureCoord(aTexCoord);
|
|
|
|
mpProgram->SetMaskCoord(aTexCoord);
|
|
|
|
mpProgram->SetAlphaCoord(aTexCoord);
|
|
|
|
|
2017-04-25 15:09:53 +02:00
|
|
|
DrawTextureRect( rPosAry );
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->Clean();
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
|
2016-04-06 13:59:50 +02:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
bool scaleTexture(const rtl::Reference< OpenGLContext > &xContext,
|
|
|
|
OpenGLTexture& rOutTexture, const double& ixscale, const double& iyscale, OpenGLTexture& rTexture)
|
|
|
|
{
|
|
|
|
int nWidth = rTexture.GetWidth();
|
|
|
|
int nHeight = rTexture.GetHeight();
|
2019-07-20 14:51:52 +01:00
|
|
|
if (nWidth == 0 || nHeight == 0)
|
|
|
|
return false;
|
|
|
|
|
2016-04-06 13:59:50 +02:00
|
|
|
int nNewWidth = nWidth / ixscale;
|
|
|
|
int nNewHeight = nHeight / iyscale;
|
|
|
|
|
2016-11-03 23:11:18 +01:00
|
|
|
OString sUseReducedRegisterVariantDefine;
|
|
|
|
if (xContext->getOpenGLCapabilitySwitch().mbLimitedShaderRegisters)
|
|
|
|
sUseReducedRegisterVariantDefine = OString("#define USE_REDUCED_REGISTER_VARIANT\n");
|
|
|
|
|
|
|
|
OpenGLProgram* pProgram = xContext->UseProgram("textureVertexShader", "areaScaleFragmentShader", sUseReducedRegisterVariantDefine);
|
2016-04-06 13:59:50 +02:00
|
|
|
if (pProgram == nullptr)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
OpenGLTexture aScratchTex(nNewWidth, nNewHeight);
|
|
|
|
OpenGLFramebuffer* pFramebuffer = xContext->AcquireFramebuffer(aScratchTex);
|
|
|
|
|
2019-04-14 19:03:45 +02:00
|
|
|
// From OpenGLSalBitmap::ImplScaleArea().
|
2016-04-06 13:59:50 +02:00
|
|
|
pProgram->SetUniform1f("xscale", ixscale);
|
|
|
|
pProgram->SetUniform1f("yscale", iyscale);
|
|
|
|
pProgram->SetUniform1i("swidth", nWidth);
|
|
|
|
pProgram->SetUniform1i("sheight", nHeight);
|
2019-04-14 19:03:45 +02:00
|
|
|
// For converting between <0,nWidth> and <0.0,1.0> coordinate systems.
|
|
|
|
GLfloat srcCoords[ 8 ];
|
|
|
|
rTexture.GetWholeCoord( srcCoords );
|
|
|
|
pProgram->SetUniform1f( "xoffset", srcCoords[ 0 ] );
|
|
|
|
pProgram->SetUniform1f( "yoffset", srcCoords[ 1 ] );
|
|
|
|
pProgram->SetUniform1f( "xtopixelratio", nNewWidth / ( srcCoords[ 4 ] - srcCoords[ 0 ] ));
|
|
|
|
pProgram->SetUniform1f( "ytopixelratio", nNewHeight / ( srcCoords[ 5 ] - srcCoords[ 1 ] ));
|
|
|
|
pProgram->SetUniform1f( "xfrompixelratio", ( srcCoords[ 4 ] - srcCoords[ 0 ] ) / nWidth );
|
|
|
|
pProgram->SetUniform1f( "yfrompixelratio", ( srcCoords[ 5 ] - srcCoords[ 1 ] ) / nHeight );
|
2016-04-06 13:59:50 +02:00
|
|
|
|
|
|
|
pProgram->SetTexture("sampler", rTexture);
|
|
|
|
pProgram->DrawTexture(rTexture);
|
|
|
|
pProgram->Clean();
|
|
|
|
|
|
|
|
OpenGLContext::ReleaseFramebuffer(pFramebuffer);
|
|
|
|
|
|
|
|
CHECK_GL_ERROR();
|
|
|
|
|
|
|
|
rOutTexture = aScratchTex;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-11-17 09:15:15 -05:00
|
|
|
void OpenGLSalGraphicsImpl::DrawTransformedTexture(
|
|
|
|
OpenGLTexture& rTexture,
|
|
|
|
OpenGLTexture& rMask,
|
|
|
|
const basegfx::B2DPoint& rNull,
|
|
|
|
const basegfx::B2DPoint& rX,
|
|
|
|
const basegfx::B2DPoint& rY )
|
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2016-05-12 13:37:11 +09:00
|
|
|
std::vector<GLfloat> aVertices = {
|
|
|
|
0, GLfloat(rTexture.GetHeight()),
|
|
|
|
0, 0,
|
|
|
|
GLfloat(rTexture.GetWidth()), 0,
|
|
|
|
GLfloat(rTexture.GetWidth()), GLfloat(rTexture.GetHeight())
|
|
|
|
};
|
|
|
|
|
2014-11-17 09:15:15 -05:00
|
|
|
GLfloat aTexCoord[8];
|
|
|
|
|
2016-02-11 15:57:27 +01:00
|
|
|
const long nDestWidth = basegfx::fround(basegfx::B2DVector(rX - rNull).getLength());
|
|
|
|
const long nDestHeight = basegfx::fround(basegfx::B2DVector(rY - rNull).getLength());
|
|
|
|
|
2016-02-11 17:35:20 +00:00
|
|
|
// Invisibly small images shouldn't divide by zero.
|
|
|
|
if( nDestHeight == 0 || nDestWidth == 0 )
|
|
|
|
return;
|
|
|
|
|
2016-04-06 13:59:50 +02:00
|
|
|
// inverted scale ratios
|
|
|
|
double ixscale = rTexture.GetWidth() / double(nDestWidth);
|
|
|
|
double iyscale = rTexture.GetHeight() / double(nDestHeight);
|
2016-02-11 15:57:27 +01:00
|
|
|
|
2016-04-06 13:59:50 +02:00
|
|
|
// If downscaling at a higher scale ratio, use the area scaling algorithm rather
|
|
|
|
// than plain OpenGL's scaling (texture mapping), for better results.
|
|
|
|
// See OpenGLSalBitmap::ImplScaleArea().
|
2015-01-20 15:41:51 +01:00
|
|
|
bool areaScaling = false;
|
|
|
|
bool fastAreaScaling = false;
|
2016-11-03 23:11:18 +01:00
|
|
|
|
|
|
|
OString sUseReducedRegisterVariantDefine;
|
|
|
|
if (mpContext->getOpenGLCapabilitySwitch().mbLimitedShaderRegisters)
|
|
|
|
sUseReducedRegisterVariantDefine = OString("#define USE_REDUCED_REGISTER_VARIANT\n");
|
|
|
|
|
2015-01-20 15:41:51 +01:00
|
|
|
OUString textureFragmentShader;
|
2016-04-06 13:59:50 +02:00
|
|
|
if( ixscale >= 2 && iyscale >= 2 ) // scale ratio less than 50%
|
2015-01-20 15:41:51 +01:00
|
|
|
{
|
|
|
|
areaScaling = true;
|
2018-05-16 10:16:01 +02:00
|
|
|
fastAreaScaling = ( ixscale == std::trunc( ixscale ) && iyscale == std::trunc( iyscale ));
|
2016-04-06 13:59:50 +02:00
|
|
|
// The generic case has arrays only up to 16 ratio downscaling and is performed in 2 passes,
|
|
|
|
// when the ratio is in the 16-100 range, which is hopefully enough in practice, but protect
|
|
|
|
// against buffer overflows in case such an extreme case happens (and in such case the precision
|
|
|
|
// of the generic algorithm probably doesn't matter anyway).
|
2015-01-20 15:41:51 +01:00
|
|
|
if( ixscale > 100 || iyscale > 100 )
|
|
|
|
fastAreaScaling = true;
|
|
|
|
if( fastAreaScaling )
|
|
|
|
textureFragmentShader = "areaScaleFastFragmentShader";
|
|
|
|
else
|
|
|
|
textureFragmentShader = "areaScaleFragmentShader";
|
|
|
|
}
|
|
|
|
|
2016-04-06 13:59:50 +02:00
|
|
|
OpenGLTexture aInTexture = rTexture;
|
|
|
|
OpenGLTexture aInMask = rMask;
|
|
|
|
|
|
|
|
// When using the area scaling algorithm we need to reduce the texture size in 2 passes
|
|
|
|
// in order to not use a big array inside the fragment shader.
|
|
|
|
if (areaScaling && !fastAreaScaling)
|
|
|
|
{
|
|
|
|
// Perform a first texture downscaling by an inverted scale ratio equal to
|
|
|
|
// the square root of the whole inverted scale ratio.
|
|
|
|
if (ixscale > 16 || iyscale > 16)
|
|
|
|
{
|
|
|
|
// The scissor area is set to the current window size in PreDraw,
|
|
|
|
// so if we do not disable the scissor test, the texture produced
|
|
|
|
// by the first downscaling is clipped to the current window size.
|
2016-11-28 16:39:26 +01:00
|
|
|
mpContext->state().scissor().disable();
|
|
|
|
mpContext->state().stencil().disable();
|
2016-04-06 13:59:50 +02:00
|
|
|
|
|
|
|
// the square root of the whole inverted scale ratio
|
|
|
|
double ixscalesqrt = std::floor(std::sqrt(ixscale));
|
|
|
|
double iyscalesqrt = std::floor(std::sqrt(iyscale));
|
|
|
|
ixscale /= ixscalesqrt; // second pass inverted x-scale factor
|
|
|
|
iyscale /= iyscalesqrt; // second pass inverted y-scale factor
|
|
|
|
|
|
|
|
scaleTexture(mpContext, aInTexture, ixscalesqrt, iyscalesqrt, rTexture);
|
|
|
|
|
|
|
|
if (rMask) // we need to downscale the mask too
|
|
|
|
{
|
|
|
|
scaleTexture(mpContext, aInMask, ixscalesqrt, iyscalesqrt, rMask);
|
|
|
|
}
|
|
|
|
|
|
|
|
// We need to re-acquire the off-screen texture.
|
|
|
|
CheckOffscreenTexture();
|
|
|
|
CHECK_GL_ERROR();
|
|
|
|
|
|
|
|
// Re-enable scissor and stencil tests if needed.
|
|
|
|
if (mbUseScissor)
|
2016-11-28 16:39:26 +01:00
|
|
|
mpContext->state().scissor().enable();
|
2016-04-28 19:34:37 +09:00
|
|
|
|
2016-04-06 13:59:50 +02:00
|
|
|
if (mbUseStencil)
|
2016-11-28 16:39:26 +01:00
|
|
|
mpContext->state().stencil().enable();
|
2016-04-06 13:59:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( aInMask )
|
2014-11-17 09:15:15 -05:00
|
|
|
{
|
2015-01-20 15:41:51 +01:00
|
|
|
if( !UseProgram( "transformedTextureVertexShader",
|
|
|
|
textureFragmentShader.isEmpty() ? "maskedTextureFragmentShader" : textureFragmentShader,
|
2016-11-03 23:11:18 +01:00
|
|
|
"#define MASKED\n" + sUseReducedRegisterVariantDefine))
|
2014-11-28 14:56:08 -05:00
|
|
|
return;
|
2016-04-06 13:59:50 +02:00
|
|
|
mpProgram->SetTexture( "mask", aInMask );
|
2015-08-24 15:00:26 +09:00
|
|
|
GLfloat aMaskCoord[8];
|
2016-04-06 13:59:50 +02:00
|
|
|
aInMask.GetWholeCoord(aMaskCoord);
|
2015-08-24 15:00:26 +09:00
|
|
|
mpProgram->SetMaskCoord(aMaskCoord);
|
2016-04-06 13:59:50 +02:00
|
|
|
aInMask.SetFilter( GL_LINEAR );
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
2014-11-17 09:15:15 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-01-20 15:41:51 +01:00
|
|
|
if( !UseProgram( "transformedTextureVertexShader",
|
2016-11-03 23:11:18 +01:00
|
|
|
textureFragmentShader.isEmpty() ? "textureFragmentShader" : textureFragmentShader,
|
|
|
|
sUseReducedRegisterVariantDefine))
|
2014-11-28 14:56:08 -05:00
|
|
|
return;
|
2014-11-17 09:15:15 -05:00
|
|
|
}
|
|
|
|
|
2016-04-06 13:59:50 +02:00
|
|
|
if(areaScaling)
|
2015-01-20 15:41:51 +01:00
|
|
|
{
|
2016-04-06 13:59:50 +02:00
|
|
|
int nWidth = aInTexture.GetWidth();
|
|
|
|
int nHeight = aInTexture.GetHeight();
|
|
|
|
|
2015-01-20 15:41:51 +01:00
|
|
|
// From OpenGLSalBitmap::ImplScaleArea().
|
2016-04-06 13:59:50 +02:00
|
|
|
if (fastAreaScaling && nWidth && nHeight)
|
2015-01-20 15:41:51 +01:00
|
|
|
{
|
|
|
|
mpProgram->SetUniform1i( "xscale", ixscale );
|
|
|
|
mpProgram->SetUniform1i( "yscale", iyscale );
|
2019-04-14 19:03:45 +02:00
|
|
|
GLfloat srcCoords[ 8 ];
|
|
|
|
aInTexture.GetWholeCoord( srcCoords );
|
|
|
|
mpProgram->SetUniform1f( "xstep", ( srcCoords[ 4 ] - srcCoords[ 0 ] ) / nWidth );
|
|
|
|
mpProgram->SetUniform1f( "ystep", ( srcCoords[ 5 ] - srcCoords[ 1 ] ) / nHeight );
|
2015-01-20 15:41:51 +01:00
|
|
|
mpProgram->SetUniform1f( "ratio", 1.0 / ( ixscale * iyscale ));
|
|
|
|
}
|
2016-04-06 13:59:50 +02:00
|
|
|
else if (nHeight > 1 && nWidth > 1)
|
2015-01-20 15:41:51 +01:00
|
|
|
{
|
|
|
|
mpProgram->SetUniform1f( "xscale", ixscale );
|
|
|
|
mpProgram->SetUniform1f( "yscale", iyscale );
|
2016-04-06 13:59:50 +02:00
|
|
|
mpProgram->SetUniform1i( "swidth", nWidth );
|
|
|
|
mpProgram->SetUniform1i( "sheight", nHeight );
|
|
|
|
// For converting between <0,nWidth-1> and <0.0,1.0> coordinate systems.
|
2019-04-14 19:03:45 +02:00
|
|
|
GLfloat srcCoords[ 8 ];
|
|
|
|
aInTexture.GetWholeCoord( srcCoords );
|
|
|
|
mpProgram->SetUniform1f( "xoffset", srcCoords[ 0 ] );
|
|
|
|
mpProgram->SetUniform1f( "yoffset", srcCoords[ 1 ] );
|
|
|
|
mpProgram->SetUniform1f( "xtopixelratio", ( nWidth / ixscale ) / ( srcCoords[ 4 ] - srcCoords[ 0 ] ));
|
|
|
|
mpProgram->SetUniform1f( "ytopixelratio", ( nHeight / iyscale ) / ( srcCoords[ 5 ] - srcCoords[ 1 ] ));
|
|
|
|
mpProgram->SetUniform1f( "xfrompixelratio", ( srcCoords[ 4 ] - srcCoords[ 0 ] ) / nWidth );
|
|
|
|
mpProgram->SetUniform1f( "yfrompixelratio", ( srcCoords[ 5 ] - srcCoords[ 1 ] ) / nHeight );
|
2015-01-20 15:41:51 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-08 18:43:32 +09:00
|
|
|
ApplyProgramMatrices();
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetUniform2f( "viewport", GetWidth(), GetHeight() );
|
2016-04-06 13:59:50 +02:00
|
|
|
// Here, in order to get the correct transformation we need to pass the original texture,
|
|
|
|
// since it has been used for initializing the rectangle vertices.
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetTransform( "transform", rTexture, rNull, rX, rY );
|
2016-04-06 13:59:50 +02:00
|
|
|
aInTexture.GetWholeCoord(aTexCoord);
|
|
|
|
mpProgram->SetTexture("sampler", aInTexture);
|
|
|
|
aInTexture.SetFilter(GL_LINEAR);
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetTextureCoord( aTexCoord );
|
2016-05-12 13:37:11 +09:00
|
|
|
mpProgram->DrawArrays(GL_TRIANGLE_FAN, aVertices);
|
2016-04-06 13:59:50 +02:00
|
|
|
|
2015-03-20 13:42:56 +01:00
|
|
|
CHECK_GL_ERROR();
|
2015-11-17 09:20:25 +02:00
|
|
|
mpProgram->Clean();
|
2014-11-17 09:15:15 -05:00
|
|
|
}
|
|
|
|
|
2014-11-13 22:24:35 -05:00
|
|
|
void OpenGLSalGraphicsImpl::DrawAlphaTexture( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted, bool bPremultiplied )
|
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2016-05-20 14:59:24 +09:00
|
|
|
if (!UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader"))
|
2014-11-28 14:56:08 -05:00
|
|
|
return;
|
2016-05-20 14:59:24 +09:00
|
|
|
mpProgram->SetShaderType(TextureShaderType::Normal);
|
|
|
|
mpProgram->SetIdentityTransform("transform");
|
|
|
|
mpProgram->SetTexture("texture", rTexture);
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetBlendMode( bPremultiplied ? GL_ONE : GL_SRC_ALPHA,
|
|
|
|
GL_ONE_MINUS_SRC_ALPHA );
|
2016-05-27 17:54:50 +09:00
|
|
|
|
|
|
|
GLfloat aTexCoord[8];
|
|
|
|
rTexture.GetCoord(aTexCoord, rPosAry, bInverted);
|
|
|
|
mpProgram->SetTextureCoord(aTexCoord);
|
|
|
|
mpProgram->SetMaskCoord(aTexCoord);
|
|
|
|
mpProgram->SetAlphaCoord(aTexCoord);
|
|
|
|
|
2017-04-25 15:09:53 +02:00
|
|
|
DrawTextureRect( rPosAry );
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->Clean();
|
2014-11-20 22:07:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLSalGraphicsImpl::DrawTextureDiff( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& rPosAry, bool bInverted )
|
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2016-05-20 14:59:24 +09:00
|
|
|
if (!UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader"))
|
2014-11-28 14:56:08 -05:00
|
|
|
return;
|
2016-05-20 14:59:24 +09:00
|
|
|
mpProgram->SetShaderType(TextureShaderType::Diff);
|
|
|
|
mpProgram->SetIdentityTransform("transform");
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetTexture( "texture", rTexture );
|
|
|
|
mpProgram->SetTexture( "mask", rMask );
|
|
|
|
mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
2015-08-24 15:00:26 +09:00
|
|
|
|
2016-05-27 17:54:50 +09:00
|
|
|
GLfloat aTexCoord[8];
|
|
|
|
rTexture.GetCoord(aTexCoord, rPosAry, bInverted);
|
|
|
|
mpProgram->SetTextureCoord(aTexCoord);
|
|
|
|
mpProgram->SetAlphaCoord(aTexCoord);
|
|
|
|
|
2015-08-24 15:00:26 +09:00
|
|
|
GLfloat aMaskCoord[8];
|
|
|
|
rMask.GetCoord(aMaskCoord, rPosAry, bInverted);
|
|
|
|
mpProgram->SetMaskCoord(aMaskCoord);
|
|
|
|
|
2017-04-25 15:09:53 +02:00
|
|
|
DrawTextureRect( rPosAry );
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->Clean();
|
2014-11-13 22:24:35 -05:00
|
|
|
}
|
|
|
|
|
2015-08-24 15:00:26 +09:00
|
|
|
void OpenGLSalGraphicsImpl::DrawTextureWithMask( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& rPosAry )
|
2014-10-29 13:05:02 -04:00
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2016-05-20 14:59:24 +09:00
|
|
|
if (!UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader"))
|
2014-11-28 14:56:08 -05:00
|
|
|
return;
|
2016-05-20 14:59:24 +09:00
|
|
|
mpProgram->SetShaderType(TextureShaderType::Masked);
|
|
|
|
mpProgram->SetIdentityTransform("transform");
|
|
|
|
mpProgram->SetTexture( "texture", rTexture );
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetTexture( "mask", rMask );
|
|
|
|
mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
2015-08-24 15:00:26 +09:00
|
|
|
|
|
|
|
GLfloat aTexCoord[8];
|
|
|
|
rTexture.GetCoord(aTexCoord, rPosAry);
|
|
|
|
mpProgram->SetTextureCoord(aTexCoord);
|
2016-05-27 17:54:50 +09:00
|
|
|
mpProgram->SetAlphaCoord(aTexCoord);
|
2015-08-24 15:00:26 +09:00
|
|
|
|
|
|
|
GLfloat aMaskCoord[8];
|
|
|
|
rMask.GetCoord(aMaskCoord, rPosAry);
|
|
|
|
mpProgram->SetMaskCoord(aMaskCoord);
|
|
|
|
|
2017-04-25 15:09:53 +02:00
|
|
|
DrawTextureRect(rPosAry);
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->Clean();
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
2014-11-18 12:34:53 -05:00
|
|
|
void OpenGLSalGraphicsImpl::DrawBlendedTexture( OpenGLTexture& rTexture, OpenGLTexture& rMask, OpenGLTexture& rAlpha, const SalTwoRect& rPosAry )
|
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2016-05-20 14:59:24 +09:00
|
|
|
if (!UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader"))
|
2014-11-28 14:56:08 -05:00
|
|
|
return;
|
2016-05-20 14:59:24 +09:00
|
|
|
mpProgram->SetShaderType(TextureShaderType::Blend);
|
|
|
|
mpProgram->SetTexture( "texture", rTexture );
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetTexture( "mask", rMask );
|
|
|
|
mpProgram->SetTexture( "alpha", rAlpha );
|
2015-08-24 15:00:26 +09:00
|
|
|
|
2016-05-27 17:54:50 +09:00
|
|
|
GLfloat aTexCoord[8];
|
|
|
|
rTexture.GetCoord(aTexCoord, rPosAry);
|
|
|
|
mpProgram->SetTextureCoord(aTexCoord);
|
|
|
|
|
2015-08-24 15:00:26 +09:00
|
|
|
GLfloat aAlphaCoord[8];
|
|
|
|
rAlpha.GetCoord(aAlphaCoord, rPosAry);
|
|
|
|
mpProgram->SetAlphaCoord(aAlphaCoord);
|
|
|
|
|
|
|
|
GLfloat aMaskCoord[8];
|
|
|
|
rMask.GetCoord(aMaskCoord, rPosAry);
|
|
|
|
mpProgram->SetMaskCoord(aMaskCoord);
|
|
|
|
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
2017-04-25 15:09:53 +02:00
|
|
|
DrawTextureRect( rPosAry );
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->Clean();
|
2014-11-18 12:34:53 -05:00
|
|
|
}
|
|
|
|
|
2018-03-14 11:11:02 +02:00
|
|
|
void OpenGLSalGraphicsImpl::DrawMask( OpenGLTexture& rMask, Color nMaskColor, const SalTwoRect& rPosAry )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2016-05-20 14:59:24 +09:00
|
|
|
if (!UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader"))
|
2014-11-28 14:56:08 -05:00
|
|
|
return;
|
2016-05-20 14:59:24 +09:00
|
|
|
mpProgram->SetShaderType(TextureShaderType::MaskedColor);
|
|
|
|
mpProgram->SetIdentityTransform("transform");
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetColor( "color", nMaskColor, 0 );
|
2016-05-20 14:59:24 +09:00
|
|
|
mpProgram->SetTexture("texture", rMask);
|
2016-05-27 17:54:50 +09:00
|
|
|
|
|
|
|
GLfloat aTexCoord[8];
|
|
|
|
rMask.GetCoord(aTexCoord, rPosAry);
|
|
|
|
mpProgram->SetTextureCoord(aTexCoord);
|
|
|
|
mpProgram->SetMaskCoord(aTexCoord);
|
|
|
|
mpProgram->SetAlphaCoord(aTexCoord);
|
|
|
|
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
2017-04-25 15:09:53 +02:00
|
|
|
DrawTextureRect(rPosAry);
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->Clean();
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
2014-10-29 13:05:02 -04:00
|
|
|
|
2018-03-14 11:11:02 +02:00
|
|
|
void OpenGLSalGraphicsImpl::DeferredTextDraw(OpenGLTexture const & rTexture, Color aMaskColor, const SalTwoRect& rPosAry)
|
2016-03-14 11:20:19 +01:00
|
|
|
{
|
2016-05-31 12:26:04 +09:00
|
|
|
mpRenderList->addDrawTextureWithMaskColor(rTexture, aMaskColor, rPosAry);
|
2016-06-24 16:42:45 +08:00
|
|
|
PostBatchDraw();
|
2016-03-14 11:20:19 +01:00
|
|
|
}
|
|
|
|
|
2018-01-22 15:52:16 +02:00
|
|
|
void OpenGLSalGraphicsImpl::FlushLinesOrTriangles(DrawShaderType eType, RenderParameters const & rParameters)
|
2016-06-07 20:45:14 +09:00
|
|
|
{
|
|
|
|
if (!UseProgram("combinedVertexShader", "combinedFragmentShader", "#define USE_VERTEX_COLORS"))
|
2018-01-22 15:52:16 +02:00
|
|
|
return;
|
2016-06-07 20:45:14 +09:00
|
|
|
|
|
|
|
mpProgram->SetShaderType(eType);
|
|
|
|
mpProgram->SetBlendMode(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
ApplyProgramMatrices(0.5f);
|
|
|
|
|
|
|
|
vcl::VertexBufferObject<Vertex> vbo;
|
|
|
|
vbo.upload(rParameters.maVertices);
|
|
|
|
|
|
|
|
GLuint positionAttrib = SAL_MAX_UINT32;
|
|
|
|
GLuint colorAttrib = SAL_MAX_UINT32;
|
|
|
|
GLuint lineDataAttrib = SAL_MAX_UINT32;
|
|
|
|
|
|
|
|
mpProgram->SetVertexAttrib(positionAttrib, "position", 2, GL_FLOAT, GL_FALSE,
|
|
|
|
sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
|
|
|
|
|
|
|
|
mpProgram->SetVertexAttrib(colorAttrib, "vertex_color_in", 4, GL_FLOAT, GL_FALSE,
|
|
|
|
sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, color)));
|
|
|
|
|
|
|
|
mpProgram->SetVertexAttrib(lineDataAttrib, "extrusion_vectors", 4, GL_FLOAT, GL_FALSE,
|
|
|
|
sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, lineData)));
|
|
|
|
|
|
|
|
vcl::IndexBufferObject ibo;
|
|
|
|
ibo.upload(rParameters.maIndices);
|
|
|
|
ibo.bind();
|
|
|
|
|
|
|
|
mpProgram->DrawElements(GL_TRIANGLES, rParameters.maIndices.size());
|
|
|
|
CHECK_GL_ERROR();
|
|
|
|
|
|
|
|
mpProgram->Clean();
|
|
|
|
}
|
|
|
|
|
2016-04-08 17:41:21 +09:00
|
|
|
void OpenGLSalGraphicsImpl::FlushDeferredDrawing()
|
2016-03-14 11:20:19 +01:00
|
|
|
{
|
2016-05-31 12:26:04 +09:00
|
|
|
if (mpRenderList->empty())
|
2016-03-14 11:20:19 +01:00
|
|
|
return;
|
|
|
|
|
2016-05-29 12:37:41 +09:00
|
|
|
VCL_GL_INFO("FlushDeferredDrawing: " << mpRenderList->getEntries().size());
|
2016-04-04 19:29:27 +09:00
|
|
|
|
2016-05-31 12:26:04 +09:00
|
|
|
InitializePreDrawState(XOROption::IMPLEMENT_XOR);
|
2016-03-14 11:20:19 +01:00
|
|
|
|
2016-05-31 12:26:04 +09:00
|
|
|
OpenGLZone aZone;
|
|
|
|
for (RenderEntry& rRenderEntry : mpRenderList->getEntries())
|
|
|
|
{
|
2016-06-07 20:45:14 +09:00
|
|
|
if (rRenderEntry.hasTriangles())
|
2016-03-14 11:20:19 +01:00
|
|
|
{
|
2016-05-31 12:26:04 +09:00
|
|
|
RenderParameters& rParameters = rRenderEntry.maTriangleParameters;
|
|
|
|
VCL_GL_INFO("Flush Triangles: " << rParameters.maVertices.size());
|
2016-06-07 20:45:14 +09:00
|
|
|
FlushLinesOrTriangles(DrawShaderType::Normal, rParameters);
|
2016-05-31 12:26:04 +09:00
|
|
|
}
|
2016-06-07 20:45:14 +09:00
|
|
|
if (rRenderEntry.hasLines())
|
2016-05-31 12:26:04 +09:00
|
|
|
{
|
|
|
|
RenderParameters& rParameters = rRenderEntry.maLineParameters;
|
|
|
|
VCL_GL_INFO("Flush Lines: " << rParameters.maVertices.size());
|
2016-06-07 20:45:14 +09:00
|
|
|
FlushLinesOrTriangles(DrawShaderType::Line, rParameters);
|
2016-05-31 12:26:04 +09:00
|
|
|
}
|
|
|
|
if (rRenderEntry.hasTextures() && UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader", "#define USE_VERTEX_COLORS"))
|
|
|
|
{
|
|
|
|
mpProgram->SetShaderType(TextureShaderType::MaskedColor);
|
|
|
|
mpProgram->SetIdentityTransform("transform");
|
|
|
|
mpProgram->SetBlendMode(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
|
|
|
for (auto& rPair : rRenderEntry.maTextureParametersMap)
|
2016-05-29 12:37:41 +09:00
|
|
|
{
|
2016-05-31 12:26:04 +09:00
|
|
|
RenderTextureParameters& rParameters = rPair.second;
|
|
|
|
mpProgram->SetTexture("texture", rParameters.maTexture);
|
2016-05-29 12:37:41 +09:00
|
|
|
ApplyProgramMatrices();
|
|
|
|
mpProgram->SetTextureCoord(rParameters.maTextureCoords.data());
|
|
|
|
mpProgram->SetMaskCoord(rParameters.maTextureCoords.data());
|
|
|
|
mpProgram->SetAlphaCoord(rParameters.maTextureCoords.data());
|
|
|
|
mpProgram->SetVertexColors(rParameters.maColors);
|
|
|
|
mpProgram->DrawArrays(GL_TRIANGLES, rParameters.maVertices);
|
|
|
|
CHECK_GL_ERROR();
|
|
|
|
}
|
2016-05-31 12:26:04 +09:00
|
|
|
mpProgram->Clean();
|
2016-03-14 11:20:19 +01:00
|
|
|
}
|
|
|
|
}
|
2016-04-08 17:41:21 +09:00
|
|
|
|
2016-05-31 12:26:04 +09:00
|
|
|
mpRenderList->clear();
|
|
|
|
PostDraw();
|
2016-05-29 12:37:41 +09:00
|
|
|
|
2016-05-31 12:26:04 +09:00
|
|
|
VCL_GL_INFO("End FlushDeferredDrawing");
|
2016-03-14 11:20:19 +01:00
|
|
|
}
|
|
|
|
|
2017-03-30 20:27:55 +02:00
|
|
|
void OpenGLSalGraphicsImpl::DrawLinearGradient( const Gradient& rGradient, const tools::Rectangle& rRect )
|
2014-11-11 05:13:40 -05:00
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2014-11-28 14:56:08 -05:00
|
|
|
if( !UseProgram( "textureVertexShader", "linearGradientFragmentShader" ) )
|
|
|
|
return;
|
2014-11-11 05:13:40 -05:00
|
|
|
Color aStartCol = rGradient.GetStartColor();
|
|
|
|
Color aEndCol = rGradient.GetEndColor();
|
|
|
|
long nFactor = rGradient.GetStartIntensity();
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetColorWithIntensity( "start_color", aStartCol, nFactor );
|
2014-11-11 05:13:40 -05:00
|
|
|
nFactor = rGradient.GetEndIntensity();
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetColorWithIntensity( "end_color", aEndCol, nFactor );
|
2014-11-11 05:13:40 -05:00
|
|
|
|
2017-03-30 20:27:55 +02:00
|
|
|
tools::Rectangle aBoundRect;
|
2014-11-11 05:13:40 -05:00
|
|
|
Point aCenter;
|
|
|
|
rGradient.GetBoundRect( rRect, aBoundRect, aCenter );
|
2015-08-16 16:45:12 -05:00
|
|
|
tools::Polygon aPoly( aBoundRect );
|
2014-11-11 05:13:40 -05:00
|
|
|
aPoly.Rotate( aCenter, rGradient.GetAngle() % 3600 );
|
|
|
|
|
|
|
|
GLfloat aTexCoord[8] = { 0, 1, 1, 1, 1, 0, 0, 0 };
|
|
|
|
GLfloat fMin = 1.0 - 100.0 / (100.0 - rGradient.GetBorder());
|
|
|
|
aTexCoord[5] = aTexCoord[7] = fMin;
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetTextureCoord( aTexCoord );
|
2015-01-18 18:58:20 +01:00
|
|
|
DrawConvexPolygon( aPoly, true );
|
2014-11-11 05:13:40 -05:00
|
|
|
}
|
|
|
|
|
2017-03-30 20:27:55 +02:00
|
|
|
void OpenGLSalGraphicsImpl::DrawAxialGradient( const Gradient& rGradient, const tools::Rectangle& rRect )
|
2014-11-14 01:16:28 -05:00
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2014-11-28 14:56:08 -05:00
|
|
|
if( !UseProgram( "textureVertexShader", "linearGradientFragmentShader" ) )
|
|
|
|
return;
|
2014-11-14 01:16:28 -05:00
|
|
|
Color aStartCol = rGradient.GetStartColor();
|
|
|
|
Color aEndCol = rGradient.GetEndColor();
|
|
|
|
long nFactor = rGradient.GetStartIntensity();
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetColorWithIntensity( "start_color", aStartCol, nFactor );
|
2014-11-14 01:16:28 -05:00
|
|
|
nFactor = rGradient.GetEndIntensity();
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetColorWithIntensity( "end_color", aEndCol, nFactor );
|
2014-11-14 01:16:28 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Draw two rectangles with linear gradient.
|
|
|
|
*
|
|
|
|
* 1 *---* 2
|
|
|
|
* | /|
|
|
|
|
* | / | Points 0 and 3 have start color
|
|
|
|
* 0 |/__| 3 Points 1, 2, 4 and 5 have end color
|
|
|
|
* |\ |
|
|
|
|
* | \ |
|
|
|
|
* | \|
|
|
|
|
* 5 *---* 4
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2017-03-30 20:27:55 +02:00
|
|
|
tools::Rectangle aRect;
|
2014-11-14 01:16:28 -05:00
|
|
|
Point aCenter;
|
|
|
|
rGradient.GetBoundRect( rRect, aRect, aCenter );
|
|
|
|
|
|
|
|
// determine points 0 and 3
|
|
|
|
Point aPt0( aRect.Left(), (aRect.Top() + aRect.Bottom() + 1) / 2 );
|
|
|
|
Point aPt3( aRect.Right(), (aRect.Top() + aRect.Bottom() + 1) / 2 );
|
|
|
|
|
2015-08-16 16:45:12 -05:00
|
|
|
tools::Polygon aPoly( 7 );
|
2014-11-14 01:16:28 -05:00
|
|
|
aPoly.SetPoint( aPt0, 0 );
|
|
|
|
aPoly.SetPoint( aRect.TopLeft(), 1 );
|
|
|
|
aPoly.SetPoint( aRect.TopRight(), 2 );
|
|
|
|
aPoly.SetPoint( aPt3, 3 );
|
|
|
|
aPoly.SetPoint( aRect.BottomRight(), 4 );
|
|
|
|
aPoly.SetPoint( aRect.BottomLeft(), 5 );
|
|
|
|
aPoly.SetPoint( aPt0, 6 );
|
|
|
|
aPoly.Rotate( aCenter, rGradient.GetAngle() % 3600 );
|
|
|
|
|
|
|
|
GLfloat aTexCoord[12] = { 0, 1, 1, 0, 2, 0, 3, 1, 4, 0, 5, 0 };
|
|
|
|
GLfloat fMin = 1.0 - 100.0 / (100.0 - rGradient.GetBorder());
|
|
|
|
aTexCoord[3] = aTexCoord[5] = aTexCoord[9] = aTexCoord[11] = fMin;
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetTextureCoord( aTexCoord );
|
2015-01-18 18:58:20 +01:00
|
|
|
DrawConvexPolygon( aPoly, true );
|
2014-11-14 01:16:28 -05:00
|
|
|
}
|
|
|
|
|
2017-03-30 20:27:55 +02:00
|
|
|
void OpenGLSalGraphicsImpl::DrawRadialGradient( const Gradient& rGradient, const tools::Rectangle& rRect )
|
2014-11-11 15:54:03 -05:00
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2014-11-28 14:56:08 -05:00
|
|
|
if( !UseProgram( "textureVertexShader", "radialGradientFragmentShader" ) )
|
|
|
|
return;
|
2014-11-11 15:54:03 -05:00
|
|
|
Color aStartCol = rGradient.GetStartColor();
|
|
|
|
Color aEndCol = rGradient.GetEndColor();
|
|
|
|
long nFactor = rGradient.GetStartIntensity();
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetColorWithIntensity( "start_color", aStartCol, nFactor );
|
2014-11-11 15:54:03 -05:00
|
|
|
nFactor = rGradient.GetEndIntensity();
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetColorWithIntensity( "end_color", aEndCol, nFactor );
|
2014-11-11 15:54:03 -05:00
|
|
|
|
2017-03-30 20:27:55 +02:00
|
|
|
tools::Rectangle aRect;
|
2014-11-11 15:54:03 -05:00
|
|
|
Point aCenter;
|
|
|
|
rGradient.GetBoundRect( rRect, aRect, aCenter );
|
|
|
|
|
|
|
|
// adjust coordinates so that radius has distance equals to 1.0
|
|
|
|
double fRadius = aRect.GetWidth() / 2.0f;
|
|
|
|
GLfloat fWidth = rRect.GetWidth() / fRadius;
|
|
|
|
GLfloat fHeight = rRect.GetHeight() / fRadius;
|
|
|
|
GLfloat aTexCoord[8] = { 0, 0, 0, fHeight, fWidth, fHeight, fWidth, 0 };
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetTextureCoord( aTexCoord );
|
|
|
|
mpProgram->SetUniform2f( "center", (aCenter.X() - rRect.Left()) / fRadius,
|
|
|
|
(aCenter.Y() - rRect.Top()) / fRadius );
|
2014-11-11 15:54:03 -05:00
|
|
|
DrawRect( rRect );
|
|
|
|
}
|
|
|
|
|
2016-05-29 12:37:41 +09:00
|
|
|
void OpenGLSalGraphicsImpl::drawPixel(long nX, long nY)
|
2014-10-29 13:05:02 -04:00
|
|
|
{
|
2016-05-29 12:37:41 +09:00
|
|
|
VCL_GL_INFO("::drawPixel: (" << nX << ", " << nY << ")");
|
|
|
|
mpRenderList->addDrawPixel(nX, nY, mnLineColor);
|
2016-06-24 16:42:45 +08:00
|
|
|
PostBatchDraw();
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
|
2018-03-14 11:11:02 +02:00
|
|
|
void OpenGLSalGraphicsImpl::drawPixel(long nX, long nY, Color nColor)
|
2014-10-29 13:05:02 -04:00
|
|
|
{
|
2016-05-29 12:37:41 +09:00
|
|
|
VCL_GL_INFO("::drawPixel: (" << nX << ", " << nY << ")");
|
2018-03-14 11:11:02 +02:00
|
|
|
mpRenderList->addDrawPixel(nX, nY, nColor);
|
2016-06-24 16:42:45 +08:00
|
|
|
PostBatchDraw();
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
|
2016-05-29 12:37:41 +09:00
|
|
|
void OpenGLSalGraphicsImpl::drawLine(long nX1, long nY1, long nX2, long nY2)
|
2014-10-29 13:05:02 -04:00
|
|
|
{
|
2016-05-29 12:37:41 +09:00
|
|
|
VCL_GL_INFO("::drawLine (" << nX1 << ", " << nY1 << ") (" << nX2 << ", " << nY2 << ")");
|
|
|
|
mpRenderList->addDrawLine(nX1, nY1, nX2, nY2, mnLineColor, mrParent.getAntiAliasB2DDraw());
|
2016-06-24 16:42:45 +08:00
|
|
|
PostBatchDraw();
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLSalGraphicsImpl::drawRect( long nX, long nY, long nWidth, long nHeight )
|
|
|
|
{
|
2016-05-29 12:37:41 +09:00
|
|
|
VCL_GL_INFO("::drawRect (" << nX << ", " << nY << ") [" << nWidth << ", " << nHeight << "]");
|
2016-05-31 12:26:04 +09:00
|
|
|
mpRenderList->addDrawRectangle(nX, nY, nWidth, nHeight, 0.0, mnLineColor, mnFillColor);
|
2016-06-24 16:42:45 +08:00
|
|
|
PostBatchDraw();
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
|
2017-10-27 10:14:42 +02:00
|
|
|
void OpenGLSalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry )
|
2014-10-29 13:05:02 -04:00
|
|
|
{
|
2016-05-31 12:04:03 +09:00
|
|
|
VCL_GL_INFO("::drawPolyLine legacy -> redirecting to drawPolyLine");
|
2016-05-18 18:47:48 +09:00
|
|
|
basegfx::B2DPolygon aPoly;
|
|
|
|
aPoly.append(basegfx::B2DPoint(pPtAry->mnX, pPtAry->mnY), nPoints);
|
|
|
|
for (sal_uInt32 i = 1; i < nPoints; ++i)
|
|
|
|
aPoly.setB2DPoint(i, basegfx::B2DPoint(pPtAry[i].mnX, pPtAry[i].mnY));
|
|
|
|
aPoly.setClosed(false);
|
2014-10-30 21:57:22 -04:00
|
|
|
|
Support buffering SystemDependent GraphicData
This is a first step to allow buffering of system
dependent data, especially (but not only) for the
system-dependent implementations of graphic output.
For example, for B2DPolygon and Win output, it allows
buffering the Gdiplus::GraphicsPath instead of re-
creating it all the time.
To support that, the change includes forwarding the
current transformation to the renderers in SalGraphics.
The current state in VCL is to transform all and
everything to device coordinates at every single
paint.
I have currently started to do this for ::drawPolyLine
implementations. The fallbacks for all systems will
at the start of that method just transform the data
to device coordinates, so all works as before.
This may also be done for FilledPolygon paint in a later
step, but most urgent is FatLine painting.
An arrangement of shared_ptr/weak_ptr is used so that
either the instance buffering (in the example B2DPolygon)
or the instance managing it can delete it. The instance
managing it currently uses a 1s Timer and a cycle-lifetime
management, but that can be extended in the future
to e.g. include size hints, too.
The mechanism it designed to support multiple Data per
buffering element, e.g. for B2DPolygon at the same time
system-dependent instances of Gdiplus and Cairo can be
buffered, but also PDF-data.
This is achieved semi-automatic by using
typeid(class).hash_code() as key for organization.
The mechanism will be used for now at B2DPolygon, but
is not limited to. There is already a similar but less
general buffer (see GdiPlusBuffer) that can and will
be converted to use this new mechanism.
Added vcl/headless Cairo renderer to support given
ObjectToDevice transformation (not to transform given
B2DPolygon)
Added support for CairoPath buffered at B2DPolygon,
seems to work well. Need to do more tests
Moved usage to templates suggested by Noel Grandin
(Noel Grandin <noelgrandin@gmail.com>), thanks for
these suggestions. Adapted Win usage to that, too.
Converted Win-specific GdiPlus BitmapBuffer to new
mechanism, works well. Checked, the manager holds
now a mix of bitmap and path data under Win
Added a cleanup mechanism to flush all buffered data
at DeInitVCL() using flushAll() at
SystemDependentDataBuffer
Adapted Linux-versions of ::drawPolyLine to support
PixelSnapHairline, for now in a simplified version
that still allows buffering. This will also be used
(and use buffering) for the Cairo-fallback in
X11SalGraphics
Change-Id: I88d7e438a20b96ddab7707050893bdd590c098c7
Reviewed-on: https://gerrit.libreoffice.org/59555
Tested-by: Armin Le Grand <Armin.Le.Grand@cib.de>
Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
2018-08-24 13:01:08 +02:00
|
|
|
drawPolyLine(
|
|
|
|
basegfx::B2DHomMatrix(),
|
|
|
|
aPoly,
|
|
|
|
0.0,
|
|
|
|
basegfx::B2DVector(1.0, 1.0),
|
|
|
|
basegfx::B2DLineJoin::Miter,
|
|
|
|
css::drawing::LineCap_BUTT,
|
|
|
|
basegfx::deg2rad(15.0) /*default*/,
|
|
|
|
false);
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLSalGraphicsImpl::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
|
|
|
|
{
|
2016-05-31 12:04:03 +09:00
|
|
|
VCL_GL_INFO("::drawPolygon legacy -> redirecting to drawPolyPolygon with transparency");
|
2016-05-18 18:47:48 +09:00
|
|
|
basegfx::B2DPolygon aPoly;
|
|
|
|
aPoly.append(basegfx::B2DPoint(pPtAry->mnX, pPtAry->mnY), nPoints);
|
|
|
|
for (sal_uInt32 i = 1; i < nPoints; ++i)
|
|
|
|
aPoly.setB2DPoint(i, basegfx::B2DPoint(pPtAry[i].mnX, pPtAry[i].mnY));
|
2014-10-30 21:57:22 -04:00
|
|
|
|
2018-09-06 18:15:02 +02:00
|
|
|
drawPolyPolygon(
|
|
|
|
basegfx::B2DHomMatrix(),
|
|
|
|
basegfx::B2DPolyPolygon(aPoly),
|
|
|
|
0.0);
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
|
2016-05-18 18:47:48 +09:00
|
|
|
void OpenGLSalGraphicsImpl::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPointCounts, PCONSTSALPOINT* pPtAry )
|
2014-10-29 13:05:02 -04:00
|
|
|
{
|
2016-05-31 12:04:03 +09:00
|
|
|
VCL_GL_INFO("::drawPolyPolygon legacy -> redirecting to drawPolyPolygon with transparency");
|
2016-05-18 18:47:48 +09:00
|
|
|
basegfx::B2DPolyPolygon aPolyPoly;
|
|
|
|
for(sal_uInt32 nPolygon = 0; nPolygon < nPoly; ++nPolygon)
|
2014-10-29 13:05:02 -04:00
|
|
|
{
|
2016-05-18 18:47:48 +09:00
|
|
|
sal_uInt32 nPoints = pPointCounts[nPolygon];
|
|
|
|
if (nPoints)
|
2015-01-18 22:42:06 +01:00
|
|
|
{
|
2016-05-18 18:47:48 +09:00
|
|
|
PCONSTSALPOINT pPoints = pPtAry[nPolygon];
|
|
|
|
basegfx::B2DPolygon aPoly;
|
|
|
|
aPoly.append( basegfx::B2DPoint(pPoints->mnX, pPoints->mnY), nPoints);
|
|
|
|
for (sal_uInt32 i = 1; i < nPoints; ++i)
|
|
|
|
aPoly.setB2DPoint(i, basegfx::B2DPoint( pPoints[i].mnX, pPoints[i].mnY));
|
2014-10-29 13:05:02 -04:00
|
|
|
|
2016-05-18 18:47:48 +09:00
|
|
|
aPolyPoly.append(aPoly);
|
|
|
|
}
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
2014-11-10 13:06:38 -05:00
|
|
|
|
2018-09-06 18:15:02 +02:00
|
|
|
drawPolyPolygon(
|
|
|
|
basegfx::B2DHomMatrix(),
|
|
|
|
aPolyPoly,
|
|
|
|
0.0);
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
|
2018-09-06 18:15:02 +02:00
|
|
|
bool OpenGLSalGraphicsImpl::drawPolyPolygon(
|
|
|
|
const basegfx::B2DHomMatrix& rObjectToDevice,
|
|
|
|
const basegfx::B2DPolyPolygon& rPolyPolygon,
|
|
|
|
double fTransparency)
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2016-05-29 15:36:39 +09:00
|
|
|
VCL_GL_INFO("::drawPolyPolygon " << rPolyPolygon.getB2DRange());
|
2018-09-06 18:15:02 +02:00
|
|
|
|
|
|
|
// Fallback: Transform to DeviceCoordinates
|
|
|
|
basegfx::B2DPolyPolygon aPolyPolygon(rPolyPolygon);
|
|
|
|
aPolyPolygon.transform(rObjectToDevice);
|
|
|
|
|
2019-03-29 13:40:21 +01:00
|
|
|
// FlushLinesOrTriangles() works with a 0.5 pixel offset, compensate for that here.
|
|
|
|
basegfx::B2DHomMatrix aMatrix;
|
|
|
|
aMatrix.translate(-0.5f, -0.5f);
|
|
|
|
aPolyPolygon.transform(aMatrix);
|
|
|
|
|
2018-09-06 18:15:02 +02:00
|
|
|
mpRenderList->addDrawPolyPolygon(
|
|
|
|
aPolyPolygon,
|
|
|
|
fTransparency,
|
|
|
|
mnLineColor,
|
|
|
|
mnFillColor,
|
|
|
|
mrParent.getAntiAliasB2DDraw());
|
|
|
|
|
2016-06-24 16:42:45 +08:00
|
|
|
PostBatchDraw();
|
2014-11-08 22:55:06 -05:00
|
|
|
return true;
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
Support buffering SystemDependent GraphicData
This is a first step to allow buffering of system
dependent data, especially (but not only) for the
system-dependent implementations of graphic output.
For example, for B2DPolygon and Win output, it allows
buffering the Gdiplus::GraphicsPath instead of re-
creating it all the time.
To support that, the change includes forwarding the
current transformation to the renderers in SalGraphics.
The current state in VCL is to transform all and
everything to device coordinates at every single
paint.
I have currently started to do this for ::drawPolyLine
implementations. The fallbacks for all systems will
at the start of that method just transform the data
to device coordinates, so all works as before.
This may also be done for FilledPolygon paint in a later
step, but most urgent is FatLine painting.
An arrangement of shared_ptr/weak_ptr is used so that
either the instance buffering (in the example B2DPolygon)
or the instance managing it can delete it. The instance
managing it currently uses a 1s Timer and a cycle-lifetime
management, but that can be extended in the future
to e.g. include size hints, too.
The mechanism it designed to support multiple Data per
buffering element, e.g. for B2DPolygon at the same time
system-dependent instances of Gdiplus and Cairo can be
buffered, but also PDF-data.
This is achieved semi-automatic by using
typeid(class).hash_code() as key for organization.
The mechanism will be used for now at B2DPolygon, but
is not limited to. There is already a similar but less
general buffer (see GdiPlusBuffer) that can and will
be converted to use this new mechanism.
Added vcl/headless Cairo renderer to support given
ObjectToDevice transformation (not to transform given
B2DPolygon)
Added support for CairoPath buffered at B2DPolygon,
seems to work well. Need to do more tests
Moved usage to templates suggested by Noel Grandin
(Noel Grandin <noelgrandin@gmail.com>), thanks for
these suggestions. Adapted Win usage to that, too.
Converted Win-specific GdiPlus BitmapBuffer to new
mechanism, works well. Checked, the manager holds
now a mix of bitmap and path data under Win
Added a cleanup mechanism to flush all buffered data
at DeInitVCL() using flushAll() at
SystemDependentDataBuffer
Adapted Linux-versions of ::drawPolyLine to support
PixelSnapHairline, for now in a simplified version
that still allows buffering. This will also be used
(and use buffering) for the Cairo-fallback in
X11SalGraphics
Change-Id: I88d7e438a20b96ddab7707050893bdd590c098c7
Reviewed-on: https://gerrit.libreoffice.org/59555
Tested-by: Armin Le Grand <Armin.Le.Grand@cib.de>
Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
2018-08-24 13:01:08 +02:00
|
|
|
bool OpenGLSalGraphicsImpl::drawPolyLine(
|
|
|
|
const basegfx::B2DHomMatrix& rObjectToDevice,
|
|
|
|
const basegfx::B2DPolygon& rPolygon,
|
|
|
|
double fTransparency,
|
|
|
|
const basegfx::B2DVector& rLineWidth,
|
|
|
|
basegfx::B2DLineJoin eLineJoin,
|
|
|
|
css::drawing::LineCap eLineCap,
|
|
|
|
double fMiterMinimumAngle,
|
|
|
|
bool bPixelSnapHairline)
|
2014-11-08 23:04:46 -05:00
|
|
|
{
|
2016-06-07 20:45:14 +09:00
|
|
|
VCL_GL_INFO("::drawPolyLine " << rPolygon.getB2DRange());
|
2014-11-08 23:04:46 -05:00
|
|
|
|
Support buffering SystemDependent GraphicData
This is a first step to allow buffering of system
dependent data, especially (but not only) for the
system-dependent implementations of graphic output.
For example, for B2DPolygon and Win output, it allows
buffering the Gdiplus::GraphicsPath instead of re-
creating it all the time.
To support that, the change includes forwarding the
current transformation to the renderers in SalGraphics.
The current state in VCL is to transform all and
everything to device coordinates at every single
paint.
I have currently started to do this for ::drawPolyLine
implementations. The fallbacks for all systems will
at the start of that method just transform the data
to device coordinates, so all works as before.
This may also be done for FilledPolygon paint in a later
step, but most urgent is FatLine painting.
An arrangement of shared_ptr/weak_ptr is used so that
either the instance buffering (in the example B2DPolygon)
or the instance managing it can delete it. The instance
managing it currently uses a 1s Timer and a cycle-lifetime
management, but that can be extended in the future
to e.g. include size hints, too.
The mechanism it designed to support multiple Data per
buffering element, e.g. for B2DPolygon at the same time
system-dependent instances of Gdiplus and Cairo can be
buffered, but also PDF-data.
This is achieved semi-automatic by using
typeid(class).hash_code() as key for organization.
The mechanism will be used for now at B2DPolygon, but
is not limited to. There is already a similar but less
general buffer (see GdiPlusBuffer) that can and will
be converted to use this new mechanism.
Added vcl/headless Cairo renderer to support given
ObjectToDevice transformation (not to transform given
B2DPolygon)
Added support for CairoPath buffered at B2DPolygon,
seems to work well. Need to do more tests
Moved usage to templates suggested by Noel Grandin
(Noel Grandin <noelgrandin@gmail.com>), thanks for
these suggestions. Adapted Win usage to that, too.
Converted Win-specific GdiPlus BitmapBuffer to new
mechanism, works well. Checked, the manager holds
now a mix of bitmap and path data under Win
Added a cleanup mechanism to flush all buffered data
at DeInitVCL() using flushAll() at
SystemDependentDataBuffer
Adapted Linux-versions of ::drawPolyLine to support
PixelSnapHairline, for now in a simplified version
that still allows buffering. This will also be used
(and use buffering) for the Cairo-fallback in
X11SalGraphics
Change-Id: I88d7e438a20b96ddab7707050893bdd590c098c7
Reviewed-on: https://gerrit.libreoffice.org/59555
Tested-by: Armin Le Grand <Armin.Le.Grand@cib.de>
Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
2018-08-24 13:01:08 +02:00
|
|
|
// Transform to DeviceCoordinates, get DeviceLineWidth, execute PixelSnapHairline
|
|
|
|
basegfx::B2DPolygon aPolyLine(rPolygon);
|
|
|
|
aPolyLine.transform(rObjectToDevice);
|
|
|
|
if(bPixelSnapHairline) { aPolyLine = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aPolyLine); }
|
|
|
|
const basegfx::B2DVector aLineWidth(rObjectToDevice * rLineWidth);
|
|
|
|
|
2018-07-03 17:17:42 +02:00
|
|
|
// addDrawPolyLine() assumes that there are no duplicate points in the
|
|
|
|
// polygon.
|
Support buffering SystemDependent GraphicData
This is a first step to allow buffering of system
dependent data, especially (but not only) for the
system-dependent implementations of graphic output.
For example, for B2DPolygon and Win output, it allows
buffering the Gdiplus::GraphicsPath instead of re-
creating it all the time.
To support that, the change includes forwarding the
current transformation to the renderers in SalGraphics.
The current state in VCL is to transform all and
everything to device coordinates at every single
paint.
I have currently started to do this for ::drawPolyLine
implementations. The fallbacks for all systems will
at the start of that method just transform the data
to device coordinates, so all works as before.
This may also be done for FilledPolygon paint in a later
step, but most urgent is FatLine painting.
An arrangement of shared_ptr/weak_ptr is used so that
either the instance buffering (in the example B2DPolygon)
or the instance managing it can delete it. The instance
managing it currently uses a 1s Timer and a cycle-lifetime
management, but that can be extended in the future
to e.g. include size hints, too.
The mechanism it designed to support multiple Data per
buffering element, e.g. for B2DPolygon at the same time
system-dependent instances of Gdiplus and Cairo can be
buffered, but also PDF-data.
This is achieved semi-automatic by using
typeid(class).hash_code() as key for organization.
The mechanism will be used for now at B2DPolygon, but
is not limited to. There is already a similar but less
general buffer (see GdiPlusBuffer) that can and will
be converted to use this new mechanism.
Added vcl/headless Cairo renderer to support given
ObjectToDevice transformation (not to transform given
B2DPolygon)
Added support for CairoPath buffered at B2DPolygon,
seems to work well. Need to do more tests
Moved usage to templates suggested by Noel Grandin
(Noel Grandin <noelgrandin@gmail.com>), thanks for
these suggestions. Adapted Win usage to that, too.
Converted Win-specific GdiPlus BitmapBuffer to new
mechanism, works well. Checked, the manager holds
now a mix of bitmap and path data under Win
Added a cleanup mechanism to flush all buffered data
at DeInitVCL() using flushAll() at
SystemDependentDataBuffer
Adapted Linux-versions of ::drawPolyLine to support
PixelSnapHairline, for now in a simplified version
that still allows buffering. This will also be used
(and use buffering) for the Cairo-fallback in
X11SalGraphics
Change-Id: I88d7e438a20b96ddab7707050893bdd590c098c7
Reviewed-on: https://gerrit.libreoffice.org/59555
Tested-by: Armin Le Grand <Armin.Le.Grand@cib.de>
Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
2018-08-24 13:01:08 +02:00
|
|
|
// basegfx::B2DPolygon aPolygon(rPolygon);
|
|
|
|
aPolyLine.removeDoublePoints();
|
|
|
|
|
|
|
|
mpRenderList->addDrawPolyLine(
|
|
|
|
aPolyLine,
|
|
|
|
fTransparency,
|
|
|
|
aLineWidth,
|
|
|
|
eLineJoin,
|
|
|
|
eLineCap,
|
|
|
|
fMiterMinimumAngle,
|
|
|
|
mnLineColor,
|
|
|
|
mrParent.getAntiAliasB2DDraw());
|
2018-07-03 17:17:42 +02:00
|
|
|
|
2016-06-24 16:42:45 +08:00
|
|
|
PostBatchDraw();
|
2014-11-08 23:04:46 -05:00
|
|
|
return true;
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool OpenGLSalGraphicsImpl::drawPolyLineBezier(
|
|
|
|
sal_uInt32 /*nPoints*/,
|
|
|
|
const SalPoint* /*pPtAry*/,
|
2016-12-05 12:47:37 +02:00
|
|
|
const PolyFlags* /*pFlgAry*/ )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OpenGLSalGraphicsImpl::drawPolygonBezier(
|
|
|
|
sal_uInt32 /*nPoints*/,
|
|
|
|
const SalPoint* /*pPtAry*/,
|
2016-12-05 12:47:37 +02:00
|
|
|
const PolyFlags* /*pFlgAry*/ )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OpenGLSalGraphicsImpl::drawPolyPolygonBezier(
|
|
|
|
sal_uInt32 /*nPoly*/,
|
|
|
|
const sal_uInt32* /*pPoints*/,
|
|
|
|
const SalPoint* const* /*pPtAry*/,
|
2016-12-05 12:47:37 +02:00
|
|
|
const PolyFlags* const* /*pFlgAry*/ )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2014-11-10 08:13:31 +01:00
|
|
|
return false;
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// CopyArea --> No RasterOp, but ClipRegion
|
|
|
|
void OpenGLSalGraphicsImpl::copyArea(
|
2014-11-18 19:11:04 -05:00
|
|
|
long nDestX, long nDestY,
|
|
|
|
long nSrcX, long nSrcY,
|
2016-05-10 11:55:49 +02:00
|
|
|
long nSrcWidth, long nSrcHeight, bool /*bWindowInvalidate*/ )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::copyArea " << nSrcX << "," << nSrcY << " >> " << nDestX << "," << nDestY << " (" << nSrcWidth << "," << nSrcHeight << ")" );
|
2014-11-18 19:11:04 -05:00
|
|
|
OpenGLTexture aTexture;
|
2014-11-24 10:10:11 +00:00
|
|
|
SalTwoRect aPosAry(0, 0, nSrcWidth, nSrcHeight, nDestX, nDestY, nSrcWidth, nSrcHeight);
|
2014-11-18 19:11:04 -05:00
|
|
|
|
|
|
|
PreDraw();
|
2014-11-28 14:56:08 -05:00
|
|
|
// TODO offscreen case
|
|
|
|
aTexture = OpenGLTexture( nSrcX, GetHeight() - nSrcY - nSrcHeight,
|
|
|
|
nSrcWidth, nSrcHeight );
|
2014-11-18 19:11:04 -05:00
|
|
|
DrawTexture( aTexture, aPosAry );
|
|
|
|
PostDraw();
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// CopyBits and DrawBitmap --> RasterOp and ClipRegion
|
|
|
|
// CopyBits() --> pSrcGraphics == NULL, then CopyBits on same Graphics
|
2014-11-19 09:58:05 +00:00
|
|
|
void OpenGLSalGraphicsImpl::DoCopyBits( const SalTwoRect& rPosAry, OpenGLSalGraphicsImpl& rImpl )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::copyBits" );
|
2014-11-13 21:30:05 -05:00
|
|
|
|
2016-03-14 11:20:19 +01:00
|
|
|
rImpl.FlushDeferredDrawing();
|
|
|
|
|
2015-12-23 13:37:33 +00:00
|
|
|
if( !rImpl.maOffscreenTex )
|
|
|
|
{
|
|
|
|
VCL_GL_INFO( "::copyBits - skipping copy of un-initialized framebuffer contents of size "
|
|
|
|
<< rImpl.GetWidth() << "x" << rImpl.GetHeight() );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-11-19 09:58:05 +00:00
|
|
|
if( &rImpl == this &&
|
2014-10-29 13:05:02 -04:00
|
|
|
(rPosAry.mnSrcWidth == rPosAry.mnDestWidth) &&
|
|
|
|
(rPosAry.mnSrcHeight == rPosAry.mnDestHeight))
|
|
|
|
{
|
|
|
|
// short circuit if there is nothing to do
|
|
|
|
if( (rPosAry.mnSrcX == rPosAry.mnDestX) &&
|
|
|
|
(rPosAry.mnSrcY == rPosAry.mnDestY))
|
|
|
|
return;
|
|
|
|
// use copyArea() if source and destination context are identical
|
|
|
|
copyArea( rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnSrcX, rPosAry.mnSrcY,
|
2016-05-10 11:55:49 +02:00
|
|
|
rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, false/*bWindowInvalidate*/ );
|
2014-10-29 13:05:02 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-11-13 12:00:59 +00:00
|
|
|
PreDraw();
|
|
|
|
DrawTexture( rImpl.maOffscreenTex, rPosAry );
|
|
|
|
PostDraw();
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
2014-10-29 13:05:02 -04:00
|
|
|
void OpenGLSalGraphicsImpl::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2014-11-11 21:19:02 +01:00
|
|
|
// check that carefully only in the debug mode
|
|
|
|
assert(dynamic_cast<const OpenGLSalBitmap*>(&rSalBitmap));
|
|
|
|
|
2015-12-16 17:19:31 +00:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2014-10-29 13:05:02 -04:00
|
|
|
const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
|
2014-11-17 14:24:31 -05:00
|
|
|
OpenGLTexture& rTexture = rBitmap.GetTexture();
|
2014-10-29 13:05:02 -04:00
|
|
|
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::drawBitmap" );
|
2014-11-10 13:06:38 -05:00
|
|
|
PreDraw();
|
2019-03-22 13:39:17 +01:00
|
|
|
if (rPosAry.mnSrcWidth != rPosAry.mnDestWidth ||
|
|
|
|
rPosAry.mnSrcHeight != rPosAry.mnDestHeight)
|
|
|
|
{
|
|
|
|
basegfx::B2DPoint aNull(rPosAry.mnDestX,rPosAry.mnDestY);
|
|
|
|
basegfx::B2DPoint aX(rPosAry.mnDestX + rPosAry.mnDestWidth, rPosAry.mnDestY);
|
|
|
|
basegfx::B2DPoint aY(rPosAry.mnDestX, rPosAry.mnDestY + rPosAry.mnDestHeight);
|
|
|
|
OpenGLTexture mask; // no mask set
|
|
|
|
DrawTransformedTexture(rTexture, mask, aNull, aX, aY);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DrawTexture( rTexture, rPosAry );
|
|
|
|
}
|
2014-11-10 13:06:38 -05:00
|
|
|
PostDraw();
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLSalGraphicsImpl::drawBitmap(
|
2014-10-29 13:05:02 -04:00
|
|
|
const SalTwoRect& rPosAry,
|
|
|
|
const SalBitmap& rSalBitmap,
|
|
|
|
const SalBitmap& rMaskBitmap )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2016-05-27 19:43:12 +09:00
|
|
|
VCL_GL_INFO("::drawBitmap with MASK -> redirect to ::drawAlphaBitmap");
|
|
|
|
drawAlphaBitmap(rPosAry, rSalBitmap, rMaskBitmap);
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLSalGraphicsImpl::drawMask(
|
2014-10-29 13:05:02 -04:00
|
|
|
const SalTwoRect& rPosAry,
|
|
|
|
const SalBitmap& rSalBitmap,
|
2018-03-14 11:11:02 +02:00
|
|
|
Color nMaskColor )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2016-05-31 12:26:04 +09:00
|
|
|
VCL_GL_INFO("::drawMask");
|
2015-12-16 17:19:31 +00:00
|
|
|
|
2016-05-31 12:26:04 +09:00
|
|
|
assert(dynamic_cast<const OpenGLSalBitmap*>(&rSalBitmap));
|
2014-10-29 13:05:02 -04:00
|
|
|
const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
|
2016-05-31 12:26:04 +09:00
|
|
|
mpRenderList->addDrawTextureWithMaskColor(rBitmap.GetTexture(), nMaskColor, rPosAry);
|
2016-06-24 16:42:45 +08:00
|
|
|
PostBatchDraw();
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
2018-06-08 12:29:09 +02:00
|
|
|
std::shared_ptr<SalBitmap> OpenGLSalGraphicsImpl::getBitmap( long nX, long nY, long nWidth, long nHeight )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2016-05-27 19:43:12 +09:00
|
|
|
FlushDeferredDrawing();
|
|
|
|
|
2015-12-16 17:19:31 +00:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2018-06-08 12:29:09 +02:00
|
|
|
std::shared_ptr<OpenGLSalBitmap> pBitmap(std::make_shared<OpenGLSalBitmap>());
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::getBitmap " << nX << "," << nY <<
|
2014-11-07 12:33:15 +00:00
|
|
|
" " << nWidth << "x" << nHeight );
|
2014-11-28 14:58:53 -05:00
|
|
|
//TODO really needed?
|
2014-11-10 13:06:38 -05:00
|
|
|
PreDraw();
|
2018-07-26 12:27:10 +02:00
|
|
|
pBitmap->Create( maOffscreenTex, nX, nY, nWidth, nHeight );
|
2014-11-10 13:06:38 -05:00
|
|
|
PostDraw();
|
2014-10-29 13:05:02 -04:00
|
|
|
return pBitmap;
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
2018-03-14 11:11:02 +02:00
|
|
|
Color OpenGLSalGraphicsImpl::getPixel( long nX, long nY )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2016-03-14 11:20:19 +01:00
|
|
|
FlushDeferredDrawing();
|
|
|
|
|
2014-11-10 12:16:00 +00:00
|
|
|
char pixel[3] = { 0, 0, 0 };
|
2014-10-29 13:05:02 -04:00
|
|
|
|
2016-01-08 22:33:11 +00:00
|
|
|
PreDraw( XOROption::IMPLEMENT_XOR );
|
2015-03-19 18:06:27 +01:00
|
|
|
nY = GetHeight() - nY - 1;
|
2014-10-29 13:05:02 -04:00
|
|
|
glReadPixels( nX, nY, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixel);
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2014-11-10 13:06:38 -05:00
|
|
|
PostDraw();
|
2014-11-12 18:21:47 +01:00
|
|
|
|
2018-03-14 11:11:02 +02:00
|
|
|
return Color( pixel[0], pixel[1], pixel[2] );
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// invert --> ClipRegion (only Windows or VirDevs)
|
|
|
|
void OpenGLSalGraphicsImpl::invert(
|
2014-10-29 13:05:02 -04:00
|
|
|
long nX, long nY,
|
|
|
|
long nWidth, long nHeight,
|
|
|
|
SalInvert nFlags)
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2014-11-10 13:06:38 -05:00
|
|
|
PreDraw();
|
2014-10-30 21:57:22 -04:00
|
|
|
|
2015-12-31 21:19:48 +00:00
|
|
|
if( UseInvert( nFlags ) )
|
2016-01-09 12:13:15 +00:00
|
|
|
{
|
2016-05-10 09:55:14 +02:00
|
|
|
if( nFlags & SalInvert::TrackFrame )
|
2016-01-09 12:13:15 +00:00
|
|
|
{ // FIXME: could be more efficient.
|
|
|
|
DrawRect( nX, nY, nWidth, 1 );
|
|
|
|
DrawRect( nX, nY + nHeight, nWidth, 1 );
|
|
|
|
DrawRect( nX, nY, 1, nHeight );
|
|
|
|
DrawRect( nX + nWidth, nY, 1, nHeight );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
DrawRect( nX, nY, nWidth, nHeight );
|
|
|
|
}
|
2014-11-10 13:06:38 -05:00
|
|
|
|
|
|
|
PostDraw();
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
2014-10-29 13:05:02 -04:00
|
|
|
void OpenGLSalGraphicsImpl::invert( sal_uInt32 nPoints, const SalPoint* pPtAry, SalInvert nFlags )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2014-11-10 13:06:38 -05:00
|
|
|
PreDraw();
|
2014-10-30 21:57:22 -04:00
|
|
|
|
2015-12-31 21:19:48 +00:00
|
|
|
if( UseInvert( nFlags ) )
|
2018-06-27 16:50:38 +02:00
|
|
|
{
|
|
|
|
if (nFlags & SalInvert::TrackFrame)
|
|
|
|
{
|
|
|
|
// Track frame means the invert50FragmentShader must remain active
|
|
|
|
// (to draw what looks like a dashed line), so DrawLineSegment()
|
|
|
|
// can't be used. Draw the edge of the polygon as polygons instead.
|
|
|
|
for (size_t nPoint = 0; nPoint < nPoints; ++nPoint)
|
|
|
|
{
|
|
|
|
const SalPoint& rFrom = pPtAry[nPoint];
|
|
|
|
const SalPoint& rTo = pPtAry[(nPoint + 1) % nPoints];
|
|
|
|
if (rFrom.mnX == rTo.mnX)
|
|
|
|
{
|
|
|
|
// Extend to the right, comments assuming "to" is above
|
|
|
|
// "from":
|
|
|
|
const SalPoint aPoints[] = { { rFrom.mnX + 1, rFrom.mnY }, // bottom right
|
|
|
|
{ rFrom.mnX, rFrom.mnY }, // bottom left
|
|
|
|
{ rTo.mnX, rTo.mnY }, // top left
|
|
|
|
{ rTo.mnX + 1, rTo.mnY } }; // top right
|
|
|
|
DrawConvexPolygon(4, aPoints, true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Otherwise can extend downwards, comments assuming "to"
|
|
|
|
// is above and on the right of "from":
|
|
|
|
const SalPoint aPoints[] = { { rFrom.mnX, rFrom.mnY + 1 }, // bottom left
|
|
|
|
{ rFrom.mnX, rFrom.mnY }, // top left
|
|
|
|
{ rTo.mnX, rTo.mnY }, // top right
|
|
|
|
{ rTo.mnX, rTo.mnY + 1 } }; // bottom right
|
|
|
|
DrawConvexPolygon(4, aPoints, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
DrawPolygon(nPoints, pPtAry);
|
|
|
|
}
|
2014-11-10 13:06:38 -05:00
|
|
|
|
|
|
|
PostDraw();
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool OpenGLSalGraphicsImpl::drawEPS(
|
|
|
|
long /*nX*/, long /*nY*/,
|
|
|
|
long /*nWidth*/, long /*nHeight*/,
|
|
|
|
void* /*pPtr*/,
|
2019-02-25 14:30:01 +02:00
|
|
|
sal_uInt32 /*nSize*/ )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-11-18 12:34:53 -05:00
|
|
|
bool OpenGLSalGraphicsImpl::blendBitmap(
|
|
|
|
const SalTwoRect& rPosAry,
|
|
|
|
const SalBitmap& rSalBitmap )
|
|
|
|
{
|
2015-12-12 18:00:21 +01:00
|
|
|
assert(dynamic_cast<const OpenGLSalBitmap*>(&rSalBitmap));
|
|
|
|
|
2015-12-16 17:19:31 +00:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2014-11-18 12:34:53 -05:00
|
|
|
const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
|
|
|
|
OpenGLTexture& rTexture( rBitmap.GetTexture() );
|
|
|
|
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::blendBitmap" );
|
2014-11-18 12:34:53 -05:00
|
|
|
PreDraw();
|
2016-05-12 13:37:11 +09:00
|
|
|
|
2016-05-20 14:59:24 +09:00
|
|
|
if (!UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader"))
|
2016-05-12 13:37:11 +09:00
|
|
|
return true;
|
|
|
|
|
2016-05-20 14:59:24 +09:00
|
|
|
mpProgram->SetShaderType(TextureShaderType::Normal);
|
|
|
|
mpProgram->SetIdentityTransform("transform");
|
|
|
|
mpProgram->SetTexture("texture", rTexture);
|
2016-05-27 17:54:50 +09:00
|
|
|
|
|
|
|
GLfloat aTexCoord[8];
|
|
|
|
rTexture.GetCoord(aTexCoord, rPosAry);
|
|
|
|
mpProgram->SetTextureCoord(aTexCoord);
|
|
|
|
mpProgram->SetMaskCoord(aTexCoord);
|
|
|
|
mpProgram->SetAlphaCoord(aTexCoord);
|
|
|
|
|
2016-05-12 13:37:11 +09:00
|
|
|
mpProgram->SetBlendMode(GL_ZERO, GL_SRC_COLOR);
|
2017-04-25 15:09:53 +02:00
|
|
|
DrawTextureRect(rPosAry);
|
2016-05-12 13:37:11 +09:00
|
|
|
mpProgram->Clean();
|
|
|
|
|
2014-11-18 12:34:53 -05:00
|
|
|
PostDraw();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OpenGLSalGraphicsImpl::blendAlphaBitmap(
|
|
|
|
const SalTwoRect& rPosAry,
|
|
|
|
const SalBitmap& rSalSrcBitmap,
|
|
|
|
const SalBitmap& rSalMaskBitmap,
|
|
|
|
const SalBitmap& rSalAlphaBitmap )
|
|
|
|
{
|
2015-12-12 18:00:21 +01:00
|
|
|
assert(dynamic_cast<const OpenGLSalBitmap*>(&rSalSrcBitmap));
|
|
|
|
assert(dynamic_cast<const OpenGLSalBitmap*>(&rSalMaskBitmap));
|
|
|
|
assert(dynamic_cast<const OpenGLSalBitmap*>(&rSalAlphaBitmap));
|
|
|
|
|
2015-12-16 17:19:31 +00:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2014-11-18 12:34:53 -05:00
|
|
|
const OpenGLSalBitmap& rSrcBitmap = static_cast<const OpenGLSalBitmap&>(rSalSrcBitmap);
|
|
|
|
const OpenGLSalBitmap& rMaskBitmap = static_cast<const OpenGLSalBitmap&>(rSalMaskBitmap);
|
|
|
|
const OpenGLSalBitmap& rAlphaBitmap = static_cast<const OpenGLSalBitmap&>(rSalAlphaBitmap);
|
|
|
|
OpenGLTexture& rTexture( rSrcBitmap.GetTexture() );
|
|
|
|
OpenGLTexture& rMask( rMaskBitmap.GetTexture() );
|
|
|
|
OpenGLTexture& rAlpha( rAlphaBitmap.GetTexture() );
|
|
|
|
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::blendAlphaBitmap" );
|
2014-11-18 12:34:53 -05:00
|
|
|
PreDraw();
|
|
|
|
DrawBlendedTexture( rTexture, rMask, rAlpha, rPosAry );
|
|
|
|
PostDraw();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-10-23 23:23:26 +02:00
|
|
|
/** Render bitmap with alpha channel
|
|
|
|
|
|
|
|
@param rSourceBitmap
|
|
|
|
Source bitmap to blit
|
|
|
|
|
|
|
|
@param rAlphaBitmap
|
|
|
|
Alpha channel to use for blitting
|
|
|
|
|
|
|
|
@return true, if the operation succeeded, and false
|
|
|
|
otherwise. In this case, clients should try to emulate alpha
|
|
|
|
compositing themselves
|
|
|
|
*/
|
|
|
|
bool OpenGLSalGraphicsImpl::drawAlphaBitmap(
|
2014-10-29 13:05:02 -04:00
|
|
|
const SalTwoRect& rPosAry,
|
|
|
|
const SalBitmap& rSalBitmap,
|
|
|
|
const SalBitmap& rAlphaBitmap )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2015-12-12 18:00:21 +01:00
|
|
|
assert(dynamic_cast<const OpenGLSalBitmap*>(&rSalBitmap));
|
|
|
|
assert(dynamic_cast<const OpenGLSalBitmap*>(&rAlphaBitmap));
|
|
|
|
|
2015-12-16 17:19:31 +00:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2014-10-29 13:05:02 -04:00
|
|
|
const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
|
|
|
|
const OpenGLSalBitmap& rAlpha = static_cast<const OpenGLSalBitmap&>(rAlphaBitmap);
|
2016-06-09 14:58:42 +09:00
|
|
|
OpenGLTexture& rTexture(rBitmap.GetTexture());
|
|
|
|
OpenGLTexture& rAlphaTexture(rAlpha.GetTexture());
|
2014-10-29 13:05:02 -04:00
|
|
|
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::drawAlphaBitmap" );
|
2014-11-10 13:06:38 -05:00
|
|
|
PreDraw();
|
2016-06-09 14:58:42 +09:00
|
|
|
|
|
|
|
if (rPosAry.mnSrcWidth != rPosAry.mnDestWidth ||
|
|
|
|
rPosAry.mnSrcHeight != rPosAry.mnDestHeight)
|
|
|
|
{
|
|
|
|
basegfx::B2DPoint aNull(rPosAry.mnDestX,rPosAry.mnDestY);
|
|
|
|
basegfx::B2DPoint aX(rPosAry.mnDestX + rPosAry.mnDestWidth, rPosAry.mnDestY);
|
|
|
|
basegfx::B2DPoint aY(rPosAry.mnDestX, rPosAry.mnDestY + rPosAry.mnDestHeight);
|
|
|
|
DrawTransformedTexture(rTexture, rAlphaTexture, aNull, aX, aY);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DrawTextureWithMask( rTexture, rAlphaTexture, rPosAry );
|
|
|
|
}
|
|
|
|
|
2014-11-10 13:06:38 -05:00
|
|
|
PostDraw();
|
2014-10-29 13:05:02 -04:00
|
|
|
return true;
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** draw transformed bitmap (maybe with alpha) where Null, X, Y define the coordinate system */
|
|
|
|
bool OpenGLSalGraphicsImpl::drawTransformedBitmap(
|
2014-11-17 09:15:15 -05:00
|
|
|
const basegfx::B2DPoint& rNull,
|
|
|
|
const basegfx::B2DPoint& rX,
|
|
|
|
const basegfx::B2DPoint& rY,
|
|
|
|
const SalBitmap& rSrcBitmap,
|
|
|
|
const SalBitmap* pAlphaBitmap)
|
|
|
|
{
|
2015-12-12 18:00:21 +01:00
|
|
|
assert(dynamic_cast<const OpenGLSalBitmap*>(&rSrcBitmap));
|
2016-01-01 12:38:37 +00:00
|
|
|
assert(!pAlphaBitmap || dynamic_cast<const OpenGLSalBitmap*>(pAlphaBitmap));
|
2015-12-12 18:00:21 +01:00
|
|
|
|
2015-12-16 17:19:31 +00:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2014-11-17 09:15:15 -05:00
|
|
|
const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSrcBitmap);
|
|
|
|
const OpenGLSalBitmap* pMaskBitmap = static_cast<const OpenGLSalBitmap*>(pAlphaBitmap);
|
2014-11-17 14:24:31 -05:00
|
|
|
OpenGLTexture& rTexture( rBitmap.GetTexture() );
|
2014-11-17 09:15:15 -05:00
|
|
|
OpenGLTexture aMask; // no texture
|
|
|
|
|
2015-11-10 10:28:29 +01:00
|
|
|
if( pMaskBitmap != nullptr )
|
2014-11-17 14:24:31 -05:00
|
|
|
aMask = pMaskBitmap->GetTexture();
|
2014-11-17 09:15:15 -05:00
|
|
|
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::drawTransformedBitmap" );
|
2014-11-17 09:15:15 -05:00
|
|
|
PreDraw();
|
|
|
|
DrawTransformedTexture( rTexture, aMask, rNull, rX, rY );
|
|
|
|
PostDraw();
|
|
|
|
|
|
|
|
return true;
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Render solid rectangle with given transparency
|
|
|
|
|
|
|
|
@param nTransparency
|
|
|
|
Transparency value (0-255) to use. 0 blits and opaque, 255 a
|
|
|
|
fully transparent rectangle
|
|
|
|
*/
|
|
|
|
bool OpenGLSalGraphicsImpl::drawAlphaRect(
|
2014-10-29 13:05:02 -04:00
|
|
|
long nX, long nY,
|
|
|
|
long nWidth, long nHeight,
|
|
|
|
sal_uInt8 nTransparency )
|
|
|
|
{
|
2016-05-31 12:26:04 +09:00
|
|
|
VCL_GL_INFO("::drawAlphaRect (" << nX << ", " << nY << ") [" << nWidth << ", " << nHeight << "]");
|
2018-11-16 10:41:03 +02:00
|
|
|
mpRenderList->addDrawRectangle(nX, nY, nWidth, nHeight, nTransparency / 100.0, mnLineColor, mnFillColor);
|
2016-06-24 16:42:45 +08:00
|
|
|
PostBatchDraw();
|
2014-10-29 13:05:02 -04:00
|
|
|
return true;
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
2014-11-11 05:13:40 -05:00
|
|
|
bool OpenGLSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPoly,
|
|
|
|
const Gradient& rGradient)
|
2014-10-29 17:25:55 +01:00
|
|
|
{
|
2017-03-30 20:27:55 +02:00
|
|
|
tools::Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
|
2014-11-11 15:54:03 -05:00
|
|
|
|
2016-08-04 16:21:47 +09:00
|
|
|
VCL_GL_INFO("::drawGradient " << rPolyPoly.GetBoundRect());
|
2014-11-11 05:13:40 -05:00
|
|
|
|
2016-08-04 16:21:47 +09:00
|
|
|
if (aBoundRect.IsEmpty())
|
|
|
|
{
|
|
|
|
VCL_GL_INFO("::drawGradient nothing to draw");
|
2014-11-11 05:13:40 -05:00
|
|
|
return true;
|
2016-08-04 16:21:47 +09:00
|
|
|
}
|
2014-11-11 05:13:40 -05:00
|
|
|
|
2016-09-02 10:53:14 +02:00
|
|
|
if (rGradient.GetStyle() != GradientStyle::Linear &&
|
|
|
|
rGradient.GetStyle() != GradientStyle::Axial &&
|
|
|
|
rGradient.GetStyle() != GradientStyle::Radial )
|
2016-08-04 16:21:47 +09:00
|
|
|
{
|
|
|
|
VCL_GL_INFO("::drawGradient unsupported gradient type");
|
2014-11-12 18:11:34 -05:00
|
|
|
return false;
|
2016-08-04 16:21:47 +09:00
|
|
|
}
|
2014-11-12 18:11:34 -05:00
|
|
|
|
2018-02-21 15:56:58 +02:00
|
|
|
aBoundRect.AdjustLeft( -1 );
|
|
|
|
aBoundRect.AdjustTop( -1 );
|
|
|
|
aBoundRect.AdjustRight( 1 );
|
|
|
|
aBoundRect.AdjustBottom( 1 );
|
2014-11-12 18:11:34 -05:00
|
|
|
|
2016-01-08 22:33:11 +00:00
|
|
|
PreDraw( XOROption::IMPLEMENT_XOR );
|
2014-11-12 18:11:34 -05:00
|
|
|
|
2014-11-15 17:33:36 +01:00
|
|
|
#define FIXME_BROKEN_STENCIL_FOR_GRADIENTS 0
|
|
|
|
#if FIXME_BROKEN_STENCIL_FOR_GRADIENTS
|
2014-11-12 18:11:34 -05:00
|
|
|
ImplSetClipBit( vcl::Region( rPolyPoly ), 0x02 );
|
|
|
|
if( mbUseStencil )
|
|
|
|
{
|
2016-11-28 16:39:26 +01:00
|
|
|
mpContext->state().stencil().enable();
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2014-11-12 18:11:34 -05:00
|
|
|
glStencilFunc( GL_EQUAL, 3, 0xFF );
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2014-11-12 18:11:34 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-11-28 16:39:26 +01:00
|
|
|
mpContext->state().stencil().enable();
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2014-11-12 18:11:34 -05:00
|
|
|
glStencilFunc( GL_EQUAL, 2, 0xFF );
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2014-11-12 18:11:34 -05:00
|
|
|
}
|
2014-11-15 17:33:36 +01:00
|
|
|
#endif
|
2014-11-11 15:54:03 -05:00
|
|
|
|
|
|
|
// if border >= 100%, draw solid rectangle with start color
|
2016-08-04 16:21:47 +09:00
|
|
|
if (rGradient.GetBorder() >= 100.0)
|
2014-11-11 15:54:03 -05:00
|
|
|
{
|
2016-08-04 16:21:47 +09:00
|
|
|
VCL_GL_INFO("::drawGradient -> DrawRect (no gradient)");
|
|
|
|
|
|
|
|
Color aColor = rGradient.GetStartColor();
|
|
|
|
long nIntensity = rGradient.GetStartIntensity();
|
2018-03-14 11:11:02 +02:00
|
|
|
if (UseSolid(Color(aColor.GetRed() * nIntensity / 100.0,
|
2016-08-04 16:21:47 +09:00
|
|
|
aColor.GetGreen()* nIntensity / 100.0,
|
|
|
|
aColor.GetBlue() * nIntensity / 100.0)))
|
|
|
|
{
|
|
|
|
DrawRect(aBoundRect);
|
|
|
|
}
|
2014-11-11 15:54:03 -05:00
|
|
|
}
|
2016-09-02 10:53:14 +02:00
|
|
|
else if (rGradient.GetStyle() == GradientStyle::Linear)
|
2014-11-11 05:13:40 -05:00
|
|
|
{
|
2016-08-04 16:21:47 +09:00
|
|
|
VCL_GL_INFO("::drawGradient -> DrawLinearGradient");
|
|
|
|
DrawLinearGradient(rGradient, aBoundRect);
|
2014-11-11 05:13:40 -05:00
|
|
|
}
|
2016-09-02 10:53:14 +02:00
|
|
|
else if (rGradient.GetStyle() == GradientStyle::Axial)
|
2014-11-14 01:16:28 -05:00
|
|
|
{
|
2016-08-04 16:21:47 +09:00
|
|
|
VCL_GL_INFO("::drawGradient -> DrawAxialGradient");
|
|
|
|
DrawAxialGradient(rGradient, aBoundRect);
|
2014-11-14 01:16:28 -05:00
|
|
|
}
|
2016-09-02 10:53:14 +02:00
|
|
|
else if (rGradient.GetStyle() == GradientStyle::Radial)
|
2014-11-11 15:54:03 -05:00
|
|
|
{
|
2016-08-04 16:21:47 +09:00
|
|
|
VCL_GL_INFO("::drawGradient -> DrawRadialGradient");
|
|
|
|
DrawRadialGradient(rGradient, aBoundRect);
|
2014-11-11 15:54:03 -05:00
|
|
|
}
|
2014-11-12 18:11:34 -05:00
|
|
|
|
2014-11-15 17:33:36 +01:00
|
|
|
#if FIXME_BROKEN_STENCIL_FOR_GRADIENTS
|
2014-11-12 18:11:34 -05:00
|
|
|
if( !mbUseStencil )
|
2015-11-17 09:20:25 +02:00
|
|
|
{
|
2016-11-28 16:39:26 +01:00
|
|
|
mpContext->state().stencil().disable();
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
|
|
|
}
|
2014-11-15 17:33:36 +01:00
|
|
|
#endif
|
2014-11-12 18:11:34 -05:00
|
|
|
PostDraw();
|
|
|
|
|
|
|
|
return true;
|
2014-10-29 17:25:55 +01:00
|
|
|
}
|
|
|
|
|
2015-11-13 12:00:59 +00:00
|
|
|
void OpenGLSalGraphicsImpl::flush()
|
2014-11-04 17:29:49 -05:00
|
|
|
{
|
2016-03-14 11:20:19 +01:00
|
|
|
FlushDeferredDrawing();
|
|
|
|
|
2015-11-13 12:00:59 +00:00
|
|
|
if( IsOffscreen() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if( !Application::IsInExecute() )
|
|
|
|
{
|
|
|
|
// otherwise nothing would trigger idle rendering
|
|
|
|
doFlush();
|
|
|
|
}
|
|
|
|
else if( !mpFlush->IsActive() )
|
|
|
|
mpFlush->Start();
|
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLSalGraphicsImpl::doFlush()
|
|
|
|
{
|
2016-03-14 11:20:19 +01:00
|
|
|
FlushDeferredDrawing();
|
|
|
|
|
2016-05-10 12:50:38 +03:00
|
|
|
if (OpenGLContext::hasCurrent())
|
|
|
|
{
|
2016-11-28 16:39:26 +01:00
|
|
|
mpContext->state().scissor().disable();
|
|
|
|
mpContext->state().stencil().disable();
|
2016-05-10 12:50:38 +03:00
|
|
|
}
|
2016-04-28 19:34:37 +09:00
|
|
|
|
2015-11-13 12:00:59 +00:00
|
|
|
if( IsOffscreen() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if( !maOffscreenTex )
|
|
|
|
{
|
2016-05-11 14:52:38 +03:00
|
|
|
VCL_GL_INFO( "doFlush - odd no texture !" );
|
2015-11-13 12:00:59 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-12-10 18:31:04 +00:00
|
|
|
if( mnDrawCountAtFlush == mnDrawCount )
|
2015-11-13 12:00:59 +00:00
|
|
|
{
|
2016-05-11 14:52:38 +03:00
|
|
|
VCL_GL_INFO( "eliding redundant doFlush, no drawing since last!" );
|
2015-11-13 12:00:59 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mnDrawCountAtFlush = mnDrawCount;
|
|
|
|
|
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2016-05-11 14:52:38 +03:00
|
|
|
VCL_GL_INFO( "doFlush" );
|
2015-11-13 12:00:59 +00:00
|
|
|
|
2015-12-10 18:31:04 +00:00
|
|
|
if( !mpWindowContext.is() )
|
|
|
|
{
|
2016-01-01 17:45:06 +00:00
|
|
|
// ensure everything is released from the old context.
|
|
|
|
OpenGLContext::clearCurrent();
|
2015-12-10 18:31:04 +00:00
|
|
|
mpWindowContext = CreateWinContext();
|
2016-01-01 17:45:06 +00:00
|
|
|
VCL_GL_INFO( "late creation of window context" );
|
2015-12-10 18:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
assert( mpWindowContext.is() );
|
|
|
|
|
2017-04-19 13:15:03 +01:00
|
|
|
if( !mpWindowContext.is() )
|
|
|
|
{
|
|
|
|
// failed to create a GL context for this window:
|
|
|
|
// eg. mis-matching pixel formats, underlying window
|
|
|
|
// resource lifecycle, etc.
|
|
|
|
VCL_GL_INFO( "Failed to create window context" );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-11-13 12:00:59 +00:00
|
|
|
// Interesting ! -> this destroys a context [ somehow ] ...
|
|
|
|
mpWindowContext->makeCurrent();
|
|
|
|
CHECK_GL_ERROR();
|
|
|
|
|
2016-05-11 14:52:38 +03:00
|
|
|
VCL_GL_INFO( "doFlush - acquire default framebuffer" );
|
2015-11-13 12:00:59 +00:00
|
|
|
|
|
|
|
mpWindowContext->AcquireDefaultFramebuffer();
|
2016-07-28 21:45:56 +09:00
|
|
|
|
2015-11-13 12:00:59 +00:00
|
|
|
CHECK_GL_ERROR();
|
|
|
|
|
2016-11-28 16:39:26 +01:00
|
|
|
mpWindowContext->state().sync();
|
2017-03-30 20:27:55 +02:00
|
|
|
mpWindowContext->state().viewport(tools::Rectangle(Point(0, 0), Size(GetWidth(), GetHeight())));
|
2016-11-28 16:39:26 +01:00
|
|
|
mpWindowContext->state().scissor().disable();
|
|
|
|
mpWindowContext->state().stencil().disable();
|
2016-04-28 19:34:37 +09:00
|
|
|
|
2015-11-13 12:00:59 +00:00
|
|
|
#if OSL_DEBUG_LEVEL > 0 // random background glClear
|
2019-08-10 13:03:32 +02:00
|
|
|
glClearColor(static_cast<float>(double(rand())/RAND_MAX),
|
|
|
|
static_cast<float>(double(rand())/RAND_MAX),
|
|
|
|
static_cast<float>(double(rand())/RAND_MAX), 1.0);
|
2015-11-13 12:00:59 +00:00
|
|
|
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
|
|
|
|
CHECK_GL_ERROR();
|
2016-07-28 21:45:56 +09:00
|
|
|
#endif
|
2015-11-13 12:00:59 +00:00
|
|
|
|
|
|
|
VCL_GL_INFO( "Texture height " << maOffscreenTex.GetHeight() << " vs. window height " << GetHeight() );
|
|
|
|
|
2016-07-28 21:45:56 +09:00
|
|
|
OpenGLFramebuffer* pFrameBuffer = mpWindowContext->AcquireFramebuffer(maOffscreenTex);
|
|
|
|
CHECK_GL_ERROR();
|
|
|
|
if (pFrameBuffer)
|
2015-11-13 12:00:59 +00:00
|
|
|
{
|
2016-07-28 21:45:56 +09:00
|
|
|
OpenGLFramebuffer::Unbind(GL_DRAW_FRAMEBUFFER);
|
|
|
|
pFrameBuffer->Bind(GL_READ_FRAMEBUFFER);
|
2015-11-13 12:00:59 +00:00
|
|
|
|
2016-07-28 21:45:56 +09:00
|
|
|
glBlitFramebuffer(0, 0, GetWidth(), GetHeight(),
|
|
|
|
0, 0, GetWidth(), GetHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
|
|
|
CHECK_GL_ERROR();
|
2015-11-13 12:00:59 +00:00
|
|
|
|
2016-07-28 21:45:56 +09:00
|
|
|
pFrameBuffer->Bind();
|
2015-11-13 12:00:59 +00:00
|
|
|
}
|
|
|
|
|
2016-07-28 21:45:56 +09:00
|
|
|
static bool bNoSwap = getenv("SAL_GL_NO_SWAP");
|
|
|
|
if (!bNoSwap)
|
|
|
|
mpWindowContext->swapBuffers();
|
|
|
|
|
2016-05-11 14:52:38 +03:00
|
|
|
VCL_GL_INFO( "doFlush - end." );
|
2014-11-04 17:29:49 -05:00
|
|
|
}
|
|
|
|
|
2014-10-23 23:23:26 +02:00
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|