diff --git a/mythtv/libs/libmythtv/mythvideoout.cpp b/mythtv/libs/libmythtv/mythvideoout.cpp
index ee4b759d81..888b283cfc 100644
a
|
b
|
void MythVideoOutput::InitDisplayMeasurements(void) |
1020 | 1020 | .arg(displayaspect).arg(source)); |
1021 | 1021 | |
1022 | 1022 | // Get the window and screen resolutions |
1023 | | QSize window = m_window.GetWindowRect().size(); |
| 1023 | QSize window = m_window.GetRawWindowRect().size(); |
1024 | 1024 | QSize screen = m_display->GetResolution(); |
1025 | 1025 | |
1026 | 1026 | // If not running fullscreen, adjust for window size and ignore any video |
diff --git a/mythtv/libs/libmythtv/videooutwindow.cpp b/mythtv/libs/libmythtv/videooutwindow.cpp
index af8af15c31..7bd5ca4929 100644
a
|
b
|
|
38 | 38 | |
39 | 39 | #define LOC QString("VideoWin: ") |
40 | 40 | |
| 41 | |
| 42 | #define SCALED_RECT(SRC, SCALE) QRect{ static_cast<int>(SRC.left() * SCALE), \ |
| 43 | static_cast<int>(SRC.top() * SCALE), \ |
| 44 | static_cast<int>(SRC.width() * SCALE), \ |
| 45 | static_cast<int>(SRC.height() * SCALE) } |
41 | 46 | static float fix_aspect(float raw); |
42 | 47 | static float snap(float value, float snapto, float diff); |
43 | 48 | |
… |
… |
void VideoOutWindow::ScreenChanged(QScreen */*screen*/) |
63 | 68 | MoveResize(); |
64 | 69 | } |
65 | 70 | |
| 71 | void VideoOutWindow::PhysicalDPIChanged(qreal /*DPI*/) |
| 72 | { |
| 73 | PopulateGeometry(); |
| 74 | m_windowRect = m_displayVisibleRect = SCALED_RECT(m_rawWindowRect, m_devicePixelRatio); |
| 75 | MoveResize(); |
| 76 | } |
| 77 | |
66 | 78 | void VideoOutWindow::PopulateGeometry(void) |
67 | 79 | { |
68 | 80 | if (!m_display) |
… |
… |
void VideoOutWindow::PopulateGeometry(void) |
72 | 84 | if (!screen) |
73 | 85 | return; |
74 | 86 | |
| 87 | #ifdef Q_OS_MAC |
| 88 | m_devicePixelRatio = screen->devicePixelRatio(); |
| 89 | #endif |
| 90 | |
75 | 91 | if (MythDisplay::SpanAllScreens() && MythDisplay::GetScreenCount() > 1) |
76 | 92 | { |
77 | 93 | m_screenGeometry = screen->virtualGeometry(); |
… |
… |
bool VideoOutWindow::Init(const QSize &VideoDim, const QSize &VideoDispDim, |
416 | 432 | { |
417 | 433 | m_display = Display; |
418 | 434 | connect(m_display, &MythDisplay::CurrentScreenChanged, this, &VideoOutWindow::ScreenChanged); |
| 435 | #ifdef Q_OS_MAC |
| 436 | connect(m_display, &MythDisplay::PhysicalDPIChanged, this, &VideoOutWindow::PhysicalDPIChanged); |
| 437 | #endif |
419 | 438 | } |
420 | 439 | |
421 | 440 | if (m_display) |
… |
… |
bool VideoOutWindow::Init(const QSize &VideoDim, const QSize &VideoDispDim, |
429 | 448 | |
430 | 449 | // N.B. we are always confined to the window size so use that for the initial |
431 | 450 | // displayVisibleRect |
432 | | m_windowRect = m_displayVisibleRect = WindowRect; |
| 451 | m_rawWindowRect = WindowRect; |
| 452 | m_windowRect = m_displayVisibleRect = SCALED_RECT(WindowRect, m_devicePixelRatio); |
433 | 453 | |
434 | 454 | int pbp_width = m_displayVisibleRect.width() / 2; |
435 | 455 | if (m_pipState == kPBPLeft || m_pipState == kPBPRight) |
… |
… |
void VideoOutWindow::SetDisplayAspect(float DisplayAspect) |
613 | 633 | |
614 | 634 | void VideoOutWindow::SetWindowSize(QSize Size) |
615 | 635 | { |
616 | | if (Size != m_windowRect.size()) |
| 636 | if (Size != m_rawWindowRect.size()) |
617 | 637 | { |
618 | | QRect rect(m_windowRect.topLeft(), Size); |
| 638 | QRect rect(m_rawWindowRect.topLeft(), Size); |
619 | 639 | LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("New window rect: %1x%2+%3+%4") |
620 | 640 | .arg(rect.width()).arg(rect.height()).arg(rect.left()).arg(rect.top())); |
621 | | m_windowRect = m_displayVisibleRect = rect; |
| 641 | m_rawWindowRect = rect; |
| 642 | m_windowRect = m_displayVisibleRect = SCALED_RECT(rect, m_devicePixelRatio); |
622 | 643 | MoveResize(); |
623 | 644 | } |
624 | 645 | } |
diff --git a/mythtv/libs/libmythtv/videooutwindow.h b/mythtv/libs/libmythtv/videooutwindow.h
index 9480045c92..cce077b5fd 100644
a
|
b
|
class VideoOutWindow : public QObject |
45 | 45 | |
46 | 46 | public slots: |
47 | 47 | void ScreenChanged (QScreen *screen); |
| 48 | void PhysicalDPIChanged (qreal /*DPI*/); |
48 | 49 | |
49 | 50 | // Sets |
50 | 51 | void InputChanged (const QSize &VideoDim, const QSize &VideoDispDim, float Aspect); |
… |
… |
class VideoOutWindow : public QObject |
74 | 75 | float GetOverridenVideoAspect(void) const { return m_videoAspectOverride;} |
75 | 76 | QRect GetDisplayVisibleRect(void) const { return m_displayVisibleRect; } |
76 | 77 | QRect GetWindowRect(void) const { return m_windowRect; } |
| 78 | QRect GetRawWindowRect(void) const { return m_rawWindowRect; } |
77 | 79 | QRect GetScreenGeometry(void) const { return m_screenGeometry; } |
78 | 80 | QRect GetVideoRect(void) const { return m_videoRect; } |
79 | 81 | QRect GetDisplayVideoRect(void) const { return m_displayVideoRect; } |
… |
… |
class VideoOutWindow : public QObject |
115 | 117 | bool m_dbScalingAllowed {true}; ///< disable this to prevent overscan/underscan |
116 | 118 | bool m_dbUseGUISize {false}; ///< Use the gui size for video window |
117 | 119 | QRect m_screenGeometry {0,0,1024,768}; ///< Full screen geometry |
| 120 | qreal m_devicePixelRatio {1.0}; |
118 | 121 | |
119 | 122 | // Manual Zoom |
120 | 123 | float m_manualVertScale {1.0F}; ///< Manually applied vertical scaling. |
… |
… |
class VideoOutWindow : public QObject |
147 | 150 | QRect m_displayVisibleRect {0,0,0,0}; |
148 | 151 | /// Rectangle describing QWidget bounds. |
149 | 152 | QRect m_windowRect {0,0,0,0}; |
| 153 | /// Rectangle describing QWidget bounds - not adjusted for high DPI scaling (macos) |
| 154 | QRect m_rawWindowRect {0,0,0,0}; |
150 | 155 | /// Used to save the display_visible_rect for |
151 | 156 | /// restoration after video embedding ends. |
152 | 157 | QRect m_tmpDisplayVisibleRect {0,0,0,0}; |
diff --git a/mythtv/libs/libmythui/opengl/mythpainteropengl.cpp b/mythtv/libs/libmythui/opengl/mythpainteropengl.cpp
index 8fec14d3c2..53cd422544 100644
a
|
b
|
void MythOpenGLPainter::Begin(QPaintDevice *Parent) |
109 | 109 | buf = m_render->CreateVBO(static_cast<int>(MythRenderOpenGL::kVertexSize)); |
110 | 110 | } |
111 | 111 | |
| 112 | // check for high dpi on macos |
| 113 | // If we do not have swap control (i.e. OSD), then the master should be pixel |
| 114 | // ratio 'aware' (i.e. the video output classes) |
| 115 | #if defined(Q_OS_MAC) |
| 116 | m_pixelRatio = m_swapControl ? m_parent->devicePixelRatioF() : 1.0; |
| 117 | #endif |
| 118 | QSize currentsize = m_parent->size() * m_pixelRatio; |
| 119 | |
112 | 120 | // check if we need to adjust cache sizes |
113 | | if (m_lastSize != m_parent->size()) |
| 121 | if (m_lastSize != currentsize) |
114 | 122 | { |
115 | 123 | // This will scale the cache depending on the resolution in use |
116 | 124 | static const int s_onehd = 1920 * 1080; |
117 | 125 | static const int s_basesize = 64; |
118 | | m_lastSize = m_parent->size(); |
| 126 | m_lastSize = currentsize; |
119 | 127 | float hdscreens = (static_cast<float>(m_lastSize.width() + 1) * m_lastSize.height()) / s_onehd; |
120 | 128 | int cpu = qMax(static_cast<int>(hdscreens * s_basesize), s_basesize); |
121 | 129 | int gpu = cpu * 3 / 2; |
… |
… |
void MythOpenGLPainter::Begin(QPaintDevice *Parent) |
131 | 139 | if (m_target || m_swapControl) |
132 | 140 | { |
133 | 141 | m_render->BindFramebuffer(m_target); |
134 | | m_render->SetViewPort(QRect(0, 0, m_parent->width(), m_parent->height())); |
| 142 | m_render->SetViewPort(QRect(0, 0, m_lastSize.width(), m_lastSize.height())); |
135 | 143 | m_render->SetBackground(0, 0, 0, 0); |
136 | 144 | m_render->ClearFramebuffer(); |
137 | 145 | } |
… |
… |
void MythOpenGLPainter::DrawImage(const QRect &Dest, MythImage *Image, |
226 | 234 | { |
227 | 235 | if (m_render) |
228 | 236 | { |
229 | | // Drawing an image multiple times with the same VBO will stall most GPUs as |
| 237 | // Drawing an image multiple times with the same VBO will stall most GPUs as |
230 | 238 | // the VBO is re-mapped whilst still in use. Use a pooled VBO instead. |
231 | 239 | MythGLTexture *texture = GetTextureFromCache(Image); |
232 | 240 | if (texture && m_mappedTextures.contains(texture)) |
… |
… |
void MythOpenGLPainter::DrawImage(const QRect &Dest, MythImage *Image, |
234 | 242 | QOpenGLBuffer *vbo = texture->m_vbo; |
235 | 243 | texture->m_vbo = m_mappedBufferPool[m_mappedBufferPoolIdx]; |
236 | 244 | texture->m_destination = QRect(); |
237 | | m_render->DrawBitmap(texture, m_target, Source, Dest, nullptr, Alpha); |
| 245 | m_render->DrawBitmap(texture, m_target, Source, Dest, nullptr, Alpha, m_pixelRatio); |
238 | 246 | texture->m_destination = QRect(); |
239 | 247 | texture->m_vbo = vbo; |
240 | 248 | if (++m_mappedBufferPoolIdx >= MAX_BUFFER_POOL) |
… |
… |
void MythOpenGLPainter::DrawImage(const QRect &Dest, MythImage *Image, |
242 | 250 | } |
243 | 251 | else |
244 | 252 | { |
245 | | m_render->DrawBitmap(texture, m_target, Source, Dest, nullptr, Alpha); |
| 253 | m_render->DrawBitmap(texture, m_target, Source, Dest, nullptr, Alpha, m_pixelRatio); |
246 | 254 | m_mappedTextures.append(texture); |
247 | 255 | } |
248 | 256 | } |
249 | 257 | } |
250 | 258 | |
| 259 | /*! \brief Render a rectangle to the UI |
| 260 | * |
| 261 | * \note MythRenderOpenGL can only handle simple (i.e. solid) brush patterns - |
| 262 | * otherwise we fallback to QPainter rendering, which will create a QImage that |
| 263 | * will be rendered as a texture. |
| 264 | * \note Fallback to QPainter rendering for high DPI (pixel ratio > 1.0) rather |
| 265 | * than handle the various adjustments that are needed. |
| 266 | */ |
251 | 267 | void MythOpenGLPainter::DrawRect(const QRect &Area, const QBrush &FillBrush, |
252 | 268 | const QPen &LinePen, int Alpha) |
253 | 269 | { |
254 | | if ((FillBrush.style() == Qt::SolidPattern || |
255 | | FillBrush.style() == Qt::NoBrush) && m_render) |
| 270 | if ((FillBrush.style() == Qt::SolidPattern || FillBrush.style() == Qt::NoBrush) && |
| 271 | (m_pixelRatio == 1.0) && m_render) |
256 | 272 | { |
257 | 273 | m_render->DrawRect(m_target, Area, FillBrush, LinePen, Alpha); |
258 | 274 | return; |
259 | 275 | } |
| 276 | |
260 | 277 | MythPainter::DrawRect(Area, FillBrush, LinePen, Alpha); |
261 | 278 | } |
262 | 279 | |
… |
… |
void MythOpenGLPainter::DrawRoundRect(const QRect &Area, int CornerRadius, |
264 | 281 | const QBrush &FillBrush, |
265 | 282 | const QPen &LinePen, int Alpha) |
266 | 283 | { |
267 | | if ((FillBrush.style() == Qt::SolidPattern || |
268 | | FillBrush.style() == Qt::NoBrush) && m_render) |
| 284 | if ((FillBrush.style() == Qt::SolidPattern || FillBrush.style() == Qt::NoBrush) && |
| 285 | (m_pixelRatio = 1.0) && m_render) |
269 | 286 | { |
270 | | m_render->DrawRoundRect(m_target, Area, CornerRadius, FillBrush, |
271 | | LinePen, Alpha); |
| 287 | m_render->DrawRoundRect(m_target, Area, CornerRadius, FillBrush, LinePen, Alpha); |
272 | 288 | return; |
273 | 289 | } |
| 290 | |
274 | 291 | MythPainter::DrawRoundRect(Area, CornerRadius, FillBrush, LinePen, Alpha); |
275 | 292 | } |
276 | 293 | |
diff --git a/mythtv/libs/libmythui/opengl/mythpainteropengl.h b/mythtv/libs/libmythui/opengl/mythpainteropengl.h
index 097577231f..b4a72bd586 100644
a
|
b
|
class MUI_PUBLIC MythOpenGLPainter : public MythPainter |
60 | 60 | QOpenGLFramebufferObject* m_target { nullptr }; |
61 | 61 | bool m_swapControl { true }; |
62 | 62 | QSize m_lastSize { }; |
| 63 | qreal m_pixelRatio { 1.0 }; |
63 | 64 | |
64 | 65 | QMap<MythImage *, MythGLTexture*> m_imageToTextureMap; |
65 | 66 | std::list<MythImage *> m_ImageExpireList; |
diff --git a/mythtv/libs/libmythui/opengl/mythrenderopengl.cpp b/mythtv/libs/libmythui/opengl/mythrenderopengl.cpp
index e34320f3dc..c67e518d66 100644
a
|
b
|
void MythRenderOpenGL::ClearFramebuffer(void) |
804 | 804 | |
805 | 805 | void MythRenderOpenGL::DrawBitmap(MythGLTexture *Texture, QOpenGLFramebufferObject *Target, |
806 | 806 | const QRect &Source, const QRect &Destination, |
807 | | QOpenGLShaderProgram *Program, int Alpha) |
| 807 | QOpenGLShaderProgram *Program, int Alpha, qreal Scale) |
808 | 808 | { |
809 | 809 | makeCurrent(); |
810 | 810 | |
… |
… |
void MythRenderOpenGL::DrawBitmap(MythGLTexture *Texture, QOpenGLFramebufferObje |
827 | 827 | |
828 | 828 | QOpenGLBuffer* buffer = Texture->m_vbo; |
829 | 829 | buffer->bind(); |
830 | | if (UpdateTextureVertices(Texture, Source, Destination, 0)) |
| 830 | if (UpdateTextureVertices(Texture, Source, Destination, 0, Scale)) |
831 | 831 | { |
832 | 832 | if (m_extraFeaturesUsed & kGLBufferMap) |
833 | 833 | { |
… |
… |
QStringList MythRenderOpenGL::GetDescription(void) |
1262 | 1262 | } |
1263 | 1263 | |
1264 | 1264 | bool MythRenderOpenGL::UpdateTextureVertices(MythGLTexture *Texture, const QRect &Source, |
1265 | | const QRect &Destination, int Rotation) |
| 1265 | const QRect &Destination, int Rotation, qreal Scale) |
1266 | 1266 | { |
1267 | 1267 | if (!Texture || (Texture && Texture->m_size.isEmpty())) |
1268 | 1268 | return false; |
1269 | 1269 | |
| 1270 | #ifdef Q_OS_MAC |
| 1271 | QRect destination { static_cast<int>(Destination.left() * Scale), |
| 1272 | static_cast<int>(Destination.top() * Scale), |
| 1273 | static_cast<int>(Destination.width() * Scale), |
| 1274 | static_cast<int>(Destination.height() * Scale) }; |
| 1275 | if ((Texture->m_source == Source) && (Texture->m_destination == destination) && |
| 1276 | (Texture->m_rotation == Rotation)) |
| 1277 | return false; |
| 1278 | Texture->m_destination = destination; |
| 1279 | #else |
| 1280 | (void)Scale; |
1270 | 1281 | if ((Texture->m_source == Source) && (Texture->m_destination == Destination) && |
1271 | 1282 | (Texture->m_rotation == Rotation)) |
1272 | 1283 | return false; |
1273 | | |
1274 | | Texture->m_source = Source; |
1275 | 1284 | Texture->m_destination = Destination; |
| 1285 | #endif |
| 1286 | Texture->m_source = Source; |
1276 | 1287 | Texture->m_rotation = Rotation; |
1277 | 1288 | |
1278 | 1289 | GLfloat *data = Texture->m_vertexData; |
… |
… |
bool MythRenderOpenGL::UpdateTextureVertices(MythGLTexture *Texture, const QRect |
1301 | 1312 | data[4 + TEX_OFFSET] = data[6 + TEX_OFFSET]; |
1302 | 1313 | data[5 + TEX_OFFSET] = data[1 + TEX_OFFSET]; |
1303 | 1314 | |
| 1315 | #ifdef Q_OS_MAC |
| 1316 | width = Texture->m_crop ? min(static_cast<int>(width * Scale), destination.width()) : destination.width(); |
| 1317 | height = Texture->m_crop ? min(static_cast<int>(height * Scale), destination.height()) : destination.height(); |
| 1318 | |
| 1319 | data[2] = data[0] = destination.left(); |
| 1320 | data[5] = data[1] = destination.top(); |
| 1321 | data[4] = data[6] = destination.left() + width; |
| 1322 | data[3] = data[7] = destination.top() + height; |
| 1323 | #else |
1304 | 1324 | width = Texture->m_crop ? min(width, Destination.width()) : Destination.width(); |
1305 | 1325 | height = Texture->m_crop ? min(height, Destination.height()) : Destination.height(); |
1306 | 1326 | |
… |
… |
bool MythRenderOpenGL::UpdateTextureVertices(MythGLTexture *Texture, const QRect |
1308 | 1328 | data[5] = data[1] = Destination.top(); |
1309 | 1329 | data[4] = data[6] = Destination.left() + width; |
1310 | 1330 | data[3] = data[7] = Destination.top() + height; |
| 1331 | #endif |
1311 | 1332 | |
1312 | 1333 | if (Texture->m_rotation != 0) |
1313 | 1334 | { |
diff --git a/mythtv/libs/libmythui/opengl/mythrenderopengl.h b/mythtv/libs/libmythui/opengl/mythrenderopengl.h
index 199f0d642b..2ccb9a60d5 100644
a
|
b
|
class MUI_PUBLIC MythRenderOpenGL : public QOpenGLContext, public QOpenGLFunctio |
143 | 143 | |
144 | 144 | void DrawBitmap(MythGLTexture *Texture, QOpenGLFramebufferObject *Target, |
145 | 145 | const QRect &Source, const QRect &Destination, |
146 | | QOpenGLShaderProgram *Program, int Alpha = 255); |
| 146 | QOpenGLShaderProgram *Program, int Alpha = 255, qreal Scale = 1.0); |
147 | 147 | void DrawBitmap(MythGLTexture **Textures, uint TextureCount, |
148 | 148 | QOpenGLFramebufferObject *Target, |
149 | 149 | const QRect &Source, const QRect &Destination, |
… |
… |
class MUI_PUBLIC MythRenderOpenGL : public QOpenGLContext, public QOpenGLFunctio |
171 | 171 | void SetMatrixView(void); |
172 | 172 | void DeleteFramebuffers(void); |
173 | 173 | static bool UpdateTextureVertices(MythGLTexture *Texture, const QRect &Source, |
174 | | const QRect &Destination, int Rotation); |
| 174 | const QRect &Destination, int Rotation, qreal Scale = 1.0); |
175 | 175 | GLfloat* GetCachedVertices(GLuint Type, const QRect &Area); |
176 | 176 | void ExpireVertices(int Max = 0); |
177 | 177 | void GetCachedVBO(GLuint Type, const QRect &Area); |
diff --git a/mythtv/libs/libmythui/platforms/mythdisplayosx.cpp b/mythtv/libs/libmythui/platforms/mythdisplayosx.cpp
index fa2de7c4cf..68e342a2a1 100644
a
|
b
|
void MythDisplayOSX::UpdateCurrentMode(void) |
27 | 27 | { |
28 | 28 | if (!HasMythMainWindow()) |
29 | 29 | { |
| 30 | LOG(VB_GENERAL, LOG_WARNING, LOC + "Cannot update current mode"); |
30 | 31 | MythDisplay::UpdateCurrentMode(); |
31 | 32 | return; |
32 | 33 | } |
… |
… |
void MythDisplayOSX::UpdateCurrentMode(void) |
36 | 37 | CGDirectDisplayID disp = GetOSXDisplay(widget->winId()); |
37 | 38 | if (!disp) |
38 | 39 | { |
| 40 | LOG(VB_GENERAL, LOG_WARNING, LOC + "No display"); |
39 | 41 | MythDisplay::UpdateCurrentMode(); |
40 | 42 | return; |
41 | 43 | } |
42 | 44 | CGDisplayModeRef mode = CGDisplayCopyDisplayMode(disp); |
43 | 45 | if (!mode) |
44 | 46 | { |
| 47 | LOG(VB_GENERAL, LOG_WARNING, LOC + "Could not copy mode"); |
45 | 48 | MythDisplay::UpdateCurrentMode(); |
46 | 49 | return; |
47 | 50 | } |
… |
… |
bool MythDisplayOSX::UsingVideoModes(void) |
67 | 70 | |
68 | 71 | const std::vector<MythDisplayMode>& MythDisplayOSX::GetVideoModes(void) |
69 | 72 | { |
70 | | if (!m_videoModes.empty() || !HasMythMainWindow()) |
| 73 | if (!m_videoModes.empty()) |
71 | 74 | return m_videoModes; |
72 | 75 | |
| 76 | if (!HasMythMainWindow()) |
| 77 | { |
| 78 | LOG(VB_GENERAL, LOG_WARNING, LOC + "Cannot retrieve modes"); |
| 79 | return m_videoModes; |
| 80 | } |
| 81 | |
73 | 82 | ClearModes(); |
74 | 83 | |
75 | 84 | WId win = (qobject_cast<QWidget*>(MythMainWindow::getMainWindow()))->winId(); |
… |
… |
const std::vector<MythDisplayMode>& MythDisplayOSX::GetVideoModes(void) |
83 | 92 | DisplayModeMap screen_map; |
84 | 93 | CGSize sizemm = CGDisplayScreenSize(disp); |
85 | 94 | |
| 95 | LOG(VB_GENERAL, LOG_INFO, LOC + "Raw video mode sizes:"); |
86 | 96 | for (int i = 0; i < CFArrayGetCount(modes); ++i) |
87 | 97 | { |
88 | 98 | CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); |
… |
… |
const std::vector<MythDisplayMode>& MythDisplayOSX::GetVideoModes(void) |
90 | 100 | bool interlaced = CGDisplayModeGetIOFlags(mode) & kDisplayModeInterlacedFlag; |
91 | 101 | int width = static_cast<int>(CGDisplayModeGetWidth(mode)); |
92 | 102 | int height = static_cast<int>(CGDisplayModeGetHeight(mode)); |
| 103 | int widthp = static_cast<int>(CGDisplayModeGetPixelWidth(mode)); |
| 104 | int heightp = static_cast<int>(CGDisplayModeGetPixelHeight(mode)); |
| 105 | |
| 106 | LOG(VB_GENERAL, LOG_INFO, LOC + QString("Resolution: %1x%2 PixelSize: %3x%4") |
| 107 | .arg(width).arg(height).arg(widthp).arg(heightp)); |
93 | 108 | |
94 | 109 | // See note in MythDisplayX11 |
95 | 110 | if (interlaced) |
… |
… |
const std::vector<MythDisplayMode>& MythDisplayOSX::GetVideoModes(void) |
120 | 135 | bool MythDisplayOSX::SwitchToVideoMode(QSize Size, double DesiredRate) |
121 | 136 | { |
122 | 137 | if (!HasMythMainWindow()) |
| 138 | { |
| 139 | LOG(VB_GENERAL, LOG_WARNING, LOC + "Cannot switch mode"); |
123 | 140 | return false; |
| 141 | } |
| 142 | |
124 | 143 | WId win = (qobject_cast<QWidget*>(MythMainWindow::getMainWindow()))->winId(); |
125 | 144 | CGDirectDisplayID disp = GetOSXDisplay(win); |
126 | 145 | if (!disp) |
| 146 | { |
| 147 | LOG(VB_GENERAL, LOG_WARNING, LOC + "No display"); |
127 | 148 | return false; |
| 149 | } |
128 | 150 | |
129 | 151 | auto rate = static_cast<double>(NAN); |
130 | 152 | MythDisplayMode desired(Size, QSize(0, 0), -1.0, DesiredRate); |
… |
… |
bool MythDisplayOSX::SwitchToVideoMode(QSize Size, double DesiredRate) |
147 | 169 | CGDisplayConfigRef cfg; |
148 | 170 | CGBeginDisplayConfiguration(&cfg); |
149 | 171 | CGConfigureDisplayFadeEffect(cfg, 0.3f, 0.5f, 0, 0, 0); |
150 | | CGDisplaySetDisplayMode(disp, m_modeMap.value(mode), nullptr); |
151 | | CGError err = CGCompleteDisplayConfiguration(cfg, kCGConfigureForAppOnly); |
| 172 | CGError err = CGDisplaySetDisplayMode(disp, m_modeMap.value(mode), nullptr); |
| 173 | if (err != kCGErrorSuccess) |
| 174 | LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to set display mode (%1)").arg(err)); |
| 175 | err = CGCompleteDisplayConfiguration(cfg, kCGConfigureForAppOnly); |
152 | 176 | CGDisplayRelease(disp); |
153 | 177 | return err == kCGErrorSuccess; |
154 | 178 | } |