18#if defined(WITH_COCOA) || defined(DOXYGEN_API)
20#include "../../stdafx.h"
21#include "../../os/macosx/macos.h"
24#define GL_SILENCE_DEPRECATION
26#include "../../os/macosx/macos_objective_c.h"
27#include "../../openttd.h"
28#include "../../debug.h"
29#include "../../core/geometry_func.hpp"
30#include "../../core/math_func.hpp"
33#include "../../blitter/factory.hpp"
34#include "../../gfx_func.h"
35#include "../../framerate_type.h"
39#import <OpenGL/OpenGL.h>
47 static void *dl =
nullptr;
50 dl = dlopen(
"/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
53 return reinterpret_cast<OGLProc
>(dlsym(dl, proc));
58 CGLContextObj _context;
61@property (
class)
bool allowSoftware;
62+ (CGLPixelFormatObj)defaultPixelFormat;
64- (instancetype)initWithContext:(CGLContextObj)context;
69static bool _allowSoftware;
72 return _allowSoftware;
74+ (void)setAllowSoftware:(
bool)newVal
76 _allowSoftware = newVal;
79- (instancetype)initWithContext:(CGLContextObj)context
81 if (self = [ super init ]) {
82 self->_context = context;
85 self.magnificationFilter = kCAFilterNearest;
90+ (CGLPixelFormatObj)defaultPixelFormat
92 CGLPixelFormatAttribute attribs[] = {
93 kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core,
94 kCGLPFAColorSize, (CGLPixelFormatAttribute)24,
95 kCGLPFAAlphaSize, (CGLPixelFormatAttribute)0,
96 kCGLPFADepthSize, (CGLPixelFormatAttribute)0,
98 kCGLPFAAllowOfflineRenderers,
99 kCGLPFASupportsAutomaticGraphicsSwitching,
101 _allowSoftware ? (CGLPixelFormatAttribute)0 : kCGLPFAAccelerated,
102 (CGLPixelFormatAttribute)0
105 CGLPixelFormatObj pxfmt =
nullptr;
106 GLint numPixelFormats;
107 CGLChoosePixelFormat(attribs, &pxfmt, &numPixelFormats);
112- (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask
117- (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pf
120 CGLCreateContext(pf, self->_context, &ctx);
123 CGLSetCurrentContext(ctx);
129- (void)drawInCGLContext:(CGLContextObj)ctx pixelFormat:(CGLPixelFormatObj)pf forLayerTime:(CFTimeInterval)t displayTime:(nullable const CVTimeStamp *)ts
131 CGLSetCurrentContext(ctx);
136 [
super drawInCGLContext:ctx pixelFormat:pf forLayerTime:t displayTime:ts ];
141- (instancetype)initWithFrame:(NSRect)frameRect context:(CGLContextObj)context;
146- (instancetype)initWithFrame:(NSRect)frameRect context:(CGLContextObj)context
148 if (self = [ super initWithFrame:frameRect ]) {
150 self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay;
153 CALayer *l = [ [
OTTD_CGLLayer alloc ] initWithContext:context ];
155 self.wantsLayer = YES;
161- (BOOL)acceptsFirstResponder
171- (void)viewDidChangeBackingProperties
173 self.layer.contentsScale =
_allow_hidpi_window && [
self.window respondsToSelector:@selector(backingScaleFactor) ] ? [
self.window backingScaleFactor ] : 1.0f;
184 auto err = this->Initialize();
188 if (bpp != 8 && bpp != 32) {
190 return "The cocoa OpenGL subdriver only supports 8 and 32 bpp.";
200 this->driver_info = GetName();
201 this->driver_info +=
" (";
203 this->driver_info +=
")";
205 bool fullscreen = _fullscreen;
208 return "Could not create window";
211 this->AllocateBackingStore(
true);
213 if (fullscreen) this->ToggleFullscreen(fullscreen);
216 this->UpdateVideoModes();
229 CGLSetCurrentContext(this->gl_context);
231 CGLReleaseContext(this->gl_context);
245 CGLSetCurrentContext(this->gl_context);
249std::optional<std::string_view> VideoDriver_CocoaOpenGL::AllocateContext(
bool allow_software)
253 CGLPixelFormatObj pxfmt = [
OTTD_CGLLayer defaultPixelFormat ];
254 if (pxfmt ==
nullptr)
return "No suitable pixel format found";
256 CGLCreateContext(pxfmt,
nullptr, &this->gl_context);
257 CGLDestroyPixelFormat(pxfmt);
259 if (this->gl_context ==
nullptr)
return "Can't create a rendering context";
261 CGLSetCurrentContext(this->gl_context);
266NSView *VideoDriver_CocoaOpenGL::AllocateDrawView()
268 return [ [
OTTD_CGLLayerView alloc ] initWithFrame:this->cocoaview.bounds context:this->gl_context ];
274 if (this->window == nil || this->setup)
return;
276 if (_screen.dst_ptr !=
nullptr) this->ReleaseVideoPointer();
278 CGLSetCurrentContext(this->gl_context);
279 NSRect frame = [ this->cocoaview getRealRect:[ this->cocoaview frame ] ];
281 if (this->buffer_locked) _screen.dst_ptr = this->GetVideoPointer();
282 this->dirty_rect = {};
290 CGLSetCurrentContext(this->gl_context);
299 CGLSetCurrentContext(this->gl_context);
303 this->dirty_rect = {};
304 _screen.dst_ptr =
nullptr;
305 this->anim_buffer =
nullptr;
316 CGLSetCurrentContext(this->gl_context);
323 [ CATransaction begin ];
324 [ this->cocoaview.subviews[0].layer setNeedsDisplay ];
325 [ CATransaction commit ];
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
How all blitters should look like.
virtual uint8_t GetScreenDepth()=0
Get the screen depth this blitter works for.
virtual Blitter::PaletteAnimation UsePaletteAnimation()=0
Check if the blitter uses palette animation at all.
virtual void PaletteAnimate(const Palette &palette)=0
Called when the 8bpp palette is changed; you should redraw all pixels on the screen that are equal to...
@ Blitter
The blitter takes care of the palette animation.
void Paint()
Render video buffer to the screen.
uint8_t * GetAnimBuffer()
Get a pointer to the memory for the separate animation buffer.
void * GetVideoBuffer()
Get a pointer to the memory for the video driver to draw to.
bool Resize(int w, int h, bool force=false)
Change the size of the drawing window and allocate matching resources.
static std::optional< std::string_view > Create(GetOGLProcAddressProc get_proc, const Dimension &screen_res)
Create and initialize the singleton back-end class.
void UpdatePalette(const Colour *pal, uint first, uint length)
Update the stored palette.
void ReleaseAnimBuffer(const Rect &update_rect)
Update animation buffer texture after the animation buffer was filled.
void ClearCursorCache()
Queue a request for cursor cache clear.
static OpenGLBackend * Get()
Get singleton instance of this class.
void DrawMouseCursor()
Draw mouse cursor on screen.
void ReleaseVideoBuffer(const Rect &update_rect)
Update video buffer texture after the video buffer was filled.
static void Destroy()
Free resources and destroy singleton back-end class.
void * GetVideoPointer() override
Get a pointer to the video buffer.
void PopulateSystemSprites() override
Populate all sprites in cache.
void ReleaseVideoPointer() override
Hand video buffer back to the drawing backend.
std::optional< std::string_view > Start(const StringList ¶m) override
Start this driver.
void Paint() override
Paint the window.
void ClearSystemSprites() override
Clear all cached sprites.
void Stop() override
Stop Cocoa video driver.
void AllocateBackingStore(bool force=false) override
Resize the window.
void PopulateSystemSprites() override
Populate all sprites in cache.
void ClearSystemSprites() override
Clear all cached sprites.
void Stop() override
Stop Cocoa video driver.
The Cocoa OpenGL video driver.
static FVideoDriver_CocoaOpenGL iFVideoDriver_CocoaOpenGL
Storage for instance of the FVideoDriver_CocoaOpenGL class.
static Palette _local_palette
Current palette to use for drawing.
static OGLProc GetOGLProcAddressCallback(const char *proc)
Platform-specific callback to get an OpenGL function pointer.
OS interface for the cocoa video driver.
bool _allow_hidpi_window
Storage for allow_hidpi setting. If true renders OTTD in native resolution.
bool GetDriverParamBool(const StringList &parm, std::string_view name)
Get a boolean parameter the list of parameters.
Dimension _cur_resolution
The current resolution.
@ PFE_VIDEO
Speed of painting drawn video buffer.
void GameSizeChanged()
Size of the application screen changed.
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
@ Stop
Go to the depot and stop there.
bool CopyPalette(Palette &local_palette, bool force_copy)
Copy the current palette if the palette was updated.
std::vector< std::string > StringList
Type for a list of strings.
Information about the currently used palette.
int first_dirty
The first dirty element.
int count_dirty
The number of dirty elements.
Colour palette[256]
Current palette. Entry 0 has to be always fully transparent!