summaryrefslogtreecommitdiff
path: root/indra/llwindow/llwindowsdl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llwindow/llwindowsdl.cpp')
-rw-r--r--indra/llwindow/llwindowsdl.cpp327
1 files changed, 318 insertions, 9 deletions
diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp
index 218f953c7f..e592815f4f 100644
--- a/indra/llwindow/llwindowsdl.cpp
+++ b/indra/llwindow/llwindowsdl.cpp
@@ -46,12 +46,14 @@ extern "C" {
# include "fontconfig/fontconfig.h"
}
-#if LL_LINUX
+#if LL_LINUX || __FreeBSD__
// not necessarily available on random SDL platforms, so #if LL_LINUX
// for execv(), waitpid(), fork()
# include <unistd.h>
# include <sys/types.h>
# include <sys/wait.h>
+# define GLX_GLXEXT_PROTOTYPES 1
+# include <GL/glx.h>
# include <stdio.h>
#endif // LL_LINUX
@@ -62,6 +64,43 @@ const S32 MAX_NUM_RESOLUTIONS = 200;
// static variable for ATI mouse cursor crash work-around:
static bool ATIbug = false;
+#if LL_DARWIN
+
+#include <OpenGL/OpenGL.h>
+#include <CoreGraphics/CGDirectDisplay.h>
+#include <CoreServices/CoreServices.h>
+
+BOOL gHiDPISupport = TRUE;
+
+namespace
+{
+ struct NativeKeyEventData {
+ enum EventType {
+ KEYUNKNOWN,
+ KEYUP,
+ KEYDOWN,
+ KEYCHAR
+ };
+
+ EventType mKeyEvent = KEYUNKNOWN;
+ uint32_t mEventType = 0;
+ uint32_t mEventModifiers = 0;
+ uint32_t mEventKeyCode = 0;
+ uint32_t mEventChars = 0;
+ uint32_t mEventUnmodChars = 0;
+ bool mEventRepeat = false;
+ } *mRawKeyEvent = NULL;
+}
+//
+// LLWindowMacOSX
+//
+
+BOOL LLWindowSDL::sUseMultGL = FALSE;
+
+#endif
+
+BOOL hasHIDPI = 0;
+
//
// LLWindowSDL
//
@@ -371,6 +410,10 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
gKeyboard->setCallbacks(callbacks);
// Note that we can't set up key-repeat until after SDL has init'd video
+#if LL_DARWIN
+ hasHIDPI = gHiDPISupport;
+#endif
+
// Ignore use_gl for now, only used for drones on PC
mWindow = NULL;
mContext = {};
@@ -702,6 +745,8 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
tryFindFullscreenSize( width, height );
}
+ if(hasHIDPI) sdlflags = sdlflags | SDL_WINDOW_ALLOW_HIGHDPI;
+
mSDLFlags = sdlflags;
GLint redBits{8}, greenBits{8}, blueBits{8}, alphaBits{8};
@@ -722,6 +767,14 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencilBits);
// *FIX: try to toggle vsync here?
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
+#if LL_DARWIN
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
+#else
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
+#endif
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
if (mFSAASamples > 0)
@@ -806,7 +859,36 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
{
LL_INFOS() << "X11 log-parser detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL;
} else
+ {
+ PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC queryInteger;
+ queryInteger = (PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC)
+ glXGetProcAddressARB((const GLubyte *)"glXQueryCurrentRendererIntegerMESA");
+ unsigned int vram_megabytes = 0;
+ queryInteger(GLX_RENDERER_VIDEO_MEMORY_MESA, &vram_megabytes);
+ if (!vram_megabytes) {
+ glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, (int *)&vram_megabytes);
+ vram_megabytes /= 1024;
+ }
+ if (!vram_megabytes) {
+ glGetIntegerv(GL_VBO_FREE_MEMORY_ATI, (int *)&vram_megabytes);
+ vram_megabytes /= 1024;
+ }
+ gGLManager.mVRAM = vram_megabytes;
+ }
+#elif LL_DARWIN
+ CGLRendererInfoObj info = 0;
+ GLint vram_megabytes = 0;
+ int num_renderers = 0;
+ auto err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay),
+ &info, &num_renderers);
+ if (!err) {
+ CGLDescribeRenderer(info, 0, kCGLRPVideoMemoryMegabytes, &vram_megabytes);
+ CGLDestroyRendererInfo(info);
+ } else
+ vram_megabytes = 256;
+ gGLManager.mVRAM = vram_megabytes;
# endif // LL_X11
+/*
{
// fallback to letting SDL detect VRAM.
// note: I've not seen SDL's detection ever actually find
@@ -817,6 +899,7 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
LL_INFOS() << "SDL detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL;
}
}
+*/
// If VRAM is not detected, that is handled later
// *TODO: Now would be an appropriate time to check for some
@@ -844,6 +927,7 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
// relaxed about if we have to.
if (colorBits < 32)
{
+#if 0
close();
setupFailure(
"Second Life requires True Color (32-bit) to run in a window.\n"
@@ -854,6 +938,7 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
"Error",
OSMB_OK);
return FALSE;
+#endif
}
#if LL_X11
@@ -884,7 +969,9 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
SDL_StartTextInput();
//make sure multisampling is disabled by default
+#if GL_VERSION_1_3
glDisable(GL_MULTISAMPLE_ARB);
+#endif
// Don't need to get the current gamma, since there's a call that restores it to the system defaults.
return TRUE;
@@ -956,23 +1043,39 @@ LLWindowSDL::~LLWindowSDL()
void LLWindowSDL::show()
{
// *FIX: What to do with SDL?
+ if (mWindow)
+ {
+ SDL_ShowWindow(mWindow);
+ }
}
void LLWindowSDL::hide()
{
// *FIX: What to do with SDL?
+ if (mWindow)
+ {
+ SDL_HideWindow(mWindow);
+ }
}
//virtual
void LLWindowSDL::minimize()
{
// *FIX: What to do with SDL?
+ if (mWindow)
+ {
+ SDL_MinimizeWindow(mWindow);
+ }
}
//virtual
void LLWindowSDL::restore()
{
// *FIX: What to do with SDL?
+ if (mWindow)
+ {
+ SDL_RestoreWindow(mWindow);
+ }
}
@@ -1006,7 +1109,7 @@ BOOL LLWindowSDL::getVisible()
// Then what is?
if (mWindow)
{
- result = TRUE;
+ if( SDL_GetWindowFlags(mWindow) & SDL_WINDOW_SHOWN ) result = TRUE;
}
return(result);
@@ -1016,10 +1119,12 @@ BOOL LLWindowSDL::getMinimized()
{
BOOL result = FALSE;
- if (mWindow && (1 == mIsMinimized))
+ if (mWindow/*&& (1 == mIsMinimized)*/)
{
- result = TRUE;
+ if( SDL_GetWindowFlags(mWindow) & SDL_WINDOW_MINIMIZED ) result = TRUE;
}
+
+ mIsMinimized = result;
return(result);
}
@@ -1030,6 +1135,8 @@ BOOL LLWindowSDL::getMaximized()
if (mWindow)
{
// TODO
+ if( SDL_GetWindowFlags(mWindow) & SDL_WINDOW_MAXIMIZED ) result = TRUE;
+ else result = FALSE;
}
return(result);
@@ -1038,7 +1145,15 @@ BOOL LLWindowSDL::getMaximized()
BOOL LLWindowSDL::maximize()
{
// TODO
- return FALSE;
+ BOOL result = FALSE;
+
+ if (mWindow)
+ {
+ SDL_MaximizeWindow(mWindow);
+ result = TRUE;
+ }
+
+ return result;
}
BOOL LLWindowSDL::getFullscreen()
@@ -1058,6 +1173,14 @@ BOOL LLWindowSDL::getSize(LLCoordScreen *size)
{
if (mSurface)
{
+ /*
+ if(hasHIDPI)
+ {
+ SDL_GL_GetDrawableSize(mWindow, &size->mX, &size->mY);
+ return (TRUE);
+ }
+ */
+
size->mX = mSurface->w;
size->mY = mSurface->h;
return (TRUE);
@@ -1070,6 +1193,12 @@ BOOL LLWindowSDL::getSize(LLCoordWindow *size)
{
if (mSurface)
{
+ if(hasHIDPI)
+ {
+ SDL_GL_GetDrawableSize(mWindow, &size->mX, &size->mY);
+ return (TRUE);
+ }
+
size->mX = mSurface->w;
size->mY = mSurface->h;
return (TRUE);
@@ -1080,13 +1209,17 @@ BOOL LLWindowSDL::getSize(LLCoordWindow *size)
BOOL LLWindowSDL::setPosition(const LLCoordScreen position)
{
+ BOOL result = FALSE;
+
if(mWindow)
{
// *FIX: (?)
//MacMoveWindow(mWindow, position.mX, position.mY, false);
+ SDL_SetWindowPosition(mWindow, position.mX, position.mY);
+ result = TRUE;
}
- return TRUE;
+ return result;
}
template< typename T > bool setSizeImpl( const T& newSize, SDL_Window *pWin )
@@ -1150,6 +1283,9 @@ BOOL LLWindowSDL::restoreGamma()
{
//CGDisplayRestoreColorSyncSettings();
// SDL_SetGamma(1.0f, 1.0f, 1.0f);
+ Uint16 ramp;
+ SDL_CalculateGammaRamp(1.0f, &ramp);
+ SDL_SetWindowGammaRamp(mWindow, &ramp, &ramp, &ramp);
return true;
}
@@ -1159,6 +1295,9 @@ BOOL LLWindowSDL::setGamma(const F32 gamma)
if (mGamma == 0) mGamma = 0.1f;
mGamma = 1/mGamma;
// SDL_SetGamma(mGamma, mGamma, mGamma);
+ Uint16 ramp;
+ SDL_CalculateGammaRamp(mGamma, &ramp);
+ SDL_SetWindowGammaRamp(mWindow, &ramp, &ramp, &ramp);
return true;
}
@@ -1207,6 +1346,13 @@ BOOL LLWindowSDL::setCursorPosition(const LLCoordWindow position)
//LL_INFOS() << "setCursorPosition(" << screen_pos.mX << ", " << screen_pos.mY << ")" << LL_ENDL;
// do the actual forced cursor move.
+
+ if (mFullscreen)
+ {
+ SDL_WarpMouseGlobal(screen_pos.mX, screen_pos.mY);
+ return result;
+ }
+
SDL_WarpMouseInWindow(mWindow, screen_pos.mX, screen_pos.mY);
//LL_INFOS() << llformat("llcw %d,%d -> scr %d,%d", position.mX, position.mY, screen_pos.mX, screen_pos.mY) << LL_ENDL;
@@ -1229,6 +1375,11 @@ BOOL LLWindowSDL::getCursorPosition(LLCoordWindow *position)
return convertCoords(screen_pos, position);
}
+F32 LLWindowSDL::getSystemUISize()
+{
+ if(hasHIDPI) return 2.0f;
+ else return 1.f;
+}
F32 LLWindowSDL::getNativeAspectRatio()
{
@@ -1386,33 +1537,64 @@ void LLWindowSDL::flashIcon(F32 seconds)
BOOL LLWindowSDL::isClipboardTextAvailable()
{
+#if LL_X11
return mSDL_Display && XGetSelectionOwner(mSDL_Display, XA_CLIPBOARD) != None;
+#else
+ return SDL_HasClipboardText();
+#endif
}
BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &dst)
{
+#if LL_X11
return getSelectionText(XA_CLIPBOARD, dst);
+#else
+ auto data = SDL_GetClipboardText();
+ if (data)
+ {
+ dst = LLWString(utf8str_to_wstring(data));
+ SDL_free(data);
+ return TRUE;
+ }
+ return FALSE;
+#endif
}
BOOL LLWindowSDL::copyTextToClipboard(const LLWString &s)
{
+#if LL_X11
return setSelectionText(XA_CLIPBOARD, s);
+#else
+ return !SDL_SetClipboardText(wstring_to_utf8str(s).c_str());
+#endif
}
BOOL LLWindowSDL::isPrimaryTextAvailable()
{
+#if LL_X11
LLWString text;
return getSelectionText(XA_PRIMARY, text) && !text.empty();
+#else
+ return FALSE; // unsupported
+#endif
}
BOOL LLWindowSDL::pasteTextFromPrimary(LLWString &dst)
{
+#if LL_X11
return getSelectionText(XA_PRIMARY, dst);
+#else
+ return FALSE; // unsupported
+#endif
}
BOOL LLWindowSDL::copyTextToPrimary(const LLWString &s)
{
+#if LL_X11
return setSelectionText(XA_PRIMARY, s);
+#else
+ return FALSE; // unsupported
+#endif
}
LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_resolutions)
@@ -1778,6 +1960,12 @@ void LLWindowSDL::gatherInput()
LLCoordWindow winCoord(event.button.x, event.button.y);
LLCoordGL openGlCoord;
convertCoords(winCoord, &openGlCoord);
+
+ openGlCoord.mX = openGlCoord.mX * getSystemUISize();
+ openGlCoord.mY = openGlCoord.mY * getSystemUISize();
+
+ //LL_INFOS() << "SDL_MOUSEMOTION " << event.button.x << " " << event.button.y << " gl " << openGlCoord.mX << " " << openGlCoord.mY << LL_ENDL;
+
MASK mask = gKeyboard->currentMask(TRUE);
mCallbacks->handleMouseMove(this, openGlCoord, mask);
break;
@@ -1852,6 +2040,10 @@ void LLWindowSDL::gatherInput()
LLCoordWindow winCoord(event.button.x, event.button.y);
LLCoordGL openGlCoord;
convertCoords(winCoord, &openGlCoord);
+
+ openGlCoord.mX *= getSystemUISize();
+ openGlCoord.mY *= getSystemUISize();
+
MASK mask = gKeyboard->currentMask(TRUE);
if (event.button.button == SDL_BUTTON_LEFT) // SDL doesn't manage double clicking...
@@ -1915,6 +2107,10 @@ void LLWindowSDL::gatherInput()
LLCoordWindow winCoord(event.button.x, event.button.y);
LLCoordGL openGlCoord;
convertCoords(winCoord, &openGlCoord);
+
+ openGlCoord.mX *= getSystemUISize();
+ openGlCoord.mY *= getSystemUISize();
+
MASK mask = gKeyboard->currentMask(TRUE);
if (event.button.button == SDL_BUTTON_LEFT) // left
@@ -1944,7 +2140,19 @@ void LLWindowSDL::gatherInput()
// SDL_SetWindowSize(mWindow, width, height);
//
- mCallbacks->handleResize(this, width, height);
+ mCallbacks->handleResize(this, width * getSystemUISize(), height * getSystemUISize());
+ }
+ else if(event.window.event == SDL_WINDOWEVENT_ENTER)
+ {
+ LL_INFOS() << "SDL_WINDOWEVENT_ENTER" << LL_ENDL;
+ if(!mHaveInputFocus) mCallbacks->handleFocus(this);
+ mHaveInputFocus = TRUE;
+ }
+ else if(event.window.event == SDL_WINDOWEVENT_LEAVE)
+ {
+ LL_INFOS() << "SDL_WINDOWEVENT_LEAVE" << LL_ENDL;
+ if(mHaveInputFocus) mCallbacks->handleFocusLost(this);
+ mHaveInputFocus = FALSE;
}
else if( event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED ) // <FS:ND> What about SDL_WINDOWEVENT_ENTER (mouse focus)
{
@@ -1964,6 +2172,30 @@ void LLWindowSDL::gatherInput()
mCallbacks->handleFocusLost(this);
}
+ /*
+
+ Bug : the app remains inactive when maximized ..
+
+ else if(event.window.event == SDL_WINDOWEVENT_MINIMIZED)
+ {
+ LL_INFOS() << "SDL_WINDOWEVENT_MINIMIZED" << LL_ENDL;
+ if(!mIsMinimized) mCallbacks->handleActivate(this,FALSE);
+ mIsMinimized = TRUE;
+ }
+ else if(event.window.event == SDL_WINDOWEVENT_MAXIMIZED)
+ {
+ LL_INFOS() << "SDL_WINDOWEVENT_MAXIMIZED" << LL_ENDL;
+ if(mIsMinimized) mCallbacks->handleActivate(this,TRUE);
+ mIsMinimized = FALSE;
+ }
+ */
+ else if (event.window.event == SDL_WINDOWEVENT_EXPOSED)
+ {
+ int w, h;
+ SDL_GL_GetDrawableSize(mWindow, &w, &h);
+
+ mCallbacks->handlePaint(this, 0, 0, w, h);
+ }
else if( event.window.event == SDL_WINDOWEVENT_MINIMIZED ||
event.window.event == SDL_WINDOWEVENT_MAXIMIZED ||
event.window.event == SDL_WINDOWEVENT_RESTORED ||
@@ -2317,6 +2549,26 @@ BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b)
return (FALSE);
}
+#if LL_DARWIN
+LLSD LLWindowSDL::getNativeKeyData()
+{
+ LLSD result = LLSD::emptyMap();
+
+ if(mRawKeyEvent)
+ {
+ result["event_type"] = LLSD::Integer(mRawKeyEvent->mEventType);
+ result["event_modifiers"] = LLSD::Integer(mRawKeyEvent->mEventModifiers);
+ result["event_keycode"] = LLSD::Integer(mRawKeyEvent->mEventKeyCode);
+ result["event_chars"] = (mRawKeyEvent->mEventChars) ? LLSD(LLSD::Integer(mRawKeyEvent->mEventChars)) : LLSD();
+ result["event_umodchars"] = (mRawKeyEvent->mEventUnmodChars) ? LLSD(LLSD::Integer(mRawKeyEvent->mEventUnmodChars)) : LLSD();
+ result["event_isrepeat"] = LLSD::Boolean(mRawKeyEvent->mEventRepeat);
+ }
+
+ LL_DEBUGS() << "native key data is: " << result << LL_ENDL;
+
+ return result;
+}
+#else
/*
Make the raw keyboard data available - used to poke through to LLQtWebKit so
that Qt/Webkit has access to the virtual keycodes etc. that it needs
@@ -2347,8 +2599,9 @@ LLSD LLWindowSDL::getNativeKeyData()
result["input_type"] = mInputType;
return result;
}
+#endif // LL_DARWIN
-#if LL_LINUX || LL_SOLARIS
+#if LL_LINUX || LL_SOLARIS || __FreeBSD__
// extracted from spawnWebBrowser for clarity and to eliminate
// compiler confusion regarding close(int fd) vs. LLWindow::close()
void exec_cmd(const std::string& cmd, const std::string& arg)
@@ -2427,7 +2680,7 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async)
LL_INFOS() << "spawn_web_browser: " << escaped_url << LL_ENDL;
-#if LL_LINUX
+#if LL_LINUX || __FreeBSD__
# if LL_X11
if (mSDL_Display)
{
@@ -2439,13 +2692,53 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async)
# endif // LL_X11
std::string cmd, arg;
+#ifdef LL_USESYSTEMLIBS
+ cmd = gDirUtilp->getExecutableDir();
+#else
cmd = gDirUtilp->getAppRODataDir();
cmd += gDirUtilp->getDirDelimiter();
cmd += "etc";
+#endif
cmd += gDirUtilp->getDirDelimiter();
cmd += "launch_url.sh";
arg = escaped_url;
exec_cmd(cmd, arg);
+
+#elif LL_DARWIN
+
+ S32 result = 0;
+ CFURLRef urlRef = NULL;
+
+ LL_INFOS() << "Opening URL " << escaped_url << LL_ENDL;
+
+ CFStringRef stringRef = CFStringCreateWithCString(NULL, escaped_url.c_str(), kCFStringEncodingUTF8);
+ if (stringRef)
+ {
+ // This will succeed if the string is a full URL, including the http://
+ // Note that URLs specified this way need to be properly percent-escaped.
+ urlRef = CFURLCreateWithString(NULL, stringRef, NULL);
+
+ // Don't use CRURLCreateWithFileSystemPath -- only want valid URLs
+
+ CFRelease(stringRef);
+ }
+
+ if (urlRef)
+ {
+ result = LSOpenCFURLRef(urlRef, NULL);
+
+ if (result != noErr)
+ {
+ LL_INFOS() << "Error " << result << " on open." << LL_ENDL;
+ }
+
+ CFRelease(urlRef);
+ }
+ else
+ {
+ LL_INFOS() << "Error: couldn't create URL." << LL_ENDL;
+ }
+
#endif // LL_LINUX
LL_INFOS() << "spawn_web_browser returning." << LL_ENDL;
@@ -2614,11 +2907,27 @@ void LLWindowSDL::destroySharedContext(void* contextPtr)
void LLWindowSDL::toggleVSync(bool enable_vsync)
{
+ if( !enable_vsync)
+ {
+ SDL_GL_SetSwapInterval(0);
+ SDL_SetHintWithPriority(SDL_HINT_RENDER_VSYNC,"0",SDL_HINT_OVERRIDE);
+ }
+ else
+ {
+ SDL_GL_SetSwapInterval(1);
+ SDL_SetHintWithPriority(SDL_HINT_RENDER_VSYNC,"1",SDL_HINT_OVERRIDE);
+ }
}
U32 LLWindowSDL::getAvailableVRAMMegabytes()
{
+#if LL_DARWIN
+ static const U32 mb = 1024*1024;
+ static const U32 total_factor = 2;
+ return gGLManager.mVRAM - (LLImageGL::getTextureBytesAllocated() * total_factor/mb);
+#else
return 4096;
+#endif
}
void LLWindowSDL::setLanguageTextInput(const LLCoordGL& position)