Merge branch 'master' into jgrpp

# Conflicts:
#	src/dock_gui.cpp
#	src/rail_gui.cpp
#	src/road_gui.cpp
#	src/terraform_gui.cpp
#	src/vehicle.cpp
#	src/video/allegro_v.cpp
#	src/video/cocoa/cocoa_v.mm
#	src/video/dedicated_v.cpp
#	src/video/sdl2_v.cpp
#	src/video/sdl_v.cpp
#	src/video/win32_v.cpp
This commit is contained in:
Jonathan G Rennison
2021-02-21 11:49:54 +00:00
42 changed files with 885 additions and 1005 deletions

View File

@@ -32,10 +32,8 @@ private:
void *pixel_buffer; ///< used for direct pixel access
void *window_buffer; ///< Colour translation from palette to screen
static const int MAX_DIRTY_RECTS = 100;
Rect dirty_rect; ///< Region of the screen that needs redrawing.
Rect dirty_rects[MAX_DIRTY_RECTS]; ///< dirty rectangles
uint num_dirty_rects; ///< Number of dirty rectangles
uint32 palette[256]; ///< Colour Palette
public:
@@ -74,6 +72,9 @@ public:
protected:
Dimension GetScreenSize() const override;
float GetDPIScale() override;
void InputLoop() override;
void Paint() override;
void CheckPaletteAnim() override;
private:
bool PollEvent();
@@ -86,9 +87,7 @@ private:
bool MakeWindow(int width, int height);
void UpdatePalette(uint first_color, uint num_colors);
void CheckPaletteAnim();
void Draw(bool force_update = false);
void BlitIndexedToView32(int left, int top, int right, int bottom);
};

View File

