Skip to content

Commit

Permalink
Added: DisplayMode class
Browse files Browse the repository at this point in the history
Implemented display mode enumeration for Mac OS X.
Modes are automatically sorted by size and their width/height
ratio is calculated.
  • Loading branch information
skyjake committed Mar 18, 2012
1 parent 80356ce commit b825280
Show file tree
Hide file tree
Showing 6 changed files with 321 additions and 0 deletions.
4 changes: 4 additions & 0 deletions doomsday/engine/engine.pro
Expand Up @@ -185,6 +185,7 @@ DENG_HEADERS = \
portable/include/de_render.h \
portable/include/de_system.h \
portable/include/de_ui.h \
portable/include/displaymode.h \
portable/include/edit_bias.h \
portable/include/edit_map.h \
portable/include/filedirectory.h \
Expand Down Expand Up @@ -345,9 +346,11 @@ unix:!win32 {
}
macx {
DENG_PLATFORM_HEADERS += \
$$DENG_MAC_INCLUDE_DIR/displaymode_macx.h \
$$DENG_MAC_INCLUDE_DIR/MusicPlayer.h

OBJECTIVE_SOURCES += \
mac/src/displaymode_macx.mm \
mac/src/MusicPlayer.m

INCLUDEPATH += $$DENG_MAC_INCLUDE_DIR
Expand Down Expand Up @@ -437,6 +440,7 @@ SOURCES += \
portable/src/dfile.c \
portable/src/dgl_common.c \
portable/src/dgl_draw.c \
portable/src/displaymode.cpp \
portable/src/edit_bias.c \
portable/src/edit_map.c \
portable/src/filedirectory.c \
Expand Down
43 changes: 43 additions & 0 deletions doomsday/engine/mac/include/displaymode_macx.h
@@ -0,0 +1,43 @@
/**
* @file displaymode_macx.h
* Changing and enumerating available display modes for Mac OS X. @ingroup gl
*
* @authors Copyright © 2012 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA</small>
*/

#ifndef LIBDENG_DISPLAYMODE_MACX_H
#define LIBDENG_DISPLAYMODE_MACX_H

#include "displaymode.h"

#ifdef __cplusplus
extern "C" {
#endif

void DisplayMode_Native_Init(void);

int DisplayMode_Native_Count(void);

void DisplayMode_Native_GetMode(int index, DisplayMode* mode);

void DisplayMode_Native_Shutdown(void);

#ifdef __cplusplus
}
#endif

#endif // LIBDENG_DISPLAYMODE_MACX_H
89 changes: 89 additions & 0 deletions doomsday/engine/mac/src/displaymode_macx.mm
@@ -0,0 +1,89 @@
/**
* @file displaymode.mm
* Mac OS X implementation of the DisplayMode class. @ingroup gl
*
* @authors Copyright © 2012 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA</small>
*/

#include "displaymode_macx.h"
#include "dd_types.h"

#include <assert.h>
#include <CoreFoundation/CoreFoundation.h>
#include <ApplicationServices/ApplicationServices.h>
#include <vector>
#include <qDebug>

/// Returns -1 on error.
static int intFromDict(CFDictionaryRef dict, CFStringRef key)
{
CFNumberRef ref = (CFNumberRef) CFDictionaryGetValue(dict, key);
if(!ref) return -1;
int value;
if(!CFNumberGetValue(ref, kCFNumberIntType, &value)) return -1;
return value;
}

/// Returns -1 on error.
static float floatFromDict(CFDictionaryRef dict, CFStringRef key)
{
CFNumberRef ref = (CFNumberRef) CFDictionaryGetValue(dict, key);
if(!ref) return -1;
float value;
if(!CFNumberGetValue(ref, kCFNumberFloatType, &value)) return -1;
return value;
}

static DisplayMode modeFromDict(CFDictionaryRef dict)
{
DisplayMode m;
m.width = intFromDict(dict, kCGDisplayWidth);
m.height = intFromDict(dict, kCGDisplayHeight);
m.refreshRate = floatFromDict(dict, kCGDisplayRefreshRate);
m.depth = intFromDict(dict, kCGDisplayBitsPerPixel);
return m;
}

static std::vector<DisplayMode> displayModes;

void DisplayMode_Native_Init(void)
{
// Let's see which modes are available.
CFArrayRef modes = CGDisplayAvailableModes(kCGDirectMainDisplay);
CFIndex count = CFArrayGetCount(modes);
for(CFIndex i = 0; i < count; ++i)
{
displayModes.push_back(modeFromDict((CFDictionaryRef)CFArrayGetValueAtIndex(modes, i)));
}
}

int DisplayMode_Native_Count(void)
{
return displayModes.size();
}

void DisplayMode_Native_GetMode(int index, DisplayMode* mode)
{
assert(index >= 0 && index < (int)displayModes.size());
*mode = displayModes[index];
}

void DisplayMode_Native_Shutdown(void)
{
displayModes.clear();
}

56 changes: 56 additions & 0 deletions doomsday/engine/portable/include/displaymode.h
@@ -0,0 +1,56 @@
/**
* @file displaymode.h
* Changing and enumerating available display modes. @ingroup gl
*
* @authors Copyright © 2012 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA</small>
*/

#ifndef LIBDENG_DISPLAYMODE_H
#define LIBDENG_DISPLAYMODE_H

#ifdef __cplusplus
extern "C" {
#endif

typedef struct displaymode_s {
int width;
int height;
float refreshRate; // might be zero
int depth;

// Calculated automatically:
int ratioX;
int ratioY;
} DisplayMode;

/**
* Initializes the DisplayMode class. Enumerates all available display modes and
* saves the current display mode.
*/
int DisplayMode_Init(void);

/**
* Shuts down the DisplayMode class. The current display mode is restored to what
* it was at initialization time.
*/
void DisplayMode_Shutdown(void);

#ifdef __cplusplus
}
#endif

#endif // LIBDENG_DISPLAYMODE_H
11 changes: 11 additions & 0 deletions doomsday/engine/portable/src/dd_init.cpp
Expand Up @@ -65,6 +65,7 @@
#include "de_platform.h"
#include "dd_loop.h"
#include "window.h"
#include "displaymode.h"
#include "sys_system.h"

extern "C" {
Expand Down Expand Up @@ -131,6 +132,11 @@ int main(int argc, char** argv)
// C interface to the app.
de2LegacyCore = LegacyCore_New(&dengApp);

if(useGUI)
{
DisplayMode_Init();
}

// Initialize.
#if WIN32
if(!DD_Win32_Init()) return 1;
Expand All @@ -153,5 +159,10 @@ int main(int argc, char** argv)
DD_Shutdown();
LegacyCore_Delete(de2LegacyCore);

if(useGUI)
{
DisplayMode_Shutdown();
}

return result;
}
118 changes: 118 additions & 0 deletions doomsday/engine/portable/src/displaymode.cpp
@@ -0,0 +1,118 @@
/**
* @file displaymode.cpp
* Platform-independent display mode management. @ingroup gl
*
* @authors Copyright (c) 2012 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA</small>
*/

#include "displaymode.h"

#ifdef MACOSX
# include "displaymode_macx.h"
#endif

#include <vector>
#include <set>
#include <algorithm>

#include <qDebug>

static bool inited = false;

typedef std::set<DisplayMode> DisplayModes;
static DisplayModes displayModes;

static bool operator < (const DisplayMode& a, const DisplayMode& b)
{
if(a.height == b.height)
{
if(a.width == b.width)
{
if(a.depth == b.depth)
{
return a.refreshRate < b.refreshRate;
}
return a.depth < b.depth;
}
return a.width < b.width;
}
return a.height < b.height;
}

static void calculateRatio(int width, int height, int* x, int* y)
{
Q_ASSERT(x && y);

*x = width;
*y = height;

// Reduce until we must resort to fractions.
forever
{
bool divved = false;
for(int div = 2; div <= qMin(*x/2, *y/2); div++)
{
int dx = *x / div;
if(dx * div != *x) continue;
int dy = *y / div;
if(dy * div != *y) continue;
divved = true;
*x = dx;
*y = dy;
break;
}
if(!divved) break;
}

if(*x == 8 && *y == 5)
{
// This is commonly referred to as 16:10.
*x *= 2;
*y *= 2;
}
}

int DisplayMode_Init(void)
{
if(inited) return true;

DisplayMode_Native_Init();

for(int i = 0; i < DisplayMode_Native_Count(); ++i)
{
DisplayMode m;
DisplayMode_Native_GetMode(i, &m);
calculateRatio(m.width, m.height, &m.ratioX, &m.ratioY);
displayModes.insert(m);
}

for(DisplayModes::iterator i = displayModes.begin(); i != displayModes.end(); ++i)
{
qDebug() << "size" << i->width << "x" << i->height << "depth" << i->depth << "rate"
<< i->refreshRate << "ratio" << i->ratioX << ":" << i->ratioY;
}

inited = true;
return true;
}

void DisplayMode_Shutdown(void)
{
displayModes.clear();

DisplayMode_Native_Shutdown();
}

0 comments on commit b825280

Please sign in to comment.