2014-03-14 18:51:06 +01: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/.
|
|
|
|
*/
|
|
|
|
|
2014-04-18 18:21:34 +02:00
|
|
|
#ifndef INCLUDED_VCL_OPENGL_OPENGLCONTEXT_HXX
|
|
|
|
#define INCLUDED_VCL_OPENGL_OPENGLCONTEXT_HXX
|
2014-03-14 18:51:06 +01:00
|
|
|
|
2014-04-08 14:21:41 +03:00
|
|
|
#include <string.h>
|
|
|
|
|
2014-04-08 01:17:16 +02:00
|
|
|
#include <GL/glew.h>
|
|
|
|
|
2014-03-17 05:06:00 +01:00
|
|
|
#if defined( MACOSX )
|
2014-04-08 14:21:41 +03:00
|
|
|
#elif defined( IOS )
|
|
|
|
#elif defined( ANDROID )
|
2014-12-22 19:10:59 +01:00
|
|
|
#elif defined( LIBO_HEADLESS )
|
2014-03-17 05:06:00 +01:00
|
|
|
#elif defined( UNX )
|
|
|
|
# include <prex.h>
|
|
|
|
# include "GL/glxew.h"
|
|
|
|
# include <postx.h>
|
|
|
|
#elif defined( _WIN32 )
|
2014-10-30 16:06:01 +01:00
|
|
|
#ifndef INCLUDED_PRE_POST_WIN_H
|
|
|
|
#define INCLUDED_PRE_POST_WIN_H
|
2014-03-17 05:06:00 +01:00
|
|
|
# include "prewin.h"
|
|
|
|
# include "postwin.h"
|
|
|
|
#endif
|
2014-10-30 16:06:01 +01:00
|
|
|
#endif
|
2014-03-17 05:06:00 +01:00
|
|
|
|
|
|
|
#if defined( _WIN32 )
|
2014-11-18 11:45:40 +01:00
|
|
|
#include <GL/wglew.h>
|
2014-03-17 05:06:00 +01:00
|
|
|
#elif defined( MACOSX )
|
2014-07-16 08:02:32 +02:00
|
|
|
#include <OpenGL/OpenGL.h>
|
2014-09-01 07:31:15 +02:00
|
|
|
#ifdef __OBJC__
|
2014-09-01 01:59:57 +02:00
|
|
|
@class NSOpenGLView;
|
2014-09-01 07:31:15 +02:00
|
|
|
#else
|
|
|
|
class NSOpenGLView;
|
|
|
|
#endif
|
2014-04-08 14:21:41 +03:00
|
|
|
#elif defined( IOS )
|
|
|
|
#elif defined( ANDROID )
|
2014-12-22 19:10:59 +01:00
|
|
|
#elif defined( LIBO_HEADLESS )
|
2014-03-17 05:06:00 +01:00
|
|
|
#elif defined( UNX )
|
|
|
|
#endif
|
|
|
|
|
2015-04-23 13:44:47 +03:00
|
|
|
#include <vcl/dllapi.h>
|
2014-03-17 05:06:00 +01:00
|
|
|
#include <vcl/window.hxx>
|
|
|
|
#include <tools/gen.hxx>
|
|
|
|
#include <vcl/syschild.hxx>
|
2015-09-13 12:15:13 +02:00
|
|
|
#include <rtl/crc.h>
|
2015-09-07 22:21:15 +01:00
|
|
|
#include <rtl/ref.hxx>
|
2014-03-17 05:06:00 +01:00
|
|
|
|
2015-07-10 18:55:12 +02:00
|
|
|
#include <map>
|
2015-09-13 12:15:13 +02:00
|
|
|
#include <memory>
|
2015-01-20 04:12:18 +01:00
|
|
|
#include <set>
|
2015-09-13 12:15:13 +02:00
|
|
|
#include <unordered_map>
|
2015-01-20 04:12:18 +01:00
|
|
|
|
2014-11-26 09:22:25 -05:00
|
|
|
class OpenGLFramebuffer;
|
2014-11-28 14:56:08 -05:00
|
|
|
class OpenGLProgram;
|
2014-11-26 09:22:25 -05:00
|
|
|
class OpenGLTexture;
|
2015-01-20 04:12:18 +01:00
|
|
|
class SalGraphicsImpl;
|
2015-08-29 23:15:54 +01:00
|
|
|
class OpenGLTests;
|
2014-11-26 09:22:25 -05:00
|
|
|
|
2014-03-17 05:06:00 +01:00
|
|
|
/// Holds the information of our new child window
|
|
|
|
struct GLWindow
|
|
|
|
{
|
|
|
|
#if defined( _WIN32 )
|
|
|
|
HWND hWnd;
|
|
|
|
HDC hDC;
|
|
|
|
HGLRC hRC;
|
|
|
|
#elif defined( MACOSX )
|
2014-04-08 14:21:41 +03:00
|
|
|
#elif defined( IOS )
|
|
|
|
#elif defined( ANDROID )
|
2014-12-22 19:10:59 +01:00
|
|
|
#elif defined( LIBO_HEADLESS )
|
2014-03-17 05:06:00 +01:00
|
|
|
#elif defined( UNX )
|
2014-11-07 07:32:00 +01:00
|
|
|
Display* dpy;
|
|
|
|
int screen;
|
|
|
|
Window win;
|
2014-05-23 02:13:28 +02:00
|
|
|
#if defined( GLX_EXT_texture_from_pixmap )
|
2014-03-17 05:06:00 +01:00
|
|
|
GLXFBConfig fbc;
|
|
|
|
#endif
|
|
|
|
XVisualInfo* vi;
|
|
|
|
GLXContext ctx;
|
|
|
|
|
2015-11-11 18:06:29 +02:00
|
|
|
bool HasGLXExtension( const char* name ) const;
|
2014-03-17 05:06:00 +01:00
|
|
|
const char* GLXExtensions;
|
|
|
|
#endif
|
|
|
|
unsigned int Width;
|
|
|
|
unsigned int Height;
|
|
|
|
const GLubyte* GLExtensions;
|
2014-03-17 08:24:14 +01:00
|
|
|
bool bMultiSampleSupported;
|
2014-03-17 05:06:00 +01:00
|
|
|
|
|
|
|
GLWindow()
|
|
|
|
:
|
|
|
|
#if defined( _WIN32 )
|
2015-09-30 16:12:55 +02:00
|
|
|
hWnd(NULL),
|
|
|
|
hDC(NULL),
|
|
|
|
hRC(NULL),
|
2014-03-17 05:06:00 +01:00
|
|
|
#elif defined( MACOSX )
|
2014-04-08 14:21:41 +03:00
|
|
|
#elif defined( IOS )
|
|
|
|
#elif defined( ANDROID )
|
2014-12-22 19:10:59 +01:00
|
|
|
#elif defined( LIBO_HEADLESS )
|
2014-03-17 05:06:00 +01:00
|
|
|
#elif defined( UNX )
|
2015-11-10 10:28:29 +01:00
|
|
|
dpy(nullptr),
|
2014-03-17 05:06:00 +01:00
|
|
|
screen(0),
|
|
|
|
win(0),
|
2014-05-23 02:13:28 +02:00
|
|
|
#if defined( GLX_EXT_texture_from_pixmap )
|
2015-11-10 10:28:29 +01:00
|
|
|
fbc(nullptr),
|
2014-03-17 05:06:00 +01:00
|
|
|
#endif
|
2015-11-10 10:28:29 +01:00
|
|
|
vi(nullptr),
|
|
|
|
ctx(nullptr),
|
|
|
|
GLXExtensions(nullptr),
|
2014-03-17 05:06:00 +01:00
|
|
|
#endif
|
|
|
|
Width(0),
|
|
|
|
Height(0),
|
2015-11-10 10:28:29 +01:00
|
|
|
GLExtensions(nullptr),
|
2014-03-17 08:24:14 +01:00
|
|
|
bMultiSampleSupported(false)
|
2014-03-17 05:06:00 +01:00
|
|
|
{
|
|
|
|
}
|
2014-05-23 02:11:23 +02:00
|
|
|
|
|
|
|
~GLWindow();
|
2014-03-17 05:06:00 +01:00
|
|
|
};
|
2014-03-14 18:51:06 +01:00
|
|
|
|
2015-04-23 13:44:47 +03:00
|
|
|
class VCL_DLLPUBLIC OpenGLContext
|
2014-03-14 18:51:06 +01:00
|
|
|
{
|
2015-08-29 23:15:54 +01:00
|
|
|
friend class OpenGLTests;
|
2014-03-15 07:07:08 +01:00
|
|
|
OpenGLContext();
|
2015-09-08 11:46:13 +01:00
|
|
|
public:
|
2015-09-07 22:21:15 +01:00
|
|
|
static rtl::Reference<OpenGLContext> Create();
|
2014-03-15 07:07:08 +01:00
|
|
|
~OpenGLContext();
|
2015-09-07 22:21:15 +01:00
|
|
|
void acquire() { mnRefCount++; }
|
|
|
|
void release() { if ( --mnRefCount == 0 ) delete this; }
|
2015-09-08 15:57:55 +01:00
|
|
|
void dispose();
|
2014-03-15 07:07:08 +01:00
|
|
|
|
2014-08-16 05:36:30 +02:00
|
|
|
void requestLegacyContext();
|
2014-10-31 19:19:47 +01:00
|
|
|
void requestSingleBufferedRendering();
|
2014-08-16 05:36:30 +02:00
|
|
|
|
2015-11-10 10:28:29 +01:00
|
|
|
bool init(vcl::Window* pParent = nullptr);
|
2014-04-27 12:20:13 +02:00
|
|
|
bool init(SystemChildWindow* pChildWindow);
|
|
|
|
|
2014-10-24 17:03:39 +02:00
|
|
|
// these methods are for the deep platform layer, don't use them in normal code
|
|
|
|
// only in vcl's platform code
|
2014-12-22 19:10:59 +01:00
|
|
|
#if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID && !defined(LIBO_HEADLESS)
|
2014-10-24 17:03:39 +02:00
|
|
|
bool init(Display* dpy, Window win, int screen);
|
2014-11-02 04:12:59 +01:00
|
|
|
#elif defined( _WIN32 )
|
|
|
|
bool init( HDC hDC, HWND hWnd );
|
2014-10-24 17:03:39 +02:00
|
|
|
#endif
|
2014-12-04 22:17:58 -05:00
|
|
|
void reset();
|
2014-10-24 17:03:39 +02:00
|
|
|
|
2014-11-26 09:22:25 -05:00
|
|
|
// use these methods right after setting a context to make sure drawing happens
|
|
|
|
// in the right FBO (default one is for onscreen painting)
|
2014-12-04 22:25:56 -05:00
|
|
|
bool BindFramebuffer( OpenGLFramebuffer* pFramebuffer );
|
2014-11-26 09:22:25 -05:00
|
|
|
bool AcquireDefaultFramebuffer();
|
|
|
|
OpenGLFramebuffer* AcquireFramebuffer( const OpenGLTexture& rTexture );
|
2015-04-01 08:33:09 +02:00
|
|
|
static void ReleaseFramebuffer( OpenGLFramebuffer* pFramebuffer );
|
2015-08-31 12:11:50 +01:00
|
|
|
void UnbindTextureFromFramebuffers( GLuint nTexture );
|
2015-12-31 22:12:59 +00:00
|
|
|
static bool IsTextureAttachedAnywhere( GLuint nTexture );
|
2015-09-07 22:21:15 +01:00
|
|
|
|
2014-12-04 22:25:56 -05:00
|
|
|
void ReleaseFramebuffer( const OpenGLTexture& rTexture );
|
|
|
|
void ReleaseFramebuffers();
|
2014-11-26 09:22:25 -05:00
|
|
|
|
2014-11-28 14:56:08 -05:00
|
|
|
// retrieve a program from the cache or compile/link it
|
2015-01-20 14:48:48 +01:00
|
|
|
OpenGLProgram* GetProgram( const OUString& rVertexShader, const OUString& rFragmentShader, const OString& preamble = "" );
|
|
|
|
OpenGLProgram* UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader, const OString& preamble = "" );
|
2015-11-16 20:31:58 +02:00
|
|
|
void UseNoProgram();
|
2014-11-28 14:56:08 -05:00
|
|
|
|
2015-09-02 17:28:39 +01:00
|
|
|
/// Is this GL context the current context ?
|
2014-12-04 22:17:58 -05:00
|
|
|
bool isCurrent();
|
2015-09-02 22:14:10 +01:00
|
|
|
/// release bound resources from the current context
|
2015-01-06 16:09:09 +00:00
|
|
|
static void clearCurrent();
|
2015-09-02 22:14:10 +01:00
|
|
|
/// release contexts etc. before (potentially) allowing another thread run.
|
|
|
|
static void prepareForYield();
|
2015-09-02 17:28:39 +01:00
|
|
|
/// Is there a current GL context ?
|
|
|
|
static bool hasCurrent();
|
2016-01-05 16:17:41 +00:00
|
|
|
|
|
|
|
/// make a VCL context (any context) current, create it if necessary.
|
|
|
|
static void makeVCLCurrent();
|
|
|
|
/// fetch any VCL context, creating one if @bMakeIfNecessary is set.
|
|
|
|
static rtl::Reference<OpenGLContext> getVCLContext(bool bMakeIfNecessary = true);
|
2015-01-06 16:09:09 +00:00
|
|
|
/// make this GL context current - so it is implicit in subsequent GL calls
|
2014-04-28 09:57:29 +02:00
|
|
|
void makeCurrent();
|
windows opengl: make sure mpLastContext is indeed the current context
There were two problems here:
1) The OpenGLContext ctor registered the instance on the list of
contexts, but platform-specific call (e.g. wglMakeCurrent()) was only
made later. Add a registerAsCurrent() member function that helps
ensuring that the last item in the context list is indeed the current
context.
2) OpenGLContext::prepareForYield() is called without the solar mutex
being locked, but it still assumes that the last context in the context
list is the thread's current context, which may not be true. The result
is that during JunitTest_sd_unoapi, we end up in a situation like:
debug:4640:5240: OpenGLContext::registerAsCurrent: wglGetCurrentContext() is 00010001, pSVData->maGDIData.mpLastContext is 00FA65F8
debug:4640:7944: OpenGLContext::registerAsCurrent: wglGetCurrentContext() is 000D0003, pSVData->maGDIData.mpLastContext is 00FA6C70
debug:4640:5240: OpenGLContext::prepareForYield: start, wglGetCurrentContext() is 00010001, pSVData->maGDIData.mpLastContext is 00FA6C70
I.e. one thread registers as current, an other registers as current, too (while
the other thread has the solar mutex), then once the original thread wants to
release the solar mutex, the real current context and the last item in the
context list won't match, so the assert at the end of prepareForYield() will
fail.
Fix this by releasing the GL context in WinSalInstance::DestroyFrame().
With this, JunitTest_sd_unoapi passes on Windows with GL enabled.
Change-Id: Icfb9c65c871586b5df69b5a2ab3aa91843dfc799
Reviewed-on: https://gerrit.libreoffice.org/18473
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Tested-by: Michael Meeks <michael.meeks@collabora.com>
2015-09-10 17:25:27 +02:00
|
|
|
/// Put this GL context to the end of the context list.
|
|
|
|
void registerAsCurrent();
|
2015-01-06 16:09:09 +00:00
|
|
|
/// reset the GL context so this context is not implicit in subsequent GL calls.
|
2014-07-13 07:52:51 +02:00
|
|
|
void resetCurrent();
|
2014-04-27 12:20:13 +02:00
|
|
|
void swapBuffers();
|
2014-05-19 19:21:29 +02:00
|
|
|
void sync();
|
|
|
|
void show();
|
2014-04-27 12:20:13 +02:00
|
|
|
|
2014-05-19 19:21:29 +02:00
|
|
|
void setWinPosAndSize(const Point &rPos, const Size& rSize);
|
2014-03-14 18:51:06 +01:00
|
|
|
void setWinSize(const Size& rSize);
|
2014-10-30 21:54:22 -04:00
|
|
|
const GLWindow& getOpenGLWindow() const { return m_aGLWin;}
|
2014-03-14 18:51:06 +01:00
|
|
|
|
2014-08-08 01:55:33 +02:00
|
|
|
SystemChildWindow* getChildWindow();
|
|
|
|
const SystemChildWindow* getChildWindow() const;
|
|
|
|
|
2014-04-15 00:27:25 +02:00
|
|
|
bool isInitialized()
|
|
|
|
{
|
|
|
|
return mbInitialized;
|
|
|
|
}
|
|
|
|
|
2015-12-11 18:18:50 +00:00
|
|
|
/// VCL promiscuously re-uses its own contexts:
|
|
|
|
void setVCLOnly() { mbVCLOnly = true; }
|
|
|
|
bool isVCLOnly() { return mbVCLOnly; }
|
|
|
|
|
2014-08-29 11:55:23 +02:00
|
|
|
bool supportMultiSampling() const;
|
|
|
|
|
2014-09-23 11:20:40 +02:00
|
|
|
static SystemWindowData generateWinData(vcl::Window* pParent, bool bRequestLegacyContext);
|
2014-04-27 12:09:20 +02:00
|
|
|
|
2014-03-14 18:51:06 +01:00
|
|
|
private:
|
2014-11-07 06:13:05 +01:00
|
|
|
SAL_DLLPRIVATE bool InitGLEW();
|
2015-08-14 09:57:53 +02:00
|
|
|
SAL_DLLPRIVATE void InitGLEWDebugging();
|
2014-03-14 18:51:06 +01:00
|
|
|
SAL_DLLPRIVATE bool initWindow();
|
2014-04-27 12:20:13 +02:00
|
|
|
SAL_DLLPRIVATE bool ImplInit();
|
2014-12-22 19:10:59 +01:00
|
|
|
#if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID && !defined(LIBO_HEADLESS)
|
2014-10-24 16:50:05 +02:00
|
|
|
SAL_DLLPRIVATE void initGLWindow(Visual* pVisual);
|
|
|
|
#endif
|
2014-03-14 18:51:06 +01:00
|
|
|
|
2014-09-01 01:59:57 +02:00
|
|
|
#if defined(MACOSX)
|
|
|
|
NSOpenGLView* getOpenGLView();
|
|
|
|
#endif
|
|
|
|
|
2014-03-14 18:51:06 +01:00
|
|
|
GLWindow m_aGLWin;
|
2015-03-09 14:29:30 +02:00
|
|
|
VclPtr<vcl::Window> m_xWindow;
|
|
|
|
VclPtr<vcl::Window> mpWindow; //points to m_pWindow or the parent window, don't delete it
|
|
|
|
VclPtr<SystemChildWindow> m_pChildWindow;
|
2014-04-02 03:31:01 +02:00
|
|
|
bool mbInitialized;
|
2014-12-02 21:51:50 +01:00
|
|
|
int mnRefCount;
|
2014-08-16 05:36:30 +02:00
|
|
|
bool mbRequestLegacyContext;
|
2014-10-31 19:19:47 +01:00
|
|
|
bool mbUseDoubleBufferedRendering;
|
2015-12-11 18:18:50 +00:00
|
|
|
bool mbVCLOnly;
|
2014-11-22 07:58:38 -05:00
|
|
|
|
2014-12-11 07:46:51 +01:00
|
|
|
int mnFramebufferCount;
|
2014-11-26 09:22:25 -05:00
|
|
|
OpenGLFramebuffer* mpCurrentFramebuffer;
|
|
|
|
OpenGLFramebuffer* mpFirstFramebuffer;
|
|
|
|
OpenGLFramebuffer* mpLastFramebuffer;
|
|
|
|
|
2015-09-13 12:15:13 +02:00
|
|
|
struct ProgramHash
|
2015-01-20 14:48:48 +01:00
|
|
|
{
|
2015-09-13 12:15:13 +02:00
|
|
|
size_t operator()( const rtl::OString& aDigest ) const
|
|
|
|
{
|
|
|
|
return (size_t)( rtl_crc32( 0, aDigest.getStr(), aDigest.getLength() ) );
|
|
|
|
}
|
2015-01-20 14:48:48 +01:00
|
|
|
};
|
2015-09-13 12:15:13 +02:00
|
|
|
|
|
|
|
typedef std::unordered_map< rtl::OString, std::shared_ptr<OpenGLProgram>, ProgramHash > ProgramCollection;
|
|
|
|
ProgramCollection maPrograms;
|
2014-11-28 14:56:08 -05:00
|
|
|
OpenGLProgram* mpCurrentProgram;
|
|
|
|
|
2014-11-22 07:58:38 -05:00
|
|
|
public:
|
2014-11-22 08:07:47 -05:00
|
|
|
vcl::Region maClipRegion;
|
2014-11-22 08:04:23 -05:00
|
|
|
int mnPainting;
|
|
|
|
|
2015-09-07 22:21:15 +01:00
|
|
|
// Don't hold references to ourselves:
|
|
|
|
OpenGLContext *mpPrevContext;
|
|
|
|
OpenGLContext *mpNextContext;
|
2014-03-14 18:51:06 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|