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 .
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "openglgdiimpl.hxx"
|
|
|
|
|
2014-10-29 17:25:55 +01:00
|
|
|
#include <vcl/gradient.hxx>
|
2014-11-03 11:08:24 -05:00
|
|
|
#include <salframe.hxx>
|
2014-11-08 19:23:16 +01: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>
|
2014-10-29 13:05:02 -04:00
|
|
|
|
2014-10-29 22:30:55 +01:00
|
|
|
#include <vcl/opengl/OpenGLHelper.hxx>
|
2014-11-13 21:30:05 -05:00
|
|
|
#include "salgdi.hxx"
|
2014-11-22 07:58:38 -05:00
|
|
|
#include "svdata.hxx"
|
2015-08-20 17:03:30 +01:00
|
|
|
#include "opengl/zone.hxx"
|
2014-10-30 22:00:37 -04:00
|
|
|
#include "opengl/salbmp.hxx"
|
2014-10-29 22:30:55 +01:00
|
|
|
|
2014-11-06 03:37:47 +01:00
|
|
|
#include <vector>
|
|
|
|
|
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.
|
|
|
|
SetPriority( SchedulerPriority::POST_PAINT );
|
2015-11-13 12:00:59 +00:00
|
|
|
}
|
2015-12-11 15:07:29 +01:00
|
|
|
virtual ~OpenGLFlushIdle()
|
2015-11-13 12:00:59 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
virtual void Invoke() override
|
|
|
|
{
|
|
|
|
m_pImpl->doFlush();
|
2016-01-12 21:02:01 +00:00
|
|
|
SetPriority( SchedulerPriority::HIGHEST );
|
2015-11-13 12:00:59 +00:00
|
|
|
Stop();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-12-15 20:00:45 +01:00
|
|
|
OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl(SalGraphics& rParent, SalGeometryProvider *pProvider)
|
2015-11-10 10:28:29 +01:00
|
|
|
: mpContext(nullptr)
|
2014-12-15 20:00:45 +01:00
|
|
|
, mrParent(rParent)
|
|
|
|
, 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)
|
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)
|
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" );
|
|
|
|
|
|
|
|
delete mpFlush;
|
|
|
|
|
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
|
|
|
{
|
2015-12-10 18:31:04 +00:00
|
|
|
if( !AcquireContext(true) )
|
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
|
|
|
}
|
|
|
|
|
|
|
|
bool OpenGLSalGraphicsImpl::ReleaseContext()
|
|
|
|
{
|
2015-09-07 22:21:15 +01:00
|
|
|
mpContext.clear();
|
|
|
|
|
2014-11-22 07:58:38 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
{
|
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()
|
|
|
|
{
|
|
|
|
// 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)
|
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
|
|
|
|
2014-11-10 13:06:38 -05:00
|
|
|
glViewport( 0, 0, GetWidth(), GetHeight() );
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
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);
|
|
|
|
}
|
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();
|
|
|
|
}
|
|
|
|
|
2014-11-12 15:37:11 -05:00
|
|
|
if( mbUseScissor )
|
2015-11-17 09:20:25 +02:00
|
|
|
{
|
2014-11-12 15:37:11 -05:00
|
|
|
glDisable( GL_SCISSOR_TEST );
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
|
|
|
}
|
2015-11-13 12:00:59 +00:00
|
|
|
if( mbUseStencil )
|
|
|
|
{
|
2014-11-12 15:37:11 -05:00
|
|
|
glDisable( GL_STENCIL_TEST );
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
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();
|
|
|
|
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 )
|
|
|
|
{
|
|
|
|
glEnable( GL_STENCIL_TEST );
|
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();
|
2014-11-28 14:56:08 -05:00
|
|
|
if( UseSolid( MAKE_SALCOLOR( 0xFF, 0xFF, 0xFF ) ) )
|
|
|
|
{
|
|
|
|
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();
|
2014-11-12 18:11:34 -05:00
|
|
|
glDisable( GL_STENCIL_TEST );
|
2014-11-14 15:43:44 +01:00
|
|
|
CHECK_GL_ERROR();
|
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
|
|
|
|
if( maClipRegion != mpContext->maClipRegion )
|
2014-11-12 15:37:11 -05:00
|
|
|
{
|
2014-11-22 08:07:47 -05:00
|
|
|
mpContext->maClipRegion = maClipRegion;
|
2015-11-13 12:00:59 +00:00
|
|
|
if( mbUseScissor )
|
2014-11-22 08:07:47 -05:00
|
|
|
{
|
|
|
|
Rectangle aRect( maClipRegion.GetBoundRect() );
|
2016-01-02 10:54:40 +00:00
|
|
|
glScissor( aRect.Left(), GetHeight() - aRect.Bottom() - 1, aRect.GetWidth(), aRect.GetHeight() );
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2014-11-22 08:07:47 -05:00
|
|
|
}
|
|
|
|
else if( !maClipRegion.IsEmpty() )
|
|
|
|
{
|
|
|
|
ImplSetClipBit( maClipRegion, 0x01 );
|
|
|
|
}
|
2014-11-12 15:37:11 -05:00
|
|
|
}
|
2014-10-29 13:05:02 -04:00
|
|
|
|
2014-11-22 08:07:47 -05:00
|
|
|
if( mbUseScissor )
|
2015-11-17 09:20:25 +02:00
|
|
|
{
|
2014-11-22 08:07:47 -05:00
|
|
|
glEnable( GL_SCISSOR_TEST );
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
|
|
|
}
|
2014-11-22 08:07:47 -05: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();
|
2014-11-22 08:07:47 -05:00
|
|
|
glEnable( GL_STENCIL_TEST );
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
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 )
|
|
|
|
{
|
2015-11-20 10:14:49 +01: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;
|
|
|
|
if( maClipRegion.IsRectangle() )
|
2014-11-12 15:37:11 -05:00
|
|
|
mbUseScissor = true;
|
2014-11-22 08:07:47 -05: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()
|
|
|
|
{
|
2015-11-20 10:14:49 +01: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
|
2014-10-29 13:05:02 -04:00
|
|
|
void OpenGLSalGraphicsImpl::SetLineColor( SalColor nSalColor )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2014-10-29 13:05:02 -04:00
|
|
|
if( mnLineColor != nSalColor )
|
|
|
|
{
|
|
|
|
mnLineColor = nSalColor;
|
|
|
|
}
|
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
|
2014-10-29 13:05:02 -04:00
|
|
|
void OpenGLSalGraphicsImpl::SetFillColor( SalColor nSalColor )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2014-10-29 13:05:02 -04:00
|
|
|
if( mnFillColor != nSalColor )
|
|
|
|
{
|
|
|
|
mnFillColor = nSalColor;
|
|
|
|
}
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// enable/disable XOR drawing
|
2016-01-08 22:33:11 +00:00
|
|
|
void OpenGLSalGraphicsImpl::SetXORMode( bool bSet, bool )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2016-01-08 22:33:11 +00:00
|
|
|
mbXORMode = bSet;
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// set line color for raster operations
|
|
|
|
void OpenGLSalGraphicsImpl::SetROPLineColor( SalROPColor /*nROPColor*/ )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// set fill color for raster operations
|
|
|
|
void OpenGLSalGraphicsImpl::SetROPFillColor( SalROPColor /*nROPColor*/ )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-11-13 21:38:58 -05:00
|
|
|
bool OpenGLSalGraphicsImpl::CheckOffscreenTexture()
|
|
|
|
{
|
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() );
|
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?
|
|
|
|
OpenGLTexture aNewTex = OpenGLTexture( GetWidth(), GetHeight() );
|
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.
|
|
|
|
GLfloat clearColor[4] = { 1.0, 0, 0, 0 };
|
|
|
|
#else
|
|
|
|
GLfloat clearColor[4] = { 1.0, 1.0, 1.0, 0 };
|
|
|
|
#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
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2014-11-28 14:56:08 -05:00
|
|
|
bool OpenGLSalGraphicsImpl::UseSolid( SalColor 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;
|
2014-11-28 14:56:08 -05:00
|
|
|
if( !UseProgram( "dumbVertexShader", "solidFragmentShader" ) )
|
2014-11-17 09:15:15 -05:00
|
|
|
return false;
|
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;
|
|
|
|
}
|
|
|
|
|
2014-11-28 14:56:08 -05:00
|
|
|
bool OpenGLSalGraphicsImpl::UseSolid( SalColor 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;
|
2014-11-28 14:56:08 -05:00
|
|
|
if( !UseProgram( "dumbVertexShader", "solidFragmentShader" ) )
|
2014-10-29 13:05:02 -04:00
|
|
|
return false;
|
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;
|
|
|
|
}
|
|
|
|
|
2015-12-31 21:19:48 +00:00
|
|
|
bool OpenGLSalGraphicsImpl::UseInvert50()
|
|
|
|
{
|
|
|
|
if( !UseProgram( "dumbVertexShader", "invert50FragmentShader" ) )
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-11-28 14:56:08 -05:00
|
|
|
bool OpenGLSalGraphicsImpl::UseSolid( SalColor 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
|
|
|
}
|
|
|
|
|
2014-12-15 20:00:45 +01:00
|
|
|
// Like UseSolid(), but sets up for AA drawing, which uses gradients to create the AA.
|
2014-12-18 11:47:58 +01:00
|
|
|
bool OpenGLSalGraphicsImpl::UseSolidAA( SalColor nColor, double fTransparency )
|
2014-12-15 20:00:45 +01:00
|
|
|
{
|
2015-01-19 22:36:40 +01:00
|
|
|
if( nColor == SALCOLOR_NONE )
|
|
|
|
return false;
|
2014-12-15 20:00:45 +01:00
|
|
|
if( !mrParent.getAntiAliasB2DDraw())
|
|
|
|
return UseSolid( nColor );
|
|
|
|
if( !UseProgram( "textureVertexShader", "linearGradientFragmentShader" ) )
|
|
|
|
return false;
|
2015-01-07 18:06:25 +01:00
|
|
|
mpProgram->SetColorf( "start_color", nColor, fTransparency );
|
|
|
|
mpProgram->SetColorf( "end_color", nColor, 1.0f );
|
2014-12-15 20:00:45 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-12-18 11:47:58 +01:00
|
|
|
bool OpenGLSalGraphicsImpl::UseSolidAA( SalColor nColor )
|
|
|
|
{
|
2015-01-07 18:06:25 +01:00
|
|
|
return UseSolidAA( nColor, 0.0 );
|
2014-12-18 11:47:58 +01: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;
|
|
|
|
|
2015-12-31 21:19:48 +00:00
|
|
|
if( ( nFlags & SAL_INVERT_50 ) ||
|
|
|
|
( nFlags & SAL_INVERT_TRACKFRAME ) )
|
|
|
|
{
|
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
|
|
|
|
{
|
|
|
|
if( !UseSolid( MAKE_SALCOLOR( 255, 255, 255 ) ) )
|
|
|
|
return false;
|
|
|
|
mpProgram->SetBlendMode( GL_ONE_MINUS_DST_COLOR, GL_ZERO );
|
|
|
|
}
|
2014-11-11 05:13:40 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-10-29 13:05:02 -04:00
|
|
|
void OpenGLSalGraphicsImpl::DrawPoint( long nX, long nY )
|
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2014-11-08 22:59:09 -05:00
|
|
|
GLfloat pPoint[2];
|
2014-10-29 13:05:02 -04:00
|
|
|
|
2015-07-08 18:43:32 +09:00
|
|
|
pPoint[0] = GLfloat(nX);
|
|
|
|
pPoint[1] = GLfloat(nY);
|
2014-10-29 13:05:02 -04:00
|
|
|
|
2015-07-08 18:43:32 +09:00
|
|
|
ApplyProgramMatrices(0.5f);
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetVertices( pPoint );
|
2014-10-29 13:05:02 -04:00
|
|
|
glDrawArrays( GL_POINTS, 0, 1 );
|
2015-03-20 13:42:56 +01:00
|
|
|
CHECK_GL_ERROR();
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
|
2014-12-18 11:47:58 +01:00
|
|
|
void OpenGLSalGraphicsImpl::DrawLine( double nX1, double nY1, double nX2, double nY2 )
|
2014-10-29 13:05:02 -04:00
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2014-12-15 20:00:45 +01:00
|
|
|
GLfloat pPoints[4];
|
|
|
|
|
2015-07-08 18:43:32 +09:00
|
|
|
pPoints[0] = GLfloat(nX1);
|
|
|
|
pPoints[1] = GLfloat(nY1);
|
|
|
|
pPoints[2] = GLfloat(nX2);
|
|
|
|
pPoints[3] = GLfloat(nY2);
|
2014-12-15 20:00:45 +01:00
|
|
|
|
2015-07-08 18:43:32 +09:00
|
|
|
ApplyProgramMatrices(0.5f);
|
2014-12-15 20:00:45 +01:00
|
|
|
mpProgram->SetVertices( pPoints );
|
|
|
|
glDrawArrays( GL_LINES, 0, 2 );
|
2015-03-20 13:42:56 +01:00
|
|
|
CHECK_GL_ERROR();
|
2014-12-15 20:00:45 +01:00
|
|
|
}
|
|
|
|
|
2014-12-18 11:47:58 +01:00
|
|
|
void OpenGLSalGraphicsImpl::DrawLineAA( double nX1, double nY1, double nX2, double nY2 )
|
2014-12-15 20:00:45 +01:00
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2014-12-15 20:00:45 +01:00
|
|
|
if( !mrParent.getAntiAliasB2DDraw())
|
|
|
|
return DrawLine( nX1, nY1, nX2, nY2 );
|
|
|
|
|
2014-12-15 13:05:35 +01:00
|
|
|
if( nX1 == nX2 || nY1 == nY2 )
|
2014-12-15 20:00:45 +01:00
|
|
|
{ // Horizontal/vertical, no need for AA, both points have normal color.
|
2014-10-29 13:05:02 -04:00
|
|
|
|
2014-12-15 20:00:45 +01:00
|
|
|
// Still set up for the trivial "gradients", because presumably UseSolidAA() has been called.
|
|
|
|
GLfloat aTexCoord[4] = { 0, 1, 1, 1 };
|
|
|
|
mpProgram->SetTextureCoord( aTexCoord );
|
2015-07-08 18:43:32 +09:00
|
|
|
DrawLine(nX1, nY1, nX2, nY2);
|
2014-12-15 20:00:45 +01:00
|
|
|
|
2014-12-15 13:05:35 +01:00
|
|
|
return;
|
|
|
|
}
|
2015-01-12 13:24:47 +01:00
|
|
|
ImplDrawLineAA( nX1, nY1, nX2, nY2 );
|
|
|
|
}
|
2014-10-29 13:05:02 -04:00
|
|
|
|
2015-01-12 13:24:47 +01:00
|
|
|
void OpenGLSalGraphicsImpl::ImplDrawLineAA( double nX1, double nY1, double nX2, double nY2, bool edge )
|
|
|
|
{
|
2014-12-15 13:05:35 +01:00
|
|
|
// Draw the line anti-aliased. Based on code with the following notice:
|
|
|
|
/* Drawing nearly perfect 2D line segments in OpenGL
|
|
|
|
* You can use this code however you want.
|
|
|
|
* I just hope you to cite my name and the page of this technique:
|
|
|
|
* http://artgrammer.blogspot.com/2011/05/drawing-nearly-perfect-2d-line-segments.html
|
|
|
|
* http://www.codeproject.com/KB/openGL/gllinedraw.aspx
|
|
|
|
*
|
|
|
|
* Enjoy. Chris Tsang.*/
|
2014-10-29 13:05:02 -04:00
|
|
|
|
2014-12-15 13:05:35 +01:00
|
|
|
double x1 = nX1;
|
|
|
|
double y1 = nY1;
|
|
|
|
double x2 = nX2;
|
|
|
|
double y2 = nY2;
|
2015-01-12 13:24:47 +01:00
|
|
|
|
|
|
|
// A special hack for drawing lines that are in fact AA edges of a shape. Make the line somewhat
|
|
|
|
// wider, but (done further below) draw the entire width as a gradient. This would be wrong for a line
|
|
|
|
// (too wide and seemingly less straight), but it makes the edges look smoother and the width difference
|
|
|
|
// is almost unnoticeable.
|
|
|
|
const double w = edge ? 1.4 : 1.0;
|
2014-12-15 13:05:35 +01:00
|
|
|
|
2015-01-12 20:22:17 +00:00
|
|
|
double t(0.0);
|
|
|
|
double R(0.0);
|
2015-01-12 13:24:47 +01:00
|
|
|
double f = w - static_cast<int>(w);
|
2014-12-15 13:05:35 +01:00
|
|
|
//determine parameters t,R
|
2015-01-12 13:24:47 +01:00
|
|
|
if ( w>=0.0 && w<1.0 )
|
|
|
|
{
|
|
|
|
t=0.05;
|
|
|
|
R=0.48+0.32*f;
|
|
|
|
}
|
|
|
|
else if ( w>=1.0 && w<2.0 )
|
|
|
|
{
|
|
|
|
t=0.05+f*0.33;
|
|
|
|
R=0.768+0.312*f;
|
|
|
|
}
|
|
|
|
else if ( w>=2.0 && w<3.0 )
|
|
|
|
{
|
|
|
|
t=0.38+f*0.58;
|
|
|
|
R=1.08;
|
|
|
|
}
|
|
|
|
else if ( w>=3.0 && w<4.0 )
|
|
|
|
{
|
|
|
|
t=0.96+f*0.48;
|
|
|
|
R=1.08;
|
|
|
|
}
|
|
|
|
else if ( w>=4.0 && w<5.0 )
|
|
|
|
{
|
|
|
|
t=1.44+f*0.46;
|
|
|
|
R=1.08;
|
|
|
|
}
|
|
|
|
else if ( w>=5.0 && w<6.0 )
|
|
|
|
{
|
|
|
|
t=1.9+f*0.6;
|
|
|
|
R=1.08;
|
|
|
|
}
|
|
|
|
else if ( w>=6.0 )
|
|
|
|
{
|
|
|
|
double ff=w-6.0;
|
|
|
|
t=2.5+ff*0.50;
|
|
|
|
R=1.08;
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
|
2014-12-15 13:05:35 +01:00
|
|
|
//determine angle of the line to horizontal
|
|
|
|
double tx=0,ty=0; //core thinkness of a line
|
|
|
|
double Rx=0,Ry=0; //fading edge of a line
|
|
|
|
double dx=x2-x1;
|
|
|
|
double dy=y2-y1;
|
2015-01-12 13:24:47 +01:00
|
|
|
if ( w < 3 )
|
2014-12-15 13:05:35 +01:00
|
|
|
{ //approximate to make things even faster
|
|
|
|
double m=dy/dx;
|
|
|
|
//and calculate tx,ty,Rx,Ry
|
|
|
|
if ( m>-0.4142 && m<=0.4142)
|
|
|
|
{
|
|
|
|
// -22.5< angle <= 22.5, approximate to 0 (degree)
|
|
|
|
tx=t*0.1; ty=t;
|
|
|
|
Rx=R*0.6; Ry=R;
|
|
|
|
}
|
|
|
|
else if ( m>0.4142 && m<=2.4142)
|
|
|
|
{
|
|
|
|
// 22.5< angle <= 67.5, approximate to 45 (degree)
|
|
|
|
tx=t*-0.7071; ty=t*0.7071;
|
|
|
|
Rx=R*-0.7071; Ry=R*0.7071;
|
|
|
|
}
|
|
|
|
else if ( m>2.4142 || m<=-2.4142)
|
|
|
|
{
|
|
|
|
// 67.5 < angle <=112.5, approximate to 90 (degree)
|
|
|
|
tx=t; ty=t*0.1;
|
|
|
|
Rx=R; Ry=R*0.6;
|
|
|
|
}
|
|
|
|
else if ( m>-2.4142 && m<-0.4142)
|
|
|
|
{
|
|
|
|
// 112.5 < angle < 157.5, approximate to 135 (degree)
|
|
|
|
tx=t*0.7071; ty=t*0.7071;
|
|
|
|
Rx=R*0.7071; Ry=R*0.7071;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
assert( false );
|
|
|
|
}
|
2014-10-29 13:05:02 -04:00
|
|
|
else
|
2014-12-15 13:05:35 +01:00
|
|
|
{ //calculate to exact
|
|
|
|
dx=y1-y2;
|
|
|
|
dy=x2-x1;
|
|
|
|
double L=sqrt(dx*dx+dy*dy);
|
|
|
|
dx/=L;
|
|
|
|
dy/=L;
|
|
|
|
tx=t*dx; ty=t*dy;
|
|
|
|
Rx=R*dx; Ry=R*dy;
|
|
|
|
}
|
|
|
|
|
2015-01-12 13:24:47 +01:00
|
|
|
if( edge )
|
|
|
|
{ // See above.
|
|
|
|
Rx += tx;
|
|
|
|
Ry += ty;
|
|
|
|
tx = ty = 0;
|
|
|
|
}
|
|
|
|
|
2014-12-15 13:05:35 +01:00
|
|
|
GLfloat vertices[]=
|
|
|
|
{
|
2015-07-08 18:43:32 +09:00
|
|
|
GLfloat(x1-tx-Rx), GLfloat(y1-ty-Ry), //fading edge1
|
|
|
|
GLfloat(x2-tx-Rx), GLfloat(y2-ty-Ry),
|
|
|
|
GLfloat(x1-tx), GLfloat(y1-ty), //core
|
|
|
|
GLfloat(x2-tx), GLfloat(y2-ty),
|
|
|
|
GLfloat(x1+tx), GLfloat(y1+ty),
|
|
|
|
GLfloat(x2+tx), GLfloat(y2+ty),
|
|
|
|
GLfloat(x1+tx+Rx), GLfloat(y1+ty+Ry), //fading edge2
|
|
|
|
GLfloat(x2+tx+Rx), GLfloat(y2+ty+Ry)
|
2014-12-15 13:05:35 +01:00
|
|
|
};
|
|
|
|
|
2015-07-08 18:43:32 +09:00
|
|
|
ApplyProgramMatrices(0.0f);
|
2014-12-15 13:05:35 +01:00
|
|
|
GLfloat aTexCoord[16] = { 0, 0, 1, 0, 2, 1, 3, 1, 4, 1, 5, 1, 6, 0, 7, 0 };
|
|
|
|
mpProgram->SetTextureCoord( aTexCoord );
|
|
|
|
mpProgram->SetVertices( vertices );
|
|
|
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
|
2015-03-20 13:42:56 +01:00
|
|
|
CHECK_GL_ERROR();
|
2014-12-15 13:05:35 +01:00
|
|
|
}
|
|
|
|
|
2014-10-29 13:05:02 -04:00
|
|
|
|
2014-12-15 20:00:45 +01:00
|
|
|
void OpenGLSalGraphicsImpl::DrawLinesAA( sal_uInt32 nPoints, const SalPoint* pPtAry, bool bClose )
|
|
|
|
{
|
|
|
|
for( int i = 0; i < int(nPoints) - 1; ++i )
|
|
|
|
DrawLineAA( pPtAry[ i ].mnX, pPtAry[ i ].mnY, pPtAry[ i + 1 ].mnX, pPtAry[ i + 1 ].mnY );
|
|
|
|
if( bClose )
|
|
|
|
DrawLineAA( pPtAry[ nPoints - 1 ].mnX, pPtAry[ nPoints - 1 ].mnY, pPtAry[ 0 ].mnX, pPtAry[ 0 ].mnY );
|
|
|
|
}
|
|
|
|
|
2015-01-12 13:24:47 +01:00
|
|
|
void OpenGLSalGraphicsImpl::DrawEdgeAA( double nX1, double nY1, double nX2, double nY2 )
|
|
|
|
{
|
|
|
|
assert( mrParent.getAntiAliasB2DDraw());
|
|
|
|
if( nX1 == nX2 || nY1 == nY2 )
|
|
|
|
return; //horizontal/vertical, no need for AA
|
|
|
|
ImplDrawLineAA( nX1, nY1, nX2, nY2, true );
|
|
|
|
}
|
|
|
|
|
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();
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetVertices( &aVertices[0] );
|
2014-10-29 13:05:02 -04:00
|
|
|
glDrawArrays( GL_TRIANGLE_FAN, 0, nPoints );
|
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
|
|
|
|
SalColor lastSolidColor = mProgramSolidColor;
|
|
|
|
double lastSolidTransparency = mProgramSolidTransparency;
|
|
|
|
if( UseSolidAA( lastSolidColor, lastSolidTransparency ))
|
|
|
|
{
|
|
|
|
for( i = 0; i < nPoints; ++i )
|
|
|
|
{
|
|
|
|
const SalPoint& rPt1 = pPtAry[ i ];
|
|
|
|
const SalPoint& rPt2 = pPtAry[ ( i + 1 ) % nPoints ];
|
|
|
|
DrawEdgeAA( rPt1.mnX, rPt1.mnY, rPt2.mnX, rPt2.mnY );
|
|
|
|
}
|
|
|
|
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();
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetVertices( &aVertices[0] );
|
2014-11-11 05:13:40 -05:00
|
|
|
glDrawArrays( GL_TRIANGLE_FAN, 0, nPoints );
|
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
|
2015-01-12 13:20:54 +01:00
|
|
|
SalColor lastSolidColor = mProgramSolidColor;
|
|
|
|
double lastSolidTransparency = mProgramSolidTransparency;
|
|
|
|
if( UseSolidAA( lastSolidColor, lastSolidTransparency ))
|
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 );
|
2015-01-12 13:24:47 +01:00
|
|
|
DrawEdgeAA( 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();
|
2015-01-18 19:00:32 +01:00
|
|
|
mpProgram->SetVertices( &aVertices[0] );
|
|
|
|
glDrawArrays( GL_TRIANGLE_FAN, 0, nPoints );
|
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
|
|
|
|
SalColor lastSolidColor = mProgramSolidColor;
|
|
|
|
double lastSolidTransparency = mProgramSolidTransparency;
|
|
|
|
if( UseSolidAA( lastSolidColor, lastSolidTransparency ))
|
|
|
|
{
|
|
|
|
for( i = 0; i < nPoints; ++i )
|
|
|
|
{
|
|
|
|
const basegfx::B2DPoint& rPt1 = rPolygon.getB2DPoint( i );
|
|
|
|
const basegfx::B2DPoint& rPt2 = rPolygon.getB2DPoint(( i + 1 ) % nPoints );
|
|
|
|
DrawEdgeAA( rPt1.getX(), rPt1.getY(), rPt2.getX(), rPt2.getY());
|
|
|
|
}
|
|
|
|
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
|
|
|
{
|
2014-10-29 13:05:02 -04:00
|
|
|
long nX1( nX );
|
2014-11-12 18:12:00 -05:00
|
|
|
long nY1( nY );
|
2014-11-03 11:10:14 -05:00
|
|
|
long nX2( nX + nWidth );
|
2014-11-12 18:12:00 -05:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2014-11-11 15:54:03 -05:00
|
|
|
void OpenGLSalGraphicsImpl::DrawRect( const Rectangle& rRect )
|
|
|
|
{
|
|
|
|
long nX1( rRect.Left() );
|
2014-11-12 18:12:00 -05:00
|
|
|
long nY1( rRect.Top() );
|
2014-11-11 15:54:03 -05:00
|
|
|
long nX2( rRect.Right() );
|
2014-11-12 18:12:00 -05:00
|
|
|
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 );
|
|
|
|
|
2015-12-15 15:31:50 +02:00
|
|
|
if( basegfx::tools::isConvex( aPolygon ) )
|
2014-10-29 13:05:02 -04:00
|
|
|
{
|
|
|
|
if( nPoints > 2L )
|
|
|
|
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
|
|
|
{
|
2015-12-15 15:31:50 +02:00
|
|
|
const basegfx::B2DPolyPolygon& aSimplePolyPolygon = ::basegfx::tools::solveCrossovers( rPolyPolygon );
|
2015-01-18 22:42:06 +01:00
|
|
|
basegfx::B2DTrapezoidVector aB2DTrapVector;
|
|
|
|
basegfx::tools::trapezoidSubdivide( aB2DTrapVector, aSimplePolyPolygon );
|
|
|
|
// draw tesselation result
|
|
|
|
if( aB2DTrapVector.size())
|
2014-12-18 11:47:58 +01:00
|
|
|
{
|
2015-01-18 22:42:06 +01:00
|
|
|
for( size_t i = 0; i < aB2DTrapVector.size(); ++i )
|
|
|
|
DrawTrapezoid( aB2DTrapVector[ i ], blockAA );
|
2014-12-18 11:47:58 +01:00
|
|
|
}
|
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
|
|
|
|
|
|
|
for( size_t i = 0; i < aRects.size(); ++i )
|
|
|
|
{
|
|
|
|
aRects[i].Bottom() += 1;
|
|
|
|
aRects[i].Right() += 1;
|
|
|
|
ADD_VERTICE( aRects[i].TopLeft() );
|
|
|
|
ADD_VERTICE( aRects[i].TopRight() );
|
|
|
|
ADD_VERTICE( aRects[i].BottomLeft() );
|
|
|
|
ADD_VERTICE( aRects[i].BottomLeft() );
|
|
|
|
ADD_VERTICE( aRects[i].TopRight() );
|
|
|
|
ADD_VERTICE( aRects[i].BottomRight() );
|
|
|
|
}
|
|
|
|
#undef ADD_VERTICE
|
|
|
|
|
2015-07-08 18:43:32 +09:00
|
|
|
ApplyProgramMatrices();
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetVertices( &aVertices[0] );
|
2014-11-22 08:09:29 -05:00
|
|
|
glDrawArrays( GL_TRIANGLES, 0, aVertices.size() / 2 );
|
2015-03-20 13:42:56 +01:00
|
|
|
CHECK_GL_ERROR();
|
2014-11-22 08:09:29 -05:00
|
|
|
}
|
|
|
|
|
2014-11-13 21:37:54 -05:00
|
|
|
void OpenGLSalGraphicsImpl::DrawTextureRect( 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 rect");
|
|
|
|
|
2014-11-03 22:51:15 -05:00
|
|
|
GLfloat aTexCoord[8];
|
2014-11-13 21:37:54 -05:00
|
|
|
rTexture.GetCoord( aTexCoord, rPosAry, bInverted );
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetTextureCoord( aTexCoord );
|
2014-11-03 22:51:15 -05:00
|
|
|
DrawRect( rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth, rPosAry.mnDestHeight );
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
2014-11-13 21:37:54 -05:00
|
|
|
void OpenGLSalGraphicsImpl::DrawTexture( OpenGLTexture& rTexture, const SalTwoRect& pPosAry, 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");
|
|
|
|
|
2014-11-28 14:56:08 -05:00
|
|
|
if( !UseProgram( "textureVertexShader", "textureFragmentShader" ) )
|
|
|
|
return;
|
|
|
|
mpProgram->SetTexture( "sampler", rTexture );
|
2014-11-13 21:37:54 -05:00
|
|
|
DrawTextureRect( rTexture, pPosAry, bInverted );
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->Clean();
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
2014-11-17 09:15:15 -05:00
|
|
|
GLfloat aVertices[8] = {
|
2014-11-28 14:56:08 -05:00
|
|
|
0, (float) rTexture.GetHeight(), 0, 0,
|
|
|
|
(float) rTexture.GetWidth(), 0, (float) rTexture.GetWidth(), (float) rTexture.GetHeight() };
|
2014-11-17 09:15:15 -05:00
|
|
|
GLfloat aTexCoord[8];
|
|
|
|
|
2015-01-20 15:41:51 +01:00
|
|
|
// If downscaling at a higher scale ratio, use the area scaling algorithm rather
|
|
|
|
// than plain OpenGL's scaling, for better results.
|
|
|
|
// See OpenGLSalBitmap::ImplScaleArea().
|
|
|
|
double ixscale = rTexture.GetWidth() / fabs( rX.getX() - rNull.getX());
|
|
|
|
double iyscale = rTexture.GetHeight() / fabs( rY.getY() - rNull.getY());
|
|
|
|
bool areaScaling = false;
|
|
|
|
bool fastAreaScaling = false;
|
|
|
|
OUString textureFragmentShader;
|
|
|
|
if( ixscale >= 2 && iyscale >= 2 ) // Downscaling to 50% or less? (inverted scale ratios)
|
|
|
|
{
|
|
|
|
areaScaling = true;
|
|
|
|
fastAreaScaling = ( ixscale == int( ixscale ) && iyscale == int( iyscale ));
|
|
|
|
// The generic case has arrays only up to 100 ratio downscaling, 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).
|
|
|
|
if( ixscale > 100 || iyscale > 100 )
|
|
|
|
fastAreaScaling = true;
|
|
|
|
if( fastAreaScaling )
|
|
|
|
textureFragmentShader = "areaScaleFastFragmentShader";
|
|
|
|
else
|
|
|
|
textureFragmentShader = "areaScaleFragmentShader";
|
|
|
|
}
|
|
|
|
|
2014-11-17 09:15:15 -05:00
|
|
|
if( rMask )
|
|
|
|
{
|
2015-01-20 15:41:51 +01:00
|
|
|
if( !UseProgram( "transformedTextureVertexShader",
|
|
|
|
textureFragmentShader.isEmpty() ? "maskedTextureFragmentShader" : textureFragmentShader,
|
|
|
|
"#define MASKED" ) )
|
2014-11-28 14:56:08 -05:00
|
|
|
return;
|
|
|
|
mpProgram->SetTexture( "mask", rMask );
|
2015-08-24 15:00:26 +09:00
|
|
|
GLfloat aMaskCoord[8];
|
|
|
|
rMask.GetWholeCoord(aMaskCoord);
|
|
|
|
mpProgram->SetMaskCoord(aMaskCoord);
|
2014-11-17 09:15:15 -05:00
|
|
|
rMask.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",
|
|
|
|
textureFragmentShader.isEmpty() ? "textureFragmentShader" : textureFragmentShader ) )
|
2014-11-28 14:56:08 -05:00
|
|
|
return;
|
2014-11-17 09:15:15 -05:00
|
|
|
}
|
|
|
|
|
2015-01-31 19:06:52 +00:00
|
|
|
int mnWidth = rTexture.GetWidth();
|
|
|
|
int mnHeight = rTexture.GetHeight();
|
|
|
|
if(areaScaling )
|
2015-01-20 15:41:51 +01:00
|
|
|
{
|
|
|
|
// From OpenGLSalBitmap::ImplScaleArea().
|
2015-01-31 19:06:52 +00:00
|
|
|
if (fastAreaScaling && mnWidth && mnHeight)
|
2015-01-20 15:41:51 +01:00
|
|
|
{
|
|
|
|
mpProgram->SetUniform1i( "xscale", ixscale );
|
|
|
|
mpProgram->SetUniform1i( "yscale", iyscale );
|
|
|
|
mpProgram->SetUniform1f( "xstep", 1.0 / mnWidth );
|
|
|
|
mpProgram->SetUniform1f( "ystep", 1.0 / mnHeight );
|
|
|
|
mpProgram->SetUniform1f( "ratio", 1.0 / ( ixscale * iyscale ));
|
|
|
|
}
|
2015-01-31 19:06:52 +00:00
|
|
|
else if (mnHeight > 1 && mnWidth > 1)
|
2015-01-20 15:41:51 +01:00
|
|
|
{
|
|
|
|
mpProgram->SetUniform1f( "xscale", ixscale );
|
|
|
|
mpProgram->SetUniform1f( "yscale", iyscale );
|
|
|
|
mpProgram->SetUniform1i( "swidth", mnWidth );
|
|
|
|
mpProgram->SetUniform1i( "sheight", mnHeight );
|
|
|
|
// For converting between <0,mnWidth-1> and <0.0,1.0> coordinate systems.
|
|
|
|
mpProgram->SetUniform1f( "xsrcconvert", 1.0 / ( mnWidth - 1 ));
|
|
|
|
mpProgram->SetUniform1f( "ysrcconvert", 1.0 / ( mnHeight - 1 ));
|
|
|
|
mpProgram->SetUniform1f( "xdestconvert", 1.0 * (( mnWidth / ixscale ) - 1 ));
|
|
|
|
mpProgram->SetUniform1f( "ydestconvert", 1.0 * (( mnHeight / iyscale ) - 1 ));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-08 18:43:32 +09:00
|
|
|
ApplyProgramMatrices();
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetUniform2f( "viewport", GetWidth(), GetHeight() );
|
|
|
|
mpProgram->SetTransform( "transform", rTexture, rNull, rX, rY );
|
|
|
|
rTexture.GetWholeCoord( aTexCoord );
|
|
|
|
mpProgram->SetTexture( "sampler", rTexture );
|
2014-11-17 09:15:15 -05:00
|
|
|
rTexture.SetFilter( GL_LINEAR );
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->SetTextureCoord( aTexCoord );
|
|
|
|
mpProgram->SetVertices( &aVertices[0] );
|
2014-11-17 09:15:15 -05:00
|
|
|
glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
|
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;
|
|
|
|
|
2014-11-28 14:56:08 -05:00
|
|
|
if( !UseProgram( "textureVertexShader", "textureFragmentShader" ) )
|
|
|
|
return;
|
|
|
|
mpProgram->SetTexture( "sampler", rTexture );
|
|
|
|
mpProgram->SetBlendMode( bPremultiplied ? GL_ONE : GL_SRC_ALPHA,
|
|
|
|
GL_ONE_MINUS_SRC_ALPHA );
|
|
|
|
DrawTextureRect( rTexture, rPosAry, bInverted );
|
|
|
|
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;
|
|
|
|
|
2015-08-24 15:00:26 +09:00
|
|
|
if( !UseProgram( "maskedTextureVertexShader", "diffTextureFragmentShader" ) )
|
2014-11-28 14:56:08 -05:00
|
|
|
return;
|
|
|
|
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
|
|
|
|
|
|
|
GLfloat aMaskCoord[8];
|
|
|
|
rMask.GetCoord(aMaskCoord, rPosAry, bInverted);
|
|
|
|
mpProgram->SetMaskCoord(aMaskCoord);
|
|
|
|
|
2014-11-20 22:07:12 -05:00
|
|
|
DrawTextureRect( rTexture, rPosAry, bInverted );
|
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;
|
|
|
|
|
2015-08-24 15:00:26 +09:00
|
|
|
if( !UseProgram( "maskedTextureVertexShader", "maskedTextureFragmentShader" ) )
|
2014-11-28 14:56:08 -05:00
|
|
|
return;
|
|
|
|
mpProgram->SetTexture( "sampler", rTexture );
|
|
|
|
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);
|
|
|
|
|
|
|
|
GLfloat aMaskCoord[8];
|
|
|
|
rMask.GetCoord(aMaskCoord, rPosAry);
|
|
|
|
mpProgram->SetMaskCoord(aMaskCoord);
|
|
|
|
|
|
|
|
DrawRect(rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth, rPosAry.mnDestHeight);
|
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;
|
|
|
|
|
2014-11-28 14:56:08 -05:00
|
|
|
if( !UseProgram( "blendedTextureVertexShader", "blendedTextureFragmentShader" ) )
|
|
|
|
return;
|
|
|
|
mpProgram->SetTexture( "sampler", rTexture );
|
|
|
|
mpProgram->SetTexture( "mask", rMask );
|
|
|
|
mpProgram->SetTexture( "alpha", rAlpha );
|
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 );
|
2014-11-18 12:34:53 -05:00
|
|
|
DrawTextureRect( rTexture, rPosAry );
|
2014-11-28 14:56:08 -05:00
|
|
|
mpProgram->Clean();
|
2014-11-18 12:34:53 -05:00
|
|
|
}
|
|
|
|
|
2014-11-17 10:00:33 -05:00
|
|
|
void OpenGLSalGraphicsImpl::DrawMask( OpenGLTexture& rMask, SalColor nMaskColor, const SalTwoRect& pPosAry )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2015-08-20 17:03:30 +01:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2014-11-28 14:56:08 -05:00
|
|
|
if( !UseProgram( "textureVertexShader", "maskFragmentShader" ) )
|
|
|
|
return;
|
|
|
|
mpProgram->SetColor( "color", nMaskColor, 0 );
|
|
|
|
mpProgram->SetTexture( "sampler", rMask );
|
|
|
|
mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
2014-11-17 10:00:33 -05:00
|
|
|
DrawTextureRect( rMask, pPosAry );
|
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
|
|
|
|
2014-11-11 05:13:40 -05:00
|
|
|
void OpenGLSalGraphicsImpl::DrawLinearGradient( const Gradient& rGradient, const Rectangle& rRect )
|
|
|
|
{
|
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
|
|
|
|
|
|
|
Rectangle aBoundRect;
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2014-11-14 01:16:28 -05:00
|
|
|
void OpenGLSalGraphicsImpl::DrawAxialGradient( const Gradient& rGradient, const Rectangle& rRect )
|
|
|
|
{
|
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
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
Rectangle aRect;
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2014-11-11 15:54:03 -05:00
|
|
|
void OpenGLSalGraphicsImpl::DrawRadialGradient( const Gradient& rGradient, const Rectangle& rRect )
|
|
|
|
{
|
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
|
|
|
|
|
|
|
Rectangle aRect;
|
|
|
|
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 );
|
|
|
|
}
|
|
|
|
|
2014-10-29 13:05:02 -04:00
|
|
|
|
|
|
|
// draw --> LineColor and FillColor and RasterOp and ClipRegion
|
|
|
|
void OpenGLSalGraphicsImpl::drawPixel( long nX, long nY )
|
|
|
|
{
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::drawPixel" );
|
2014-10-29 13:05:02 -04:00
|
|
|
if( mnLineColor != SALCOLOR_NONE )
|
|
|
|
{
|
2016-01-08 22:33:11 +00:00
|
|
|
PreDraw( XOROption::IMPLEMENT_XOR );
|
2014-11-28 14:56:08 -05:00
|
|
|
if( UseSolid( mnLineColor ) )
|
|
|
|
DrawPoint( nX, nY );
|
2014-11-10 13:06:38 -05:00
|
|
|
PostDraw();
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLSalGraphicsImpl::drawPixel( long nX, long nY, SalColor nSalColor )
|
|
|
|
{
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::drawPixel" );
|
2014-10-29 13:05:02 -04:00
|
|
|
if( nSalColor != SALCOLOR_NONE )
|
|
|
|
{
|
2016-01-08 22:33:11 +00:00
|
|
|
PreDraw( XOROption::IMPLEMENT_XOR );
|
2014-11-28 14:56:08 -05:00
|
|
|
if( UseSolid( nSalColor ) )
|
|
|
|
DrawPoint( nX, nY );
|
2014-11-10 13:06:38 -05:00
|
|
|
PostDraw();
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLSalGraphicsImpl::drawLine( long nX1, long nY1, long nX2, long nY2 )
|
|
|
|
{
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::drawLine" );
|
2014-10-29 13:05:02 -04:00
|
|
|
if( mnLineColor != SALCOLOR_NONE )
|
|
|
|
{
|
2016-01-08 22:33:11 +00:00
|
|
|
PreDraw( XOROption::IMPLEMENT_XOR );
|
2014-12-15 20:00:45 +01:00
|
|
|
if( UseSolidAA( mnLineColor ) )
|
|
|
|
DrawLineAA( nX1, nY1, nX2, nY2 );
|
2014-11-10 13:06:38 -05:00
|
|
|
PostDraw();
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLSalGraphicsImpl::drawRect( long nX, long nY, long nWidth, long nHeight )
|
|
|
|
{
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::drawRect" );
|
2016-01-08 22:33:11 +00:00
|
|
|
PreDraw( XOROption::IMPLEMENT_XOR );
|
2014-10-30 21:57:22 -04:00
|
|
|
|
2014-11-28 14:56:08 -05:00
|
|
|
if( UseSolid( mnFillColor ) )
|
2014-10-29 13:05:02 -04:00
|
|
|
DrawRect( nX, nY, nWidth, nHeight );
|
|
|
|
|
2014-11-28 14:56:08 -05:00
|
|
|
if( UseSolid( mnLineColor ) )
|
2014-10-29 13:05:02 -04:00
|
|
|
{
|
2015-07-08 18:43:32 +09:00
|
|
|
GLfloat fX1(nX);
|
|
|
|
GLfloat fY1(nY);
|
|
|
|
GLfloat fX2(nX + nWidth - 1);
|
|
|
|
GLfloat fY2(nY + nHeight - 1);
|
2015-06-30 18:07:41 +09:00
|
|
|
|
2015-08-28 02:13:45 +02:00
|
|
|
GLfloat pPoints[8];
|
2015-06-30 18:07:41 +09:00
|
|
|
|
|
|
|
pPoints[0] = fX1;
|
|
|
|
pPoints[1] = fY1;
|
|
|
|
pPoints[2] = fX2;
|
|
|
|
pPoints[3] = fY1;
|
|
|
|
pPoints[4] = fX2;
|
|
|
|
pPoints[5] = fY2;
|
|
|
|
pPoints[6] = fX1;
|
|
|
|
pPoints[7] = fY2;
|
|
|
|
|
2015-07-08 18:43:32 +09:00
|
|
|
ApplyProgramMatrices(0.5f);
|
2015-06-30 18:07:41 +09:00
|
|
|
mpProgram->SetVertices(pPoints);
|
|
|
|
glDrawArrays(GL_LINE_LOOP, 0, 4);
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
2014-11-10 13:06:38 -05:00
|
|
|
|
|
|
|
PostDraw();
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLSalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry )
|
|
|
|
{
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::drawPolyLine" );
|
2014-10-30 21:57:22 -04:00
|
|
|
|
2014-10-29 13:05:02 -04:00
|
|
|
if( mnLineColor != SALCOLOR_NONE && nPoints > 1 )
|
|
|
|
{
|
2016-01-08 22:33:11 +00:00
|
|
|
PreDraw( XOROption::IMPLEMENT_XOR );
|
2014-12-15 20:00:45 +01:00
|
|
|
if( UseSolidAA( mnLineColor ) )
|
|
|
|
DrawLinesAA( nPoints, pPtAry, false );
|
2014-11-10 13:06:38 -05:00
|
|
|
PostDraw();
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLSalGraphicsImpl::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
|
|
|
|
{
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::drawPolygon" );
|
2014-10-29 13:05:02 -04:00
|
|
|
if( nPoints == 0 )
|
|
|
|
return;
|
|
|
|
if( nPoints == 1 )
|
|
|
|
{
|
|
|
|
drawPixel( pPtAry[0].mnX, pPtAry[0].mnY );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if( nPoints == 2 )
|
|
|
|
{
|
|
|
|
drawLine( pPtAry[0].mnX, pPtAry[0].mnY,
|
|
|
|
pPtAry[1].mnX, pPtAry[1].mnY );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-01-08 22:33:11 +00:00
|
|
|
PreDraw( XOROption::IMPLEMENT_XOR );
|
2014-10-30 21:57:22 -04:00
|
|
|
|
2014-11-28 14:56:08 -05:00
|
|
|
if( UseSolid( mnFillColor ) )
|
2014-10-29 13:05:02 -04:00
|
|
|
DrawPolygon( nPoints, pPtAry );
|
|
|
|
|
2014-12-15 20:00:45 +01:00
|
|
|
if( UseSolidAA( mnLineColor ) )
|
|
|
|
DrawLinesAA( nPoints, pPtAry, true );
|
2014-11-10 13:06:38 -05:00
|
|
|
|
|
|
|
PostDraw();
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLSalGraphicsImpl::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry )
|
|
|
|
{
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::drawPolyPolygon" );
|
2014-10-29 13:05:02 -04:00
|
|
|
if( nPoly <= 0 )
|
|
|
|
return;
|
|
|
|
|
2016-01-08 22:33:11 +00:00
|
|
|
PreDraw( XOROption::IMPLEMENT_XOR );
|
2014-10-30 21:57:22 -04:00
|
|
|
|
2014-11-28 14:56:08 -05:00
|
|
|
if( UseSolid( mnFillColor ) )
|
2014-10-29 13:05:02 -04:00
|
|
|
{
|
2015-01-18 22:42:06 +01:00
|
|
|
if( nPoly == 1 )
|
2015-01-19 22:33:29 +01:00
|
|
|
DrawPolygon( pPoints[ 0 ], pPtAry[ 0 ] );
|
2015-01-18 22:42:06 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
basegfx::B2DPolyPolygon polyPolygon;
|
|
|
|
for( sal_uInt32 i = 0; i < nPoly; ++i )
|
|
|
|
{
|
|
|
|
basegfx::B2DPolygon polygon;
|
|
|
|
for( sal_uInt32 j = 0; j < pPoints[ i ]; ++j )
|
|
|
|
polygon.append( basegfx::B2DPoint( pPtAry[i][j].mnX, pPtAry[i][j].mnY ) );
|
|
|
|
polygon.setClosed( true );
|
|
|
|
polyPolygon.append( polygon );
|
|
|
|
}
|
|
|
|
DrawPolyPolygon( polyPolygon );
|
|
|
|
}
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
|
2015-01-18 22:49:22 +01:00
|
|
|
if( mnLineColor != mnFillColor && UseSolidAA( mnLineColor ) )
|
2014-10-29 13:05:02 -04:00
|
|
|
{
|
2014-11-28 14:56:08 -05:00
|
|
|
// TODO Use glMultiDrawElements or primitive restart
|
2014-10-29 13:05:02 -04:00
|
|
|
for( sal_uInt32 i = 0; i < nPoly; i++ )
|
2014-12-15 20:00:45 +01:00
|
|
|
DrawLinesAA( pPoints[i], pPtAry[i], true );
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
2014-11-10 13:06:38 -05:00
|
|
|
|
|
|
|
PostDraw();
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
|
|
|
|
2015-12-15 15:31:50 +02:00
|
|
|
bool OpenGLSalGraphicsImpl::drawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::drawPolyPolygon trans " << fTransparency );
|
2014-11-08 22:55:06 -05:00
|
|
|
if( rPolyPolygon.count() <= 0 )
|
|
|
|
return true;
|
|
|
|
|
2016-01-08 22:33:11 +00:00
|
|
|
PreDraw( XOROption::IMPLEMENT_XOR );
|
2014-11-08 22:55:06 -05:00
|
|
|
|
2014-11-28 14:56:08 -05:00
|
|
|
if( UseSolid( mnFillColor, fTransparency ) )
|
2015-01-18 22:42:06 +01:00
|
|
|
DrawPolyPolygon( rPolyPolygon );
|
2014-11-08 22:55:06 -05:00
|
|
|
|
2015-01-19 22:47:01 +01:00
|
|
|
if( mnLineColor != mnFillColor && UseSolid( mnLineColor, fTransparency ))
|
2015-01-18 22:49:22 +01:00
|
|
|
{
|
2015-01-19 22:47:01 +01:00
|
|
|
basegfx::B2DTrapezoidVector aB2DTrapVector;
|
|
|
|
basegfx::tools::createLineTrapezoidFromB2DPolyPolygon( aB2DTrapVector, rPolyPolygon );
|
|
|
|
for( size_t i = 0; i < aB2DTrapVector.size(); ++i )
|
|
|
|
DrawTrapezoid( aB2DTrapVector[ i ] );
|
2015-01-18 22:49:22 +01:00
|
|
|
}
|
|
|
|
|
2014-11-10 13:06:38 -05:00
|
|
|
PostDraw();
|
|
|
|
|
2014-11-08 22:55:06 -05:00
|
|
|
return true;
|
2014-10-23 23:23:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool OpenGLSalGraphicsImpl::drawPolyLine(
|
2015-12-15 15:31:50 +02:00
|
|
|
const basegfx::B2DPolygon& rPolygon,
|
2014-11-08 23:04:46 -05:00
|
|
|
double fTransparency,
|
2015-12-15 15:31:50 +02:00
|
|
|
const basegfx::B2DVector& rLineWidth,
|
2014-11-08 23:04:46 -05:00
|
|
|
basegfx::B2DLineJoin eLineJoin,
|
2015-11-18 10:11:06 +02:00
|
|
|
css::drawing::LineCap eLineCap)
|
2014-11-08 23:04:46 -05:00
|
|
|
{
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::drawPolyLine trans " << fTransparency );
|
2014-11-08 23:04:46 -05:00
|
|
|
if( mnLineColor == SALCOLOR_NONE )
|
|
|
|
return true;
|
|
|
|
|
|
|
|
const bool bIsHairline = (rLineWidth.getX() == rLineWidth.getY()) && (rLineWidth.getX() <= 1.2);
|
|
|
|
|
|
|
|
// #i101491#
|
|
|
|
if( !bIsHairline && (rPolygon.count() > 1000) )
|
|
|
|
{
|
|
|
|
// the used basegfx::tools::createAreaGeometry is simply too
|
|
|
|
// expensive with very big polygons; fallback to caller (who
|
|
|
|
// should use ImplLineConverter normally)
|
|
|
|
// AW: ImplLineConverter had to be removed since it does not even
|
|
|
|
// know LineJoins, so the fallback will now prepare the line geometry
|
|
|
|
// the same way.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// shortcut for hairline drawing to improve performance
|
2015-09-01 14:54:53 +09:00
|
|
|
if (bIsHairline)
|
2014-11-08 23:04:46 -05:00
|
|
|
{
|
2015-09-03 11:30:52 +09:00
|
|
|
// Let's just leave it to OutputDevice to do the bezier subdivision,
|
|
|
|
// drawPolyLine(sal_uInt32 nPoints, const SalPoint* pPtAry) will be
|
|
|
|
// called with the result.
|
|
|
|
return false;
|
2014-11-08 23:04:46 -05:00
|
|
|
}
|
|
|
|
|
2015-09-03 11:30:52 +09:00
|
|
|
// #i11575#desc5#b adjust B2D tesselation result to raster positions
|
|
|
|
basegfx::B2DPolygon aPolygon = rPolygon;
|
|
|
|
const double fHalfWidth = 0.5 * rLineWidth.getX();
|
|
|
|
|
2014-11-08 23:04:46 -05:00
|
|
|
// get the area polygon for the line polygon
|
|
|
|
if( (rLineWidth.getX() != rLineWidth.getY())
|
|
|
|
&& !basegfx::fTools::equalZero( rLineWidth.getY() ) )
|
|
|
|
{
|
|
|
|
// prepare for createAreaGeometry() with anisotropic linewidth
|
|
|
|
aPolygon.transform( basegfx::tools::createScaleB2DHomMatrix(1.0, rLineWidth.getX() / rLineWidth.getY()));
|
|
|
|
}
|
|
|
|
|
|
|
|
// create the area-polygon for the line
|
|
|
|
const basegfx::B2DPolyPolygon aAreaPolyPoly( basegfx::tools::createAreaGeometry(aPolygon, fHalfWidth, eLineJoin, eLineCap) );
|
|
|
|
|
|
|
|
if( (rLineWidth.getX() != rLineWidth.getY())
|
|
|
|
&& !basegfx::fTools::equalZero( rLineWidth.getX() ) )
|
|
|
|
{
|
|
|
|
// postprocess createAreaGeometry() for anisotropic linewidth
|
|
|
|
aPolygon.transform(basegfx::tools::createScaleB2DHomMatrix(1.0, rLineWidth.getY() / rLineWidth.getX()));
|
|
|
|
}
|
|
|
|
|
2016-01-08 22:33:11 +00:00
|
|
|
PreDraw( XOROption::IMPLEMENT_XOR );
|
2014-11-28 14:56:08 -05:00
|
|
|
if( UseSolid( mnLineColor, fTransparency ) )
|
2014-11-08 23:04:46 -05:00
|
|
|
{
|
2014-11-28 14:56:08 -05:00
|
|
|
for( sal_uInt32 i = 0; i < aAreaPolyPoly.count(); i++ )
|
|
|
|
{
|
2015-12-15 15:31:50 +02:00
|
|
|
const basegfx::B2DPolyPolygon aOnePoly( aAreaPolyPoly.getB2DPolygon( i ) );
|
2015-01-12 13:20:54 +01:00
|
|
|
DrawPolyPolygon( aOnePoly );
|
2014-11-28 14:56:08 -05:00
|
|
|
}
|
2014-11-08 23:04:46 -05:00
|
|
|
}
|
2014-11-10 13:06:38 -05:00
|
|
|
PostDraw();
|
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*/,
|
|
|
|
const sal_uInt8* /*pFlgAry*/ )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OpenGLSalGraphicsImpl::drawPolygonBezier(
|
|
|
|
sal_uInt32 /*nPoints*/,
|
|
|
|
const SalPoint* /*pPtAry*/,
|
|
|
|
const sal_uInt8* /*pFlgAry*/ )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OpenGLSalGraphicsImpl::drawPolyPolygonBezier(
|
|
|
|
sal_uInt32 /*nPoly*/,
|
|
|
|
const sal_uInt32* /*pPoints*/,
|
|
|
|
const SalPoint* const* /*pPtAry*/,
|
|
|
|
const sal_uInt8* const* /*pFlgAry*/ )
|
|
|
|
{
|
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,
|
|
|
|
long nSrcWidth, long nSrcHeight,
|
2014-10-23 23:23:26 +02:00
|
|
|
sal_uInt16 /*nFlags*/ )
|
|
|
|
{
|
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
|
|
|
|
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,
|
|
|
|
rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, 0 );
|
|
|
|
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();
|
2014-11-13 21:37:54 -05:00
|
|
|
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
|
|
|
{
|
2015-12-12 18:00:21 +01:00
|
|
|
assert(dynamic_cast<const OpenGLSalBitmap*>(&rSalBitmap));
|
|
|
|
assert(dynamic_cast<const OpenGLSalBitmap*>(&rMaskBitmap));
|
|
|
|
|
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& rMask = static_cast<const OpenGLSalBitmap&>(rMaskBitmap);
|
2014-11-17 14:24:31 -05:00
|
|
|
OpenGLTexture& rTexture( rBitmap.GetTexture() );
|
|
|
|
OpenGLTexture& rMaskTex( rMask.GetTexture() );
|
2014-10-29 13:05:02 -04:00
|
|
|
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::drawBitmap with MASK" );
|
2014-11-10 13:06:38 -05:00
|
|
|
PreDraw();
|
2014-11-13 21:37:54 -05:00
|
|
|
DrawTextureWithMask( rTexture, rMaskTex, rPosAry );
|
2014-11-10 13:06:38 -05:00
|
|
|
PostDraw();
|
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,
|
|
|
|
SalColor nMaskColor )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
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-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( "::drawMask" );
|
2014-11-10 13:06:38 -05:00
|
|
|
PreDraw();
|
2014-11-13 21:37:54 -05:00
|
|
|
DrawMask( rTexture, nMaskColor, rPosAry );
|
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
|
|
|
SalBitmap* OpenGLSalGraphicsImpl::getBitmap( long nX, long nY, long nWidth, long nHeight )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
2015-12-16 17:19:31 +00:00
|
|
|
OpenGLZone aZone;
|
|
|
|
|
2014-10-29 13:05:02 -04:00
|
|
|
OpenGLSalBitmap* pBitmap = new 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();
|
2014-11-18 20:21:07 +00:00
|
|
|
if( !pBitmap->Create( maOffscreenTex, nX, nY, nWidth, nHeight ) )
|
2014-10-29 13:05:02 -04:00
|
|
|
{
|
|
|
|
delete pBitmap;
|
2015-11-10 10:28:29 +01:00
|
|
|
pBitmap = nullptr;
|
2014-10-29 13:05:02 -04:00
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
2014-10-29 13:05:02 -04:00
|
|
|
SalColor OpenGLSalGraphicsImpl::getPixel( long nX, long nY )
|
2014-10-23 23:23:26 +02:00
|
|
|
{
|
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
|
|
|
|
2014-10-29 13:05:02 -04:00
|
|
|
return MAKE_SALCOLOR( 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
|
|
|
{
|
|
|
|
if( nFlags & SAL_INVERT_TRACKFRAME )
|
|
|
|
{ // 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 ) )
|
|
|
|
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*/,
|
|
|
|
sal_uLong /*nSize*/ )
|
|
|
|
{
|
|
|
|
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();
|
|
|
|
glEnable( GL_BLEND );
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2014-11-18 12:34:53 -05:00
|
|
|
glBlendFunc( GL_ZERO, GL_SRC_COLOR );
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
2014-11-18 12:34:53 -05:00
|
|
|
DrawTexture( rTexture, rPosAry );
|
|
|
|
glDisable( GL_BLEND );
|
2015-11-17 09:20:25 +02:00
|
|
|
CHECK_GL_ERROR();
|
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);
|
2014-11-17 14:24:31 -05:00
|
|
|
OpenGLTexture& rTexture( rBitmap.GetTexture() );
|
|
|
|
OpenGLTexture& rAlphaTex( 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();
|
2014-11-13 21:37:54 -05:00
|
|
|
DrawTextureWithMask( rTexture, rAlphaTex, 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 )
|
|
|
|
{
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::drawAlphaRect" );
|
2014-10-29 13:05:02 -04:00
|
|
|
if( mnFillColor != SALCOLOR_NONE && nTransparency < 100 )
|
|
|
|
{
|
2014-11-10 13:06:38 -05:00
|
|
|
PreDraw();
|
2014-11-28 14:56:08 -05:00
|
|
|
UseSolid( mnFillColor, nTransparency );
|
2014-10-29 13:05:02 -04:00
|
|
|
DrawRect( nX, nY, nWidth, nHeight );
|
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
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2014-11-11 15:54:03 -05:00
|
|
|
Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
|
|
|
|
|
2015-11-20 10:14:49 +01:00
|
|
|
VCL_GL_INFO( "::drawGradient" );
|
2014-11-11 05:13:40 -05:00
|
|
|
|
|
|
|
if( aBoundRect.IsEmpty() )
|
|
|
|
return true;
|
|
|
|
|
2014-11-12 18:11:34 -05:00
|
|
|
if( rGradient.GetStyle() != GradientStyle_LINEAR &&
|
2014-11-14 01:16:28 -05:00
|
|
|
rGradient.GetStyle() != GradientStyle_AXIAL &&
|
2014-11-12 18:11:34 -05:00
|
|
|
rGradient.GetStyle() != GradientStyle_RADIAL )
|
|
|
|
return false;
|
|
|
|
|
2014-11-11 15:54:03 -05:00
|
|
|
aBoundRect.Left()--;
|
|
|
|
aBoundRect.Top()--;
|
|
|
|
aBoundRect.Right()++;
|
|
|
|
aBoundRect.Bottom()++;
|
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 )
|
|
|
|
{
|
|
|
|
glEnable( GL_STENCIL_TEST );
|
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
|
|
|
|
{
|
|
|
|
glEnable( GL_STENCIL_TEST );
|
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
|
|
|
|
if( rGradient.GetBorder() >= 100.0 )
|
|
|
|
{
|
|
|
|
Color aCol = rGradient.GetStartColor();
|
|
|
|
long nF = rGradient.GetStartIntensity();
|
2014-11-28 14:56:08 -05:00
|
|
|
if( UseSolid( MAKE_SALCOLOR( aCol.GetRed() * nF / 100,
|
|
|
|
aCol.GetGreen() * nF / 100,
|
|
|
|
aCol.GetBlue() * nF / 100 ) ) )
|
|
|
|
DrawRect( aBoundRect );
|
2014-11-11 15:54:03 -05:00
|
|
|
}
|
2014-11-12 18:11:34 -05:00
|
|
|
else if( rGradient.GetStyle() == GradientStyle_LINEAR )
|
2014-11-11 05:13:40 -05:00
|
|
|
{
|
|
|
|
DrawLinearGradient( rGradient, aBoundRect );
|
|
|
|
}
|
2014-11-14 01:16:28 -05:00
|
|
|
else if( rGradient.GetStyle() == GradientStyle_AXIAL )
|
|
|
|
{
|
|
|
|
DrawAxialGradient( rGradient, aBoundRect );
|
|
|
|
}
|
2014-11-11 15:54:03 -05:00
|
|
|
else if( rGradient.GetStyle() == GradientStyle_RADIAL )
|
|
|
|
{
|
|
|
|
DrawRadialGradient( rGradient, aBoundRect );
|
|
|
|
}
|
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
|
|
|
{
|
2014-11-12 18:11:34 -05:00
|
|
|
glDisable( GL_STENCIL_TEST );
|
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
|
|
|
{
|
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()
|
|
|
|
{
|
|
|
|
if( IsOffscreen() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if( !maOffscreenTex )
|
|
|
|
{
|
|
|
|
VCL_GL_INFO( "flushAndSwap - odd no texture !" );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-12-10 18:31:04 +00:00
|
|
|
if( mnDrawCountAtFlush == mnDrawCount )
|
2015-11-13 12:00:59 +00:00
|
|
|
{
|
|
|
|
VCL_GL_INFO( "eliding redundant flushAndSwap, no drawing since last!" );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mnDrawCountAtFlush = mnDrawCount;
|
|
|
|
|
|
|
|
OpenGLZone aZone;
|
|
|
|
|
|
|
|
VCL_GL_INFO( "flushAndSwap" );
|
|
|
|
|
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() );
|
|
|
|
|
2015-11-13 12:00:59 +00:00
|
|
|
// Interesting ! -> this destroys a context [ somehow ] ...
|
|
|
|
mpWindowContext->makeCurrent();
|
|
|
|
CHECK_GL_ERROR();
|
|
|
|
|
2016-01-01 17:45:06 +00:00
|
|
|
VCL_GL_INFO( "flushAndSwap - acquire default framebuffer" );
|
2015-11-13 12:00:59 +00:00
|
|
|
|
|
|
|
mpWindowContext->AcquireDefaultFramebuffer();
|
|
|
|
CHECK_GL_ERROR();
|
|
|
|
|
|
|
|
glViewport( 0, 0, GetWidth(), GetHeight() );
|
|
|
|
CHECK_GL_ERROR();
|
|
|
|
|
|
|
|
#if OSL_DEBUG_LEVEL > 0 // random background glClear
|
|
|
|
glClearColor((float)rand()/RAND_MAX, (float)rand()/RAND_MAX,
|
|
|
|
(float)rand()/RAND_MAX, 1.0);
|
|
|
|
#else
|
|
|
|
glClearColor(1.0, 1.0, 1.0, 1.0);
|
|
|
|
#endif
|
|
|
|
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
|
|
|
|
CHECK_GL_ERROR();
|
|
|
|
|
|
|
|
VCL_GL_INFO( "Texture height " << maOffscreenTex.GetHeight() << " vs. window height " << GetHeight() );
|
|
|
|
|
|
|
|
OpenGLProgram *pProgram =
|
2016-01-05 16:17:41 +00:00
|
|
|
mpWindowContext->UseProgram( "textureVertexShader", "textureFragmentShader", "// flush shader\n" ); // flush helps profiling
|
2015-11-13 12:00:59 +00:00
|
|
|
if( !pProgram )
|
|
|
|
VCL_GL_INFO( "Can't compile simple copying shader !" );
|
2015-09-16 09:17:37 +01:00
|
|
|
else
|
2015-11-13 12:00:59 +00:00
|
|
|
{
|
|
|
|
pProgram->SetTexture( "sampler", maOffscreenTex );
|
|
|
|
|
2016-01-01 17:45:06 +00:00
|
|
|
SalTwoRect aPosAry( 0, 0, maOffscreenTex.GetWidth(), maOffscreenTex.GetHeight(),
|
|
|
|
0, 0, maOffscreenTex.GetWidth(), maOffscreenTex.GetHeight() );
|
2015-11-13 12:00:59 +00:00
|
|
|
|
|
|
|
GLfloat aTexCoord[8];
|
2015-12-11 15:06:29 +01:00
|
|
|
maOffscreenTex.GetCoord( aTexCoord, aPosAry );
|
2015-11-13 12:00:59 +00:00
|
|
|
pProgram->SetTextureCoord( aTexCoord );
|
|
|
|
|
2016-01-01 17:45:06 +00:00
|
|
|
GLfloat fWidth( maOffscreenTex.GetWidth() );
|
|
|
|
GLfloat fHeight( maOffscreenTex.GetHeight() );
|
|
|
|
const GLfloat aVertices[] = { 0, fHeight,
|
|
|
|
0, 0,
|
|
|
|
fWidth, 0,
|
|
|
|
fWidth, fHeight };
|
2015-11-13 12:00:59 +00:00
|
|
|
|
|
|
|
pProgram->ApplyMatrix(GetWidth(), GetHeight(), 0.0);
|
|
|
|
pProgram->SetVertices( &aVertices[0] );
|
2016-01-01 17:45:06 +00:00
|
|
|
glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
|
2015-11-13 12:00:59 +00:00
|
|
|
|
|
|
|
pProgram->Clean();
|
|
|
|
|
2016-01-01 17:45:06 +00:00
|
|
|
maOffscreenTex.Unbind();
|
2015-11-13 12:00:59 +00:00
|
|
|
|
|
|
|
static bool bNoSwap = getenv("SAL_GL_NO_SWAP");
|
|
|
|
if (!bNoSwap)
|
|
|
|
mpWindowContext->swapBuffers();
|
|
|
|
}
|
|
|
|
|
|
|
|
VCL_GL_INFO( "flushAndSwap - end." );
|
2014-11-04 17:29:49 -05:00
|
|
|
}
|
|
|
|
|
2014-10-23 23:23:26 +02:00
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|