@@ -21,12 +21,13 @@
#define Rect OTTDRect
#define Point OTTDPoint
#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>
#undef Rect
#undef Point
#include "../../openttd.h"
#include "../../debug.h"
#include "../../core/geometry_type.hpp"
#include "../../core/geometry_func.hpp"
#include "../../core/math_func.hpp"
#include "cocoa_v.h"
#include "cocoa_wnd.h"
@@ -125,7 +126,7 @@ VideoDriver_Cocoa::VideoDriver_Cocoa()
this->color_space = nullptr;
this->cgcontext = nullptr;
this->num_dirty_rects = lengthof(this->dirty_rects);
this->dirty_rect = {};
}
/** Stop Cocoa video driver. */
@@ -192,13 +193,8 @@ const char *VideoDriver_Cocoa::Start(const StringList &parm)
*/
void VideoDriver_Cocoa::MakeDirty(int left, int top, int width, int height)
{
if (this->num_dirty_rects < lengthof(this->dirty_rects)) {
dirty_rects[this->num_dirty_rects].left = left;
dirty_rects[this->num_dirty_rects].top = top;
dirty_rects[this->num_dirty_rects].right = left + width;
dirty_rects[this->num_dirty_rects].bottom = top + height;
}
this->num_dirty_rects++;
Rect r = {left, top, left + width, top + height};
this->dirty_rect = BoundingRect(this->dirty_rect, r);
}
/**
@@ -465,49 +461,39 @@ void VideoDriver_Cocoa::BlitIndexedToView32(int left, int top, int right, int bo
}
/**
* Draw window.
* Paint window.
* @param force_update Whether to redraw unconditionally
*/
void VideoDriver_Cocoa::Draw(bool force_update)
void VideoDriver_Cocoa::Paint()
{
PerformanceMeasurer framerate(PFE_VIDEO);
/* Check if we need to do anything */
if (this->num_dirty_rects == 0 || [ this->window isMiniaturized ]) return;
if (IsEmptyRect(this->dirty_rect) || [ this->window isMiniaturized ]) return;
if (this->num_dirty_rects >= lengthof(this->dirty_rects)) {
this->num_dirty_rects = 1;
this->dirty_rects[0].left = 0;
this->dirty_rects[0].top = 0;
this->dirty_rects[0].right = this->window_width;
this->dirty_rects[0].bottom = this->window_height;
/* We only need to blit in indexed mode since in 32bpp mode the game draws directly to the image. */
if (this->buffer_depth == 8) {
BlitIndexedToView32(
this->dirty_rect.left,
this->dirty_rect.top,
this->dirty_rect.right,
this->dirty_rect.bottom
);
}
/* Build the region of dirty rectangles */
for (uint i = 0; i < this->num_dirty_rects; i++) {
/* We only need to blit in indexed mode since in 32bpp mode the game draws directly to the image. */
if (this->buffer_depth == 8) {
BlitIndexedToView32(
this->dirty_rects[i].left,
this->dirty_rects[i].top,
this->dirty_rects[i].right,
this->dirty_rects[i].bottom
);
}
NSRect dirtyrect;
dirtyrect.origin.x = this->dirty_rect.left;
dirtyrect.origin.y = this->window_height - this->dirty_rect.bottom;
dirtyrect.size.width = this->dirty_rect.right - this->dirty_rect.left;
dirtyrect.size.height = this->dirty_rect.bottom - this->dirty_rect.top;
NSRect dirtyrect;
dirtyrect.origin.x = this->dirty_rects[i].left;
dirtyrect.origin.y = this->window_height - this->dirty_rects[i].bottom;
dirtyrect.size.width = this->dirty_rects[i].right - this->dirty_rects[i].left;
dirtyrect.size.height = this->dirty_rects[i].bottom - this->dirty_rects[i].top;
/* Notify OS X that we have new content to show. */
[ this->cocoaview setNeedsDisplayInRect:[ this->cocoaview getVirtualRect:dirtyrect ] ];
/* Normally drawRect will be automatically called by Mac OS X during next update cycle,
* and then blitting will occur. If force_update is true, it will be done right now. */
[ this->cocoaview setNeedsDisplayInRect:[ this->cocoaview getVirtualRect:dirtyrect ] ];
if (force_update) [ this->cocoaview displayIfNeeded ];
}
/* Tell the OS to get our contents to screen as soon as possible. */
[ CATransaction flush ];
this->num_dirty_rects = 0;
this->dirty_rect = {};
}
/** Update the palette. */
@@ -523,7 +509,7 @@ void VideoDriver_Cocoa::UpdatePalette(uint first_color, uint num_colors)
this->palette[i] = clr;
}
this->num_dirty_rects = lengthof(this->dirty_rects);
this->MakeDirty(0, 0, _screen.width, _screen.height);
}
/** Clear buffer to opaque black. */
@@ -581,8 +567,8 @@ void VideoDriver_Cocoa::AllocateBackingStore()
}
/* Redraw screen */
this->num_dirty_rects = lengthof(this->dirty_rects);
this->GameSizeChanged();
this->MakeDirty(0, 0, _screen.width, _screen.height);
}
/** Check if palette updates need to be performed. */
@@ -632,14 +618,33 @@ bool VideoDriver_Cocoa::PollEvent()
return true;
}
void VideoDriver_Cocoa::InputLoop()
{
NSUInteger cur_mods = [ NSEvent modifierFlags ];
bool old_ctrl_pressed = _ctrl_pressed;
bool old_shift_pressed = _shift_pressed;
_ctrl_pressed = ((cur_mods & ( _settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask)) != 0) != _invert_ctrl;
_shift_pressed = ((cur_mods & NSShiftKeyMask) != 0) != _invert_shift;
#if defined(_DEBUG)
if (_shift_pressed) {
#else
if (_tab_is_down) {
#endif
if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
} else if (_fast_forward & 2) {
_fast_forward = 0;
}
if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
if (old_shift_pressed != _shift_pressed) HandleShiftChanged();
}
/** Main game loop. */
void VideoDriver_Cocoa::GameLoop()
{
auto cur_ticks = std::chrono::steady_clock::now();
auto last_realtime_tick = cur_ticks;
auto next_game_tick = cur_ticks;
auto next_draw_tick = cur_ticks;
for (;;) {
@autoreleasepool {
@@ -653,69 +658,10 @@ void VideoDriver_Cocoa::GameLoop()
break;
}
NSUInteger cur_mods = [ NSEvent modifierFlags ];
#if defined(_DEBUG)
if (cur_mods & NSShiftKeyMask) {
#else
if (_tab_is_down) {
#endif
if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
} else if (_fast_forward & 2) {
_fast_forward = 0;
}
cur_ticks = std::chrono::steady_clock::now();
/* If more than a millisecond has passed, increase the _realtime_tick. */
if (cur_ticks - last_realtime_tick > std::chrono::milliseconds(1)) {
auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(cur_ticks - last_realtime_tick);
IncreaseRealtimeTick(delta.count());
last_realtime_tick += delta;
}
if (cur_ticks >= next_game_tick || (_fast_forward && !_pause_mode)) {
if (_fast_forward && !_pause_mode) {
next_game_tick = cur_ticks + this->GetGameInterval();
} else {
next_game_tick += this->GetGameInterval();
/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
if (next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) next_game_tick = cur_ticks;
}
::GameLoop();
}
/* Prevent drawing when switching mode, as windows can be removed when they should still appear. */
if (cur_ticks >= next_draw_tick && (_switch_mode == SM_NONE || HasModalProgress())) {
next_draw_tick += this->GetDrawInterval();
/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;
bool old_ctrl_pressed = _ctrl_pressed;
_ctrl_pressed = (cur_mods & ( _settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask)) != 0;
_shift_pressed = (cur_mods & NSShiftKeyMask) != 0;
if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
InputLoop();
UpdateWindows();
this->CheckPaletteAnim();
this->Draw();
}
/* If we are not in fast-forward, create some time between calls to ease up CPU usage. */
if (!_fast_forward || _pause_mode) {
/* See how much time there is till we have to process the next event, and try to hit that as close as possible. */
auto next_tick = std::min(next_draw_tick, next_game_tick);
auto now = std::chrono::steady_clock::now();
if (next_tick > now) {
std::this_thread::sleep_for(next_tick - now);
}
if (this->Tick()) {
this->Paint();
}
this->SleepTillNextTick();
}
}
}
@@ -733,6 +679,7 @@ void VideoDriver_Cocoa::GameLoop()
self.wantsLayer = YES;
self.layer.magnificationFilter = kCAFilterNearest;
self.layer.opaque = YES;
}
return self;
}