Merge commit '6c536afdb7bdc9cece4152c7e1f9a18306976b46' into main
commit
48f2d2f832
|
@ -824,7 +824,10 @@ prepare_audioqueue(_THIS)
|
||||||
const AudioStreamBasicDescription *strdesc = &this->hidden->strdesc;
|
const AudioStreamBasicDescription *strdesc = &this->hidden->strdesc;
|
||||||
const int iscapture = this->iscapture;
|
const int iscapture = this->iscapture;
|
||||||
OSStatus result;
|
OSStatus result;
|
||||||
int i;
|
int i, numAudioBuffers = 2;
|
||||||
|
AudioChannelLayout layout;
|
||||||
|
double MINIMUM_AUDIO_BUFFER_TIME_MS;
|
||||||
|
const double msecs = (this->spec.samples / ((double) this->spec.freq)) * 1000.0;;
|
||||||
|
|
||||||
SDL_assert(CFRunLoopGetCurrent() != NULL);
|
SDL_assert(CFRunLoopGetCurrent() != NULL);
|
||||||
|
|
||||||
|
@ -856,7 +859,6 @@ prepare_audioqueue(_THIS)
|
||||||
SDL_CalculateAudioSpec(&this->spec);
|
SDL_CalculateAudioSpec(&this->spec);
|
||||||
|
|
||||||
/* Set the channel layout for the audio queue */
|
/* Set the channel layout for the audio queue */
|
||||||
AudioChannelLayout layout;
|
|
||||||
SDL_zero(layout);
|
SDL_zero(layout);
|
||||||
switch (this->spec.channels) {
|
switch (this->spec.channels) {
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -901,15 +903,13 @@ prepare_audioqueue(_THIS)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure we can feed the device a minimum amount of time */
|
/* Make sure we can feed the device a minimum amount of time */
|
||||||
double MINIMUM_AUDIO_BUFFER_TIME_MS = 15.0;
|
MINIMUM_AUDIO_BUFFER_TIME_MS = 15.0;
|
||||||
#if defined(__IPHONEOS__)
|
#if defined(__IPHONEOS__)
|
||||||
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
|
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
|
||||||
/* Older iOS hardware, use 40 ms as a minimum time */
|
/* Older iOS hardware, use 40 ms as a minimum time */
|
||||||
MINIMUM_AUDIO_BUFFER_TIME_MS = 40.0;
|
MINIMUM_AUDIO_BUFFER_TIME_MS = 40.0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
const double msecs = (this->spec.samples / ((double) this->spec.freq)) * 1000.0;
|
|
||||||
int numAudioBuffers = 2;
|
|
||||||
if (msecs < MINIMUM_AUDIO_BUFFER_TIME_MS) { /* use more buffers if we have a VERY small sample set. */
|
if (msecs < MINIMUM_AUDIO_BUFFER_TIME_MS) { /* use more buffers if we have a VERY small sample set. */
|
||||||
numAudioBuffers = ((int)SDL_ceil(MINIMUM_AUDIO_BUFFER_TIME_MS / msecs) * 2);
|
numAudioBuffers = ((int)SDL_ceil(MINIMUM_AUDIO_BUFFER_TIME_MS / msecs) * 2);
|
||||||
}
|
}
|
||||||
|
@ -946,6 +946,7 @@ static int
|
||||||
audioqueue_thread(void *arg)
|
audioqueue_thread(void *arg)
|
||||||
{
|
{
|
||||||
SDL_AudioDevice *this = (SDL_AudioDevice *) arg;
|
SDL_AudioDevice *this = (SDL_AudioDevice *) arg;
|
||||||
|
int rc;
|
||||||
|
|
||||||
#if MACOSX_COREAUDIO
|
#if MACOSX_COREAUDIO
|
||||||
const AudioObjectPropertyAddress default_device_address = {
|
const AudioObjectPropertyAddress default_device_address = {
|
||||||
|
@ -960,7 +961,7 @@ audioqueue_thread(void *arg)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const int rc = prepare_audioqueue(this);
|
rc = prepare_audioqueue(this);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
this->hidden->thread_error = SDL_strdup(SDL_GetError());
|
this->hidden->thread_error = SDL_strdup(SDL_GetError());
|
||||||
SDL_SemPost(this->hidden->ready_semaphore);
|
SDL_SemPost(this->hidden->ready_semaphore);
|
||||||
|
@ -977,6 +978,7 @@ audioqueue_thread(void *arg)
|
||||||
|
|
||||||
#if MACOSX_COREAUDIO
|
#if MACOSX_COREAUDIO
|
||||||
if ((this->handle == NULL) && SDL_AtomicGet(&this->hidden->device_change_flag)) {
|
if ((this->handle == NULL) && SDL_AtomicGet(&this->hidden->device_change_flag)) {
|
||||||
|
const AudioDeviceID prev_devid = this->hidden->deviceID;
|
||||||
SDL_AtomicSet(&this->hidden->device_change_flag, 0);
|
SDL_AtomicSet(&this->hidden->device_change_flag, 0);
|
||||||
|
|
||||||
#if DEBUG_COREAUDIO
|
#if DEBUG_COREAUDIO
|
||||||
|
@ -986,7 +988,6 @@ audioqueue_thread(void *arg)
|
||||||
/* if any of this fails, there's not much to do but wait to see if the user gives up
|
/* if any of this fails, there's not much to do but wait to see if the user gives up
|
||||||
and quits (flagging the audioqueue for shutdown), or toggles to some other system
|
and quits (flagging the audioqueue for shutdown), or toggles to some other system
|
||||||
output device (in which case we'll try again). */
|
output device (in which case we'll try again). */
|
||||||
const AudioDeviceID prev_devid = this->hidden->deviceID;
|
|
||||||
if (prepare_device(this) && (prev_devid != this->hidden->deviceID)) {
|
if (prepare_device(this) && (prev_devid != this->hidden->deviceID)) {
|
||||||
AudioQueueStop(this->hidden->audioQueue, 1);
|
AudioQueueStop(this->hidden->audioQueue, 1);
|
||||||
if (assign_device_to_audioqueue(this)) {
|
if (assign_device_to_audioqueue(this)) {
|
||||||
|
|
|
@ -36,18 +36,22 @@ FILE* SDL_OpenFPFromBundleOrFallback(const char *file, const char *mode)
|
||||||
{ @autoreleasepool
|
{ @autoreleasepool
|
||||||
{
|
{
|
||||||
FILE* fp = NULL;
|
FILE* fp = NULL;
|
||||||
|
NSFileManager* file_manager;
|
||||||
|
NSString* resource_path;
|
||||||
|
NSString* ns_string_file_component;
|
||||||
|
NSString* full_path_with_file_to_try;
|
||||||
|
|
||||||
/* If the file mode is writable, skip all the bundle stuff because generally the bundle is read-only. */
|
/* If the file mode is writable, skip all the bundle stuff because generally the bundle is read-only. */
|
||||||
if(strcmp("r", mode) && strcmp("rb", mode)) {
|
if(strcmp("r", mode) && strcmp("rb", mode)) {
|
||||||
return fopen(file, mode);
|
return fopen(file, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
NSFileManager* file_manager = [NSFileManager defaultManager];
|
file_manager = [NSFileManager defaultManager];
|
||||||
NSString* resource_path = [[NSBundle mainBundle] resourcePath];
|
resource_path = [[NSBundle mainBundle] resourcePath];
|
||||||
|
|
||||||
NSString* ns_string_file_component = [file_manager stringWithFileSystemRepresentation:file length:strlen(file)];
|
ns_string_file_component = [file_manager stringWithFileSystemRepresentation:file length:strlen(file)];
|
||||||
|
|
||||||
NSString* full_path_with_file_to_try = [resource_path stringByAppendingPathComponent:ns_string_file_component];
|
full_path_with_file_to_try = [resource_path stringByAppendingPathComponent:ns_string_file_component];
|
||||||
if([file_manager fileExistsAtPath:full_path_with_file_to_try]) {
|
if([file_manager fileExistsAtPath:full_path_with_file_to_try]) {
|
||||||
fp = fopen([full_path_with_file_to_try fileSystemRepresentation], mode);
|
fp = fopen([full_path_with_file_to_try fileSystemRepresentation], mode);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -71,6 +71,10 @@ char *
|
||||||
SDL_GetPrefPath(const char *org, const char *app)
|
SDL_GetPrefPath(const char *org, const char *app)
|
||||||
{ @autoreleasepool
|
{ @autoreleasepool
|
||||||
{
|
{
|
||||||
|
char *retval = NULL;
|
||||||
|
static SDL_bool shown = SDL_FALSE;
|
||||||
|
NSArray *array;
|
||||||
|
|
||||||
if (!app) {
|
if (!app) {
|
||||||
SDL_InvalidParamError("app");
|
SDL_InvalidParamError("app");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -79,9 +83,8 @@ SDL_GetPrefPath(const char *org, const char *app)
|
||||||
org = "";
|
org = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
char *retval = NULL;
|
|
||||||
#if !TARGET_OS_TV
|
#if !TARGET_OS_TV
|
||||||
NSArray *array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
|
array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
|
||||||
#else
|
#else
|
||||||
/* tvOS does not have persistent local storage!
|
/* tvOS does not have persistent local storage!
|
||||||
* The only place on-device where we can store data is
|
* The only place on-device where we can store data is
|
||||||
|
@ -91,15 +94,13 @@ SDL_GetPrefPath(const char *org, const char *app)
|
||||||
* between sessions. If you want your app's save data to
|
* between sessions. If you want your app's save data to
|
||||||
* actually stick around, you'll need to use iCloud storage.
|
* actually stick around, you'll need to use iCloud storage.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static SDL_bool shown = SDL_FALSE;
|
|
||||||
if (!shown)
|
if (!shown)
|
||||||
{
|
{
|
||||||
shown = SDL_TRUE;
|
shown = SDL_TRUE;
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "tvOS does not have persistent local storage! Use iCloud storage if you want your data to persist between sessions.\n");
|
SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "tvOS does not have persistent local storage! Use iCloud storage if you want your data to persist between sessions.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
NSArray *array = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
array = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||||
#endif /* !TARGET_OS_TV */
|
#endif /* !TARGET_OS_TV */
|
||||||
|
|
||||||
if ([array count] > 0) { /* we only want the first item in the list. */
|
if ([array count] > 0) { /* we only want the first item in the list. */
|
||||||
|
|
|
@ -156,11 +156,12 @@ static hid_device *new_hid_device(void)
|
||||||
|
|
||||||
static void free_hid_device(hid_device *dev)
|
static void free_hid_device(hid_device *dev)
|
||||||
{
|
{
|
||||||
|
struct input_report *rpt;
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Delete any input reports still left over. */
|
/* Delete any input reports still left over. */
|
||||||
struct input_report *rpt = dev->input_reports;
|
rpt = dev->input_reports;
|
||||||
while (rpt) {
|
while (rpt) {
|
||||||
struct input_report *next = rpt->next;
|
struct input_report *next = rpt->next;
|
||||||
free(rpt->data);
|
free(rpt->data);
|
||||||
|
@ -260,14 +261,12 @@ static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t
|
||||||
buf[0] = 0;
|
buf[0] = 0;
|
||||||
|
|
||||||
if (str && CFGetTypeID(str) == CFStringGetTypeID()) {
|
if (str && CFGetTypeID(str) == CFStringGetTypeID()) {
|
||||||
len --;
|
CFIndex used_buf_len, chars_copied;
|
||||||
|
|
||||||
CFIndex str_len = CFStringGetLength(str);
|
|
||||||
CFRange range;
|
CFRange range;
|
||||||
|
CFIndex str_len = CFStringGetLength(str);
|
||||||
|
len --;
|
||||||
range.location = 0;
|
range.location = 0;
|
||||||
range.length = (str_len > len)? len: str_len;
|
range.length = (str_len > len)? len: str_len;
|
||||||
CFIndex used_buf_len;
|
|
||||||
CFIndex chars_copied;
|
|
||||||
chars_copied = CFStringGetBytes(str,
|
chars_copied = CFStringGetBytes(str,
|
||||||
range,
|
range,
|
||||||
kCFStringEncodingUTF32LE,
|
kCFStringEncodingUTF32LE,
|
||||||
|
@ -299,14 +298,12 @@ static int get_string_property_utf8(IOHIDDeviceRef device, CFStringRef prop, cha
|
||||||
buf[0] = 0;
|
buf[0] = 0;
|
||||||
|
|
||||||
if (str && CFGetTypeID(str) == CFStringGetTypeID()) {
|
if (str && CFGetTypeID(str) == CFStringGetTypeID()) {
|
||||||
len--;
|
CFIndex used_buf_len, chars_copied;
|
||||||
|
|
||||||
CFIndex str_len = CFStringGetLength(str);
|
|
||||||
CFRange range;
|
CFRange range;
|
||||||
|
CFIndex str_len = CFStringGetLength(str);
|
||||||
|
len--;
|
||||||
range.location = 0;
|
range.location = 0;
|
||||||
range.length = (str_len > len)? len: str_len;
|
range.length = (str_len > len)? len: str_len;
|
||||||
CFIndex used_buf_len;
|
|
||||||
CFIndex chars_copied;
|
|
||||||
chars_copied = CFStringGetBytes(str,
|
chars_copied = CFStringGetBytes(str,
|
||||||
range,
|
range,
|
||||||
kCFStringEncodingUTF8,
|
kCFStringEncodingUTF8,
|
||||||
|
@ -517,6 +514,8 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
||||||
struct hid_device_info *root = NULL; // return object
|
struct hid_device_info *root = NULL; // return object
|
||||||
struct hid_device_info *cur_dev = NULL;
|
struct hid_device_info *cur_dev = NULL;
|
||||||
CFIndex num_devices;
|
CFIndex num_devices;
|
||||||
|
CFSetRef device_set;
|
||||||
|
IOHIDDeviceRef *device_array;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Set up the HID Manager if it hasn't been done */
|
/* Set up the HID Manager if it hasn't been done */
|
||||||
|
@ -527,7 +526,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
||||||
process_pending_events();
|
process_pending_events();
|
||||||
|
|
||||||
/* Get a list of the Devices */
|
/* Get a list of the Devices */
|
||||||
CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
|
device_set = IOHIDManagerCopyDevices(hid_mgr);
|
||||||
if (!device_set)
|
if (!device_set)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -537,7 +536,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
||||||
CFRelease(device_set);
|
CFRelease(device_set);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
IOHIDDeviceRef *device_array = (IOHIDDeviceRef*)calloc(num_devices, sizeof(IOHIDDeviceRef));
|
device_array = (IOHIDDeviceRef*)calloc(num_devices, sizeof(IOHIDDeviceRef));
|
||||||
CFSetGetValues(device_set, (const void **) device_array);
|
CFSetGetValues(device_set, (const void **) device_array);
|
||||||
|
|
||||||
/* Iterate over each device, making an entry for it. */
|
/* Iterate over each device, making an entry for it. */
|
||||||
|
@ -733,13 +732,14 @@ static void perform_signal_callback(void *context)
|
||||||
static void *read_thread(void *param)
|
static void *read_thread(void *param)
|
||||||
{
|
{
|
||||||
hid_device *dev = (hid_device *)param;
|
hid_device *dev = (hid_device *)param;
|
||||||
|
CFRunLoopSourceContext ctx;
|
||||||
|
SInt32 code;
|
||||||
|
|
||||||
/* Move the device's run loop to this thread. */
|
/* Move the device's run loop to this thread. */
|
||||||
IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode);
|
IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode);
|
||||||
|
|
||||||
/* Create the RunLoopSource which is used to signal the
|
/* Create the RunLoopSource which is used to signal the
|
||||||
event loop to stop when hid_close() is called. */
|
event loop to stop when hid_close() is called. */
|
||||||
CFRunLoopSourceContext ctx;
|
|
||||||
memset(&ctx, 0, sizeof(ctx));
|
memset(&ctx, 0, sizeof(ctx));
|
||||||
ctx.version = 0;
|
ctx.version = 0;
|
||||||
ctx.info = dev;
|
ctx.info = dev;
|
||||||
|
@ -756,7 +756,6 @@ static void *read_thread(void *param)
|
||||||
|
|
||||||
/* Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input
|
/* Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input
|
||||||
reports into the hid_report_callback(). */
|
reports into the hid_report_callback(). */
|
||||||
SInt32 code;
|
|
||||||
while (!dev->shutdown_thread && !dev->disconnected) {
|
while (!dev->shutdown_thread && !dev->disconnected) {
|
||||||
code = CFRunLoopRunInMode(dev->run_loop_mode, 1000/*sec*/, FALSE);
|
code = CFRunLoopRunInMode(dev->run_loop_mode, 1000/*sec*/, FALSE);
|
||||||
/* Return if the device has been disconnected */
|
/* Return if the device has been disconnected */
|
||||||
|
@ -796,9 +795,11 @@ static void *read_thread(void *param)
|
||||||
|
|
||||||
hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
|
hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
hid_device *dev = NULL;
|
hid_device *dev = NULL;
|
||||||
CFIndex num_devices;
|
CFIndex num_devices;
|
||||||
|
CFSetRef device_set;
|
||||||
|
IOHIDDeviceRef *device_array;
|
||||||
|
|
||||||
dev = new_hid_device();
|
dev = new_hid_device();
|
||||||
|
|
||||||
|
@ -809,10 +810,10 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
|
||||||
/* give the IOHIDManager a chance to update itself */
|
/* give the IOHIDManager a chance to update itself */
|
||||||
process_pending_events();
|
process_pending_events();
|
||||||
|
|
||||||
CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
|
device_set = IOHIDManagerCopyDevices(hid_mgr);
|
||||||
|
|
||||||
num_devices = CFSetGetCount(device_set);
|
num_devices = CFSetGetCount(device_set);
|
||||||
IOHIDDeviceRef *device_array = (IOHIDDeviceRef *)calloc(num_devices, sizeof(IOHIDDeviceRef));
|
device_array = (IOHIDDeviceRef *)calloc(num_devices, sizeof(IOHIDDeviceRef));
|
||||||
CFSetGetValues(device_set, (const void **) device_array);
|
CFSetGetValues(device_set, (const void **) device_array);
|
||||||
for (i = 0; i < num_devices; i++) {
|
for (i = 0; i < num_devices; i++) {
|
||||||
char cbuf[BUF_LEN];
|
char cbuf[BUF_LEN];
|
||||||
|
@ -824,6 +825,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
|
||||||
IOReturn ret = IOHIDDeviceOpen(os_dev, kIOHIDOptionsTypeNone);
|
IOReturn ret = IOHIDDeviceOpen(os_dev, kIOHIDOptionsTypeNone);
|
||||||
if (ret == kIOReturnSuccess) {
|
if (ret == kIOReturnSuccess) {
|
||||||
char str[32];
|
char str[32];
|
||||||
|
struct hid_device_list_node *node;
|
||||||
|
|
||||||
free(device_array);
|
free(device_array);
|
||||||
CFRelease(device_set);
|
CFRelease(device_set);
|
||||||
|
@ -845,7 +847,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
|
||||||
os_dev, dev->input_report_buf, dev->max_input_report_len,
|
os_dev, dev->input_report_buf, dev->max_input_report_len,
|
||||||
&hid_report_callback, dev);
|
&hid_report_callback, dev);
|
||||||
|
|
||||||
struct hid_device_list_node *node = (struct hid_device_list_node *)calloc(1, sizeof(struct hid_device_list_node));
|
node = (struct hid_device_list_node *)calloc(1, sizeof(struct hid_device_list_node));
|
||||||
node->dev = dev;
|
node->dev = dev;
|
||||||
node->next = device_list;
|
node->next = device_list;
|
||||||
device_list = node;
|
device_list = node;
|
||||||
|
@ -1083,13 +1085,13 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data,
|
||||||
{
|
{
|
||||||
CFIndex len = length;
|
CFIndex len = length;
|
||||||
IOReturn res;
|
IOReturn res;
|
||||||
|
int skipped_report_id = 0, report_number;
|
||||||
|
|
||||||
/* Return if the device has been unplugged. */
|
/* Return if the device has been unplugged. */
|
||||||
if (dev->disconnected)
|
if (dev->disconnected)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int skipped_report_id = 0;
|
report_number = data[0];
|
||||||
int report_number = data[0];
|
|
||||||
if (report_number == 0x0) {
|
if (report_number == 0x0) {
|
||||||
/* Offset the return buffer by 1, so that the report ID
|
/* Offset the return buffer by 1, so that the report ID
|
||||||
will remain in byte 0. */
|
will remain in byte 0. */
|
||||||
|
|
|
@ -985,7 +985,7 @@ DARWIN_JoystickUpdate(SDL_Joystick *joystick)
|
||||||
recDevice *device = joystick->hwdata;
|
recDevice *device = joystick->hwdata;
|
||||||
recElement *element;
|
recElement *element;
|
||||||
SInt32 value, range;
|
SInt32 value, range;
|
||||||
int i;
|
int i, goodRead = SDL_FALSE;
|
||||||
|
|
||||||
if (!device) {
|
if (!device) {
|
||||||
return;
|
return;
|
||||||
|
@ -1001,7 +1001,6 @@ DARWIN_JoystickUpdate(SDL_Joystick *joystick)
|
||||||
element = device->firstAxis;
|
element = device->firstAxis;
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
int goodRead = SDL_FALSE;
|
|
||||||
while (element) {
|
while (element) {
|
||||||
goodRead = GetHIDScaledCalibratedState(device, element, -32768, 32767, &value);
|
goodRead = GetHIDScaledCalibratedState(device, element, -32768, 32767, &value);
|
||||||
if (goodRead) {
|
if (goodRead) {
|
||||||
|
|
|
@ -180,16 +180,16 @@ IsControllerXbox(GCController *controller)
|
||||||
static BOOL
|
static BOOL
|
||||||
IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controller)
|
IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controller)
|
||||||
{
|
{
|
||||||
if ((@available(macOS 11.3, *)) && !GCController.shouldMonitorBackgroundEvents) {
|
|
||||||
GCController.shouldMonitorBackgroundEvents = YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
Uint16 *guid16 = (Uint16 *)device->guid.data;
|
Uint16 *guid16 = (Uint16 *)device->guid.data;
|
||||||
Uint16 vendor = 0;
|
Uint16 vendor = 0;
|
||||||
Uint16 product = 0;
|
Uint16 product = 0;
|
||||||
Uint8 subtype = 0;
|
Uint8 subtype = 0;
|
||||||
|
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
|
|
||||||
|
if ((@available(macOS 11.3, *)) && !GCController.shouldMonitorBackgroundEvents) {
|
||||||
|
GCController.shouldMonitorBackgroundEvents = YES;
|
||||||
|
}
|
||||||
|
|
||||||
/* Explicitly retain the controller because SDL_JoystickDeviceItem is a
|
/* Explicitly retain the controller because SDL_JoystickDeviceItem is a
|
||||||
* struct, and ARC doesn't work with structs. */
|
* struct, and ARC doesn't work with structs. */
|
||||||
device->controller = (__bridge GCController *) CFBridgingRetain(controller);
|
device->controller = (__bridge GCController *) CFBridgingRetain(controller);
|
||||||
|
@ -213,6 +213,7 @@ IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controlle
|
||||||
BOOL is_MFi = (!is_xbox && !is_ps4 && !is_ps5);
|
BOOL is_MFi = (!is_xbox && !is_ps4 && !is_ps5);
|
||||||
#endif
|
#endif
|
||||||
int nbuttons = 0;
|
int nbuttons = 0;
|
||||||
|
BOOL has_direct_menu;
|
||||||
|
|
||||||
#ifdef SDL_JOYSTICK_HIDAPI
|
#ifdef SDL_JOYSTICK_HIDAPI
|
||||||
if ((is_xbox && HIDAPI_IsDeviceTypePresent(SDL_CONTROLLER_TYPE_XBOXONE)) ||
|
if ((is_xbox && HIDAPI_IsDeviceTypePresent(SDL_CONTROLLER_TYPE_XBOXONE)) ||
|
||||||
|
@ -251,7 +252,7 @@ IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controlle
|
||||||
device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_GUIDE);
|
device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_GUIDE);
|
||||||
++nbuttons;
|
++nbuttons;
|
||||||
}
|
}
|
||||||
BOOL has_direct_menu = [gamepad respondsToSelector:@selector(buttonMenu)] && gamepad.buttonMenu;
|
has_direct_menu = [gamepad respondsToSelector:@selector(buttonMenu)] && gamepad.buttonMenu;
|
||||||
#if TARGET_OS_TV
|
#if TARGET_OS_TV
|
||||||
/* On tvOS MFi controller menu button brings you to the home screen */
|
/* On tvOS MFi controller menu button brings you to the home screen */
|
||||||
if (is_MFi) {
|
if (is_MFi) {
|
||||||
|
@ -575,6 +576,7 @@ IOS_JoystickInit(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
NSNotificationCenter *center;
|
||||||
#ifdef SDL_JOYSTICK_iOS_ACCELEROMETER
|
#ifdef SDL_JOYSTICK_iOS_ACCELEROMETER
|
||||||
if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_TRUE)) {
|
if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_TRUE)) {
|
||||||
/* Default behavior, accelerometer as joystick */
|
/* Default behavior, accelerometer as joystick */
|
||||||
|
@ -599,7 +601,7 @@ IOS_JoystickInit(void)
|
||||||
SDL_AppleTVRemoteRotationHintChanged, NULL);
|
SDL_AppleTVRemoteRotationHintChanged, NULL);
|
||||||
#endif /* TARGET_OS_TV */
|
#endif /* TARGET_OS_TV */
|
||||||
|
|
||||||
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
center = [NSNotificationCenter defaultCenter];
|
||||||
|
|
||||||
connectObserver = [center addObserverForName:GCControllerDidConnectNotification
|
connectObserver = [center addObserverForName:GCControllerDidConnectNotification
|
||||||
object:nil
|
object:nil
|
||||||
|
@ -907,9 +909,8 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
|
||||||
|
|
||||||
#ifdef ENABLE_PHYSICAL_INPUT_PROFILE
|
#ifdef ENABLE_PHYSICAL_INPUT_PROFILE
|
||||||
if (joystick->hwdata->has_dualshock_touchpad) {
|
if (joystick->hwdata->has_dualshock_touchpad) {
|
||||||
buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputDualShockTouchpadButton].isPressed;
|
|
||||||
|
|
||||||
GCControllerDirectionPad *dpad;
|
GCControllerDirectionPad *dpad;
|
||||||
|
buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputDualShockTouchpadButton].isPressed;
|
||||||
|
|
||||||
dpad = controller.physicalInputProfile.dpads[GCInputDualShockTouchpadOne];
|
dpad = controller.physicalInputProfile.dpads[GCInputDualShockTouchpadOne];
|
||||||
if (dpad.xAxis.value || dpad.yAxis.value) {
|
if (dpad.xAxis.value || dpad.yAxis.value) {
|
||||||
|
@ -1129,6 +1130,7 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
|
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
|
CHHapticDynamicParameter *param;
|
||||||
|
|
||||||
if (self.engine == nil) {
|
if (self.engine == nil) {
|
||||||
return SDL_SetError("Haptics engine was stopped");
|
return SDL_SetError("Haptics engine was stopped");
|
||||||
|
@ -1143,8 +1145,8 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.player == nil) {
|
if (self.player == nil) {
|
||||||
CHHapticEventParameter *param = [[CHHapticEventParameter alloc] initWithParameterID:CHHapticEventParameterIDHapticIntensity value:1.0f];
|
CHHapticEventParameter *event_param = [[CHHapticEventParameter alloc] initWithParameterID:CHHapticEventParameterIDHapticIntensity value:1.0f];
|
||||||
CHHapticEvent *event = [[CHHapticEvent alloc] initWithEventType:CHHapticEventTypeHapticContinuous parameters:[NSArray arrayWithObjects:param, nil] relativeTime:0 duration:GCHapticDurationInfinite];
|
CHHapticEvent *event = [[CHHapticEvent alloc] initWithEventType:CHHapticEventTypeHapticContinuous parameters:[NSArray arrayWithObjects:event_param, nil] relativeTime:0 duration:GCHapticDurationInfinite];
|
||||||
CHHapticPattern *pattern = [[CHHapticPattern alloc] initWithEvents:[NSArray arrayWithObject:event] parameters:[[NSArray alloc] init] error:&error];
|
CHHapticPattern *pattern = [[CHHapticPattern alloc] initWithEvents:[NSArray arrayWithObject:event] parameters:[[NSArray alloc] init] error:&error];
|
||||||
if (error != nil) {
|
if (error != nil) {
|
||||||
return SDL_SetError("Couldn't create haptic pattern: %s", [error.localizedDescription UTF8String]);
|
return SDL_SetError("Couldn't create haptic pattern: %s", [error.localizedDescription UTF8String]);
|
||||||
|
@ -1157,7 +1159,7 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
|
||||||
self.active = false;
|
self.active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CHHapticDynamicParameter *param = [[CHHapticDynamicParameter alloc] initWithParameterID:CHHapticDynamicParameterIDHapticIntensityControl value:intensity relativeTime:0];
|
param = [[CHHapticDynamicParameter alloc] initWithParameterID:CHHapticDynamicParameterIDHapticIntensityControl value:intensity relativeTime:0];
|
||||||
[self.player sendParameters:[NSArray arrayWithObject:param] atTime:0 error:&error];
|
[self.player sendParameters:[NSArray arrayWithObject:param] atTime:0 error:&error];
|
||||||
if (error != nil) {
|
if (error != nil) {
|
||||||
return SDL_SetError("Couldn't update haptic player: %s", [error.localizedDescription UTF8String]);
|
return SDL_SetError("Couldn't update haptic player: %s", [error.localizedDescription UTF8String]);
|
||||||
|
@ -1176,8 +1178,10 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
|
||||||
-(id) initWithController:(GCController*)controller locality:(GCHapticsLocality)locality API_AVAILABLE(macos(10.16), ios(14.0), tvos(14.0))
|
-(id) initWithController:(GCController*)controller locality:(GCHapticsLocality)locality API_AVAILABLE(macos(10.16), ios(14.0), tvos(14.0))
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
self = [super init];
|
|
||||||
NSError *error;
|
NSError *error;
|
||||||
|
__weak __typeof(self) weakSelf;
|
||||||
|
self = [super init];
|
||||||
|
weakSelf = self;
|
||||||
|
|
||||||
self.engine = [controller.haptics createEngineWithLocality:locality];
|
self.engine = [controller.haptics createEngineWithLocality:locality];
|
||||||
if (self.engine == nil) {
|
if (self.engine == nil) {
|
||||||
|
@ -1191,7 +1195,6 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
__weak __typeof(self) weakSelf = self;
|
|
||||||
self.engine.stoppedHandler = ^(CHHapticEngineStoppedReason stoppedReason) {
|
self.engine.stoppedHandler = ^(CHHapticEngineStoppedReason stoppedReason) {
|
||||||
SDL_RumbleMotor *_this = weakSelf;
|
SDL_RumbleMotor *_this = weakSelf;
|
||||||
if (_this == nil) {
|
if (_this == nil) {
|
||||||
|
|
|
@ -240,16 +240,24 @@ static id<MTLRenderPipelineState>
|
||||||
MakePipelineState(METAL_RenderData *data, METAL_PipelineCache *cache,
|
MakePipelineState(METAL_RenderData *data, METAL_PipelineCache *cache,
|
||||||
NSString *blendlabel, SDL_BlendMode blendmode)
|
NSString *blendlabel, SDL_BlendMode blendmode)
|
||||||
{
|
{
|
||||||
|
MTLRenderPipelineDescriptor *mtlpipedesc;
|
||||||
|
MTLVertexDescriptor *vertdesc;
|
||||||
|
MTLRenderPipelineColorAttachmentDescriptor *rtdesc;
|
||||||
|
NSError *err = nil;
|
||||||
|
id<MTLRenderPipelineState> state;
|
||||||
|
METAL_PipelineState pipeline;
|
||||||
|
METAL_PipelineState *states;
|
||||||
|
|
||||||
id<MTLFunction> mtlvertfn = [data.mtllibrary newFunctionWithName:GetVertexFunctionName(cache->vertexFunction)];
|
id<MTLFunction> mtlvertfn = [data.mtllibrary newFunctionWithName:GetVertexFunctionName(cache->vertexFunction)];
|
||||||
id<MTLFunction> mtlfragfn = [data.mtllibrary newFunctionWithName:GetFragmentFunctionName(cache->fragmentFunction)];
|
id<MTLFunction> mtlfragfn = [data.mtllibrary newFunctionWithName:GetFragmentFunctionName(cache->fragmentFunction)];
|
||||||
SDL_assert(mtlvertfn != nil);
|
SDL_assert(mtlvertfn != nil);
|
||||||
SDL_assert(mtlfragfn != nil);
|
SDL_assert(mtlfragfn != nil);
|
||||||
|
|
||||||
MTLRenderPipelineDescriptor *mtlpipedesc = [[MTLRenderPipelineDescriptor alloc] init];
|
mtlpipedesc = [[MTLRenderPipelineDescriptor alloc] init];
|
||||||
mtlpipedesc.vertexFunction = mtlvertfn;
|
mtlpipedesc.vertexFunction = mtlvertfn;
|
||||||
mtlpipedesc.fragmentFunction = mtlfragfn;
|
mtlpipedesc.fragmentFunction = mtlfragfn;
|
||||||
|
|
||||||
MTLVertexDescriptor *vertdesc = [MTLVertexDescriptor vertexDescriptor];
|
vertdesc = [MTLVertexDescriptor vertexDescriptor];
|
||||||
|
|
||||||
switch (cache->vertexFunction) {
|
switch (cache->vertexFunction) {
|
||||||
case SDL_METAL_VERTEX_SOLID:
|
case SDL_METAL_VERTEX_SOLID:
|
||||||
|
@ -287,7 +295,7 @@ MakePipelineState(METAL_RenderData *data, METAL_PipelineCache *cache,
|
||||||
|
|
||||||
mtlpipedesc.vertexDescriptor = vertdesc;
|
mtlpipedesc.vertexDescriptor = vertdesc;
|
||||||
|
|
||||||
MTLRenderPipelineColorAttachmentDescriptor *rtdesc = mtlpipedesc.colorAttachments[0];
|
rtdesc = mtlpipedesc.colorAttachments[0];
|
||||||
rtdesc.pixelFormat = cache->renderTargetFormat;
|
rtdesc.pixelFormat = cache->renderTargetFormat;
|
||||||
|
|
||||||
if (blendmode != SDL_BLENDMODE_NONE) {
|
if (blendmode != SDL_BLENDMODE_NONE) {
|
||||||
|
@ -304,15 +312,13 @@ MakePipelineState(METAL_RenderData *data, METAL_PipelineCache *cache,
|
||||||
|
|
||||||
mtlpipedesc.label = [@(cache->label) stringByAppendingString:blendlabel];
|
mtlpipedesc.label = [@(cache->label) stringByAppendingString:blendlabel];
|
||||||
|
|
||||||
NSError *err = nil;
|
state = [data.mtldevice newRenderPipelineStateWithDescriptor:mtlpipedesc error:&err];
|
||||||
id<MTLRenderPipelineState> state = [data.mtldevice newRenderPipelineStateWithDescriptor:mtlpipedesc error:&err];
|
|
||||||
SDL_assert(err == nil);
|
SDL_assert(err == nil);
|
||||||
|
|
||||||
METAL_PipelineState pipeline;
|
|
||||||
pipeline.blendMode = blendmode;
|
pipeline.blendMode = blendmode;
|
||||||
pipeline.pipe = (void *)CFBridgingRetain(state);
|
pipeline.pipe = (void *)CFBridgingRetain(state);
|
||||||
|
|
||||||
METAL_PipelineState *states = SDL_realloc(cache->states, (cache->count + 1) * sizeof(pipeline));
|
states = SDL_realloc(cache->states, (cache->count + 1) * sizeof(pipeline));
|
||||||
|
|
||||||
if (states) {
|
if (states) {
|
||||||
states[cache->count++] = pipeline;
|
states[cache->count++] = pipeline;
|
||||||
|
@ -542,6 +548,10 @@ METAL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
{ @autoreleasepool {
|
{ @autoreleasepool {
|
||||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||||
MTLPixelFormat pixfmt;
|
MTLPixelFormat pixfmt;
|
||||||
|
MTLTextureDescriptor *mtltexdesc;
|
||||||
|
id<MTLTexture> mtltexture, mtltexture_uv;
|
||||||
|
BOOL yuv, nv12;
|
||||||
|
METAL_TextureData *texturedata;
|
||||||
|
|
||||||
switch (texture->format) {
|
switch (texture->format) {
|
||||||
case SDL_PIXELFORMAT_ABGR8888:
|
case SDL_PIXELFORMAT_ABGR8888:
|
||||||
|
@ -560,7 +570,7 @@ METAL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
return SDL_SetError("Texture format %s not supported by Metal", SDL_GetPixelFormatName(texture->format));
|
return SDL_SetError("Texture format %s not supported by Metal", SDL_GetPixelFormatName(texture->format));
|
||||||
}
|
}
|
||||||
|
|
||||||
MTLTextureDescriptor *mtltexdesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pixfmt
|
mtltexdesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pixfmt
|
||||||
width:(NSUInteger)texture->w height:(NSUInteger)texture->h mipmapped:NO];
|
width:(NSUInteger)texture->w height:(NSUInteger)texture->h mipmapped:NO];
|
||||||
|
|
||||||
/* Not available in iOS 8. */
|
/* Not available in iOS 8. */
|
||||||
|
@ -572,15 +582,15 @@ METAL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLTexture> mtltexture = [data.mtldevice newTextureWithDescriptor:mtltexdesc];
|
mtltexture = [data.mtldevice newTextureWithDescriptor:mtltexdesc];
|
||||||
if (mtltexture == nil) {
|
if (mtltexture == nil) {
|
||||||
return SDL_SetError("Texture allocation failed");
|
return SDL_SetError("Texture allocation failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLTexture> mtltexture_uv = nil;
|
mtltexture_uv = nil;
|
||||||
#if SDL_HAVE_YUV
|
#if SDL_HAVE_YUV
|
||||||
BOOL yuv = (texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12);
|
yuv = (texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12);
|
||||||
BOOL nv12 = (texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21);
|
nv12 = (texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21);
|
||||||
|
|
||||||
if (yuv) {
|
if (yuv) {
|
||||||
mtltexdesc.pixelFormat = MTLPixelFormatR8Unorm;
|
mtltexdesc.pixelFormat = MTLPixelFormatR8Unorm;
|
||||||
|
@ -601,7 +611,7 @@ METAL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* SDL_HAVE_YUV */
|
#endif /* SDL_HAVE_YUV */
|
||||||
METAL_TextureData *texturedata = [[METAL_TextureData alloc] init];
|
texturedata = [[METAL_TextureData alloc] init];
|
||||||
if (texture->scaleMode == SDL_ScaleModeNearest) {
|
if (texture->scaleMode == SDL_ScaleModeNearest) {
|
||||||
texturedata.mtlsampler = data.mtlsamplernearest;
|
texturedata.mtlsampler = data.mtlsamplernearest;
|
||||||
} else {
|
} else {
|
||||||
|
@ -672,6 +682,8 @@ METAL_UpdateTextureInternal(SDL_Renderer * renderer, METAL_TextureData *textured
|
||||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||||
SDL_Rect stagingrect = {0, 0, rect.w, rect.h};
|
SDL_Rect stagingrect = {0, 0, rect.w, rect.h};
|
||||||
MTLTextureDescriptor *desc;
|
MTLTextureDescriptor *desc;
|
||||||
|
id<MTLTexture> stagingtex;
|
||||||
|
id<MTLBlitCommandEncoder> blitcmd;
|
||||||
|
|
||||||
/* If the texture is managed or shared and this is the first upload, we can
|
/* If the texture is managed or shared and this is the first upload, we can
|
||||||
* use replaceRegion to upload to it directly. Otherwise we upload the data
|
* use replaceRegion to upload to it directly. Otherwise we upload the data
|
||||||
|
@ -693,7 +705,7 @@ METAL_UpdateTextureInternal(SDL_Renderer * renderer, METAL_TextureData *textured
|
||||||
/* TODO: We could have a pool of textures or a MTLHeap we allocate from,
|
/* TODO: We could have a pool of textures or a MTLHeap we allocate from,
|
||||||
* and release a staging texture back to the pool in the command buffer's
|
* and release a staging texture back to the pool in the command buffer's
|
||||||
* completion handler. */
|
* completion handler. */
|
||||||
id<MTLTexture> stagingtex = [data.mtldevice newTextureWithDescriptor:desc];
|
stagingtex = [data.mtldevice newTextureWithDescriptor:desc];
|
||||||
if (stagingtex == nil) {
|
if (stagingtex == nil) {
|
||||||
return SDL_OutOfMemory();
|
return SDL_OutOfMemory();
|
||||||
}
|
}
|
||||||
|
@ -709,7 +721,7 @@ METAL_UpdateTextureInternal(SDL_Renderer * renderer, METAL_TextureData *textured
|
||||||
data.mtlcmdbuffer = [data.mtlcmdqueue commandBuffer];
|
data.mtlcmdbuffer = [data.mtlcmdqueue commandBuffer];
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLBlitCommandEncoder> blitcmd = [data.mtlcmdbuffer blitCommandEncoder];
|
blitcmd = [data.mtlcmdbuffer blitCommandEncoder];
|
||||||
|
|
||||||
[blitcmd copyFromTexture:stagingtex
|
[blitcmd copyFromTexture:stagingtex
|
||||||
sourceSlice:0
|
sourceSlice:0
|
||||||
|
@ -877,6 +889,7 @@ METAL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
{ @autoreleasepool {
|
{ @autoreleasepool {
|
||||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||||
METAL_TextureData *texturedata = (__bridge METAL_TextureData *)texture->driverdata;
|
METAL_TextureData *texturedata = (__bridge METAL_TextureData *)texture->driverdata;
|
||||||
|
id<MTLBlitCommandEncoder> blitcmd;
|
||||||
SDL_Rect rect = texturedata.lockedrect;
|
SDL_Rect rect = texturedata.lockedrect;
|
||||||
int pitch = SDL_BYTESPERPIXEL(texture->format) * rect.w;
|
int pitch = SDL_BYTESPERPIXEL(texture->format) * rect.w;
|
||||||
SDL_Rect UVrect = {rect.x / 2, rect.y / 2, (rect.w + 1) / 2, (rect.h + 1) / 2};
|
SDL_Rect UVrect = {rect.x / 2, rect.y / 2, (rect.w + 1) / 2, (rect.h + 1) / 2};
|
||||||
|
@ -894,7 +907,7 @@ METAL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
data.mtlcmdbuffer = [data.mtlcmdqueue commandBuffer];
|
data.mtlcmdbuffer = [data.mtlcmdqueue commandBuffer];
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLBlitCommandEncoder> blitcmd = [data.mtlcmdbuffer blitCommandEncoder];
|
blitcmd = [data.mtlcmdbuffer blitCommandEncoder];
|
||||||
|
|
||||||
[blitcmd copyFromBuffer:texturedata.lockedbuffer
|
[blitcmd copyFromBuffer:texturedata.lockedbuffer
|
||||||
sourceOffset:0
|
sourceOffset:0
|
||||||
|
@ -1068,11 +1081,13 @@ METAL_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_
|
||||||
cmd->data.draw.b,
|
cmd->data.draw.b,
|
||||||
cmd->data.draw.a
|
cmd->data.draw.a
|
||||||
};
|
};
|
||||||
|
size_t vertlen;
|
||||||
|
float *verts;
|
||||||
|
|
||||||
SDL_assert(count >= 2); /* should have been checked at the higher level. */
|
SDL_assert(count >= 2); /* should have been checked at the higher level. */
|
||||||
|
|
||||||
const size_t vertlen = (2 * sizeof (float) + sizeof (SDL_Color)) * count;
|
vertlen = (2 * sizeof (float) + sizeof (SDL_Color)) * count;
|
||||||
float *verts = (float *) SDL_AllocateRenderVertices(renderer, vertlen, DEVICE_ALIGN(8), &cmd->data.draw.first);
|
verts = (float *) SDL_AllocateRenderVertices(renderer, vertlen, DEVICE_ALIGN(8), &cmd->data.draw.first);
|
||||||
if (!verts) {
|
if (!verts) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1095,15 +1110,17 @@ METAL_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_
|
||||||
points -= 2; /* update the last line. */
|
points -= 2; /* update the last line. */
|
||||||
verts -= 2 + 1;
|
verts -= 2 + 1;
|
||||||
|
|
||||||
const float xstart = points[0].x;
|
{
|
||||||
const float ystart = points[0].y;
|
const float xstart = points[0].x;
|
||||||
const float xend = points[1].x;
|
const float ystart = points[0].y;
|
||||||
const float yend = points[1].y;
|
const float xend = points[1].x;
|
||||||
|
const float yend = points[1].y;
|
||||||
|
|
||||||
if (ystart == yend) { /* horizontal line */
|
if (ystart == yend) { /* horizontal line */
|
||||||
verts[0] += (xend > xstart) ? 1.0f : -1.0f;
|
verts[0] += (xend > xstart) ? 1.0f : -1.0f;
|
||||||
} else if (xstart == xend) { /* vertical line */
|
} else if (xstart == xend) { /* vertical line */
|
||||||
verts[1] += (yend > ystart) ? 1.0f : -1.0f;
|
verts[1] += (yend > ystart) ? 1.0f : -1.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1127,6 +1144,7 @@ METAL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
int j;
|
int j;
|
||||||
|
float *xy_;
|
||||||
if (size_indices == 4) {
|
if (size_indices == 4) {
|
||||||
j = ((const Uint32 *)indices)[i];
|
j = ((const Uint32 *)indices)[i];
|
||||||
} else if (size_indices == 2) {
|
} else if (size_indices == 2) {
|
||||||
|
@ -1137,7 +1155,7 @@ METAL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture
|
||||||
j = i;
|
j = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
float *xy_ = (float *)((char*)xy + j * xy_stride);
|
xy_ = (float *)((char*)xy + j * xy_stride);
|
||||||
|
|
||||||
*(verts++) = xy_[0] * scale_x;
|
*(verts++) = xy_[0] * scale_x;
|
||||||
*(verts++) = xy_[1] * scale_y;
|
*(verts++) = xy_[1] * scale_y;
|
||||||
|
@ -1282,11 +1300,10 @@ static int
|
||||||
METAL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
|
METAL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
|
||||||
{ @autoreleasepool {
|
{ @autoreleasepool {
|
||||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||||
|
id<MTLBuffer> mtlbufvertex = nil;
|
||||||
METAL_DrawStateCache statecache;
|
METAL_DrawStateCache statecache;
|
||||||
SDL_zero(statecache);
|
SDL_zero(statecache);
|
||||||
|
|
||||||
id<MTLBuffer> mtlbufvertex = nil;
|
|
||||||
|
|
||||||
statecache.pipeline = nil;
|
statecache.pipeline = nil;
|
||||||
statecache.vertex_buffer = nil;
|
statecache.vertex_buffer = nil;
|
||||||
statecache.constants_offset = CONSTANTS_OFFSET_INVALID;
|
statecache.constants_offset = CONSTANTS_OFFSET_INVALID;
|
||||||
|
@ -1363,15 +1380,17 @@ METAL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
|
||||||
statecache.cliprect_dirty = SDL_TRUE;
|
statecache.cliprect_dirty = SDL_TRUE;
|
||||||
statecache.viewport_dirty = SDL_TRUE;
|
statecache.viewport_dirty = SDL_TRUE;
|
||||||
|
|
||||||
const Uint8 r = cmd->data.color.r;
|
{
|
||||||
const Uint8 g = cmd->data.color.g;
|
const Uint8 r = cmd->data.color.r;
|
||||||
const Uint8 b = cmd->data.color.b;
|
const Uint8 g = cmd->data.color.g;
|
||||||
const Uint8 a = cmd->data.color.a;
|
const Uint8 b = cmd->data.color.b;
|
||||||
MTLClearColor color = MTLClearColorMake(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
|
const Uint8 a = cmd->data.color.a;
|
||||||
|
MTLClearColor color = MTLClearColorMake(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
|
||||||
|
|
||||||
// get new command encoder, set up with an initial clear operation.
|
// get new command encoder, set up with an initial clear operation.
|
||||||
// (this might fail, and future draw operations will notice.)
|
// (this might fail, and future draw operations will notice.)
|
||||||
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionClear, &color, mtlbufvertex);
|
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionClear, &color, mtlbufvertex);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1424,12 +1443,17 @@ METAL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
Uint32 pixel_format, void * pixels, int pitch)
|
Uint32 pixel_format, void * pixels, int pitch)
|
||||||
{ @autoreleasepool {
|
{ @autoreleasepool {
|
||||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||||
|
id<MTLTexture> mtltexture;
|
||||||
|
MTLRegion mtlregion;
|
||||||
|
int temp_pitch, status;
|
||||||
|
Uint32 temp_format;
|
||||||
|
void *temp_pixels;
|
||||||
if (!METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, nil)) {
|
if (!METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, nil)) {
|
||||||
return SDL_SetError("Failed to activate render command encoder (is your window in the background?");
|
return SDL_SetError("Failed to activate render command encoder (is your window in the background?");
|
||||||
}
|
}
|
||||||
|
|
||||||
[data.mtlcmdencoder endEncoding];
|
[data.mtlcmdencoder endEncoding];
|
||||||
id<MTLTexture> mtltexture = data.mtlpassdesc.colorAttachments[0].texture;
|
mtltexture = data.mtlpassdesc.colorAttachments[0].texture;
|
||||||
|
|
||||||
#ifdef __MACOSX__
|
#ifdef __MACOSX__
|
||||||
/* on macOS with managed-storage textures, we need to tell the driver to
|
/* on macOS with managed-storage textures, we need to tell the driver to
|
||||||
|
@ -1450,19 +1474,19 @@ METAL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
data.mtlcmdencoder = nil;
|
data.mtlcmdencoder = nil;
|
||||||
data.mtlcmdbuffer = nil;
|
data.mtlcmdbuffer = nil;
|
||||||
|
|
||||||
MTLRegion mtlregion = MTLRegionMake2D(rect->x, rect->y, rect->w, rect->h);
|
mtlregion = MTLRegionMake2D(rect->x, rect->y, rect->w, rect->h);
|
||||||
|
|
||||||
// we only do BGRA8 or RGBA8 at the moment, so 4 will do.
|
// we only do BGRA8 or RGBA8 at the moment, so 4 will do.
|
||||||
const int temp_pitch = rect->w * 4;
|
temp_pitch = rect->w * 4;
|
||||||
void *temp_pixels = SDL_malloc(temp_pitch * rect->h);
|
temp_pixels = SDL_malloc(temp_pitch * rect->h);
|
||||||
if (!temp_pixels) {
|
if (!temp_pixels) {
|
||||||
return SDL_OutOfMemory();
|
return SDL_OutOfMemory();
|
||||||
}
|
}
|
||||||
|
|
||||||
[mtltexture getBytes:temp_pixels bytesPerRow:temp_pitch fromRegion:mtlregion mipmapLevel:0];
|
[mtltexture getBytes:temp_pixels bytesPerRow:temp_pitch fromRegion:mtlregion mipmapLevel:0];
|
||||||
|
|
||||||
const Uint32 temp_format = (mtltexture.pixelFormat == MTLPixelFormatBGRA8Unorm) ? SDL_PIXELFORMAT_ARGB8888 : SDL_PIXELFORMAT_ABGR8888;
|
temp_format = (mtltexture.pixelFormat == MTLPixelFormatBGRA8Unorm) ? SDL_PIXELFORMAT_ARGB8888 : SDL_PIXELFORMAT_ABGR8888;
|
||||||
const int status = SDL_ConvertPixels(rect->w, rect->h, temp_format, temp_pixels, temp_pitch, pixel_format, pixels, pitch);
|
status = SDL_ConvertPixels(rect->w, rect->h, temp_format, temp_pixels, temp_pitch, pixel_format, pixels, pitch);
|
||||||
SDL_free(temp_pixels);
|
SDL_free(temp_pixels);
|
||||||
return status;
|
return status;
|
||||||
}}
|
}}
|
||||||
|
@ -1542,8 +1566,9 @@ METAL_GetMetalCommandEncoder(SDL_Renderer * renderer)
|
||||||
// note that data.mtlcmdencoder can be nil if METAL_ActivateRenderCommandEncoder fails.
|
// note that data.mtlcmdencoder can be nil if METAL_ActivateRenderCommandEncoder fails.
|
||||||
// Before SDL 2.0.18, it might have returned a non-nil encoding that might not have been
|
// Before SDL 2.0.18, it might have returned a non-nil encoding that might not have been
|
||||||
// usable for presentation. Check your return values!
|
// usable for presentation. Check your return values!
|
||||||
|
METAL_RenderData *data;
|
||||||
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, nil);
|
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, nil);
|
||||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||||
return (__bridge void*)data.mtlcmdencoder;
|
return (__bridge void*)data.mtlcmdencoder;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
@ -1603,8 +1628,58 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
SDL_MetalView view = NULL;
|
SDL_MetalView view = NULL;
|
||||||
CAMetalLayer *layer = nil;
|
CAMetalLayer *layer = nil;
|
||||||
SDL_SysWMinfo syswm;
|
SDL_SysWMinfo syswm;
|
||||||
Uint32 window_flags;
|
|
||||||
SDL_bool changed_window = SDL_FALSE;
|
SDL_bool changed_window = SDL_FALSE;
|
||||||
|
NSError *err = nil;
|
||||||
|
dispatch_data_t mtllibdata;
|
||||||
|
char *constantdata;
|
||||||
|
int maxtexsize, quadcount = UINT16_MAX / 4;
|
||||||
|
UInt16 *indexdata;
|
||||||
|
Uint32 window_flags;
|
||||||
|
size_t indicessize = sizeof(UInt16) * quadcount * 6;
|
||||||
|
MTLSamplerDescriptor *samplerdesc;
|
||||||
|
id<MTLCommandQueue> mtlcmdqueue;
|
||||||
|
id<MTLLibrary> mtllibrary;
|
||||||
|
id<MTLSamplerState> mtlsamplernearest, mtlsamplerlinear;
|
||||||
|
id<MTLBuffer> mtlbufconstantstaging, mtlbufquadindicesstaging, mtlbufconstants, mtlbufquadindices;
|
||||||
|
id<MTLCommandBuffer> cmdbuffer;
|
||||||
|
id<MTLBlitCommandEncoder> blitcmd;
|
||||||
|
|
||||||
|
/* Note: matrices are column major. */
|
||||||
|
float identitytransform[16] = {
|
||||||
|
1.0f, 0.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 1.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 0.0f, 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
float halfpixeltransform[16] = {
|
||||||
|
1.0f, 0.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 1.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f, 0.0f,
|
||||||
|
0.5f, 0.5f, 0.0f, 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Metal pads float3s to 16 bytes. */
|
||||||
|
float decodetransformJPEG[4*4] = {
|
||||||
|
0.0, -0.501960814, -0.501960814, 0.0, /* offset */
|
||||||
|
1.0000, 0.0000, 1.4020, 0.0, /* Rcoeff */
|
||||||
|
1.0000, -0.3441, -0.7141, 0.0, /* Gcoeff */
|
||||||
|
1.0000, 1.7720, 0.0000, 0.0, /* Bcoeff */
|
||||||
|
};
|
||||||
|
|
||||||
|
float decodetransformBT601[4*4] = {
|
||||||
|
-0.0627451017, -0.501960814, -0.501960814, 0.0, /* offset */
|
||||||
|
1.1644, 0.0000, 1.5960, 0.0, /* Rcoeff */
|
||||||
|
1.1644, -0.3918, -0.8130, 0.0, /* Gcoeff */
|
||||||
|
1.1644, 2.0172, 0.0000, 0.0, /* Bcoeff */
|
||||||
|
};
|
||||||
|
|
||||||
|
float decodetransformBT709[4*4] = {
|
||||||
|
0.0, -0.501960814, -0.501960814, 0.0, /* offset */
|
||||||
|
1.0000, 0.0000, 1.4020, 0.0, /* Rcoeff */
|
||||||
|
1.0000, -0.3441, -0.7141, 0.0, /* Gcoeff */
|
||||||
|
1.0000, 1.7720, 0.0000, 0.0, /* Bcoeff */
|
||||||
|
};
|
||||||
|
|
||||||
SDL_VERSION(&syswm.version);
|
SDL_VERSION(&syswm.version);
|
||||||
if (!SDL_GetWindowWMInfo(window, &syswm)) {
|
if (!SDL_GetWindowWMInfo(window, &syswm)) {
|
||||||
|
@ -1691,17 +1766,15 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
|
|
||||||
data.mtldevice = layer.device;
|
data.mtldevice = layer.device;
|
||||||
data.mtllayer = layer;
|
data.mtllayer = layer;
|
||||||
id<MTLCommandQueue> mtlcmdqueue = [data.mtldevice newCommandQueue];
|
mtlcmdqueue = [data.mtldevice newCommandQueue];
|
||||||
data.mtlcmdqueue = mtlcmdqueue;
|
data.mtlcmdqueue = mtlcmdqueue;
|
||||||
data.mtlcmdqueue.label = @"SDL Metal Renderer";
|
data.mtlcmdqueue.label = @"SDL Metal Renderer";
|
||||||
data.mtlpassdesc = [MTLRenderPassDescriptor renderPassDescriptor];
|
data.mtlpassdesc = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||||
|
|
||||||
NSError *err = nil;
|
|
||||||
|
|
||||||
// The compiled .metallib is embedded in a static array in a header file
|
// The compiled .metallib is embedded in a static array in a header file
|
||||||
// but the original shader source code is in SDL_shaders_metal.metal.
|
// but the original shader source code is in SDL_shaders_metal.metal.
|
||||||
dispatch_data_t mtllibdata = dispatch_data_create(sdl_metallib, sdl_metallib_len, dispatch_get_global_queue(0, 0), ^{});
|
mtllibdata = dispatch_data_create(sdl_metallib, sdl_metallib_len, dispatch_get_global_queue(0, 0), ^{});
|
||||||
id<MTLLibrary> mtllibrary = [data.mtldevice newLibraryWithData:mtllibdata error:&err];
|
mtllibrary = [data.mtldevice newLibraryWithData:mtllibdata error:&err];
|
||||||
data.mtllibrary = mtllibrary;
|
data.mtllibrary = mtllibrary;
|
||||||
SDL_assert(err == nil);
|
SDL_assert(err == nil);
|
||||||
data.mtllibrary.label = @"SDL Metal renderer shader library";
|
data.mtllibrary.label = @"SDL Metal renderer shader library";
|
||||||
|
@ -1711,74 +1784,35 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
data.allpipelines = NULL;
|
data.allpipelines = NULL;
|
||||||
ChooseShaderPipelines(data, MTLPixelFormatBGRA8Unorm);
|
ChooseShaderPipelines(data, MTLPixelFormatBGRA8Unorm);
|
||||||
|
|
||||||
MTLSamplerDescriptor *samplerdesc = [[MTLSamplerDescriptor alloc] init];
|
samplerdesc = [[MTLSamplerDescriptor alloc] init];
|
||||||
|
|
||||||
samplerdesc.minFilter = MTLSamplerMinMagFilterNearest;
|
samplerdesc.minFilter = MTLSamplerMinMagFilterNearest;
|
||||||
samplerdesc.magFilter = MTLSamplerMinMagFilterNearest;
|
samplerdesc.magFilter = MTLSamplerMinMagFilterNearest;
|
||||||
id<MTLSamplerState> mtlsamplernearest = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
|
mtlsamplernearest = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
|
||||||
data.mtlsamplernearest = mtlsamplernearest;
|
data.mtlsamplernearest = mtlsamplernearest;
|
||||||
|
|
||||||
samplerdesc.minFilter = MTLSamplerMinMagFilterLinear;
|
samplerdesc.minFilter = MTLSamplerMinMagFilterLinear;
|
||||||
samplerdesc.magFilter = MTLSamplerMinMagFilterLinear;
|
samplerdesc.magFilter = MTLSamplerMinMagFilterLinear;
|
||||||
id<MTLSamplerState> mtlsamplerlinear = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
|
mtlsamplerlinear = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
|
||||||
data.mtlsamplerlinear = mtlsamplerlinear;
|
data.mtlsamplerlinear = mtlsamplerlinear;
|
||||||
|
|
||||||
/* Note: matrices are column major. */
|
mtlbufconstantstaging = [data.mtldevice newBufferWithLength:CONSTANTS_LENGTH options:MTLResourceStorageModeShared];
|
||||||
float identitytransform[16] = {
|
|
||||||
1.0f, 0.0f, 0.0f, 0.0f,
|
|
||||||
0.0f, 1.0f, 0.0f, 0.0f,
|
|
||||||
0.0f, 0.0f, 1.0f, 0.0f,
|
|
||||||
0.0f, 0.0f, 0.0f, 1.0f,
|
|
||||||
};
|
|
||||||
|
|
||||||
float halfpixeltransform[16] = {
|
constantdata = [mtlbufconstantstaging contents];
|
||||||
1.0f, 0.0f, 0.0f, 0.0f,
|
|
||||||
0.0f, 1.0f, 0.0f, 0.0f,
|
|
||||||
0.0f, 0.0f, 1.0f, 0.0f,
|
|
||||||
0.5f, 0.5f, 0.0f, 1.0f,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Metal pads float3s to 16 bytes. */
|
|
||||||
float decodetransformJPEG[4*4] = {
|
|
||||||
0.0, -0.501960814, -0.501960814, 0.0, /* offset */
|
|
||||||
1.0000, 0.0000, 1.4020, 0.0, /* Rcoeff */
|
|
||||||
1.0000, -0.3441, -0.7141, 0.0, /* Gcoeff */
|
|
||||||
1.0000, 1.7720, 0.0000, 0.0, /* Bcoeff */
|
|
||||||
};
|
|
||||||
|
|
||||||
float decodetransformBT601[4*4] = {
|
|
||||||
-0.0627451017, -0.501960814, -0.501960814, 0.0, /* offset */
|
|
||||||
1.1644, 0.0000, 1.5960, 0.0, /* Rcoeff */
|
|
||||||
1.1644, -0.3918, -0.8130, 0.0, /* Gcoeff */
|
|
||||||
1.1644, 2.0172, 0.0000, 0.0, /* Bcoeff */
|
|
||||||
};
|
|
||||||
|
|
||||||
float decodetransformBT709[4*4] = {
|
|
||||||
0.0, -0.501960814, -0.501960814, 0.0, /* offset */
|
|
||||||
1.0000, 0.0000, 1.4020, 0.0, /* Rcoeff */
|
|
||||||
1.0000, -0.3441, -0.7141, 0.0, /* Gcoeff */
|
|
||||||
1.0000, 1.7720, 0.0000, 0.0, /* Bcoeff */
|
|
||||||
};
|
|
||||||
|
|
||||||
id<MTLBuffer> mtlbufconstantstaging = [data.mtldevice newBufferWithLength:CONSTANTS_LENGTH options:MTLResourceStorageModeShared];
|
|
||||||
|
|
||||||
char *constantdata = [mtlbufconstantstaging contents];
|
|
||||||
SDL_memcpy(constantdata + CONSTANTS_OFFSET_IDENTITY, identitytransform, sizeof(identitytransform));
|
SDL_memcpy(constantdata + CONSTANTS_OFFSET_IDENTITY, identitytransform, sizeof(identitytransform));
|
||||||
SDL_memcpy(constantdata + CONSTANTS_OFFSET_HALF_PIXEL_TRANSFORM, halfpixeltransform, sizeof(halfpixeltransform));
|
SDL_memcpy(constantdata + CONSTANTS_OFFSET_HALF_PIXEL_TRANSFORM, halfpixeltransform, sizeof(halfpixeltransform));
|
||||||
SDL_memcpy(constantdata + CONSTANTS_OFFSET_DECODE_JPEG, decodetransformJPEG, sizeof(decodetransformJPEG));
|
SDL_memcpy(constantdata + CONSTANTS_OFFSET_DECODE_JPEG, decodetransformJPEG, sizeof(decodetransformJPEG));
|
||||||
SDL_memcpy(constantdata + CONSTANTS_OFFSET_DECODE_BT601, decodetransformBT601, sizeof(decodetransformBT601));
|
SDL_memcpy(constantdata + CONSTANTS_OFFSET_DECODE_BT601, decodetransformBT601, sizeof(decodetransformBT601));
|
||||||
SDL_memcpy(constantdata + CONSTANTS_OFFSET_DECODE_BT709, decodetransformBT709, sizeof(decodetransformBT709));
|
SDL_memcpy(constantdata + CONSTANTS_OFFSET_DECODE_BT709, decodetransformBT709, sizeof(decodetransformBT709));
|
||||||
|
|
||||||
int quadcount = UINT16_MAX / 4;
|
mtlbufquadindicesstaging = [data.mtldevice newBufferWithLength:indicessize options:MTLResourceStorageModeShared];
|
||||||
size_t indicessize = sizeof(UInt16) * quadcount * 6;
|
|
||||||
id<MTLBuffer> mtlbufquadindicesstaging = [data.mtldevice newBufferWithLength:indicessize options:MTLResourceStorageModeShared];
|
|
||||||
|
|
||||||
/* Quads in the following vertex order (matches the FillRects vertices):
|
/* Quads in the following vertex order (matches the FillRects vertices):
|
||||||
* 1---3
|
* 1---3
|
||||||
* | \ |
|
* | \ |
|
||||||
* 0---2
|
* 0---2
|
||||||
*/
|
*/
|
||||||
UInt16 *indexdata = [mtlbufquadindicesstaging contents];
|
indexdata = [mtlbufquadindicesstaging contents];
|
||||||
for (int i = 0; i < quadcount; i++) {
|
for (int i = 0; i < quadcount; i++) {
|
||||||
indexdata[i * 6 + 0] = i * 4 + 0;
|
indexdata[i * 6 + 0] = i * 4 + 0;
|
||||||
indexdata[i * 6 + 1] = i * 4 + 1;
|
indexdata[i * 6 + 1] = i * 4 + 1;
|
||||||
|
@ -1789,16 +1823,16 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
indexdata[i * 6 + 5] = i * 4 + 3;
|
indexdata[i * 6 + 5] = i * 4 + 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLBuffer> mtlbufconstants = [data.mtldevice newBufferWithLength:CONSTANTS_LENGTH options:MTLResourceStorageModePrivate];
|
mtlbufconstants = [data.mtldevice newBufferWithLength:CONSTANTS_LENGTH options:MTLResourceStorageModePrivate];
|
||||||
data.mtlbufconstants = mtlbufconstants;
|
data.mtlbufconstants = mtlbufconstants;
|
||||||
data.mtlbufconstants.label = @"SDL constant data";
|
data.mtlbufconstants.label = @"SDL constant data";
|
||||||
|
|
||||||
id<MTLBuffer> mtlbufquadindices = [data.mtldevice newBufferWithLength:indicessize options:MTLResourceStorageModePrivate];
|
mtlbufquadindices = [data.mtldevice newBufferWithLength:indicessize options:MTLResourceStorageModePrivate];
|
||||||
data.mtlbufquadindices = mtlbufquadindices;
|
data.mtlbufquadindices = mtlbufquadindices;
|
||||||
data.mtlbufquadindices.label = @"SDL quad index buffer";
|
data.mtlbufquadindices.label = @"SDL quad index buffer";
|
||||||
|
|
||||||
id<MTLCommandBuffer> cmdbuffer = [data.mtlcmdqueue commandBuffer];
|
cmdbuffer = [data.mtlcmdqueue commandBuffer];
|
||||||
id<MTLBlitCommandEncoder> blitcmd = [cmdbuffer blitCommandEncoder];
|
blitcmd = [cmdbuffer blitCommandEncoder];
|
||||||
|
|
||||||
[blitcmd copyFromBuffer:mtlbufconstantstaging sourceOffset:0 toBuffer:mtlbufconstants destinationOffset:0 size:CONSTANTS_LENGTH];
|
[blitcmd copyFromBuffer:mtlbufconstantstaging sourceOffset:0 toBuffer:mtlbufconstants destinationOffset:0 size:CONSTANTS_LENGTH];
|
||||||
[blitcmd copyFromBuffer:mtlbufquadindicesstaging sourceOffset:0 toBuffer:mtlbufquadindices destinationOffset:0 size:indicessize];
|
[blitcmd copyFromBuffer:mtlbufquadindicesstaging sourceOffset:0 toBuffer:mtlbufquadindices destinationOffset:0 size:indicessize];
|
||||||
|
@ -1853,7 +1887,7 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf */
|
/* https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf */
|
||||||
int maxtexsize = 4096;
|
maxtexsize = 4096;
|
||||||
#if defined(__MACOSX__) || TARGET_OS_MACCATALYST
|
#if defined(__MACOSX__) || TARGET_OS_MACCATALYST
|
||||||
maxtexsize = 16384;
|
maxtexsize = 16384;
|
||||||
#elif defined(__TVOS__)
|
#elif defined(__TVOS__)
|
||||||
|
|
|
@ -87,8 +87,7 @@ SDL_TicksInit(void)
|
||||||
has_monotonic_time = SDL_TRUE;
|
has_monotonic_time = SDL_TRUE;
|
||||||
} else
|
} else
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
kern_return_t ret = mach_timebase_info(&mach_base_info);
|
if (0 == mach_timebase_info(&mach_base_info)) {
|
||||||
if (ret == 0) {
|
|
||||||
has_monotonic_time = SDL_TRUE;
|
has_monotonic_time = SDL_TRUE;
|
||||||
start_mach = mach_absolute_time();
|
start_mach = mach_absolute_time();
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -229,6 +229,7 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
|
||||||
|
|
||||||
- (void)focusSomeWindow:(NSNotification *)aNotification
|
- (void)focusSomeWindow:(NSNotification *)aNotification
|
||||||
{
|
{
|
||||||
|
SDL_VideoDevice *device;
|
||||||
/* HACK: Ignore the first call. The application gets a
|
/* HACK: Ignore the first call. The application gets a
|
||||||
* applicationDidBecomeActive: a little bit after the first window is
|
* applicationDidBecomeActive: a little bit after the first window is
|
||||||
* created, and if we don't ignore it, a window that has been created with
|
* created, and if we don't ignore it, a window that has been created with
|
||||||
|
@ -246,7 +247,7 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_VideoDevice *device = SDL_GetVideoDevice();
|
device = SDL_GetVideoDevice();
|
||||||
if (device && device->windows) {
|
if (device && device->windows) {
|
||||||
SDL_Window *window = device->windows;
|
SDL_Window *window = device->windows;
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -390,6 +390,7 @@ UpdateKeymap(SDL_VideoData *data, SDL_bool send_event)
|
||||||
int i;
|
int i;
|
||||||
SDL_Scancode scancode;
|
SDL_Scancode scancode;
|
||||||
SDL_Keycode keymap[SDL_NUM_SCANCODES];
|
SDL_Keycode keymap[SDL_NUM_SCANCODES];
|
||||||
|
CFDataRef uchrDataRef;
|
||||||
|
|
||||||
/* See if the keymap needs to be updated */
|
/* See if the keymap needs to be updated */
|
||||||
key_layout = TISCopyCurrentKeyboardLayoutInputSource();
|
key_layout = TISCopyCurrentKeyboardLayoutInputSource();
|
||||||
|
@ -401,7 +402,7 @@ UpdateKeymap(SDL_VideoData *data, SDL_bool send_event)
|
||||||
SDL_GetDefaultKeymap(keymap);
|
SDL_GetDefaultKeymap(keymap);
|
||||||
|
|
||||||
/* Try Unicode data first */
|
/* Try Unicode data first */
|
||||||
CFDataRef uchrDataRef = TISGetInputSourceProperty(key_layout, kTISPropertyUnicodeKeyLayoutData);
|
uchrDataRef = TISGetInputSourceProperty(key_layout, kTISPropertyUnicodeKeyLayoutData);
|
||||||
if (uchrDataRef) {
|
if (uchrDataRef) {
|
||||||
chr_data = CFDataGetBytePtr(uchrDataRef);
|
chr_data = CFDataGetBytePtr(uchrDataRef);
|
||||||
} else {
|
} else {
|
||||||
|
@ -472,6 +473,7 @@ void
|
||||||
Cocoa_StartTextInput(_THIS)
|
Cocoa_StartTextInput(_THIS)
|
||||||
{ @autoreleasepool
|
{ @autoreleasepool
|
||||||
{
|
{
|
||||||
|
NSView *parentView;
|
||||||
SDL_VideoData *data = (__bridge SDL_VideoData *) _this->driverdata;
|
SDL_VideoData *data = (__bridge SDL_VideoData *) _this->driverdata;
|
||||||
SDL_Window *window = SDL_GetKeyboardFocus();
|
SDL_Window *window = SDL_GetKeyboardFocus();
|
||||||
NSWindow *nswindow = nil;
|
NSWindow *nswindow = nil;
|
||||||
|
@ -479,7 +481,7 @@ Cocoa_StartTextInput(_THIS)
|
||||||
nswindow = ((__bridge SDL_WindowData*)window->driverdata).nswindow;
|
nswindow = ((__bridge SDL_WindowData*)window->driverdata).nswindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSView *parentView = [nswindow contentView];
|
parentView = [nswindow contentView];
|
||||||
|
|
||||||
/* We only keep one field editor per process, since only the front most
|
/* We only keep one field editor per process, since only the front most
|
||||||
* window can receive text input events, so it make no sense to keep more
|
* window can receive text input events, so it make no sense to keep more
|
||||||
|
@ -527,13 +529,14 @@ Cocoa_SetTextInputRect(_THIS, SDL_Rect *rect)
|
||||||
void
|
void
|
||||||
Cocoa_HandleKeyEvent(_THIS, NSEvent *event)
|
Cocoa_HandleKeyEvent(_THIS, NSEvent *event)
|
||||||
{
|
{
|
||||||
|
unsigned short scancode;
|
||||||
|
SDL_Scancode code;
|
||||||
SDL_VideoData *data = _this ? ((__bridge SDL_VideoData *) _this->driverdata) : nil;
|
SDL_VideoData *data = _this ? ((__bridge SDL_VideoData *) _this->driverdata) : nil;
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return; /* can happen when returning from fullscreen Space on shutdown */
|
return; /* can happen when returning from fullscreen Space on shutdown */
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short scancode = [event keyCode];
|
scancode = [event keyCode];
|
||||||
SDL_Scancode code;
|
|
||||||
#if 0
|
#if 0
|
||||||
const char *text;
|
const char *text;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -92,9 +92,14 @@
|
||||||
static void
|
static void
|
||||||
Cocoa_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int *buttonid, int *returnValue)
|
Cocoa_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int *buttonid, int *returnValue)
|
||||||
{
|
{
|
||||||
|
NSAlert* alert;
|
||||||
|
const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
|
||||||
|
SDLMessageBoxPresenter* presenter;
|
||||||
|
NSInteger clicked;
|
||||||
|
int i;
|
||||||
Cocoa_RegisterApp();
|
Cocoa_RegisterApp();
|
||||||
|
|
||||||
NSAlert* alert = [[NSAlert alloc] init];
|
alert = [[NSAlert alloc] init];
|
||||||
|
|
||||||
if (messageboxdata->flags & SDL_MESSAGEBOX_ERROR) {
|
if (messageboxdata->flags & SDL_MESSAGEBOX_ERROR) {
|
||||||
[alert setAlertStyle:NSAlertStyleCritical];
|
[alert setAlertStyle:NSAlertStyleCritical];
|
||||||
|
@ -107,8 +112,6 @@ Cocoa_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int *buttonid
|
||||||
[alert setMessageText:[NSString stringWithUTF8String:messageboxdata->title]];
|
[alert setMessageText:[NSString stringWithUTF8String:messageboxdata->title]];
|
||||||
[alert setInformativeText:[NSString stringWithUTF8String:messageboxdata->message]];
|
[alert setInformativeText:[NSString stringWithUTF8String:messageboxdata->message]];
|
||||||
|
|
||||||
const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < messageboxdata->numbuttons; ++i) {
|
for (i = 0; i < messageboxdata->numbuttons; ++i) {
|
||||||
const SDL_MessageBoxButtonData *sdlButton;
|
const SDL_MessageBoxButtonData *sdlButton;
|
||||||
NSButton *button;
|
NSButton *button;
|
||||||
|
@ -129,11 +132,11 @@ Cocoa_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int *buttonid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDLMessageBoxPresenter* presenter = [[SDLMessageBoxPresenter alloc] initWithParentWindow:messageboxdata->window];
|
presenter = [[SDLMessageBoxPresenter alloc] initWithParentWindow:messageboxdata->window];
|
||||||
|
|
||||||
[presenter showAlert:alert];
|
[presenter showAlert:alert];
|
||||||
|
|
||||||
NSInteger clicked = presenter->clicked;
|
clicked = presenter->clicked;
|
||||||
if (clicked >= NSAlertFirstButtonReturn) {
|
if (clicked >= NSAlertFirstButtonReturn) {
|
||||||
clicked -= NSAlertFirstButtonReturn;
|
clicked -= NSAlertFirstButtonReturn;
|
||||||
if (messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) {
|
if (messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) {
|
||||||
|
|
|
@ -185,6 +185,9 @@ GetDisplayMode(_THIS, CGDisplayModeRef vidmode, SDL_bool vidmodeCurrent, CFArray
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < modescount; i++) {
|
for (i = 0; i < modescount; i++) {
|
||||||
|
int otherW, otherH, otherpixelW, otherpixelH, otherrefresh;
|
||||||
|
Uint32 otherformat;
|
||||||
|
bool otherGUI;
|
||||||
CGDisplayModeRef othermode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modelist, i);
|
CGDisplayModeRef othermode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modelist, i);
|
||||||
uint32_t otherioflags = CGDisplayModeGetIOFlags(othermode);
|
uint32_t otherioflags = CGDisplayModeGetIOFlags(othermode);
|
||||||
|
|
||||||
|
@ -196,13 +199,13 @@ GetDisplayMode(_THIS, CGDisplayModeRef vidmode, SDL_bool vidmodeCurrent, CFArray
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int otherW = (int) CGDisplayModeGetWidth(othermode);
|
otherW = (int) CGDisplayModeGetWidth(othermode);
|
||||||
int otherH = (int) CGDisplayModeGetHeight(othermode);
|
otherH = (int) CGDisplayModeGetHeight(othermode);
|
||||||
int otherpixelW = (int) CGDisplayModeGetPixelWidth(othermode);
|
otherpixelW = (int) CGDisplayModeGetPixelWidth(othermode);
|
||||||
int otherpixelH = (int) CGDisplayModeGetPixelHeight(othermode);
|
otherpixelH = (int) CGDisplayModeGetPixelHeight(othermode);
|
||||||
int otherrefresh = GetDisplayModeRefreshRate(othermode, link);
|
otherrefresh = GetDisplayModeRefreshRate(othermode, link);
|
||||||
Uint32 otherformat = GetDisplayModePixelFormat(othermode);
|
otherformat = GetDisplayModePixelFormat(othermode);
|
||||||
bool otherGUI = CGDisplayModeIsUsableForDesktopGUI(othermode);
|
otherGUI = CGDisplayModeIsUsableForDesktopGUI(othermode);
|
||||||
|
|
||||||
/* Ignore this mode if it's low-dpi (@1x) and we have a high-dpi
|
/* Ignore this mode if it's low-dpi (@1x) and we have a high-dpi
|
||||||
* mode in the list with the same size in points.
|
* mode in the list with the same size in points.
|
||||||
|
@ -417,11 +420,13 @@ Cocoa_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NSRect frame = [screen visibleFrame];
|
{
|
||||||
rect->x = (int)frame.origin.x;
|
const NSRect frame = [screen visibleFrame];
|
||||||
rect->y = (int)(CGDisplayPixelsHigh(kCGDirectMainDisplay) - frame.origin.y - frame.size.height);
|
rect->x = (int)frame.origin.x;
|
||||||
rect->w = (int)frame.size.width;
|
rect->y = (int)(CGDisplayPixelsHigh(kCGDirectMainDisplay) - frame.origin.y - frame.size.height);
|
||||||
rect->h = (int)frame.size.height;
|
rect->w = (int)frame.size.width;
|
||||||
|
rect->h = (int)frame.size.height;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -487,20 +492,21 @@ Cocoa_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const CGSize displaySize = CGDisplayScreenSize(data->display);
|
{
|
||||||
const int pixelWidth = displayNativeSize.width;
|
const CGSize displaySize = CGDisplayScreenSize(data->display);
|
||||||
const int pixelHeight = displayNativeSize.height;
|
const int pixelWidth = displayNativeSize.width;
|
||||||
|
const int pixelHeight = displayNativeSize.height;
|
||||||
|
|
||||||
if (ddpi) {
|
if (ddpi) {
|
||||||
*ddpi = (SDL_ComputeDiagonalDPI(pixelWidth, pixelHeight, displaySize.width / MM_IN_INCH, displaySize.height / MM_IN_INCH));
|
*ddpi = (SDL_ComputeDiagonalDPI(pixelWidth, pixelHeight, displaySize.width / MM_IN_INCH, displaySize.height / MM_IN_INCH));
|
||||||
|
}
|
||||||
|
if (hdpi) {
|
||||||
|
*hdpi = (pixelWidth * MM_IN_INCH / displaySize.width);
|
||||||
|
}
|
||||||
|
if (vdpi) {
|
||||||
|
*vdpi = (pixelHeight * MM_IN_INCH / displaySize.height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (hdpi) {
|
|
||||||
*hdpi = (pixelWidth * MM_IN_INCH / displaySize.width);
|
|
||||||
}
|
|
||||||
if (vdpi) {
|
|
||||||
*vdpi = (pixelHeight * MM_IN_INCH / displaySize.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
|
@ -112,35 +112,37 @@ static NSCursor *
|
||||||
LoadHiddenSystemCursor(NSString *cursorName, SEL fallback)
|
LoadHiddenSystemCursor(NSString *cursorName, SEL fallback)
|
||||||
{
|
{
|
||||||
NSString *cursorPath = [@"/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/Resources/cursors" stringByAppendingPathComponent:cursorName];
|
NSString *cursorPath = [@"/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/Resources/cursors" stringByAppendingPathComponent:cursorName];
|
||||||
|
NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[cursorPath stringByAppendingPathComponent:@"info.plist"]];
|
||||||
|
/* we can't do animation atm. :/ */
|
||||||
|
const int frames = [[info valueForKey:@"frames"] integerValue];
|
||||||
|
NSCursor *cursor;
|
||||||
NSImage *image = [[NSImage alloc] initWithContentsOfFile:[cursorPath stringByAppendingPathComponent:@"cursor.pdf"]];
|
NSImage *image = [[NSImage alloc] initWithContentsOfFile:[cursorPath stringByAppendingPathComponent:@"cursor.pdf"]];
|
||||||
if ((image == nil) || (image.valid == NO)) {
|
if ((image == nil) || (image.valid == NO)) {
|
||||||
return [NSCursor performSelector:fallback];
|
return [NSCursor performSelector:fallback];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[cursorPath stringByAppendingPathComponent:@"info.plist"]];
|
|
||||||
|
|
||||||
/* we can't do animation atm. :/ */
|
|
||||||
const int frames = [[info valueForKey:@"frames"] integerValue];
|
|
||||||
if (frames > 1) {
|
if (frames > 1) {
|
||||||
|
#ifdef MAC_OS_VERSION_12_0 /* same value as deprecated symbol. */
|
||||||
|
const NSCompositingOperation operation = NSCompositingOperationCopy;
|
||||||
|
#else
|
||||||
|
const NSCompositingOperation operation = NSCompositeCopy;
|
||||||
|
#endif
|
||||||
const NSSize cropped_size = NSMakeSize(image.size.width, (int) (image.size.height / frames));
|
const NSSize cropped_size = NSMakeSize(image.size.width, (int) (image.size.height / frames));
|
||||||
NSImage *cropped = [[NSImage alloc] initWithSize:cropped_size];
|
NSImage *cropped = [[NSImage alloc] initWithSize:cropped_size];
|
||||||
if (cropped == nil) {
|
if (cropped == nil) {
|
||||||
return [NSCursor performSelector:fallback];
|
return [NSCursor performSelector:fallback];
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MAC_OS_VERSION_12_0 /* same value as deprecated symbol. */
|
|
||||||
const NSCompositingOperation operation = NSCompositingOperationCopy;
|
|
||||||
#else
|
|
||||||
const NSCompositingOperation operation = NSCompositeCopy;
|
|
||||||
#endif
|
|
||||||
[cropped lockFocus];
|
[cropped lockFocus];
|
||||||
const NSRect cropped_rect = NSMakeRect(0, 0, cropped_size.width, cropped_size.height);
|
{
|
||||||
[image drawInRect:cropped_rect fromRect:cropped_rect operation:operation fraction:1];
|
const NSRect cropped_rect = NSMakeRect(0, 0, cropped_size.width, cropped_size.height);
|
||||||
|
[image drawInRect:cropped_rect fromRect:cropped_rect operation:operation fraction:1];
|
||||||
|
}
|
||||||
[cropped unlockFocus];
|
[cropped unlockFocus];
|
||||||
image = cropped;
|
image = cropped;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSCursor *cursor = [[NSCursor alloc] initWithImage:image hotSpot:NSMakePoint([[info valueForKey:@"hotx"] doubleValue], [[info valueForKey:@"hoty"] doubleValue])];
|
cursor = [[NSCursor alloc] initWithImage:image hotSpot:NSMakePoint([[info valueForKey:@"hotx"] doubleValue], [[info valueForKey:@"hoty"] doubleValue])];
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,6 +249,7 @@ SDL_FindWindowAtPoint(const int x, const int y)
|
||||||
static int
|
static int
|
||||||
Cocoa_WarpMouseGlobal(int x, int y)
|
Cocoa_WarpMouseGlobal(int x, int y)
|
||||||
{
|
{
|
||||||
|
CGPoint point;
|
||||||
SDL_Mouse *mouse = SDL_GetMouse();
|
SDL_Mouse *mouse = SDL_GetMouse();
|
||||||
if (mouse->focus) {
|
if (mouse->focus) {
|
||||||
SDL_WindowData *data = (__bridge SDL_WindowData *) mouse->focus->driverdata;
|
SDL_WindowData *data = (__bridge SDL_WindowData *) mouse->focus->driverdata;
|
||||||
|
@ -256,7 +259,7 @@ Cocoa_WarpMouseGlobal(int x, int y)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const CGPoint point = CGPointMake((float)x, (float)y);
|
point = CGPointMake((float)x, (float)y);
|
||||||
|
|
||||||
Cocoa_HandleMouseWarp(point.x, point.y);
|
Cocoa_HandleMouseWarp(point.x, point.y);
|
||||||
|
|
||||||
|
@ -295,6 +298,8 @@ static int
|
||||||
Cocoa_SetRelativeMouseMode(SDL_bool enabled)
|
Cocoa_SetRelativeMouseMode(SDL_bool enabled)
|
||||||
{
|
{
|
||||||
CGError result;
|
CGError result;
|
||||||
|
SDL_Window *window;
|
||||||
|
SDL_WindowData *data;
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
DLog("Turning on.");
|
DLog("Turning on.");
|
||||||
result = CGAssociateMouseAndMouseCursorPosition(NO);
|
result = CGAssociateMouseAndMouseCursorPosition(NO);
|
||||||
|
@ -309,7 +314,7 @@ Cocoa_SetRelativeMouseMode(SDL_bool enabled)
|
||||||
/* We will re-apply the non-relative mode when the window gets focus, if it
|
/* We will re-apply the non-relative mode when the window gets focus, if it
|
||||||
* doesn't have focus right now.
|
* doesn't have focus right now.
|
||||||
*/
|
*/
|
||||||
SDL_Window *window = SDL_GetKeyboardFocus();
|
window = SDL_GetKeyboardFocus();
|
||||||
if (!window) {
|
if (!window) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -317,7 +322,7 @@ Cocoa_SetRelativeMouseMode(SDL_bool enabled)
|
||||||
/* We will re-apply the non-relative mode when the window finishes being moved,
|
/* We will re-apply the non-relative mode when the window finishes being moved,
|
||||||
* if it is being moved right now.
|
* if it is being moved right now.
|
||||||
*/
|
*/
|
||||||
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
data = (__bridge SDL_WindowData *) window->driverdata;
|
||||||
if ([data.listener isMovingOrFocusClickPending]) {
|
if ([data.listener isMovingOrFocusClickPending]) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -363,6 +368,7 @@ Cocoa_GetGlobalMouseState(int *x, int *y)
|
||||||
int
|
int
|
||||||
Cocoa_InitMouse(_THIS)
|
Cocoa_InitMouse(_THIS)
|
||||||
{
|
{
|
||||||
|
NSPoint location;
|
||||||
SDL_Mouse *mouse = SDL_GetMouse();
|
SDL_Mouse *mouse = SDL_GetMouse();
|
||||||
SDL_MouseData *driverdata = (SDL_MouseData*) SDL_calloc(1, sizeof(SDL_MouseData));
|
SDL_MouseData *driverdata = (SDL_MouseData*) SDL_calloc(1, sizeof(SDL_MouseData));
|
||||||
if (driverdata == NULL) {
|
if (driverdata == NULL) {
|
||||||
|
@ -382,7 +388,7 @@ Cocoa_InitMouse(_THIS)
|
||||||
|
|
||||||
SDL_SetDefaultCursor(Cocoa_CreateDefaultCursor());
|
SDL_SetDefaultCursor(Cocoa_CreateDefaultCursor());
|
||||||
|
|
||||||
const NSPoint location = [NSEvent mouseLocation];
|
location = [NSEvent mouseLocation];
|
||||||
driverdata->lastMoveX = location.x;
|
driverdata->lastMoveX = location.x;
|
||||||
driverdata->lastMoveY = location.y;
|
driverdata->lastMoveY = location.y;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -419,6 +425,13 @@ Cocoa_HandleTitleButtonEvent(_THIS, NSEvent *event)
|
||||||
void
|
void
|
||||||
Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
|
Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
|
||||||
{
|
{
|
||||||
|
SDL_Mouse *mouse;
|
||||||
|
SDL_MouseData *driverdata;
|
||||||
|
SDL_MouseID mouseID;
|
||||||
|
NSPoint location;
|
||||||
|
CGFloat lastMoveX, lastMoveY;
|
||||||
|
float deltaX, deltaY;
|
||||||
|
SDL_bool seenWarp;
|
||||||
switch ([event type]) {
|
switch ([event type]) {
|
||||||
case NSEventTypeMouseMoved:
|
case NSEventTypeMouseMoved:
|
||||||
case NSEventTypeLeftMouseDragged:
|
case NSEventTypeLeftMouseDragged:
|
||||||
|
@ -446,19 +459,19 @@ Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Mouse *mouse = SDL_GetMouse();
|
mouse = SDL_GetMouse();
|
||||||
SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata;
|
driverdata = (SDL_MouseData*)mouse->driverdata;
|
||||||
if (!driverdata) {
|
if (!driverdata) {
|
||||||
return; /* can happen when returning from fullscreen Space on shutdown */
|
return; /* can happen when returning from fullscreen Space on shutdown */
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_MouseID mouseID = mouse ? mouse->mouseID : 0;
|
mouseID = mouse ? mouse->mouseID : 0;
|
||||||
const SDL_bool seenWarp = driverdata->seenWarp;
|
seenWarp = driverdata->seenWarp;
|
||||||
driverdata->seenWarp = NO;
|
driverdata->seenWarp = NO;
|
||||||
|
|
||||||
const NSPoint location = [NSEvent mouseLocation];
|
location = [NSEvent mouseLocation];
|
||||||
const CGFloat lastMoveX = driverdata->lastMoveX;
|
lastMoveX = driverdata->lastMoveX;
|
||||||
const CGFloat lastMoveY = driverdata->lastMoveY;
|
lastMoveY = driverdata->lastMoveY;
|
||||||
driverdata->lastMoveX = location.x;
|
driverdata->lastMoveX = location.x;
|
||||||
driverdata->lastMoveY = location.y;
|
driverdata->lastMoveY = location.y;
|
||||||
DLog("Last seen mouse: (%g, %g)", location.x, location.y);
|
DLog("Last seen mouse: (%g, %g)", location.x, location.y);
|
||||||
|
@ -476,8 +489,8 @@ Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float deltaX = [event deltaX];
|
deltaX = [event deltaX];
|
||||||
float deltaY = [event deltaY];
|
deltaY = [event deltaY];
|
||||||
|
|
||||||
if (seenWarp) {
|
if (seenWarp) {
|
||||||
deltaX += (lastMoveX - driverdata->lastWarpX);
|
deltaX += (lastMoveX - driverdata->lastWarpX);
|
||||||
|
@ -492,15 +505,18 @@ Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
|
||||||
void
|
void
|
||||||
Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event)
|
Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event)
|
||||||
{
|
{
|
||||||
|
SDL_MouseID mouseID;
|
||||||
|
SDL_MouseWheelDirection direction;
|
||||||
|
CGFloat x, y;
|
||||||
SDL_Mouse *mouse = SDL_GetMouse();
|
SDL_Mouse *mouse = SDL_GetMouse();
|
||||||
if (!mouse) {
|
if (!mouse) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_MouseID mouseID = mouse->mouseID;
|
mouseID = mouse->mouseID;
|
||||||
CGFloat x = -[event deltaX];
|
x = -[event deltaX];
|
||||||
CGFloat y = [event deltaY];
|
y = [event deltaY];
|
||||||
SDL_MouseWheelDirection direction = SDL_MOUSEWHEEL_NORMAL;
|
direction = SDL_MOUSEWHEEL_NORMAL;
|
||||||
|
|
||||||
if ([event isDirectionInvertedFromDevice] == YES) {
|
if ([event isDirectionInvertedFromDevice] == YES) {
|
||||||
direction = SDL_MOUSEWHEEL_FLIPPED;
|
direction = SDL_MOUSEWHEEL_FLIPPED;
|
||||||
|
|
|
@ -189,6 +189,7 @@ Cocoa_GL_CreateContext(_THIS, SDL_Window * window)
|
||||||
const char *glversion;
|
const char *glversion;
|
||||||
int glversion_major;
|
int glversion_major;
|
||||||
int glversion_minor;
|
int glversion_minor;
|
||||||
|
NSOpenGLPixelFormatAttribute profile;
|
||||||
|
|
||||||
if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
|
if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
|
||||||
#if SDL_VIDEO_OPENGL_EGL
|
#if SDL_VIDEO_OPENGL_EGL
|
||||||
|
@ -216,7 +217,7 @@ Cocoa_GL_CreateContext(_THIS, SDL_Window * window)
|
||||||
|
|
||||||
attr[i++] = NSOpenGLPFAAllowOfflineRenderers;
|
attr[i++] = NSOpenGLPFAAllowOfflineRenderers;
|
||||||
|
|
||||||
NSOpenGLPixelFormatAttribute profile = NSOpenGLProfileVersionLegacy;
|
profile = NSOpenGLProfileVersionLegacy;
|
||||||
if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_CORE) {
|
if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_CORE) {
|
||||||
profile = NSOpenGLProfileVersion3_2Core;
|
profile = NSOpenGLProfileVersion3_2Core;
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,6 +115,7 @@ Cocoa_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
|
||||||
int
|
int
|
||||||
Cocoa_GLES_SetupWindow(_THIS, SDL_Window * window)
|
Cocoa_GLES_SetupWindow(_THIS, SDL_Window * window)
|
||||||
{
|
{
|
||||||
|
NSView* v;
|
||||||
/* The current context is lost in here; save it and reset it. */
|
/* The current context is lost in here; save it and reset it. */
|
||||||
SDL_WindowData *windowdata = (__bridge SDL_WindowData *) window->driverdata;
|
SDL_WindowData *windowdata = (__bridge SDL_WindowData *) window->driverdata;
|
||||||
SDL_Window *current_win = SDL_GL_GetCurrentWindow();
|
SDL_Window *current_win = SDL_GL_GetCurrentWindow();
|
||||||
|
@ -134,7 +135,7 @@ Cocoa_GLES_SetupWindow(_THIS, SDL_Window * window)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the GLES window surface */
|
/* Create the GLES window surface */
|
||||||
NSView* v = windowdata.nswindow.contentView;
|
v = windowdata.nswindow.contentView;
|
||||||
windowdata.egl_surface = SDL_EGL_CreateSurface(_this, (__bridge NativeWindowType)[v layer]);
|
windowdata.egl_surface = SDL_EGL_CreateSurface(_this, (__bridge NativeWindowType)[v layer]);
|
||||||
|
|
||||||
if (windowdata.egl_surface == EGL_NO_SURFACE) {
|
if (windowdata.egl_surface == EGL_NO_SURFACE) {
|
||||||
|
|
|
@ -31,25 +31,28 @@ SDL_WindowShaper*
|
||||||
Cocoa_CreateShaper(SDL_Window* window)
|
Cocoa_CreateShaper(SDL_Window* window)
|
||||||
{ @autoreleasepool
|
{ @autoreleasepool
|
||||||
{
|
{
|
||||||
|
SDL_WindowShaper* result;
|
||||||
|
SDL_ShapeData* data;
|
||||||
|
int resized_properly;
|
||||||
SDL_WindowData* windata = (__bridge SDL_WindowData*)window->driverdata;
|
SDL_WindowData* windata = (__bridge SDL_WindowData*)window->driverdata;
|
||||||
[windata.nswindow setOpaque:NO];
|
[windata.nswindow setOpaque:NO];
|
||||||
|
|
||||||
[windata.nswindow setStyleMask:NSWindowStyleMaskBorderless];
|
[windata.nswindow setStyleMask:NSWindowStyleMaskBorderless];
|
||||||
|
|
||||||
SDL_WindowShaper* result = (SDL_WindowShaper *)SDL_malloc(sizeof(SDL_WindowShaper));
|
result = (SDL_WindowShaper *)SDL_malloc(sizeof(SDL_WindowShaper));
|
||||||
result->window = window;
|
result->window = window;
|
||||||
result->mode.mode = ShapeModeDefault;
|
result->mode.mode = ShapeModeDefault;
|
||||||
result->mode.parameters.binarizationCutoff = 1;
|
result->mode.parameters.binarizationCutoff = 1;
|
||||||
result->userx = result->usery = 0;
|
result->userx = result->usery = 0;
|
||||||
window->shaper = result;
|
window->shaper = result;
|
||||||
|
|
||||||
SDL_ShapeData* data = (SDL_ShapeData *)SDL_malloc(sizeof(SDL_ShapeData));
|
data = (SDL_ShapeData *)SDL_malloc(sizeof(SDL_ShapeData));
|
||||||
result->driverdata = data;
|
result->driverdata = data;
|
||||||
data->context = [windata.nswindow graphicsContext];
|
data->context = [windata.nswindow graphicsContext];
|
||||||
data->saved = SDL_FALSE;
|
data->saved = SDL_FALSE;
|
||||||
data->shape = NULL;
|
data->shape = NULL;
|
||||||
|
|
||||||
int resized_properly = Cocoa_ResizeWindowShape(window);
|
resized_properly = Cocoa_ResizeWindowShape(window);
|
||||||
SDL_assert(resized_properly == 0);
|
SDL_assert(resized_properly == 0);
|
||||||
return result;
|
return result;
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -123,13 +123,14 @@
|
||||||
|
|
||||||
- (void)sendEvent:(NSEvent *)event
|
- (void)sendEvent:(NSEvent *)event
|
||||||
{
|
{
|
||||||
|
id delegate;
|
||||||
[super sendEvent:event];
|
[super sendEvent:event];
|
||||||
|
|
||||||
if ([event type] != NSEventTypeLeftMouseUp) {
|
if ([event type] != NSEventTypeLeftMouseUp) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
id delegate = [self delegate];
|
delegate = [self delegate];
|
||||||
if (![delegate isKindOfClass:[Cocoa_WindowListener class]]) {
|
if (![delegate isKindOfClass:[Cocoa_WindowListener class]]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -163,24 +164,29 @@
|
||||||
NSArray *types = [NSArray arrayWithObject:NSFilenamesPboardType];
|
NSArray *types = [NSArray arrayWithObject:NSFilenamesPboardType];
|
||||||
NSString *desiredType = [pasteboard availableTypeFromArray:types];
|
NSString *desiredType = [pasteboard availableTypeFromArray:types];
|
||||||
SDL_Window *sdlwindow = [self findSDLWindow];
|
SDL_Window *sdlwindow = [self findSDLWindow];
|
||||||
|
NSData *data;
|
||||||
|
NSArray *array;
|
||||||
|
NSPoint point;
|
||||||
|
SDL_Mouse *mouse;
|
||||||
|
int x, y;
|
||||||
|
|
||||||
if (desiredType == nil) {
|
if (desiredType == nil) {
|
||||||
return NO; /* can't accept anything that's being dropped here. */
|
return NO; /* can't accept anything that's being dropped here. */
|
||||||
}
|
}
|
||||||
|
|
||||||
NSData *data = [pasteboard dataForType:desiredType];
|
data = [pasteboard dataForType:desiredType];
|
||||||
if (data == nil) {
|
if (data == nil) {
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_assert([desiredType isEqualToString:NSFilenamesPboardType]);
|
SDL_assert([desiredType isEqualToString:NSFilenamesPboardType]);
|
||||||
NSArray *array = [pasteboard propertyListForType:@"NSFilenamesPboardType"];
|
array = [pasteboard propertyListForType:@"NSFilenamesPboardType"];
|
||||||
|
|
||||||
/* Code addon to update the mouse location */
|
/* Code addon to update the mouse location */
|
||||||
NSPoint point = [sender draggingLocation];
|
point = [sender draggingLocation];
|
||||||
SDL_Mouse *mouse = SDL_GetMouse();
|
mouse = SDL_GetMouse();
|
||||||
int x = (int)point.x;
|
x = (int)point.x;
|
||||||
int y = (int)(sdlwindow->h - point.y);
|
y = (int)(sdlwindow->h - point.y);
|
||||||
if (x >= 0 && x < sdlwindow->w && y >= 0 && y < sdlwindow->h) {
|
if (x >= 0 && x < sdlwindow->w && y >= 0 && y < sdlwindow->h) {
|
||||||
SDL_SendMouseMotion(sdlwindow, mouse->mouseID, 0, x, y);
|
SDL_SendMouseMotion(sdlwindow, mouse->mouseID, 0, x, y);
|
||||||
}
|
}
|
||||||
|
@ -254,6 +260,8 @@ static void ConvertNSRect(NSScreen *screen, BOOL fullscreen, NSRect *r)
|
||||||
static void
|
static void
|
||||||
ScheduleContextUpdates(SDL_WindowData *data)
|
ScheduleContextUpdates(SDL_WindowData *data)
|
||||||
{
|
{
|
||||||
|
NSOpenGLContext *currentContext;
|
||||||
|
NSMutableArray *contexts;
|
||||||
if (!data || !data.nscontexts) {
|
if (!data || !data.nscontexts) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -264,8 +272,8 @@ ScheduleContextUpdates(SDL_WindowData *data)
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NSOpenGLContext *currentContext = [NSOpenGLContext currentContext];
|
currentContext = [NSOpenGLContext currentContext];
|
||||||
NSMutableArray *contexts = data.nscontexts;
|
contexts = data.nscontexts;
|
||||||
@synchronized (contexts) {
|
@synchronized (contexts) {
|
||||||
for (SDLOpenGLContext *context in contexts) {
|
for (SDLOpenGLContext *context in contexts) {
|
||||||
if (context == currentContext) {
|
if (context == currentContext) {
|
||||||
|
@ -763,15 +771,19 @@ Cocoa_UpdateClipCursor(SDL_Window * window)
|
||||||
|
|
||||||
- (void)windowDidResize:(NSNotification *)aNotification
|
- (void)windowDidResize:(NSNotification *)aNotification
|
||||||
{
|
{
|
||||||
|
SDL_Window *window;
|
||||||
|
NSWindow *nswindow;
|
||||||
|
NSRect rect;
|
||||||
|
int x, y, w, h;
|
||||||
|
BOOL zoomed;
|
||||||
if (inFullscreenTransition) {
|
if (inFullscreenTransition) {
|
||||||
/* We'll take care of this at the end of the transition */
|
/* We'll take care of this at the end of the transition */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Window *window = _data.window;
|
window = _data.window;
|
||||||
NSWindow *nswindow = _data.nswindow;
|
nswindow = _data.nswindow;
|
||||||
int x, y, w, h;
|
rect = [nswindow contentRectForFrameRect:[nswindow frame]];
|
||||||
NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
|
|
||||||
ConvertNSRect([nswindow screen], (window->flags & FULLSCREEN_MASK), &rect);
|
ConvertNSRect([nswindow screen], (window->flags & FULLSCREEN_MASK), &rect);
|
||||||
x = (int)rect.origin.x;
|
x = (int)rect.origin.x;
|
||||||
y = (int)rect.origin.y;
|
y = (int)rect.origin.y;
|
||||||
|
@ -789,7 +801,7 @@ Cocoa_UpdateClipCursor(SDL_Window * window)
|
||||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
|
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
|
||||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, w, h);
|
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, w, h);
|
||||||
|
|
||||||
const BOOL zoomed = [nswindow isZoomed];
|
zoomed = [nswindow isZoomed];
|
||||||
if (!zoomed) {
|
if (!zoomed) {
|
||||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
|
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
|
||||||
} else if (zoomed) {
|
} else if (zoomed) {
|
||||||
|
@ -844,10 +856,11 @@ Cocoa_UpdateClipCursor(SDL_Window * window)
|
||||||
if ((isFullscreenSpace) && ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP)) {
|
if ((isFullscreenSpace) && ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP)) {
|
||||||
[NSMenu setMenuBarVisible:NO];
|
[NSMenu setMenuBarVisible:NO];
|
||||||
}
|
}
|
||||||
|
{
|
||||||
const unsigned int newflags = [NSEvent modifierFlags] & NSEventModifierFlagCapsLock;
|
const unsigned int newflags = [NSEvent modifierFlags] & NSEventModifierFlagCapsLock;
|
||||||
_data.videodata.modifierFlags = (_data.videodata.modifierFlags & ~NSEventModifierFlagCapsLock) | newflags;
|
_data.videodata.modifierFlags = (_data.videodata.modifierFlags & ~NSEventModifierFlagCapsLock) | newflags;
|
||||||
SDL_ToggleModState(KMOD_CAPS, newflags != 0);
|
SDL_ToggleModState(KMOD_CAPS, newflags != 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)windowDidResignKey:(NSNotification *)aNotification
|
- (void)windowDidResignKey:(NSNotification *)aNotification
|
||||||
|
@ -1187,12 +1200,12 @@ Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * w
|
||||||
- (void)mouseDown:(NSEvent *)theEvent
|
- (void)mouseDown:(NSEvent *)theEvent
|
||||||
{
|
{
|
||||||
SDL_Mouse *mouse = SDL_GetMouse();
|
SDL_Mouse *mouse = SDL_GetMouse();
|
||||||
|
int button;
|
||||||
|
|
||||||
if (!mouse) {
|
if (!mouse) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int button;
|
|
||||||
|
|
||||||
/* Ignore events that aren't inside the client area (i.e. title bar.) */
|
/* Ignore events that aren't inside the client area (i.e. title bar.) */
|
||||||
if ([theEvent window]) {
|
if ([theEvent window]) {
|
||||||
NSRect windowRect = [[[theEvent window] contentView] frame];
|
NSRect windowRect = [[[theEvent window] contentView] frame];
|
||||||
|
@ -1244,12 +1257,12 @@ Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * w
|
||||||
- (void)mouseUp:(NSEvent *)theEvent
|
- (void)mouseUp:(NSEvent *)theEvent
|
||||||
{
|
{
|
||||||
SDL_Mouse *mouse = SDL_GetMouse();
|
SDL_Mouse *mouse = SDL_GetMouse();
|
||||||
|
int button;
|
||||||
|
|
||||||
if (!mouse) {
|
if (!mouse) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int button;
|
|
||||||
|
|
||||||
if ([self processHitTest:theEvent]) {
|
if ([self processHitTest:theEvent]) {
|
||||||
SDL_SendWindowEvent(_data.window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
|
SDL_SendWindowEvent(_data.window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
|
||||||
return; /* stopped dragging, drop event. */
|
return; /* stopped dragging, drop event. */
|
||||||
|
@ -1291,14 +1304,17 @@ Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * w
|
||||||
- (void)mouseMoved:(NSEvent *)theEvent
|
- (void)mouseMoved:(NSEvent *)theEvent
|
||||||
{
|
{
|
||||||
SDL_Mouse *mouse = SDL_GetMouse();
|
SDL_Mouse *mouse = SDL_GetMouse();
|
||||||
|
SDL_MouseID mouseID;
|
||||||
|
NSPoint point;
|
||||||
|
int x, y;
|
||||||
|
SDL_Window *window;
|
||||||
|
|
||||||
if (!mouse) {
|
if (!mouse) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SDL_MouseID mouseID = mouse->mouseID;
|
mouseID = mouse->mouseID;
|
||||||
SDL_Window *window = _data.window;
|
window = _data.window;
|
||||||
NSPoint point;
|
|
||||||
int x, y;
|
|
||||||
|
|
||||||
if ([self processHitTest:theEvent]) {
|
if ([self processHitTest:theEvent]) {
|
||||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
|
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
|
||||||
|
@ -1350,6 +1366,10 @@ Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * w
|
||||||
|
|
||||||
- (void)touchesBeganWithEvent:(NSEvent *) theEvent
|
- (void)touchesBeganWithEvent:(NSEvent *) theEvent
|
||||||
{
|
{
|
||||||
|
NSSet *touches;
|
||||||
|
SDL_TouchID touchID;
|
||||||
|
int existingTouchCount;
|
||||||
|
|
||||||
/* probably a MacBook trackpad; make this look like a synthesized event.
|
/* probably a MacBook trackpad; make this look like a synthesized event.
|
||||||
This is backwards from reality, but better matches user expectations. */
|
This is backwards from reality, but better matches user expectations. */
|
||||||
BOOL istrackpad = NO;
|
BOOL istrackpad = NO;
|
||||||
|
@ -1365,9 +1385,9 @@ Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * w
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
NSSet *touches = [theEvent touchesMatchingPhase:NSTouchPhaseAny inView:nil];
|
touches = [theEvent touchesMatchingPhase:NSTouchPhaseAny inView:nil];
|
||||||
const SDL_TouchID touchID = istrackpad ? SDL_MOUSE_TOUCHID : (SDL_TouchID)(intptr_t)[[touches anyObject] device];
|
touchID = istrackpad ? SDL_MOUSE_TOUCHID : (SDL_TouchID)(intptr_t)[[touches anyObject] device];
|
||||||
int existingTouchCount = 0;
|
existingTouchCount = 0;
|
||||||
|
|
||||||
for (NSTouch* touch in touches) {
|
for (NSTouch* touch in touches) {
|
||||||
if ([touch phase] != NSTouchPhaseBegan) {
|
if ([touch phase] != NSTouchPhaseBegan) {
|
||||||
|
@ -1411,6 +1431,8 @@ Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * w
|
||||||
- (void)handleTouches:(NSTouchPhase) phase withEvent:(NSEvent *) theEvent
|
- (void)handleTouches:(NSTouchPhase) phase withEvent:(NSEvent *) theEvent
|
||||||
{
|
{
|
||||||
NSSet *touches = [theEvent touchesMatchingPhase:phase inView:nil];
|
NSSet *touches = [theEvent touchesMatchingPhase:phase inView:nil];
|
||||||
|
SDL_FingerID fingerId;
|
||||||
|
float x, y;
|
||||||
|
|
||||||
/* probably a MacBook trackpad; make this look like a synthesized event.
|
/* probably a MacBook trackpad; make this look like a synthesized event.
|
||||||
This is backwards from reality, but better matches user expectations. */
|
This is backwards from reality, but better matches user expectations. */
|
||||||
|
@ -1457,9 +1479,9 @@ Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * w
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SDL_FingerID fingerId = (SDL_FingerID)(intptr_t)[touch identity];
|
fingerId = (SDL_FingerID)(intptr_t)[touch identity];
|
||||||
float x = [touch normalizedPosition].x;
|
x = [touch normalizedPosition].x;
|
||||||
float y = [touch normalizedPosition].y;
|
y = [touch normalizedPosition].y;
|
||||||
/* Make the origin the upper left instead of the lower left */
|
/* Make the origin the upper left instead of the lower left */
|
||||||
y = 1.0f - y;
|
y = 1.0f - y;
|
||||||
|
|
||||||
|
@ -1554,8 +1576,9 @@ Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * w
|
||||||
|
|
||||||
- (void)resetCursorRects
|
- (void)resetCursorRects
|
||||||
{
|
{
|
||||||
|
SDL_Mouse *mouse;
|
||||||
[super resetCursorRects];
|
[super resetCursorRects];
|
||||||
SDL_Mouse *mouse = SDL_GetMouse();
|
mouse = SDL_GetMouse();
|
||||||
|
|
||||||
if (mouse->cursor_shown && mouse->cur_cursor && !mouse->relative_mode) {
|
if (mouse->cursor_shown && mouse->cur_cursor && !mouse->relative_mode) {
|
||||||
[self addCursorRect:[self bounds]
|
[self addCursorRect:[self bounds]
|
||||||
|
@ -1680,6 +1703,9 @@ Cocoa_CreateWindow(_THIS, SDL_Window * window)
|
||||||
SDL_Rect bounds;
|
SDL_Rect bounds;
|
||||||
NSUInteger style;
|
NSUInteger style;
|
||||||
NSArray *screens = [NSScreen screens];
|
NSArray *screens = [NSScreen screens];
|
||||||
|
NSScreen *screen = nil;
|
||||||
|
SDLView *contentView;
|
||||||
|
BOOL highdpi;
|
||||||
|
|
||||||
Cocoa_GetDisplayBounds(_this, display, &bounds);
|
Cocoa_GetDisplayBounds(_this, display, &bounds);
|
||||||
rect.origin.x = window->x;
|
rect.origin.x = window->x;
|
||||||
|
@ -1691,7 +1717,6 @@ Cocoa_CreateWindow(_THIS, SDL_Window * window)
|
||||||
style = GetWindowStyle(window);
|
style = GetWindowStyle(window);
|
||||||
|
|
||||||
/* Figure out which screen to place this window */
|
/* Figure out which screen to place this window */
|
||||||
NSScreen *screen = nil;
|
|
||||||
for (NSScreen *candidate in screens) {
|
for (NSScreen *candidate in screens) {
|
||||||
NSRect screenRect = [candidate frame];
|
NSRect screenRect = [candidate frame];
|
||||||
if (rect.origin.x >= screenRect.origin.x &&
|
if (rect.origin.x >= screenRect.origin.x &&
|
||||||
|
@ -1732,7 +1757,7 @@ Cocoa_CreateWindow(_THIS, SDL_Window * window)
|
||||||
|
|
||||||
/* Create a default view for this window */
|
/* Create a default view for this window */
|
||||||
rect = [nswindow contentRectForFrameRect:[nswindow frame]];
|
rect = [nswindow contentRectForFrameRect:[nswindow frame]];
|
||||||
SDLView *contentView = [[SDLView alloc] initWithFrame:rect];
|
contentView = [[SDLView alloc] initWithFrame:rect];
|
||||||
[contentView setSDLWindow:window];
|
[contentView setSDLWindow:window];
|
||||||
|
|
||||||
/* We still support OpenGL as long as Apple offers it, deprecated or not, so disable deprecation warnings about it. */
|
/* We still support OpenGL as long as Apple offers it, deprecated or not, so disable deprecation warnings about it. */
|
||||||
|
@ -1742,7 +1767,7 @@ Cocoa_CreateWindow(_THIS, SDL_Window * window)
|
||||||
#endif
|
#endif
|
||||||
/* Note: as of the macOS 10.15 SDK, this defaults to YES instead of NO when
|
/* Note: as of the macOS 10.15 SDK, this defaults to YES instead of NO when
|
||||||
* the NSHighResolutionCapable boolean is set in Info.plist. */
|
* the NSHighResolutionCapable boolean is set in Info.plist. */
|
||||||
BOOL highdpi = (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
|
highdpi = (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
|
||||||
[contentView setWantsBestResolutionOpenGLSurface:highdpi];
|
[contentView setWantsBestResolutionOpenGLSurface:highdpi];
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
@ -1789,6 +1814,8 @@ Cocoa_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
|
||||||
{
|
{
|
||||||
NSView* nsview = nil;
|
NSView* nsview = nil;
|
||||||
NSWindow *nswindow = nil;
|
NSWindow *nswindow = nil;
|
||||||
|
NSString *title;
|
||||||
|
BOOL highdpi;
|
||||||
|
|
||||||
if ([(__bridge id)data isKindOfClass:[NSWindow class]]) {
|
if ([(__bridge id)data isKindOfClass:[NSWindow class]]) {
|
||||||
nswindow = (__bridge NSWindow*)data;
|
nswindow = (__bridge NSWindow*)data;
|
||||||
|
@ -1800,8 +1827,6 @@ Cocoa_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
|
||||||
SDL_assert(false);
|
SDL_assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *title;
|
|
||||||
|
|
||||||
/* Query the title from the existing window */
|
/* Query the title from the existing window */
|
||||||
title = [nswindow title];
|
title = [nswindow title];
|
||||||
if (title) {
|
if (title) {
|
||||||
|
@ -1815,7 +1840,7 @@ Cocoa_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
|
||||||
#endif
|
#endif
|
||||||
/* Note: as of the macOS 10.15 SDK, this defaults to YES instead of NO when
|
/* Note: as of the macOS 10.15 SDK, this defaults to YES instead of NO when
|
||||||
* the NSHighResolutionCapable boolean is set in Info.plist. */
|
* the NSHighResolutionCapable boolean is set in Info.plist. */
|
||||||
BOOL highdpi = (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
|
highdpi = (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
|
||||||
[nsview setWantsBestResolutionOpenGLSurface:highdpi];
|
[nsview setWantsBestResolutionOpenGLSurface:highdpi];
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
@ -2083,6 +2108,7 @@ Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display
|
||||||
|
|
||||||
[nswindow setStyleMask:NSWindowStyleMaskBorderless];
|
[nswindow setStyleMask:NSWindowStyleMaskBorderless];
|
||||||
} else {
|
} else {
|
||||||
|
NSRect frameRect;
|
||||||
rect.origin.x = window->windowed.x;
|
rect.origin.x = window->windowed.x;
|
||||||
rect.origin.y = window->windowed.y;
|
rect.origin.y = window->windowed.y;
|
||||||
rect.size.width = window->windowed.w;
|
rect.size.width = window->windowed.w;
|
||||||
|
@ -2098,7 +2124,7 @@ Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display
|
||||||
[nswindow setStyleMask:GetWindowWindowedStyle(window)];
|
[nswindow setStyleMask:GetWindowWindowedStyle(window)];
|
||||||
|
|
||||||
/* Hack to restore window decorations on Mac OS X 10.10 */
|
/* Hack to restore window decorations on Mac OS X 10.10 */
|
||||||
NSRect frameRect = [nswindow frame];
|
frameRect = [nswindow frame];
|
||||||
[nswindow setFrame:NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width + 1, frameRect.size.height) display:NO];
|
[nswindow setFrame:NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width + 1, frameRect.size.height) display:NO];
|
||||||
[nswindow setFrame:frameRect display:NO];
|
[nswindow setFrame:frameRect display:NO];
|
||||||
}
|
}
|
||||||
|
@ -2204,6 +2230,9 @@ int
|
||||||
Cocoa_GetWindowDisplayIndex(_THIS, SDL_Window * window)
|
Cocoa_GetWindowDisplayIndex(_THIS, SDL_Window * window)
|
||||||
{ @autoreleasepool
|
{ @autoreleasepool
|
||||||
{
|
{
|
||||||
|
NSRect displayframe;
|
||||||
|
SDL_Point display_center;
|
||||||
|
SDL_Rect sdl_display_rect;
|
||||||
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||||
|
|
||||||
/* Not recognized via CHECK_WINDOW_MAGIC */
|
/* Not recognized via CHECK_WINDOW_MAGIC */
|
||||||
|
@ -2216,9 +2245,7 @@ Cocoa_GetWindowDisplayIndex(_THIS, SDL_Window * window)
|
||||||
instead of checking in which display the window is placed, we should check which SDL display matches the display described
|
instead of checking in which display the window is placed, we should check which SDL display matches the display described
|
||||||
via displayframe.
|
via displayframe.
|
||||||
*/
|
*/
|
||||||
NSRect displayframe = data.nswindow.screen.frame;
|
displayframe = data.nswindow.screen.frame;
|
||||||
SDL_Point display_center;
|
|
||||||
SDL_Rect sdl_display_rect;
|
|
||||||
|
|
||||||
display_center.x = displayframe.origin.x + displayframe.size.width / 2;
|
display_center.x = displayframe.origin.x + displayframe.size.width / 2;
|
||||||
display_center.y = displayframe.origin.y + displayframe.size.height / 2;
|
display_center.y = displayframe.origin.y + displayframe.size.height / 2;
|
||||||
|
@ -2292,6 +2319,7 @@ Cocoa_DestroyWindow(_THIS, SDL_Window * window)
|
||||||
SDL_WindowData *data = (SDL_WindowData *) CFBridgingRelease(window->driverdata);
|
SDL_WindowData *data = (SDL_WindowData *) CFBridgingRelease(window->driverdata);
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
|
NSArray *contexts;
|
||||||
if ([data.listener isInFullscreenSpace]) {
|
if ([data.listener isInFullscreenSpace]) {
|
||||||
[NSMenu setMenuBarVisible:YES];
|
[NSMenu setMenuBarVisible:YES];
|
||||||
}
|
}
|
||||||
|
@ -2303,7 +2331,7 @@ Cocoa_DestroyWindow(_THIS, SDL_Window * window)
|
||||||
[data.nswindow close];
|
[data.nswindow close];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSArray *contexts = [data.nscontexts copy];
|
contexts = [data.nscontexts copy];
|
||||||
for (SDLOpenGLContext *context in contexts) {
|
for (SDLOpenGLContext *context in contexts) {
|
||||||
/* Calling setWindow:NULL causes the context to remove itself from the context list. */
|
/* Calling setWindow:NULL causes the context to remove itself from the context list. */
|
||||||
[context setWindow:NULL];
|
[context setWindow:NULL];
|
||||||
|
|
Loading…
Reference in New Issue